From 7c8e34de56b3348c5a421cd0cced183e1394c5c7 Mon Sep 17 00:00:00 2001
From: Rob Mensching <rob@firegiant.com>
Date: Tue, 4 May 2021 22:48:12 -0700
Subject: Move Iis.wixext into ext

---
 src/.editorconfig                                  |   37 +
 src/CSharp.Build.props                             |   11 -
 src/Cpp.Build.props                                |   86 -
 src/Directory.Build.props                          |   29 -
 src/Directory.Build.targets                        |   48 -
 src/ca/CustomMsiErrors.h                           |   48 -
 src/ca/caDecor.h                                   |   13 -
 src/ca/dllmain.cpp                                 |   26 -
 src/ca/iisca.cpp                                   |    3 -
 src/ca/iisca.def                                   |   30 -
 src/ca/iisca.vcxproj                               |  147 -
 src/ca/packages.config                             |    5 -
 src/ca/precomp.h                                   |   66 -
 src/ca/sca.h                                       |  124 -
 src/ca/scaapppool.cpp                              |  594 ---
 src/ca/scaapppool.h                                |   88 -
 src/ca/scaapppool7.cpp                             |  401 --
 src/ca/scaapppool7.h                               |   36 -
 src/ca/scacert.cpp                                 | 1482 -------
 src/ca/scacert.h                                   |   23 -
 src/ca/scacertexec.cpp                             |  431 --
 src/ca/scacost.h                                   |   15 -
 src/ca/scaexec.cpp                                 | 1184 ------
 src/ca/scaexecIIS7.cpp                             | 4205 --------------------
 src/ca/scaexecIIS7.h                               |    5 -
 src/ca/scafilter.cpp                               |  510 ---
 src/ca/scafilter.h                                 |   46 -
 src/ca/scafilter7.cpp                              |  284 --
 src/ca/scafilter7.h                                |   21 -
 src/ca/scahttpheader.cpp                           |  323 --
 src/ca/scahttpheader.h                             |   40 -
 src/ca/scahttpheader7.cpp                          |  130 -
 src/ca/scahttpheader7.h                            |   15 -
 src/ca/scaiis.cpp                                  |  481 ---
 src/ca/scaiis.h                                    |   33 -
 src/ca/scaiis7.cpp                                 |   74 -
 src/ca/scaiis7.h                                   |   17 -
 src/ca/scamimemap.cpp                              |  200 -
 src/ca/scamimemap.h                                |   33 -
 src/ca/scamimemap7.cpp                             |   68 -
 src/ca/scamimemap7.h                               |   10 -
 src/ca/scaproperty.cpp                             |  252 --
 src/ca/scaproperty.h                               |   54 -
 src/ca/scaproperty7.cpp                            |  108 -
 src/ca/scaproperty7.h                              |   26 -
 src/ca/scasched.cpp                                |  823 ----
 src/ca/scassl.cpp                                  |  115 -
 src/ca/scassl.h                                    |   36 -
 src/ca/scassl7.cpp                                 |   34 -
 src/ca/scassl7.h                                   |    8 -
 src/ca/scauser.cpp                                 |   91 -
 src/ca/scauser.h                                   |   39 -
 src/ca/scavdir.cpp                                 |  331 --
 src/ca/scavdir.h                                   |   71 -
 src/ca/scavdir7.cpp                                |  380 --
 src/ca/scavdir7.h                                  |   66 -
 src/ca/scaweb.cpp                                  | 1187 ------
 src/ca/scaweb.h                                    |  123 -
 src/ca/scaweb7.cpp                                 |  953 -----
 src/ca/scaweb7.h                                   |   97 -
 src/ca/scawebapp.cpp                               |  194 -
 src/ca/scawebapp.h                                 |   42 -
 src/ca/scawebapp7.cpp                              |  120 -
 src/ca/scawebapp7.h                                |   10 -
 src/ca/scawebappext.cpp                            |  207 -
 src/ca/scawebappext.h                              |   32 -
 src/ca/scawebappext7.cpp                           |   61 -
 src/ca/scawebappext7.h                             |    9 -
 src/ca/scawebdir.cpp                               |  241 --
 src/ca/scawebdir.h                                 |   57 -
 src/ca/scawebdir7.cpp                              |  219 -
 src/ca/scawebdir7.h                                |   51 -
 src/ca/scaweberr.cpp                               |  371 --
 src/ca/scaweberr.h                                 |   30 -
 src/ca/scaweberr7.cpp                              |   88 -
 src/ca/scaweberr7.h                                |   10 -
 src/ca/scaweblog.cpp                               |  177 -
 src/ca/scaweblog.h                                 |   27 -
 src/ca/scaweblog7.cpp                              |  120 -
 src/ca/scaweblog7.h                                |   14 -
 src/ca/scawebprop.cpp                              |  301 --
 src/ca/scawebprop.h                                |   60 -
 src/ca/scawebprop7.cpp                             |  155 -
 src/ca/scawebprop7.h                               |   12 -
 src/ca/scawebsvcext.cpp                            |  343 --
 src/ca/scawebsvcext.h                              |   35 -
 src/ca/scawebsvcext7.cpp                           |  106 -
 src/ca/scawebsvcext7.h                             |    8 -
 src/ext/Iis/CSharp.Build.props                     |   11 +
 src/ext/Iis/Cpp.Build.props                        |   86 +
 src/ext/Iis/Directory.Build.props                  |   29 +
 src/ext/Iis/Directory.Build.targets                |   48 +
 src/ext/Iis/Iis.wixext.sln                         |   58 +
 src/ext/Iis/README.md                              |    2 +
 src/ext/Iis/appveyor.cmd                           |   14 +
 src/ext/Iis/appveyor.yml                           |   40 +
 src/ext/Iis/ca/CustomMsiErrors.h                   |   48 +
 src/ext/Iis/ca/caDecor.h                           |   13 +
 src/ext/Iis/ca/dllmain.cpp                         |   26 +
 src/ext/Iis/ca/iisca.cpp                           |    3 +
 src/ext/Iis/ca/iisca.def                           |   30 +
 src/ext/Iis/ca/iisca.vcxproj                       |  147 +
 src/ext/Iis/ca/packages.config                     |    5 +
 src/ext/Iis/ca/precomp.h                           |   66 +
 src/ext/Iis/ca/sca.h                               |  124 +
 src/ext/Iis/ca/scaapppool.cpp                      |  594 +++
 src/ext/Iis/ca/scaapppool.h                        |   88 +
 src/ext/Iis/ca/scaapppool7.cpp                     |  401 ++
 src/ext/Iis/ca/scaapppool7.h                       |   36 +
 src/ext/Iis/ca/scacert.cpp                         | 1482 +++++++
 src/ext/Iis/ca/scacert.h                           |   23 +
 src/ext/Iis/ca/scacertexec.cpp                     |  431 ++
 src/ext/Iis/ca/scacost.h                           |   15 +
 src/ext/Iis/ca/scaexec.cpp                         | 1184 ++++++
 src/ext/Iis/ca/scaexecIIS7.cpp                     | 4205 ++++++++++++++++++++
 src/ext/Iis/ca/scaexecIIS7.h                       |    5 +
 src/ext/Iis/ca/scafilter.cpp                       |  510 +++
 src/ext/Iis/ca/scafilter.h                         |   46 +
 src/ext/Iis/ca/scafilter7.cpp                      |  284 ++
 src/ext/Iis/ca/scafilter7.h                        |   21 +
 src/ext/Iis/ca/scahttpheader.cpp                   |  323 ++
 src/ext/Iis/ca/scahttpheader.h                     |   40 +
 src/ext/Iis/ca/scahttpheader7.cpp                  |  130 +
 src/ext/Iis/ca/scahttpheader7.h                    |   15 +
 src/ext/Iis/ca/scaiis.cpp                          |  481 +++
 src/ext/Iis/ca/scaiis.h                            |   33 +
 src/ext/Iis/ca/scaiis7.cpp                         |   74 +
 src/ext/Iis/ca/scaiis7.h                           |   17 +
 src/ext/Iis/ca/scamimemap.cpp                      |  200 +
 src/ext/Iis/ca/scamimemap.h                        |   33 +
 src/ext/Iis/ca/scamimemap7.cpp                     |   68 +
 src/ext/Iis/ca/scamimemap7.h                       |   10 +
 src/ext/Iis/ca/scaproperty.cpp                     |  252 ++
 src/ext/Iis/ca/scaproperty.h                       |   54 +
 src/ext/Iis/ca/scaproperty7.cpp                    |  108 +
 src/ext/Iis/ca/scaproperty7.h                      |   26 +
 src/ext/Iis/ca/scasched.cpp                        |  823 ++++
 src/ext/Iis/ca/scassl.cpp                          |  115 +
 src/ext/Iis/ca/scassl.h                            |   36 +
 src/ext/Iis/ca/scassl7.cpp                         |   34 +
 src/ext/Iis/ca/scassl7.h                           |    8 +
 src/ext/Iis/ca/scauser.cpp                         |   91 +
 src/ext/Iis/ca/scauser.h                           |   39 +
 src/ext/Iis/ca/scavdir.cpp                         |  331 ++
 src/ext/Iis/ca/scavdir.h                           |   71 +
 src/ext/Iis/ca/scavdir7.cpp                        |  380 ++
 src/ext/Iis/ca/scavdir7.h                          |   66 +
 src/ext/Iis/ca/scaweb.cpp                          | 1187 ++++++
 src/ext/Iis/ca/scaweb.h                            |  123 +
 src/ext/Iis/ca/scaweb7.cpp                         |  953 +++++
 src/ext/Iis/ca/scaweb7.h                           |   97 +
 src/ext/Iis/ca/scawebapp.cpp                       |  194 +
 src/ext/Iis/ca/scawebapp.h                         |   42 +
 src/ext/Iis/ca/scawebapp7.cpp                      |  120 +
 src/ext/Iis/ca/scawebapp7.h                        |   10 +
 src/ext/Iis/ca/scawebappext.cpp                    |  207 +
 src/ext/Iis/ca/scawebappext.h                      |   32 +
 src/ext/Iis/ca/scawebappext7.cpp                   |   61 +
 src/ext/Iis/ca/scawebappext7.h                     |    9 +
 src/ext/Iis/ca/scawebdir.cpp                       |  241 ++
 src/ext/Iis/ca/scawebdir.h                         |   57 +
 src/ext/Iis/ca/scawebdir7.cpp                      |  219 +
 src/ext/Iis/ca/scawebdir7.h                        |   51 +
 src/ext/Iis/ca/scaweberr.cpp                       |  371 ++
 src/ext/Iis/ca/scaweberr.h                         |   30 +
 src/ext/Iis/ca/scaweberr7.cpp                      |   88 +
 src/ext/Iis/ca/scaweberr7.h                        |   10 +
 src/ext/Iis/ca/scaweblog.cpp                       |  177 +
 src/ext/Iis/ca/scaweblog.h                         |   27 +
 src/ext/Iis/ca/scaweblog7.cpp                      |  120 +
 src/ext/Iis/ca/scaweblog7.h                        |   14 +
 src/ext/Iis/ca/scawebprop.cpp                      |  301 ++
 src/ext/Iis/ca/scawebprop.h                        |   60 +
 src/ext/Iis/ca/scawebprop7.cpp                     |  155 +
 src/ext/Iis/ca/scawebprop7.h                       |   12 +
 src/ext/Iis/ca/scawebsvcext.cpp                    |  343 ++
 src/ext/Iis/ca/scawebsvcext.h                      |   35 +
 src/ext/Iis/ca/scawebsvcext7.cpp                   |  106 +
 src/ext/Iis/ca/scawebsvcext7.h                     |    8 +
 src/ext/Iis/nuget.config                           |   17 +
 .../test/WixToolsetTest.Iis/IisExtensionFixture.cs |   32 +
 .../TestData/UsingIis/Package.en-us.wxl            |   11 +
 .../TestData/UsingIis/Package.wxs                  |   17 +
 .../TestData/UsingIis/PackageComponents.wxs        |   16 +
 .../TestData/UsingIis/example.txt                  |    1 +
 .../WixToolsetTest.Iis/WixToolsetTest.Iis.csproj   |   41 +
 .../WixToolsetTest.Iis.v3.ncrunchproject           |    5 +
 src/ext/Iis/wix.snk                                |  Bin 0 -> 596 bytes
 src/ext/Iis/wixext/IIsCompiler.cs                  | 2620 ++++++++++++
 src/ext/Iis/wixext/IIsDecompiler.cs                | 1549 +++++++
 src/ext/Iis/wixext/IIsExtensionData.cs             |   30 +
 src/ext/Iis/wixext/IisErrors.cs                    |   78 +
 src/ext/Iis/wixext/IisExtensionFactory.cs          |   18 +
 src/ext/Iis/wixext/IisTableDefinitions.cs          |  324 ++
 .../IisWindowsInstallerBackendBinderExtension.cs   |   13 +
 .../Iis/wixext/Symbols/CertificateHashSymbol.cs    |   55 +
 src/ext/Iis/wixext/Symbols/CertificateSymbol.cs    |  103 +
 src/ext/Iis/wixext/Symbols/IIsAppPoolSymbol.cs     |  159 +
 src/ext/Iis/wixext/Symbols/IIsFilterSymbol.cs      |   95 +
 src/ext/Iis/wixext/Symbols/IIsHttpHeaderSymbol.cs  |   95 +
 src/ext/Iis/wixext/Symbols/IIsMimeMapSymbol.cs     |   71 +
 src/ext/Iis/wixext/Symbols/IIsPropertySymbol.cs    |   63 +
 src/ext/Iis/wixext/Symbols/IIsWebAddressSymbol.cs  |   79 +
 .../Symbols/IIsWebApplicationExtensionSymbol.cs    |   79 +
 .../Iis/wixext/Symbols/IIsWebApplicationSymbol.cs  |  127 +
 .../wixext/Symbols/IIsWebDirPropertiesSymbol.cs    |  151 +
 src/ext/Iis/wixext/Symbols/IIsWebDirSymbol.cs      |   79 +
 src/ext/Iis/wixext/Symbols/IIsWebErrorSymbol.cs    |   87 +
 src/ext/Iis/wixext/Symbols/IIsWebLogSymbol.cs      |   47 +
 .../wixext/Symbols/IIsWebServiceExtensionSymbol.cs |   79 +
 .../wixext/Symbols/IIsWebSiteCertificatesSymbol.cs |   55 +
 src/ext/Iis/wixext/Symbols/IIsWebSiteSymbol.cs     |  135 +
 .../Iis/wixext/Symbols/IIsWebVirtualDirSymbol.cs   |   87 +
 src/ext/Iis/wixext/Symbols/IisSymbolDefinitions.cs |  107 +
 src/ext/Iis/wixext/WixToolset.Iis.wixext.csproj    |   31 +
 src/ext/Iis/wixext/WixToolset.Iis.wixext.targets   |   11 +
 src/ext/Iis/wixlib/IIsExtension.wxs                |   58 +
 src/ext/Iis/wixlib/IIsExtension_Platform.wxi       |   66 +
 src/ext/Iis/wixlib/IIsExtension_arm64.wxs          |    7 +
 src/ext/Iis/wixlib/IIsExtension_x64.wxs            |    7 +
 src/ext/Iis/wixlib/IIsExtension_x86.wxs            |    7 +
 src/ext/Iis/wixlib/caDecor.wxi                     |   39 +
 src/ext/Iis/wixlib/caerr.wxi                       |   96 +
 src/ext/Iis/wixlib/de-de.wxl                       |   55 +
 src/ext/Iis/wixlib/en-us.wxl                       |   55 +
 src/ext/Iis/wixlib/iis.v3.ncrunchproject           |    5 +
 src/ext/Iis/wixlib/iis.wixproj                     |   26 +
 src/ext/Iis/wixlib/ja-jp.wxl                       |   47 +
 src/ext/Iis/wixlib/pt-br.wxl                       |   50 +
 src/ext/global.json                                |    5 +
 src/test/WixToolsetTest.Iis/IisExtensionFixture.cs |   32 -
 .../TestData/UsingIis/Package.en-us.wxl            |   11 -
 .../TestData/UsingIis/Package.wxs                  |   17 -
 .../TestData/UsingIis/PackageComponents.wxs        |   16 -
 .../TestData/UsingIis/example.txt                  |    1 -
 .../WixToolsetTest.Iis/WixToolsetTest.Iis.csproj   |   41 -
 .../WixToolsetTest.Iis.v3.ncrunchproject           |    5 -
 src/version.json                                   |   11 +
 src/wix.snk                                        |  Bin 596 -> 0 bytes
 src/wixext/IIsCompiler.cs                          | 2620 ------------
 src/wixext/IIsDecompiler.cs                        | 1549 -------
 src/wixext/IIsExtensionData.cs                     |   30 -
 src/wixext/IisErrors.cs                            |   78 -
 src/wixext/IisExtensionFactory.cs                  |   18 -
 src/wixext/IisTableDefinitions.cs                  |  324 --
 .../IisWindowsInstallerBackendBinderExtension.cs   |   13 -
 src/wixext/Symbols/CertificateHashSymbol.cs        |   55 -
 src/wixext/Symbols/CertificateSymbol.cs            |  103 -
 src/wixext/Symbols/IIsAppPoolSymbol.cs             |  159 -
 src/wixext/Symbols/IIsFilterSymbol.cs              |   95 -
 src/wixext/Symbols/IIsHttpHeaderSymbol.cs          |   95 -
 src/wixext/Symbols/IIsMimeMapSymbol.cs             |   71 -
 src/wixext/Symbols/IIsPropertySymbol.cs            |   63 -
 src/wixext/Symbols/IIsWebAddressSymbol.cs          |   79 -
 .../Symbols/IIsWebApplicationExtensionSymbol.cs    |   79 -
 src/wixext/Symbols/IIsWebApplicationSymbol.cs      |  127 -
 src/wixext/Symbols/IIsWebDirPropertiesSymbol.cs    |  151 -
 src/wixext/Symbols/IIsWebDirSymbol.cs              |   79 -
 src/wixext/Symbols/IIsWebErrorSymbol.cs            |   87 -
 src/wixext/Symbols/IIsWebLogSymbol.cs              |   47 -
 src/wixext/Symbols/IIsWebServiceExtensionSymbol.cs |   79 -
 src/wixext/Symbols/IIsWebSiteCertificatesSymbol.cs |   55 -
 src/wixext/Symbols/IIsWebSiteSymbol.cs             |  135 -
 src/wixext/Symbols/IIsWebVirtualDirSymbol.cs       |   87 -
 src/wixext/Symbols/IisSymbolDefinitions.cs         |  107 -
 src/wixext/WixToolset.Iis.wixext.csproj            |   31 -
 src/wixext/WixToolset.Iis.wixext.targets           |   11 -
 src/wixlib/IIsExtension.wxs                        |   58 -
 src/wixlib/IIsExtension_Platform.wxi               |   66 -
 src/wixlib/IIsExtension_arm64.wxs                  |    7 -
 src/wixlib/IIsExtension_x64.wxs                    |    7 -
 src/wixlib/IIsExtension_x86.wxs                    |    7 -
 src/wixlib/caDecor.wxi                             |   39 -
 src/wixlib/caerr.wxi                               |   96 -
 src/wixlib/de-de.wxl                               |   55 -
 src/wixlib/en-us.wxl                               |   55 -
 src/wixlib/iis.v3.ncrunchproject                   |    5 -
 src/wixlib/iis.wixproj                             |   26 -
 src/wixlib/ja-jp.wxl                               |   47 -
 src/wixlib/pt-br.wxl                               |   50 -
 280 files changed, 26531 insertions(+), 26347 deletions(-)
 create mode 100644 src/.editorconfig
 delete mode 100644 src/CSharp.Build.props
 delete mode 100644 src/Cpp.Build.props
 delete mode 100644 src/Directory.Build.props
 delete mode 100644 src/Directory.Build.targets
 delete mode 100644 src/ca/CustomMsiErrors.h
 delete mode 100644 src/ca/caDecor.h
 delete mode 100644 src/ca/dllmain.cpp
 delete mode 100644 src/ca/iisca.cpp
 delete mode 100644 src/ca/iisca.def
 delete mode 100644 src/ca/iisca.vcxproj
 delete mode 100644 src/ca/packages.config
 delete mode 100644 src/ca/precomp.h
 delete mode 100644 src/ca/sca.h
 delete mode 100644 src/ca/scaapppool.cpp
 delete mode 100644 src/ca/scaapppool.h
 delete mode 100644 src/ca/scaapppool7.cpp
 delete mode 100644 src/ca/scaapppool7.h
 delete mode 100644 src/ca/scacert.cpp
 delete mode 100644 src/ca/scacert.h
 delete mode 100644 src/ca/scacertexec.cpp
 delete mode 100644 src/ca/scacost.h
 delete mode 100644 src/ca/scaexec.cpp
 delete mode 100644 src/ca/scaexecIIS7.cpp
 delete mode 100644 src/ca/scaexecIIS7.h
 delete mode 100644 src/ca/scafilter.cpp
 delete mode 100644 src/ca/scafilter.h
 delete mode 100644 src/ca/scafilter7.cpp
 delete mode 100644 src/ca/scafilter7.h
 delete mode 100644 src/ca/scahttpheader.cpp
 delete mode 100644 src/ca/scahttpheader.h
 delete mode 100644 src/ca/scahttpheader7.cpp
 delete mode 100644 src/ca/scahttpheader7.h
 delete mode 100644 src/ca/scaiis.cpp
 delete mode 100644 src/ca/scaiis.h
 delete mode 100644 src/ca/scaiis7.cpp
 delete mode 100644 src/ca/scaiis7.h
 delete mode 100644 src/ca/scamimemap.cpp
 delete mode 100644 src/ca/scamimemap.h
 delete mode 100644 src/ca/scamimemap7.cpp
 delete mode 100644 src/ca/scamimemap7.h
 delete mode 100644 src/ca/scaproperty.cpp
 delete mode 100644 src/ca/scaproperty.h
 delete mode 100644 src/ca/scaproperty7.cpp
 delete mode 100644 src/ca/scaproperty7.h
 delete mode 100644 src/ca/scasched.cpp
 delete mode 100644 src/ca/scassl.cpp
 delete mode 100644 src/ca/scassl.h
 delete mode 100644 src/ca/scassl7.cpp
 delete mode 100644 src/ca/scassl7.h
 delete mode 100644 src/ca/scauser.cpp
 delete mode 100644 src/ca/scauser.h
 delete mode 100644 src/ca/scavdir.cpp
 delete mode 100644 src/ca/scavdir.h
 delete mode 100644 src/ca/scavdir7.cpp
 delete mode 100644 src/ca/scavdir7.h
 delete mode 100644 src/ca/scaweb.cpp
 delete mode 100644 src/ca/scaweb.h
 delete mode 100644 src/ca/scaweb7.cpp
 delete mode 100644 src/ca/scaweb7.h
 delete mode 100644 src/ca/scawebapp.cpp
 delete mode 100644 src/ca/scawebapp.h
 delete mode 100644 src/ca/scawebapp7.cpp
 delete mode 100644 src/ca/scawebapp7.h
 delete mode 100644 src/ca/scawebappext.cpp
 delete mode 100644 src/ca/scawebappext.h
 delete mode 100644 src/ca/scawebappext7.cpp
 delete mode 100644 src/ca/scawebappext7.h
 delete mode 100644 src/ca/scawebdir.cpp
 delete mode 100644 src/ca/scawebdir.h
 delete mode 100644 src/ca/scawebdir7.cpp
 delete mode 100644 src/ca/scawebdir7.h
 delete mode 100644 src/ca/scaweberr.cpp
 delete mode 100644 src/ca/scaweberr.h
 delete mode 100644 src/ca/scaweberr7.cpp
 delete mode 100644 src/ca/scaweberr7.h
 delete mode 100644 src/ca/scaweblog.cpp
 delete mode 100644 src/ca/scaweblog.h
 delete mode 100644 src/ca/scaweblog7.cpp
 delete mode 100644 src/ca/scaweblog7.h
 delete mode 100644 src/ca/scawebprop.cpp
 delete mode 100644 src/ca/scawebprop.h
 delete mode 100644 src/ca/scawebprop7.cpp
 delete mode 100644 src/ca/scawebprop7.h
 delete mode 100644 src/ca/scawebsvcext.cpp
 delete mode 100644 src/ca/scawebsvcext.h
 delete mode 100644 src/ca/scawebsvcext7.cpp
 delete mode 100644 src/ca/scawebsvcext7.h
 create mode 100644 src/ext/Iis/CSharp.Build.props
 create mode 100644 src/ext/Iis/Cpp.Build.props
 create mode 100644 src/ext/Iis/Directory.Build.props
 create mode 100644 src/ext/Iis/Directory.Build.targets
 create mode 100644 src/ext/Iis/Iis.wixext.sln
 create mode 100644 src/ext/Iis/README.md
 create mode 100644 src/ext/Iis/appveyor.cmd
 create mode 100644 src/ext/Iis/appveyor.yml
 create mode 100644 src/ext/Iis/ca/CustomMsiErrors.h
 create mode 100644 src/ext/Iis/ca/caDecor.h
 create mode 100644 src/ext/Iis/ca/dllmain.cpp
 create mode 100644 src/ext/Iis/ca/iisca.cpp
 create mode 100644 src/ext/Iis/ca/iisca.def
 create mode 100644 src/ext/Iis/ca/iisca.vcxproj
 create mode 100644 src/ext/Iis/ca/packages.config
 create mode 100644 src/ext/Iis/ca/precomp.h
 create mode 100644 src/ext/Iis/ca/sca.h
 create mode 100644 src/ext/Iis/ca/scaapppool.cpp
 create mode 100644 src/ext/Iis/ca/scaapppool.h
 create mode 100644 src/ext/Iis/ca/scaapppool7.cpp
 create mode 100644 src/ext/Iis/ca/scaapppool7.h
 create mode 100644 src/ext/Iis/ca/scacert.cpp
 create mode 100644 src/ext/Iis/ca/scacert.h
 create mode 100644 src/ext/Iis/ca/scacertexec.cpp
 create mode 100644 src/ext/Iis/ca/scacost.h
 create mode 100644 src/ext/Iis/ca/scaexec.cpp
 create mode 100644 src/ext/Iis/ca/scaexecIIS7.cpp
 create mode 100644 src/ext/Iis/ca/scaexecIIS7.h
 create mode 100644 src/ext/Iis/ca/scafilter.cpp
 create mode 100644 src/ext/Iis/ca/scafilter.h
 create mode 100644 src/ext/Iis/ca/scafilter7.cpp
 create mode 100644 src/ext/Iis/ca/scafilter7.h
 create mode 100644 src/ext/Iis/ca/scahttpheader.cpp
 create mode 100644 src/ext/Iis/ca/scahttpheader.h
 create mode 100644 src/ext/Iis/ca/scahttpheader7.cpp
 create mode 100644 src/ext/Iis/ca/scahttpheader7.h
 create mode 100644 src/ext/Iis/ca/scaiis.cpp
 create mode 100644 src/ext/Iis/ca/scaiis.h
 create mode 100644 src/ext/Iis/ca/scaiis7.cpp
 create mode 100644 src/ext/Iis/ca/scaiis7.h
 create mode 100644 src/ext/Iis/ca/scamimemap.cpp
 create mode 100644 src/ext/Iis/ca/scamimemap.h
 create mode 100644 src/ext/Iis/ca/scamimemap7.cpp
 create mode 100644 src/ext/Iis/ca/scamimemap7.h
 create mode 100644 src/ext/Iis/ca/scaproperty.cpp
 create mode 100644 src/ext/Iis/ca/scaproperty.h
 create mode 100644 src/ext/Iis/ca/scaproperty7.cpp
 create mode 100644 src/ext/Iis/ca/scaproperty7.h
 create mode 100644 src/ext/Iis/ca/scasched.cpp
 create mode 100644 src/ext/Iis/ca/scassl.cpp
 create mode 100644 src/ext/Iis/ca/scassl.h
 create mode 100644 src/ext/Iis/ca/scassl7.cpp
 create mode 100644 src/ext/Iis/ca/scassl7.h
 create mode 100644 src/ext/Iis/ca/scauser.cpp
 create mode 100644 src/ext/Iis/ca/scauser.h
 create mode 100644 src/ext/Iis/ca/scavdir.cpp
 create mode 100644 src/ext/Iis/ca/scavdir.h
 create mode 100644 src/ext/Iis/ca/scavdir7.cpp
 create mode 100644 src/ext/Iis/ca/scavdir7.h
 create mode 100644 src/ext/Iis/ca/scaweb.cpp
 create mode 100644 src/ext/Iis/ca/scaweb.h
 create mode 100644 src/ext/Iis/ca/scaweb7.cpp
 create mode 100644 src/ext/Iis/ca/scaweb7.h
 create mode 100644 src/ext/Iis/ca/scawebapp.cpp
 create mode 100644 src/ext/Iis/ca/scawebapp.h
 create mode 100644 src/ext/Iis/ca/scawebapp7.cpp
 create mode 100644 src/ext/Iis/ca/scawebapp7.h
 create mode 100644 src/ext/Iis/ca/scawebappext.cpp
 create mode 100644 src/ext/Iis/ca/scawebappext.h
 create mode 100644 src/ext/Iis/ca/scawebappext7.cpp
 create mode 100644 src/ext/Iis/ca/scawebappext7.h
 create mode 100644 src/ext/Iis/ca/scawebdir.cpp
 create mode 100644 src/ext/Iis/ca/scawebdir.h
 create mode 100644 src/ext/Iis/ca/scawebdir7.cpp
 create mode 100644 src/ext/Iis/ca/scawebdir7.h
 create mode 100644 src/ext/Iis/ca/scaweberr.cpp
 create mode 100644 src/ext/Iis/ca/scaweberr.h
 create mode 100644 src/ext/Iis/ca/scaweberr7.cpp
 create mode 100644 src/ext/Iis/ca/scaweberr7.h
 create mode 100644 src/ext/Iis/ca/scaweblog.cpp
 create mode 100644 src/ext/Iis/ca/scaweblog.h
 create mode 100644 src/ext/Iis/ca/scaweblog7.cpp
 create mode 100644 src/ext/Iis/ca/scaweblog7.h
 create mode 100644 src/ext/Iis/ca/scawebprop.cpp
 create mode 100644 src/ext/Iis/ca/scawebprop.h
 create mode 100644 src/ext/Iis/ca/scawebprop7.cpp
 create mode 100644 src/ext/Iis/ca/scawebprop7.h
 create mode 100644 src/ext/Iis/ca/scawebsvcext.cpp
 create mode 100644 src/ext/Iis/ca/scawebsvcext.h
 create mode 100644 src/ext/Iis/ca/scawebsvcext7.cpp
 create mode 100644 src/ext/Iis/ca/scawebsvcext7.h
 create mode 100644 src/ext/Iis/nuget.config
 create mode 100644 src/ext/Iis/test/WixToolsetTest.Iis/IisExtensionFixture.cs
 create mode 100644 src/ext/Iis/test/WixToolsetTest.Iis/TestData/UsingIis/Package.en-us.wxl
 create mode 100644 src/ext/Iis/test/WixToolsetTest.Iis/TestData/UsingIis/Package.wxs
 create mode 100644 src/ext/Iis/test/WixToolsetTest.Iis/TestData/UsingIis/PackageComponents.wxs
 create mode 100644 src/ext/Iis/test/WixToolsetTest.Iis/TestData/UsingIis/example.txt
 create mode 100644 src/ext/Iis/test/WixToolsetTest.Iis/WixToolsetTest.Iis.csproj
 create mode 100644 src/ext/Iis/test/WixToolsetTest.Iis/WixToolsetTest.Iis.v3.ncrunchproject
 create mode 100644 src/ext/Iis/wix.snk
 create mode 100644 src/ext/Iis/wixext/IIsCompiler.cs
 create mode 100644 src/ext/Iis/wixext/IIsDecompiler.cs
 create mode 100644 src/ext/Iis/wixext/IIsExtensionData.cs
 create mode 100644 src/ext/Iis/wixext/IisErrors.cs
 create mode 100644 src/ext/Iis/wixext/IisExtensionFactory.cs
 create mode 100644 src/ext/Iis/wixext/IisTableDefinitions.cs
 create mode 100644 src/ext/Iis/wixext/IisWindowsInstallerBackendBinderExtension.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/CertificateHashSymbol.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/CertificateSymbol.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/IIsAppPoolSymbol.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/IIsFilterSymbol.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/IIsHttpHeaderSymbol.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/IIsMimeMapSymbol.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/IIsPropertySymbol.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/IIsWebAddressSymbol.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/IIsWebApplicationExtensionSymbol.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/IIsWebApplicationSymbol.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/IIsWebDirPropertiesSymbol.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/IIsWebDirSymbol.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/IIsWebErrorSymbol.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/IIsWebLogSymbol.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/IIsWebServiceExtensionSymbol.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/IIsWebSiteCertificatesSymbol.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/IIsWebSiteSymbol.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/IIsWebVirtualDirSymbol.cs
 create mode 100644 src/ext/Iis/wixext/Symbols/IisSymbolDefinitions.cs
 create mode 100644 src/ext/Iis/wixext/WixToolset.Iis.wixext.csproj
 create mode 100644 src/ext/Iis/wixext/WixToolset.Iis.wixext.targets
 create mode 100644 src/ext/Iis/wixlib/IIsExtension.wxs
 create mode 100644 src/ext/Iis/wixlib/IIsExtension_Platform.wxi
 create mode 100644 src/ext/Iis/wixlib/IIsExtension_arm64.wxs
 create mode 100644 src/ext/Iis/wixlib/IIsExtension_x64.wxs
 create mode 100644 src/ext/Iis/wixlib/IIsExtension_x86.wxs
 create mode 100644 src/ext/Iis/wixlib/caDecor.wxi
 create mode 100644 src/ext/Iis/wixlib/caerr.wxi
 create mode 100644 src/ext/Iis/wixlib/de-de.wxl
 create mode 100644 src/ext/Iis/wixlib/en-us.wxl
 create mode 100644 src/ext/Iis/wixlib/iis.v3.ncrunchproject
 create mode 100644 src/ext/Iis/wixlib/iis.wixproj
 create mode 100644 src/ext/Iis/wixlib/ja-jp.wxl
 create mode 100644 src/ext/Iis/wixlib/pt-br.wxl
 create mode 100644 src/ext/global.json
 delete mode 100644 src/test/WixToolsetTest.Iis/IisExtensionFixture.cs
 delete mode 100644 src/test/WixToolsetTest.Iis/TestData/UsingIis/Package.en-us.wxl
 delete mode 100644 src/test/WixToolsetTest.Iis/TestData/UsingIis/Package.wxs
 delete mode 100644 src/test/WixToolsetTest.Iis/TestData/UsingIis/PackageComponents.wxs
 delete mode 100644 src/test/WixToolsetTest.Iis/TestData/UsingIis/example.txt
 delete mode 100644 src/test/WixToolsetTest.Iis/WixToolsetTest.Iis.csproj
 delete mode 100644 src/test/WixToolsetTest.Iis/WixToolsetTest.Iis.v3.ncrunchproject
 create mode 100644 src/version.json
 delete mode 100644 src/wix.snk
 delete mode 100644 src/wixext/IIsCompiler.cs
 delete mode 100644 src/wixext/IIsDecompiler.cs
 delete mode 100644 src/wixext/IIsExtensionData.cs
 delete mode 100644 src/wixext/IisErrors.cs
 delete mode 100644 src/wixext/IisExtensionFactory.cs
 delete mode 100644 src/wixext/IisTableDefinitions.cs
 delete mode 100644 src/wixext/IisWindowsInstallerBackendBinderExtension.cs
 delete mode 100644 src/wixext/Symbols/CertificateHashSymbol.cs
 delete mode 100644 src/wixext/Symbols/CertificateSymbol.cs
 delete mode 100644 src/wixext/Symbols/IIsAppPoolSymbol.cs
 delete mode 100644 src/wixext/Symbols/IIsFilterSymbol.cs
 delete mode 100644 src/wixext/Symbols/IIsHttpHeaderSymbol.cs
 delete mode 100644 src/wixext/Symbols/IIsMimeMapSymbol.cs
 delete mode 100644 src/wixext/Symbols/IIsPropertySymbol.cs
 delete mode 100644 src/wixext/Symbols/IIsWebAddressSymbol.cs
 delete mode 100644 src/wixext/Symbols/IIsWebApplicationExtensionSymbol.cs
 delete mode 100644 src/wixext/Symbols/IIsWebApplicationSymbol.cs
 delete mode 100644 src/wixext/Symbols/IIsWebDirPropertiesSymbol.cs
 delete mode 100644 src/wixext/Symbols/IIsWebDirSymbol.cs
 delete mode 100644 src/wixext/Symbols/IIsWebErrorSymbol.cs
 delete mode 100644 src/wixext/Symbols/IIsWebLogSymbol.cs
 delete mode 100644 src/wixext/Symbols/IIsWebServiceExtensionSymbol.cs
 delete mode 100644 src/wixext/Symbols/IIsWebSiteCertificatesSymbol.cs
 delete mode 100644 src/wixext/Symbols/IIsWebSiteSymbol.cs
 delete mode 100644 src/wixext/Symbols/IIsWebVirtualDirSymbol.cs
 delete mode 100644 src/wixext/Symbols/IisSymbolDefinitions.cs
 delete mode 100644 src/wixext/WixToolset.Iis.wixext.csproj
 delete mode 100644 src/wixext/WixToolset.Iis.wixext.targets
 delete mode 100644 src/wixlib/IIsExtension.wxs
 delete mode 100644 src/wixlib/IIsExtension_Platform.wxi
 delete mode 100644 src/wixlib/IIsExtension_arm64.wxs
 delete mode 100644 src/wixlib/IIsExtension_x64.wxs
 delete mode 100644 src/wixlib/IIsExtension_x86.wxs
 delete mode 100644 src/wixlib/caDecor.wxi
 delete mode 100644 src/wixlib/caerr.wxi
 delete mode 100644 src/wixlib/de-de.wxl
 delete mode 100644 src/wixlib/en-us.wxl
 delete mode 100644 src/wixlib/iis.v3.ncrunchproject
 delete mode 100644 src/wixlib/iis.wixproj
 delete mode 100644 src/wixlib/ja-jp.wxl
 delete mode 100644 src/wixlib/pt-br.wxl

(limited to 'src')

diff --git a/src/.editorconfig b/src/.editorconfig
new file mode 100644
index 00000000..1d72e683
--- /dev/null
+++ b/src/.editorconfig
@@ -0,0 +1,37 @@
+# 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.
+#
+#  Do NOT modify this file. Update the canonical version in Home\repo-template\src\.editorconfig
+#  then update all of the repos.
+
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 4
+trim_trailing_whitespace = true
+
+[*.{cs,vb}]
+dotnet_sort_system_directives_first = true
+
+[*.cs]
+csharp_indent_case_contents = true : error
+csharp_indent_switch_labels = true : error
+csharp_new_line_before_open_brace = all
+csharp_prefer_braces = true : error
+csharp_style_expression_bodied_methods = when_on_single_line : suggestion
+csharp_style_expression_bodied_constructors = when_on_single_line : suggestion
+csharp_style_expression_bodied_operators = when_on_single_line : suggestion
+csharp_style_expression_bodied_properties = when_on_single_line : suggestion
+csharp_style_expression_bodied_indexers = when_on_single_line : suggestion
+csharp_style_expression_bodied_accessors = when_on_single_line : suggestion
+csharp_style_var_elsewhere = true : suggestion
+csharp_style_var_for_built_in_types = true : suggestion
+csharp_style_var_when_type_is_apparent = true : suggestion
+dotnet_style_qualification_for_event = true : error
+dotnet_style_qualification_for_field = true : error
+dotnet_style_qualification_for_method = true : error
+dotnet_style_qualification_for_property = true : error
+
+[*.targets]
+indent_size = 2
diff --git a/src/CSharp.Build.props b/src/CSharp.Build.props
deleted file mode 100644
index b12f4c6e..00000000
--- a/src/CSharp.Build.props
+++ /dev/null
@@ -1,11 +0,0 @@
-<!-- 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. -->
-<!--
-  Do NOT modify this file. Update the canonical version in Home\repo-template\src\CSharp.Build.props
-  then update all of the repos.
--->
-<Project>
-  <PropertyGroup>
-    <SignAssembly>true</SignAssembly>
-    <AssemblyOriginatorKeyFile>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)wix.snk))</AssemblyOriginatorKeyFile>
-  </PropertyGroup>
-</Project>
diff --git a/src/Cpp.Build.props b/src/Cpp.Build.props
deleted file mode 100644
index 9b7a1bb5..00000000
--- a/src/Cpp.Build.props
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<Project>
-  <PropertyGroup>
-    <Platform Condition=" '$(Platform)' == '' OR '$(Platform)' == 'AnyCPU' ">Win32</Platform>
-    <IntDir>$(BaseIntermediateOutputPath)$(Configuration)\$(Platform)\</IntDir>
-    <OutDir>$(OutputPath)$(Platform)\</OutDir>
-  </PropertyGroup>
-
-  <PropertyGroup Condition="'$(WindowsTargetPlatformVersion)'=='' AND '$(VisualStudioVersion)'>='15.0'">
-    <WindowsTargetPlatformVersion>$([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0'))</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-
-  <ItemDefinitionGroup>
-    <ClCompile>
-      <DisableSpecificWarnings>$(DisableSpecificCompilerWarnings)</DisableSpecificWarnings>
-      <WarningLevel>Level4</WarningLevel>
-      <AdditionalIncludeDirectories>$(ProjectDir)inc;$(MSBuildProjectDirectory);$(IntDir);$(SqlCESdkIncludePath);$(ProjectAdditionalIncludeDirectories);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_WINDOWS;_WIN32_MSI=500;_WIN32_WINNT=0x0501;$(ArmPreprocessorDefinitions);$(UnicodePreprocessorDefinitions);_CRT_STDIO_LEGACY_WIDE_SPECIFIERS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PrecompiledHeader>Use</PrecompiledHeader>
-      <PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
-      <CallingConvention Condition="'$(Platform)'=='Win32'">StdCall</CallingConvention>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <ExceptionHandling>false</ExceptionHandling>
-      <AdditionalOptions>-YlprecompDefine</AdditionalOptions>
-      <AdditionalOptions Condition=" $(PlatformToolset.StartsWith('v14')) ">/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
-      <MultiProcessorCompilation Condition=" $(NUMBER_OF_PROCESSORS) &gt; 4 ">true</MultiProcessorCompilation>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>$(ArmPreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>$(ProjectAdditionalResourceIncludeDirectories);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-    </ResourceCompile>
-    <Lib>
-      <AdditionalLibraryDirectories>$(OutDir);$(AdditionalMultiTargetLibraryPath);$(ProjectAdditionalLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
-    </Lib>
-    <Link>
-      <SubSystem>$(ProjectSubSystem)</SubSystem>
-      <ModuleDefinitionFile>$(ProjectModuleDefinitionFile)</ModuleDefinitionFile>
-      <NoEntryPoint>$(ResourceOnlyDll)</NoEntryPoint>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>$(ProjectAdditionalLinkLibraries);advapi32.lib;comdlg32.lib;user32.lib;oleaut32.lib;gdi32.lib;shell32.lib;ole32.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(OutDir);$(AdditionalMultiTargetLibraryPath);$(ArmLibraryDirectories);$(ProjectAdditionalLinkLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
-      <AdditionalOptions Condition=" $(PlatformToolset.StartsWith('v14')) ">/IGNORE:4099 %(AdditionalOptions)</AdditionalOptions>
-    </Link>
-  </ItemDefinitionGroup>
-
-  <ItemDefinitionGroup Condition=" '$(Platform)'=='Win32' and '$(PlatformToolset)'!='v100'">
-    <ClCompile>
-      <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
-    </ClCompile>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition=" '$(Platform)'=='arm' ">
-    <ClCompile>
-      <CallingConvention>CDecl</CallingConvention>
-    </ClCompile>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition=" '$(ConfigurationType)'=='StaticLibrary' ">
-    <ClCompile>
-      <DebugInformationFormat>OldStyle</DebugInformationFormat>
-      <OmitDefaultLibName>true</OmitDefaultLibName>
-      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
-    </ClCompile>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition=" '$(Configuration)'=='Debug' ">
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <PreprocessorDefinitions>_DEBUG;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition=" '$(Configuration)'=='Release' ">
-    <ClCompile>
-      <Optimization>MinSpace</Optimization>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-</Project>
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
deleted file mode 100644
index f83cc154..00000000
--- a/src/Directory.Build.props
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<!--
-  Do NOT modify this file. Update the canonical version in Home\repo-template\src\Directory.Build.props
-  then update all of the repos.
--->
-<Project>
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <EnableSourceLink Condition=" '$(NCrunch)' == '1' ">false</EnableSourceLink>
-    <MSBuildWarningsAsMessages>MSB3246</MSBuildWarningsAsMessages>
-
-    <ProjectName Condition=" '$(ProjectName)' == '' ">$(MSBuildProjectName)</ProjectName>
-    <BaseOutputPath>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\build\))</BaseOutputPath>
-    <BaseIntermediateOutputPath>$(BaseOutputPath)obj\$(ProjectName)\</BaseIntermediateOutputPath>
-    <OutputPath>$(BaseOutputPath)$(Configuration)\</OutputPath>
-
-    <Authors>WiX Toolset Team</Authors>
-    <Company>WiX Toolset</Company>
-    <Copyright>Copyright (c) .NET Foundation and contributors. All rights reserved.</Copyright>
-    <PackageLicenseExpression>MS-RL</PackageLicenseExpression>
-    <Product>WiX Toolset</Product>
-  </PropertyGroup>
-
-  <Import Project="CSharp.Build.props" Condition=" '$(MSBuildProjectExtension)'=='.csproj' and Exists('CSharp.Build.props') " />
-  <Import Project="Cpp.Build.props" Condition=" Exists('Cpp.Build.props') And '$(MSBuildProjectExtension)'=='.vcxproj' " />
-  <Import Project="Wix.Build.props" Condition=" Exists('Wix.Build.props') And '$(MSBuildProjectExtension)'=='.wixproj' " />
-  <Import Project="Custom.Build.props" Condition=" Exists('Custom.Build.props') " />
-</Project>
diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets
deleted file mode 100644
index dac7452a..00000000
--- a/src/Directory.Build.targets
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<!--
-  Do NOT modify this file. Update the canonical version in Home\repo-template\src\Directory.Build.targets
-  then update all of the repos.
--->
-<!--
-  Replace PackageReferences with ProjectReferences when the projects can be found in .sln.
-  See the original here: https://github.com/dotnet/sdk/issues/1151#issuecomment-385133284
--->
-<Project>
-  <PropertyGroup>
-    <ReplacePackageReferences>true</ReplacePackageReferences>
-    <TheSolutionPath Condition=" '$(NCrunch)'=='' ">$(SolutionPath)</TheSolutionPath>
-    <TheSolutionPath Condition=" '$(NCrunch)'=='1' ">$(NCrunchOriginalSolutionPath)</TheSolutionPath>
-  </PropertyGroup>
-
-  <Choose>
-    <When Condition="$(ReplacePackageReferences) AND '$(TheSolutionPath)' != '' AND '$(TheSolutionPath)' != '*undefined*' AND Exists('$(TheSolutionPath)')">
-
-      <PropertyGroup>
-        <SolutionFileContent>$([System.IO.File]::ReadAllText($(TheSolutionPath)))</SolutionFileContent>
-        <SmartSolutionDir>$([System.IO.Path]::GetDirectoryName( $(TheSolutionPath) ))</SmartSolutionDir>
-        <RegexPattern>(?&lt;="[PackageName]", ")(.*)(?=", ")</RegexPattern>
-      </PropertyGroup>
-
-      <ItemGroup>
-        <!-- Keep the identity of the PackageReference -->
-        <SmartPackageReference Include="@(PackageReference)">
-          <PackageName>%(Identity)</PackageName>
-          <InSolution>$(SolutionFileContent.Contains('\%(Identity).csproj'))</InSolution>
-        </SmartPackageReference>
-
-        <!-- Filter them by mapping them to another ItemGroup using the WithMetadataValue item function -->
-        <PackageInSolution Include="@(SmartPackageReference->WithMetadataValue('InSolution', True))">
-          <Pattern>$(RegexPattern.Replace('[PackageName]','%(PackageName)') )</Pattern>
-          <SmartPath>$([System.Text.RegularExpressions.Regex]::Match('$(SolutionFileContent)', '%(Pattern)'))</SmartPath>
-        </PackageInSolution>
-
-        <ProjectReference  Include="@(PackageInSolution->'$(SmartSolutionDir)\%(SmartPath)' )"/>
-
-        <!-- Remove the package references that are now referenced as projects -->
-        <PackageReference Remove="@(PackageInSolution->'%(PackageName)' )"/>
-      </ItemGroup>
-
-    </When>
-  </Choose>
-</Project>
diff --git a/src/ca/CustomMsiErrors.h b/src/ca/CustomMsiErrors.h
deleted file mode 100644
index 1fd8d050..00000000
--- a/src/ca/CustomMsiErrors.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#pragma once
-// 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.
-
-#define msierrIISCannotConnect                 26001
-#define msierrIISFailedReadWebSite             26002
-#define msierrIISFailedReadWebDirs             26003
-#define msierrIISFailedReadVDirs               26004
-#define msierrIISFailedReadFilters             26005
-#define msierrIISFailedReadAppPool             26006
-#define msierrIISFailedReadMimeMap             26007
-#define msierrIISFailedReadProp                26008
-#define msierrIISFailedReadWebSvcExt           26009
-#define msierrIISFailedReadWebError            26010
-#define msierrIISFailedReadHttpHeader          26011
-
-#define msierrIISFailedSchedTransaction        26031
-#define msierrIISFailedSchedInstallWebs        26032
-#define msierrIISFailedSchedInstallWebDirs     26033
-#define msierrIISFailedSchedInstallVDirs       26034
-#define msierrIISFailedSchedInstallFilters     26035
-#define msierrIISFailedSchedInstallAppPool     26036
-#define msierrIISFailedSchedInstallProp        26037
-#define msierrIISFailedSchedInstallWebSvcExt   26038
-
-#define msierrIISFailedSchedUninstallWebs      26051
-#define msierrIISFailedSchedUninstallWebDirs   26052
-#define msierrIISFailedSchedUninstallVDirs     26053
-#define msierrIISFailedSchedUninstallFilters   26054
-#define msierrIISFailedSchedUninstallAppPool   26055
-#define msierrIISFailedSchedUninstallProp      26056
-#define msierrIISFailedSchedUninstallWebSvcExt 26057
-
-#define msierrIISFailedStartTransaction        26101
-#define msierrIISFailedOpenKey                 26102
-#define msierrIISFailedCreateKey               26103
-#define msierrIISFailedWriteData               26104
-#define msierrIISFailedCreateApp               26105
-#define msierrIISFailedDeleteKey               26106
-#define msierrIISFailedDeleteApp               26107
-#define msierrIISFailedDeleteValue             26108
-#define msierrIISFailedCommitInUse             26109
-
-// Last available value 26200
-
-#define msierrCERTFailedOpen                   26351
-#define msierrCERTFailedAdd                    26352
-
-// Last available value 26450
diff --git a/src/ca/caDecor.h b/src/ca/caDecor.h
deleted file mode 100644
index da274650..00000000
--- a/src/ca/caDecor.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-// 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.
-
-
-#if defined(_M_ARM64)
-#define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_A64"
-#elif defined(_M_AMD64)
-#define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_X64"
-#elif defined(_M_ARM)
-#define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_ARM"
-#else
-#define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_X86"
-#endif
diff --git a/src/ca/dllmain.cpp b/src/ca/dllmain.cpp
deleted file mode 100644
index 35ae6d1c..00000000
--- a/src/ca/dllmain.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-/********************************************************************
-DllMain - standard entry point for all WiX custom actions
-
-********************************************************************/
-extern "C" BOOL WINAPI DllMain(
-    IN HINSTANCE hInst,
-    IN ULONG ulReason,
-    IN LPVOID)
-{
-    switch(ulReason)
-    {
-    case DLL_PROCESS_ATTACH:
-        WcaGlobalInitialize(hInst);
-        break;
-
-    case DLL_PROCESS_DETACH:
-        WcaGlobalFinalize();
-        break;
-    }
-
-    return TRUE;
-}
diff --git a/src/ca/iisca.cpp b/src/ca/iisca.cpp
deleted file mode 100644
index 37664a1c..00000000
--- a/src/ca/iisca.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-// 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.
-
-#include "precomp.h"
diff --git a/src/ca/iisca.def b/src/ca/iisca.def
deleted file mode 100644
index b9127da6..00000000
--- a/src/ca/iisca.def
+++ /dev/null
@@ -1,30 +0,0 @@
-; 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.
-
-
-LIBRARY      "iisca"
-
-EXPORTS
-;scacert.cpp
-    InstallCertificates
-    UninstallCertificates
-;scacertexec.cpp
-    AddUserCertificate
-    AddMachineCertificate
-    DeleteUserCertificate
-    DeleteMachineCertificate
-;scaexec.cpp
-    StartMetabaseTransaction
-    RollbackMetabaseTransaction
-    CommitMetabaseTransaction
-
-    WriteMetabaseChanges
-
-    StartIIS7ConfigTransaction
-    RollbackIIS7ConfigTransaction
-    CommitIIS7ConfigTransaction
-
-    WriteIIS7ConfigChanges  
-;scasched.cpp
-    ConfigureIIs
-    ConfigureIIsExec
-    ConfigureIIs7Exec
diff --git a/src/ca/iisca.vcxproj b/src/ca/iisca.vcxproj
deleted file mode 100644
index eb1174be..00000000
--- a/src/ca/iisca.vcxproj
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="..\..\packages\WixToolset.DUtil.4.0.30\build\WixToolset.DUtil.props" Condition="Exists('..\..\packages\WixToolset.DUtil.4.0.30\build\WixToolset.DUtil.props')" />
-  <Import Project="..\..\packages\WixToolset.WcaUtil.4.0.16\build\WixToolset.WcaUtil.props" Condition="Exists('..\..\packages\WixToolset.WcaUtil.4.0.16\build\WixToolset.WcaUtil.props')" />
-
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|ARM64">
-      <Configuration>Debug</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|ARM64">
-      <Configuration>Release</Configuration>
-      <Platform>ARM64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}</ProjectGuid>
-    <ConfigurationType>DynamicLibrary</ConfigurationType>
-    <TargetName>iisca</TargetName>
-    <PlatformToolset>v142</PlatformToolset>
-    <CharacterSet>Unicode</CharacterSet>
-    <ProjectModuleDefinitionFile>iisca.def</ProjectModuleDefinitionFile>
-    <Description>WiX Toolset Iis CustomAction</Description>
-  </PropertyGroup>
-  
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  
-  <PropertyGroup>
-    <ProjectAdditionalLinkLibraries>crypt32.lib;msi.lib;Ws2_32.lib</ProjectAdditionalLinkLibraries>
-  </PropertyGroup>
-  
-  <ItemGroup>
-    <ClCompile Include="dllmain.cpp">
-      <PrecompiledHeader>Create</PrecompiledHeader>
-    </ClCompile>
-    <ClCompile Include="iisca.cpp" />
-    <ClCompile Include="scaapppool.cpp" />
-    <ClCompile Include="scaapppool7.cpp" />
-    <ClCompile Include="scacert.cpp" />
-    <ClCompile Include="scacertexec.cpp" />
-    <ClCompile Include="scaexec.cpp" />
-    <ClCompile Include="scaexecIIS7.cpp" />
-    <ClCompile Include="scafilter.cpp" />
-    <ClCompile Include="scafilter7.cpp" />
-    <ClCompile Include="scahttpheader.cpp" />
-    <ClCompile Include="scahttpheader7.cpp" />
-    <ClCompile Include="scaiis.cpp" />
-    <ClCompile Include="scaiis7.cpp" />
-    <ClCompile Include="scamimemap.cpp" />
-    <ClCompile Include="scamimemap7.cpp" />
-    <ClCompile Include="scaproperty.cpp" />
-    <ClCompile Include="scaproperty7.cpp" />
-    <ClCompile Include="scasched.cpp" />
-    <ClCompile Include="scassl.cpp" />
-    <ClCompile Include="scassl7.cpp" />
-    <ClCompile Include="scauser.cpp" />
-    <ClCompile Include="scavdir.cpp" />
-    <ClCompile Include="scavdir7.cpp" />
-    <ClCompile Include="scaweb.cpp" />
-    <ClCompile Include="scaweb7.cpp" />
-    <ClCompile Include="scawebapp.cpp" />
-    <ClCompile Include="scawebapp7.cpp" />
-    <ClCompile Include="scawebappext.cpp" />
-    <ClCompile Include="scawebappext7.cpp" />
-    <ClCompile Include="scawebdir.cpp" />
-    <ClCompile Include="scawebdir7.cpp" />
-    <ClCompile Include="scaweberr.cpp" />
-    <ClCompile Include="scaweberr7.cpp" />
-    <ClCompile Include="scaweblog.cpp" />
-    <ClCompile Include="scaweblog7.cpp" />
-    <ClCompile Include="scawebprop.cpp" />
-    <ClCompile Include="scawebprop7.cpp" />
-    <ClCompile Include="scawebsvcext.cpp" />
-    <ClCompile Include="scawebsvcext7.cpp" />
-    <ClInclude Include="caSuffix.h" />
-    <ClInclude Include="CustomMsiErrors.h" />
-    <ClInclude Include="precomp.h" />
-    <ClInclude Include="sca.h" />
-    <ClInclude Include="scaapppool.h" />
-    <ClInclude Include="scaapppool7.h" />
-    <ClInclude Include="scacert.h" />
-    <ClInclude Include="scacost.h" />
-    <ClInclude Include="scaexecIIS7.h" />
-    <ClInclude Include="scafilter.h" />
-    <ClInclude Include="scafilter7.h" />
-    <ClInclude Include="scahttpheader.h" />
-    <ClInclude Include="scahttpheader7.h" />
-    <ClInclude Include="scaiis.h" />
-    <ClInclude Include="scaiis7.h" />
-    <ClInclude Include="scamimemap.h" />
-    <ClInclude Include="scamimemap7.h" />
-    <ClInclude Include="scaproperty.h" />
-    <ClInclude Include="scaproperty7.h" />
-    <ClInclude Include="scassl.h" />
-    <ClInclude Include="scassl7.h" />
-    <ClInclude Include="scauser.h" />
-    <ClInclude Include="scavdir.h" />
-    <ClInclude Include="scavdir7.h" />
-    <ClInclude Include="scaweb.h" />
-    <ClInclude Include="scaweb7.h" />
-    <ClInclude Include="scawebapp.h" />
-    <ClInclude Include="scawebapp7.h" />
-    <ClInclude Include="scawebappext.h" />
-    <ClInclude Include="scawebappext7.h" />
-    <ClInclude Include="scawebdir.h" />
-    <ClInclude Include="scawebdir7.h" />
-    <ClInclude Include="scaweberr.h" />
-    <ClInclude Include="scaweberr7.h" />
-    <ClInclude Include="scaweblog.h" />
-    <ClInclude Include="scaweblog7.h" />
-    <ClInclude Include="scawebprop.h" />
-    <ClInclude Include="scawebprop7.h" />
-    <ClInclude Include="scawebsvcext.h" />
-    <ClInclude Include="scawebsvcext7.h" />
-    <None Include="packages.config" />
-    <None Include="iisca.def" />
-  </ItemGroup>
-  
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <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>
-    </PropertyGroup>
-    <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'))" />
-    <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'))" />
-  </Target>
-</Project>
\ No newline at end of file
diff --git a/src/ca/packages.config b/src/ca/packages.config
deleted file mode 100644
index e3dc0e43..00000000
--- a/src/ca/packages.config
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
-  <package id="WixToolset.DUtil" version="4.0.30" targetFramework="native" />
-  <package id="WixToolset.WcaUtil" version="4.0.16" targetFramework="native" />
-</packages>
\ No newline at end of file
diff --git a/src/ca/precomp.h b/src/ca/precomp.h
deleted file mode 100644
index 85ee0890..00000000
--- a/src/ca/precomp.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#pragma once
-// 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.
-
-
-#if _WIN32_MSI < 150
-#define _WIN32_MSI 150
-#endif
-
-#include <windows.h>
-#include <msiquery.h>
-#include <msidefs.h>
-#include <strsafe.h>
-
-#include <lm.h>        // NetApi32.lib
-
-#include <Dsgetdc.h>
-#include <ComAdmin.h>
-#include <ahadmin.h>    // IIS 7 config
-
-#define MAXUINT USHRT_MAX
-
-#include "wcautil.h"
-#include "wcawow64.h"
-#include "wcawrapquery.h"
-
-#include "certutil.h"
-#include "cryputil.h"
-#include "fileutil.h"
-#include "iis7util.h"
-#include "memutil.h"
-#include "metautil.h"
-#include "strutil.h"
-#include "userutil.h"
-#include "wiutil.h"
-
-#include "CustomMsiErrors.h"
-#include "sca.h"
-#include "scacost.h"
-#include "scacert.h"
-#include "scafilter.h"
-
-#include "scaiis.h"
-#include "scaiis7.h"
-#include "scaproperty.h"
-#include "scaweb.h"
-#include "scawebdir.h"
-#include "scawebsvcext.h"
-#include "scavdir.h"
-#include "scaweb7.h"
-#include "scaapppool7.h"
-#include "scavdir7.h"
-#include "scawebapp7.h"
-#include "scawebappext7.h"
-#include "scamimemap7.h"
-#include "scawebprop7.h"
-#include "scaweblog7.h"
-#include "scafilter7.h"
-#include "scahttpheader7.h"
-#include "scaweberr7.h"
-#include "scawebsvcext7.h"
-#include "scaproperty7.h"
-#include "scawebdir7.h"
-#include "scassl7.h"
-#include "scaexecIIS7.h"
-
-#include "caDecor.h"
diff --git a/src/ca/sca.h b/src/ca/sca.h
deleted file mode 100644
index 64567dcb..00000000
--- a/src/ca/sca.h
+++ /dev/null
@@ -1,124 +0,0 @@
-#pragma once
-// 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.
-
-
-#define MAGIC_MULTISZ_CHAR 127
-
-// Generic action enum.
-enum SCA_ACTION
-{
-    SCA_ACTION_NONE,
-    SCA_ACTION_INSTALL,
-    SCA_ACTION_UNINSTALL
-};
-
-
-// IIS Metabase actions
-enum METABASE_ACTION
-{
-    MBA_UNKNOWNACTION = 0,
-    MBA_CREATEKEY,
-    MBA_DELETEKEY,
-    MBA_WRITEVALUE,
-    MBA_DELETEVALUE,
-    MBA_CREATEAPP,
-    MBA_DELETEAPP,
-};
-
-// IIS 7 Config actions
-enum IIS_CONFIG_ACTION
-{
-    IIS_CREATE,
-    IIS_DELETE,
-    IIS_SITE,
-    IIS_APPLICATION,
-    IIS_APPPOOL,
-    IIS_APPPOOL_RECYCLE_MIN,
-    IIS_APPPOOL_RECYCLE_REQ,
-    IIS_APPPOOL_RECYCLE_TIMES,
-    IIS_APPPOOL_RECYCLE_VIRMEM,
-    IIS_APPPOOL_RECYCLE_PRIVMEM,
-    IIS_APPPOOL_RECYCLE_IDLTIMEOUT,
-    IIS_APPPOOL_RECYCLE_QUEUELIMIT,
-    IIS_APPPOOL_RECYCLE_CPU_PCT,
-    IIS_APPPOOL_RECYCLE_CPU_REFRESH,
-    IIS_APPPOOL_RECYCLE_CPU_ACTION,
-    IIS_APPPOOL_MAXPROCESS,
-    IIS_APPPOOL_IDENTITY,
-    IIS_APPPOOL_USER,
-    IIS_APPPOOL_PWD,
-    IIS_APPPOOL_32BIT,
-    IIS_APPPOOL_MANAGED_PIPELINE_MODE,
-    IIS_APPPOOL_MANAGED_RUNTIME_VERSION,
-    IIS_APPPOOL_END,
-    IIS_APPEXT_BEGIN,
-    IIS_APPEXT,
-    IIS_APPEXT_END,
-    IIS_VDIR,
-    IIS_BINDING,
-    IIS_MIMEMAP_BEGIN,
-    IIS_MIMEMAP,
-    IIS_MIMEMAP_END,
-    IIS_DIRPROP_BEGIN,
-    IIS_DIRPROP_ACCESS,
-    IIS_DIRPROP_AUTH,
-    IIS_DIRPROP_USER,
-    IIS_DIRPROP_PWD,
-    IIS_DIRPROP_PWDCTRL,
-    IIS_DIRPROP_LOG,
-    IIS_DIRPROP_DEFDOCS,
-    IIS_DIRPROP_SSLFLAGS,
-    IIS_DIRPROP_AUTHPROVID,
-    IIS_DIRPROP_ASPERROR,
-    IIS_DIRPROP_HTTPEXPIRES,
-    IIS_DIRPROP_MAXAGE,
-    IIS_DIRPROP_CACHECUST,
-    IIS_DIRPROP_NOCUSTERROR,
-    IIS_DIRPROP_LOGVISITS,
-    IIS_DIRPROP_END,
-    IIS_WEBLOG,
-    IIS_FILTER_BEGIN,
-    IIS_FILTER_GLOBAL_BEGIN,
-    IIS_FILTER,
-    IIS_FILTER_END,
-    IIS_HTTP_HEADER_BEGIN,
-    IIS_HTTP_HEADER,
-    IIS_HTTP_HEADER_END,
-    IIS_WEBERROR_BEGIN,
-    IIS_WEBERROR,
-    IIS_WEBERROR_END,
-    IIS_WEB_SVC_EXT,
-    IIS_PROPERTY,
-    IIS_PROPERTY_MAXBAND,
-    IIS_PROPERTY_LOGUTF8,
-    IIS_WEBDIR,
-    IIS_ASP_BEGIN,
-    IIS_ASP_SESSIONSTATE,
-    IIS_ASP_SESSIONTIMEOUT,
-    IIS_ASP_BUFFER,
-    IIS_ASP_PARENTPATHS,
-    IIS_ASP_SCRIPTLANG,
-    IIS_ASP_SCRIPTTIMEOUT,
-    IIS_ASP_SCRIPTSERVERDEBUG,
-    IIS_ASP_SCRIPTCLIENTDEBUG,
-    IIS_ASP_END,
-    IIS_SSL_BINDING
-};
-
-
-// user creation attributes definitions
-enum SCAU_ATTRIBUTES
-{
-    SCAU_DONT_EXPIRE_PASSWRD = 0x00000001,
-    SCAU_PASSWD_CANT_CHANGE = 0x00000002,
-    SCAU_PASSWD_CHANGE_REQD_ON_LOGIN = 0x00000004,
-    SCAU_DISABLE_ACCOUNT = 0x00000008,
-    SCAU_FAIL_IF_EXISTS = 0x00000010,
-    SCAU_UPDATE_IF_EXISTS = 0x00000020,
-    SCAU_ALLOW_LOGON_AS_SERVICE = 0x00000040,
-    SCAU_ALLOW_LOGON_AS_BATCH = 0x00000080,
-
-    SCAU_DONT_REMOVE_ON_UNINSTALL = 0x00000100,
-    SCAU_DONT_CREATE_USER = 0x00000200,
-    SCAU_NON_VITAL = 0x00000400,
-};
diff --git a/src/ca/scaapppool.cpp b/src/ca/scaapppool.cpp
deleted file mode 100644
index 781c55ca..00000000
--- a/src/ca/scaapppool.cpp
+++ /dev/null
@@ -1,594 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-/*------------------------------------------------------------------
-AppPool table:
-
-Column                Type   Nullable     Example Value
-AppPool               s72    No           TestPool
-Name                  s72    No           "TestPool"
-Component_            s72    No           ComponentName
-Attributes            i2     No           8 (APATTR_OTHERUSER)
-User_                 s72    Yes          UserKey
-RecycleMinutes        i2     Yes          500
-RecycleRequests       i2     Yes          5000
-RecycleTimes          s72    Yes          "1:45,13:30,22:00"
-IdleTimeout           i2     Yes          15
-QueueLimit            i2     Yes          500
-CPUMon                s72    Yes          "65,500,1" (65% CPU usage, 500 minutes, Shutdown Action)
-MaxProc               i2     Yes          5
-ManagedRuntimeVersion s72    Yes          "v2.0"
-ManagedPipelineMode   s72    Yes          "Integrated"
-
-Notes:
-RecycleTimes is a comma delimeted list of times.  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).
-
-------------------------------------------------------------------*/
-
-enum eAppPoolQuery { apqAppPool = 1, apqName, apqComponent, apqAttributes, apqUser, apqRecycleMinutes, apqRecycleRequests, apqRecycleTimes, apqVirtualMemory, apqPrivateMemory, apqIdleTimeout, apqQueueLimit, apqCpuMon, apqMaxProc, apqManagedRuntimeVersion, apqManagedPipelineMode, apqInstalled, apqAction };
-
-enum eComponentAttrQuery { caqComponent = 1, caqAttributes };
-
-// prototypes
-static HRESULT AppPoolExists(
-    __in IMSAdminBase* piMetabase,
-    __in LPCWSTR wzAppPool
-    );
-
-// functions
-
-void ScaAppPoolFreeList(
-    __in SCA_APPPOOL* psapList
-    )
-{
-    SCA_APPPOOL* psapDelete = psapList;
-    while (psapList)
-    {
-        psapDelete = psapList;
-        psapList = psapList->psapNext;
-
-        MemFree(psapDelete);
-    }
-}
-
-
-HRESULT ScaAppPoolRead(
-    __inout SCA_APPPOOL** ppsapList,
-    __in WCA_WRAPQUERY_HANDLE hUserQuery,
-    __inout LPWSTR *ppwzCustomActionData
-    )
-{
-    Assert(ppsapList);
-
-    HRESULT hr = S_OK;
-
-    MSIHANDLE hRec, hRecComp;
-    LPWSTR pwzData = NULL;
-    SCA_APPPOOL* psap = NULL;
-    WCA_WRAPQUERY_HANDLE hAppPoolQuery = NULL;
-    WCA_WRAPQUERY_HANDLE hComponentQuery = NULL;
-
-    hr = WcaBeginUnwrapQuery(&hAppPoolQuery, ppwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead");
-
-    if (0 == WcaGetQueryRecords(hAppPoolQuery))
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ScaAppPoolRead() - required table not present");
-        ExitFunction1(hr = S_FALSE);
-    }
-    
-    hr = WcaBeginUnwrapQuery(&hComponentQuery, ppwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead");
-
-    // loop through all the AppPools
-    while (S_OK == (hr = WcaFetchWrappedRecord(hAppPoolQuery, &hRec)))
-    {
-        // Add this record's information into the list of things to process.
-        hr = AddAppPoolToList(ppsapList);
-        ExitOnFailure(hr, "failed to add app pool to app pool list");
-
-        psap = *ppsapList;
-
-        hr = WcaGetRecordString(hRec, apqComponent, &pwzData);
-        ExitOnFailure(hr, "failed to get AppPool.Component");
-
-        if (pwzData && *pwzData)
-        {
-            psap->fHasComponent = TRUE;
-
-            hr = ::StringCchCopyW(psap->wzComponent, countof(psap->wzComponent), pwzData);
-            ExitOnFailure(hr, "failed to copy component name: %ls", pwzData);
-
-            hr = WcaGetRecordInteger(hRec, apqInstalled, (int *)&psap->isInstalled);
-            ExitOnFailure(hr, "Failed to get Component installed state for app pool");
-
-            hr = WcaGetRecordInteger(hRec, apqAction, (int *)&psap->isAction);
-            ExitOnFailure(hr, "Failed to get Component action state for app pool");
-
-            WcaFetchWrappedReset(hComponentQuery);
-            hr = WcaFetchWrappedRecordWhereString(hComponentQuery, caqComponent, psap->wzComponent, &hRecComp);
-            ExitOnFailure(hr, "Failed to fetch Component.Attributes for Component '%ls'", psap->wzComponent);
-
-            hr = WcaGetRecordInteger(hRecComp, caqAttributes, &psap->iCompAttributes);
-            ExitOnFailure(hr, "failed to get Component.Attributes");
-        }
-
-        hr = WcaGetRecordString(hRec, apqAppPool, &pwzData);
-        ExitOnFailure(hr, "failed to get AppPool.AppPool");
-        hr = ::StringCchCopyW(psap->wzAppPool, countof(psap->wzAppPool), pwzData);
-        ExitOnFailure(hr, "failed to copy AppPool name: %ls", pwzData);
-
-        hr = WcaGetRecordString(hRec, apqName, &pwzData);
-        ExitOnFailure(hr, "failed to get AppPool.Name");
-        hr = ::StringCchCopyW(psap->wzName, countof(psap->wzName), pwzData);
-        ExitOnFailure(hr, "failed to copy app pool name: %ls", pwzData);
-        hr = ::StringCchPrintfW(psap->wzKey, countof(psap->wzKey), L"/LM/W3SVC/AppPools/%s", pwzData);
-        ExitOnFailure(hr, "failed to format app pool key name");
-
-        hr = WcaGetRecordInteger(hRec, apqAttributes, &psap->iAttributes);
-        ExitOnFailure(hr, "failed to get AppPool.Attributes");
-
-        hr = WcaGetRecordString(hRec, apqUser, &pwzData);
-        ExitOnFailure(hr, "failed to get AppPool.User");
-        hr = ScaGetUserDeferred(pwzData, hUserQuery, &psap->suUser);
-        ExitOnFailure(hr, "failed to get user: %ls", pwzData);
-
-        hr = WcaGetRecordInteger(hRec, apqRecycleRequests, &psap->iRecycleRequests);
-        ExitOnFailure(hr, "failed to get AppPool.RecycleRequests");
-
-        hr = WcaGetRecordInteger(hRec, apqRecycleMinutes, &psap->iRecycleMinutes);
-        ExitOnFailure(hr, "failed to get AppPool.Minutes");
-
-        hr = WcaGetRecordString(hRec, apqRecycleTimes, &pwzData);
-        ExitOnFailure(hr, "failed to get AppPool.RecycleTimes");
-        hr = ::StringCchCopyW(psap->wzRecycleTimes, countof(psap->wzRecycleTimes), pwzData);
-        ExitOnFailure(hr, "failed to copy recycle value: %ls", pwzData);
-
-        hr = WcaGetRecordInteger(hRec, apqVirtualMemory, &psap->iVirtualMemory);
-        ExitOnFailure(hr, "failed to get AppPool.VirtualMemory");
-
-        hr = WcaGetRecordInteger(hRec, apqPrivateMemory, &psap->iPrivateMemory);
-        ExitOnFailure(hr, "failed to get AppPool.PrivateMemory");
-
-        hr = WcaGetRecordInteger(hRec, apqIdleTimeout, &psap->iIdleTimeout);
-        ExitOnFailure(hr, "failed to get AppPool.IdleTimeout");
-
-        hr = WcaGetRecordInteger(hRec, apqQueueLimit, &psap->iQueueLimit);
-        ExitOnFailure(hr, "failed to get AppPool.QueueLimit");
-
-        hr = WcaGetRecordString(hRec, apqCpuMon, &pwzData);
-        ExitOnFailure(hr, "failed to get AppPool.CPUMon");
-        hr = ::StringCchCopyW(psap->wzCpuMon, countof(psap->wzCpuMon), pwzData);
-        ExitOnFailure(hr, "failed to copy cpu monitor value: %ls", pwzData);
-
-        hr = WcaGetRecordInteger(hRec, apqMaxProc, &psap->iMaxProcesses);
-        ExitOnFailure(hr, "failed to get AppPool.MaxProc");
-
-        hr = WcaGetRecordString(hRec, apqManagedRuntimeVersion, &pwzData);
-        ExitOnFailure(hr, "failed to get AppPool.ManagedRuntimeVersion");
-        hr = ::StringCchCopyW(psap->wzManagedRuntimeVersion, countof(psap->wzManagedRuntimeVersion), pwzData);
-        ExitOnFailure(hr, "failed to copy ManagedRuntimeVersion value: %ls", pwzData);
-
-        hr = WcaGetRecordString(hRec, apqManagedPipelineMode, &pwzData);
-        ExitOnFailure(hr, "failed to get AppPool.ManagedPipelineMode");
-        hr = ::StringCchCopyW(psap->wzManagedPipelineMode, countof(psap->wzManagedPipelineMode), pwzData);
-        ExitOnFailure(hr, "failed to copy ManagedPipelineMode value: %ls", pwzData);
-
-    }
-
-    if (E_NOMOREITEMS == hr)
-    {
-        hr = S_OK;
-    }
-    ExitOnFailure(hr, "failure while processing AppPools");
-
-LExit:
-    WcaFinishUnwrapQuery(hAppPoolQuery);
-    WcaFinishUnwrapQuery(hComponentQuery);
-
-    ReleaseStr(pwzData);
-    return hr;
-}
-
-
-HRESULT ScaFindAppPool(
-    __in IMSAdminBase* piMetabase,
-    __in LPCWSTR wzAppPool,
-    __out_ecount(cchName) LPWSTR wzName,
-    __in DWORD cchName,
-    __in SCA_APPPOOL *psapList
-    )
-{
-    Assert(piMetabase && wzAppPool && *wzAppPool && wzName && *wzName);
-
-    HRESULT hr = S_OK;
-
-    // check memory first
-    SCA_APPPOOL* psap = psapList;
-    for (; psap; psap = psap->psapNext)
-    {
-        if (0 == lstrcmpW(psap->wzAppPool, wzAppPool))
-        {
-            break;
-        }
-    }
-    ExitOnNull(psap, hr, HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Could not find the app pool: %ls", wzAppPool);
-
-    // copy the web app pool name
-    hr = ::StringCchCopyW(wzName, cchName, psap->wzName);
-    ExitOnFailure(hr, "failed to copy app pool name while finding app pool: %ls", psap->wzName);
-
-    // if it's not being installed now, check if it exists already
-    if (!psap->fHasComponent)
-    {
-        hr = AppPoolExists(piMetabase, psap->wzName);
-        ExitOnFailure(hr, "failed to check for existence of app pool: %ls", psap->wzName);
-    }
-
-LExit:
-    return hr;
-}
-
-
-static HRESULT AppPoolExists(
-    __in IMSAdminBase* piMetabase,
-    __in LPCWSTR wzAppPool
-    )
-{
-    Assert(piMetabase && wzAppPool && *wzAppPool);
-
-    HRESULT hr = S_OK;
-    WCHAR wzSubKey[METADATA_MAX_NAME_LEN];
-
-    for (DWORD dwIndex = 0; SUCCEEDED(hr); ++dwIndex)
-    {
-        hr = piMetabase->EnumKeys(METADATA_MASTER_ROOT_HANDLE, L"/LM/W3SVC/AppPools", wzSubKey, dwIndex);
-        if (SUCCEEDED(hr) && 0 == lstrcmpW(wzSubKey, wzAppPool))
-        {
-            hr = S_OK;
-            break;
-        }
-    }
-
-    if (E_NOMOREITEMS == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
-    {
-        hr = S_FALSE;
-    }
-
-    return hr;
-}
-
-
-HRESULT ScaAppPoolInstall(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_APPPOOL* psapList
-    )
-{
-    Assert(piMetabase);
-
-    HRESULT hr = S_OK;
-
-    for (SCA_APPPOOL* psap = psapList; psap; psap = psap->psapNext)
-    {
-        // if we are installing the app pool
-        if (psap->fHasComponent && WcaIsInstalling(psap->isInstalled, psap->isAction))
-        {
-            hr = ScaWriteAppPool(piMetabase, psap);
-            ExitOnFailure(hr, "failed to write AppPool '%ls' to metabase", psap->wzAppPool);
-        }
-    }
-
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaAppPoolUninstall(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_APPPOOL* psapList
-    )
-{
-    Assert(piMetabase);
-
-    HRESULT hr = S_OK;
-
-    for (SCA_APPPOOL* psap = psapList; psap; psap = psap->psapNext)
-    {
-        // if we are uninstalling the app pool
-        if (psap->fHasComponent && WcaIsUninstalling(psap->isInstalled, psap->isAction))
-        {
-            hr = ScaRemoveAppPool(piMetabase, psap);
-            ExitOnFailure(hr, "Failed to remove AppPool '%ls' from metabase", psap->wzAppPool);
-        }
-    }
-
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaWriteAppPool(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_APPPOOL* psap
-    )
-{
-    Assert(piMetabase && psap);
-
-    HRESULT hr = S_OK;
-    DWORD dwIdentity = 0xFFFFFFFF;
-    BOOL fExists = FALSE;
-    LPWSTR pwzValue = NULL;
-    LPWSTR wz = NULL;
-
-    hr = AppPoolExists(piMetabase, psap->wzName);
-    ExitOnFailure(hr, "failed to check if app pool already exists");
-    if (S_FALSE == hr)
-    {
-        // didn't find the AppPool key, so we need to create it
-        hr = ScaCreateMetabaseKey(piMetabase, psap->wzKey, L"");
-        ExitOnFailure(hr, "failed to create AppPool key: %ls", psap->wzKey);
-
-        // mark it as an AppPool
-        hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsApplicationPool");
-        ExitOnFailure(hr, "failed to mark key as AppPool key: %ls", psap->wzKey);
-
-        // TODO: Make this an Attribute?
-        // set autostart value
-        hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_AUTO_START, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)1);
-        ExitOnFailure(hr, "failed to mark key as AppPool key: %ls", psap->wzKey);
-    }
-    else
-    {
-        fExists = TRUE;
-    }
-
-    //
-    // Set the AppPool Recycling Tab
-    //
-    if (MSI_NULL_INTEGER != psap->iRecycleMinutes)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_PERIODIC_RESTART_TIME, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iRecycleMinutes));
-        ExitOnFailure(hr, "failed to set periodic restart time");
-    }
-
-    if (MSI_NULL_INTEGER != psap->iRecycleRequests)
-    {
-        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));
-        ExitOnFailure(hr, "failed to set periodic restart request count");
-    }
-
-    if (*psap->wzRecycleTimes)
-    {
-        // Add another NULL' onto pwz since it's a 'MULTISZ'
-        hr = StrAllocString(&pwzValue, psap->wzRecycleTimes, 0);
-        ExitOnFailure(hr, "failed to allocate string for MULTISZ");
-        hr = StrAllocConcat(&pwzValue, L"\0", 1);
-        ExitOnFailure(hr, "failed to add second null to RecycleTime multisz");
-
-        // Replace the commas with NULLs
-        wz = pwzValue;
-        while (NULL != (wz = wcschr(wz, L',')))
-        {
-            *wz = L'\0';
-            ++wz;
-        }
-
-        hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_PERIODIC_RESTART_SCHEDULE, METADATA_INHERIT, IIS_MD_UT_SERVER, MULTISZ_METADATA, (LPVOID)pwzValue);
-        ExitOnFailure(hr, "failed to set periodic restart schedule");
-    }
-
-    if (MSI_NULL_INTEGER != psap->iVirtualMemory)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_PERIODIC_RESTART_MEMORY, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iVirtualMemory));
-        ExitOnFailure(hr, "failed to set periodic restart memory count");
-    }
-
-    if (MSI_NULL_INTEGER != psap->iPrivateMemory)
-    {
-        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));
-        ExitOnFailure(hr, "failed to set periodic restart private memory count");
-    }
-
-
-    //
-    // Set AppPool Performance Tab
-    //
-    if (MSI_NULL_INTEGER != psap->iIdleTimeout)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_IDLE_TIMEOUT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iIdleTimeout));
-        ExitOnFailure(hr, "failed to set idle timeout value");
-    }
-
-    if (MSI_NULL_INTEGER != psap->iQueueLimit)
-    {
-        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));
-        ExitOnFailure(hr, "failed to set request queue limit value");
-    }
-
-    if (*psap->wzCpuMon)
-    {
-        hr = StrAllocString(&pwzValue, psap->wzCpuMon, 0);
-        ExitOnFailure(hr, "failed to allocate CPUMonitor string");
-
-        DWORD dwPercent = 0;
-        DWORD dwRefreshMinutes = 0;
-        DWORD dwAction = 0;
-
-        dwPercent = wcstoul(pwzValue, &wz, 10);
-        if (100  < dwPercent)
-        {
-            ExitOnFailure(hr = E_INVALIDARG, "invalid maximum cpu percentage value: %d", dwPercent);
-        }
-        if (wz && L',' == *wz)
-        {
-            ++wz;
-            dwRefreshMinutes = wcstoul(wz, &wz, 10);
-            if (wz && L',' == *wz)
-            {
-                ++wz;
-                dwAction = wcstoul(wz, &wz, 10);
-            }
-        }
-
-        if (dwPercent)
-        {
-            hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_CPU_LIMIT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)(dwPercent * 1000)));
-            ExitOnFailure(hr, "failed to set CPU percentage max");
-        }
-        if (dwRefreshMinutes)
-        {
-            hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_CPU_RESET_INTERVAL, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwRefreshMinutes));
-            ExitOnFailure(hr, "failed to set refresh CPU minutes");
-        }
-        if (dwAction)
-        {
-            // 0 = No Action
-            // 1 = Shutdown
-            hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_CPU_ACTION, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwAction));
-            ExitOnFailure(hr, "failed to set CPU action");
-        }
-    }
-
-    if (MSI_NULL_INTEGER != psap->iMaxProcesses)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_MAX_PROCESS_COUNT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iMaxProcesses));
-        ExitOnFailure(hr, "failed to set web garden maximum worker processes");
-    }
-
-    // TODO: Health Tab if anyone wants it?
-
-    //
-    // Set the AppPool Identity tab
-    //
-    if (psap->iAttributes & APATTR_NETSERVICE)
-    {
-        dwIdentity = MD_APPPOOL_IDENTITY_TYPE_NETWORKSERVICE;
-    }
-    else if (psap->iAttributes & APATTR_LOCSERVICE)
-    {
-        dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSERVICE;
-    }
-    else if (psap->iAttributes & APATTR_LOCSYSTEM)
-    {
-        dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSYSTEM;
-    }
-    else if (psap->iAttributes & APATTR_OTHERUSER)
-    {
-        if (!*psap->suUser.wzDomain || CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzDomain, -1, L".", -1))
-        {
-            if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"NetworkService", -1))
-            {
-                dwIdentity = MD_APPPOOL_IDENTITY_TYPE_NETWORKSERVICE;
-            }
-            else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"LocalService", -1))
-            {
-                dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSERVICE;
-            }
-            else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"LocalSystem", -1))
-            {
-                dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSYSTEM;
-            }
-            else
-            {
-                dwIdentity = MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER;
-            }
-        }
-        else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzDomain, -1, L"NT AUTHORITY", -1))
-        {
-            if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"NETWORK SERVICE", -1))
-            {
-                dwIdentity = MD_APPPOOL_IDENTITY_TYPE_NETWORKSERVICE;
-            }
-            else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"SERVICE", -1))
-            {
-                dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSERVICE;
-            }
-            else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"SYSTEM", -1))
-            {
-                dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSYSTEM;
-            }
-            else
-            {
-                dwIdentity = MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER;
-            }
-        }
-        else
-        {
-            dwIdentity = MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER;
-        }
-    }
-
-    if (-1 != dwIdentity)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_IDENTITY_TYPE, METADATA_INHERIT , IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwIdentity));
-        ExitOnFailure(hr, "failed to set app pool identity");
-
-        if (MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER == dwIdentity)
-        {
-            if (*psap->suUser.wzDomain)
-            {
-                hr = StrAllocFormatted(&pwzValue, L"%s\\%s", psap->suUser.wzDomain, psap->suUser.wzName);
-                ExitOnFailure(hr, "failed to format user name: %ls domain: %ls", psap->suUser.wzName, psap->suUser.wzDomain);
-            }
-            else
-            {
-                hr = StrAllocFormatted(&pwzValue, L"%s", psap->suUser.wzName);
-                ExitOnFailure(hr, "failed to format user name: %ls", psap->suUser.wzName);
-            }
-
-            hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_WAM_USER_NAME, METADATA_INHERIT , IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pwzValue);
-            ExitOnFailure(hr, "failed to set app pool identity name");
-
-            hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_WAM_PWD, METADATA_INHERIT | METADATA_SECURE, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)psap->suUser.wzPassword);
-            ExitOnFailure(hr, "failed to set app pool identity password");
-        }
-    }
-
-LExit:
-    ReleaseStr(pwzValue);
-
-    return hr;
-}
-
-
-HRESULT ScaRemoveAppPool(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_APPPOOL* psap
-    )
-{
-    Assert(piMetabase && psap);
-
-    HRESULT hr = S_OK;
-
-    // simply remove the root key and everything else is pulled at the same time
-    if (0 != lstrlenW(psap->wzKey))
-    {
-        hr = ScaDeleteMetabaseKey(piMetabase, psap->wzKey, L"");
-        ExitOnFailure(hr, "failed to delete AppPool key: %ls", psap->wzKey);
-    }
-
-    // TODO: Maybe check to make sure any web sites that are using this AppPool are put back in the 'DefaultAppPool'
-
-LExit:
-    return hr;
-}
-
-
-HRESULT AddAppPoolToList(
-    __in SCA_APPPOOL** ppsapList
-    )
-{
-    HRESULT hr = S_OK;
-    SCA_APPPOOL* psap = static_cast<SCA_APPPOOL*>(MemAlloc(sizeof(SCA_APPPOOL), TRUE));
-    ExitOnNull(psap, hr, E_OUTOFMEMORY, "failed to allocate memory for new element in app pool list");
-
-    psap->psapNext = *ppsapList;
-    *ppsapList = psap;
-
-LExit:
-    return hr;
-}
diff --git a/src/ca/scaapppool.h b/src/ca/scaapppool.h
deleted file mode 100644
index 68575fcb..00000000
--- a/src/ca/scaapppool.h
+++ /dev/null
@@ -1,88 +0,0 @@
-#pragma once
-// 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.
-
-
-#include "scauser.h"
-
-// Identity
-#define APATTR_NETSERVICE 0x0001 // Network Service
-#define APATTR_LOCSERVICE 0x0002 // Local Service
-#define APATTR_LOCSYSTEM 0x0004 // Local System
-#define APATTR_OTHERUSER 0x0008 // Other User
-
-struct SCA_APPPOOL
-{
-    // iis app pool configuation information
-    WCHAR wzAppPool[MAX_DARWIN_KEY + 1];
-    WCHAR wzName[METADATA_MAX_NAME_LEN + 1];
-    WCHAR wzKey[METADATA_MAX_NAME_LEN + 1];
-    WCHAR wzComponent[METADATA_MAX_NAME_LEN + 1];
-    BOOL fHasComponent;
-    INSTALLSTATE isInstalled;
-    INSTALLSTATE isAction;
-    INT iAttributes;
-
-    SCA_USER suUser;
-
-    INT iRecycleRequests;
-    INT iRecycleMinutes;
-    WCHAR wzRecycleTimes[MAX_DARWIN_KEY + 1];
-    INT iVirtualMemory;
-    INT iPrivateMemory;
-
-    INT iIdleTimeout;
-    INT iQueueLimit;
-    WCHAR wzCpuMon[MAX_DARWIN_KEY + 1];
-    INT iMaxProcesses;
-    WCHAR wzManagedPipelineMode[MAX_DARWIN_KEY + 1];
-    WCHAR wzManagedRuntimeVersion[MAX_DARWIN_KEY + 1];
-
-    int iCompAttributes;
-
-    SCA_APPPOOL *psapNext;
-};
-
-
-// prototypes
-
-HRESULT ScaAppPoolRead(
-    __inout SCA_APPPOOL** ppsapList,
-    __in WCA_WRAPQUERY_HANDLE hUserQuery,
-    __inout LPWSTR *ppwzCustomActionData
-    );
-
-void ScaAppPoolFreeList(
-    __in SCA_APPPOOL* psapList
-    );
-
-HRESULT ScaFindAppPool(
-    __in IMSAdminBase* piMetabase,
-    __in LPCWSTR wzAppPool,
-    __out_ecount(cchName) LPWSTR wzName,
-    __in DWORD cchName,
-    __in SCA_APPPOOL *psapList
-    );
-
-HRESULT ScaAppPoolInstall(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_APPPOOL* psapList
-    );
-
-HRESULT ScaAppPoolUninstall(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_APPPOOL* psapList
-    );
-
-HRESULT ScaWriteAppPool(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_APPPOOL* psap
-    );
-
-HRESULT ScaRemoveAppPool(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_APPPOOL* psap
-    );
-
-HRESULT AddAppPoolToList(
-    __in SCA_APPPOOL** ppsapList
-    );
diff --git a/src/ca/scaapppool7.cpp b/src/ca/scaapppool7.cpp
deleted file mode 100644
index 0fac4346..00000000
--- a/src/ca/scaapppool7.cpp
+++ /dev/null
@@ -1,401 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-// prototypes
-static HRESULT AppPoolExists(
-    __in LPCWSTR wzAppPool
-    );
-
-// functions
-HRESULT ScaFindAppPool7(
-    __in LPCWSTR wzAppPool,
-    __out_ecount(cchName) LPWSTR wzName,
-    __in DWORD cchName,
-    __in SCA_APPPOOL *psapList
-    )
-{
-    Assert(wzAppPool && *wzAppPool && wzName && *wzName);
-
-    HRESULT hr = S_OK;
-
-    // check memory first
-    SCA_APPPOOL* psap = psapList;
-    for (; psap; psap = psap->psapNext)
-    {
-        if (0 == wcscmp(psap->wzAppPool, wzAppPool))
-        {
-            break;
-        }
-    }
-    ExitOnNull(psap, hr, HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Could not find the app pool: %ls", wzAppPool);
-
-    // copy the web app pool name
-#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
-    hr = ::StringCchCopyW(wzName, cchName, psap->wzName);
-    ExitOnFailure(hr, "failed to copy app pool name while finding app pool: %ls", psap->wzName);
-
-    // if it's not being installed now, check if it exists already
-    if (!psap->fHasComponent)
-    {
-        hr = AppPoolExists(psap->wzName);
-        ExitOnFailure(hr, "failed to check for existence of app pool: %ls", psap->wzName);
-    }
-
-LExit:
-    return hr;
-}
-
-
-static HRESULT AppPoolExists(
-    __in LPCWSTR /*wzAppPool*/
-    )
-{
-    HRESULT hr = S_OK;
-
-    //this function checks for existance of app pool in IIS7 config
-    //at schedule time, we will defer this to execute time.
-
-    return hr;
-}
-
-
-HRESULT ScaAppPoolInstall7(
-    __in SCA_APPPOOL* psapList
-    )
-{
-    HRESULT hr = S_OK;
-
-    for (SCA_APPPOOL* psap = psapList; psap; psap = psap->psapNext)
-    {
-        // if we are installing the app pool
-        if (psap->fHasComponent && WcaIsInstalling(psap->isInstalled, psap->isAction))
-        {
-            hr = ScaWriteAppPool7(psap);
-            ExitOnFailure(hr, "failed to write AppPool '%ls' to metabase", psap->wzAppPool);
-        }
-    }
-
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaAppPoolUninstall7(
-    __in SCA_APPPOOL* psapList
-    )
-{
-
-    HRESULT hr = S_OK;
-
-    for (SCA_APPPOOL* psap = psapList; psap; psap = psap->psapNext)
-    {
-        // if we are uninstalling the app pool
-        if (psap->fHasComponent && WcaIsUninstalling(psap->isInstalled, psap->isAction))
-        {
-            hr = ScaRemoveAppPool7(psap);
-            ExitOnFailure(hr, "Failed to remove AppPool '%ls' from metabase", psap->wzAppPool);
-        }
-    }
-
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaWriteAppPool7(
-    __in const SCA_APPPOOL* psap
-    )
-{
-    Assert(psap);
-
-    HRESULT hr = S_OK;
-    DWORD dwIdentity = 0xFFFFFFFF;
-    LPWSTR pwzValue = NULL;
-    LPWSTR wz = NULL;
-
-    //create the app pool
-    hr = ScaWriteConfigID(IIS_APPPOOL);
-    ExitOnFailure(hr, "failed to write AppPool key.");
-
-    hr = ScaWriteConfigID(IIS_CREATE);
-    ExitOnFailure(hr, "failed to write AppPool create action.");
-
-    hr = ScaWriteConfigString(psap->wzName);
-    ExitOnFailure(hr, "failed to write AppPool name: %ls", psap->wzName);
-
-    // Now do all the optional stuff
-
-    // Set the AppPool Recycling Tab
-    if (MSI_NULL_INTEGER != psap->iRecycleMinutes)
-    {
-        hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_MIN);
-        ExitOnFailure(hr, "failed to set periodic restart time id");
-        hr = ScaWriteConfigInteger(psap->iRecycleMinutes);
-        ExitOnFailure(hr, "failed to set periodic restart time");
-    }
-
-    if (MSI_NULL_INTEGER != psap->iRecycleRequests)
-    {
-        hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_REQ);
-        ExitOnFailure(hr, "failed to set periodic restart request count id");
-        hr = ScaWriteConfigInteger(psap->iRecycleRequests);
-        ExitOnFailure(hr, "failed to set periodic restart request count");
-    }
-
-    if (*psap->wzRecycleTimes)
-    {
-        hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_TIMES);
-        ExitOnFailure(hr, "failed to set periodic restart schedule id");
-        hr = ScaWriteConfigString(psap->wzRecycleTimes);
-        ExitOnFailure(hr, "failed to set periodic restart schedule");
-    }
-
-    if (MSI_NULL_INTEGER != psap->iVirtualMemory)
-    {
-        hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_VIRMEM);
-        ExitOnFailure(hr, "failed to set periodic restart memory count id");
-        hr = ScaWriteConfigInteger(psap->iVirtualMemory);
-        ExitOnFailure(hr, "failed to set periodic restart memory count");
-    }
-
-    if (MSI_NULL_INTEGER != psap->iPrivateMemory)
-    {
-        hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_PRIVMEM);
-        ExitOnFailure(hr, "failed to set periodic restart private memory count id");
-        hr = ScaWriteConfigInteger(psap->iPrivateMemory);
-        ExitOnFailure(hr, "failed to set periodic restart private memory count");
-    }
-
-    // Set AppPool Performance Tab
-    if (MSI_NULL_INTEGER != psap->iIdleTimeout)
-    {
-        hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_IDLTIMEOUT);
-        ExitOnFailure(hr, "failed to set idle timeout value id");
-        hr = ScaWriteConfigInteger(psap->iIdleTimeout);
-        ExitOnFailure(hr, "failed to set idle timeout value");
-    }
-
-    if (MSI_NULL_INTEGER != psap->iQueueLimit)
-    {
-        hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_QUEUELIMIT);
-        ExitOnFailure(hr, "failed to set request queue limit value id");
-        hr = ScaWriteConfigInteger(psap->iQueueLimit);
-        ExitOnFailure(hr, "failed to set request queue limit value");
-    }
-    if (*psap->wzCpuMon)
-    {
-#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
-        hr = ::StrAllocString(&pwzValue, psap->wzCpuMon, 0);
-        ExitOnFailure(hr, "failed to allocate CPUMonitor string");
-
-        DWORD dwPercent = 0;
-        DWORD dwRefreshMinutes = 0;
-        DWORD dwAction = 0;
-
-        dwPercent = wcstoul(pwzValue, &wz, 10);
-        if (100  < dwPercent)
-        {
-            ExitOnFailure(hr = E_INVALIDARG, "invalid maximum cpu percentage value: %d", dwPercent);
-        }
-        if (wz && L',' == *wz)
-        {
-            ++wz;
-            dwRefreshMinutes = wcstoul(wz, &wz, 10);
-            if (wz && L',' == *wz)
-            {
-                ++wz;
-                dwAction = wcstoul(wz, &wz, 10);
-            }
-        }
-        if (dwPercent)
-        {
-            hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_CPU_PCT);
-            ExitOnFailure(hr, "failed to set recycle pct id");
-            hr = ScaWriteConfigInteger(dwPercent);
-            ExitOnFailure(hr, "failed to set CPU percentage max");
-        }
-        if (dwRefreshMinutes)
-        {
-            hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_CPU_REFRESH);
-            ExitOnFailure(hr, "failed to set recycle refresh id");
-            hr = ScaWriteConfigInteger(dwRefreshMinutes);
-            ExitOnFailure(hr, "failed to set refresh CPU minutes");
-        }
-        if (dwAction)
-        {
-            // 0 = No Action
-            // 1 = Shutdown
-            hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_CPU_ACTION);
-            ExitOnFailure(hr, "failed to set recycle refresh id");
-            hr = ScaWriteConfigInteger(dwAction);
-            ExitOnFailure(hr, "failed to set CPU action");
-        }
-    }
-
-    if (MSI_NULL_INTEGER != psap->iMaxProcesses)
-    {
-        hr = ScaWriteConfigID(IIS_APPPOOL_MAXPROCESS);
-        ExitOnFailure(hr, "Failed to write max processes config ID");
-
-        hr = ScaWriteConfigInteger(psap->iMaxProcesses);
-        ExitOnFailure(hr, "failed to set web garden maximum worker processes");
-    }
-
-    hr = ScaWriteConfigID(IIS_APPPOOL_32BIT);
-    ExitOnFailure(hr, "Failed to write 32 bit app pool config ID");
-    hr = ScaWriteConfigInteger(psap->iCompAttributes & msidbComponentAttributes64bit ? 0 : 1);
-    ExitOnFailure(hr, "Failed to write 32 bit app pool config value");
-
-    //
-    // Set the AppPool Identity tab
-    //
-    if (psap->iAttributes & APATTR_APPPOOLIDENTITY)
-    {
-        dwIdentity = 4;
-    }
-    else if (psap->iAttributes & APATTR_NETSERVICE)
-    {
-        dwIdentity = 2;
-    }
-    else if (psap->iAttributes & APATTR_LOCSERVICE)
-    {
-        dwIdentity = 1;
-    }
-    else if (psap->iAttributes & APATTR_LOCSYSTEM)
-    {
-        dwIdentity = 0;
-    }
-    else if (psap->iAttributes & APATTR_OTHERUSER)
-    {
-        if (!*psap->suUser.wzDomain || 0 == _wcsicmp(psap->suUser.wzDomain, L"."))
-        {
-            if (0 == _wcsicmp(psap->suUser.wzName, L"NetworkService"))
-            {
-                dwIdentity = 2;
-            }
-            else if (0 == _wcsicmp(psap->suUser.wzName, L"LocalService"))
-            {
-                dwIdentity = 1;
-            }
-            else if (0 == _wcsicmp(psap->suUser.wzName, L"LocalSystem"))
-            {
-                dwIdentity = 0;
-            }
-            else
-            {
-                dwIdentity = 3;
-            }
-        }
-        else if (0 == _wcsicmp(psap->suUser.wzDomain, L"NT AUTHORITY"))
-        {
-            if (0 == _wcsicmp(psap->suUser.wzName, L"NETWORK SERVICE"))
-            {
-                dwIdentity = 2;
-            }
-            else if (0 == _wcsicmp(psap->suUser.wzName, L"SERVICE"))
-            {
-                dwIdentity = 1;
-            }
-            else if (0 == _wcsicmp(psap->suUser.wzName, L"SYSTEM"))
-            {
-                dwIdentity = 0;
-            }
-            else
-            {
-                dwIdentity = 3;
-            }
-        }
-        else
-        {
-            dwIdentity = 3;
-        }
-    }
-
-    if (-1 != dwIdentity)
-    {
-        hr = ScaWriteConfigID(IIS_APPPOOL_IDENTITY);
-        ExitOnFailure(hr, "failed to set app pool identity id");
-        hr = ScaWriteConfigInteger(dwIdentity);
-        ExitOnFailure(hr, "failed to set app pool identity");
-
-        if (3 == dwIdentity)
-        {
-            if (*psap->suUser.wzDomain)
-            {
-                hr = StrAllocFormatted(&pwzValue, L"%s\\%s", psap->suUser.wzDomain, psap->suUser.wzName);
-                ExitOnFailure(hr, "failed to format user name: %ls domain: %ls", psap->suUser.wzName, psap->suUser.wzDomain);
-            }
-            else
-            {
-                hr = StrAllocFormatted(&pwzValue, L"%s", psap->suUser.wzName);
-                ExitOnFailure(hr, "failed to format user name: %ls", psap->suUser.wzName);
-            }
-
-            hr = ScaWriteConfigID(IIS_APPPOOL_USER);
-            ExitOnFailure(hr, "failed to set app pool identity name id");
-            hr = ScaWriteConfigString(pwzValue);
-            ExitOnFailure(hr, "failed to set app pool identity name");
-
-            hr = ScaWriteConfigID(IIS_APPPOOL_PWD);
-            ExitOnFailure(hr, "failed to set app pool identity password id");
-            hr = ScaWriteConfigString(psap->suUser.wzPassword);
-            ExitOnFailure(hr, "failed to set app pool identity password");
-        }
-    }
-    
-    if (*psap->wzManagedPipelineMode)
-    {
-        hr = ScaWriteConfigID(IIS_APPPOOL_MANAGED_PIPELINE_MODE);
-        ExitOnFailure(hr, "failed to set app pool integrated mode");
-        hr = ScaWriteConfigString(psap->wzManagedPipelineMode);
-        ExitOnFailure(hr, "failed to set app pool managed pipeline mode value");
-    }
-
-    if (*psap->wzManagedRuntimeVersion)
-    {
-        hr = ScaWriteConfigID(IIS_APPPOOL_MANAGED_RUNTIME_VERSION);
-        ExitOnFailure(hr, "failed to set app pool managed runtime version mode");
-        hr = ScaWriteConfigString(psap->wzManagedRuntimeVersion);
-        ExitOnFailure(hr, "failed to set app pool managed runtime version value");
-    }
-
-    //
-    //The number of properties above is variable so we put an end tag in so the
-    //execute CA will know when to stop looking for AppPool properties
-    //
-    hr = ScaWriteConfigID(IIS_APPPOOL_END);
-    ExitOnFailure(hr, "failed to set app pool end of properties id");
-
-LExit:
-    ReleaseStr(pwzValue);
-
-    return hr;
-}
-
-
-HRESULT ScaRemoveAppPool7(
-    __in const SCA_APPPOOL* psap
-    )
-{
-    Assert(psap);
-
-    HRESULT hr = S_OK;
-
-    //do not delete the default App Pool
-    if (0 != _wcsicmp(psap->wzAppPool, L"DefaultAppPool"))
-    {
-        //delete the app pool
-        hr = ScaWriteConfigID(IIS_APPPOOL);
-        ExitOnFailure(hr, "failed to write AppPool key.");
-
-        hr = ScaWriteConfigID(IIS_DELETE);
-        ExitOnFailure(hr, "failed to write AppPool delete action.");
-
-        hr = ScaWriteConfigString(psap->wzName);
-        ExitOnFailure(hr, "failed to delete AppPool: %ls", psap->wzName);
-    }
-
-LExit:
-    return hr;
-}
diff --git a/src/ca/scaapppool7.h b/src/ca/scaapppool7.h
deleted file mode 100644
index 1f49d899..00000000
--- a/src/ca/scaapppool7.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-// 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.
-
-
-#include "scauser.h"
-
-// Identity
-#define APATTR_NETSERVICE 0x0001 // Network Service
-#define APATTR_LOCSERVICE 0x0002 // Local Service
-#define APATTR_LOCSYSTEM 0x0004 // Local System
-#define APATTR_OTHERUSER 0x0008 // Other User
-#define APATTR_APPPOOLIDENTITY 0x0010 // ApplicationPoolIdentity
-
-// prototypes
-HRESULT ScaFindAppPool7(
-    __in LPCWSTR wzAppPool,
-    __out_ecount(cchName) LPWSTR wzName,
-    __in DWORD cchName,
-    __in SCA_APPPOOL *psapList
-    );
-
-HRESULT ScaAppPoolInstall7(
-    __in SCA_APPPOOL* psapList
-    );
-
-HRESULT ScaAppPoolUninstall7(
-    __in SCA_APPPOOL* psapList
-    );
-
-HRESULT ScaWriteAppPool7(
-    __in const SCA_APPPOOL* psap
-    );
-
-HRESULT ScaRemoveAppPool7(
-    __in const SCA_APPPOOL* psap
-    );
diff --git a/src/ca/scacert.cpp b/src/ca/scacert.cpp
deleted file mode 100644
index 5eae905a..00000000
--- a/src/ca/scacert.cpp
+++ /dev/null
@@ -1,1482 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-// prototypes
-static HRESULT ConfigureCertificates(
-    __in SCA_ACTION saAction
-    );
-
-static LPCWSTR StoreMapping(
-    __in int iStore
-    );
-
-static HRESULT FindExistingCertificate(
-    __in LPCWSTR wzName,
-    __in DWORD dwStoreLocation,
-    __in LPCWSTR wzStore,
-    __out BYTE** prgbCertificate,
-    __out DWORD* pcbCertificate
-    );
-
-static HRESULT ResolveCertificate(
-    __in LPCWSTR wzId,
-    __in LPCWSTR wzName,
-    __in DWORD dwStoreLocation,
-    __in LPCWSTR wzStoreName,
-    __in DWORD dwAttributess,
-    __in LPCWSTR wzData,
-    __in LPCWSTR wzPFXPassword,
-    __out BYTE** ppbCertificate,
-    __out DWORD* pcbCertificate
-    );
-
-static HRESULT ReadCertificateFile(
-    __in LPCWSTR wzPath,
-    __out BYTE** prgbData,
-    __out DWORD* pcbData
-    );
-
-static HRESULT CertificateToHash(
-    __in BYTE* pbCertificate,
-    __in DWORD cbCertificate,
-    __in DWORD dwStoreLocation,
-    __in LPCWSTR wzPFXPassword,
-    __in BYTE rgbHash[],
-    __in DWORD cbHash
-    );
-
-/*
-HRESULT ScaGetCertificateByPath(LPCWSTR pwzName, BOOL fIsInstalling,
-                                BOOL fIsUninstalling, INT iStore,
-                                INT iStoreLocation, LPCWSTR wzSslCertificate,
-                                LPCWSTR wzPFXPassword, BSTR* pbstrCertificate,
-                                DWORD* pcbCertificate, BYTE* pbaHashBuffer);
-
-HRESULT ScaGetCertificateByRequest(LPCWSTR pwzName, BOOL fIsInstalling,
-                                   BOOL fIsUninstalling, INT iStore,
-                                   INT iStoreLocation, LPCWSTR wzDistinguishedName,
-                                   LPCWSTR wzCA, BSTR* pbstrCertificate,
-                                   DWORD* pcbCertificate, BYTE* pbaHashBuffer);
-
-HRESULT ScaSslNewCertificate(LPCWSTR pwzName, INT iStore,
-                            INT iStoreLocation, LPCWSTR wzComputerName,
-                            LPCWSTR wzDistinguishedName, LPCWSTR wzCertificateAuthorityOrig,
-                            BSTR* pbstrCertificate, DWORD* pcbCertificate,
-                            BYTE* pbaHashBuffer);
-
-HRESULT ScaSslExistingCertificateByName(LPCWSTR pwzName, INT iStore,
-                                       INT iStoreLocation, BSTR* pbstrCertificate,
-                                       DWORD* pcbCertificate, BYTE* pbaHashBuffer);
-
-HRESULT ScaSslExistingCertificateByBinaryData(INT iStore, INT iStoreLocation,
-                                             BYTE* pwzData, DWORD cchData);
-
-HRESULT CreateEnroll(ICEnroll2 **hEnroll, INT iStore,
-                     INT iStoreLocation);
-
-HRESULT RequestCertificate(LPCWSTR pwzName, INT iStore,
-                           INT iStoreLocation, LPCWSTR wzComputerName,
-                           LPCWSTR wzDistinguishedName, LPCWSTR wzCertificateAuthority,
-                           BSTR *pbstrCertificate);
-
-VOID ParseCertificateAuthority(__in LPCWSTR wzCertificateAuthorityOrig, __out LPWSTR *pwzBuffer,
-                               __out LPWSTR **hwzCAArray, __out int *piCAArray);
-*/
-
-
-LPCWSTR vcsCertQuery = L"SELECT `Certificate`, `Name`, `Component_`, `StoreLocation`, `StoreName`, `Attributes`, `Binary_`, `CertificatePath`, `PFXPassword` FROM `Certificate`";
-enum eCertQuery { cqCertificate = 1, cqName, cqComponent, cqStoreLocation, cqStoreName, cqAttributes, cqCertificateBinary, cqCertificatePath, cqPFXPassword };
-
-
-/********************************************************************
-InstallCertificates - CUSTOM ACTION ENTRY POINT for installing
-                      certificates
-
-********************************************************************/
-extern "C" UINT __stdcall InstallCertificates(
-    __in MSIHANDLE hInstall
-    )
-{
-    HRESULT hr = S_OK;
-    UINT er = ERROR_SUCCESS;
-
-    // initialize
-    hr = WcaInitialize(hInstall, "InstallCertificates");
-    ExitOnFailure(hr, "Failed to initialize");
-
-    hr = ConfigureCertificates(SCA_ACTION_INSTALL);
-
-LExit:
-    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
-    return WcaFinalize(er);
-}
-
-
-/********************************************************************
-UninstallCertificates - CUSTOM ACTION ENTRY POINT for uninstalling
-                        certificates
-
-********************************************************************/
-extern "C" UINT __stdcall UninstallCertificates(
-    __in MSIHANDLE hInstall
-    )
-{
-    HRESULT hr = S_OK;
-    UINT er = ERROR_SUCCESS;
-
-    // initialize
-    hr = WcaInitialize(hInstall, "UninstallCertificates");
-    ExitOnFailure(hr, "Failed to initialize");
-
-    hr = ConfigureCertificates(SCA_ACTION_UNINSTALL);
-
-LExit:
-    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
-    return WcaFinalize(er);
-}
-
-
-static HRESULT ConfigureCertificates(
-    __in SCA_ACTION saAction
-    )
-{
-    //AssertSz(FALSE, "debug ConfigureCertificates().");
-
-    HRESULT hr = S_OK;
-    DWORD er = ERROR_SUCCESS;
-
-    PMSIHANDLE hViewCertificate;
-    PMSIHANDLE hRecCertificate;
-    INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN;
-    INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN;
-
-    WCHAR* pwzId = NULL;
-    WCHAR* pwzName = NULL;
-    WCHAR* pwzComponent = NULL;
-    int iData = 0;
-    DWORD dwStoreLocation = 0;
-    LPWSTR pwzStoreName = 0;
-    DWORD dwAttributes = 0;
-    WCHAR* pwzData = NULL;
-    WCHAR* pwzPFXPassword = NULL;
-    WCHAR* pwzCaData = NULL;
-    WCHAR* pwzRollbackCaData = NULL;
-
-    BYTE* pbCertificate = NULL;
-    DWORD cbCertificate = 0;
-    DWORD_PTR cbPFXPassword = 0;
-
-    // Bail quickly if the Certificate table isn't around.
-    if (S_OK != WcaTableExists(L"Certificate"))
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ConfigureCertificates() - required table not present.");
-        ExitFunction1(hr = S_FALSE);
-    }
-
-    // Process the Certificate table.
-    hr = WcaOpenExecuteView(vcsCertQuery, &hViewCertificate);
-    ExitOnFailure(hr, "failed to open view on Certificate table");
-
-    while (SUCCEEDED(hr = WcaFetchRecord(hViewCertificate, &hRecCertificate)))
-    {
-        hr = WcaGetRecordString(hRecCertificate, cqCertificate, &pwzId); // the id is just useful to have up front
-        ExitOnFailure(hr, "failed to get Certificate.Certificate");
-
-        hr = WcaGetRecordString(hRecCertificate, cqComponent, &pwzComponent);
-        ExitOnFailure(hr, "failed to get Certificate.Component_");
-
-        er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzComponent, &isInstalled, &isAction);
-        hr = HRESULT_FROM_WIN32(er);
-        ExitOnFailure(hr, "failed to get state for component: %ls", pwzComponent);
-
-        if (!(WcaIsInstalling(isInstalled, isAction) && SCA_ACTION_INSTALL == saAction) &&
-            !(WcaIsUninstalling(isInstalled, isAction) && SCA_ACTION_UNINSTALL == saAction) &&
-            !(WcaIsReInstalling(isInstalled, isAction)))
-        {
-            WcaLog(LOGMSG_VERBOSE, "Skipping non-action certificate: %ls", pwzId);
-            continue;
-        }
-
-        // extract the rest of the data from the Certificate table
-        hr = WcaGetRecordFormattedString(hRecCertificate, cqName, &pwzName);
-        ExitOnFailure(hr, "failed to get Certificate.Name");
-
-        hr = WcaGetRecordInteger(hRecCertificate, cqStoreLocation, &iData);
-        ExitOnFailure(hr, "failed to get Certificate.StoreLocation");
-
-        switch (iData)
-        {
-        case SCA_CERTSYSTEMSTORE_CURRENTUSER:
-            dwStoreLocation = CERT_SYSTEM_STORE_CURRENT_USER;
-            break;
-        case SCA_CERTSYSTEMSTORE_LOCALMACHINE:
-            dwStoreLocation = CERT_SYSTEM_STORE_LOCAL_MACHINE;
-            break;
-        default:
-            hr = E_INVALIDARG;
-            ExitOnFailure(hr, "Invalid store location value: %d", iData);
-        }
-
-        hr = WcaGetRecordString(hRecCertificate, cqStoreName, &pwzStoreName);
-        ExitOnFailure(hr, "failed to get Certificate.StoreName");
-
-        hr = WcaGetRecordInteger(hRecCertificate, cqAttributes, reinterpret_cast<int*>(&dwAttributes));
-        ExitOnFailure(hr, "failed to get Certificate.Attributes");
-
-        if (dwAttributes & SCA_CERT_ATTRIBUTE_BINARYDATA)
-        {
-            hr = WcaGetRecordString(hRecCertificate, cqCertificateBinary, &pwzData);
-            ExitOnFailure(hr, "failed to get Certificate.Binary_");
-        }
-        else
-        {
-            hr = WcaGetRecordFormattedString(hRecCertificate, cqCertificatePath, &pwzData);
-            ExitOnFailure(hr, "failed to get Certificate.CertificatePath");
-        }
-
-        hr = WcaGetRecordFormattedString(hRecCertificate, cqPFXPassword, &pwzPFXPassword);
-        ExitOnFailure(hr, "failed to get Certificate.PFXPassword");
-
-        // Write the common data (for both install and uninstall) to the CustomActionData
-        // to pass data to the deferred CustomAction.
-        hr = StrAllocString(&pwzCaData, pwzName, 0);
-        ExitOnFailure(hr, "Failed to pass Certificate.Certificate to deferred CustomAction.");
-        hr = WcaWriteStringToCaData(pwzStoreName, &pwzCaData);
-        ExitOnFailure(hr, "Failed to pass Certificate.StoreName to deferred CustomAction.");
-        hr = WcaWriteIntegerToCaData(dwAttributes, &pwzCaData);
-        ExitOnFailure(hr, "Failed to pass Certificate.Attributes to deferred CustomAction.");
-
-        // Copy the rollback data from the deferred data because it's the same up to this point.
-        hr = StrAllocString(&pwzRollbackCaData, pwzCaData, 0);
-        ExitOnFailure(hr, "Failed to allocate string for rollback CustomAction.");
-
-        // Finally, schedule the correct deferred CustomAction to actually do work.
-        LPCWSTR wzAction = NULL;
-        LPCWSTR wzRollbackAction = NULL;
-        DWORD dwCost = 0;
-        if (SCA_ACTION_UNINSTALL == saAction)
-        {
-            // Find an existing certificate one (if there is one) to so we have it for rollback.
-            hr = FindExistingCertificate(pwzName, dwStoreLocation, pwzStoreName, &pbCertificate, &cbCertificate);
-            ExitOnFailure(hr, "Failed to search for existing certificate with friendly name: %ls", pwzName);
-
-            if (pbCertificate)
-            {
-                hr = WcaWriteStreamToCaData(pbCertificate, cbCertificate, &pwzRollbackCaData);
-                ExitOnFailure(hr, "Failed to pass Certificate.Data to rollback CustomAction.");
-
-                hr = WcaWriteStringToCaData(pwzPFXPassword, &pwzRollbackCaData);
-                ExitOnFailure(hr, "Failed to pass Certificate.PFXPassword to rollback CustomAction.");
-
-                hr = WcaWriteIntegerToCaData(dwAttributes, &pwzCaData);
-                ExitOnFailure(hr, "Failed to pass Certificate.Attributes to deferred CustomAction.");
-            }
-
-            // Pick the right action to run based on what store we're uninstalling from.
-            if (CERT_SYSTEM_STORE_LOCAL_MACHINE == dwStoreLocation)
-            {
-                wzAction = CUSTOM_ACTION_DECORATION(L"DeleteMachineCertificate");
-                if (pbCertificate)
-                {
-                    wzRollbackAction = L"RollbackDeleteMachineCertificate";
-                }
-            }
-            else
-            {
-                wzAction = CUSTOM_ACTION_DECORATION(L"DeleteUserCertificate");
-                if (pbCertificate)
-                {
-                    wzRollbackAction = L"RollbackDeleteUserCertificate";
-                }
-            }
-            dwCost = COST_CERT_DELETE;
-        }
-        else
-        {
-            // Actually get the certificate, resolve it to a blob, and get the blob's hash.
-            hr = ResolveCertificate(pwzId, pwzName, dwStoreLocation, pwzStoreName, dwAttributes, pwzData, pwzPFXPassword, &pbCertificate, &cbCertificate);
-            ExitOnFailure(hr, "Failed to resolve certificate: %ls", pwzId);
-
-            hr = WcaWriteStreamToCaData(pbCertificate, cbCertificate, &pwzCaData);
-            ExitOnFailure(hr, "Failed to pass Certificate.Data to deferred CustomAction.");
-
-            hr = WcaWriteStringToCaData(pwzPFXPassword, &pwzCaData);
-            ExitOnFailure(hr, "Failed to pass Certificate.PFXPassword to deferred CustomAction.");
-
-            // Pick the right action to run based on what store we're installing into.
-            if (CERT_SYSTEM_STORE_LOCAL_MACHINE == dwStoreLocation)
-            {
-                wzAction = CUSTOM_ACTION_DECORATION(L"AddMachineCertificate");
-                wzRollbackAction = CUSTOM_ACTION_DECORATION(L"RollbackAddMachineCertificate");
-            }
-            else
-            {
-                wzAction = CUSTOM_ACTION_DECORATION(L"AddUserCertificate");
-                wzRollbackAction = CUSTOM_ACTION_DECORATION(L"RollbackAddUserCertificate");
-            }
-            dwCost = COST_CERT_ADD;
-        }
-
-        if (wzRollbackAction)
-        {
-            hr = WcaDoDeferredAction(wzRollbackAction, pwzRollbackCaData, dwCost);
-            ExitOnFailure(hr, "Failed to schedule rollback certificate action '%ls' for: %ls", wzRollbackAction, pwzId);
-        }
-
-        hr = WcaDoDeferredAction(wzAction, pwzCaData, dwCost);
-        ExitOnFailure(hr, "Failed to schedule certificate action '%ls' for: %ls", wzAction, pwzId);
-
-        // Clean up for the next certificate.
-        ReleaseNullMem(pbCertificate);
-    }
-
-    if (E_NOMOREITEMS == hr)
-    {
-        hr = S_OK;
-    }
-
-LExit:
-    if (NULL != pwzPFXPassword && SUCCEEDED(StrSize(pwzPFXPassword, &cbPFXPassword)))
-    {
-        SecureZeroMemory(pwzPFXPassword, cbPFXPassword);
-    }
-
-    ReleaseMem(pbCertificate);
-    ReleaseStr(pwzCaData);
-    ReleaseStr(pwzPFXPassword);
-    ReleaseStr(pwzData);
-    ReleaseStr(pwzName);
-    ReleaseStr(pwzStoreName);
-    ReleaseStr(pwzComponent);
-    ReleaseStr(pwzId);
-
-    return hr;
-}
-
-
-static HRESULT ResolveCertificate(
-    __in LPCWSTR wzId,
-    __in LPCWSTR /*wzName*/,
-    __in DWORD dwStoreLocation,
-    __in LPCWSTR /*wzStoreName*/,
-    __in DWORD dwAttributes,
-    __in LPCWSTR wzData,
-    __in LPCWSTR wzPFXPassword,
-    __out BYTE** ppbCertificate,
-    __out DWORD* pcbCertificate
-    )
-{
-    HRESULT hr = S_OK;
-
-    LPWSTR pwzSql = NULL;
-    PMSIHANDLE hView;
-    PMSIHANDLE hRec;
-    MSIHANDLE hCertificateHashView = NULL;
-    MSIHANDLE hCertificateHashColumns = NULL;
-
-    BYTE rgbCertificateHash[CB_CERTIFICATE_HASH] = { 0 };
-    WCHAR wzEncodedCertificateHash[CB_CERTIFICATE_HASH * 2 + 1] = { 0 };
-
-    PMSIHANDLE hViewCertificateRequest, hRecCertificateRequest;
-
-    WCHAR* pwzDistinguishedName = NULL;
-    WCHAR* pwzCA = NULL;
-
-    BYTE* pbData = NULL;
-    DWORD cbData = 0;
-
-    if (dwAttributes & SCA_CERT_ATTRIBUTE_REQUEST)
-    {
-        hr = E_NOTIMPL;
-        ExitOnFailure(hr, "Installing certificates by requesting them from a certificate authority is not currently supported");
-        //if (dwAttributes & SCA_CERT_ATTRIBUTE_OVERWRITE)
-        //{
-        //    // try to overwrite with the patch to a cert file
-        //    WcaLog(LOGMSG_VERBOSE, "ConfigureCertificates - Overwrite with SSLCERTIFICATE");
-        //    hr = ScaGetCertificateByPath(pwzName, fIsInstalling, fIsUninstalling,
-        //        iStore, iStoreLocation, pwzData, wzPFXPassword, pbstrCertificate, pcbCertificate, pbaHashBuffer);
-        //}
-        //if (hr != S_OK)
-        //{
-        //    if (fIsUninstalling && !fIsInstalling)
-        //    {
-        //        // for uninstall, we just want to find the existing certificate
-        //        hr = ScaSslExistingCertificateByName(pwzName, iStore, iStoreLocation, pbstrCertificate, pcbCertificate, pbaHashBuffer);
-        //        ExitOnFailure(hr, "Failed Retrieving existing certificate during uninstall");
-        //        // ok if no existing cert
-        //        if (S_OK != hr)
-        //            hr = S_OK;
-        //    }
-        //    else
-        //    {
-        //        // still no certificate
-        //        // user has request this certificate, try to locate DistinguishedName and CA
-        //        hr = WcaTableExists(L"CertificateRequest");
-        //        ExitOnFailure(hr, "CertificateRequest is referenced but not found");
-        //        WcaLog(LOGMSG_VERBOSE, "ConfigureCertificates - CertificateRequest table present");
-        //        cchSQLView = 255 + lstrlenW(pwzName);
-        //        pwzSQLView = new WCHAR[cchSQLView];
-        //        if (pwzSQLView)
-        //        {
-        //            hr = ::StringCchPrintfW(pwzSQLView, cchSQLView, L"SELECT `DistinguishedName`, `CA` FROM `CertificateRequest` WHERE `Certificate_`=\'%s\'", pwzName);
-        //            ExitOnFailure(hr, "::StringCchPrintfW failed");
-        //            hr = WcaOpenExecuteView(pwzSQLView, &hViewCertificateRequest);
-        //            ExitOnFailure(hr, "failed to open view on CertificateRequest table");
-        //            hr = WcaFetchSingleRecord(hViewCertificateRequest, &hRecCertificateRequest);
-        //            ExitOnFailure(hr, "failed to retrieve request from CertificateRequest table");
-        //            hr = WcaGetRecordString(hRecCertificateRequest,  1, &pwzDistinguishedName);
-        //            ExitOnFailure(hr, "failed to get DistinguishedName");
-        //            hr = WcaGetRecordString(hRecCertificateRequest,  2, &pwzCA);
-        //            ExitOnFailure(hr, "failed to get CA");
-        //            if (pwzDistinguishedName && pwzCA && *pwzDistinguishedName && *pwzCA)
-        //            {
-        //                hr = ScaGetCertificateByRequest(pwzName, fIsInstalling, fIsUninstalling, iStore, iStoreLocation, pwzDistinguishedName, pwzCA, pbstrCertificate, pcbCertificate, pbaHashBuffer);
-        //            }
-        //            else
-        //            {
-        //                hr = E_FAIL;
-        //                ExitOnFailure(hr, "CertificateRequest entry is empty");
-        //            }
-        //        }
-        //        else
-        //        {
-        //            hr = E_FAIL;
-        //            ExitOnFailure(hr, "Out of memory");
-        //        }
-        //    }
-        //}
-    }
-    else if (dwAttributes & SCA_CERT_ATTRIBUTE_BINARYDATA)
-    {
-        // get the binary stream in Binary
-        hr = WcaTableExists(L"Binary");
-        if (S_OK != hr)
-        {
-            if (SUCCEEDED(hr))
-            {
-                hr = E_UNEXPECTED;
-            }
-            ExitOnFailure(hr, "Binary was referenced but there is no Binary table.");
-        }
-
-        hr = StrAllocFormatted(&pwzSql, L"SELECT `Data` FROM `Binary` WHERE `Name`=\'%s\'", wzData);
-        ExitOnFailure(hr, "Failed to allocate Binary table query.");
-
-        hr = WcaOpenExecuteView(pwzSql, &hView);
-        ExitOnFailure(hr, "Failed to open view on Binary table");
-
-        hr = WcaFetchSingleRecord(hView, &hRec);
-        ExitOnFailure(hr, "Failed to retrieve request from Binary table");
-
-        hr = WcaGetRecordStream(hRec, 1, &pbData, &cbData);
-        ExitOnFailure(hr, "Failed to ready Binary.Data for certificate.");
-    }
-    else if (dwAttributes == SCA_CERT_ATTRIBUTE_DEFAULT)
-    {
-        hr = ReadCertificateFile(wzData, &pbData, &cbData);
-        ExitOnFailure(hr, "Failed to read certificate from file path.");
-    }
-    else
-    {
-        hr = E_INVALIDARG;
-        ExitOnFailure(hr, "Invalid Certificate.Attributes.");
-    }
-
-    // If we have loaded a certificate, update the Certificate.Hash column.
-    if (pbData)
-    {
-        hr = CertificateToHash(pbData, cbData, dwStoreLocation, wzPFXPassword, rgbCertificateHash, countof(rgbCertificateHash));
-        ExitOnFailure(hr, "Failed to get SHA1 hash of certificate.");
-
-        hr = StrHexEncode(rgbCertificateHash, countof(rgbCertificateHash), wzEncodedCertificateHash, countof(wzEncodedCertificateHash));
-        ExitOnFailure(hr, "Failed to hex encode SHA1 hash of certificate.");
-
-        // Update the CertificateHash table.
-        hr = WcaAddTempRecord(&hCertificateHashView, &hCertificateHashColumns, L"CertificateHash", NULL, 0, 2, wzId, wzEncodedCertificateHash);
-        ExitOnFailure(hr, "Failed to add encoded has for certificate: %ls", wzId);
-    }
-
-    *ppbCertificate = pbData;
-    *pcbCertificate = cbData;
-    pbData = NULL;
-
-LExit:
-    if (hCertificateHashColumns)
-    {
-        ::MsiCloseHandle(hCertificateHashColumns);
-    }
-
-    if (hCertificateHashView)
-    {
-        ::MsiCloseHandle(hCertificateHashView);
-    }
-
-    ReleaseStr(pwzDistinguishedName);
-    ReleaseStr(pwzCA);
-    ReleaseMem(pbData);
-    ReleaseStr(pwzSql);
-
-    return hr;
-}
-
-
-static HRESULT ReadCertificateFile(
-    __in LPCWSTR wzPath,
-    __out BYTE** prgbData,
-    __out DWORD* pcbData
-    )
-{
-    HRESULT hr = S_OK;
-
-    PCCERT_CONTEXT pCertContext = NULL;
-    DWORD dwContentType;
-    BYTE* pbData = NULL;
-    DWORD cbData = 0;
-
-    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))
-    {
-        ExitOnFailure(hr, "Failed to read certificate from file: %ls", wzPath);
-    }
-
-    if (pCertContext)
-    {
-        cbData = pCertContext->cbCertEncoded;
-        pbData = static_cast<BYTE*>(MemAlloc(cbData, FALSE));
-        ExitOnNull(pbData, hr, E_OUTOFMEMORY, "Failed to allocate memory to read certificate from file: %ls", wzPath);
-
-        CopyMemory(pbData, pCertContext->pbCertEncoded, pCertContext->cbCertEncoded);
-    }
-    else
-    {
-        // If we have a PFX blob, get the first certificate out of the PFX and use that instead of the PFX.
-        if (dwContentType & CERT_QUERY_CONTENT_PFX)
-        {
-            hr = FileRead(&pbData, &cbData, wzPath);
-            ExitOnFailure(hr, "Failed to read PFX file: %ls", wzPath);
-        }
-        else
-        {
-            hr = E_UNEXPECTED;
-            ExitOnFailure(hr, "Unexpected certificate type read from disk.");
-        }
-    }
-
-    *pcbData = cbData;
-    *prgbData = pbData;
-    pbData = NULL;
-
-LExit:
-    ReleaseMem(pbData);
-    return hr;
-}
-
-
-static HRESULT CertificateToHash(
-    __in BYTE* pbCertificate,
-    __in DWORD cbCertificate,
-    __in DWORD dwStoreLocation,
-    __in LPCWSTR wzPFXPassword,
-    __in BYTE rgbHash[],
-    __in DWORD cbHash
-    )
-{
-    HRESULT hr = S_OK;
-
-    HCERTSTORE hPfxCertStore = NULL;
-    PCCERT_CONTEXT pCertContext = NULL;
-    PCCERT_CONTEXT pCertContextEnum = NULL;
-    CRYPT_DATA_BLOB blob = { 0 };
-    CRYPT_KEY_PROV_INFO* pPfxInfo = NULL;
-    DWORD dwKeyset = (CERT_SYSTEM_STORE_CURRENT_USER == dwStoreLocation) ? CRYPT_USER_KEYSET : CRYPT_MACHINE_KEYSET;
-    DWORD dwEncodingType;
-    DWORD dwContentType;
-    DWORD dwFormatType;
-
-    blob.pbData = pbCertificate;
-    blob.cbData = cbCertificate;
-
-    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))
-    {
-        ExitWithLastError(hr, "Failed to process certificate as a valid certificate.");
-    }
-
-    if (!pCertContext)
-    {
-        // If we have a PFX blob, get the first certificate out of the PFX and use that instead of the PFX.
-        if (dwContentType & CERT_QUERY_CONTENT_PFX)
-        {
-            // If we fail and our password is blank, also try passing in NULL for the password (according to the docs)
-            hPfxCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, wzPFXPassword, dwKeyset);
-            if (NULL == hPfxCertStore && !*wzPFXPassword)
-            {
-                hPfxCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, NULL, dwKeyset);
-            }
-            ExitOnNullWithLastError(hPfxCertStore, hr, "Failed to open PFX file.");
-
-            // Find the first cert with a private key, or just use the last one
-            for (pCertContextEnum = ::CertEnumCertificatesInStore(hPfxCertStore, pCertContextEnum);
-                 pCertContextEnum;
-                 pCertContextEnum = ::CertEnumCertificatesInStore(hPfxCertStore, pCertContextEnum))
-            {
-                pCertContext = pCertContextEnum;
-
-                if (pCertContext && CertHasPrivateKey(pCertContext, NULL))
-                {
-                    break;
-                }
-            }
-
-            ExitOnNullWithLastError(pCertContext, hr, "Failed to read first certificate out of PFX file.");
-
-            // Ignore failures, the worst that happens is some parts of the PFX get left behind.
-            CertReadProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, &pPfxInfo, NULL);
-        }
-        else
-        {
-            hr = E_UNEXPECTED;
-            ExitOnFailure(hr, "Unexpected certificate type processed.");
-        }
-    }
-
-    DWORD cb = cbHash;
-    if (!::CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, static_cast<LPVOID>(rgbHash), &cb))
-    {
-        ExitWithLastError(hr, "Failed to get certificate SHA1 hash property.");
-    }
-    AssertSz(cb == cbHash, "Did not correctly read certificate SHA1 hash.");
-
-LExit:
-    if (pCertContext)
-    {
-        ::CertFreeCertificateContext(pCertContext);
-    }
-
-    if (hPfxCertStore)
-    {
-        ::CertCloseStore(hPfxCertStore, 0);
-    }
-
-    if (pPfxInfo)
-    {
-        HCRYPTPROV hProvIgnored = NULL; // ignored on deletes.
-        ::CryptAcquireContextW(&hProvIgnored, pPfxInfo->pwszContainerName, pPfxInfo->pwszProvName, pPfxInfo->dwProvType, dwKeyset | CRYPT_DELETEKEYSET | CRYPT_SILENT);
-
-        MemFree(pPfxInfo);
-    }
-
-    return hr;
-}
-
-
-static HRESULT FindExistingCertificate(
-    __in LPCWSTR wzName,
-    __in DWORD dwStoreLocation,
-    __in LPCWSTR wzStore,
-    __out BYTE** prgbCertificate,
-    __out DWORD* pcbCertificate
-    )
-{
-    HRESULT hr = S_OK;
-    HCERTSTORE hCertStore = NULL;
-    PCCERT_CONTEXT pCertContext = NULL;
-    BYTE* pbCertificate = NULL;
-    DWORD cbCertificate = 0;
-
-    hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, dwStoreLocation | CERT_STORE_READONLY_FLAG, wzStore);
-    MessageExitOnNullWithLastError(hCertStore, hr, msierrCERTFailedOpen, "Failed to open certificate store.");
-
-    // Loop through the certificate, looking for certificates that match our friendly name.
-    pCertContext = CertFindCertificateInStore(hCertStore, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL);
-    while (pCertContext)
-    {
-        WCHAR wzFriendlyName[256] = { 0 };
-        DWORD cbFriendlyName = sizeof(wzFriendlyName);
-
-        if (::CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, reinterpret_cast<BYTE*>(wzFriendlyName), &cbFriendlyName) &&
-            CSTR_EQUAL == ::CompareStringW(LOCALE_SYSTEM_DEFAULT, 0, wzName, -1, wzFriendlyName, -1))
-        {
-            // If the certificate with matching friendly name is valid, let's use that.
-            long lVerify = ::CertVerifyTimeValidity(NULL, pCertContext->pCertInfo);
-            if (0 == lVerify)
-            {
-                cbCertificate = pCertContext->cbCertEncoded;
-                pbCertificate = static_cast<BYTE*>(MemAlloc(cbCertificate, FALSE));
-                ExitOnNull(pbCertificate, hr, E_OUTOFMEMORY, "Failed to allocate memory to copy out exist certificate.");
-
-                CopyMemory(pbCertificate, pCertContext->pbCertEncoded, cbCertificate);
-                break; // found a matching certificate, no more searching necessary
-            }
-        }
-
-         // Next certificate in the store.
-        PCCERT_CONTEXT pNext = ::CertFindCertificateInStore(hCertStore, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, pCertContext);
-        // old pCertContext is freed by CertFindCertificateInStore
-        pCertContext = pNext;
-    }
-
-    *prgbCertificate = pbCertificate;
-    *pcbCertificate = cbCertificate;
-    pbCertificate = NULL;
-
-LExit:
-    ReleaseMem(pbCertificate);
-
-    if (pCertContext)
-    {
-        ::CertFreeCertificateContext(pCertContext);
-    }
-
-    if (hCertStore)
-    {
-        ::CertCloseStore(hCertStore, 0);
-    }
-
-    return hr;
-}
-
-/*
-HRESULT CreateEnroll(ICEnroll2 **hEnroll, INT iStore, INT iStoreLocation)
-{
-    ICEnroll2 *pEnroll = NULL;
-    HRESULT hr = S_OK;
-    LONG lFlags;
-    DWORD dwFlags = iStoreLocation << CERT_SYSTEM_STORE_LOCATION_SHIFT;
-
-    // create IEntroll
-    hr = CoCreateInstance( CLSID_CEnroll, NULL, CLSCTX_INPROC_SERVER, IID_ICEnroll2, (void **)&pEnroll );
-    if (FAILED(hr))
-        return hr;
-
-    switch (iStore)
-    {
-    case SCA_CERT_STORENAME_MY:
-        pEnroll->get_MyStoreFlags(&lFlags);
-        lFlags &= ~CERT_SYSTEM_STORE_LOCATION_MASK;
-        lFlags |= dwFlags;
-        // following call will change Request store flags also
-        pEnroll->put_MyStoreFlags(lFlags);
-        break;
-    case SCA_CERT_STORENAME_CA:
-        pEnroll->get_CAStoreFlags(&lFlags);
-        lFlags &= ~CERT_SYSTEM_STORE_LOCATION_MASK;
-        lFlags |= dwFlags;
-        // following call will change Request store flags also
-        pEnroll->put_CAStoreFlags(lFlags);
-        break;
-    case SCA_CERT_STORENAME_REQUEST:
-        pEnroll->get_RequestStoreFlags(&lFlags);
-        lFlags &= ~CERT_SYSTEM_STORE_LOCATION_MASK;
-        lFlags |= dwFlags;
-        // following call will change Request store flags also
-        pEnroll->put_RequestStoreFlags(lFlags);
-        break;
-    case SCA_CERT_STORENAME_ROOT:
-        pEnroll->get_RootStoreFlags(&lFlags);
-        lFlags &= ~CERT_SYSTEM_STORE_LOCATION_MASK;
-        lFlags |= dwFlags;
-        // following call will change Request store flags also
-        pEnroll->put_RootStoreFlags(lFlags);
-        break;
-    default:
-        hr = E_FAIL;
-        return hr;
-    }
-
-    pEnroll->get_GenKeyFlags(&lFlags);
-    lFlags |= CRYPT_EXPORTABLE;
-    pEnroll->put_GenKeyFlags(lFlags);
-
-    pEnroll->put_KeySpec(AT_KEYEXCHANGE);
-    pEnroll->put_ProviderType(PROV_RSA_SCHANNEL);
-    pEnroll->put_DeleteRequestCert(TRUE);
-
-    *hEnroll = pEnroll;
-    return hr;
-}
-
-
-HRESULT RequestCertificate(LPCWSTR pwzName, INT iStore, INT iStoreLocation,
-                           LPCWSTR wzComputerName, LPCWSTR wzDistinguishedName, LPCWSTR wzCertificateAuthority,
-                           BSTR *pbstrCertificate)
-{
-    if (pbstrCertificate == NULL)
-        return E_INVALIDARG;
-
-    HRESULT hr;
-    ICEnroll2 *pEnroll = NULL;
-    ICertRequest *pCertRequest = NULL;
-    BSTR bstrRequest = NULL;
-    LONG nDisposition;
-
-    BSTR bstrCertificateUsage = NULL;
-    BSTR bstrCertificateAttributes = NULL;
-    BSTR bstrCertificateAuthority = NULL;
-
-    // equivalent to: sprintf(bstrDistinguishedName, L"%s,CN=%s", wzDistinguishedName, wzComputerName);
-    DWORD cchComputerName = lstrlenW(wzComputerName);
-    DWORD cchDistinguishedName = lstrlenW(wzDistinguishedName);
-    CONST DWORD cchbstrDistinguishedName = 5 + cchComputerName + cchDistinguishedName;
-    BSTR bstrDistinguishedName = SysAllocStringLen(NULL, cchbstrDistinguishedName);
-    ExitOnNull(bstrDistinguishedName, hr, E_OUTOFMEMORY, "Failed to allocate space for distinguished name.");
-    ::StringCchCopyW((WCHAR*) bstrDistinguishedName, cchbstrDistinguishedName, wzDistinguishedName);
-    ::StringCchCatW((WCHAR*) bstrDistinguishedName, cchbstrDistinguishedName, L",CN=");
-    ::StringCchCatW((WCHAR*) bstrDistinguishedName, cchbstrDistinguishedName, wzComputerName);
-
-    bstrCertificateUsage = SysAllocString(WIDE(szOID_PKIX_KP_SERVER_AUTH));
-    ExitOnNull(bstrCertificateUsage, hr, E_OUTOFMEMORY, "Failed to allocate space for Certificate Usage.");
-    bstrCertificateAttributes = SysAllocString(L"CertificateTemplate:WebServer");
-    bstrCertificateAuthority = SysAllocString(wzCertificateAuthority);
-    ExitOnNull(bstrCertificateAuthority, hr, E_OUTOFMEMORY, "Failed to allocate space for Certificate Authority.");
-
-    hr = CreateEnroll(&pEnroll, iStore, iStoreLocation);
-    ExitOnFailure(hr, "failed CoCreateInstance IEnroll");
-
-    hr = pEnroll->createPKCS10(bstrDistinguishedName, bstrCertificateUsage, &bstrRequest);
-    ExitOnFailure(hr, "failed createPKCS10");
-
-    hr = CoCreateInstance(CLSID_CCertRequest, NULL, CLSCTX_INPROC_SERVER, IID_ICertRequest, (void **)&pCertRequest);
-    ExitOnFailure(hr, "failed CoCreateInstance ICertRequest");
-
-    hr = pCertRequest->Submit(CR_IN_BASE64 | CR_IN_PKCS10, bstrRequest, bstrCertificateAttributes, bstrCertificateAuthority, &nDisposition);
-    ExitOnFailure(hr, "failed ICertRequest.Submit");
-
-    hr = (nDisposition == CR_DISP_ISSUED) ? S_OK : E_FAIL;
-    ExitOnFailure(hr, "failed CR_DISP_ISSUED");
-
-    hr = pCertRequest->GetCertificate(CR_OUT_BASE64, pbstrCertificate);
-    ExitOnFailure(hr, "failed ICertRequest.GetCertificate");
-
-    // save the certificate in place, cannot be passed to a deferred custom action
-    hr = pEnroll->acceptPKCS7(*pbstrCertificate);
-    ExitOnFailure(hr, "failed accept certificate into MY store");
-
-LExit:
-    ReleaseObject(pCertRequest);
-    ReleaseBSTR(bstrRequest);
-    ReleaseObject(pEnroll);
-    ReleaseBSTR(bstrCertificateAuthority);
-    ReleaseBSTR(bstrCertificateAttributes);
-    ReleaseBSTR(bstrDistinguishedName);
-
-    return hr;
-}
-
-
-VOID ParseCertificateAuthority(__in LPCWSTR wzCertificateAuthorityOrig, __out LPWSTR *pwzBuffer, __out LPWSTR **hwzCAArray, __out int *piCAArray)
-{
-    // @asAuthorities = split /;/, $sAuthority;
-    CONST WCHAR wchDelimiter = L';';
-
-    // copy constant into a buffer
-    Assert(wzCertificateAuthorityOrig);
-
-    INT cchCA = lstrlenW(wzCertificateAuthorityOrig) + 1;
-    WCHAR* wzBuffer = new WCHAR[cchCA];
-    if (!wzBuffer)
-        return;
-
-    ::StringCchCopyW(wzBuffer, cchCA, wzCertificateAuthorityOrig);
-
-    // determine the number of strings in the field
-    int iCAArray = 1;
-    int i;
-    for (i = 0; i < cchCA; ++i)
-    {
-        if (wzBuffer[i] == wchDelimiter)
-            ++iCAArray;
-    }
-    LPWSTR *pwzCAArray = (LPWSTR*) new BYTE[iCAArray * sizeof(LPWSTR)];
-    if (!pwzCAArray)
-    {
-        return;
-    }
-
-    pwzCAArray[0] = wzBuffer;
-    iCAArray = 0;
-    for (i = 0; i < cchCA; ++i)
-    {
-        if (wzBuffer[i] != wchDelimiter)
-            continue;
-        wzBuffer[i] = 0; // convert buffer into MULTISZ
-        pwzCAArray[iCAArray] = &wzBuffer[i+1];
-        ++iCAArray;
-    }
-
-    *pwzBuffer = wzBuffer;
-    *hwzCAArray = pwzCAArray;
-    *piCAArray = iCAArray;
-}
-
-
-HRESULT ScaSslExistingCertificateByBinaryData(INT iStore, INT iStoreLocation, BYTE* pwzData, DWORD cchData)
-{
-    HRESULT hr = S_FALSE;
-    HCERTSTORE hCertStore = NULL;
-    PCCERT_CONTEXT pCertCtx = NULL, pCertCtxExisting = NULL;
-    DWORD dwFlags = 0;
-    LPCWSTR wzStore = StoreMapping(iStore);
-    CERT_BLOB blob;
-
-    dwFlags = iStoreLocation << CERT_SYSTEM_STORE_LOCATION_SHIFT;
-    hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, dwFlags, wzStore);
-    MessageExitOnNullWithLastError(hCertStore, hr, msierrCERTFailedOpen, "failed to open certificate store, OK on uninstall");
-
-    blob.pbData = pwzData;
-    blob.cbData = cchData;
-
-    if (!::CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL,
-        0, NULL, NULL, NULL, NULL, NULL, (LPCVOID*)&pCertCtx))
-        ExitOnLastError(hr, "failed to parse the certificate blob, OK on uninstall");
-
-    pCertCtxExisting = CertFindCertificateInStore(
-        hCertStore,
-        PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
-        0,
-        CERT_FIND_EXISTING,
-        pCertCtx,
-        NULL);
-
-    if (pCertCtxExisting)
-    {
-        hr = S_OK;
-    }
-
-LExit:
-    if (pCertCtx)
-    {
-        CertFreeCertificateContext(pCertCtx);
-        pCertCtx = NULL;
-    }
-    if (pCertCtxExisting)
-    {
-        CertFreeCertificateContext(pCertCtxExisting);
-        pCertCtxExisting = NULL;
-    }
-    if (hCertStore)
-    {
-        CertCloseStore(hCertStore, 0);
-        hCertStore = NULL;
-    }
-
-    return hr;
-}
-
-
-HRESULT ScaSslExistingCertificateByName(LPCWSTR pwzName, INT iStore, INT iStoreLocation,
-                                       BSTR* pbstrCertificate, DWORD* pcbCertificate, BYTE* pbaHashBuffer)
-{
-    HRESULT hr = S_FALSE;
-    HCERTSTORE hSystemStore = NULL;
-    PCCERT_CONTEXT pTargetCert = NULL;
-    WCHAR wzFriendlyName[MAX_PATH] = {0};
-    DWORD dwFriendlyNameLen = sizeof(wzFriendlyName);
-
-    // Call CertOpenStore to open the CA store.
-    hSystemStore = CertOpenStore(
-        CERT_STORE_PROV_SYSTEM_REGISTRY,
-        0,
-        NULL,
-        (iStoreLocation << CERT_SYSTEM_STORE_LOCATION_SHIFT) | CERT_STORE_OPEN_EXISTING_FLAG,
-        StoreMapping(iStore));
-    if (hSystemStore == NULL)
-        ExitFunction();
-
-    // Get a particular certificate using CertFindCertificateInStore.
-    pTargetCert = CertFindCertificateInStore(
-        hSystemStore,
-        PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
-        0,
-        CERT_FIND_ANY,
-        NULL,
-        NULL);
-    while (pTargetCert != NULL)
-    {
-        if ((CertGetCertificateContextProperty(pTargetCert, CERT_FRIENDLY_NAME_PROP_ID,
-            (BYTE*)wzFriendlyName, &dwFriendlyNameLen)) &&
-            lstrcmpW(wzFriendlyName, pwzName) == 0)
-        {
-            // pTargetCert is a pointer to the desired certificate.
-            // Check the certificate's validity.
-            switch (CertVerifyTimeValidity(
-                NULL,
-                pTargetCert->pCertInfo))
-            {
-            case 1:
-                // Certificate is expired
-                WcaLog(LOGMSG_STANDARD, "The SSL certificate has expired");
-                // always remove it
-                {
-                    PCCERT_CONTEXT pDupCertContext = CertDuplicateCertificateContext(pTargetCert);
-                    if (pDupCertContext && CertDeleteCertificateFromStore(pDupCertContext))
-                    {
-                        WcaLog(LOGMSG_STANDARD, "A SSL certificate has removed");
-                    }
-                }
-                break;
-            case 0:
-                // Certificate is valid
-                WcaLog(LOGMSG_STANDARD, "The SSL certificate is valid");
-                hr = S_OK;
-                if (pbaHashBuffer)
-                {
-                    // if the certificate already exists and is valid, use that one
-                    DWORD dwHashSize = CB_CERTIFICATE_HASH;
-                    hr = CertGetCertificateContextProperty(pTargetCert, CERT_SHA1_HASH_PROP_ID, (VOID*)pbaHashBuffer, &dwHashSize)
-                        ? S_OK : E_FAIL;
-                    ExitOnFailure(hr, "failed CertGetCertificateContextProperty CERT_SHA1_HASH_PROP_ID");
-                    Assert(pbstrCertificate);
-                    Assert(pcbCertificate);
-                    ReleaseBSTR(*pbstrCertificate);
-
-                    *pbstrCertificate = SysAllocStringByteLen((LPCSTR)(pTargetCert->pbCertEncoded), pTargetCert->cbCertEncoded);
-                    *pcbCertificate = pTargetCert->cbCertEncoded;
-                }
-                ExitFunction();
-                break;
-            default:
-                // Certificate not valid yet, ignore it
-                WcaLog(LOGMSG_STANDARD, "The SSL certificate is not valid");
-                break;
-            }
-        }
-        pTargetCert = CertFindCertificateInStore(
-            hSystemStore,
-            PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
-            0,
-            CERT_FIND_ANY,
-            NULL,
-            pTargetCert);
-        wzFriendlyName[0] = 0;
-        dwFriendlyNameLen = sizeof(wzFriendlyName);
-    }
-
-LExit:
-    // Clean up memory and quit.
-    if (pTargetCert)
-    {
-        CertFreeCertificateContext(pTargetCert);
-        pTargetCert = NULL;
-    }
-    if (hSystemStore)
-    {
-        CertCloseStore(hSystemStore, CERT_CLOSE_STORE_CHECK_FLAG);
-        hSystemStore = NULL;
-    }
-
-    return hr;
-}
-
-
-HRESULT ScaSslNewCertificate(LPCWSTR pwzName, INT iStore, INT iStoreLocation, LPCWSTR wzComputerName, LPCWSTR wzDistinguishedName, LPCWSTR wzCertificateAuthorityOrig,
-                            BSTR* pbstrCertificate, DWORD* pcbCertificate, BYTE* pbaHashBuffer)
-{
-
-    if (pbstrCertificate == NULL)
-        return E_INVALIDARG;
-
-    HRESULT hr = S_OK;
-    LPWSTR wzCABuffer = NULL;
-    LPWSTR *wzCAArray = NULL;
-    int iCAArray = 0;
-
-    // otherwise call the CA for one
-    ParseCertificateAuthority(wzCertificateAuthorityOrig, &wzCABuffer, &wzCAArray, &iCAArray);
-
-    // try each authority three times
-    for (int i = 0; i < 3 * iCAArray; ++i)
-    {
-        LPCWSTR wzCA = wzCAArray[i % iCAArray];
-        if (NULL == wzCA || NULL == wzCA[0]) continue;
-        WcaLog(LOGMSG_STANDARD, "Requesting SSL certificate from %ls", wzCA);
-        hr = RequestCertificate(pwzName, iStore, iStoreLocation, wzComputerName, wzDistinguishedName, wzCA, pbstrCertificate);
-        if (hr == S_OK && pbstrCertificate)
-        {
-            // set the friendly name
-            CRYPT_HASH_BLOB hblob;
-            CERT_BLOB blob;
-            HCERTSTORE hCertStore = NULL;
-            PCCERT_CONTEXT pCertCtxExisting = NULL;
-
-            blob.pbData = (BYTE*)pwzName;
-            blob.cbData = (lstrlenW(pwzName) + 1) * sizeof(pwzName[0]); // including terminating null
-
-            *pcbCertificate = SysStringByteLen(*pbstrCertificate);
-            hr = CertificateToHash(*pbstrCertificate, pbaHashBuffer);
-            ExitOnFailure(hr, "failed to CertificateToHash for an existing certificate");
-
-            hblob.pbData = pbaHashBuffer;
-            hblob.cbData = CB_CERTIFICATE_HASH;
-
-            hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, (iStoreLocation << CERT_SYSTEM_STORE_LOCATION_SHIFT), StoreMapping(iStore));
-            MessageExitOnNullWithLastError(hCertStore, hr, msierrCERTFailedOpen, "failed to open certificate store");
-
-            pCertCtxExisting = CertFindCertificateInStore(
-                hCertStore,
-                PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
-                0,
-                CERT_FIND_HASH,
-                &hblob,
-                NULL);
-
-            if (pCertCtxExisting)
-            {
-                CertSetCertificateContextProperty(
-                    pCertCtxExisting,
-                    CERT_FRIENDLY_NAME_PROP_ID,
-                    0,
-                    &blob);
-            }
-
-            if (pCertCtxExisting)
-            {
-                CertFreeCertificateContext(pCertCtxExisting);
-                pCertCtxExisting = NULL;
-            }
-            if (hCertStore)
-            {
-                CertCloseStore(hCertStore, 0);
-                hCertStore = NULL;
-            }
-            ExitFunction();
-        }
-        if (pbstrCertificate && *pbstrCertificate)
-        {
-            SysFreeString(*pbstrCertificate);
-            pbstrCertificate = NULL;
-        }
-    }
-    hr = E_FAIL;
-    ExitOnFailure(hr, "failed to RequestCertificate");
-
-LExit:
-    if (wzCABuffer)
-    {
-        delete wzCABuffer;
-    }
-    if (wzCAArray)
-    {
-        delete wzCAArray;
-    }
-
-    return hr;
-}
-
-
-HRESULT ScaGetCertificateByRequest(LPCWSTR pwzName, BOOL fIsInstalling, BOOL fIsUninstalling,
-                                   INT iStore, INT iStoreLocation,
-                                   LPCWSTR wzDistinguishedName, LPCWSTR wzCA,
-                                   BSTR* pbstrCertificate, DWORD* pcbCertificate, BYTE* pbaHashBuffer)
-{
-    HRESULT hr = S_OK;
-    WCHAR wzComputerName[MAX_COMPUTER_NAME] = {0};
-    WCHAR* pwzData = NULL;
-    DWORD cchData = 0;
-
-    // override %COMPUTERNAME% with DOMAINNAME property
-    hr = WcaGetProperty( L"DOMAINNAME", &pwzData);
-    ExitOnFailure(hr, "Failed to get Property DOMAINNAME");
-    if (*pwzData)
-    {
-        // if DOMAINNAME is set, use it
-        ::StringCchCopyW(wzComputerName, MAX_COMPUTER_NAME, pwzData);
-    }
-    else
-    {
-        // otherwise get the intranet name given by %COMPUTERNAME%
-        GetEnvironmentVariableW(L"COMPUTERNAME", wzComputerName, MAX_COMPUTER_NAME);
-    }
-
-    hr = ScaSslExistingCertificateByName(pwzName, iStore, iStoreLocation, pbstrCertificate, pcbCertificate, pbaHashBuffer);
-    ExitOnFailure(hr, "Failed ScaSslExistingCertificateByName");
-    if (S_OK != hr)
-    {
-        if (!fIsUninstalling && fIsInstalling)
-        {
-            // if no existing cert and not on uninstall, hit the authority
-            WcaLog(LOGMSG_STANDARD, "Adding certificate: requested, %ls", wzDistinguishedName);
-            hr = ScaSslNewCertificate(pwzName, iStore, iStoreLocation, wzComputerName, wzDistinguishedName, wzCA,
-                pbstrCertificate, pcbCertificate, pbaHashBuffer);
-            ExitOnFailure(hr, "Failed ScaSslNewCertificate");
-        }
-        else
-        {
-            // if no existing cert and uninstall
-            hr = S_OK;
-        }
-    }
-
-LExit:
-    ReleaseStr(pwzData);
-
-    return hr;
-}
-
-
-HRESULT ScaInstallCertificateByContext(LPCWSTR pwzName, INT iStore, INT iStoreLocation,
-                                       PCCERT_CONTEXT pCertContext)
-{
-    HRESULT hr = S_OK;
-    HCERTSTORE hCertStore = NULL;
-    DWORD dwFlags = iStoreLocation << CERT_SYSTEM_STORE_LOCATION_SHIFT;
-    CERT_BLOB blob;
-
-    hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, dwFlags, StoreMapping(iStore));
-    if (hCertStore == NULL)
-        MessageExitOnLastError(hr, msierrCERTFailedOpen, "failed to open certificate store");
-
-    blob.pbData = (BYTE*)pwzName;
-    blob.cbData = (lstrlenW(pwzName) + 1) * sizeof(pwzName[0]); // including terminating null
-    CertSetCertificateContextProperty(
-        pCertContext,
-        CERT_FRIENDLY_NAME_PROP_ID,
-        0,
-        &blob);
-
-    if (!CertAddCertificateContextToStore(
-        hCertStore,
-        pCertContext,
-        CERT_STORE_ADD_REPLACE_EXISTING,
-        NULL))
-    {
-        hr = E_FAIL;
-        MessageExitOnLastError(hr, msierrCERTFailedAdd, "failed to add certificate to the store");
-    }
-
-LExit:
-    if (hCertStore)
-    {
-        CertCloseStore(hCertStore, 0);
-        hCertStore = NULL;
-    }
-
-    return hr;
-}
-
-
-HRESULT ScaGetCertificateByPath(LPCWSTR pwzName, BOOL fIsInstalling, BOOL fIsUninstalling,
-                                INT iStore, INT iStoreLocation, LPCWSTR wzSslCertificate, LPCWSTR wzPFXPassword,
-                                BSTR* pbstrCertificate, DWORD* pcbCertificate, BYTE* pbaHashBuffer)
-{
-    Assert(wzSslCertificate);
-    HRESULT hr = S_OK;
-    PCCERT_CONTEXT pCertContext = NULL;
-    DWORD dwEncodingType = 0;
-    DWORD dwContentType = 0;
-    DWORD dwFormatType = 0;
-    DWORD dwHashSize = CB_CERTIFICATE_HASH;
-    HANDLE hPfxFile = INVALID_HANDLE_VALUE;
-    CRYPT_DATA_BLOB blob;
-
-    blob.pbData = NULL;
-    blob.cbData = 0;
-
-    if (wzSslCertificate && wzSslCertificate[0] != 0)
-    {
-        if (!::CryptQueryObject(CERT_QUERY_OBJECT_FILE, (LPVOID)wzSslCertificate, CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL,
-            0, &dwEncodingType, &dwContentType, &dwFormatType, NULL, NULL, (LPCVOID*)&pCertContext))
-            hr = fIsUninstalling ? S_FALSE : HRESULT_FROM_WIN32(::GetLastError());  // don't fail on uninstall
-        ExitOnFailure(hr, "failed CryptQueryObject");
-    }
-    else
-    {
-        hr = S_FALSE;
-        ExitFunction();
-    }
-
-    if (!pCertContext)
-    {
-        // this is a pfx?
-        // make sure to exit this block of code properly for clean up blob.pbData
-        if (dwContentType & CERT_QUERY_CONTENT_PFX)
-        {
-            DWORD iSize = 0, iReadSize = 0;
-            HCERTSTORE hPfxCertStore = NULL;
-
-            hPfxFile = ::CreateFileW(wzSslCertificate, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-            hr = (hPfxFile != INVALID_HANDLE_VALUE) ? S_OK : E_FAIL;
-            ExitOnFailure(hr, "failed CryptQueryObject, file handle is null");
-            iSize = ::GetFileSize(hPfxFile, NULL);
-            hr = (iSize > 0) ? S_OK : E_FAIL;
-            ExitOnFailure(hr, "failed CryptQueryObject, file size is 0");
-            blob.pbData = new BYTE[iSize];
-            blob.cbData = iSize;
-            hr = (blob.pbData) ? S_OK : E_FAIL;
-            ExitOnFailure(hr, "out of memory for blob");
-
-            if (::ReadFile(hPfxFile, (LPVOID)blob.pbData, iSize, &iReadSize, NULL))
-            {
-                hPfxCertStore = PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, wzPFXPassword,
-                    (iStoreLocation == SCA_CERTSYSTEMSTORE_CURRENTUSER) ? CRYPT_USER_KEYSET : CRYPT_MACHINE_KEYSET);
-                if (hPfxCertStore)
-                {
-                    pCertContext = CertEnumCertificatesInStore(hPfxCertStore, NULL);
-                    // work only with the first certificate in pfx
-                    if (pCertContext)
-                    {
-                        hr = CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, (VOID*)pbaHashBuffer, &dwHashSize)
-                            ? S_OK : E_FAIL;
-                        ExitOnFailure(hr, "failed CertGetCertificateContextProperty CERT_SHA1_HASH_PROP_ID");
-                        ReleaseBSTR(*pbstrCertificate);
-
-                        *pbstrCertificate = SysAllocStringByteLen((LPCSTR)(pCertContext->pbCertEncoded), pCertContext->cbCertEncoded);
-                        *pcbCertificate = pCertContext->cbCertEncoded;
-                        if (fIsInstalling)
-                        {
-                            // install the certificate, cannot defer because the data required cannot be passed
-                            hr = ScaInstallCertificateByContext(pwzName, iStore, iStoreLocation, pCertContext);
-                        }
-                    }
-                    else
-                        hr = E_FAIL;
-                }
-                else
-                    hr = E_FAIL;
-            }
-            else
-                hr = E_FAIL;
-        }
-        else
-        {
-            ExitOnFailure(hr = E_FAIL, "failed CryptQueryObject, unknown data");
-        }
-    }
-    else
-    {
-        // return cert and its hash
-        hr = CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, (VOID*)pbaHashBuffer, &dwHashSize)
-            ? S_OK : E_FAIL;
-        ExitOnFailure(hr, "failed CertGetCertificateContextProperty CERT_SHA1_HASH_PROP_ID");
-        ReleaseBSTR(*pbstrCertificate);
-
-        *pbstrCertificate = SysAllocStringByteLen((LPCSTR)(pCertContext->pbCertEncoded), pCertContext->cbCertEncoded);
-        *pcbCertificate = pCertContext->cbCertEncoded;
-        if (fIsInstalling)
-        {
-            // install the certificate, cannot defer because the data required cannot be passed
-            hr = ScaInstallCertificateByContext(pwzName, iStore, iStoreLocation, pCertContext);
-        }
-    }
-
-LExit:
-    if (pCertContext)
-    {
-        CertFreeCertificateContext(pCertContext);
-        pCertContext = NULL;
-    }
-    if (hPfxFile != INVALID_HANDLE_VALUE)
-    {
-        CloseHandle(hPfxFile);
-        hPfxFile = INVALID_HANDLE_VALUE;
-    }
-    if (blob.pbData)
-    {
-        delete [] blob.pbData;
-        blob.pbData = NULL;
-        blob.cbData = 0;
-    }
-
-    return hr;
-}
-
-
-HRESULT ScaInstallCertificateByBinaryData(BOOL fAddCert, INT iStore, INT iStoreLocation, LPCWSTR wzName, BYTE* pwzData, DWORD cchData,
-                                          LPCWSTR wzPFXPassword)
-{
-    Assert(wzName);
-    Assert(pwzData);
-    Assert(cchData);
-    HRESULT hr = S_OK;
-    HCERTSTORE hCertStore = NULL, hPfxCertStore = NULL;
-    PCCERT_CONTEXT pCertCtx = NULL, pCertCtxExisting = NULL;
-    DWORD dwFlags, dwEncodingType, dwContentType, dwFormatType;
-    CERT_BLOB blob;
-    LPCWSTR wzStore = StoreMapping(iStore);
-
-    dwFlags = iStoreLocation << CERT_SYSTEM_STORE_LOCATION_SHIFT;
-    hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, dwFlags, wzStore);
-    MessageExitOnNullWithLastError(hCertStore, hr, msierrCERTFailedOpen, "failed to open certificate store");
-
-    blob.pbData = pwzData;
-    blob.cbData = cchData;
-
-    if (!::CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL,
-        0, &dwEncodingType, &dwContentType, &dwFormatType, NULL, NULL, (LPCVOID*)&pCertCtx))
-        ExitOnLastError(hr, "failed to parse the certificate blob");
-    ExitOnNull(pCertCtx, hr, E_UNEXPECTED, "failed to parse the certificate blob");
-
-    blob.pbData = (BYTE*)wzName;
-    blob.cbData = (lstrlenW(wzName) + 1) * sizeof(wzName[0]); // including terminating null
-
-    CertSetCertificateContextProperty(
-        pCertCtx,
-        CERT_FRIENDLY_NAME_PROP_ID,
-        0,
-        &blob);
-
-    if (fAddCert)
-    {
-        // Add
-        WcaLog(LOGMSG_STANDARD, "Adding certificate: binary name, %ls", wzName);
-        if (!CertAddCertificateContextToStore(
-            hCertStore,
-            pCertCtx,
-            CERT_STORE_ADD_REPLACE_EXISTING,
-            NULL))
-        {
-            hr = E_FAIL;
-            MessageExitOnLastError(hr, msierrCERTFailedAdd, "failed to add certificate to the store");
-        }
-    }
-    else
-    {
-        // Delete
-        WcaLog(LOGMSG_STANDARD, "Deleting certificate provided: binary name, %ls", wzName);
-        pCertCtxExisting = CertFindCertificateInStore(
-            hCertStore,
-            PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
-            0,
-            CERT_FIND_EXISTING,
-            pCertCtx,
-            NULL);
-
-        if (pCertCtxExisting)
-        {
-            if (!CertDeleteCertificateFromStore(pCertCtxExisting))
-            {
-                ExitOnLastError(hr, "failed to delete certificate");
-            }
-            else
-            {
-                pCertCtxExisting = NULL;
-            }
-        }
-    }
-
-LExit:
-    if (pCertCtx)
-    {
-        CertFreeCertificateContext(pCertCtx);
-        pCertCtx = NULL;
-    }
-    if (pCertCtxExisting)
-    {
-        CertFreeCertificateContext(pCertCtxExisting);
-        pCertCtxExisting = NULL;
-    }
-    // order is important for store
-    if (hCertStore)
-    {
-        CertCloseStore(hCertStore, 0);
-        hCertStore = NULL;
-    }
-    if (hPfxCertStore)
-    {
-        CertCloseStore(hPfxCertStore, 0);
-        hPfxCertStore = NULL;
-    }
-
-    return hr;
-}
-*/
diff --git a/src/ca/scacert.h b/src/ca/scacert.h
deleted file mode 100644
index 39b00d3d..00000000
--- a/src/ca/scacert.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-// 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.
-
-
-#define CB_CERTIFICATE_HASH 20
-
-// Certificate.Attribute
-enum SCA_CERT_ATTRIBUTES
-{
-    SCA_CERT_ATTRIBUTE_DEFAULT = 0,
-    SCA_CERT_ATTRIBUTE_REQUEST = 1,
-    SCA_CERT_ATTRIBUTE_BINARYDATA = 2,
-    SCA_CERT_ATTRIBUTE_OVERWRITE = 4,
-    SCA_CERT_ATTRIBUTE_VITAL = 8,
-};
-
-
-// Certificate.StoreLocation
-enum SCA_CERTSYSTEMSTORE
-{
-    SCA_CERTSYSTEMSTORE_CURRENTUSER = 1,
-    SCA_CERTSYSTEMSTORE_LOCALMACHINE = 2,
-};
diff --git a/src/ca/scacertexec.cpp b/src/ca/scacertexec.cpp
deleted file mode 100644
index 95870c79..00000000
--- a/src/ca/scacertexec.cpp
+++ /dev/null
@@ -1,431 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-#define SIXTY_FOUR_MEG 64 * 1024 * 1024
-
-// prototypes
-static HRESULT ExecuteCertificateOperation(
-    __in MSIHANDLE hInstall,
-    __in SCA_ACTION saAction,
-    __in DWORD dwStoreRoot
-    );
-
-static HRESULT ReadCertificateFile(
-    __in LPCWSTR wzPath,
-    __out BYTE** prgbData,
-    __out DWORD* pcbData
-    );
-
-static HRESULT InstallCertificatePackage(
-    __in HCERTSTORE hStore,
-    __in BOOL fUserCertificateStore,
-    __in LPCWSTR wzName,
-    __in_opt BYTE* rgbData,
-    __in DWORD cbData,
-    __in BOOL fVital,
-    __in_opt LPCWSTR wzPFXPassword
-    );
-
-static HRESULT UninstallCertificatePackage(
-    __in HCERTSTORE hStore,
-    __in BOOL fUserCertificateStore,
-    __in LPCWSTR wzName
-    );
-
-static HRESULT AddCertificate(
-    __in HCERTSTORE hStore,
-    __in PCCERT_CONTEXT pCertContext,
-    __in LPCWSTR wzCertificateUniqueName,
-    __in BOOL fVital
-);
-
-/* ****************************************************************
- AddUserCertificate - CUSTOM ACTION ENTRY POINT for adding per-user
-                      certificates
-
- * ***************************************************************/
-extern "C" UINT __stdcall AddUserCertificate(
-    __in MSIHANDLE hInstall
-    )
-{
-    HRESULT hr = S_OK;
-    DWORD er = ERROR_SUCCESS;
-
-    hr = WcaInitialize(hInstall, "AddUserCertificate");
-    ExitOnFailure(hr, "Failed to initialize AddUserCertificate.");
-
-    hr = ExecuteCertificateOperation(hInstall, SCA_ACTION_INSTALL, CERT_SYSTEM_STORE_CURRENT_USER);
-    ExitOnFailure(hr, "Failed to install per-user certificate.");
-
-LExit:
-    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
-    return WcaFinalize(er);
-}
-
-
-/* ****************************************************************
- AddMachineCertificate - CUSTOM ACTION ENTRY POINT for adding 
-                         per-machine certificates
-
- * ***************************************************************/
-extern "C" UINT __stdcall AddMachineCertificate(
-    __in MSIHANDLE hInstall
-    )
-{
-    HRESULT hr = S_OK;
-    DWORD er = ERROR_SUCCESS;
-
-    hr = WcaInitialize(hInstall, "AddMachineCertificate");
-    ExitOnFailure(hr, "Failed to initialize AddMachineCertificate.");
-
-    hr = ExecuteCertificateOperation(hInstall, SCA_ACTION_INSTALL, CERT_SYSTEM_STORE_LOCAL_MACHINE);
-    ExitOnFailure(hr, "Failed to install per-machine certificate.");
-
-LExit:
-    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
-    return WcaFinalize(er);
-}
-
-
-/* ****************************************************************
- DeleteUserCertificate - CUSTOM ACTION ENTRY POINT for deleting 
-                         per-user certificates
-
- * ***************************************************************/
-extern "C" UINT __stdcall DeleteUserCertificate(
-    __in MSIHANDLE hInstall
-    )
-{
-    HRESULT hr = S_OK;
-    DWORD er = ERROR_SUCCESS;
-
-    hr = WcaInitialize(hInstall, "DeleteUserCertificate");
-    ExitOnFailure(hr, "Failed to initialize DeleteUserCertificate.");
-
-    hr = ExecuteCertificateOperation(hInstall, SCA_ACTION_UNINSTALL, CERT_SYSTEM_STORE_CURRENT_USER);
-    ExitOnFailure(hr, "Failed to uninstall per-user certificate.");
-
-LExit:
-    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
-    return WcaFinalize(er);
-}
-
-
-/* ****************************************************************
- DeleteMachineCertificate - CUSTOM ACTION ENTRY POINT for deleting
-                            per-machine certificates
-
- * ***************************************************************/
-extern "C" UINT __stdcall DeleteMachineCertificate(
-    __in MSIHANDLE hInstall
-    )
-{
-    HRESULT hr = S_OK;
-    DWORD er = ERROR_SUCCESS;
-
-    hr = WcaInitialize(hInstall, "DeleteMachineCertificate");
-    ExitOnFailure(hr, "Failed to initialize DeleteMachineCertificate.");
-
-    hr = ExecuteCertificateOperation(hInstall, SCA_ACTION_UNINSTALL, CERT_SYSTEM_STORE_LOCAL_MACHINE);
-    ExitOnFailure(hr, "Failed to uninstall per-machine certificate.");
-
-LExit:
-    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
-    return WcaFinalize(er);
-}
-
-
-static HRESULT ExecuteCertificateOperation(
-    __in MSIHANDLE /*hInstall*/,
-    __in SCA_ACTION saAction,
-    __in DWORD dwStoreLocation
-    )
-{
-    //AssertSz(FALSE, "Debug ExecuteCertificateOperation() here.");
-    Assert(saAction & SCA_ACTION_INSTALL || saAction & SCA_ACTION_UNINSTALL);
-
-    HRESULT hr = S_OK;
-    LPWSTR pwzCaData = NULL;
-    LPWSTR pwz;
-    LPWSTR pwzName = NULL;
-    LPWSTR pwzStore = NULL;
-    int iAttributes = 0;
-    LPWSTR pwzPFXPassword = NULL;
-    LPWSTR pwzFilePath = NULL;
-    BYTE* pbData = NULL;
-    DWORD cbData = 0;
-    DWORD_PTR cbPFXPassword = 0;
-
-    BOOL fUserStoreLocation = (CERT_SYSTEM_STORE_CURRENT_USER == dwStoreLocation);
-    HCERTSTORE hCertStore = NULL;
-
-    hr = WcaGetProperty(L"CustomActionData", &pwzCaData);
-    ExitOnFailure(hr, "Failed to get CustomActionData");
-
-    WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCaData);
-
-    pwz = pwzCaData;
-    hr = WcaReadStringFromCaData(&pwz, &pwzName);
-    ExitOnFailure(hr, "Failed to parse certificate name.");
-    hr = WcaReadStringFromCaData(&pwz, &pwzStore);
-    ExitOnFailure(hr, "Failed to parse CustomActionData, StoreName");
-    hr = WcaReadIntegerFromCaData(&pwz, &iAttributes);
-    ExitOnFailure(hr, "Failed to parse certificate attribute");
-    if (SCA_ACTION_INSTALL == saAction) // install operations need more data
-    {
-        hr = WcaReadStreamFromCaData(&pwz, &pbData, (DWORD_PTR*)&cbData);
-        ExitOnFailure(hr, "Failed to parse certificate stream.");
-
-        hr = WcaReadStringFromCaData(&pwz, &pwzPFXPassword);
-        ExitOnFailure(hr, "Failed to parse certificate password.");
-    }
-
-    // Open the right store.
-    hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, dwStoreLocation | CERT_STORE_MAXIMUM_ALLOWED_FLAG, pwzStore);
-    MessageExitOnNullWithLastError(hCertStore, hr, msierrCERTFailedOpen, "Failed to open certificate store: %ls", pwzStore);
-
-    if (SCA_ACTION_INSTALL == saAction) // install operations need more data
-    {
-        // Uninstall existing versions of this package.  Ignore any failures
-        // This is needed to clean up the private key of a cert when we replace an existing cert
-        // CertAddCertificateContextToStore(CERT_STORE_ADD_REPLACE_EXISTING) does not remove the private key if the cert is replaced
-        UninstallCertificatePackage(hCertStore, fUserStoreLocation, pwzName);
-
-        hr = InstallCertificatePackage(hCertStore, fUserStoreLocation, pwzName, pbData, cbData, iAttributes & SCA_CERT_ATTRIBUTE_VITAL, pwzPFXPassword);
-        ExitOnFailure(hr, "Failed to install certificate.");
-    }
-    else
-    {
-        Assert(SCA_ACTION_UNINSTALL == saAction);
-
-        hr = UninstallCertificatePackage(hCertStore, fUserStoreLocation, pwzName);
-        ExitOnFailure(hr, "Failed to uninstall certificate.");
-    }
-
-LExit:
-    if (NULL != pwzPFXPassword && SUCCEEDED(StrSize(pwzPFXPassword, &cbPFXPassword)))
-    {
-        SecureZeroMemory(pwzPFXPassword, cbPFXPassword);
-    }
-
-    if (hCertStore)
-    {
-        if (!::CertCloseStore(hCertStore, CERT_CLOSE_STORE_CHECK_FLAG))
-        {
-            WcaLog(LOGMSG_VERBOSE, "Cert store was closed but not all resources were freed.  Error 0x%x", GetLastError());
-        }
-    }
-
-    ReleaseMem(pbData);
-    ReleaseStr(pwzFilePath);
-    ReleaseStr(pwzPFXPassword);
-    ReleaseStr(pwzStore);
-    ReleaseStr(pwzName);
-    ReleaseStr(pwzCaData);
-    return hr;
-}
-
-
-static HRESULT InstallCertificatePackage(
-    __in HCERTSTORE hStore,
-    __in BOOL fUserCertificateStore,
-    __in LPCWSTR wzName,
-    __in_opt BYTE* rgbData,
-    __in DWORD cbData,
-    __in BOOL fVital,
-    __in_opt LPCWSTR wzPFXPassword
-    )
-{
-    HRESULT hr = S_OK;
-
-    HCERTSTORE hPfxCertStore = NULL;
-    PCCERT_CONTEXT pCertContext = NULL;
-    CERT_BLOB blob = { 0 };
-    DWORD dwKeyset = fUserCertificateStore ? CRYPT_USER_KEYSET : CRYPT_MACHINE_KEYSET;
-    DWORD dwEncodingType;
-    DWORD dwContentType;
-    DWORD dwFormatType;
-    LPWSTR pwzUniqueName = NULL;
-    int iUniqueId = 0;
-
-    // Figure out what type of blob (certificate or PFX) we're dealing with here.
-    blob.pbData = rgbData;
-    blob.cbData = cbData;
-
-    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))
-    {
-        ExitWithLastError(hr, "Failed to parse the certificate blob: %ls", wzName);
-    }
-
-    hr = StrAllocFormatted(&pwzUniqueName, L"%s_wixCert_%d", wzName, ++iUniqueId);
-    ExitOnFailure(hr, "Failed to format unique name");
-
-    if (!pCertContext)
-    {
-        // If we have a PFX blob, get the first certificate out of the PFX and use that instead of the PFX.
-        if (dwContentType & CERT_QUERY_CONTENT_PFX)
-        {
-            ExitOnNull(wzPFXPassword, hr, E_INVALIDARG, "Failed to import PFX blob because no password was provided");
-
-            // If we fail and our password is blank, also try passing in NULL for the password (according to the docs)
-            hPfxCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, wzPFXPassword, dwKeyset);
-            if (NULL == hPfxCertStore && !*wzPFXPassword)
-            {
-                hPfxCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, NULL, dwKeyset);
-            }
-            ExitOnNullWithLastError(hPfxCertStore, hr, "Failed to open PFX file.");
-
-            // Install all certificates in the PFX
-            for (pCertContext = ::CertEnumCertificatesInStore(hPfxCertStore, pCertContext);
-                 pCertContext;
-                 pCertContext = ::CertEnumCertificatesInStore(hPfxCertStore, pCertContext))
-            {
-                hr = AddCertificate(hStore, pCertContext, pwzUniqueName, fVital);
-                MessageExitOnFailure(hr, msierrCERTFailedAdd, "Failed to add certificate to the store.");
-
-                hr = StrAllocFormatted(&pwzUniqueName, L"%s_wixCert_%d", wzName, ++iUniqueId);
-                ExitOnFailure(hr, "Failed to format unique name");
-            }
-        }
-        else
-        {
-            hr = E_UNEXPECTED;
-            ExitOnFailure(hr, "Unexpected certificate type processed.");
-        }
-    }
-    else
-    {
-        hr = AddCertificate(hStore, pCertContext, pwzUniqueName, fVital);
-        MessageExitOnFailure(hr, msierrCERTFailedAdd, "Failed to add certificate to the store.");
-    }
-
-    hr = WcaProgressMessage(COST_CERT_ADD, FALSE);
-    ExitOnFailure(hr, "Failed to send install progress message.");
-
-LExit:
-    ReleaseStr(pwzUniqueName);
-
-    if (pCertContext)
-    {
-        ::CertFreeCertificateContext(pCertContext);
-    }
-
-    // Close the stores after the context's are released.
-    if (hPfxCertStore)
-    {
-        if (!::CertCloseStore(hPfxCertStore, CERT_CLOSE_STORE_CHECK_FLAG))
-        {
-            WcaLog(LOGMSG_VERBOSE, "PFX cert store was closed but not all resources were freed.  Error 0x%x", GetLastError());
-        }
-    }
-
-    return hr;
-}
-
-
-static HRESULT UninstallCertificatePackage(
-    __in HCERTSTORE hStore,
-    __in BOOL fUserCertificateStore,
-    __in LPCWSTR wzName
-    )
-{
-    HRESULT hr = S_OK;
-    DWORD er = ERROR_SUCCESS;
-    PCCERT_CONTEXT pCertContext = NULL;
-    CRYPT_KEY_PROV_INFO* pPrivateKeyInfo = NULL;
-    LPWSTR pwzUniquePrefix = NULL;
-    int ccUniquePrefix = 0;
-
-    hr = StrAllocFormatted(&pwzUniquePrefix, L"%s_wixCert_", wzName);
-    ExitOnFailure(hr, "Failed to format unique name");
-    ccUniquePrefix = ::lstrlenW(pwzUniquePrefix);
-
-    WcaLog(LOGMSG_STANDARD, "Deleting certificate that begin with friendly name: %ls", pwzUniquePrefix);
-
-    // Loop through all certificates in the store, deleting the ones that begin with our prefix.
-    while (NULL != (pCertContext = ::CertFindCertificateInStore(hStore, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, pCertContext)))
-    {
-        WCHAR wzFriendlyName[256] = { 0 };
-        DWORD cbFriendlyName = sizeof(wzFriendlyName);
-
-        if (::CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, reinterpret_cast<BYTE*>(wzFriendlyName), &cbFriendlyName) &&
-            lstrlenW(wzFriendlyName) >= ccUniquePrefix &&
-            CSTR_EQUAL == ::CompareStringW(LOCALE_SYSTEM_DEFAULT, 0, pwzUniquePrefix, ccUniquePrefix, wzFriendlyName, ccUniquePrefix))
-        {
-            PCCERT_CONTEXT pCertContextDelete = ::CertDuplicateCertificateContext(pCertContext); // duplicate the context so we can delete it with out disrupting the looping
-            if(pCertContextDelete)
-            {
-                // Delete the certificate and if successful delete the matching private key as well.
-                if (::CertDeleteCertificateFromStore(pCertContextDelete))
-                {
-                    // If we found private key info, delete it.
-                    hr = CertReadProperty(pCertContextDelete, CERT_KEY_PROV_INFO_PROP_ID, &pPrivateKeyInfo, NULL);
-                    if (SUCCEEDED(hr))
-                    {
-                        HCRYPTPROV hProvIgnored = NULL; // ignored on deletes.
-                        DWORD dwKeyset = fUserCertificateStore ? CRYPT_USER_KEYSET : CRYPT_MACHINE_KEYSET;
-
-                        if (!::CryptAcquireContextW(&hProvIgnored, pPrivateKeyInfo->pwszContainerName, pPrivateKeyInfo->pwszProvName, pPrivateKeyInfo->dwProvType, dwKeyset | CRYPT_DELETEKEYSET | CRYPT_SILENT))
-                        {
-                            er = ::GetLastError();
-                            hr = HRESULT_FROM_WIN32(er);
-                        }
-
-                        ReleaseNullMem(pPrivateKeyInfo);
-                    }
-                    else // don't worry about failures to delete private keys.
-                    {
-                        hr = S_OK;
-                    }
-                }
-                else
-                {
-                    er = ::GetLastError();
-                    hr = HRESULT_FROM_WIN32(er);
-                }
-
-                if (FAILED(hr))
-                {
-                    WcaLog(LOGMSG_STANDARD, "Failed to delete certificate with friendly name: %ls, continuing anyway.  Error: 0x%x", wzFriendlyName, hr);
-                }
-
-                pCertContextDelete = NULL;
-            }
-        }
-    }
-
-    hr = WcaProgressMessage(COST_CERT_DELETE, FALSE);
-    ExitOnFailure(hr, "Failed to send uninstall progress message.");
-
-LExit:
-    ReleaseStr(pwzUniquePrefix);
-    ReleaseMem(pPrivateKeyInfo);
-    if(pCertContext)
-    {
-        ::CertFreeCertificateContext(pCertContext);
-    }
-
-    return hr;
-}
-
-static HRESULT AddCertificate(
-    __in HCERTSTORE hStore,
-    __in PCCERT_CONTEXT pCertContext,
-    __in LPCWSTR wzCertificateUniqueName,
-    __in BOOL fVital
-)
-{
-    HRESULT hr = S_OK;
-
-    WcaLog(LOGMSG_STANDARD, "Adding certificate: %ls", wzCertificateUniqueName);
-
-    hr = CertInstallSingleCertificate(hStore, pCertContext, wzCertificateUniqueName);
-    if (FAILED(hr) && !fVital)
-    {
-        WcaLog(LOGMSG_STANDARD, "Could not add non-vital certificate: %ls due to error: 0x%x, continuing...", wzCertificateUniqueName, hr);
-        hr = S_FALSE;
-    }
-
-    return hr;
-}
diff --git a/src/ca/scacost.h b/src/ca/scacost.h
deleted file mode 100644
index be92cf26..00000000
--- a/src/ca/scacost.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma once
-// 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.
-
-
-const UINT COST_IIS_TRANSACTIONS = 10000;
-
-const UINT COST_IIS_CREATEKEY = 5000;
-const UINT COST_IIS_DELETEKEY = 5000;
-const UINT COST_IIS_WRITEVALUE = 5000;
-const UINT COST_IIS_DELETEVALUE = 5000;
-const UINT COST_IIS_CREATEAPP = 5000;
-const UINT COST_IIS_DELETEAPP = 5000;
-
-const UINT COST_CERT_ADD = 5000;
-const UINT COST_CERT_DELETE = 5000;
diff --git a/src/ca/scaexec.cpp b/src/ca/scaexec.cpp
deleted file mode 100644
index df25e8db..00000000
--- a/src/ca/scaexec.cpp
+++ /dev/null
@@ -1,1184 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-
-/********************************************************************
- StartMetabaseTransaction - CUSTOM ACTION ENTRY POINT for backing up metabase
-
-  Input:  deferred CustomActionData - BackupName
-********************************************************************/
-extern "C" UINT __stdcall StartMetabaseTransaction(MSIHANDLE hInstall)
-{
-//AssertSz(FALSE, "debug StartMetabaseTransaction here");
-    HRESULT hr = S_OK;
-    UINT er = ERROR_SUCCESS;
-
-    IMSAdminBase* piMetabase = NULL;
-    LPWSTR pwzData = NULL;
-    BOOL fInitializedCom = FALSE;
-
-    // initialize
-    hr = WcaInitialize(hInstall, "StartMetabaseTransaction");
-    ExitOnFailure(hr, "failed to initialize StartMetabaseTransaction");
-
-    hr = ::CoInitialize(NULL);
-    ExitOnFailure(hr, "failed to initialize COM");
-    fInitializedCom = TRUE;
-    hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase));
-    if (hr == REGDB_E_CLASSNOTREG)
-    {
-        WcaLog(LOGMSG_STANDARD, "Failed to get IIMSAdminBase to backup - continuing");
-        hr = S_OK;
-    }
-    else
-    {
-        MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IIMSAdminBase object");
-
-        hr = WcaGetProperty(L"CustomActionData", &pwzData);
-        ExitOnFailure(hr, "failed to get CustomActionData");
-
-        // back up the metabase
-        Assert(lstrlenW(pwzData) < MD_BACKUP_MAX_LEN);
-
-        // MD_BACKUP_OVERWRITE = Overwrite if a backup of the same name and version exists in the backup location
-        hr = piMetabase->Backup(pwzData, MD_BACKUP_NEXT_VERSION, MD_BACKUP_OVERWRITE | MD_BACKUP_FORCE_BACKUP | MD_BACKUP_SAVE_FIRST);
-        if (MD_WARNING_SAVE_FAILED == hr)
-        {
-            WcaLog(LOGMSG_STANDARD, "Failed to save metabase before backing up - continuing");
-            hr = S_OK;
-        }
-        MessageExitOnFailure(hr, msierrIISFailedStartTransaction, "failed to begin metabase transaction: '%ls'", pwzData);
-    }
-    hr = WcaProgressMessage(COST_IIS_TRANSACTIONS, FALSE);
-LExit:
-    ReleaseStr(pwzData);
-    ReleaseObject(piMetabase);
-
-    if (fInitializedCom)
-    {
-        ::CoUninitialize();
-    }
-
-    if (FAILED(hr))
-        er = ERROR_INSTALL_FAILURE;
-    return WcaFinalize(er);
-}
-
-
-/********************************************************************
- RollbackMetabaseTransaction - CUSTOM ACTION ENTRY POINT for unbacking up metabase
-
-  Input:  deferred CustomActionData - BackupName
-********************************************************************/
-extern "C" UINT __stdcall RollbackMetabaseTransaction(MSIHANDLE hInstall)
-{
-//AssertSz(FALSE, "debug RollbackMetabaseTransaction here");
-    HRESULT hr = S_OK;
-    UINT er = ERROR_SUCCESS;
-
-    IMSAdminBase* piMetabase = NULL;
-    LPWSTR pwzData = NULL;
-    BOOL fInitializedCom = FALSE;
-
-    hr = WcaInitialize(hInstall, "RollbackMetabaseTransaction");
-    ExitOnFailure(hr, "failed to initialize");
-
-    hr = ::CoInitialize(NULL);
-    ExitOnFailure(hr, "failed to initialize COM");
-    fInitializedCom = TRUE;
-    hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase));
-    if (hr == REGDB_E_CLASSNOTREG)
-    {
-        WcaLog(LOGMSG_STANDARD, "Failed to get IIMSAdminBase to rollback - continuing");
-        hr = S_OK;
-        ExitFunction();
-    }
-    ExitOnFailure(hr, "failed to get IID_IIMSAdminBase object");
-
-
-    hr = WcaGetProperty( L"CustomActionData", &pwzData);
-    ExitOnFailure(hr, "failed to get CustomActionData");
-
-    hr = piMetabase->Restore(pwzData, MD_BACKUP_HIGHEST_VERSION, 0);
-    ExitOnFailure(hr, "failed to rollback metabase transaction: '%ls'", pwzData);
-
-    hr = piMetabase->DeleteBackup(pwzData, MD_BACKUP_HIGHEST_VERSION);
-    ExitOnFailure(hr, "failed to cleanup metabase transaction '%ls', continuing", pwzData);
-
-LExit:
-    ReleaseStr(pwzData);
-    ReleaseObject(piMetabase);
-
-    if (fInitializedCom)
-    {
-        ::CoUninitialize();
-    }
-
-    if (FAILED(hr))
-    {
-        er = ERROR_INSTALL_FAILURE;
-    }
-    return WcaFinalize(er);
-}
-
-
-/********************************************************************
- CommitMetabaseTransaction - CUSTOM ACTION ENTRY POINT for unbacking up metabase
-
-  Input:  deferred CustomActionData - BackupName
- * *****************************************************************/
-extern "C" UINT __stdcall CommitMetabaseTransaction(MSIHANDLE hInstall)
-{
-    HRESULT hr = S_OK;
-    UINT er = ERROR_SUCCESS;
-
-    IMSAdminBase* piMetabase = NULL;
-    LPWSTR pwzData = NULL;
-    BOOL fInitializedCom = FALSE;
-
-    hr = WcaInitialize(hInstall, "CommitMetabaseTransaction");
-    ExitOnFailure(hr, "failed to initialize");
-
-    hr = ::CoInitialize(NULL);
-    ExitOnFailure(hr, "failed to initialize COM");
-    fInitializedCom = TRUE;
-    hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase));
-    if (hr == REGDB_E_CLASSNOTREG)
-    {
-        WcaLog(LOGMSG_STANDARD, "Failed to get IIMSAdminBase to commit - continuing");
-        hr = S_OK;
-        ExitFunction();
-    }
-    ExitOnFailure(hr, "failed to get IID_IIMSAdminBase object");
-
-    hr = WcaGetProperty( L"CustomActionData", &pwzData);
-    ExitOnFailure(hr, "failed to get CustomActionData");
-
-    hr = piMetabase->DeleteBackup(pwzData, MD_BACKUP_HIGHEST_VERSION);
-    ExitOnFailure(hr, "failed to cleanup metabase transaction: '%ls'", pwzData);
-
-LExit:
-    ReleaseStr(pwzData);
-    ReleaseObject(piMetabase);
-
-    if (fInitializedCom)
-    {
-        ::CoUninitialize();
-    }
-
-    if (FAILED(hr))
-    {
-        er = ERROR_INSTALL_FAILURE;
-    }
-    return WcaFinalize(er);
-}
-
-
-/********************************************************************
- CreateMetabaseKey - Installs metabase keys
-
-  Input:  deferred CustomActionData - Key
- * *****************************************************************/
-static HRESULT CreateMetabaseKey(__in LPWSTR* ppwzCustomActionData, __in IMSAdminBase* piMetabase)
-{
-//AssertSz(FALSE, "debug CreateMetabaseKey here");
-    HRESULT hr = S_OK;
-    METADATA_HANDLE mhRoot = 0;
-    LPWSTR pwzData = NULL;
-    LPCWSTR pwzKey;
-
-    int i;
-
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-    ExitOnFailure(hr, "failed to read key from custom action data");
-
-    hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhRoot);
-    for (i = 30; i > 0 && HRESULT_FROM_WIN32(ERROR_PATH_BUSY) == hr; i--)
-    {
-        ::Sleep(1000);
-        WcaLog(LOGMSG_STANDARD, "failed to open root key, retrying %d time(s)...", i);
-        hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhRoot);
-    }
-    MessageExitOnFailure(hr, msierrIISFailedOpenKey, "failed to open metabase key: %ls", L"/LM");
-
-    pwzKey = pwzData + 3;
-
-    WcaLog(LOGMSG_VERBOSE, "Creating Metabase Key: %ls", pwzKey);
-
-    hr = piMetabase->AddKey(mhRoot, pwzKey);
-    if (HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hr)
-    {
-        WcaLog(LOGMSG_VERBOSE, "Key `%ls` already existed, continuing.", pwzData);
-        hr = S_OK;
-    }
-    MessageExitOnFailure(hr, msierrIISFailedCreateKey, "failed to create metabase key: %ls", pwzKey);
-
-    hr = WcaProgressMessage(COST_IIS_CREATEKEY, FALSE);
-
-LExit:
-    if (mhRoot)
-    {
-        piMetabase->CloseKey(mhRoot);
-    }
-
-    return hr;
-}
-
-
-/********************************************************************
- WriteMetabaseValue -Installs metabase values
-
-  Input:  deferred CustomActionData - Key\tIdentifier\tAttributes\tUserType\tDataType\tData
- * *****************************************************************/
-static HRESULT WriteMetabaseValue(__in LPWSTR* ppwzCustomActionData, __in IMSAdminBase* piMetabase)
-{
-    //AssertSz(FALSE, "debug WriteMetabaseValue here");
-    HRESULT hr = S_OK;
-
-    METADATA_HANDLE mhKey = 0;
-
-    LPWSTR pwzKey = NULL;
-    LPWSTR pwzTemp = NULL;
-    DWORD dwData = 0;
-    DWORD dwTemp = 0;
-    BOOL fFreeData = FALSE;
-    METADATA_RECORD mr;
-    ::ZeroMemory((LPVOID)&mr, sizeof(mr));
-    METADATA_RECORD mrGet;
-    ::ZeroMemory((LPVOID)&mrGet, sizeof(mrGet));
-
-    int i;
-
-    // get the key first
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzKey);
-    ExitOnFailure(hr, "failed to read key");
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&mr.dwMDIdentifier));
-    ExitOnFailure(hr, "failed to read identifier");
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&mr.dwMDAttributes));
-    ExitOnFailure(hr, "failed to read attributes");
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&mr.dwMDUserType));
-    ExitOnFailure(hr, "failed to read user type");
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&mr.dwMDDataType));
-    ExitOnFailure(hr, "failed to read data type");
-
-    switch (mr.dwMDDataType) // data
-    {
-    case DWORD_METADATA:
-        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&dwData));
-        mr.dwMDDataLen = sizeof(dwData);
-        mr.pbMDData = reinterpret_cast<BYTE*>(&dwData);
-        break;
-    case STRING_METADATA:
-        hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzTemp);
-        mr.dwMDDataLen = (lstrlenW(pwzTemp) + 1) * sizeof(WCHAR);
-        mr.pbMDData = reinterpret_cast<BYTE*>(pwzTemp);
-        break;
-    case MULTISZ_METADATA:
-        {
-        hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzTemp);
-        mr.dwMDDataLen = (lstrlenW(pwzTemp) + 1) * sizeof(WCHAR);
-        for (LPWSTR pwzT = pwzTemp; *pwzT; ++pwzT)
-        {
-            if (MAGIC_MULTISZ_CHAR == *pwzT)
-            {
-                *pwzT = L'\0';
-            }
-        }
-        mr.pbMDData = reinterpret_cast<BYTE*>(pwzTemp);
-        }
-        break;
-    case BINARY_METADATA:
-        hr = WcaReadStreamFromCaData(ppwzCustomActionData, &mr.pbMDData, reinterpret_cast<DWORD_PTR *>(&mr.dwMDDataLen));
-        fFreeData = TRUE;
-        break;
-    default:
-        hr = E_UNEXPECTED;
-        break;
-    }
-    ExitOnFailure(hr, "failed to parse CustomActionData into metabase record");
-
-    WcaLog(LOGMSG_VERBOSE, "Writing Metabase Value Under Key: %ls ID: %d", pwzKey, mr.dwMDIdentifier);
-
-    hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhKey);
-    for (i = 30; i > 0 && HRESULT_FROM_WIN32(ERROR_PATH_BUSY) == hr; i--)
-    {
-        ::Sleep(1000);
-        WcaLog(LOGMSG_STANDARD, "failed to open '%ls' key, retrying %d time(s)...", pwzKey, i);
-        hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhKey);
-    }
-    MessageExitOnFailure(hr, msierrIISFailedOpenKey, "failed to open metabase key: %ls", pwzKey);
-
-    if (lstrlenW(pwzKey) < 3)
-    {
-        ExitOnFailure(hr = E_INVALIDARG, "Key didn't begin with \"/LM\" as expected - key value: %ls", pwzKey);
-    }
-
-    hr = piMetabase->SetData(mhKey, pwzKey + 3, &mr); // pwzKey + 3 to skip "/LM" that was used to open the key.
-
-    // 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
-    if (MD_ERROR_CANNOT_REMOVE_SECURE_ATTRIBUTE == hr)
-    {
-        mr.dwMDAttributes |= METADATA_SECURE;
-        hr = piMetabase->SetData(mhKey, pwzKey + 3, &mr);
-    }
-
-    // If IIS6 returned failure, let's check if the correct value exists in the metabase before actually failing the CA
-    if (FAILED(hr))
-    {
-        // Backup the original failure error, so we can log it below if necessary
-        HRESULT hrOldValue = hr;
-
-        mrGet.dwMDIdentifier = mr.dwMDIdentifier;
-        mrGet.dwMDAttributes = METADATA_NO_ATTRIBUTES;
-        mrGet.dwMDUserType = mr.dwMDUserType;
-        mrGet.dwMDDataType = mr.dwMDDataType;
-        mrGet.dwMDDataLen = mr.dwMDDataLen;
-        mrGet.pbMDData = static_cast<BYTE*>(MemAlloc(mr.dwMDDataLen, TRUE));
-
-        hr = piMetabase->GetData(mhKey, pwzKey + 3, &mrGet, &dwTemp);
-        if (SUCCEEDED(hr))
-        {
-            if (mrGet.dwMDDataType == mr.dwMDDataType && mrGet.dwMDDataLen == mr.dwMDDataLen && 0 == memcmp(mrGet.pbMDData, mr.pbMDData, mr.dwMDDataLen))
-            {
-                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);
-                hr = S_OK;
-            }
-            else
-            {
-                WcaLog(LOGMSG_VERBOSE, "Succeeded in checking metabase value after write value, but the values didn't match");
-                hr = hrOldValue;
-            }
-        }
-        else
-        {
-            WcaLog(LOGMSG_VERBOSE, "Failed to check value after metabase write failure (error code 0x%x)", hr);
-            hr = hrOldValue;
-        }
-    }
-    MessageExitOnFailure(hr, msierrIISFailedWriteData, "failed to write data to metabase key: %ls", pwzKey);
-
-    hr = WcaProgressMessage(COST_IIS_WRITEVALUE, FALSE);
-
-LExit:
-    ReleaseStr(pwzTemp);
-    ReleaseStr(pwzKey);
-
-    if (mhKey)
-    {
-        piMetabase->CloseKey(mhKey);
-    }
-
-    if (fFreeData && mr.pbMDData)
-    {
-        MemFree(mr.pbMDData);
-    }
-
-    return hr;
-}
-
-
-/********************************************************************
- DeleteMetabaseValue -Installs metabase values
-
-  Input:  deferred CustomActionData - Key\tIdentifier\tAttributes\tUserType\tDataType\tData
- * *****************************************************************/
-static HRESULT DeleteMetabaseValue(__in LPWSTR* ppwzCustomActionData, __in IMSAdminBase* piMetabase)
-{
-    //AssertSz(FALSE, "debug DeleteMetabaseValue here");
-    HRESULT hr = S_OK;
-
-    METADATA_HANDLE mhKey = 0;
-
-    LPWSTR pwzKey = NULL;
-    DWORD dwIdentifier = 0;
-    DWORD dwDataType = 0;
-
-    int i;
-
-    // get the key first
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzKey);
-    ExitOnFailure(hr, "failed to read key");
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&dwIdentifier));
-    ExitOnFailure(hr, "failed to read identifier");
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&dwDataType));
-    ExitOnFailure(hr, "failed to read data type");
-
-    WcaLog(LOGMSG_VERBOSE, "Deleting Metabase Value Under Key: %ls ID: %d", pwzKey, dwIdentifier);
-
-    hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhKey);
-    for (i = 30; i > 0 && HRESULT_FROM_WIN32(ERROR_PATH_BUSY) == hr; i--)
-    {
-        ::Sleep(1000);
-        WcaLog(LOGMSG_STANDARD, "failed to open '%ls' key, retrying %d time(s)...", pwzKey, i);
-        hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhKey);
-    }
-    MessageExitOnFailure(hr, msierrIISFailedOpenKey, "failed to open metabase key: %ls", pwzKey);
-
-    if (lstrlenW(pwzKey) < 3)
-    {
-        ExitOnFailure(hr = E_INVALIDARG, "Key didn't begin with \"/LM\" as expected - key value: %ls", pwzKey);
-    }
-
-    hr = piMetabase->DeleteData(mhKey, pwzKey + 3, dwIdentifier, dwDataType); // pwzKey + 3 to skip "/LM" that was used to open the key.
-    if (MD_ERROR_DATA_NOT_FOUND == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
-    {
-        hr = S_OK;
-    }
-    MessageExitOnFailure(hr, msierrIISFailedDeleteValue, "failed to delete value %d from metabase key: %ls", dwIdentifier, pwzKey);
-
-    hr = WcaProgressMessage(COST_IIS_DELETEVALUE, FALSE);
-LExit:
-    ReleaseStr(pwzKey);
-
-    if (mhKey)
-        piMetabase->CloseKey(mhKey);
-
-    return hr;
-}
-
-
-/********************************************************************
- DeleteAspApp - Deletes applications in IIS
-
-  Input:  deferred CustomActionData - MetabaseRoot\tRecursive
- * *****************************************************************/
-static HRESULT DeleteAspApp(__in LPWSTR* ppwzCustomActionData, __in IMSAdminBase* piMetabase, __in ICatalogCollection* pApplicationCollection, __in IWamAdmin* piWam)
-{
-    const int BUFFER_BYTES = 512;
-    const BSTR bstrPropName = SysAllocString(L"Deleteable");
-
-    HRESULT hr = S_OK;
-    ICatalogObject* pApplication = NULL;
-
-    LPWSTR pwzRoot = NULL;
-    DWORD dwActualBufferSize = 0;
-    long lSize = 0;
-    long lIndex = 0;
-    long lChanges = 0;
-
-    VARIANT keyValue;
-    ::VariantInit(&keyValue);
-    VARIANT propValue;
-    propValue.vt = VT_BOOL;
-    propValue.boolVal = TRUE;
-
-    METADATA_RECORD mr;
-    // Get current set of web service extensions.
-    ::ZeroMemory(&mr, sizeof(mr));
-    mr.dwMDIdentifier = MD_APP_PACKAGE_ID;
-    mr.dwMDAttributes = 0;
-    mr.dwMDUserType  = ASP_MD_UT_APP;
-    mr.dwMDDataType = STRING_METADATA;
-    mr.pbMDData = new unsigned char[BUFFER_BYTES];
-    mr.dwMDDataLen = BUFFER_BYTES;
-
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzRoot); // MetabaseRoot
-    ExitOnFailure(hr, "failed to get metabase root");
-
-    hr = piMetabase->GetData(METADATA_MASTER_ROOT_HANDLE, pwzRoot, &mr, &dwActualBufferSize);
-    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)
-    {
-        // This one doesn't have an independent app GUID associated with it - it may have been already partially deleted, or a low isolation app
-        WcaLog(LOGMSG_VERBOSE, "No independent COM+ application found associated with %ls. It either doesn't exist, or was already removed - continuing", pwzRoot);
-        ExitFunction1(hr = S_OK);
-    }
-    MessageExitOnFailure(hr, msierrIISFailedDeleteApp, "failed to get GUID for application at path: %ls", pwzRoot);
-
-    WcaLog(LOGMSG_VERBOSE, "Deleting ASP App (used query: %ls) with GUID: %ls", pwzRoot, (LPWSTR)(mr.pbMDData));
-
-    // Delete the application association from IIS's point of view before it's obliterated from the application collection
-    hr = piWam->AppDelete(pwzRoot, FALSE);
-    if (FAILED(hr))
-    {
-        // This isn't necessarily an error if we fail here, but let's log a failure if it happens
-        WcaLog(LOGMSG_VERBOSE, "error 0x%x: failed to call IWamAdmin::AppDelete() while removing web application - continuing");
-        hr = S_OK;
-    }
-
-    if (!pApplicationCollection)
-    {
-        WcaLog(LOGMSG_STANDARD, "Could not remove application with GUID %ls because the application collection could not be found", (LPWSTR)(mr.pbMDData));
-        ExitFunction1(hr = S_OK);
-    }
-
-    hr = pApplicationCollection->Populate();
-    MessageExitOnFailure(hr, msierrIISFailedDeleteApp, "failed to populate Application collection");
-
-    hr = pApplicationCollection->get_Count(&lSize);
-    MessageExitOnFailure(hr, msierrIISFailedDeleteApp, "failed to get size of Application collection");
-    WcaLog(LOGMSG_TRACEONLY, "Found %u items in application collection", lSize);
-
-    // No need to check this too early, as we may not even need this to have successfully allocated
-    ExitOnNull(bstrPropName, hr, E_OUTOFMEMORY, "failed to allocate memory for \"Deleteable\" string");
-
-    for (lIndex = 0; lIndex < lSize; ++lIndex)
-    {
-        hr = pApplicationCollection->get_Item(lIndex, reinterpret_cast<IDispatch**>(&pApplication));
-        MessageExitOnFailure(hr, msierrIISFailedDeleteApp, "failed to get COM+ application while enumerating through COM+ applications");
-
-        hr = pApplication->get_Key(&keyValue);
-        MessageExitOnFailure(hr, msierrIISFailedDeleteApp, "failed to get key of COM+ application while enumerating through COM+ applications");
-
-        WcaLog(LOGMSG_TRACEONLY, "While enumerating through COM+ applications, found an application with GUID: %ls", (LPWSTR)keyValue.bstrVal);
-
-        if (VT_BSTR == keyValue.vt && 0 == lstrcmpW((LPWSTR)keyValue.bstrVal, (LPWSTR)(mr.pbMDData)))
-        {
-            hr = pApplication->put_Value(bstrPropName, propValue);
-            if (FAILED(hr))
-            {
-                // This isn't necessarily a critical error unless we fail to actually delete it in the next step
-                WcaLog(LOGMSG_VERBOSE, "error 0x%x: failed to ensure COM+ application with guid %ls is deletable - continuing", hr, (LPWSTR)(mr.pbMDData));
-            }
-
-            hr = pApplicationCollection->SaveChanges(&lChanges);
-            if (FAILED(hr))
-            {
-                // This isn't necessarily a critical error unless we fail to actually delete it in the next step
-                WcaLog(LOGMSG_VERBOSE, "error 0x%x: failed to save changes while ensuring COM+ application with guid %ls is deletable - continuing", hr, (LPWSTR)(mr.pbMDData));
-            }
-
-            hr = pApplicationCollection->Remove(lIndex);
-            if (FAILED(hr))
-            {
-                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));
-            }
-            else
-            {
-                hr = pApplicationCollection->SaveChanges(&lChanges);
-                if (FAILED(hr))
-                {
-                    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));
-                }
-                else
-                {
-                    WcaLog(LOGMSG_VERBOSE, "Found and removed application with GUID %ls", (LPWSTR)(mr.pbMDData));
-                }
-            }
-
-            // We've found the right key and successfully deleted the app - let's exit the loop now
-            lIndex = lSize;
-        }
-    }
-    // If we didn't find it, it isn't an error, because the application we want to delete doesn't seem to exist!
-
-    hr = WcaProgressMessage(COST_IIS_DELETEAPP, FALSE);
-LExit:
-    ReleaseBSTR(bstrPropName);
-
-    ReleaseStr(pwzRoot);
-    // Don't release pApplication, because it points to an object within the collection
-
-    delete [] mr.pbMDData;
-
-    return hr;
-}
-
-
-/********************************************************************
- CreateAspApp - Creates applications in IIS
-
-  Input:  deferred CustomActionData - MetabaseRoot\tInProc
- * ****************************************************************/
-static HRESULT CreateAspApp(__in LPWSTR* ppwzCustomActionData, __in IWamAdmin* piWam)
-{
-    HRESULT hr = S_OK;
-
-    LPWSTR pwzRoot = NULL;
-    BOOL fInProc;
-
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzRoot); // MetabaseRoot
-    ExitOnFailure(hr, "failed to get metabase root");
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&fInProc)); // InProc
-    ExitOnFailure(hr, "failed to get in proc flag");
-
-    WcaLog(LOGMSG_VERBOSE, "Creating ASP App: %ls", pwzRoot);
-
-    hr = piWam->AppCreate(pwzRoot, fInProc);
-    MessageExitOnFailure(hr, msierrIISFailedCreateApp, "failed to create web application: %ls", pwzRoot);
-
-    hr = WcaProgressMessage(COST_IIS_CREATEAPP, FALSE);
-LExit:
-    return hr;
-}
-
-
-/********************************************************************
- DeleteMetabaseKey - Deletes metabase keys
-
-  Input:  deferred CustomActionData - Key
- ******************************************************************/
-static HRESULT DeleteMetabaseKey(__in LPWSTR *ppwzCustomActionData, __in IMSAdminBase* piMetabase)
-{
-    HRESULT hr = S_OK;
-
-    METADATA_HANDLE mhRoot = 0;
-
-    LPWSTR pwzData = NULL;
-
-    LPCWSTR pwzKey;
-    int i;
-
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-    ExitOnFailure(hr, "failed to read key to be deleted");
-
-    hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhRoot);
-    for (i = 30; i > 0 && HRESULT_FROM_WIN32(ERROR_PATH_BUSY) == hr; i--)
-    {
-        ::Sleep(1000);
-        WcaLog(LOGMSG_STANDARD, "failed to open root key, retrying %d time(s)...", i);
-        hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhRoot);
-    }
-    MessageExitOnFailure(hr, msierrIISFailedOpenKey, "failed to open metabase key: %ls", L"/LM");
-
-    pwzKey = pwzData + 3;
-
-    WcaLog(LOGMSG_VERBOSE, "Deleting Metabase Key: %ls", pwzKey);
-
-    hr = piMetabase->DeleteKey(mhRoot, pwzKey);
-    if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
-    {
-        WcaLog(LOGMSG_STANDARD, "Key `%ls` did not exist, continuing.", pwzData);
-        hr = S_OK;
-    }
-    MessageExitOnFailure(hr, msierrIISFailedDeleteKey, "failed to delete metabase key: %ls", pwzData);
-
-    hr = WcaProgressMessage(COST_IIS_DELETEKEY, FALSE);
-LExit:
-    if (mhRoot)
-    {
-        piMetabase->CloseKey(mhRoot);
-    }
-
-    return hr;
-}
-
-
-/********************************************************************
- WriteMetabaseChanges - CUSTOM ACTION ENTRY POINT for IIS Metabase changes
-
- *******************************************************************/
-extern "C" UINT __stdcall WriteMetabaseChanges(MSIHANDLE hInstall)
-{
-//AssertSz(FALSE, "debug WriteMetabaseChanges here");
-    HRESULT hr = S_OK;
-    UINT er = ERROR_SUCCESS;
-    IMSAdminBase* piMetabase = NULL;
-    IWamAdmin* piWam = NULL;
-    ICOMAdminCatalog* pCatalog = NULL;
-    ICatalogCollection* pApplicationCollection = NULL;
-    WCA_CASCRIPT_HANDLE hWriteMetabaseScript = NULL;
-    BSTR bstrApplications = SysAllocString(L"Applications");
-    BOOL fInitializedCom = FALSE;
-
-    LPWSTR pwzData = NULL;
-    LPWSTR pwz = NULL;
-    LPWSTR pwzScriptKey = NULL;
-    METABASE_ACTION maAction = MBA_UNKNOWNACTION;
-
-    hr = WcaInitialize(hInstall, "WriteMetabaseChanges");
-    ExitOnFailure(hr, "failed to initialize");
-
-    hr = ::CoInitialize(NULL);
-    ExitOnFailure(hr, "failed to initialize COM");
-    fInitializedCom = TRUE;
-
-    hr = WcaGetProperty( L"CustomActionData", &pwzData);
-    ExitOnFailure(hr, "failed to get CustomActionData");
-
-    WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData);
-
-    // Get the CaScript key
-    hr = WcaReadStringFromCaData(&pwzData, &pwzScriptKey);
-    ExitOnFailure(hr, "Failed to get CaScript key from custom action data");
-
-    hr = WcaCaScriptOpen(WCA_ACTION_INSTALL, WCA_CASCRIPT_SCHEDULED, FALSE, pwzScriptKey, &hWriteMetabaseScript);
-    ExitOnFailure(hr, "Failed to open CaScript file");
-
-    // The rest of our existing custom action data string should be empty - go ahead and overwrite it
-    ReleaseNullStr(pwzData);
-    hr = WcaCaScriptReadAsCustomActionData(hWriteMetabaseScript, &pwzData);
-    ExitOnFailure(hr, "Failed to read script into CustomAction data.");
-
-    pwz = pwzData;
-
-    while (S_OK == (hr = WcaReadIntegerFromCaData(&pwz, (int *)&maAction)))
-    {
-        switch (maAction)
-        {
-        case MBA_CREATEAPP:
-            if (NULL == piWam)
-            {
-                hr = ::CoCreateInstance(CLSID_WamAdmin, NULL, CLSCTX_ALL, IID_IWamAdmin, reinterpret_cast<void**>(&piWam));
-                MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IWamAdmin object");
-            }
-
-            hr = CreateAspApp(&pwz, piWam);
-            ExitOnFailure(hr, "failed to create ASP App");
-            break;
-        case MBA_DELETEAPP:
-            if (NULL == piMetabase)
-            {
-                hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase));
-                MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IIMSAdminBase object");
-            }
-
-            if (NULL == pCatalog)
-            {
-                hr = CoCreateInstance(CLSID_COMAdminCatalog, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pCatalog);
-                MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_ICOMAdmin object");
-
-                hr = pCatalog->GetCollection(bstrApplications, reinterpret_cast<IDispatch**>(&pApplicationCollection));
-                if (FAILED(hr))
-                {
-                    hr = S_OK;
-                    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);
-                }
-            }
-
-            if (NULL == piWam)
-            {
-                hr = ::CoCreateInstance(CLSID_WamAdmin, NULL, CLSCTX_ALL, IID_IWamAdmin, reinterpret_cast<void**>(&piWam));
-                MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IWamAdmin object");
-            }
-
-            hr = DeleteAspApp(&pwz, piMetabase, pApplicationCollection, piWam);
-            ExitOnFailure(hr, "failed to delete ASP App");
-            break;
-        case MBA_CREATEKEY:
-            if (NULL == piMetabase)
-            {
-                hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase));
-                MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IIMSAdminBase object");
-            }
-
-            hr = CreateMetabaseKey(&pwz, piMetabase);
-            ExitOnFailure(hr, "failed to create metabase key");
-            break;
-        case MBA_DELETEKEY:
-            if (NULL == piMetabase)
-            {
-                hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase));
-                MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IIMSAdminBase object");
-            }
-
-            hr = DeleteMetabaseKey(&pwz, piMetabase);
-            ExitOnFailure(hr, "failed to delete metabase key");
-            break;
-        case MBA_WRITEVALUE:
-            if (NULL == piMetabase)
-            {
-                hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase));
-                MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IIMSAdminBase object");
-            }
-
-            hr = WriteMetabaseValue(&pwz, piMetabase);
-            ExitOnFailure(hr, "failed to write metabase value");
-            break;
-        case MBA_DELETEVALUE:
-            if (NULL == piMetabase)
-            {
-                hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase));
-                MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IIMSAdminBase object");
-            }
-
-            hr = DeleteMetabaseValue(&pwz, piMetabase);
-            ExitOnFailure(hr, "failed to delete metabase value");
-            break;
-        default:
-            ExitOnFailure(hr = E_UNEXPECTED, "Unexpected metabase action specified: %d", maAction);
-            break;
-        }
-    }
-    if (E_NOMOREITEMS == hr) // If there are no more items, all is well
-    {
-        if (NULL != piMetabase)
-        {
-            hr = piMetabase->SaveData();
-            for (int i = 30; i > 0 && HRESULT_FROM_WIN32(ERROR_PATH_BUSY) == hr; i--)
-            {
-                ::Sleep(1000);
-                WcaLog(LOGMSG_VERBOSE, "Failed to force save of metabase data, retrying %d time(s)...", i);
-                hr = piMetabase->SaveData();
-            }
-            if (FAILED(hr))
-            {
-                WcaLog(LOGMSG_VERBOSE, "Failed to force save of metabase data: 0x%x - continuing", hr);
-            }
-            hr = S_OK;
-        }
-        else
-        {
-            hr = S_OK;
-        }
-    }
-
-LExit:
-    WcaCaScriptClose(hWriteMetabaseScript, WCA_CASCRIPT_CLOSE_DELETE);
-
-    ReleaseBSTR(bstrApplications);
-    ReleaseStr(pwzScriptKey);
-    ReleaseStr(pwzData);
-    ReleaseObject(piMetabase);
-    ReleaseObject(piWam);
-    ReleaseObject(pCatalog);
-    ReleaseObject(pApplicationCollection);
-
-    if (fInitializedCom)
-    {
-        ::CoUninitialize();
-    }
-
-    if (FAILED(hr))
-    {
-        er = ERROR_INSTALL_FAILURE;
-    }
-    return WcaFinalize(er);
-}
-/********************************************************************
- WriteIIS7ConfigChanges - CUSTOM ACTION ENTRY POINT for IIS7 config changes
-
- *******************************************************************/
-extern "C" UINT __stdcall WriteIIS7ConfigChanges(MSIHANDLE hInstall)
-{
-    //AssertSz(FALSE, "debug WriteIIS7ConfigChanges here");
-    HRESULT hr = S_OK;
-    UINT er = ERROR_SUCCESS;
-    LPWSTR pwzData = NULL;
-    LPWSTR pwzScriptKey = NULL;
-    LPWSTR pwzHashString = NULL;
-    BYTE rgbActualHash[SHA1_HASH_LEN] = { };
-    DWORD dwHashedBytes = SHA1_HASH_LEN;
-
-    WCA_CASCRIPT_HANDLE hWriteIis7Script = NULL;
-
-    hr = WcaInitialize(hInstall, "WriteIIS7ConfigChanges");
-    ExitOnFailure(hr, "Failed to initialize");
-
-    hr = WcaGetProperty( L"CustomActionData", &pwzScriptKey);
-    ExitOnFailure(hr, "Failed to get CustomActionData");
-    WcaLog(LOGMSG_TRACEONLY, "Script WriteIIS7ConfigChanges: %ls", pwzScriptKey);
-
-    hr = WcaCaScriptOpen(WCA_ACTION_INSTALL, WCA_CASCRIPT_SCHEDULED, FALSE, pwzScriptKey, &hWriteIis7Script);
-    ExitOnFailure(hr, "Failed to open CaScript file");
-
-    hr = WcaCaScriptReadAsCustomActionData(hWriteIis7Script, &pwzData);
-    ExitOnFailure(hr, "Failed to read script into CustomAction data.");
-
-    hr = CrypHashBuffer((BYTE*)pwzData, sizeof(pwzData) * sizeof(WCHAR), PROV_RSA_AES, CALG_SHA1, rgbActualHash, dwHashedBytes);
-    ExitOnFailure(hr, "Failed to calculate hash of CustomAction data.");
-
-    hr = StrAlloc(&pwzHashString, ((dwHashedBytes * 2) + 1));
-    ExitOnFailure(hr, "Failed to allocate string for script hash");
-
-    hr = StrHexEncode(rgbActualHash, dwHashedBytes, pwzHashString, ((dwHashedBytes * 2) + 1));
-    ExitOnFailure(hr, "Failed to convert hash bytes to string.");
-
-    WcaLog(LOGMSG_TRACEONLY, "CustomActionData WriteIIS7ConfigChanges: %ls", pwzData);
-    WcaLog(LOGMSG_VERBOSE,  "Custom action data hash: %ls", pwzHashString);
-    WcaLog(LOGMSG_VERBOSE, "CustomActionData WriteIIS7ConfigChanges length: %d", wcslen(pwzData));
-
-    hr = IIS7ConfigChanges(hInstall, pwzData);
-    ExitOnFailure(hr, "WriteIIS7ConfigChanges Failed.");
-
-LExit:
-    WcaCaScriptClose(hWriteIis7Script, WCA_CASCRIPT_CLOSE_DELETE);
-    ReleaseStr(pwzScriptKey);
-    ReleaseStr(pwzData);
-    ReleaseStr(pwzHashString);
-
-    if (FAILED(hr))
-    {
-        er = ERROR_INSTALL_FAILURE;
-    }
-
-    return WcaFinalize(er);
-}
-
-
-/********************************************************************
- CommitIIS7ConfigTransaction - CUSTOM ACTION ENTRY POINT for unbacking up config
-
-  Input:  deferred CustomActionData - BackupName
- * *****************************************************************/
-extern "C" UINT __stdcall CommitIIS7ConfigTransaction(MSIHANDLE hInstall)
-{
-    HRESULT hr = S_OK;
-    UINT er = ERROR_SUCCESS;
-    LPWSTR pwzData = NULL;
-    WCHAR wzConfigCopy[MAX_PATH];
-    DWORD dwSize = 0;
-
-    BOOL fIsWow64Process = FALSE;
-    BOOL fIsFSRedirectDisabled = FALSE;
-
-    hr = WcaInitialize(hInstall, "CommitIIS7ConfigTransaction");
-    ExitOnFailure(hr, "failed to initialize IIS7 commit transaction");
-
-    WcaInitializeWow64();
-    fIsWow64Process = WcaIsWow64Process();
-    if (fIsWow64Process)
-    {
-        hr = WcaDisableWow64FSRedirection();
-        if(FAILED(hr))
-        {
-            //eat this error
-            hr = S_OK;
-        }
-        else
-        {
-            fIsFSRedirectDisabled = TRUE;
-        }
-    }
-
-    hr = WcaGetProperty( L"CustomActionData", &pwzData);
-    ExitOnFailure(hr, "failed to get CustomActionData");
-
-    // Config AdminMgr changes already committed, just
-    // delete backup config file.
-
-    dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\applicationHost.config",
-                                      wzConfigCopy,
-                                      MAX_PATH
-                                      );
-    if ( dwSize == 0 )
-    {
-        ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings");
-    }
-
-    hr = ::StringCchCatW(wzConfigCopy, MAX_PATH, L".");
-    ExitOnFailure(hr, "Commit IIS7 failed StringCchCatW of .");
-
-    hr = ::StringCchCatW(wzConfigCopy, MAX_PATH, pwzData);
-    ExitOnFailure(hr, "Commit IIS7 failed StringCchCatW of extension");
-
-    if (!::DeleteFileW(wzConfigCopy))
-    {
-        hr = HRESULT_FROM_WIN32(GetLastError());
-        if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr ||
-            HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
-        {
-            WcaLog(LOGMSG_STANDARD, "Failed to delete backup applicationHost, not found - continuing");
-            hr = S_OK;
-        }
-        else
-        {
-            ExitOnFailure(hr, "failed to delete config backup");
-        }
-    }
-
-LExit:
-    ReleaseStr(pwzData);
-
-    // Make sure we revert FS Redirection if necessary before exiting
-    if (fIsFSRedirectDisabled)
-    {
-        fIsFSRedirectDisabled = FALSE;
-        WcaRevertWow64FSRedirection();
-    }
-    WcaFinalizeWow64();
-
-
-    if (FAILED(hr))
-    {
-        er = ERROR_INSTALL_FAILURE;
-    }
-    return WcaFinalize(er);
-}
-/********************************************************************
- StartIIS7Config Transaction - CUSTOM ACTION ENTRY POINT for backing up config
-
-  Input:  deferred CustomActionData - BackupName
-********************************************************************/
-extern "C" UINT __stdcall StartIIS7ConfigTransaction(MSIHANDLE hInstall)
-{
-    HRESULT hr = S_OK;
-    UINT er = ERROR_SUCCESS;
-    LPWSTR pwzData = NULL;
-    WCHAR wzConfigSource[MAX_PATH];
-    WCHAR wzConfigCopy[MAX_PATH];
-    DWORD dwSize = 0;
-
-
-    BOOL fIsWow64Process = FALSE;
-    BOOL fIsFSRedirectDisabled = FALSE;
-
-    // initialize
-    hr = WcaInitialize(hInstall, "StartIIS7ConfigTransaction");
-    ExitOnFailure(hr, "failed to initialize StartIIS7ConfigTransaction");
-
-    WcaInitializeWow64();
-    fIsWow64Process = WcaIsWow64Process();
-    if (fIsWow64Process)
-    {
-        hr = WcaDisableWow64FSRedirection();
-        if(FAILED(hr))
-        {
-            //eat this error
-            hr = S_OK;
-        }
-        else
-        {
-            fIsFSRedirectDisabled = TRUE;
-        }
-    }
-
-    hr = WcaGetProperty(L"CustomActionData", &pwzData);
-    ExitOnFailure(hr, "failed to get CustomActionData");
-
-
-    dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\applicationHost.config",
-                                      wzConfigSource,
-                                      MAX_PATH
-                                      );
-    if ( dwSize == 0 )
-    {
-        ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings");
-    }
-    hr = ::StringCchCopyW(wzConfigCopy, MAX_PATH, wzConfigSource);
-    ExitOnFailure(hr, "Commit IIS7 failed StringCchCopyW");
-
-    //add ca action as extension
-
-    hr = ::StringCchCatW(wzConfigCopy, MAX_PATH, L".");
-    ExitOnFailure(hr, "Commit IIS7 failed StringCchCatW of .");
-
-    hr = ::StringCchCatW(wzConfigCopy, MAX_PATH, pwzData);
-    ExitOnFailure(hr, "Commit IIS7 failed StringCchCatW of extension");
-
-    if ( !::CopyFileW(wzConfigSource, wzConfigCopy, FALSE) )
-    {
-        hr = HRESULT_FROM_WIN32(GetLastError());
-        if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr ||
-            HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
-        {
-            // IIS may not be installed on the machine, we'll fail later if we try to install anything
-            WcaLog(LOGMSG_STANDARD, "Failed to back up applicationHost, not found - continuing");
-            hr = S_OK;
-        }
-        else
-        {
-            ExitOnFailure(hr, "Failed to copy config backup %ls -> %ls", wzConfigSource, wzConfigCopy);
-        }
-    }
-
-
-    hr = WcaProgressMessage(COST_IIS_TRANSACTIONS, FALSE);
-
-
-LExit:
-
-    ReleaseStr(pwzData);
-
-    // Make sure we revert FS Redirection if necessary before exiting
-    if (fIsFSRedirectDisabled)
-    {
-        fIsFSRedirectDisabled = FALSE;
-        WcaRevertWow64FSRedirection();
-    }
-    WcaFinalizeWow64();
-
-    if (FAILED(hr))
-        er = ERROR_INSTALL_FAILURE;
-    return WcaFinalize(er);
-}
-
-
-/********************************************************************
- RollbackIIS7ConfigTransaction - CUSTOM ACTION ENTRY POINT for unbacking up config
-
-  Input:  deferred CustomActionData - BackupName
-********************************************************************/
-extern "C" UINT __stdcall RollbackIIS7ConfigTransaction(MSIHANDLE hInstall)
-{
-    HRESULT hr = S_OK;
-    UINT er = ERROR_SUCCESS;
-    LPWSTR pwzData = NULL;
-    WCHAR wzConfigSource[MAX_PATH];
-    WCHAR wzConfigCopy[MAX_PATH];
-    DWORD dwSize = 0;
-
-    BOOL fIsWow64Process = FALSE;
-    BOOL fIsFSRedirectDisabled = FALSE;
-
-    hr = WcaInitialize(hInstall, "RollbackIIS7ConfigTransaction");
-    ExitOnFailure(hr, "failed to initialize");
-
-    WcaInitializeWow64();
-    fIsWow64Process = WcaIsWow64Process();
-    if (fIsWow64Process)
-    {
-        hr = WcaDisableWow64FSRedirection();
-        if(FAILED(hr))
-        {
-            //eat this error
-            hr = S_OK;
-        }
-        else
-        {
-            fIsFSRedirectDisabled = TRUE;
-        }
-    }
-
-    hr = WcaGetProperty( L"CustomActionData", &pwzData);
-    ExitOnFailure(hr, "failed to get CustomActionData");
-
-    dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\applicationHost.config",
-                                      wzConfigSource,
-                                      MAX_PATH
-                                      );
-    if ( dwSize == 0 )
-    {
-        ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings");
-    }
-    hr = ::StringCchCopyW(wzConfigCopy, MAX_PATH, wzConfigSource);
-    ExitOnFailure(hr, "Commit IIS7 failed StringCchCopyW");
-
-    //add ca action as extension
-
-    hr = ::StringCchCatW(wzConfigCopy, MAX_PATH, L".");
-    ExitOnFailure(hr, "Commit IIS7 failed StringCchCatW of .");
-
-    hr = ::StringCchCatW(wzConfigCopy, MAX_PATH, pwzData);
-    ExitOnFailure(hr, "Commit IIS7 failed StringCchCatW of extension");
-
-    //copy is reverse of start transaction
-    if (!::CopyFileW(wzConfigCopy, wzConfigSource, FALSE))
-    {
-        hr = HRESULT_FROM_WIN32(GetLastError());
-        if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr ||
-            HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
-        {
-            WcaLog(LOGMSG_STANDARD, "Failed to restore applicationHost, not found - continuing");
-            hr = S_OK;
-        }
-        else
-        {
-            ExitOnFailure(hr, "failed to restore config backup");
-        }
-    }
-
-    if (!::DeleteFileW(wzConfigCopy))
-    {
-        ExitWithLastError(hr, "failed to delete config backup");
-    }
-
-    hr = WcaProgressMessage(COST_IIS_TRANSACTIONS, FALSE);
-
-LExit:
-    ReleaseStr(pwzData);
-
-    // Make sure we revert FS Redirection if necessary before exiting
-    if (fIsFSRedirectDisabled)
-    {
-        fIsFSRedirectDisabled = FALSE;
-        WcaRevertWow64FSRedirection();
-    }
-    WcaFinalizeWow64();
-
-    if (FAILED(hr))
-    {
-        er = ERROR_INSTALL_FAILURE;
-    }
-    return WcaFinalize(er);
-}
diff --git a/src/ca/scaexecIIS7.cpp b/src/ca/scaexecIIS7.cpp
deleted file mode 100644
index 108007a1..00000000
--- a/src/ca/scaexecIIS7.cpp
+++ /dev/null
@@ -1,4205 +0,0 @@
-#pragma once
-// 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.
-
-
-#include "precomp.h"
-
-//local CAData action functions
-HRESULT IIS7Site(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    );
-
-HRESULT IIS7Application(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    );
-HRESULT IIS7VDir(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    );
-HRESULT IIS7Binding(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    );
-HRESULT IIS7AppPool(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    );
-HRESULT IIS7AppExtension(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    );
-HRESULT IIS7MimeMap(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    );
-HRESULT IIS7DirProperties(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    );
-HRESULT IIS7WebLog(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    );
-HRESULT IIS7FilterGlobal(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    );
-HRESULT IIS7FilterSite(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    );
-HRESULT IIS7HttpHeader(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    );
-HRESULT IIS7WebError(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    );
-HRESULT IIS7WebSvcExt(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    );
-HRESULT IIS7WebProperty(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    );
-HRESULT IIS7WebDir(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    );
-HRESULT IIS7AspProperty(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    );
-HRESULT IIS7SslBinding(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    );
-//local helper functions
-
-static HRESULT GetNextAvailableSiteId(
-    IAppHostWritableAdminManager *pAdminMgr,
-    DWORD *plSiteId
-    );
-static HRESULT GetSiteElement(
-    IAppHostWritableAdminManager *pAdminMgr,
-    LPCWSTR swSiteName,
-    IAppHostElement **pSiteElement,
-    BOOL* fFound
-    );
-static HRESULT GetApplicationElement(
-    IAppHostElement *pSiteElement,
-    LPCWSTR swAppPath,
-    IAppHostElement **pAppElement,
-    BOOL* fFound
-    );
-static HRESULT GetApplicationElementForVDir(
-    IAppHostElement *pSiteElement,
-    LPCWSTR swVDirPath,
-    IAppHostElement **ppAppElement,
-    LPCWSTR *ppwzVDirSubPath,
-    BOOL* fFound
-    );
-
-static HRESULT CreateApplication(
-    IAppHostElement *pSiteElement,
-    LPCWSTR swAppPath,
-    IAppHostElement **pAppElement
-    );
-static HRESULT DeleteApplication(
-    IAppHostElement *pSiteElement,
-    LPCWSTR swAppPath
-    );
-
-static HRESULT SetAppPool(
-    IAppHostElement *pAppElementpAppElement,
-    LPCWSTR pwzAppPool
-    );
-static HRESULT CreateVdir(
-    IAppHostElement *pAppElement,
-    LPCWSTR pwzVDirPath,
-    LPCWSTR pwzVDirPhyDir
-    );
-static HRESULT DeleteVdir(
-    IAppHostElement *pAppElement,
-    LPCWSTR pwzVDirPath
-    );
-
-static HRESULT CreateBinding(
-    IAppHostElement *pSiteElem,
-    LPCWSTR pwzProtocol,
-    LPCWSTR pwzInfo
-    );
-static HRESULT DeleteBinding(
-    IAppHostElement *pSiteElem,
-    LPCWSTR pwzProtocol,
-    LPCWSTR pwzInfo
-    );
-
-static HRESULT CreateSslBinding(
-    IAppHostElement *pSiteElem,
-    LPCWSTR pwzStoreName,
-    LPCWSTR pwzEncodedCertificateHash
-    );
-static HRESULT DeleteSslBinding(
-    IAppHostElement *pSiteElem,
-    LPCWSTR pwzStoreName,
-    LPCWSTR pwzEncodedCertificateHash
-    );
-
-static HRESULT CreateSite(
-    IAppHostElementCollection *pAdminMgr,
-    LPCWSTR swSiteName,
-    IAppHostElement **pSiteElement
-    );
-
-static HRESULT DeleteAppPool(
-    IAppHostWritableAdminManager *pAdminMgr,
-    LPCWSTR swAppPoolName
-    );
-static HRESULT CreateAppPool(
-    __inout LPWSTR *ppwzCustomActionData,
-    IAppHostWritableAdminManager *pAdminMgr,
-    LPCWSTR swAppPoolName
-    );
-
-static HRESULT SetDirPropAuthentications(
-    IAppHostWritableAdminManager *pAdminMgr,
-    LPCWSTR wcConfigPath,
-    DWORD dwData
-    );
-static HRESULT SetDirPropAuthProvider(
-    IAppHostWritableAdminManager *pAdminMgr,
-    LPCWSTR wszConfigPath,
-    __in LPWSTR wszData
-    );
-static HRESULT SetDirPropDefDoc(
-    IAppHostWritableAdminManager *pAdminMgr,
-    LPCWSTR wszConfigPath,
-    __in LPWSTR wszData
-    );
-
-static HRESULT ClearLocationTag(
-    IAppHostWritableAdminManager *pAdminMgr,
-    LPCWSTR swLocationPath
-    );
-
-static HRESULT CreateWebLog(
-    IAppHostElement *pSiteElem,
-    LPCWSTR pwzFormat
-    );
-
-static HRESULT CreateGlobalFilter(
-    __inout LPWSTR *ppwzCustomActionData,
-    IAppHostElement *pSection
-    );
-static HRESULT DeleteGlobalFilter(
-    __inout LPWSTR *ppwzCustomActionData,
-    IAppHostElement *pSection
-    );
-
-static HRESULT CreateSiteFilter(
-    __inout LPWSTR *ppwzCustomActionData,
-    IAppHostWritableAdminManager *pAdminMgr
-    );
-static HRESULT DeleteSiteFilter(
-    __inout LPWSTR *ppwzCustomActionData,
-    IAppHostWritableAdminManager *pAdminMgr
-    );
-
-static HRESULT DeleteCollectionElement(
-    __in IAppHostElementCollection *pCollection,
-    __in LPCWSTR pwzElementName,
-    __in LPCWSTR pwzAttributeName,
-    __in LPCWSTR pwzAttributeValue
-    );
-
-struct SCA_WEB_ERROR_SERVER
-{
-    int iErrorCode;
-    int iSubCode;
-    WCHAR wzFile[MAX_PATH];
-    WCHAR wzLangPath[MAX_PATH];
-    int iResponseMode;
-    SCA_WEB_ERROR_SERVER *psweNext;
-};
-static HRESULT AddWebErrorToList(
-    SCA_WEB_ERROR_SERVER** ppsweList
-    );
-static void ScaWebErrorFreeList7(
-    SCA_WEB_ERROR_SERVER *psweList
-    );
-static HRESULT PopulateHttpErrors(
-    IAppHostElement *pSection,
-    SCA_WEB_ERROR_SERVER **psweList
-    );
-static HRESULT GetErrorFromList(
-    const SCA_WEB_ERROR_SERVER & we,
-    SCA_WEB_ERROR_SERVER **ppsweList,
-    SCA_WEB_ERROR_SERVER **pswe,
-    BOOL *fFound
-    );
-
-static void ConvSecToHMS(
-    int Sec,
-    __out_ecount(cchDest) LPWSTR wcTime,
-    size_t cchDest
-    );
-static void ConvSecToDHMS(
-    unsigned int Sec,
-    __out_ecount(cchDest) LPWSTR wcTime,
-    size_t cchDest
-    );
-
-////////////////////////////////////////////////////////////////////
-// ScopeBSTR: Local helper class to construct & free BSTR from LPWSTR
-//
-/////////////////////////////////////////////////////////////////////
-class ScopeBSTR
-{
-public:
-    BSTR m_str;
-
-    ScopeBSTR()
-    {
-        m_str = NULL;
-    }
-
-    ScopeBSTR( __in LPCWSTR pSrc)
-    {
-        if (pSrc == NULL)
-        {
-            m_str = NULL;
-        }
-        else
-        {
-            m_str = ::SysAllocString(pSrc);
-
-        }
-    }
-
-    ~ScopeBSTR()
-    {
-        ::SysFreeString(m_str);
-    }
-
-    operator BSTR()
-    {
-        return m_str;
-    }
-};
-
-
-/********************************************************************
- IIS7ConfigChanges - Start of IIS7 config changes
-
- *******************************************************************/
-HRESULT IIS7ConfigChanges(MSIHANDLE /*hInstall*/, __inout LPWSTR pwzData)
-{
-    HRESULT hr = S_OK;
-    BOOL fInitializedCom = FALSE;
-
-    IAppHostWritableAdminManager *pAdminMgr = NULL;
-
-    LPWSTR pwz = NULL;
-    LPWSTR pwzLast = NULL;
-    LPWSTR pwzBackup = NULL;
-    DWORD cchData = lstrlenW(pwzData);
-    int iAction = -1;
-
-    int iRetryCount = 0;
-
-    hr = ::CoInitialize(NULL);
-    ExitOnFailure(hr, "Failed to initialize COM");
-    fInitializedCom = TRUE;
-
-    pwz = pwzLast = pwzData;
-
-    hr = StrAllocString(&pwzBackup, pwz, 0);
-    ExitOnFailure(hr, "Failed to backup custom action data");
-
-    while (S_OK == (hr = WcaReadIntegerFromCaData(&pwz, &iAction)))
-    {
-        if (NULL == pAdminMgr)
-        {
-            hr = ::CoCreateInstance( __uuidof(AppHostWritableAdminManager),
-                                    NULL,
-                                    CLSCTX_INPROC_SERVER,
-                                    __uuidof(IAppHostWritableAdminManager),
-                                    reinterpret_cast<void**> (&pAdminMgr));
-            ExitOnFailure(hr , "Failed to open AppHostWritableAdminManager to configure IIS7");
-        }
-
-        switch (iAction)
-        {
-        case IIS_SITE:
-            {
-#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
-                hr = IIS7Site(&pwz, pAdminMgr);
-                ExitOnFailure(hr, "Failed to configure IIS site.");
-                break;
-            }
-        case IIS_APPLICATION:
-            {
-#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
-                hr = IIS7Application(&pwz, pAdminMgr);
-                ExitOnFailure(hr, "Failed to configure IIS application.");
-                break;
-            }
-        case IIS_VDIR:
-            {
-#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
-                hr = IIS7VDir(&pwz, pAdminMgr);
-                ExitOnFailure(hr, "Failed to configure IIS VDir.");
-                break;
-            }
-        case IIS_BINDING:
-            {
-#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
-                hr = IIS7Binding(&pwz, pAdminMgr);
-                ExitOnFailure(hr, "Failed to configure IIS site binding.");
-                break;
-            }
-        case IIS_APPPOOL:
-            {
-#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
-                hr = IIS7AppPool(&pwz, pAdminMgr);
-                ExitOnFailure(hr, "Failed to configure IIS appPool.");
-                break;
-            }
-        case IIS_APPEXT_BEGIN:
-            {
-#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
-                hr = IIS7AppExtension(&pwz, pAdminMgr);
-                ExitOnFailure(hr, "Failed to configure IIS AppExtension.");
-                break;
-            }
-        case IIS_MIMEMAP_BEGIN:
-            {
-#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
-                hr = IIS7MimeMap(&pwz, pAdminMgr);
-                ExitOnFailure(hr, "Failed to configure IIS MimeMap.");
-                break;
-            }
-        case IIS_DIRPROP_BEGIN:
-            {
-#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
-                hr = IIS7DirProperties(&pwz, pAdminMgr);
-                ExitOnFailure(hr, "Failed to configure IIS DirProperties.");
-                break;
-            }
-        case IIS_WEBLOG:
-            {
-#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
-                hr = IIS7WebLog(&pwz, pAdminMgr);
-                ExitOnFailure(hr, "Failed to configure IIS WebLog.");
-                break;
-            }
-        case IIS_FILTER_GLOBAL_BEGIN:
-            {
-#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
-                hr = IIS7FilterGlobal(&pwz, pAdminMgr);
-                ExitOnFailure(hr, "Failed to configure IIS filter global.");
-                break;
-            }
-        case IIS_FILTER_BEGIN:
-            {
-#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
-                hr = IIS7FilterSite(&pwz, pAdminMgr);
-                ExitOnFailure(hr, "Failed to configure IIS Filter.");
-                break;
-            }
-        case IIS_HTTP_HEADER_BEGIN:
-            {
-#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
-                hr = IIS7HttpHeader(&pwz, pAdminMgr);
-                ExitOnFailure(hr, "Failed to configure IIS http Header.");
-                break;
-            }
-        case IIS_WEBERROR_BEGIN:
-            {
-#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
-                hr = IIS7WebError(&pwz, pAdminMgr);
-                ExitOnFailure(hr, "Failed to configure IIS http Errors.");
-                break;
-            }
-        case IIS_WEB_SVC_EXT:
-            {
-#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
-                hr = IIS7WebSvcExt(&pwz, pAdminMgr);
-                ExitOnFailure(hr, "Failed to configure IIS web svc ext.");
-                break;
-            }
-        case IIS_PROPERTY:
-            {
-#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
-                hr = IIS7WebProperty(&pwz, pAdminMgr);
-                ExitOnFailure(hr, "Failed to configure IIS web property.");
-                break;
-            }
-        case IIS_WEBDIR:
-            {
-#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
-                hr = IIS7WebDir(&pwz, pAdminMgr);
-                ExitOnFailure(hr, "Failed to configure IIS web directory.");
-                break;
-            }
-        case IIS_ASP_BEGIN:
-            {
-#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
-                hr = IIS7AspProperty(&pwz, pAdminMgr);
-                ExitOnFailure(hr, "Failed to configure IIS Asp property.");
-                break;
-            }
-        case IIS_SSL_BINDING:
-#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
-                hr = IIS7SslBinding(&pwz, pAdminMgr);
-                ExitOnFailure(hr, "Failed to configure IIS SSL binding.");
-                break;
-
-        default:
-            ExitOnFailure(hr = E_UNEXPECTED, "IIS7ConfigChanges: Unexpected IIS Config action specified: %d", iAction);
-            break;
-        }
-        if (S_OK == hr)
-        {
-            // commit config changes now to close out IIS Admin changes,
-            // the Rollback or Commit defered CAs will determine final commit status.
-            hr = pAdminMgr->CommitChanges();
-
-            // Our transaction may have been interrupted.
-            if (hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) || hr == HRESULT_FROM_WIN32(ERROR_TRANSACTIONAL_CONFLICT))
-            {
-                WcaLog(LOGMSG_VERBOSE, "Sharing violation or transactional conflict during attempt to save changes to applicationHost.config");
-                if (++iRetryCount > 30)
-                {
-                    if (IDRETRY == WcaErrorMessage(msierrIISFailedCommitInUse, hr, INSTALLMESSAGE_ERROR | MB_RETRYCANCEL, 0))
-                    {
-                        iRetryCount = 0;
-                    }
-                    else
-                    {
-                        ExitOnFailure(hr, "Failed to Commit IIS Config Changes, in silent mode or user has chosen to cancel");
-                    }
-                }
-
-                // Throw away the changes since IIS has no way to remove uncommited changes from an AdminManager.
-                ReleaseNullObject(pAdminMgr);
-
-                // Restore our CA data backup
-                pwz = pwzLast;
-                hr = ::StringCchCopyW(pwz, cchData - (pwz - pwzData) + 1, pwzBackup);
-                ExitOnFailure(hr , "Failed to restore custom action data backup");
-
-            }
-            else if (FAILED(hr))
-            {
-                ExitOnFailure(hr , "Failed to Commit IIS Config Changes");
-            }
-            else
-            {
-                // store a backup of CA data @ the last place that we successfully commited changes unless we are done.
-                if(NULL != pwz)
-                {
-                    pwzLast = pwz;
-                    hr = StrAllocString(&pwzBackup, pwz, 0);
-                    ExitOnFailure(hr, "Failed to backup custom action data");
-                }
-            }
-        }
-    }
-    if (E_NOMOREITEMS == hr) // If there are no more items, all is well
-    {
-        hr = S_OK;
-    }
-LExit:
-    ReleaseObject(pAdminMgr);
-    ReleaseStr(pwzBackup);
-
-    if (fInitializedCom)
-    {
-        ::CoUninitialize();
-    }
-
-    return hr;
-}
-//-------------------------------------------------------------------------------------------------
-// IIS7AspProperty
-// Called by WriteIIS7ConfigChanges
-// Processes asp properties for WebApplication
-//
-//-------------------------------------------------------------------------------------------------
-
-HRESULT IIS7AspProperty(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    )
-{
-    HRESULT hr = S_OK;
-
-    int iAction = -1;
-    int iData   =  0;
-
-    LPWSTR pwzData = NULL;
-    LPWSTR pwzSiteName = NULL;
-    LPWSTR pwzPathName = NULL;
-    LPWSTR pwzLocationPath = NULL;
-    WCHAR wcTime[60];
-
-    IAppHostElement *pSection = NULL;
-    IAppHostElement *pElement = NULL;
-
-    //read web site key
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
-    ExitOnFailure(hr, "Failed read webDir webkey");
-
-    //read path key
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzPathName);
-    ExitOnFailure(hr, "Failed read webDir path");
-
-    //Construct Location path
-    hr = StrAllocFormatted(&pwzLocationPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzSiteName);
-    ExitOnFailure(hr, "failed to format webDir location");
-    //
-    //Do not append trailing '/' for default vDir
-    //
-    if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzPathName, -1, L"/", -1))
-    {
-        hr = StrAllocConcat(&pwzLocationPath, L"/", 0);
-        ExitOnFailure(hr, "failed to copy location WebDir '/'");
-        hr = StrAllocConcat(&pwzLocationPath, pwzPathName, 0);
-        ExitOnFailure(hr, "failed to copy location WebDir path");
-    }
-
-    //get asp section at config path location tag
-    hr = pAdminMgr->GetAdminSection( ScopeBSTR(IIS_CONFIG_ASP_SECTION), pwzLocationPath, &pSection);
-    ExitOnFailure(hr, "Failed get httpErrors section");
-
-    // Get  action
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-    ExitOnFailure(hr, "Failed to read property action");
-
-    while (IIS_ASP_END != iAction)
-    {
-        switch (iAction)
-        {
-            case IIS_ASP_SESSIONSTATE:
-            {
-                //system.webServer/asp /session | allowSessionState
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read asp session state");
-                hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_SESSION), &pElement);
-                ExitOnFailure(hr, "Failed to get asp session element");
-                hr = Iis7PutPropertyBool( pElement, IIS_CONFIG_ALLOWSTATE, iData);
-                ExitOnFailure(hr, "Failed to put asp session value");
-                ReleaseNullObject(pElement);
-                break;
-            }
-            case IIS_ASP_SESSIONTIMEOUT:
-            {
-                //system.webServer/asp /session | timeout
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read asp session timeout");
-                hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_SESSION), &pElement);
-                ExitOnFailure(hr, "Failed to get asp session timeout");
-                *wcTime = '\0';
-                ConvSecToHMS(iData * 60, wcTime, countof( wcTime));
-                hr = Iis7PutPropertyString( pElement, IIS_CONFIG_TIMEOUT, wcTime);
-                ExitOnFailure(hr, "Failed to put asp timeout value");
-                ReleaseNullObject(pElement);
-                break;
-            }
-            case IIS_ASP_BUFFER:
-            {
-                //system.webServer/asp | bufferingOn
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read asp bufferingOn");
-                hr = Iis7PutPropertyBool( pSection, IIS_CONFIG_BUFFERING, iData);
-                ExitOnFailure(hr, "Failed to put asp bufferingOn value");
-                break;
-            }
-            case IIS_ASP_PARENTPATHS:
-            {
-                //system.webServer/asp | enableParentPaths
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read asp ParentPaths");
-                hr = Iis7PutPropertyBool( pSection, IIS_CONFIG_PARENTPATHS, iData);
-                ExitOnFailure(hr, "Failed to put asp ParentPaths value");
-                break;
-            }
-            case IIS_ASP_SCRIPTLANG:
-            {
-                //system.webServer/asp | scriptLanguage
-                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-                ExitOnFailure(hr, "Failed to read asp scriptLanguage");
-                hr = Iis7PutPropertyString( pSection, IIS_CONFIG_SCRIPTLANG, pwzData);
-                ExitOnFailure(hr, "Failed to put asp scriptLanguage value");
-                break;
-            }
-            case IIS_ASP_SCRIPTTIMEOUT:
-            {
-                //system.webServer/asp /limits | scriptTimeout
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read asp scriptTimeout");
-                hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_LIMITS), &pElement);
-                ExitOnFailure(hr, "Failed to get asp session element");
-                *wcTime = '\0';
-                ConvSecToHMS(iData, wcTime, countof( wcTime));
-                hr = Iis7PutPropertyString( pElement, IIS_CONFIG_SCRIPTTIMEOUT, wcTime);
-                ExitOnFailure(hr, "Failed to put asp scriptTimeout value");
-                ReleaseNullObject(pElement);
-                break;
-
-            }
-            case IIS_ASP_SCRIPTSERVERDEBUG:
-            {
-                //system.webServer/asp | appAllowDebugging
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read asp appAllowDebugging");
-                hr = Iis7PutPropertyBool( pSection, IIS_CONFIG_ALLOWDEBUG, iData);
-                ExitOnFailure(hr, "Failed to put asp appAllowDebugging value");
-                break;
-            }
-            case IIS_ASP_SCRIPTCLIENTDEBUG:
-            {
-                //system.webServer/asp | appAllowClientDebug
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read asp appAllowClientDebug");
-                hr = Iis7PutPropertyBool( pSection, IIS_CONFIG_ALLOWCLIENTDEBUG, iData);
-                ExitOnFailure(hr, "Failed to put asp appAllowClientDebug value");
-                break;
-            }
-            default:
-            {
-                ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for asp properties");
-                break;
-            }
-        }
-        // Get next action
-        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-        ExitOnFailure(hr, "Failed to read asp prop action");
-    }
-
-LExit:
-    ReleaseStr(pwzData);
-    ReleaseStr(pwzSiteName);
-    ReleaseStr(pwzPathName);
-    ReleaseStr(pwzLocationPath);
-    ReleaseObject(pSection);
-    ReleaseObject(pElement);
-
-    return hr;
-}
-
-//-------------------------------------------------------------------------------------------------
-// IIS7WebDir
-// Called by WriteIIS7ConfigChanges
-// Processes WebDir
-//
-//-------------------------------------------------------------------------------------------------
-HRESULT IIS7WebDir(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    )
-{
-    HRESULT hr = S_OK;
-
-    int iAction = -1;
-
-    LPWSTR pwzSiteName = NULL;
-    LPWSTR pwzPathName = NULL;
-    LPWSTR pwzLocationPath = NULL;
-
-    // Get  action
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-    ExitOnFailure(hr, "Failed to read property action");
-
-    //read web site key
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
-    ExitOnFailure(hr, "Failed read webDir webkey");
-
-    //read path key
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzPathName);
-    ExitOnFailure(hr, "Failed read webDir path");
-
-    switch (iAction)
-    {
-        case IIS_CREATE:
-        {
-            //no action needed for create since WebDir has a
-            //WebDirProperties element that will create and populate
-            //location tag
-            break;
-        }
-        case IIS_DELETE:
-        {
-            //Construct Location path
-            hr = StrAllocString(&pwzLocationPath, pwzSiteName, 0);
-            ExitOnFailure(hr, "failed to copy location WebDir web name");
-            //
-            //Do not append trailing '/' for default vDir
-            //
-            if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzPathName, -1, L"/", -1))
-            {
-                hr = StrAllocConcat(&pwzLocationPath, L"/", 0);
-                ExitOnFailure(hr, "failed to copy location WebDir '/'");
-                hr = StrAllocConcat(&pwzLocationPath, pwzPathName, 0);
-                ExitOnFailure(hr, "failed to copy location WebDir path");
-            }
-            // and delete location tag for this application
-            hr = ClearLocationTag(pAdminMgr, pwzLocationPath);
-            ExitOnFailure(hr, "failed to clear location tag for %ls", pwzLocationPath)
-            break;
-        }
-        default:
-        {
-            ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for WebDir");
-            break;
-        }
-    }
-LExit:
-    ReleaseStr(pwzSiteName);
-    ReleaseStr(pwzPathName);
-    ReleaseStr(pwzLocationPath);
-
-    return hr;
-}
-
-//-------------------------------------------------------------------------------------------------
-// IIS7WebProperty
-// Called by WriteIIS7ConfigChanges
-// Processes isapiCgiRestriction
-//
-//-------------------------------------------------------------------------------------------------
-HRESULT IIS7WebProperty(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    )
-{
-    HRESULT hr = S_OK;
-
-    int iAction = -1;
-    int iData   =  0;
-
-    IAppHostElement *pSection = NULL;
-
-    // Get  action
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-    ExitOnFailure(hr, "Failed to read property action");
-
-    switch (iAction)
-    {
-        case IIS_PROPERTY_MAXBAND:
-        {
-            hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-            ExitOnFailure(hr, "Failed to read property max band");
-            //set value at system.applicationHost/webLimits | maxGlobalBandwidth
-            //Get IIS config section
-            hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_WEBLIMITS_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pSection);
-            ExitOnFailure(hr, "Failed get isapiCgiRestriction section");
-            if (!pSection)
-            {
-                hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-                ExitOnFailure(hr, "Failed get isapiCgiRestriction section object");
-            }
-            hr = Iis7PutPropertyInteger(pSection, IIS_CONFIG_WEBLIMITS_MAXBAND, iData);
-
-            break;
-        }
-        case IIS_PROPERTY_LOGUTF8:
-        {
-            hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-            ExitOnFailure(hr, "Failed to read property log");
-            //set value at system.applicationHost/log | logInUTF8
-            //Get IIS config section
-            hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_LOG_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pSection);
-            ExitOnFailure(hr, "Failed get isapiCgiRestriction section");
-            if (!pSection)
-            {
-                hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-                ExitOnFailure(hr, "Failed get isapiCgiRestriction section object");
-            }
-            hr = Iis7PutPropertyBool(pSection, IIS_CONFIG_LOG_UTF8, iData);
-
-            break;
-        }
-        default:
-        {
-            ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for Web Property");
-            break;
-        }
-    }
-
-LExit:
-    ReleaseObject(pSection);
-
-    return hr;
-}
-
-//-------------------------------------------------------------------------------------------------
-// IIS7WebSvcExt
-// Called by WriteIIS7ConfigChanges
-// Processes isapiCgiRestriction
-//
-//-------------------------------------------------------------------------------------------------
-HRESULT IIS7WebSvcExt(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    )
-{
-    HRESULT hr = S_OK;
-
-    int iAction = -1;
-    int iData   =  0;
-    BOOL fFound = FALSE;
-    LPWSTR pwzData = NULL;
-    LPWSTR pwzPath = NULL;
-
-    IAppHostElement *pSection = NULL;
-    IAppHostElement *pElement = NULL;
-    IAppHostElementCollection *pCollection = NULL;
-
-    // Get  action
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-    ExitOnFailure(hr, "Failed to read WebSvcExt action");
-
-    //get path
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzPath);
-    ExitOnFailure(hr, "Failed to read WebSvcExt key");
-
-    //Get IIS config section
-    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_RESTRICTION_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pSection);
-    ExitOnFailure(hr, "Failed get isapiCgiRestriction section");
-    if (!pSection)
-    {
-        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-        ExitOnFailure(hr, "Failed get isapiCgiRestriction section object");
-    }
-    //get collection
-    hr = pSection->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get isapiCgiRestriction collection");
-
-    //find element
-    hr = Iis7FindAppHostElementPath(pCollection, IIS_CONFIG_ADD, IIS_CONFIG_PATH, pwzPath, &pElement, NULL);
-    ExitOnFailure(hr, "Failed get isapiCgiRestriction element");
-    fFound = (NULL != pElement);
-
-    switch (iAction)
-    {
-        case IIS_CREATE:
-        {
-            if (!fFound)
-            {
-                //create a restriction element
-                hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pElement);
-                ExitOnFailure(hr, "Failed create isapiCgiRestriction element");
-                //put path
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PATH, pwzPath);
-                ExitOnFailure(hr, "Failed set isapiCgiRestriction path property");
-            }
-            //update common properties
-
-            //update allowed
-            hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-            ExitOnFailure(hr, "Failed to read WebSvcExt allowed");
-            hr = Iis7PutPropertyBool(pElement, IIS_CONFIG_ALLOWED, iData);
-            ExitOnFailure(hr, "Failed set isapiCgiRestriction allowed property");
-
-            //update groupId
-            hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-            ExitOnFailure(hr, "Failed to read WebSvcExt group ID");
-            if (*pwzData)
-            {
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_GROUPID, pwzData);
-                ExitOnFailure(hr, "Failed set isapiCgiRestriction groupId property");
-            }
-            //update description
-            hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-            ExitOnFailure(hr, "Failed to read WebSvcExt description");
-            if (*pwzData)
-            {
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_DESC, pwzData);
-                ExitOnFailure(hr, "Failed set isapiCgiRestriction description property");
-            }
-            // add element if new
-            if (!fFound)
-            {
-                hr = pCollection->AddElement(pElement);
-                ExitOnFailure(hr, "Failed add isapiCgiRestriction element");
-            }
-
-            break;
-        }
-        case IIS_DELETE:
-        {
-            hr = DeleteCollectionElement(pCollection, IIS_CONFIG_ADD, IIS_CONFIG_PATH, pwzPath);
-            ExitOnFailure(hr, "Failed delete isapiCgiRestriction element");
-            break;
-        }
-        default:
-        {
-            ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for WebSvcExt");
-            break;
-        }
-    }
-
-LExit:
-    ReleaseStr(pwzPath);
-    ReleaseStr(pwzData);
-    ReleaseObject(pSection);
-    ReleaseObject(pElement);
-    ReleaseObject(pCollection);
-
-    return hr;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-// IIS7WebError
-// Called by WriteIIS7ConfigChanges
-// Processes http header CA Data
-//
-//-------------------------------------------------------------------------------------------------
-
-HRESULT IIS7WebError(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    )
-{
-    HRESULT hr = S_OK;
-    LPWSTR pwzConfigPath = NULL;
-    LPWSTR pwzSiteName = NULL;
-    LPWSTR pwzAppName = NULL;
-
-    IAppHostElement *pElement = NULL;
-    IAppHostElement *pSection = NULL;
-    IAppHostElementCollection *pCollection = NULL;
-
-    SCA_WEB_ERROR_SERVER *psweList = NULL;
-    SCA_WEB_ERROR_SERVER* pswe = NULL;
-    SCA_WEB_ERROR_SERVER we;
-    BOOL fFound = FALSE;
-
-    int iAction = -1;
-    LPWSTR pwzData = NULL;
-
-    //read web site key
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
-    ExitOnFailure(hr, "Failed read web error site name");
-
-    //read app key
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzAppName);
-    ExitOnFailure(hr, "Failed read web error app name");
-
-    //Construct config root path
-    hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzSiteName);
-    ExitOnFailure(hr, "failed to format web error config path");
-
-    if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzAppName, -1, L"/", -1))
-    {
-        hr = StrAllocConcat(&pwzConfigPath, L"/", 0);
-        ExitOnFailure(hr, "failed to copy web error config path delim");
-        hr = StrAllocConcat(&pwzConfigPath, pwzAppName, 0);
-        ExitOnFailure(hr, "failed to app name to web error config path");
-    }
-
-    //get httpErrors section at config path location tag
-    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_HTTPERRORS_SECTION), pwzConfigPath, &pSection);
-    ExitOnFailure(hr, "Failed get httpErrors section");
-
-    //get existing httpErrors list & clear collection
-    hr = PopulateHttpErrors(pSection, &psweList);
-    ExitOnFailure(hr, "Failed to read httpErrors list");
-
-    //get collection
-    hr = pSection->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get httpErrors collection");
-
-    DWORD cErrors = 0;
-    hr = pCollection->get_Count(&cErrors);
-
-   // Get web error action
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-    ExitOnFailure(hr, "Failed to read filter action");
-    while (IIS_WEBERROR_END != iAction)
-    {
-        //Process property action
-        if (IIS_WEBERROR == iAction)
-        {
-            hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &(we.iErrorCode));
-            ExitOnFailure(hr, "failed to get httpErrors ErrorCode");
-
-            hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &(we.iSubCode));
-            ExitOnFailure(hr, "failed to get httpErrors SubCode");
-            //0 is the sub error code wild card for IIS6, change to -1 for IIS7
-            if (we.iSubCode == 0)
-            {
-                we.iSubCode = -1;
-            }
-            hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-            ExitOnFailure(hr, "Failed to get httpErrors File");
-            hr = ::StringCchCopyW(we.wzFile, countof(we.wzFile), pwzData);
-            ExitOnFailure(hr, "Failed to copy httpErrors File");
-
-            hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &(we.iResponseMode));
-            ExitOnFailure(hr, "Failed to get httpErrors File code");
-
-            fFound = FALSE;
-            hr = GetErrorFromList( we, &psweList, &pswe, &fFound);
-            if (!fFound)
-            {
-                hr = AddWebErrorToList(&psweList);
-                ExitOnFailure(hr, "failed to add web error to list");
-                pswe = psweList;
-            }
-            else
-            {
-                //if overwriting existing http errors element then clear lang path
-                hr = ::StringCchCopyW(pswe->wzLangPath, countof(pswe->wzLangPath), L"");
-                ExitOnFailure(hr, "Failed to copy httpErrors lang path value");
-            }
-            pswe->iErrorCode = we.iErrorCode;
-            pswe->iSubCode   = we.iSubCode;
-            hr = ::StringCchCopyW(pswe->wzFile, countof(pswe->wzFile), we.wzFile);
-            ExitOnFailure(hr, "Failed to copy httpErrors File value");
-            pswe->iResponseMode = we.iResponseMode;
-
-        }
-        else
-        {
-            ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for http header");
-        }
-
-        // Get AppExt action
-        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-        ExitOnFailure(hr, "Failed to read filter action");
-    }
-
-    //No inheritance - put a clear in at this loc tag
-    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_CLEAR), &pElement);
-    ExitOnFailure(hr, "Failed create httpErrors clear");
-    hr = pCollection->AddElement(pElement);
-    ExitOnFailure(hr, "Failed add httpErrors clear");
-
-    //now we have merged new, from MSI, http errors with global list
-    //write this back out at location tag.
-    // Loop through the HTTP headers
-    for ( pswe = psweList; pswe; pswe = pswe->psweNext)
-    {
-        hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ERROR), &pElement);
-        ExitOnFailure(hr, "Failed create httpErrors element");
-
-        // status code
-        hr = Iis7PutPropertyInteger(pElement, IIS_CONFIG_STATUSCODE, pswe->iErrorCode);
-        ExitOnFailure(hr, "Failed set httpErrors code value");
-
-        //sub status
-        hr = Iis7PutPropertyInteger(pElement, IIS_CONFIG_SUBSTATUS, pswe->iSubCode);
-        ExitOnFailure(hr, "Failed set httpErrors sub code value");
-
-        //lang path
-        hr = Iis7PutPropertyString(pElement, IIS_CONFIG_LANGPATH, pswe->wzLangPath);
-        ExitOnFailure(hr, "Failed set httpErrors lang path value");
-
-        //path
-        hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PATH, pswe->wzFile);
-        ExitOnFailure(hr, "Failed set httpErrors path value");
-
-        //response mode
-        hr = Iis7PutPropertyInteger(pElement, IIS_CONFIG_RESPMODE, pswe->iResponseMode);
-        ExitOnFailure(hr, "Failed set httpErrors resp mode value");
-
-        //add the element
-        hr = pCollection->AddElement(pElement);
-        ExitOnFailure(hr, "Failed add httpErrors element");
-        ReleaseNullObject(pElement);
-    }
-
-LExit:
-    ScaWebErrorFreeList7(psweList);
-
-    ReleaseStr(pwzConfigPath);
-    ReleaseStr(pwzSiteName);
-    ReleaseStr(pwzAppName);
-    ReleaseStr(pwzData);
-    ReleaseObject(pElement);
-    ReleaseObject(pSection);
-    ReleaseObject(pCollection);
-
-    return hr;
-}
-
-static HRESULT PopulateHttpErrors(IAppHostElement *pSection, SCA_WEB_ERROR_SERVER **ppsweList)
-{
-    HRESULT hr = S_OK;
-
-    IAppHostElement *pElement = NULL;
-    IAppHostElementCollection *pCollection = NULL;
-    IAppHostProperty *pProperty = NULL;
-
-    DWORD cErrors = 0;
-    SCA_WEB_ERROR_SERVER *pswe = NULL;
-
-    VARIANT vPropValue;
-    VARIANT vtIndex;
-
-    VariantInit(&vPropValue);
-    VariantInit(&vtIndex);
-
-    hr = pSection->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get httpErrors collection");
-
-    hr = pCollection->get_Count(&cErrors);
-    ExitOnFailure(hr, "Failed get sites collection count");
-
-    vtIndex.vt = VT_UI4;
-    for (DWORD i = 0; i < cErrors; ++i)
-    {
-        vtIndex.ulVal = i;
-        hr = pCollection->get_Item(vtIndex , &pElement);
-        ExitOnFailure(hr, "Failed get httpErrors collection item");
-
-        hr = AddWebErrorToList(ppsweList);
-        ExitOnFailure(hr, "Failed add web error list item");
-        pswe = *ppsweList;
-
-        //get all properties
-        //
-        // statusCode UINT
-        // subStatusCode INT
-        // prefixLanguageFilePath type="string"
-        // path type="string"
-        // responseMode type="enum" defaultValue="File">
-        //  <enum name="File" value="0" />
-        //  <enum name="ExecuteURL" value="1" />
-        //  <enum name="Redirect" value="2" />
-
-        // status code
-        hr = pElement->GetPropertyByName(ScopeBSTR(IIS_CONFIG_STATUSCODE), &pProperty);
-        ExitOnFailure(hr, "Failed get httpErrors code property");
-        hr = pProperty->get_Value(&vPropValue);
-        ExitOnFailure(hr, "Failed get httpErrors code value");
-        pswe->iErrorCode = vPropValue.uintVal;
-        ReleaseVariant(vPropValue);
-
-        //sub status
-        hr = pElement->GetPropertyByName(ScopeBSTR(IIS_CONFIG_SUBSTATUS), &pProperty);
-        ExitOnFailure(hr, "Failed get httpErrors sub code property");
-        hr = pProperty->get_Value(&vPropValue);
-        ExitOnFailure(hr, "Failed get httpErrors sub code value");
-        pswe->iSubCode = vPropValue.intVal;
-        ReleaseVariant(vPropValue);
-
-        //lang path
-        hr = pElement->GetPropertyByName(ScopeBSTR(IIS_CONFIG_LANGPATH), &pProperty);
-        ExitOnFailure(hr, "Failed get httpErrors lang path property");
-        hr = pProperty->get_Value(&vPropValue);
-        ExitOnFailure(hr, "Failed get httpErrors lang path value");
-        hr = ::StringCchCopyW(pswe->wzLangPath, countof(pswe->wzLangPath), vPropValue.bstrVal);
-        ExitOnFailure(hr, "Failed to copy httpErrors lang path");
-        ReleaseVariant(vPropValue);
-
-        //path
-        hr = pElement->GetPropertyByName(ScopeBSTR(IIS_CONFIG_PATH), &pProperty);
-        ExitOnFailure(hr, "Failed get httpErrors path property");
-        hr = pProperty->get_Value(&vPropValue);
-        ExitOnFailure(hr, "Failed get httpErrors path value");
-        hr = ::StringCchCopyW(pswe->wzFile, countof(pswe->wzFile), vPropValue.bstrVal);
-        ExitOnFailure(hr, "Failed to copy httpErrors File");
-        ReleaseVariant(vPropValue);
-
-        //response mode
-        hr = pElement->GetPropertyByName(ScopeBSTR(IIS_CONFIG_RESPMODE), &pProperty);
-        ExitOnFailure(hr, "Failed get httpErrors resp mode property");
-        hr = pProperty->get_Value(&vPropValue);
-        ExitOnFailure(hr, "Failed get httpErrors resp mode value");
-        pswe->iResponseMode = vPropValue.intVal;
-        ReleaseVariant(vPropValue);
-
-        ReleaseNullObject(pElement);
-        ReleaseNullObject(pProperty);
-    }
-
-    //remove the elements from connection so we can add back later
-    hr = pCollection->Clear();
-    ExitOnFailure(hr, "Failed clear httpErrors collection");
-
-LExit:
-    ReleaseVariant(vPropValue);
-    ReleaseObject(pProperty);
-    ReleaseObject(pElement);
-    ReleaseObject(pCollection);
-
-    return hr;
-}
-
-static void ScaWebErrorFreeList7(SCA_WEB_ERROR_SERVER *psweList)
-{
-    SCA_WEB_ERROR_SERVER *psweDelete = psweList;
-    while (psweList)
-    {
-        psweDelete = psweList;
-        psweList = psweList->psweNext;
-
-        MemFree(psweDelete);
-    }
-}
-static HRESULT AddWebErrorToList(SCA_WEB_ERROR_SERVER **ppsweList)
-{
-    HRESULT hr = S_OK;
-
-    SCA_WEB_ERROR_SERVER* pswe = static_cast<SCA_WEB_ERROR_SERVER*>(MemAlloc(sizeof(SCA_WEB_ERROR_SERVER), TRUE));
-
-    ExitOnNull(pswe, hr, E_OUTOFMEMORY, "failed to allocate memory for new web error list element");
-
-    pswe->psweNext = *ppsweList;
-    *ppsweList = pswe;
-
-LExit:
-    return hr;
-}
-static HRESULT GetErrorFromList( const SCA_WEB_ERROR_SERVER& we,
-                                    SCA_WEB_ERROR_SERVER **ppsweList,
-                                    SCA_WEB_ERROR_SERVER **ppswe,
-                                    BOOL *fFound)
-{
-    HRESULT hr = S_OK;
-
-    *fFound = FALSE;
-
-    SCA_WEB_ERROR_SERVER *pswe;
-
-    for ( pswe = *ppsweList; pswe; pswe = pswe->psweNext)
-    {
-        if ((pswe->iErrorCode == we.iErrorCode) && (pswe->iSubCode == we.iSubCode))
-        {
-            *fFound = TRUE;
-            *ppswe = pswe;
-            break;
-        }
-    }
-
-    return hr;
-}
-
-//-------------------------------------------------------------------------------------------------
-// IIS7HttpHeader
-// Called by WriteIIS7ConfigChanges
-// Processes http header CA Data
-//
-//-------------------------------------------------------------------------------------------------
-
-HRESULT IIS7HttpHeader(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    )
-{
-    HRESULT hr = S_OK;
-    LPWSTR pwzConfigPath = NULL;
-    LPWSTR pwzSiteName = NULL;
-    LPWSTR pwzAppName = NULL;
-
-    LPWSTR pwzHeaderName = NULL;
-    LPWSTR pwzHeaderValue = NULL;
-
-    IAppHostElement *pElement = NULL;
-    IAppHostElement *pSection = NULL;
-    IAppHostElementCollection *pCollection = NULL;
-    IAppHostElement *pElementHeaders = NULL;
-
-    int iAction = -1;
-    BOOL fFound = FALSE;
-
-    //read web site key
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
-    ExitOnFailure(hr, "Failed read header web site name");
-
-    //read app key
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzAppName);
-    ExitOnFailure(hr, "Failed read header appkey");
-
-    //Construct config root path
-    hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzSiteName);
-    ExitOnFailure(hr, "failed to format web error config path");
-
-    if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzAppName, -1, L"/", -1))
-    {
-        hr = StrAllocConcat(&pwzConfigPath, L"/", 0);
-        ExitOnFailure(hr, "failed to copy web error config path delim");
-        hr = StrAllocConcat(&pwzConfigPath, pwzAppName, 0);
-        ExitOnFailure(hr, "failed to app name to web error config path");
-    }
-
-    //get admin handlers section at config path location tag
-    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_HTTPPROTO_SECTION), pwzConfigPath, &pSection);
-    ExitOnFailure(hr, "Failed get http protocol section");
-
-    hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_HEADERS), &pElementHeaders);
-    ExitOnFailure(hr, "Failed get http customHeaders section");
-
-    hr = pElementHeaders->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get http customHeaders collection");
-
-   // Get filter action
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-    ExitOnFailure(hr, "Failed to read filter action");
-    while (IIS_HTTP_HEADER_END != iAction)
-    {
-        //Process property action
-        if (IIS_HTTP_HEADER == iAction)
-        {
-            hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzHeaderName);
-            ExitOnFailure(hr, "Fail to read httpHeader name");
-
-            hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzHeaderValue);
-            ExitOnFailure(hr, "Fail to read httpHeader value");
-
-            hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_ADD, IIS_CONFIG_NAME, pwzHeaderName, &pElement, NULL);
-            ExitOnFailure(hr, "Failed get isapiCgiRestriction element");
-            fFound = (NULL != pElement);
-
-            if (!fFound)
-            {
-                //make a new element
-                hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pElement);
-                ExitOnFailure(hr, "Failed to create filter config element");
-
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_NAME, pwzHeaderName);
-                ExitOnFailure(hr, "Failed to set header name");
-            }
-
-            hr = Iis7PutPropertyString(pElement, IIS_CONFIG_VALUE, pwzHeaderValue);
-            ExitOnFailure(hr, "Failed to set header Value");
-
-            if (!fFound)
-            {
-                hr = pCollection->AddElement(pElement);
-                ExitOnFailure(hr, "Failed add http header");
-            }
-
-        }
-        else
-        {
-            ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for http header");
-        }
-
-        // Get AppExt action
-        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-        ExitOnFailure(hr, "Failed to read filter action");
-    }
-
-LExit:
-    ReleaseStr(pwzConfigPath);
-    ReleaseStr(pwzSiteName);
-    ReleaseStr(pwzAppName);
-    ReleaseStr(pwzHeaderName);
-    ReleaseStr(pwzHeaderValue);
-    ReleaseObject(pElementHeaders);
-    ReleaseObject(pElement);
-    ReleaseObject(pSection);
-    ReleaseObject(pCollection);
-
-    return hr;
-}
-
-//-------------------------------------------------------------------------------------------------
-// IIS7FilterGlobal
-// Called by WriteIIS7ConfigChanges
-// Processes Filter CA Data
-//
-//-------------------------------------------------------------------------------------------------
-HRESULT IIS7FilterGlobal(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    )
-{
-    HRESULT hr = S_OK;
-    int iAction = 0;
-
-    IAppHostElement *pSection = NULL;
-
-    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_ISAPI_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pSection);
-    ExitOnFailure(hr, "Failed get sites section");
-
-    if (!pSection)
-    {
-        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-        ExitOnFailure(hr, "Failed get isapiFilters section object");
-    }
-
-   // Get filter action
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-    ExitOnFailure(hr, "Failed to read filter action");
-
-    while (IIS_FILTER_END != iAction)
-    {
-        //Process property action
-        switch (iAction)
-        {
-            case IIS_FILTER :
-            {
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-                ExitOnFailure(hr, "Failed to read filter action");
-
-                if (iAction == IIS_CREATE)
-                {
-                    hr = CreateGlobalFilter(ppwzCustomActionData, pSection);
-                }
-                else
-                {
-                    hr = DeleteGlobalFilter(ppwzCustomActionData, pSection);
-                }
-                break;
-            }
-            default:
-            {
-                ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for global filter");
-                break;
-            }
-        }
-        // Get AppExt action
-        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-        ExitOnFailure(hr, "Failed to read filter action");
-
-    }
-
-LExit:
-    ReleaseObject(pSection);
-
-    return hr;
-}
-
-static HRESULT CreateGlobalFilter( __inout LPWSTR *ppwzCustomActionData, IAppHostElement *pSection)
-{
-    HRESULT hr = S_OK;
-
-    LPWSTR pwzFilterName = NULL;
-    LPWSTR pwzSiteName = NULL;
-    LPWSTR pwzFilterPath = NULL;
-    int iLoadOrder = 0;
-    DWORD cFilters = 0;
-
-    IAppHostElement *pElement = NULL;
-    IAppHostElementCollection *pCollection = NULL;
-
-    hr = pSection->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get filter collection");
-
-    hr = pCollection->get_Count(&cFilters);
-    ExitOnFailure(hr, "Failed get filter collection count");
-
-    // Attempt to delete, we will we recreate with desired property values and order
-    hr = DeleteCollectionElement(pCollection, IIS_CONFIG_FILTER, IIS_CONFIG_NAME, pwzFilterName);
-    ExitOnFailure(hr, "Failed to delete filter");
-
-    //make a new element
-    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_FILTER), &pElement);
-    ExitOnFailure(hr, "Failed to create filter config element");
-
-    //filter Name key
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzFilterName);
-    ExitOnFailure(hr, "Failed to read filter name");
-    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_NAME, pwzFilterName);
-    ExitOnFailure(hr, "Failed to set filter name");
-
-    //web site name
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
-    ExitOnFailure(hr, "Failed to read filter site name");
-
-    // filter path
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzFilterPath);
-    ExitOnFailure(hr, "Failed to read filter path");
-    hr = Iis7PutPropertyString(pElement,IIS_CONFIG_PATH, pwzFilterPath);
-    ExitOnFailure(hr, "Failed to set filter path");
-
-    //filter load order
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iLoadOrder);
-    ExitOnFailure(hr, "Failed to read filter load order");
-
-    //  put element in order in list
-    int iPosition = -1;
-    int icFilters = cFilters;
-    switch (iLoadOrder)
-    {
-        case 0 :
-        {
-            iPosition = -1;
-            break;
-        }
-        case -1 :
-        {
-            iPosition = icFilters;
-            break;
-        }
-        case MSI_NULL_INTEGER :
-        {
-             iPosition = icFilters;
-             break;
-        }
-        default:
-        {
-            if (iLoadOrder > icFilters)
-            {
-                iPosition = icFilters;
-            }
-            else
-            {
-                iPosition = iLoadOrder;
-            }
-            break;
-        }
-    }
-    hr = pCollection->AddElement(pElement, iPosition);
-    ExitOnFailure(hr, "Failed to add filter element");
-
-LExit:
-    ReleaseStr(pwzFilterName);
-    ReleaseStr(pwzSiteName);
-    ReleaseStr(pwzFilterPath);
-    ReleaseObject(pCollection);
-    ReleaseObject(pElement);
-
-    return hr;
-}
-
-static HRESULT DeleteGlobalFilter( __inout LPWSTR *ppwzCustomActionData, IAppHostElement *pSection)
-{
-    HRESULT hr = S_OK;
-
-    LPWSTR pwzFilterName = NULL;
-    LPWSTR pwzSiteName = NULL;
-
-    IAppHostElementCollection *pCollection = NULL;
-
-    hr = pSection->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get filter collection");
-
-    //filter Name key
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzFilterName);
-    ExitOnFailure(hr, "Failed to read filter name");
-
-    //web site name
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName); // TODO: unused?
-    ExitOnFailure(hr, "Failed to read filter site name");
-
-    DeleteCollectionElement(pCollection, IIS_CONFIG_FILTER, IIS_CONFIG_NAME, pwzFilterName);
-    ExitOnFailure(hr, "Failed to delete filter %ls", pwzFilterName);
-
-LExit:
-    ReleaseStr(pwzFilterName);
-    ReleaseStr(pwzSiteName);
-    ReleaseObject(pCollection);
-
-    return hr;
-}
-
-//-------------------------------------------------------------------------------------------------
-// IIS7FilterSite
-// Called by WriteIIS7ConfigChanges
-// Processes Filter CA Data
-//
-//-------------------------------------------------------------------------------------------------
-HRESULT IIS7FilterSite(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    )
-{
-    HRESULT hr = S_OK;
-    int iAction = 0;
-
-   // Get filter action
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-    ExitOnFailure(hr, "Failed to read filter action");
-
-    while (IIS_FILTER_END != iAction)
-    {
-        //Process property action
-        switch (iAction)
-        {
-            case IIS_FILTER :
-            {
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-                ExitOnFailure(hr, "Failed to read filter action");
-
-                if (iAction == IIS_CREATE)
-                {
-                    hr = CreateSiteFilter(ppwzCustomActionData, pAdminMgr);
-                }
-                else
-                {
-                    hr = DeleteSiteFilter(ppwzCustomActionData, pAdminMgr);
-                }
-                break;
-            }
-            default:
-            {
-                ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for global filter");
-                break;
-            }
-        }
-
-        // Get AppExt action
-        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-        ExitOnFailure(hr, "Failed to read filter action");
-    }
-
-LExit:
-    return hr;
-
-}
-
-static HRESULT CreateSiteFilter(__inout LPWSTR *ppwzCustomActionData, IAppHostWritableAdminManager *pAdminMgr)
-{
-    HRESULT hr = S_OK;
-    LPWSTR pwzFilterName = NULL;
-    LPWSTR pwzSiteName = NULL;
-    LPWSTR pwzFilterPath = NULL;
-    LPWSTR pwzConfigPath = NULL;
-    int iLoadOrder = 0;
-    DWORD cFilters;
-
-    IAppHostElement *pElement = NULL;
-    IAppHostElement *pSection = NULL;
-    IAppHostElementCollection *pCollection = NULL;
-
-    //filter Name key
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzFilterName);
-    ExitOnFailure(hr, "Failed to read filter name");
-
-    //web site name
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
-    ExitOnFailure(hr, "Failed to read filter site name");
-
-     //Construct config root
-    hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzSiteName);
-    ExitOnFailure(hr, "failed to format filter config path");
-
-    //get admin isapiFilters section at config path location tag
-    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_ISAPI_SECTION), pwzConfigPath, &pSection);
-    ExitOnFailure(hr, "Failed get isapiFilters section");
-
-    hr = pSection->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get filter collection");
-
-    hr = pCollection->get_Count(&cFilters);
-    ExitOnFailure(hr, "Failed get filter collection count");
-
-    // Attempt to delete, we will we recreate with desired property values and order
-    hr = DeleteCollectionElement(pCollection, IIS_CONFIG_FILTER, IIS_CONFIG_NAME, pwzFilterName);
-    ExitOnFailure(hr, "Failed to delete filter");
-
-     //make a new element
-    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_FILTER), &pElement);
-    ExitOnFailure(hr, "Failed to create filter config element");
-
-    hr = Iis7PutPropertyString(pElement,IIS_CONFIG_NAME, pwzFilterName);
-    ExitOnFailure(hr, "Failed to set filter name");
-
-    // filter path
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzFilterPath);
-    ExitOnFailure(hr, "Failed to read filter path");
-
-    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PATH, pwzFilterPath);
-    ExitOnFailure(hr, "Failed to set filter path");
-
-    //filter load order
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iLoadOrder);
-    ExitOnFailure(hr, "Failed to read filter load order");
-
-    //  put element in order in list
-    int iPosition = -1;
-    int icFilters = cFilters;
-    switch (iLoadOrder)
-    {
-        case 0 :
-        {
-            iPosition = -1;
-            break;
-        }
-        case -1 :
-        {
-            iPosition = icFilters;
-            break;
-        }
-        case MSI_NULL_INTEGER :
-        {
-            iPosition = icFilters;
-            break;
-        }
-        default:
-        {
-            if (iLoadOrder > icFilters)
-            {
-                iPosition = icFilters;
-            }
-            else
-            {
-                iPosition = iLoadOrder;
-            }
-            break;
-        }
-    }
-
-    hr = pCollection->AddElement(pElement, iPosition);
-    ExitOnFailure(hr, "Failed to add filter element");
-
-LExit:
-    ReleaseStr(pwzFilterName);
-    ReleaseStr(pwzSiteName);
-    ReleaseStr(pwzFilterPath);
-    ReleaseStr(pwzConfigPath);
-    ReleaseObject(pElement);
-    ReleaseObject(pSection);
-    ReleaseObject(pCollection);
-
-    return hr;
-}
-
-static HRESULT DeleteSiteFilter(__inout LPWSTR *ppwzCustomActionData, IAppHostWritableAdminManager *pAdminMgr)
-{
-    HRESULT hr = S_OK;
-    LPWSTR pwzFilterName = NULL;
-    LPWSTR pwzSiteName = NULL;
-    LPWSTR pwzConfigPath = NULL;
-
-    IAppHostElement *pSection = NULL;
-    IAppHostElementCollection *pCollection = NULL;
-
-    //filter Name key
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzFilterName);
-    ExitOnFailure(hr, "Failed to read filter name");
-
-    //web site name
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
-    ExitOnFailure(hr, "Failed to read filter site name");
-
-     //Construct config root
-    hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzSiteName);
-    ExitOnFailure(hr, "failed to format filter config path");
-
-    //get admin isapiFilters section at config path location tag
-    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_ISAPI_SECTION), pwzConfigPath, &pSection);
-    ExitOnFailure(hr, "Failed get isapiFilters section");
-
-    hr = pSection->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get filter collection");
-
-    DeleteCollectionElement(pCollection, IIS_CONFIG_FILTER, IIS_CONFIG_NAME, pwzFilterName);
-    ExitOnFailure(hr, "Failed to delete filter %ls", pwzFilterName);
-
-LExit:
-    ReleaseStr(pwzFilterName);
-    ReleaseStr(pwzSiteName);
-    ReleaseStr(pwzConfigPath);
-    ReleaseObject(pSection);
-    ReleaseObject(pCollection);
-
-    return hr;
-}
-
-//-------------------------------------------------------------------------------------------------
-// IIS7Site
-// Called by WriteIIS7ConfigChanges
-// Processes WebSite CA Data
-//
-//-------------------------------------------------------------------------------------------------
-HRESULT IIS7Site(
-    __inout LPWSTR *ppwzCustomActionData,
-    __in    IAppHostWritableAdminManager *pAdminMgr)
-{
-    HRESULT hr  = S_OK;
-    int iAction = -1;
-    int iData   =  0;
-    BOOL fFound = FALSE;
-
-    LPWSTR pwzSiteName = NULL;
-    IAppHostElement *pSites = NULL;
-    IAppHostElementCollection *pCollection = NULL;
-    IAppHostElement *pSiteElem = NULL;
-    IAppHostElement *pElement = NULL;
-
-    // Get site action
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-    ExitOnFailure(hr, "Failed to read site action");
-
-    //get site name
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
-    ExitOnFailure(hr, "Failed to read site key");
-
-    //Get site if it exists
-    hr = GetSiteElement(pAdminMgr, pwzSiteName, &pSiteElem, &fFound);
-    ExitOnFailure(hr, "Failed to read sites from config");
-
-    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_SITES_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pSites);
-    ExitOnFailure(hr, "Failed get sites section");
-    ExitOnNull(pSites, hr, ERROR_FILE_NOT_FOUND, "Failed get sites section object");
-
-    hr = pSites->get_Collection( &pCollection);
-    ExitOnFailure(hr, "Failed get site collection");
-    switch (iAction)
-    {
-        case IIS_DELETE :
-        {
-            if (fFound)
-            {
-                hr = DeleteCollectionElement(pCollection, IIS_CONFIG_SITE, IIS_CONFIG_NAME, pwzSiteName);
-                ExitOnFailure(hr, "Failed to delete website");
-            }
-            ExitFunction();
-            break;
-        }
-        case IIS_CREATE :
-        {
-            if (!fFound)
-            {
-                //Create the site
-                hr = CreateSite(pCollection, pwzSiteName, &pSiteElem);
-                ExitOnFailure(hr, "Failed to create site");
-
-            }
-        }
-    }
-    //
-    //Set other Site properties
-    //
-    //set site Id
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-    ExitOnFailure(hr, "Failed to read site Id");
-    if (iData != MSI_NULL_INTEGER && -1 != iData)
-    {
-        hr = Iis7PutPropertyInteger(pSiteElem, IIS_CONFIG_SITE_ID, iData);
-        ExitOnFailure(hr, "Failed set site Id data");
-    }
-    //Set Site AutoStart
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-    ExitOnFailure(hr, "Failed to read site autostart");
-    if (MSI_NULL_INTEGER != iData)
-    {
-        hr = Iis7PutPropertyBool(pSiteElem, IIS_CONFIG_AUTOSTART, iData);
-        ExitOnFailure(hr, "Failed set site config data");
-    }
-
-    //Set Site Connection timeout
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-    ExitOnFailure(hr, "Failed to read site connection tomeout data");
-    if (MSI_NULL_INTEGER != iData)
-    {
-        // get limits element, get connectionTimeout property
-        hr = pSiteElem->GetElementByName(ScopeBSTR(IIS_CONFIG_LIMITS), &pElement);
-        ExitOnFailure(hr, "Failed to read limits from config");
-        //convert iData in seconds to timeSpan hh:mm:ss
-        WCHAR wcTime[60];
-        *wcTime = '\0';
-        ConvSecToHMS( iData, wcTime, countof( wcTime));
-
-        hr = Iis7PutPropertyString(pElement, IIS_CONFIG_CONNECTTIMEOUT, wcTime);
-        ExitOnFailure(hr, "IIS: failed set connection timeout config data");
-   }
-
-LExit:
-    ReleaseStr(pwzSiteName);
-    ReleaseObject(pSites);
-    ReleaseObject(pCollection);
-    ReleaseObject(pSiteElem);
-    ReleaseObject(pElement);
-
-    return hr;
-}
-//-------------------------------------------------------------------------------------------------
-// IIS7Application
-//  Processes Application CA Data
-//
-//
-//-------------------------------------------------------------------------------------------------
-
-HRESULT IIS7Application(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr)
-{
-    HRESULT hr = S_OK;
-
-    int iAction = -1;
-    BOOL fSiteFound = FALSE;
-    BOOL fAppFound = FALSE;
-
-    LPWSTR pwzSiteName = NULL;
-    LPWSTR pwzAppPath = NULL;
-    LPWSTR pwzAppPool = NULL;
-    LPWSTR pwzLocationPath = NULL;
-    IAppHostElement *pSiteElem = NULL;
-    IAppHostElement *pAppElement = NULL;
-    // Get Application action
-    hr = WcaReadIntegerFromCaData( ppwzCustomActionData, &iAction);
-    ExitOnFailure(hr, "Failed to read application action")
-    //get site key name
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
-    ExitOnFailure(hr, "Failed to read app site key");
-    //get application path
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzAppPath);
-    ExitOnFailure(hr, "Failed to read app path key");
-    //get application Pool
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzAppPool);
-    ExitOnFailure(hr, "Failed to read app pool key");
-
-    //Get site if it exists
-    hr = GetSiteElement(pAdminMgr, pwzSiteName, &pSiteElem, &fSiteFound);
-    ExitOnFailure(hr, "Failed to read sites from config");
-
-    switch (iAction)
-    {
-        case IIS_CREATE :
-        {
-            if (fSiteFound)
-            {
-                //have site get application collection
-                hr = GetApplicationElement(pSiteElem,
-                                            pwzAppPath,
-                                            &pAppElement,
-                                            &fAppFound);
-                ExitOnFailure(hr, "Error reading application from config");
-
-                if (!fAppFound)
-                {
-                    //Create Application
-                    hr = CreateApplication(pSiteElem, pwzAppPath, &pAppElement);
-                    ExitOnFailure(hr, "Error creating application in config");
-                }
-                //Update application properties:
-                //
-                //Set appPool
-                hr = SetAppPool(pAppElement, pwzAppPool);
-                ExitOnFailure(hr, "Unable to set appPool for application");
-            }
-            else
-            {
-                hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-                ExitOnFailure(hr, "Site not found for create application");
-            }
-            break;
-        }
-        case IIS_DELETE :
-        {
-            if (fSiteFound)
-            {
-                //have site get application collection
-                hr = GetApplicationElement( pSiteElem,
-                                            pwzAppPath,
-                                            &pAppElement,
-                                            &fAppFound);
-                ExitOnFailure(hr, "Error reading application from config")
-                if (fAppFound)
-                {
-                    //delete Application
-                    hr = DeleteApplication(pSiteElem, pwzAppPath);
-                    ExitOnFailure(hr, "Error deleating application from config")
-                    //Construct Location path
-                    // TODO: it seems odd that these are just
-                    // jammed together, need to determine if this requires a '\'
-                    hr = StrAllocString(&pwzLocationPath, pwzSiteName, 0);
-                    ExitOnFailure(hr, "failed to copy location config path web name");
-                    hr = StrAllocConcat(&pwzLocationPath, pwzAppPath, 0);
-                    ExitOnFailure(hr, "failed to copy location config path appPath ");
-
-                    // and delete location tag for this application
-                    hr = ClearLocationTag(pAdminMgr, pwzLocationPath);
-                    ExitOnFailure(hr, "failed to clear location tag for %ls", pwzLocationPath);
-                }
-            }
-            break;
-        }
-        default:
-            ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for Application");
-            break;
-    }
-
-LExit:
-    ReleaseStr(pwzSiteName);
-    ReleaseStr(pwzAppPath);
-    ReleaseStr(pwzAppPool);
-    ReleaseStr(pwzLocationPath);
-    ReleaseObject(pSiteElem);
-    ReleaseObject(pAppElement);
-
-    return hr;
-}
-//-------------------------------------------------------------------------------------------------
-// IIS7VDir
-//  Processes VDir CA Data
-//
-//
-//-------------------------------------------------------------------------------------------------
-HRESULT IIS7VDir(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr)
-{
-    HRESULT hr = S_OK;
-
-    int iAction = -1;
-    BOOL fSiteFound = FALSE;
-    BOOL fAppFound = FALSE;
-
-    LPWSTR pwzSiteName = NULL;
-    LPWSTR pwzVDirPath = NULL;
-    LPWSTR pwzVDirPhyDir = NULL;
-    LPCWSTR pwzVDirSubPath = NULL;
-
-    IAppHostElement *pSiteElem = NULL;
-    IAppHostElement *pAppElement = NULL;
-    IAppHostElementCollection *pElement = NULL;
-
-    // Get Application action
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-    ExitOnFailure(hr, "Failed to read VDir action");
-
-    //get site key name
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
-    ExitOnFailure(hr, "Failed to read site key");
-    //get VDir path
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzVDirPath);
-    ExitOnFailure(hr, "Failed to read VDir key");
-    //get physical dir path
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzVDirPhyDir);
-    ExitOnFailure(hr, "Failed to read VDirPath key");
-
-    //Get site if it exists
-    hr = GetSiteElement(pAdminMgr, pwzSiteName, &pSiteElem, &fSiteFound);
-    ExitOnFailure(hr, "Failed to read sites from config");
-
-    if (IIS_CREATE == iAction)
-    {
-        if (fSiteFound)
-        {
-            //have site get application
-            hr = GetApplicationElementForVDir( pSiteElem,
-                                               pwzVDirPath,
-                                               &pAppElement,
-                                               &pwzVDirSubPath,
-                                               &fAppFound);
-            ExitOnFailure(hr, "Error reading application element from config");
-
-            if (!fAppFound)
-            {
-                // need application to add vDir
-                hr = E_FILENOTFOUND;
-                ExitOnFailure(hr, "Error application not found for create VDir");
-            }
-            //
-            // create the virDir
-            //
-            hr = CreateVdir(pAppElement, pwzVDirSubPath, pwzVDirPhyDir);
-            ExitOnFailure(hr, "Failed to create vdir for application");
-        }
-        else
-        {
-            hr = E_FILENOTFOUND;
-            ExitOnFailure(hr, "IIS: site not found for create VDir");
-        }
-    }
-    else if (IIS_DELETE == iAction)
-    {
-        if (fSiteFound)
-        {
-            //have site get application
-            hr = GetApplicationElementForVDir( pSiteElem,
-                                               pwzVDirPath,
-                                               &pAppElement,
-                                               &pwzVDirSubPath,
-                                               &fAppFound);
-            ExitOnFailure(hr, "Error reading application from config")
-            if (fAppFound)
-            {
-                //delete vdir
-                hr = DeleteVdir(pAppElement, pwzVDirSubPath);
-                ExitOnFailure(hr, "Unable to delete vdir for application");
-            }
-        }
-    }
-
- LExit:
-    ReleaseStr(pwzSiteName);
-    ReleaseStr(pwzVDirPath);
-    ReleaseStr(pwzVDirPhyDir);
-    ReleaseObject(pSiteElem);
-    ReleaseObject(pAppElement);
-    ReleaseObject(pElement);
-
-    return hr;
-}
-
-//-------------------------------------------------------------------------------------------------
-// IIS7Binding
-//  Processes Bindings CA Data
-//
-//
-//-------------------------------------------------------------------------------------------------
-HRESULT IIS7Binding(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr)
-{
-    HRESULT hr = S_OK;
-
-    int iAction = -1;
-    BOOL fSiteFound = FALSE;
-
-    LPWSTR pwzSiteName = NULL;
-    LPWSTR pwzProtocol = NULL;
-    LPWSTR pwzInfo = NULL;
-
-    IAppHostElement *pSiteElem = NULL;
-
-    // Get Application action
-    hr = WcaReadIntegerFromCaData( ppwzCustomActionData, &iAction);
-    ExitOnFailure(hr, "Failed to read binding action");
-
-    //get site key name
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
-    ExitOnFailure(hr, "Failed to read binding site name key");
-
-    //get binding protocol
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzProtocol);
-    ExitOnFailure(hr, "Failed to read binding protocol");
-
-    //get binding info
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzInfo);
-    ExitOnFailure(hr, "Failed to read binding info");
-
-    //Get site if it exists
-    hr = GetSiteElement(pAdminMgr, pwzSiteName, &pSiteElem, &fSiteFound);
-    ExitOnFailure(hr, "Failed to read sites from config");
-
-    if (IIS_CREATE == iAction)
-    {
-        if (fSiteFound)
-        {
-            //add binding
-            hr = CreateBinding(pSiteElem, pwzProtocol, pwzInfo);
-            ExitOnFailure(hr, "Failed to create site binding");
-        }
-        else
-        {
-            hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-            ExitOnFailure(hr, "Site not found for create binding");
-        }
-    }
-    else if (IIS_DELETE == iAction)
-    {
-        if (fSiteFound)
-        {
-            //delete binding
-            hr = DeleteBinding(pSiteElem, pwzProtocol, pwzInfo);
-            ExitOnFailure(hr, "Failed to delete binding");
-        }
-    }
-
- LExit:
-    ReleaseStr(pwzSiteName);
-    ReleaseStr(pwzProtocol);
-    ReleaseStr(pwzInfo);
-    ReleaseObject(pSiteElem);
-
-    return hr;
-}
-//-------------------------------------------------------------------------------------------------
-// IIS7Binding
-//  Processes WebLog CA Data
-//
-//
-//-------------------------------------------------------------------------------------------------
-HRESULT IIS7WebLog(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr)
-{
-    HRESULT hr = S_OK;
-
-    BOOL fSiteFound = FALSE;
-
-    LPWSTR pwzSiteName = NULL;
-    LPWSTR pwzLogFormat = NULL;
-
-    IAppHostElement *pSiteElem = NULL;
-
-    //get site key name
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
-    ExitOnFailure(hr, "Failed to read web log site name key");
-
-    //get log format
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzLogFormat);
-    ExitOnFailure(hr, "Failed to read web log protocol");
-
-    //Get site if it exists
-    hr = GetSiteElement(pAdminMgr, pwzSiteName, &pSiteElem, &fSiteFound);
-    ExitOnFailure(hr, "Failed to read web log sites from config");
-
-    if (fSiteFound)
-    {
-        //add log format
-        hr = CreateWebLog(pSiteElem, pwzLogFormat);
-        ExitOnFailure(hr, "Failed to create weblog file format");
-    }
-    else
-    {
-        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-        ExitOnFailure(hr, "Site not found for create weblog file format");
-    }
-
- LExit:
-    ReleaseStr(pwzSiteName);
-    ReleaseStr(pwzLogFormat);
-    ReleaseObject(pSiteElem);
-
-    return hr;
-}
-//-------------------------------------------------------------------------------------------------
-// IIS7AppPool
-//  Processes AppPool CA Data
-//
-//
-//-------------------------------------------------------------------------------------------------
-HRESULT IIS7AppPool(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    )
-{
-    HRESULT hr = S_OK;
-
-    int iAction = -1;
-
-    LPWSTR pwzAppPoolName = NULL;
-
-    // Get AppPool action
-    hr = WcaReadIntegerFromCaData( ppwzCustomActionData, &iAction);
-    ExitOnFailure(hr, "Failed to read AppPool action");
-
-    //get appPool name
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzAppPoolName);
-    ExitOnFailure(hr, "Failed to read AppPool name key");
-
-    switch (iAction)
-    {
-        case IIS_CREATE :
-        {
-            hr = CreateAppPool(ppwzCustomActionData, pAdminMgr, pwzAppPoolName);
-            break;
-        }
-        case IIS_DELETE:
-        {
-            hr = DeleteAppPool(pAdminMgr, pwzAppPoolName);
-            break;
-        }
-        default:
-            ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for appPool");
-            break;
-    }
-
-LExit:
-    ReleaseStr(pwzAppPoolName);
-    return hr;
-}
-
-//-------------------------------------------------------------------------------------------------
-// IIS7AppExtension
-//  Processes AppExtension (config handlers) CA Data
-//
-//
-//-------------------------------------------------------------------------------------------------
-HRESULT IIS7AppExtension(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr)
-{
-   HRESULT hr = S_OK;
-
-   LPWSTR pwzWebName = NULL;
-   LPWSTR pwzWebRoot = NULL;
-   LPWSTR pwzData = NULL;
-   LPWSTR pwzConfigPath = NULL;
-   LPWSTR pwzHandlerName = NULL;
-   LPWSTR pwzPath = NULL;
-   int iAction = -1;
-
-   IAppHostElement *pSection = NULL;
-   IAppHostElement *pElement = NULL;
-   IAppHostElementCollection *pCollection = NULL;
-
-   BOOL fFound = FALSE;
-   DWORD cHandlers = 1000;
-
-    //get web name
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzWebName);
-    ExitOnFailure(hr, "Failed to read appExt Web name key");
-
-    //get root name
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzWebRoot);
-    ExitOnFailure(hr, "Failed to read appExt Web name key");
-
-    //Construct config root
-    hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzWebName);
-    ExitOnFailure(hr, "failed to format appext config path");
-    //
-    //Do not append trailing '/' for default vDir
-    //
-    if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzWebRoot, -1, L"/", -1))
-    {
-        hr = StrAllocConcat(&pwzConfigPath, L"/", 0);
-        ExitOnFailure(hr, "failed to copy appext config path delim");
-        hr = StrAllocConcat(&pwzConfigPath, pwzWebRoot, 0);
-        ExitOnFailure(hr, "failed to copy appext config path root name");
-    }
-    //get admin handlers section at config path location tag
-    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_HANDLERS_SECTION), pwzConfigPath, &pSection);
-    ExitOnFailure(hr, "Failed get appext section");
-
-    if (!pSection)
-    {
-        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-        ExitOnFailure(hr, "Failed get appext section object");
-    }
-
-    // Get AppExt action
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-    ExitOnFailure(hr, "Failed to read appExt action");
-
-    hr = pSection->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get handlers collection for appext");
-
-    while (IIS_APPEXT_END != iAction)
-    {
-        fFound = FALSE;
-
-        //Process property action
-        switch (iAction)
-        {
-            case IIS_APPEXT :
-            {
-                // These IDs aren't really stable but this is stable enough to support repair since the MSI won't change
-                hr = StrAllocFormatted(&pwzHandlerName, L"MsiCustom-%u", ++cHandlers);
-                ExitOnFailure(hr, "Failed increment handler name");
-
-                hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_ADD, IIS_CONFIG_NAME, pwzHandlerName, &pElement, NULL);
-                ExitOnFailure(hr, "Failed to find mimemap extension");
-
-                fFound = (NULL != pElement);
-                if (!fFound)
-                {
-                    //create new handler element
-                    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pElement);
-                    ExitOnFailure(hr, "Failed get create handler element for appext");
-
-                    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_NAME, pwzHandlerName);
-                    ExitOnFailure(hr, "Failed set appext name property");
-                }
-
-                //BUGBUG: For compat we are assuming these are all ISAPI MODULES so we are
-                //setting the modules property to IsapiModule.
-                //Currently can't deal with handlers of different module types.
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_MODULES, L"IsapiModule");
-                ExitOnFailure(hr, "Failed set site appExt path property");
-
-                //get extension (path)
-                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-                ExitOnFailure(hr, "Failed to read appExt extension");
-                hr = StrAllocFormatted(&pwzPath, L"*.%s", pwzData);
-                ExitOnFailure(hr, "Failed decorate appExt path");
-                //put property
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PATH, pwzPath);
-                ExitOnFailure(hr, "Failed set site appExt path property");
-
-                //get executable
-                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-                ExitOnFailure(hr, "Failed to read appExt executable");
-                //put property
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_EXECUTABLE, pwzData);
-                ExitOnFailure(hr, "Failed set site appExt executable property");
-
-                //get verbs
-                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-                ExitOnFailure(hr, "Failed to read appExt verbs");
-                //put property
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_VERBS, pwzData);
-                ExitOnFailure(hr, "Failed set site appExt verbs property");
-
-                break;
-            }
-            default:
-            {
-                ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for AppExt");
-                break;
-            }
-        }
-
-        if (!fFound)
-        {
-            //  put handler element at beginning of list
-            hr = pCollection->AddElement(pElement, 0);
-            ExitOnFailure(hr, "Failed add handler element for appext");
-        }
-
-        ReleaseNullObject(pElement);
-
-        // Get AppExt action
-        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-        ExitOnFailure(hr, "Failed to read AppPool Property action");
-    }
-
-LExit:
-    ReleaseStr(pwzWebName);
-    ReleaseStr(pwzWebRoot);
-    ReleaseStr(pwzData);
-    ReleaseStr(pwzConfigPath);
-    ReleaseStr(pwzHandlerName);
-    ReleaseStr(pwzPath);
-    ReleaseObject(pSection);
-    ReleaseObject(pElement);
-    ReleaseObject(pCollection);
-
-    return hr;
-}
-
-//-------------------------------------------------------------------------------------------------
-// IIS7MimeMap
-//  Processes Mime Map (config handlers) CA Data
-//
-//
-//-------------------------------------------------------------------------------------------------
- HRESULT IIS7MimeMap(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    )
-{
-    HRESULT hr = S_OK;
-    LPWSTR pwzConfigPath = NULL;
-    LPWSTR pwzWebName = NULL;
-    LPWSTR pwzWebRoot = NULL;
-    LPWSTR pwzData = NULL;
-    int iAction = -1;
-
-    IAppHostElement *pSection = NULL;
-    IAppHostElement *pElement = NULL;
-    IAppHostElementCollection *pCollection = NULL;
-
-    BOOL fFound = FALSE;
-
-    //get web name
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzWebName);
-    ExitOnFailure(hr, "Failed to read mime map Web name key");
-
-    //get vdir root name
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzWebRoot);
-    ExitOnFailure(hr, "Failed to read vdir root name key");
-
-    //Construct config root
-    hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s",  IIS_CONFIG_APPHOST_ROOT, pwzWebName);
-    ExitOnFailure(hr, "failed to format mime map config path web name");
-    //
-    //Do not append trailing '/' for default vDir
-    //
-    if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzWebRoot, -1, L"/", -1))
-    {
-        hr = StrAllocConcat(&pwzConfigPath, L"/", 0);
-        ExitOnFailure(hr, "failed to copy appext config path delim");
-        hr = StrAllocConcat(&pwzConfigPath, pwzWebRoot, 0);
-        ExitOnFailure(hr, "failed to copy appext config path root name");
-    }
-
-    //get admin section <staticContent> at config path location tag
-    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_STATICCONTENT_SECTION), pwzConfigPath, &pSection);
-    ExitOnFailure(hr, "Failed get staticContent section for mimemap");
-
-    if (!pSection)
-    {
-        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-        ExitOnFailure(hr, "Failed get staticContent section object");
-    }
-
-    // Get mimemap action
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-    ExitOnFailure(hr, "Failed to read mimemap action");
-
-    hr = pSection->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get staticContent collection for mimemap");
-
-    while (IIS_MIMEMAP_END != iAction)
-    {
-        //Process property action
-        switch (iAction)
-        {
-            case IIS_MIMEMAP :
-            {
-                //get extension
-                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-                ExitOnFailure(hr, "Failed to read mimemap extension");
-
-                hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_MIMEMAP, IIS_CONFIG_FILEEXT, pwzData, &pElement, NULL);
-                ExitOnFailure(hr, "Failed to find mimemap extension");
-                fFound = (NULL != pElement);
-
-                if (!fFound)
-                {
-                    //create new mimeMap element
-                    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_MIMEMAP), &pElement);
-                    ExitOnFailure(hr, "Failed get create MimeMap element");
-                }
-
-                //put property
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_FILEEXT, pwzData);
-                ExitOnFailure(hr, "Failed set mimemap extension property");
-
-                //get type
-                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-                ExitOnFailure(hr, "Failed to read mimemap type");
-                //put property
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_MIMETYPE, pwzData);
-                ExitOnFailure(hr, "Failed set mimemap type property");
-
-                break;
-            }
-            default:
-            {
-                ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for mimeMap");
-                break;
-            }
-        }
-
-        if (!fFound)
-        {
-            //  put mimeMap element at beginning of list
-            hr = pCollection->AddElement(pElement, -1);
-            ExitOnFailure(hr, "Failed add mimemap");
-        }
-
-        // Get AppExt action
-        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-        ExitOnFailure(hr, "Failed to read mimemap action");
-
-        ReleaseNullObject(pElement);
-    }
-
-LExit:
-    ReleaseStr(pwzConfigPath);
-    ReleaseStr(pwzWebName);
-    ReleaseStr(pwzWebRoot);
-    ReleaseStr(pwzData);
-    ReleaseObject(pSection);
-    ReleaseObject(pElement);
-    ReleaseObject(pCollection);
-
-    return hr;
-}
-
-//-------------------------------------------------------------------------------------------------
-// IIS7DirProperties
-//  ProcessesVdir Properties  CA Data
-//
-//
-//-------------------------------------------------------------------------------------------------
-HRESULT IIS7DirProperties(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    )
-{
-    HRESULT hr = S_OK;
-    WCHAR wcTime[60];
-    LPWSTR pwzConfigPath = NULL;
-    LPWSTR pwzWebName = NULL;
-    LPWSTR pwzWebRoot = NULL;
-    LPWSTR pwzData = NULL;
-    int iAction = -1;
-    int iData   =  0;
-    DWORD dwData = 0;
-
-    IAppHostElement *pSection = NULL;
-    IAppHostElement *pElement = NULL;
-    IAppHostElementCollection *pCollection = NULL;
-
-    //get web name
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzWebName);
-    ExitOnFailure(hr, "Failed to read DirProp Web name key");
-
-    //get vdir root name
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzWebRoot);
-    ExitOnFailure(hr, "Failed to read DirProp Web name key");
-
-    //Construct config root
-    hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s",  IIS_CONFIG_APPHOST_ROOT, pwzWebName);
-    ExitOnFailure(hr, "failed to format mime map config path web name");
-    //
-    //Do not append trailing '/' for default vDir
-    //
-    if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzWebRoot, -1, L"/", -1))
-    {
-        hr = StrAllocConcat(&pwzConfigPath, L"/", 0);
-        ExitOnFailure(hr, "failed to copy appext config path delim");
-        hr = StrAllocConcat(&pwzConfigPath, pwzWebRoot, 0);
-        ExitOnFailure(hr, "failed to copy appext config path root name");
-    }
-
-    // Get DirProps action
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-    ExitOnFailure(hr, "Failed to read DirProps action");
-
-    while (IIS_DIRPROP_END != iAction)
-    {
-        //Process property action
-        switch (iAction)
-        {
-            case IIS_DIRPROP_ACCESS :
-            {
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read DirProps access");
-                //iData contains bit flags for <handlers accessPolicy="">
-                //no translation required
-                //get admin section at config path location tag
-                hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_HANDLERS_SECTION), pwzConfigPath, &pSection);
-                ExitOnFailure(hr, "Failed get handlers section for DirProp");
-                if (!pSection)
-                {
-                    hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-                    ExitOnFailure(hr, "Failed get handlers section object for DirProps");
-                }
-                dwData = iData;
-                hr = Iis7PutPropertyInteger( pSection, L"accessPolicy", dwData);
-                ExitOnFailure(hr, "Failed set accessPolicy for DirProps");
-                ReleaseNullObject(pSection);
-                break;
-            }
-            case IIS_DIRPROP_USER :
-            {
-                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-                ExitOnFailure(hr, "Failed to read DirProps user");
-                hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/anonymousAuthentication"), pwzConfigPath, &pSection);
-                ExitOnFailure(hr, "Failed get AnonymousAuthentication section for DirProp");
-                hr = Iis7PutPropertyString( pSection, IIS_CONFIG_USERNAME, pwzData);
-                ExitOnFailure(hr, "Failed set accessPolicy for DirProps");
-                ReleaseNullObject(pSection);
-                break;
-            }
-            case IIS_DIRPROP_PWD :
-            {
-                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-                ExitOnFailure(hr, "Failed to read DirProps pwd");
-                hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/anonymousAuthentication"), pwzConfigPath, &pSection);
-                ExitOnFailure(hr, "Failed get AnonymousAuthentication section for DirProp");
-                hr = Iis7PutPropertyString( pSection, IIS_CONFIG_PASSWORD, pwzData);
-                ExitOnFailure(hr, "Failed set accessPolicy for DirProps");
-                ReleaseNullObject(pSection);
-                break;
-            }
-            case IIS_DIRPROP_DEFDOCS :
-            {
-                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-                ExitOnFailure(hr, "Failed to read DirProps def doc");
-                hr = SetDirPropDefDoc(pAdminMgr, pwzConfigPath, pwzData);
-                ExitOnFailure(hr, "Failed to set DirProps Default Documents");
-                break;
-            }
-            case IIS_DIRPROP_AUTH :
-            {
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read DirProps auth");
-                //iData contains bit flags for /security/authentication/<...>
-                // Anonymous    = 1
-                // Basic        = 2
-                // Windows      = 4
-                // Digest       =16
-                // Passport     =64  *not supported
-                //translation required from bit map to section
-                // E.G security/authentication/windowsAuthentication [property enabled true|false]
-                dwData= iData;
-                hr = SetDirPropAuthentications(pAdminMgr, pwzConfigPath, dwData);
-                ExitOnFailure(hr, "Failed set Authentication for DirProps");
-                break;
-            }
-            case IIS_DIRPROP_SSLFLAGS :
-            {
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read DirProps sslFlags");
-                //iData contains bit flags for /security/access sslFlags
-                //no translation required
-                hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/access"), pwzConfigPath, &pSection);
-                ExitOnFailure(hr, "Failed get security/access section for DirProp");
-                dwData = iData;
-                hr = Iis7PutPropertyInteger( pSection, L"sslFlags", dwData);
-                ExitOnFailure(hr, "Failed set security/access for DirProps");
-                ReleaseNullObject(pSection);
-                break;
-            }
-            case IIS_DIRPROP_AUTHPROVID :
-            {
-                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-                ExitOnFailure(hr, "Failed to read DirProps auth provider");
-                hr = SetDirPropAuthProvider(pAdminMgr, pwzConfigPath, pwzData);
-                ExitOnFailure(hr, "Failed to set DirProps auth provider");
-                break;
-            }
-            case IIS_DIRPROP_ASPERROR:
-            {
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read DirProps aspDetailedError");
-                hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_ASP_SECTION), pwzConfigPath, &pSection);
-                ExitOnFailure(hr, "Failed get asp section for DirProp");
-                hr = Iis7PutPropertyBool(pSection, IIS_CONFIG_SCRIPTERROR, iData);
-                ExitOnFailure(hr, "Failed to set DirProps aspDetailedError");
-                ReleaseNullObject(pSection);
-                break;
-            }
-            case IIS_DIRPROP_HTTPEXPIRES:
-            {
-                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-                ExitOnFailure(hr, "Failed to read DirProps httpExpires provider");
-                hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_STATICCONTENT_SECTION), pwzConfigPath, &pSection);
-                ExitOnFailure(hr, "Failed get staticContent section for DirProp");
-                hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_CLIENTCACHE), &pElement);
-                ExitOnFailure(hr, "Failed to get clientCache element");
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_HTTPEXPIRES, pwzData);
-                ExitOnFailure(hr, "Failed to set clientCache httpExpires value");
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_CACHECONTROLMODE, IIS_CONFIG_USEEXPIRES);
-                ExitOnFailure(hr, "Failed to set clientCache cacheControlMode value");
-                ReleaseNullObject(pSection);
-                ReleaseNullObject(pElement);
-                break;
-            }
-            case IIS_DIRPROP_MAXAGE:
-            {
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read DirProps httpExpires provider");
-                hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_STATICCONTENT_SECTION), pwzConfigPath, &pSection);
-                ExitOnFailure(hr, "Failed get staticContent section for DirProp");
-                hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_CLIENTCACHE), &pElement);
-                ExitOnFailure(hr, "Failed to get clientCache element");
-                *wcTime = '\0';
-                ConvSecToDHMS(iData, wcTime, countof(wcTime));
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_MAXAGE, wcTime);
-                ExitOnFailure(hr, "Failed to set clientCache maxAge value");
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_CACHECONTROLMODE, IIS_CONFIG_USEMAXAGE);
-                ExitOnFailure(hr, "Failed to set clientCache cacheControlMode value");
-                ReleaseNullObject(pSection);
-                ReleaseNullObject(pElement);
-                break;
-            }
-            case IIS_DIRPROP_CACHECUST:
-            {
-                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-                ExitOnFailure(hr, "Failed to read DirProps cacheControlCustom");
-                hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_STATICCONTENT_SECTION), pwzConfigPath, &pSection);
-                ExitOnFailure(hr, "Failed get staticContent section for DirProp");
-                hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_CLIENTCACHE), &pElement);
-                ExitOnFailure(hr, "Failed to get clientCache element");
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_CACHECUST, pwzData);
-                ExitOnFailure(hr, "Failed to set clientCache cacheControlCustom value");
-                ReleaseNullObject(pSection);
-                ReleaseNullObject(pElement);
-                break;
-            }
-            case IIS_DIRPROP_NOCUSTERROR:
-            {
-                //no value, if have ID tag write clear to system.webServer/httpErrors
-                //error collection
-                hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_HTTPERRORS_SECTION), pwzConfigPath, &pSection);
-                ExitOnFailure(hr, "Failed get httperrors section for DirProp");
-                hr = pSection->get_Collection(&pCollection);
-                ExitOnFailure(hr, "Failed get error collection for DirProp");
-                hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_CLEAR), &pElement);
-                ExitOnFailure(hr, "Failed to create clear element for error collection for DirProp");
-                hr = pCollection->AddElement(pElement);
-                ExitOnFailure(hr, "Failed to add lear element for error collection for DirProp");
-                ReleaseNullObject(pSection);
-                ReleaseNullObject(pElement);
-                break;
-            }
-            case IIS_DIRPROP_LOGVISITS:
-            {
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read DirProps logVisits");
-                hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_HTTPLOGGING_SECTION), pwzConfigPath, &pSection);
-                ExitOnFailure(hr, "Failed get httpLogging section for DirProp");
-                hr = Iis7PutPropertyBool(pSection, IIS_CONFIG_DONTLOG, iData);
-                ExitOnFailure(hr, "Failed to set DirProps aspDetailedError");
-                ReleaseNullObject(pSection);
-                break;
-            }
-            default:
-            {
-                ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for WebDirProperties");
-                break;
-            }
-        }
-
-        // Get AppExt action
-        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-        ExitOnFailure(hr, "Failed to read DirProps Property action");
-    }
-LExit:
-    ReleaseStr(pwzConfigPath);
-    ReleaseStr(pwzWebName);
-    ReleaseStr(pwzWebRoot);
-    ReleaseStr(pwzData);
-    ReleaseObject(pSection);
-    ReleaseObject(pElement);
-    ReleaseObject(pCollection);
-
-    return hr;
-}
-
-//-------------------------------------------------------------------------------------------------
-// IIS7SslBinding
-//  ProcessesVdir Properties  CA Data
-//
-//
-//-------------------------------------------------------------------------------------------------
-HRESULT IIS7SslBinding(
-    __inout  LPWSTR *ppwzCustomActionData,
-    __in     IAppHostWritableAdminManager *pAdminMgr
-    )
-{
-    HRESULT hr = S_OK;
-    int iAction = -1;
-    BOOL fSiteFound = FALSE;
-
-    LPWSTR pwzSiteName = NULL;
-    LPWSTR pwzStoreName = NULL;
-    LPWSTR pwzEncodedCertificateHash = NULL;
-
-    IAppHostElement *pSiteElem = NULL;
-
-    // Get Application action
-    hr = WcaReadIntegerFromCaData( ppwzCustomActionData, &iAction);
-    ExitOnFailure(hr, "Failed to read binding action");
-
-    //get site key name
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
-    ExitOnFailure(hr, "Failed to read binding site name key");
-
-    //get binding protocol
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzStoreName);
-    ExitOnFailure(hr, "Failed to read binding protocol");
-
-    //get binding info
-    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzEncodedCertificateHash);
-    ExitOnFailure(hr, "Failed to read binding info");
-
-    //Get site if it exists
-    hr = GetSiteElement(pAdminMgr, pwzSiteName, &pSiteElem, &fSiteFound);
-    ExitOnFailure(hr, "Failed to read sites from config");
-
-    if (IIS_CREATE == iAction)
-    {
-        if (fSiteFound)
-        {
-            //add SSL cert to binding
-            hr = CreateSslBinding(pSiteElem, pwzStoreName, pwzEncodedCertificateHash);
-            ExitOnFailure(hr, "Failed to create site binding");
-        }
-        else
-        {
-            hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-            ExitOnFailure(hr, "Site not found for create binding");
-        }
-    }
-    else if (IIS_DELETE == iAction)
-    {
-        if (fSiteFound)
-        {
-            //delete binding
-            hr = DeleteSslBinding(pSiteElem, pwzStoreName, pwzEncodedCertificateHash);
-            ExitOnFailure(hr, "Failed to delete binding");
-        }
-    }
-
- LExit:
-    ReleaseStr(pwzSiteName);
-    ReleaseStr(pwzStoreName);
-    ReleaseStr(pwzEncodedCertificateHash);
-    ReleaseObject(pSiteElem);
-
-    return hr;
-}
-
-//-------------------------------------------------------------------------------------------------
-// Helper Functions
-//
-//
-//
-//-------------------------------------------------------------------------------------------------
-
-static HRESULT GetNextAvailableSiteId(
-    IAppHostElementCollection *pCollection,
-    DWORD *plSiteId
-    )
-{
-   HRESULT hr = S_OK;
-   IAppHostElement *pElement = NULL;
-   IAppHostProperty *pProperty = NULL;
-
-   DWORD cSites;
-   DWORD plNextAvailSite  = 0;
-   VARIANT vPropValue;
-   VARIANT vtIndex;
-
-   VariantInit(&vPropValue);
-   VariantInit(&vtIndex);
-
-   *plSiteId = 0;
-
-    hr = pCollection->get_Count(&cSites);
-    ExitOnFailure(hr, "Failed get sites collection count");
-
-    vtIndex.vt = VT_UI4;
-    for (DWORD i = 0; i < cSites; ++i)
-    {
-        vtIndex.ulVal = i;
-        hr = pCollection->get_Item(vtIndex , &pElement);
-        ExitOnFailure(hr, "Failed get sites collection item");
-
-        hr = pElement->GetPropertyByName(ScopeBSTR(IIS_CONFIG_ID), &pProperty);
-        ExitOnFailure(hr, "Failed get site property");
-
-        hr = pProperty->get_Value(&vPropValue);
-        ExitOnFailure(hr, "Failed get site property value");
-
-        *plSiteId = vPropValue.lVal;
-        if (*plSiteId > plNextAvailSite)
-        {
-            plNextAvailSite = *plSiteId;
-        }
-        ReleaseNullObject(pElement);
-        ReleaseNullObject(pProperty);
-    }
-    *plSiteId = ++plNextAvailSite;
-
-LExit:
-    ReleaseVariant(vPropValue);
-    ReleaseVariant(vtIndex);
-
-    ReleaseObject(pElement);
-    ReleaseObject(pProperty);
-
-    return hr;
-}
-
-static HRESULT GetSiteElement(
-    IAppHostWritableAdminManager *pAdminMgr,
-    LPCWSTR swSiteName,
-    IAppHostElement **ppSiteElement,
-    BOOL* fFound
-    )
-{
-   HRESULT hr = S_OK;
-   IAppHostElement *pSites = NULL;
-   IAppHostElementCollection *pCollection = NULL;
-
-   *fFound = FALSE;
-
-    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_SITES_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pSites);
-    ExitOnFailure(hr, "Failed get sites section");
-    ExitOnNull(pSites, hr, ERROR_FILE_NOT_FOUND, "Failed get sites section object");
-
-    hr = pSites->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get sites collection");
-
-    hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_SITE, IIS_CONFIG_NAME, swSiteName, ppSiteElement, NULL);
-    ExitOnFailure(hr, "Failed to find site %ls", swSiteName);
-
-    *fFound = ppSiteElement != NULL && *ppSiteElement != NULL;
-
-LExit:
-    ReleaseObject(pSites);
-    ReleaseObject(pCollection);
-
-    return hr;
-}
-
-static HRESULT GetApplicationElement( IAppHostElement *pSiteElement,
-                                      LPCWSTR swAppPath,
-                                      IAppHostElement **ppAppElement,
-                                      BOOL* fFound)
-{
-   HRESULT hr = S_OK;
-   IAppHostElementCollection *pCollection = NULL;
-
-   *fFound = FALSE;
-
-    hr = pSiteElement->get_Collection( &pCollection);
-    ExitOnFailure(hr, "Failed get site app collection");
-
-    hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_APPLICATION, IIS_CONFIG_PATH, swAppPath, ppAppElement, NULL);
-    ExitOnFailure(hr, "Failed to find app %ls", swAppPath);
-
-    *fFound = ppAppElement != NULL && *ppAppElement != NULL;
-
-LExit:
-    ReleaseObject(pCollection);
-
-    return hr;
-}
-
-static HRESULT GetApplicationElementForVDir( IAppHostElement *pSiteElement,
-                                             LPCWSTR pwzVDirPath,
-                                             IAppHostElement **ppAppElement,
-                                             LPCWSTR *ppwzVDirSubPath,
-                                             BOOL* fFound)
-{
-    HRESULT hr = S_OK;
-    IAppHostElementCollection *pCollection = NULL;
-    LPWSTR pwzAppPath = NULL;
-    *fFound = FALSE;
-    *ppwzVDirSubPath = NULL;
-
-    hr = pSiteElement->get_Collection( &pCollection);
-    ExitOnFailure(hr, "Failed get site app collection");
-
-    // Start with full path
-    int iLastPathIndex = lstrlenW(pwzVDirPath) - 1;
-    hr = StrAllocString(&pwzAppPath, pwzVDirPath, 0);
-    ExitOnFailure(hr, "Failed allocate application path");
-
-    for (int iSubPathIndex = iLastPathIndex; (iSubPathIndex >= 0) && (!*fFound); --iSubPathIndex)
-    {
-        // We are looking at the full path, or at a directory boundary, or at the root
-        if (iSubPathIndex == iLastPathIndex ||
-            '/' == pwzAppPath[iSubPathIndex] ||
-            0 == iSubPathIndex)
-        {
-            // break the path if needed
-            if ('/' == pwzAppPath[iSubPathIndex])
-            {
-                pwzAppPath[iSubPathIndex] = '\0';
-            }
-
-            // Special case for root path, need an empty app path
-            LPCWSTR pwzAppSearchPath = 0 == iSubPathIndex ? L"/" : pwzAppPath;
-
-            // Try to find an app with the specified path
-            hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_APPLICATION, IIS_CONFIG_PATH, pwzAppSearchPath, ppAppElement, NULL);
-            ExitOnFailure(hr, "Failed to search for app %ls", pwzAppSearchPath);
-            *fFound = ppAppElement != NULL && *ppAppElement != NULL;
-
-            if (*fFound)
-            {
-                // set return value for sub path
-                // special case for app path == vdir path, need an empty subpath.
-                *ppwzVDirSubPath = (iSubPathIndex == iLastPathIndex) ? L"/" : pwzVDirPath + iSubPathIndex;
-            }
-        }
-    }
-
-LExit:
-    ReleaseObject(pCollection);
-    ReleaseStr(pwzAppPath);
-
-    return hr;
-}
-
-static HRESULT CreateSite(
-    __in IAppHostElementCollection *pCollection,
-    __in LPCWSTR swSiteName,
-    __out IAppHostElement **pSiteElement
-    )
-{
-    HRESULT hr = S_OK;
-    IAppHostElement *pNewElement = NULL;
-
-    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_SITE), &pNewElement);
-    ExitOnFailure(hr, "Failed create site element");
-
-    hr = Iis7PutPropertyString(pNewElement, IIS_CONFIG_NAME, swSiteName);
-    ExitOnFailure(hr, "Failed set site name property");
-
-    DWORD lSiteId = 0;
-    hr = GetNextAvailableSiteId(pCollection, &lSiteId);
-    ExitOnFailure(hr, "Failed get next site id");
-
-    Iis7PutPropertyInteger(pNewElement, IIS_CONFIG_ID, lSiteId);
-    ExitOnFailure(hr, "Failed set site id property");
-
-    hr = pCollection->AddElement(pNewElement);
-    ExitOnFailure(hr, "Failed add site element");
-
-    *pSiteElement = pNewElement;
-    pNewElement = NULL;
-
-LExit:
-    ReleaseObject(pNewElement);
-
-    return hr;
-}
-
-static HRESULT CreateApplication(
-    IAppHostElement *pSiteElement,
-    LPCWSTR swAppPath,
-    IAppHostElement **pAppElement
-    )
-{
-    HRESULT hr = S_OK;
-    IAppHostElement *pNewElement = NULL;
-    IAppHostElementCollection *pCollection = NULL;
-
-    hr = pSiteElement->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get application collection");
-
-    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_APPLICATION), &pNewElement);
-    ExitOnFailure(hr, "Failed get application element");
-
-    hr = Iis7PutPropertyString(pNewElement, IIS_CONFIG_PATH, swAppPath);
-    ExitOnFailure(hr, "Failed set application path property");
-
-    hr = pCollection->AddElement(pNewElement);
-    ExitOnFailure(hr, "Failed add application to collection");
-
-    *pAppElement = pNewElement;
-    pNewElement = NULL;
-
-LExit:
-    ReleaseObject(pCollection);
-    ReleaseObject(pNewElement);
-
-    return hr;
-}
-
-static HRESULT DeleteApplication(
-    IAppHostElement *pSiteElement,
-    LPCWSTR swAppPath
-    )
-{
-    HRESULT hr = S_OK;
-    IAppHostElementCollection *pCollection = NULL;
-
-    hr = pSiteElement->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get application collection");
-
-    hr = DeleteCollectionElement(pCollection, IIS_CONFIG_APPLICATION, IIS_CONFIG_PATH, swAppPath);
-    ExitOnFailure(hr, "Failed to delete website");
-
-LExit:
-    ReleaseObject(pCollection);
-
-    return hr;
-}
-
-static HRESULT SetAppPool(
-    IAppHostElement *pAppElement,
-    LPCWSTR pwzAppPool
-    )
-{
-    HRESULT hr = S_OK;
-
-    if (*pwzAppPool != 0)
-    {
-        hr = Iis7PutPropertyString(pAppElement, IIS_CONFIG_APPPOOL, pwzAppPool);
-        ExitOnFailure(hr, "Failed set application appPool property");
-    }
-LExit:
-    return hr;
-}
-
-static HRESULT CreateVdir(
-    IAppHostElement *pAppElement,
-    LPCWSTR pwzVDirPath,
-    LPCWSTR pwzVDirPhyDir
-    )
-{
-    HRESULT hr = S_OK;
-    IAppHostElement *pElement = NULL;
-    IAppHostElementCollection *pCollection = NULL;
-    BOOL fFound;
-
-    hr = pAppElement->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get application VDir collection");
-
-    hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_VDIR, IIS_CONFIG_PATH, pwzVDirPath, &pElement, NULL);
-    ExitOnFailure(hr, "Failed while finding virtualDir");
-    fFound = (NULL != pElement);
-
-    if (!fFound)
-    {
-        hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_VDIR), &pElement);
-        ExitOnFailure(hr, "Failed create application VDir collection");
-
-        hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PATH, pwzVDirPath);
-        ExitOnFailure(hr, "Failed set VDir path property");
-    }
-
-    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PHYSPATH, pwzVDirPhyDir);
-    ExitOnFailure(hr, "Failed set VDir phys path property");
-
-    if (!fFound)
-    {
-        hr = pCollection->AddElement(pElement);
-        ExitOnFailure(hr, "Failed add application VDir element");
-    }
-
-LExit:
-    ReleaseObject(pCollection);
-    ReleaseObject(pElement);
-
-    return hr;
-}
-
-static HRESULT DeleteVdir(
-    IAppHostElement *pAppElement,
-    LPCWSTR pwzVDirPath
-    )
-{
-    HRESULT hr = S_OK;
-    IAppHostElementCollection *pCollection = NULL;
-
-    hr = pAppElement->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get application VDir collection");
-
-    hr = DeleteCollectionElement(pCollection, IIS_CONFIG_VDIR, IIS_CONFIG_PATH, pwzVDirPath);
-    ExitOnFailure(hr, "Failed to delete vdir");
-
-LExit:
-    ReleaseObject(pCollection);
-
-    return hr;
-}
-
-static HRESULT CreateBinding(
-    IAppHostElement *pSiteElem,
-    LPCWSTR pwzProtocol,
-    LPCWSTR pwzInfo
-    )
-{
-    HRESULT hr = S_OK;
-    IAppHostChildElementCollection *pChildElems = NULL;
-    IAppHostElement *pBindings = NULL;
-    IAppHostElement *pBindingElement = NULL;
-    IAppHostElementCollection *pCollection = NULL;
-
-    VARIANT vtProp;
-
-    VariantInit(&vtProp);
-
-    hr = pSiteElem->get_ChildElements(&pChildElems);
-    ExitOnFailure(hr, "Failed get site child elements collection");
-
-    vtProp.vt = VT_BSTR;
-    vtProp.bstrVal = ::SysAllocString(IIS_CONFIG_BINDINGS);
-    hr = pChildElems->get_Item(vtProp, &pBindings);
-    ExitOnFailure(hr, "Failed get bindings element");
-    ReleaseVariant(vtProp);
-
-    hr = pBindings->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get bindings collection");
-
-    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_BINDING), &pBindingElement);
-    ExitOnFailure(hr, "Failed get binding element");
-
-    hr = Iis7PutPropertyString(pBindingElement, IIS_CONFIG_PROTOCOL, pwzProtocol);
-    ExitOnFailure(hr, "Failed set binding protocol property");
-
-    hr = Iis7PutPropertyString(pBindingElement, IIS_CONFIG_BINDINGINFO, pwzInfo);
-    ExitOnFailure(hr, "Failed set binding information property");
-
-    hr = pCollection->AddElement(pBindingElement);
-    if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS))
-    {
-        //Eat this error. Binding is there and nothing to repair since
-        //identity == protocol + info so all is OK
-        hr = S_OK;
-    }
-    else
-    {
-        ExitOnFailure(hr, "Failed add binding to site");
-    }
-
-LExit:
-    ReleaseVariant(vtProp);
-
-    ReleaseObject(pCollection);
-    ReleaseObject(pChildElems);
-    ReleaseObject(pBindingElement);
-    ReleaseObject(pBindings);
-
-    return hr;
-}
-static HRESULT CreateWebLog(
-    IAppHostElement *pSiteElem,
-    LPCWSTR pwzFormat
-    )
-{
-    HRESULT hr = S_OK;
-    IAppHostChildElementCollection *pChildElems = NULL;
-    IAppHostElement *pLogFile = NULL;
-
-    VARIANT vtProp;
-
-    VariantInit(&vtProp);
-
-    hr = pSiteElem->get_ChildElements(&pChildElems);
-    ExitOnFailure(hr, "Failed get site child elements collection");
-
-    vtProp.vt = VT_BSTR;
-    vtProp.bstrVal = ::SysAllocString(IIS_CONFIG_WEBLOG);
-    hr = pChildElems->get_Item(vtProp, &pLogFile);
-    ExitOnFailure(hr, "Failed get logfile element");
-    ReleaseVariant(vtProp);
-
-    if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzFormat, -1, L"none", -1))
-    {
-        hr = Iis7PutPropertyString(pLogFile, IIS_CONFIG_LOGFORMAT, pwzFormat);
-        ExitOnFailure(hr, "Failed set logfile format property");
-        hr = Iis7PutPropertyString(pLogFile, IIS_CONFIG_ENABLED, IIS_CONFIG_TRUE);
-        ExitOnFailure(hr, "Failed set logfile enabled property");
-    }
-    else
-    {
-        hr = Iis7PutPropertyString(pLogFile, IIS_CONFIG_ENABLED, IIS_CONFIG_FALSE);
-        ExitOnFailure(hr, "Failed set logfile enabled property");
-    }
-
-LExit:
-    ReleaseVariant(vtProp);
-
-    ReleaseObject(pLogFile);
-    ReleaseObject(pChildElems);
-
-    return hr;
-}
-
-static HRESULT DeleteBinding(
-    IAppHostElement* /*pSiteElem*/,
-    LPCWSTR /*pwzProtocol*/,
-    LPCWSTR /*pwzInfo*/
-    )
-{
-    HRESULT hr = S_OK;
-    //
-    //this isn't supported right now, we should support this for the SiteSearch scenario
-    return hr;
-}
-
-struct SCA_SSLBINDINGINFO
-{
-    IIS7_APPHOSTELEMENTCOMPARISON comparison;
-    LPCWSTR pwzStoreName;
-    LPCWSTR pwzEncodedCertificateHash;
-    HRESULT hr;
-};
-
-static BOOL AddSslCertificateToBindingCallback(IAppHostElement *pBindingElement, LPVOID pContext)
-{
-    HRESULT hr = S_OK;
-    VARIANT vtProp;
-    VariantInit(&vtProp);
-    SCA_SSLBINDINGINFO* pBindingInfo = (SCA_SSLBINDINGINFO*)pContext;
-    IAppHostMethodCollection *pAppHostMethodCollection = NULL;
-    IAppHostMethod *pAddSslMethod = NULL;
-    IAppHostMethodInstance *pAddSslMethodInstance = NULL;
-    IAppHostElement *pAddSslInput = NULL;
-    int iWsaError = 0;
-    WSADATA wsaData = {};
-    BOOL fWsaInitialized = FALSE;
-
-    // IIS's AddSslCertificate doesn't initialize WinSock on 2008 before using it to parse the IP
-    // Initialize before calling to workaround the failure.
-    iWsaError = WSAStartup(MAKEWORD(2, 2), &wsaData);
-    if (0 != iWsaError)
-    {
-        ExitOnWin32Error(iWsaError, hr, "Failed to initialize WinSock");
-    }
-
-    fWsaInitialized = TRUE;
-
-    if (Iis7IsMatchingAppHostElement(pBindingElement, &pBindingInfo->comparison))
-    {
-        hr = pBindingElement->get_Methods(&pAppHostMethodCollection);
-        ExitOnFailure(hr, "failed to get binding method collection");
-
-        hr = Iis7FindAppHostMethod(pAppHostMethodCollection, L"AddSslCertificate", &pAddSslMethod, NULL);
-        if (FAILED(hr))
-        {
-            WcaLog(LOGMSG_STANDARD, "The AddSslCertificate method is not supported by the binding element, SSL certificate will not be associated with the website");
-            ExitFunction();
-        }
-
-        pAddSslMethod->CreateInstance(&pAddSslMethodInstance);
-        ExitOnFailure(hr, "failed to create an instance of AddSslCertificate method");
-
-        pAddSslMethodInstance->get_Input(&pAddSslInput);
-        ExitOnFailure(hr, "failed to get input element of AddSslCertificate method");
-
-        Iis7PutPropertyString(pAddSslInput, IIS_CONFIG_CERTIFICATESTORENAME, pBindingInfo->pwzStoreName);
-        ExitOnFailure(hr, "failed to set certificateStoreName input parameter of AddSslCertificate method");
-
-        Iis7PutPropertyString(pAddSslInput, IIS_CONFIG_CERTIFICATEHASH, pBindingInfo->pwzEncodedCertificateHash);
-        ExitOnFailure(hr, "failed to set certificateHash input parameter of AddSslCertificate method");
-
-        hr = pAddSslMethodInstance->Execute();
-        ExitOnFailure(hr, "failed to execute AddSslCertificate method");
-    }
-LExit:
-    pBindingInfo->hr = hr;
-    ReleaseObject(pAppHostMethodCollection);
-    ReleaseObject(pAddSslMethod);
-    ReleaseObject(pAddSslMethodInstance);
-    ReleaseObject(pAddSslInput);
-    if (fWsaInitialized)
-    {
-        WSACleanup();
-    }
-
-    return FAILED(hr);
-}
-
-static HRESULT CreateSslBinding( IAppHostElement *pSiteElem, LPCWSTR pwzStoreName, LPCWSTR pwzEncodedCertificateHash)
-{
-    HRESULT hr = S_OK;
-    IAppHostChildElementCollection *pChildElems = NULL;
-    IAppHostElement *pBindingsElement = NULL;
-    IAppHostElementCollection *pBindingsCollection = NULL;
-    SCA_SSLBINDINGINFO bindingInfo = {};
-    VARIANT vtProp;
-    VariantInit(&vtProp);
-
-    hr = pSiteElem->get_ChildElements(&pChildElems);
-    ExitOnFailure(hr, "Failed get site child elements collection");
-
-    vtProp.vt = VT_BSTR;
-    vtProp.bstrVal = ::SysAllocString(IIS_CONFIG_BINDINGS);
-    hr = pChildElems->get_Item(vtProp, &pBindingsElement);
-    ExitOnFailure(hr, "Failed get bindings element");
-    ReleaseVariant(vtProp);
-
-    hr = pBindingsElement->get_Collection(&pBindingsCollection);
-    ExitOnFailure(hr, "Failed get bindings collection");
-
-    bindingInfo.comparison.sczElementName = IIS_CONFIG_BINDING;
-    bindingInfo.comparison.sczAttributeName = IIS_CONFIG_PROTOCOL;
-    vtProp.vt = VT_BSTR;
-    vtProp.bstrVal = ::SysAllocString(L"https");
-    bindingInfo.comparison.pvAttributeValue = &vtProp;
-    bindingInfo.pwzStoreName = pwzStoreName;
-    bindingInfo.pwzEncodedCertificateHash = pwzEncodedCertificateHash;
-
-    // Our current IISWebSiteCertificates schema does not allow specification of the website binding
-    // to associate the certificate with.  For now just associate it with all secure bindings.
-
-    hr = Iis7EnumAppHostElements(pBindingsCollection, AddSslCertificateToBindingCallback, &bindingInfo, NULL, NULL);
-    ExitOnFailure(hr, "Failed to enumerate bindings collection");
-    hr = bindingInfo.hr;
-    ExitOnFailure(hr, "Failed to add ssl binding");
-
-LExit:
-    ReleaseVariant(vtProp);
-
-    ReleaseObject(pChildElems);
-    ReleaseObject(pBindingsElement);
-    ReleaseObject(pBindingsCollection);
-
-    return hr;
-}
-
-static HRESULT DeleteSslBinding(
-    IAppHostElement * /*pSiteElem*/,
-    LPCWSTR /*pwzStoreName*/,
-    LPCWSTR /*pwzEncodedCertificateHash*/
-    )
-{
-    HRESULT hr = S_OK;
-    //
-    //this isn't supported right now, we should support this for the SiteSearch scenario
-    return hr;
-}
-
-static HRESULT DeleteAppPool( IAppHostWritableAdminManager *pAdminMgr,
-                            LPCWSTR swAppPoolName)
-{
-    HRESULT hr = S_OK;
-    IAppHostElement *pAppPools = NULL;
-    IAppHostElementCollection *pCollection = NULL;
-
-    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_APPPOOL_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pAppPools);
-    ExitOnFailure(hr, "Failed get AppPools section");
-    ExitOnNull(pAppPools, hr, E_UNEXPECTED, "Failed get appPools section object");
-
-    hr = pAppPools->get_Collection( &pCollection);
-    ExitOnFailure(hr, "Failed get AppPools collection");
-
-    hr = DeleteCollectionElement(pCollection, IIS_CONFIG_ADD, IIS_CONFIG_NAME, swAppPoolName);
-    ExitOnFailure(hr, "Failed to delete app pool %ls", swAppPoolName);
-
-LExit:
-    ReleaseObject(pAppPools);
-    ReleaseObject(pCollection);
-
-    return hr;
-}
-
-static HRESULT CreateAppPool(
-    __inout LPWSTR *ppwzCustomActionData,
-    IAppHostWritableAdminManager *pAdminMgr,
-    LPCWSTR swAppPoolName
-    )
-{
-    HRESULT hr = S_OK;
-    IAppHostElement *pAppPools = NULL;
-    IAppHostElement *pAppPoolElement = NULL;
-    IAppHostElement *pElement = NULL;
-    IAppHostElement *pElement2 = NULL;
-    IAppHostElement *pElement3 = NULL;
-    IAppHostElementCollection *pCollection = NULL;
-    IAppHostElementCollection *pCollection2 = NULL;
-    int iAction = -1;
-    int iData   =  0;
-    LPWSTR pwzData = NULL;
-    WCHAR wcData[512];
-    WCHAR wcTime[60];
-    BOOL fFound = FALSE;
-
-    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_APPPOOL_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pAppPools);
-    ExitOnFailure(hr, "Failed get AppPools section");
-    ExitOnNull(pAppPools, hr, ERROR_FILE_NOT_FOUND, "Failed get AppPools section object");
-
-    hr = pAppPools->get_Collection( &pCollection);
-    ExitOnFailure(hr, "Failed get AppPools collection");
-
-    hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_ADD, IIS_CONFIG_NAME, swAppPoolName, &pAppPoolElement, NULL);
-    ExitOnFailure(hr, "Failed find AppPool element");
-    fFound = (NULL != pAppPoolElement);
-
-    if (!fFound)
-    {
-        hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pAppPoolElement);
-        ExitOnFailure(hr, "Failed create AppPool element");
-    }
-
-    hr = Iis7PutPropertyString(pAppPoolElement, IIS_CONFIG_NAME, swAppPoolName);
-    ExitOnFailure(hr, "Failed set AppPool name property");
-
-    //For WiX II6 /ABO compat we will default managedPipelineMode="Classic"
-    hr = Iis7PutPropertyString(pAppPoolElement, IIS_CONFIG_PIPELINEMODE, L"Classic");
-    ExitOnFailure(hr, "Failed set AppPool managedPipelineMode property");
-    //For WiX II6 /ABO compat we will be hardcoding autostart="true"
-    hr = Iis7PutPropertyString(pAppPoolElement, IIS_CONFIG_APPPOOL_AUTO, L"true");
-    ExitOnFailure(hr, "Failed set AppPool autoStart property");
-
-    if (!fFound)
-    {
-        hr = pCollection->AddElement(pAppPoolElement);
-        ExitOnFailure(hr, "Failed to add appPool element");
-    }
-
-    // Get AppPool Property action
-    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-    ExitOnFailure(hr, "Failed to read AppPool Property action");
-    while (IIS_APPPOOL_END != iAction)
-    {
-        //Process property action
-        switch (iAction)
-        {
-            case IIS_APPPOOL_RECYCLE_MIN :
-            {
-            // /recycling / periodicRestart | time
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read AppPool recycle min");
-                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_RECYCLING), &pElement);
-                ExitOnFailure(hr, "Failed to get AppPool recycling element");
-                hr = pElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PEROIDRESTART), &pElement2);
-                ExitOnFailure(hr, "Failed to get AppPool periodicRestart element");
-                *wcTime = '\0';
-                ConvSecToHMS(iData * 60, wcTime, countof(wcTime));
-                hr = Iis7PutPropertyString(pElement2, IIS_CONFIG_TIME, wcTime);
-                ExitOnFailure(hr, "Failed to set AppPool periodicRestart time value");
-                ReleaseNullObject(pElement);
-                ReleaseNullObject(pElement2);
-                break;
-            }
-            case IIS_APPPOOL_RECYCLE_REQ :
-            {
-            // /recycling / periodicRestart | requests
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read AppPool recycle req");
-                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_RECYCLING), &pElement);
-                ExitOnFailure(hr, "Failed to get AppPool recycling element");
-                hr = pElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PEROIDRESTART), &pElement2);
-                ExitOnFailure(hr, "Failed to get AppPool periodicRestart element");
-                hr = Iis7PutPropertyInteger(pElement2, IIS_CONFIG_REQUESTS, iData);
-                ExitOnFailure(hr, "Failed to set AppPool periodicRestart time value");
-                ReleaseNullObject(pElement);
-                ReleaseNullObject(pElement2);
-                break;
-            }
-            case IIS_APPPOOL_RECYCLE_TIMES :
-            {
-            // /recycling / periodicRestart | schedule
-                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-                ExitOnFailure(hr, "Failed to read AppPool recycle times");
-                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_RECYCLING), &pElement);
-                ExitOnFailure(hr, "Failed to get AppPool recycling element");
-                hr = pElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PEROIDRESTART), &pElement2);
-                ExitOnFailure(hr, "Failed to get AppPool periodicRestart element");
-                hr = pElement2->GetElementByName(ScopeBSTR(IIS_CONFIG_SCHEDULE), &pElement3);
-                ExitOnFailure(hr, "Failed to get AppPool schedule element");
-                hr = pElement3->get_Collection(&pCollection2);
-                ExitOnFailure(hr, "Failed to get AppPool schedule collection");
-
-                WCHAR wcDelim[] = L",";
-                const WCHAR *wszToken = NULL;
-                WCHAR *wszNextToken = NULL;
-                wszToken = wcstok_s( pwzData, wcDelim, &wszNextToken);
-
-                while (wszToken)
-                {
-                    *wcData = '\0';
-                    hr = ::StringCchCopyW(wcData, countof(wcData), wszToken);
-                    ExitOnFailure(hr, "failed to copy AppPool schedule");
-                    hr = ::StringCchCatW(wcData, countof(wcData), L":00");
-                    ExitOnFailure(hr, "failed to append AppPool schedule");
-
-                    hr = pCollection2->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pElement3);
-                    ExitOnFailure(hr, "Failed to create AppPool schedule element");
-
-                    hr = Iis7PutPropertyString(pElement3, IIS_CONFIG_VALUE, wcData);
-                    ExitOnFailure(hr, "Failed to set AppPool schedule value");
-
-                    hr = pCollection2->AddElement(pElement3);
-                    if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS))
-                    {
-                        //Eat this error, recycle time already exists NBD
-                        hr = S_OK;
-                    }
-                    ExitOnFailure(hr, "Failed to add win auth providers element");
-                    ReleaseNullObject(pElement3);
-                    wszToken = wcstok_s( NULL, wcDelim, &wszNextToken);
-                }
-                ReleaseNullObject(pElement);
-                ReleaseNullObject(pElement2);
-                ReleaseNullObject(pElement3);
-                ReleaseNullObject(pCollection2);
-                break;
-            }
-            case IIS_APPPOOL_RECYCLE_VIRMEM :
-            {
-            // /recycling / periodicRestart | memory
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read AppPool recycle vir memory");
-                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_RECYCLING), &pElement);
-                ExitOnFailure(hr, "Failed to get AppPool recycling element");
-                hr = pElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PEROIDRESTART), &pElement2);
-                ExitOnFailure(hr, "Failed to get AppPool periodicRestart element");
-                hr = Iis7PutPropertyInteger(pElement2, IIS_CONFIG_MEMORY, iData);
-                ExitOnFailure(hr, "Failed to set AppPool periodicRestart memory");
-                ReleaseNullObject(pElement);
-                ReleaseNullObject(pElement2);
-                break;
-            }
-            case IIS_APPPOOL_RECYCLE_PRIVMEM :
-            {
-            // /recycling / periodicRestart | privateMemory
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read AppPool recycle priv mem");
-                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_RECYCLING), &pElement);
-                ExitOnFailure(hr, "Failed to get AppPool recycling element");
-                hr = pElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PEROIDRESTART), &pElement2);
-                ExitOnFailure(hr, "Failed to get AppPool periodicRestart element");
-                hr = Iis7PutPropertyInteger(pElement2, IIS_CONFIG_PRIVMEMORY, iData);
-                ExitOnFailure(hr, "Failed to set AppPool periodicRestart private memory");
-                ReleaseNullObject(pElement);
-                ReleaseNullObject(pElement2);
-                break;
-            }
-            case IIS_APPPOOL_RECYCLE_IDLTIMEOUT :
-            {
-            //  /processModel | idleTimeout
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read AppPool idle timeout");
-                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PROCESSMODEL), &pElement);
-                ExitOnFailure(hr, "Failed to get AppPool processModel element");
-                *wcTime = '\0';
-                ConvSecToHMS(iData * 60, wcTime, countof(wcTime));
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_IDLETIMEOUT, wcTime);
-                ExitOnFailure(hr, "Failed to set AppPool processModel idle timeout value");
-                ReleaseNullObject(pElement);
-                break;
-            }
-            case IIS_APPPOOL_RECYCLE_QUEUELIMIT :
-            {
-            //  /applicationPools | queueLength
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read AppPool recycle queue limit");
-                hr = Iis7PutPropertyInteger(pAppPoolElement, IIS_CONFIG_QUEUELENGTH, iData);
-                ExitOnFailure(hr, "Failed to set AppPool recycle queue limit value");
-                break;
-            }
-            case IIS_APPPOOL_MAXPROCESS :
-            {
-            //  /processModel | maxProcesses
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read AppPool max processes");
-                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PROCESSMODEL), &pElement);
-                ExitOnFailure(hr, "Failed to get AppPool processModel element");
-                hr = Iis7PutPropertyInteger(pElement, IIS_CONFIG_MAXWRKPROCESSES, iData);
-                ExitOnFailure(hr, "Failed to set AppPool processModel maxProcesses value");
-                ReleaseNullObject(pElement);
-                break;
-            }
-            case IIS_APPPOOL_IDENTITY :
-            {
-            //"LocalSystem" 0
-            //"LocalService" 1
-            //"NetworkService" 2
-            //"SpecificUser" 3
-            //"ApplicationPoolIdentity" 4
-            //  /processModel | identityType
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read AppPool identity");
-                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PROCESSMODEL), &pElement);
-                ExitOnFailure(hr, "Failed to get AppPool processModel element");
-                if (iData == 0)
-                {
-                    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_IDENITITYTYPE, IIS_CONFIG_LOCALSYSTEM);
-                }
-                else if (iData == 1)
-                {
-                    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_IDENITITYTYPE, IIS_CONFIG_LOCALSERVICE);
-                }
-                else if (iData == 2)
-                {
-                    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_IDENITITYTYPE, IIS_CONFIG_NETWORKSERVICE);
-                }
-                else if (iData == 3)
-                {
-                    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_IDENITITYTYPE, IIS_CONFIG_SPECIFICUSER);
-                }
-                else if (iData == 4)
-                {
-                    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_IDENITITYTYPE, IIS_CONFIG_APPLICATIONPOOLIDENTITY);
-                }
-                ExitOnFailure(hr, "Failed to set AppPool processModel identityType value");
-                ReleaseNullObject(pElement);
-                break;
-            }
-            case IIS_APPPOOL_USER :
-            {
-            //  /processModel | userName
-                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-                ExitOnFailure(hr, "Failed to read AppPool user");
-                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PROCESSMODEL), &pElement);
-                ExitOnFailure(hr, "Failed to get AppPool processModel element");
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_USERNAME, pwzData);
-                ExitOnFailure(hr, "Failed to set AppPool processModel username value");
-                ReleaseNullObject(pElement);
-                break;
-            }
-            case IIS_APPPOOL_PWD :
-            {
-            //  /processModel | password
-                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-                ExitOnFailure(hr, "Failed to read AppPool pwd");
-                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PROCESSMODEL), &pElement);
-                ExitOnFailure(hr, "Failed to get AppPool processModel element");
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PASSWORD, pwzData);
-                ExitOnFailure(hr, "Failed to set AppPool processModel password value");
-                ReleaseNullObject(pElement);
-                break;
-            }
-            case  IIS_APPPOOL_RECYCLE_CPU_PCT:
-            {
-            // /cpu | limit
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read cpu pct");
-                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_CPU), &pElement);
-                ExitOnFailure(hr, "Failed to get AppPool cpu element");
-                // limit is maximum percentage of CPU time (in 1/1000ths of one percent)
-                hr = Iis7PutPropertyInteger(pElement, IIS_CONFIG_LIMIT, iData * 1000);
-                ExitOnFailure(hr, "Failed to set AppPool cpu limit");
-                ReleaseNullObject(pElement);
-                break;
-            }
-            case  IIS_APPPOOL_RECYCLE_CPU_REFRESH:
-            {
-            // /cpu | resetInterval
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read cpu refresh pwd");
-                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_CPU), &pElement);
-                ExitOnFailure(hr, "Failed to get AppPool cpu element");
-                *wcTime = '\0';
-                ConvSecToHMS(iData * 60, wcTime, countof(wcTime));
-                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_RESETINTERVAL, wcTime);
-                ExitOnFailure(hr, "Failed to set AppPool cpu resetInterval value");
-                ReleaseNullObject(pElement);
-                break;
-            }
-            case  IIS_APPPOOL_RECYCLE_CPU_ACTION:
-            {
-            // /cpu | action
-            //"NoAction" 0
-            //"KillW3wp" 1
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read cpu action");
-                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_CPU), &pElement);
-                ExitOnFailure(hr, "Failed to get AppPool cpu element");
-                if (iData)
-                {
-                    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_CPU_ACTION, IIS_CONFIG_KILLW3WP);
-                }
-                else
-                {
-                    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_CPU_ACTION, IIS_CONFIG_NOACTION);
-                }
-                ExitOnFailure(hr, "Failed to set AppPool cpu action value");
-                ReleaseNullObject(pElement);
-                break;
-            }
-            case IIS_APPPOOL_32BIT:
-            {
-                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
-                ExitOnFailure(hr, "Failed to read enable32BitAppOnWin64 value");
-                //  enable32BitAppOnWin64
-                hr = Iis7PutPropertyBool(pAppPoolElement, IIS_CONFIG_ENABLE32, iData ? TRUE : FALSE);
-                ExitOnFailure(hr, "Failed to set AppPool enable32BitAppOnWin64 value");
-                break;
-            }
-            case IIS_APPPOOL_MANAGED_PIPELINE_MODE:
-            {
-                // managedPipelineMode
-                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-                ExitOnFailure(hr, "Failed to read AppPool managedRuntimeVersion");
-                hr = Iis7PutPropertyString(pAppPoolElement, IIS_CONFIG_PIPELINEMODE, pwzData);
-                ExitOnFailure(hr, "Failed set AppPool managedPipelineMode property");
-                break;
-            }
-            case IIS_APPPOOL_MANAGED_RUNTIME_VERSION:
-            {
-                // managedRuntimeVersion
-                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
-                ExitOnFailure(hr, "Failed to read AppPool managedRuntimeVersion");
-                hr = Iis7PutPropertyString(pAppPoolElement, IIS_CONFIG_MANAGEDRUNTIMEVERSION, pwzData);
-                ExitOnFailure(hr, "Failed set AppPool managedRuntimeVersion property");
-                break;
-            }
-
-            default:
-            ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for AppPool");
-            break;
-
-        }
-        // Get AppPool property action
-        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
-        ExitOnFailure(hr, "Failed to read AppPool Property action");
-    }
-
-LExit:
-    ReleaseObject(pAppPools);
-    ReleaseObject(pCollection);
-    ReleaseObject(pCollection2);
-    ReleaseObject(pAppPoolElement);
-    ReleaseObject(pElement);
-    ReleaseObject(pElement2);
-    ReleaseObject(pElement3);
-
-    return hr;
-}
-
-static HRESULT SetDirPropAuthentications(IAppHostWritableAdminManager *pAdminMgr,
-                                         LPCWSTR wszConfigPath,
-                                         DWORD dwData)
-{
-    HRESULT hr = S_OK;
-    IAppHostElement *pSection = NULL;
-
-    //dwData contains bit flags for /security/authentication/<...>
-    // Anonymous    = 1
-    // Basic        = 2
-    // Windows      = 4
-    // Digest       =16
-    // Passport     =64  *not supported
-    //translation required from bit map to section name
-    // E.G security/authentication/windowsAuthentication [property enabled true|false]
-
-    // AnonymousAuthentication = 1
-    hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/anonymousAuthentication"), ScopeBSTR(wszConfigPath), &pSection);
-    ExitOnFailure(hr, "Failed get AnonymousAuthentication section for DirProp");
-    if (!pSection)
-    {
-        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-        ExitOnFailure(hr, "Failed get AnonymousAuthentication section object for DirProps");
-    }
-
-    hr = Iis7PutPropertyBool(pSection, L"enabled", (BOOL)(dwData & 0x1));
-    ExitOnFailure(hr, "Failed set AnonymousAuthentication enabled for DirProps");
-    ReleaseNullObject(pSection);
-
-    // basicAuthentication = 2
-    hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/basicAuthentication"), ScopeBSTR(wszConfigPath), &pSection);
-    ExitOnFailure(hr, "Failed get basicAuthentication section for DirProp");
-    if (!pSection)
-    {
-        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-        ExitOnFailure(hr, "Failed get basicAuthentication section object for DirProps");
-    }
-
-    hr = Iis7PutPropertyBool(pSection, L"enabled", (BOOL)(dwData & 0x2));
-    ExitOnFailure(hr, "Failed set basicAuthentication enabled for DirProps");
-    ReleaseNullObject(pSection);
-
-    // WindowsAuthentication = 4
-    hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/windowsAuthentication"), ScopeBSTR(wszConfigPath), &pSection);
-    ExitOnFailure(hr, "Failed get windowsAuthentication section for DirProp");
-    if (!pSection)
-    {
-        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-        ExitOnFailure(hr, "Failed get windowsAuthentication section object for DirProps");
-    }
-
-    hr = Iis7PutPropertyBool(pSection, L"enabled", (BOOL)(dwData & 0x4));
-    ExitOnFailure(hr, "Failed set windowsAuthentication enabled for DirProps");
-    ReleaseNullObject(pSection);
-
-    // digestAuthentication = 16
-    hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/digestAuthentication"), ScopeBSTR(wszConfigPath), &pSection);
-    ExitOnFailure(hr, "Failed get digestAuthentication section for DirProp");
-    if (!pSection)
-    {
-        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-        ExitOnFailure(hr, "Failed get digestAuthentication section object for DirProps");
-    }
-
-    hr = Iis7PutPropertyBool(pSection, L"enabled", (BOOL)(dwData & 0x10));
-    ExitOnFailure(hr, "Failed set digestAuthentication enabled for DirProps");
-    ReleaseNullObject(pSection);
-
-LExit:
-    ReleaseObject(pSection);
-
-    return hr;
-}
-
-static HRESULT SetDirPropAuthProvider(IAppHostWritableAdminManager *pAdminMgr,
-                                         LPCWSTR wszConfigPath,
-                                         __in LPWSTR wszData)
-{
-    HRESULT hr = S_OK;
-    IAppHostElement *pSection = NULL;
-    IAppHostElement *pElement = NULL;
-    IAppHostElement *pNewElement = NULL;
-    IAppHostElementCollection *pCollection = NULL;
-
-    WCHAR wcDelim[] = L",";
-    const WCHAR *wszToken = NULL;
-    WCHAR *wszNextToken = NULL;
-
-    hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/windowsAuthentication"), ScopeBSTR(wszConfigPath), &pSection);
-    ExitOnFailure(hr, "Failed get windowsAuthentication section for DirProp providers");
-
-    hr = pSection->GetElementByName(ScopeBSTR(L"providers"), &pElement);
-    ExitOnFailure(hr, "Failed get win auth providers section");
-
-    hr = pElement->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get win auth providers collection");
-
-    hr = pCollection->Clear();
-    ExitOnFailure(hr, "Failed to clear win auth providers collection");
-
-    //Clear out inherited items - add clear
-    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_CLEAR), &pNewElement);
-    ExitOnFailure(hr, "Failed to create win auth providers clear element");
-    hr = pCollection->AddElement(pNewElement);
-    ExitOnFailure(hr, "Failed to add win auth providers clear element");
-    ReleaseNullObject(pNewElement);
-
-    wszToken = wcstok_s( wszData, wcDelim, &wszNextToken);
-    for (int i = 0; (wszToken); ++i)
-    {
-        hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pNewElement);
-        ExitOnFailure(hr, "Failed to create win auth providers element");
-
-        hr = Iis7PutPropertyString( pNewElement, IIS_CONFIG_VALUE, wszToken);
-        ExitOnFailure(hr, "Failed to set win auth providers value");
-
-        hr = pCollection->AddElement(pNewElement, i);
-        ExitOnFailure(hr, "Failed to add win auth providers element");
-        ReleaseNullObject(pNewElement);
-
-        wszToken = wcstok_s( NULL, wcDelim, &wszNextToken);
-    }
-
-LExit:
-    ReleaseObject(pSection);
-    ReleaseObject(pCollection);
-    ReleaseObject(pElement);
-    ReleaseObject(pNewElement);
-
-    return hr;
-}
-
-static HRESULT SetDirPropDefDoc(
-    IAppHostWritableAdminManager *pAdminMgr,
-    LPCWSTR wszConfigPath,
-    __in LPWSTR wszData)
-{
-    HRESULT hr = S_OK;
-    IAppHostElement *pSection = NULL;
-    IAppHostElement *pElement = NULL;
-    IAppHostElement *pNewElement = NULL;
-    IAppHostElementCollection *pCollection = NULL;
-
-    WCHAR wcDelim[] = L",";
-    const WCHAR *wszToken = NULL;
-    WCHAR *wszNextToken = NULL;
-
-    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_DEFAULTDOC_SECTION), ScopeBSTR(wszConfigPath), &pSection);
-    ExitOnFailure(hr, "Failed get defaultDocument section for DirProp");
-
-    hr = pSection->GetElementByName(ScopeBSTR(L"files"), &pElement);
-    ExitOnFailure(hr, "Failed get win files section");
-
-    hr = pElement->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get files collection");
-
-    hr = pCollection->Clear();
-    ExitOnFailure(hr, "Failed clear files collection");
-
-    //Clear out inherited items - add clear
-    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_CLEAR), &pNewElement);
-    ExitOnFailure(hr, "Failed to create files clear element");
-    hr = pCollection->AddElement(pNewElement);
-    ExitOnFailure(hr, "Failed to add files clear element");
-
-    wszToken = wcstok_s( wszData, wcDelim, &wszNextToken);
-    for (int i = 0; (wszToken); ++i)
-    {
-        hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pNewElement);
-        ExitOnFailure(hr, "Failed to create win auth providers element");
-
-        hr = Iis7PutPropertyString( pNewElement, IIS_CONFIG_VALUE, wszToken);
-        ExitOnFailure(hr, "Failed to set win auth providers value");
-
-        hr = pCollection->AddElement(pNewElement, i);
-        ExitOnFailure(hr, "Failed to add defaultDocument Files element");
-        ReleaseNullObject(pNewElement);
-
-        wszToken = wcstok_s( NULL, wcDelim, &wszNextToken);
-    }
-
-LExit:
-    ReleaseObject(pSection);
-    ReleaseObject(pCollection);
-    ReleaseObject(pNewElement);
-
-    return hr;
-}
-
-static HRESULT ClearLocationTag(
-    IAppHostWritableAdminManager *pAdminMgr,
-    LPCWSTR swLocationPath
-    )
-{
-    HRESULT hr = S_OK;
-    IAppHostConfigManager *pConfigMgr = NULL;
-    IAppHostConfigFile    *pConfigFile = NULL;
-    IAppHostConfigLocationCollection *pLocationCollection = NULL;
-    IAppHostConfigLocation *pLocation = NULL;
-
-    DWORD dwCount = 0;
-    BSTR bstrLocationPath = NULL;
-
-    hr = pAdminMgr->get_ConfigManager(&pConfigMgr);
-    ExitOnFailure(hr, "Failed to get IIS ConfigManager interface");
-
-    hr = pConfigMgr->GetConfigFile(ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pConfigFile);
-    ExitOnFailure(hr, "Failed to get IIS ConfigFile interface");
-
-    hr = pConfigFile->get_Locations(&pLocationCollection);
-    ExitOnFailure(hr, "Failed to get IIS location tag collection");
-
-    hr = pLocationCollection->get_Count(&dwCount);
-    ExitOnFailure(hr, "Failed to get IIS location collection count");
-
-    VARIANT vtIndex;
-    vtIndex.vt = VT_UI4;
-    for (DWORD i = 0; i < dwCount; ++i)
-    {
-        vtIndex.ulVal = i;
-        hr = pLocationCollection->get_Item(vtIndex, &pLocation);
-        ExitOnFailure(hr, "Failed to get IIS location collection count");
-
-        hr = pLocation->get_Path(&bstrLocationPath);
-        if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, swLocationPath, -1, bstrLocationPath, -1))
-        {
-            hr = pLocationCollection->DeleteLocation(vtIndex);
-            ExitOnFailure(hr, "Failed to delete IIS location tag %ls",swLocationPath);
-            break;
-        }
-
-        ReleaseNullObject(pLocation);
-        ::SysFreeString(bstrLocationPath);
-        bstrLocationPath = NULL;
-    }
-LExit:
-    ReleaseObject(pConfigMgr);
-    ReleaseObject(pConfigFile);
-    ReleaseObject(pLocationCollection);
-    ReleaseObject(pLocation);
-    ReleaseBSTR(bstrLocationPath);
-
-    return hr;
-
-}
-
-static HRESULT DeleteCollectionElement(
-    __in IAppHostElementCollection *pCollection,
-    __in LPCWSTR pwzElementName,
-    __in LPCWSTR pwzAttributeName,
-    __in LPCWSTR pwzAttributeValue
-    )
-{
-    HRESULT hr = S_OK;
-
-    DWORD dwIndex;
-    VARIANT vtIndex;
-    VariantInit(&vtIndex);
-
-    hr = Iis7FindAppHostElementString(pCollection, pwzElementName, pwzAttributeName, pwzAttributeValue, NULL, &dwIndex);
-    ExitOnFailure(hr, "Failed while finding IAppHostElement %ls/@%ls=%ls", pwzElementName, pwzAttributeName, pwzAttributeValue);
-
-    if (MAXDWORD != dwIndex)
-    {
-        vtIndex.vt = VT_UI4;
-        vtIndex.ulVal = dwIndex;
-        hr = pCollection->DeleteElement(vtIndex);
-        ExitOnFailure(hr, "Failed to delete IAppHostElement %ls/@%ls=%ls", pwzElementName, pwzAttributeName, pwzAttributeValue);
-    }
-    // else : nothing to do, already deleted
-LExit:
-    ReleaseVariant(vtIndex);
-
-    return hr;
-}
-static void ConvSecToHMS( int Sec,  __out_ecount(cchDest) LPWSTR wcTime, size_t cchDest)
-{
-    int ZH, ZM, ZS = 0;
-
-    ZH = (Sec / 3600);
-    Sec = Sec - ZH * 3600;
-    ZM = (Sec / 60) ;
-    Sec = Sec - ZM * 60;
-    ZS = Sec ;
-
-    HRESULT hr = ::StringCchPrintfW(wcTime, cchDest, L"%02d:%02d:%02d", ZH, ZM, ZS);
-    if (S_OK != hr)
-    {
-        *wcTime = '\0';
-    }
-}
-static void ConvSecToDHMS( unsigned int Sec,  __out_ecount(cchDest) LPWSTR wcTime, size_t cchDest)
-{
-    int ZD, ZH, ZM, ZS = 0;
-
-    ZD = Sec / 86400;
-    Sec = Sec - ZD * 86400;
-    ZH = (Sec / 3600);
-    Sec = Sec - ZH * 3600;
-    ZM = (Sec / 60) ;
-    Sec = Sec - ZM * 60;
-    ZS = Sec ;
-
-    HRESULT hr = ::StringCchPrintfW(wcTime, cchDest, L"%d.%02d:%02d:%02d", ZD, ZH, ZM, ZS);
-    if (S_OK != hr)
-    {
-        *wcTime = '\0';
-    }
-}
diff --git a/src/ca/scaexecIIS7.h b/src/ca/scaexecIIS7.h
deleted file mode 100644
index ec31f202..00000000
--- a/src/ca/scaexecIIS7.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#pragma once
-// 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.
-
-
-HRESULT IIS7ConfigChanges(MSIHANDLE hInstall, __inout LPWSTR pwzData);
diff --git a/src/ca/scafilter.cpp b/src/ca/scafilter.cpp
deleted file mode 100644
index 9d9014fd..00000000
--- a/src/ca/scafilter.cpp
+++ /dev/null
@@ -1,510 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-// prototypes
-static HRESULT ReadFilterLoadOrder(
-    __in IMSAdminBase* piMetabase,
-    __in LPCWSTR wzFilterRoot,
-    __out LPWSTR *ppwzLoadOrder
-    );
-static HRESULT AddFilterToLoadOrder(
-    __in LPCWSTR wzFilter,
-    __in int iLoadOrder,
-    __inout LPWSTR *ppwzLoadOrder
-    );
-static HRESULT RemoveFilterFromLoadOrder(
-    __in LPCWSTR wzFilter,
-    __inout LPWSTR *ppwzLoadOrder
-    );
-
-
-UINT __stdcall ScaFiltersRead(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_WEB* pswList,
-    __in WCA_WRAPQUERY_HANDLE hWebBaseQuery,
-    __inout SCA_FILTER** ppsfList,
-    __inout LPWSTR *ppwzCustomActionData
-    )
-{
-    HRESULT hr = S_OK;
-    MSIHANDLE hRec;
-    INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN;
-    INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN;
-
-    LPWSTR pwzData = NULL;
-
-    SCA_FILTER* psf = NULL;
-    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
-
-    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead");
-
-    if (0 == WcaGetQueryRecords(hWrapQuery))
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ScaFiltersRead() - no IIsFilter table");
-        ExitFunction1(hr = S_FALSE);
-    }
-
-    // loop through all the filters
-    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
-    {
-        // Get the Component first.  If the component is not being modified during
-        // this transaction, skip processing this whole record.
-        hr = WcaGetRecordString(hRec, fqComponent, &pwzData);
-        ExitOnFailure(hr, "failed to get IIsFilter.Component");
-
-        hr = WcaGetRecordInteger(hRec, fqInstalled, (int *)&isInstalled);
-        ExitOnFailure(hr, "Failed to get Component installed state for IIs filter");
-
-        hr = WcaGetRecordInteger(hRec, fqAction, (int *)&isAction);
-        ExitOnFailure(hr, "Failed to get Component action state for IIs filter");
-
-        if (!WcaIsInstalling(isInstalled, isAction) &&
-            !WcaIsReInstalling(isInstalled, isAction) &&
-            !WcaIsUninstalling(isInstalled, isAction))
-        {
-            continue; // skip this record.
-        }
-
-        hr = AddFilterToList(ppsfList);
-        ExitOnFailure(hr, "failed to add filter to list");
-
-        psf = *ppsfList;
-
-        hr = ::StringCchCopyW(psf->wzComponent, countof(psf->wzComponent), pwzData);
-        ExitOnFailure(hr, "failed to copy component name: %ls", pwzData);
-
-        psf->isInstalled = isInstalled;
-        psf->isAction = isAction;
-
-        hr = WcaGetRecordString(hRec, fqWeb, &pwzData);
-        ExitOnFailure(hr, "Failed to get Web for VirtualDir");
-
-        if (*pwzData)
-        {
-            hr = ScaWebsGetBase(piMetabase, pswList, pwzData, psf->wzWebBase, countof(psf->wzWebBase), hWebBaseQuery);
-            if (FAILED(hr) && WcaIsUninstalling(isInstalled, isAction))
-            {
-                // If we're uninstalling, don't bother finding the existing web, just leave the filter root empty
-                hr = S_OK;
-            }
-            ExitOnFailure(hr, "Failed to get base of web for Filter");
-
-            if (0 != lstrlenW(psf->wzWebBase))
-            {
-                hr = ::StringCchPrintfW(psf->wzFilterRoot, countof(psf->wzFilterRoot), L"%s/Filters", psf->wzWebBase);
-                ExitOnFailure(hr, "Failed to allocate filter base string");
-            }
-        }
-        else
-        {
-            hr = ::StringCchCopyW(psf->wzFilterRoot, countof(psf->wzFilterRoot), L"/LM/W3SVC/Filters");
-            ExitOnFailure(hr, "Failed to allocate global filter base string");
-        }
-
-        // filter key
-        hr = WcaGetRecordString(hRec, fqFilter, &pwzData);
-        ExitOnFailure(hr, "Failed to get Filter.Filter");
-        hr = ::StringCchCopyW(psf->wzKey, countof(psf->wzKey), pwzData);
-        ExitOnFailure(hr, "Failed to copy key string to filter object");
-
-        // filter path
-        hr = WcaGetRecordString(hRec, fqPath, &pwzData);
-        ExitOnFailure(hr, "Failed to get Filter.Path");
-        hr = ::StringCchCopyW(psf->wzPath, countof(psf->wzPath), pwzData);
-        ExitOnFailure(hr, "Failed to copy path string to filter object");
-
-        // filter description
-        hr = WcaGetRecordString(hRec, fqDescription, &pwzData);
-        ExitOnFailure(hr, "Failed to get Filter.Description");
-        hr = ::StringCchCopyW(psf->wzDescription, countof(psf->wzDescription), pwzData);
-        ExitOnFailure(hr, "Failed to copy description string to filter object");
-
-        // filter flags
-        hr = WcaGetRecordInteger(hRec, fqFlags, &psf->iFlags);
-        ExitOnFailure(hr, "Failed to get Filter.Flags");
-
-        // filter load order
-        hr = WcaGetRecordInteger(hRec, fqLoadOrder, &psf->iLoadOrder);
-        ExitOnFailure(hr, "Failed to get Filter.LoadOrder");
-    }
-
-    if (E_NOMOREITEMS == hr)
-    {
-        hr = S_OK;
-    }
-    ExitOnFailure(hr, "Failure while processing filters");
-
-LExit:
-    WcaFinishUnwrapQuery(hWrapQuery);
-
-    ReleaseStr(pwzData);
-    return hr;
-}
-
-
-HRESULT ScaFiltersInstall(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_FILTER* psfList
-    )
-{
-    HRESULT hr = S_OK;
-    SCA_FILTER* psf = psfList;
-    LPCWSTR wzPreviousFilterRoot = NULL;
-    LPWSTR pwzLoadOrder = NULL;
-
-    while (psf)
-    {
-        if (WcaIsInstalling(psf->isInstalled, psf->isAction))
-        {
-            if (!wzPreviousFilterRoot || CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, 0, wzPreviousFilterRoot, -1, psf->wzFilterRoot, -1))
-            {
-                if (pwzLoadOrder)
-                {
-                    hr = ScaWriteMetabaseValue(piMetabase, wzPreviousFilterRoot, L"", MD_FILTER_LOAD_ORDER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)pwzLoadOrder);
-                    ExitOnFailure(hr, "Failed to write filter load order to metabase");
-
-                    ReleaseNullStr(pwzLoadOrder);
-                }
-
-                hr = ReadFilterLoadOrder(piMetabase, psf->wzFilterRoot, &pwzLoadOrder);
-                ExitOnFailure(hr, "Failed to read filter load order.");
-
-                wzPreviousFilterRoot = psf->wzFilterRoot;
-            }
-
-            hr = ScaCreateMetabaseKey(piMetabase, psf->wzFilterRoot, psf->wzKey);
-            ExitOnFailure(hr, "Failed to create key for filter '%ls'", psf->wzKey);
-
-            hr = ScaWriteMetabaseValue(piMetabase, psf->wzFilterRoot, psf->wzKey, MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsFilter");
-            ExitOnFailure(hr, "Failed to write key type for filter '%ls'", psf->wzKey);
-
-            // filter path
-            hr = ScaWriteMetabaseValue(piMetabase, psf->wzFilterRoot, psf->wzKey, MD_FILTER_IMAGE_PATH, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)psf->wzPath);
-            ExitOnFailure(hr, "Failed to write Path for filter '%ls'", psf->wzKey);
-
-            // filter description
-            hr = ScaWriteMetabaseValue(piMetabase, psf->wzFilterRoot, psf->wzKey, MD_FILTER_DESCRIPTION, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)psf->wzDescription);
-            ExitOnFailure(hr, "Failed to write Description for filter '%ls'", psf->wzKey);
-
-            // filter flags
-            if (MSI_NULL_INTEGER != psf->iFlags)
-            {
-                hr = ScaWriteMetabaseValue(piMetabase, psf->wzFilterRoot, psf->wzKey, MD_FILTER_FLAGS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psf->iFlags));
-                ExitOnFailure(hr, "Failed to write Flags for filter '%ls'", psf->wzKey);
-            }
-
-            // filter load order
-            if (MSI_NULL_INTEGER != psf->iLoadOrder)
-            {
-                hr = AddFilterToLoadOrder(psf->wzKey, psf->iLoadOrder, &pwzLoadOrder);
-                ExitOnFailure(hr, "Failed to add filter '%ls' to load order.", psf->wzKey);
-            }
-        }
-
-        psf = psf->psfNext;
-    }
-
-    if (pwzLoadOrder)
-    {
-        Assert(wzPreviousFilterRoot && *wzPreviousFilterRoot);
-
-        hr = ScaWriteMetabaseValue(piMetabase, wzPreviousFilterRoot, L"", MD_FILTER_LOAD_ORDER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)pwzLoadOrder);
-        ExitOnFailure(hr, "Failed to write filter load order to metabase");
-    }
-
-LExit:
-    ReleaseStr(pwzLoadOrder);
-    return hr;
-}
-
-
-HRESULT ScaFiltersUninstall(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_FILTER* psfList
-    )
-{
-    HRESULT hr = S_OK;
-    SCA_FILTER* psf = psfList;
-    LPCWSTR wzPreviousFilterRoot = NULL;
-    LPWSTR pwzLoadOrder = NULL;
-
-    while (psf)
-    {
-        if (WcaIsUninstalling(psf->isInstalled, psf->isAction))
-        {
-            if (!wzPreviousFilterRoot || CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, 0, wzPreviousFilterRoot, -1, psf->wzFilterRoot, -1))
-            {
-                if (pwzLoadOrder)
-                {
-                    hr = ScaWriteMetabaseValue(piMetabase, wzPreviousFilterRoot, L"", MD_FILTER_LOAD_ORDER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)pwzLoadOrder);
-                    ExitOnFailure(hr, "Failed to write filter load order to metabase");
-
-                    ReleaseNullStr(pwzLoadOrder);
-                }
-
-                hr = ReadFilterLoadOrder(piMetabase, psf->wzFilterRoot, &pwzLoadOrder);
-                ExitOnFailure(hr, "Failed to read filter load order.");
-
-                wzPreviousFilterRoot = psf->wzFilterRoot;
-            }
-
-            hr = RemoveFilterFromLoadOrder(psf->wzKey, &pwzLoadOrder);
-            ExitOnFailure(hr, "Failed to remove filter '%ls' from load order", psf->wzKey);
-
-            // remove the filter from the load order and remove the filter's key
-            if (0 != lstrlenW(psf->wzFilterRoot))
-            {
-                hr = ScaDeleteMetabaseKey(piMetabase, psf->wzFilterRoot, psf->wzKey);
-                ExitOnFailure(hr, "Failed to remove web '%ls' from metabase", psf->wzKey);
-            }
-        }
-
-        psf = psf->psfNext;
-    }
-
-    if (pwzLoadOrder)
-    {
-        Assert(wzPreviousFilterRoot && *wzPreviousFilterRoot);
-
-        hr = ScaWriteMetabaseValue(piMetabase, wzPreviousFilterRoot, L"", MD_FILTER_LOAD_ORDER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)pwzLoadOrder);
-        ExitOnFailure(hr, "Failed to write filter load order to metabase");
-    }
-
-LExit:
-    return hr;
-}
-
-
-void ScaFiltersFreeList(
-    __in SCA_FILTER* psfList
-    )
-{
-    SCA_FILTER* psfDelete = psfList;
-    while (psfList)
-    {
-        psfDelete = psfList;
-        psfList = psfList->psfNext;
-
-        MemFree(psfDelete);
-    }
-}
-
-HRESULT AddFilterToList(
-    __inout SCA_FILTER** ppsfList)
-{
-    HRESULT hr = S_OK;
-    SCA_FILTER* psf = static_cast<SCA_FILTER*>(MemAlloc(sizeof(SCA_FILTER), TRUE));
-    ExitOnNull(psf, hr, E_OUTOFMEMORY, "failed to add filter to filter list");
-
-    psf->psfNext = *ppsfList;
-    *ppsfList = psf;
-
-LExit:
-    return hr;
-}
-
-// private helper functions
-
-
-static HRESULT ReadFilterLoadOrder(
-    __in IMSAdminBase* piMetabase,
-    __in LPCWSTR wzFilterRoot,
-    __out LPWSTR *ppwzLoadOrder
-    )
-{
-    HRESULT hr = S_OK;
-    METADATA_HANDLE mhRoot = NULL;
-
-    METADATA_RECORD mr;
-    DWORD dwRequired = 0;
-    DWORD cchData = 255;
-
-    ::ZeroMemory(&mr, sizeof(mr));
-    mr.dwMDIdentifier = MD_FILTER_LOAD_ORDER;
-    mr.dwMDAttributes = METADATA_NO_ATTRIBUTES;
-    mr.dwMDUserType = IIS_MD_UT_SERVER;
-    mr.dwMDDataType = ALL_METADATA;
-    mr.dwMDDataLen = cchData;
-    mr.pbMDData = static_cast<BYTE*>(MemAlloc(mr.dwMDDataLen * sizeof(WCHAR), TRUE));
-    ExitOnNull(mr.pbMDData, hr, E_OUTOFMEMORY, "failed to allocate memory for MDData in metadata record");
-
-    hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, wzFilterRoot, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE, 10, &mhRoot);
-    for (int i = 30; i > 0 && HRESULT_FROM_WIN32(ERROR_PATH_BUSY) == hr; i--)
-    {
-        ::Sleep(1000);
-        WcaLog(LOGMSG_STANDARD, "Failed to open root key, retrying %d time(s)...", i);
-        hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, wzFilterRoot, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE, 10, &mhRoot);
-    }
-
-    if (SUCCEEDED(hr))
-    {
-        hr = piMetabase->GetData(mhRoot, L"", &mr, &dwRequired);
-        if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr)
-        {
-            mr.dwMDDataLen = cchData = dwRequired;
-
-            LPVOID pv = MemReAlloc(mr.pbMDData, mr.dwMDDataLen * sizeof(WCHAR), TRUE);
-            ExitOnNull(pv, hr, E_OUTOFMEMORY, "failed to allocate memory for MDData in metadata record");
-            mr.pbMDData = static_cast<BYTE*>(pv);
-
-            hr = piMetabase->GetData(mhRoot, L"", &mr, &dwRequired);
-        }
-    }
-
-    // The /Filters node or /Filters/FilterLoadOrder property might not exist (yet).
-    if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || MD_ERROR_DATA_NOT_FOUND == hr)
-    {
-        hr = S_OK;
-    }
-    ExitOnFailure(hr, "Failed to get filter load order.");
-
-    hr = StrAllocString(ppwzLoadOrder, reinterpret_cast<LPCWSTR>(mr.pbMDData), 0);
-    ExitOnFailure(hr, "Failed to allocate string for filter load order.");
-
-LExit:
-    ReleaseMem(mr.pbMDData);
-
-    if (mhRoot)
-    {
-        piMetabase->CloseKey(mhRoot);
-    }
-
-    return hr;
-}
-
-
-static HRESULT AddFilterToLoadOrder(
-    __in LPCWSTR wzFilter,
-    __in int iLoadOrder,
-    __inout LPWSTR *ppwzLoadOrder
-    )
-{
-    HRESULT hr = S_OK;
-    LPCWSTR wzLoadOrder = *ppwzLoadOrder;
-    int cchFilter = lstrlenW(wzFilter);
-    LPWSTR pwzTemp = NULL;
-
-    // If the filter name ends with '\0' or ',' and
-    // the filter name begins at the beginning of the list or with ','
-    // Then we've found the exact filter by name.
-    //
-    // If the filter isn't already in the load order, add it
-    if (wzLoadOrder && *wzLoadOrder)
-    {
-        LPCWSTR pwz = wcsstr(wzLoadOrder, wzFilter);
-
-        if (NULL != pwz &&
-            (L'\0' == *(pwz + cchFilter) || L',' == *(pwz + cchFilter)) &&
-            (pwz == wzLoadOrder || L',' == *(pwz - 1)))
-        {
-            // Filter already in the load order, no work to do.
-        }
-        else
-        {
-            pwz = NULL;
-            if (0 <= iLoadOrder)
-            {
-                pwz = wzLoadOrder;
-                for (int i = 0; i < iLoadOrder && pwz; ++i)
-                {
-                    pwz = wcsstr(pwz, L",");
-                }
-            }
-
-            if (NULL == pwz) // put the filter at the end of the order
-            {
-                Assert(wzLoadOrder && *wzLoadOrder);
-
-                // tack on a comma since there are other filters in the order
-                hr = StrAllocConcat(ppwzLoadOrder, L",", 1);
-                ExitOnFailure(hr, "Failed to append a comma to filter load order.");
-
-                hr = StrAllocConcat(ppwzLoadOrder, wzFilter, cchFilter);
-                ExitOnFailure(hr, "Failed to append the filter on to the load order.");
-            }
-            else if (L',' == *pwz) // put the filter in the middle of the order
-            {
-                hr = StrAllocString(&pwzTemp, wzLoadOrder, pwz - wzLoadOrder + 1);
-                ExitOnFailure(hr, "Failed to copy first half of filter load order to temp string.");
-
-                hr = StrAllocConcat(&pwzTemp, wzFilter, 0);
-                ExitOnFailure(hr, "Failed to copy filter into load order.");
-
-                hr = StrAllocConcat(&pwzTemp, pwz, 0);
-                ExitOnFailure(hr, "Failed to copy remaining filter load order back onto load order.");
-
-                hr = StrAllocString(ppwzLoadOrder, pwzTemp, 0);
-                ExitOnFailure(hr, "Failed to copy temp string to load order string.");
-            }
-            else // put the filter at the beginning of the order
-            {
-                hr = StrAllocPrefix(ppwzLoadOrder, L",", 1);
-                ExitOnFailure(hr, "Failed to prepend a comma to filter load order.");
-
-                hr = StrAllocPrefix(ppwzLoadOrder, wzFilter, cchFilter);
-                ExitOnFailure(hr, "Failed to prepend the filter on to the load order.");
-            }
-        }
-    }
-    else
-    {
-        hr = StrAllocString(ppwzLoadOrder, wzFilter, cchFilter);
-        ExitOnFailure(hr, "Failed to add filter to load order.");
-    }
-
-LExit:
-    ReleaseStr(pwzTemp);
-    return hr;
-}
-
-
-static HRESULT RemoveFilterFromLoadOrder(
-    __in LPCWSTR wzFilter,
-    __inout LPWSTR *ppwzLoadOrder
-    )
-{
-    HRESULT hr = S_OK;
-    int cchFilter = lstrlenW(wzFilter);
-
-    LPCWSTR pwzStart = NULL;
-    LPWSTR pwzFind = NULL;
-
-    pwzStart = pwzFind = *ppwzLoadOrder;
-    while (NULL != (pwzFind = wcsstr(pwzFind, wzFilter)))
-    {
-        // Make sure to only match [wzFilter] and NOT foo[wzFilter]bar
-        if (pwzFind == pwzStart || L',' == *(pwzFind - 1))
-        {
-            int cchRemainder = lstrlenW(pwzFind) - cchFilter + 1; // add one to include the null terminator
-
-            if (L'\0' == *(pwzFind + cchFilter))
-            {
-                if (pwzFind == pwzStart)
-                {
-                    memmove(pwzFind, pwzFind + cchFilter, cchRemainder * sizeof(WCHAR)); // copy down the null terminator
-                }
-                else
-                {
-                    memmove(pwzFind - 1, pwzFind + cchFilter, cchRemainder * sizeof(WCHAR)); // copy down the null terminator over top the trailing ","
-                }
-            }
-            else if (L',' == *(pwzFind + cchFilter))
-            {
-                memmove(pwzFind, pwzFind + cchFilter + 1, (cchRemainder - 1) * sizeof(WCHAR)); // skip copying the ","
-            }
-            else // skip past the partial match
-            {
-                pwzFind = pwzFind + cchFilter;
-            }
-        }
-        else // skip past the partial match
-        {
-            pwzFind = pwzFind + cchFilter;
-        }
-    }
-
-//LExit:
-    return hr;
-}
diff --git a/src/ca/scafilter.h b/src/ca/scafilter.h
deleted file mode 100644
index d072bf22..00000000
--- a/src/ca/scafilter.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#pragma once
-// 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.
-
-
-#include "scaweb.h"
-
-enum eFilterQuery { fqWeb = 1, fqFilter, fqComponent , fqPath, fqDescription, fqFlags, fqLoadOrder, fqInstalled, fqAction };
-
-struct SCA_FILTER
-{
-	// darwin information
-	WCHAR wzKey[MAX_DARWIN_KEY + 1];
-	WCHAR wzComponent[MAX_DARWIN_KEY + 1];
-	INSTALLSTATE isInstalled;
-	INSTALLSTATE isAction;
-
-	// metabase information
-	WCHAR wzWebKey[MAX_DARWIN_KEY + 1];
-	WCHAR wzWebBase[METADATA_MAX_NAME_LEN + 1];
-	WCHAR wzFilterRoot[METADATA_MAX_NAME_LEN + 1];
-
-	// iis configuation information
-	WCHAR wzPath[MAX_PATH];
-	WCHAR wzDescription[MAX_DARWIN_COLUMN + 1];
-	int iFlags;
-	int iLoadOrder;
-
-	SCA_FILTER* psfNext;
-};
-
-
-// prototypes
-HRESULT AddFilterToList(
-    __in SCA_FILTER** ppsfList
-    );
-
-UINT __stdcall ScaFiltersRead(IMSAdminBase* piMetabase,
-                              SCA_WEB* pswList, __in WCA_WRAPQUERY_HANDLE hWebBaseQuery, SCA_FILTER** ppsfList,
-                              __inout LPWSTR *ppwzCustomActionData);
-
-HRESULT ScaFiltersInstall(IMSAdminBase* piMetabase, SCA_FILTER* psfList);
-
-HRESULT ScaFiltersUninstall(IMSAdminBase* piMetabase, SCA_FILTER* psfList);
-
-void ScaFiltersFreeList(SCA_FILTER* psfList);
-
diff --git a/src/ca/scafilter7.cpp b/src/ca/scafilter7.cpp
deleted file mode 100644
index dda91c4d..00000000
--- a/src/ca/scafilter7.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-static HRESULT WriteFilter(const SCA_FILTER* psf);
-
-UINT __stdcall ScaFiltersRead7(
-    __in SCA_WEB7* pswList,
-    __in WCA_WRAPQUERY_HANDLE /*hWebBaseQuery*/,
-    __inout SCA_FILTER** ppsfList,
-    __inout LPWSTR *ppwzCustomActionData
-    )
-{
-    HRESULT hr = S_OK;
-    MSIHANDLE hRec;
-    INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN;
-    INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN;
-    SCA_FILTER* psf;
-
-    LPWSTR pwzData = NULL;
-    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
-    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead");
-
-    if (0 == WcaGetQueryRecords(hWrapQuery))
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ScaFiltersRead() - no IIsFilter table");
-        ExitFunction1(hr = S_FALSE);
-    }
-
-    // loop through all the filters
-    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
-    {
-        // Get the Component first.  If the component is not being modified during
-        // this transaction, skip processing this whole record.
-        // get the darwin information
-        hr = WcaGetRecordString(hRec, fqComponent, &pwzData);
-        ExitOnFailure(hr, "failed to get IIsFilter.Component");
-
-        hr = WcaGetRecordInteger(hRec, fqInstalled, (int *)&isInstalled);
-        ExitOnFailure(hr, "Failed to get Component installed state for IIs filter");
-
-        hr = WcaGetRecordInteger(hRec, fqAction, (int *)&isAction);
-        ExitOnFailure(hr, "Failed to get Component action state for IIs filter");
-
-        if (!WcaIsInstalling(isInstalled, isAction) &&
-            !WcaIsReInstalling(isInstalled, isAction) &&
-            !WcaIsUninstalling(isInstalled, isAction))
-        {
-            continue; // skip this record.
-        }
-
-        hr = AddFilterToList(ppsfList);
-        ExitOnFailure(hr, "failed to add filter to list");
-
-        psf = *ppsfList;
-
-        hr = ::StringCchCopyW(psf->wzComponent, countof(psf->wzComponent), pwzData);
-        ExitOnFailure(hr, "failed to copy component name: %ls", pwzData);
-
-        psf->isInstalled = isInstalled;
-        psf->isAction = isAction;
-
-        hr = WcaGetRecordString(hRec, fqWeb, &pwzData);
-        ExitOnFailure(hr, "Failed to get Web for VirtualDir");
-
-        if (*pwzData)
-        {
-            hr = ScaWebsGetBase7(pswList, pwzData, psf->wzFilterRoot, countof(psf->wzFilterRoot));
-            if (FAILED(hr))
-            {
-                WcaLog(LOGMSG_VERBOSE, "Could not find site for filter: %ls. Result 0x%x ", psf->wzFilterRoot, hr);
-                hr = S_OK;
-            }
-        }
-        else
-        {
-            hr = ::StringCchCopyW(psf->wzFilterRoot, countof(psf->wzFilterRoot), L"/");
-            ExitOnFailure(hr, "Failed to allocate global filter base string");
-        }
-
-        // filter Name key
-        hr = WcaGetRecordString(hRec, fqFilter, &pwzData);
-        ExitOnFailure(hr, "Failed to get Filter.Filter");
-        hr = ::StringCchCopyW(psf->wzKey, countof(psf->wzKey), pwzData);
-        ExitOnFailure(hr, "Failed to copy key string to filter object");
-
-        // filter path
-        hr = WcaGetRecordString(hRec, fqPath, &pwzData);
-        ExitOnFailure(hr, "Failed to get Filter.Path");
-        hr = ::StringCchCopyW(psf->wzPath, countof(psf->wzPath), pwzData);
-        ExitOnFailure(hr, "Failed to copy path string to filter object");
-
-        // filter description -- not supported in iis 7
-        hr = WcaGetRecordString(hRec, fqDescription, &pwzData);
-        ExitOnFailure(hr, "Failed to get Filter.Description");
-        hr = ::StringCchCopyW(psf->wzDescription, countof(psf->wzDescription), pwzData);
-        ExitOnFailure(hr, "Failed to copy description string to filter object");
-
-        // filter flags
-        //What are these
-        hr = WcaGetRecordInteger(hRec, fqFlags, &psf->iFlags);
-        ExitOnFailure(hr, "Failed to get Filter.Flags");
-
-        // filter load order
-        hr = WcaGetRecordInteger(hRec, fqLoadOrder, &psf->iLoadOrder);
-        ExitOnFailure(hr, "Failed to get Filter.LoadOrder");
-    }
-
-    if (E_NOMOREITEMS == hr)
-    {
-        hr = S_OK;
-    }
-    ExitOnFailure(hr, "Failure while processing filters");
-
-LExit:
-    WcaFinishUnwrapQuery(hWrapQuery);
-
-    ReleaseStr(pwzData);
-
-    return hr;
-}
-
-
-HRESULT ScaFiltersInstall7(
-    __in SCA_FILTER* psfList
-    )
-{
-    HRESULT hr = S_OK;
-    SCA_FILTER* psf = psfList;
-
-    if (!psf)
-    {
-        ExitFunction();
-    }
-    //write global filters
-    hr = ScaWriteConfigID(IIS_FILTER_GLOBAL_BEGIN);
-    ExitOnFailure(hr, "Failed to write filter begin ID");
-    while (psf)
-    {
-        if (WcaIsInstalling(psf->isInstalled, psf->isAction))
-        {
-            if (0 == wcscmp(psf->wzFilterRoot, L"/"))
-            {
-                hr = WriteFilter(psf);
-            }
-        }
-        psf = psf->psfNext;
-    }
-    hr = ScaWriteConfigID(IIS_FILTER_END);
-    ExitOnFailure(hr, "Failed to write filter ID");
-
-    psf = psfList;
-
-    //Write Web Site Filters
-    hr = ScaWriteConfigID(IIS_FILTER_BEGIN);
-    ExitOnFailure(hr, "Failed to write filter begin ID");
-    while (psf)
-    {
-        if (WcaIsInstalling(psf->isInstalled, psf->isAction))
-        {
-            if (0 != wcscmp(psf->wzFilterRoot, L"/"))
-            {
-                hr = WriteFilter(psf);
-            }
-        }
-        psf = psf->psfNext;
-    }
-    hr = ScaWriteConfigID(IIS_FILTER_END);
-    ExitOnFailure(hr, "Failed to write filter ID");
-
-LExit:
-
-    return hr;
-}
-static HRESULT WriteFilter(const SCA_FILTER* psf)
-{
-    HRESULT hr = S_OK;
-
-    hr = ScaWriteConfigID(IIS_FILTER);
-    ExitOnFailure(hr, "Failed to write filter begin ID");
-
-    hr = ScaWriteConfigID(IIS_CREATE);
-    ExitOnFailure(hr, "Failed to write filter create ID");
-
-    //filter Name key
-    hr = ScaWriteConfigString(psf->wzKey);
-    ExitOnFailure(hr, "Failed to write key name for filter '%ls'", psf->wzKey);
-
-    //web site name
-    hr = ScaWriteConfigString(psf->wzFilterRoot);
-    ExitOnFailure(hr, "Failed to write filter web root ");
-
-    // filter path
-    hr = ScaWriteConfigString(psf->wzPath);
-    ExitOnFailure(hr, "Failed to write Path for filter '%ls'", psf->wzKey);
-
-    //filter load order
-    hr = ScaWriteConfigInteger(psf->iLoadOrder);
-    ExitOnFailure(hr, "Failed to write load order for filter '%ls'", psf->wzKey);
-
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaFiltersUninstall7(
-    __in SCA_FILTER* psfList
-    )
-{
-    HRESULT hr = S_OK;
-    SCA_FILTER* psf = psfList;
-
-    if (!psf)
-    {
-        ExitFunction1(hr = S_OK);
-    }
-
-    //Uninstall global filters
-    hr = ScaWriteConfigID(IIS_FILTER_GLOBAL_BEGIN);
-    ExitOnFailure(hr, "Failed to write filter begin ID");
-
-    while (psf)
-    {
-        if (WcaIsUninstalling(psf->isInstalled, psf->isAction))
-        {
-            if (0 == wcscmp(psf->wzFilterRoot, L"/"))
-            {
-                hr = ScaWriteConfigID(IIS_FILTER);
-                ExitOnFailure(hr, "Failed to write filter begin ID");
-
-                hr = ScaWriteConfigID(IIS_DELETE);
-                ExitOnFailure(hr, "Failed to write filter create ID");
-
-                //filter Name key
-                hr = ScaWriteConfigString(psf->wzKey);
-                ExitOnFailure(hr, "Failed to write key name for filter '%ls'", psf->wzKey);
-
-                //web site name
-                hr = ScaWriteConfigString(psf->wzFilterRoot);
-                ExitOnFailure(hr, "Failed to write filter web root ");
-
-            }
-        }
-        psf = psf->psfNext;
-    }
-
-    hr = ScaWriteConfigID(IIS_FILTER_END);
-    ExitOnFailure(hr, "Failed to write filter ID");
-
-    psf = psfList;
-
-    //Uninstall website filters
-    hr = ScaWriteConfigID(IIS_FILTER_BEGIN);
-    ExitOnFailure(hr, "Failed to write filter begin ID");
-    while (psf)
-    {
-        if (WcaIsUninstalling(psf->isInstalled, psf->isAction))
-        {
-            if (0 != wcscmp(psf->wzFilterRoot, L"/"))
-            {
-                hr = ScaWriteConfigID(IIS_FILTER);
-                ExitOnFailure(hr, "Failed to write filter begin ID");
-
-                hr = ScaWriteConfigID(IIS_DELETE);
-                ExitOnFailure(hr, "Failed to write filter create ID");
-
-                //filter Name key
-                hr = ScaWriteConfigString(psf->wzKey);
-                ExitOnFailure(hr, "Failed to write key name for filter '%ls'", psf->wzKey);
-
-                //web site name
-                hr = ScaWriteConfigString(psf->wzFilterRoot);
-                ExitOnFailure(hr, "Failed to write filter web root ");
-            }
-        }
-        psf = psf->psfNext;
-    }
-    hr = ScaWriteConfigID(IIS_FILTER_END);
-    ExitOnFailure(hr, "Failed to write filter ID");
-
-LExit:
-    return hr;
-}
diff --git a/src/ca/scafilter7.h b/src/ca/scafilter7.h
deleted file mode 100644
index 50ff6652..00000000
--- a/src/ca/scafilter7.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma once
-// 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.
-
-
-#include "scaweb.h"
-
-// prototypes
-UINT __stdcall ScaFiltersRead7(
-    __in SCA_WEB7* pswList,
-    __in WCA_WRAPQUERY_HANDLE hWebBaseQuery, 
-    __inout SCA_FILTER** ppsfList,
-    __inout LPWSTR *ppwzCustomActionData
-    );
-
-HRESULT ScaFiltersInstall7(
-    SCA_FILTER* psfList
-    );
-
-HRESULT ScaFiltersUninstall7(
-    SCA_FILTER* psfList
-    );
diff --git a/src/ca/scahttpheader.cpp b/src/ca/scahttpheader.cpp
deleted file mode 100644
index 1e134cea..00000000
--- a/src/ca/scahttpheader.cpp
+++ /dev/null
@@ -1,323 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-enum eHttpHeaderQuery { hhqName = 1, hhqParentType, hhqParentValue, hhqValue, hhqAttributes};
-
-static HRESULT AddHttpHeaderToList(
-    __in SCA_HTTP_HEADER** ppshhList
-    );
-
-
-void ScaHttpHeaderFreeList(
-    __in SCA_HTTP_HEADER* pshhList
-    )
-{
-    SCA_HTTP_HEADER* pshhDelete = pshhList;
-    while (pshhList)
-    {
-        pshhDelete = pshhList;
-        pshhList = pshhList->pshhNext;
-
-        MemFree(pshhDelete);
-    }
-}
-
-
-HRESULT ScaHttpHeaderRead(
-    __in SCA_HTTP_HEADER** ppshhList,
-    __inout LPWSTR *ppwzCustomActionData
-    )
-{
-    Assert(ppshhList);
-
-    HRESULT hr = S_OK;
-        MSIHANDLE hRec;
-    LPWSTR pwzData = NULL;
-    SCA_HTTP_HEADER* pshh = NULL;
-    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
-
-    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead");
-
-    if (0 == WcaGetQueryRecords(hWrapQuery))
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ScaHttpHeaderRead() - required tables not present.");
-        ExitFunction1(hr = S_FALSE);
-    }
-
-    // loop through all the HTTP headers
-    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
-    {
-        hr = AddHttpHeaderToList(ppshhList);
-        ExitOnFailure(hr, "failed to add http header to list");
-
-        pshh = *ppshhList;
-
-        hr = WcaGetRecordInteger(hRec, hhqParentType, &(pshh->iParentType));
-        ExitOnFailure(hr, "failed to get IIsHttpHeader.ParentType");
-
-        hr = WcaGetRecordString(hRec, hhqParentValue, &pwzData);
-        ExitOnFailure(hr, "Failed to get IIsHttpHeader.ParentValue");
-        hr = ::StringCchCopyW(pshh->wzParentValue, countof(pshh->wzParentValue), pwzData);
-        ExitOnFailure(hr, "Failed to copy IIsHttpHeader.ParentValue");
-
-        hr = WcaGetRecordString(hRec, hhqName, &pwzData);
-        ExitOnFailure(hr, "Failed to get IIsHttpHeader.Name");
-        hr = ::StringCchCopyW(pshh->wzName, countof(pshh->wzName), pwzData);
-        ExitOnFailure(hr, "Failed to copy IIsHttpHeader.Name");
-
-        hr = WcaGetRecordString(hRec, hhqValue, &pwzData);
-        ExitOnFailure(hr, "Failed to get IIsHttpHeader.Value");
-        hr = ::StringCchCopyW(pshh->wzValue, countof(pshh->wzValue), pwzData);
-        ExitOnFailure(hr, "Failed to copy IIsHttpHeader.Value");
-
-        hr = WcaGetRecordInteger(hRec, hhqAttributes, &(pshh->iAttributes));
-        ExitOnFailure(hr, "failed to get IIsHttpHeader.Attributes");
-    }
-
-    if (E_NOMOREITEMS == hr)
-    {
-        hr = S_OK;
-    }
-    ExitOnFailure(hr, "Failure while processing web errors");
-
-LExit:
-    WcaFinishUnwrapQuery(hWrapQuery);
-
-    ReleaseStr(pwzData);
-
-    return hr;
-}
-
-
-HRESULT ScaGetHttpHeader(
-    __in int iParentType,
-    __in LPCWSTR wzParentValue,
-    __in SCA_HTTP_HEADER** ppshhList,
-    __out SCA_HTTP_HEADER** ppshhOut
-    )
-{
-    HRESULT hr = S_OK;
-    SCA_HTTP_HEADER* pshhAdd = NULL;
-    SCA_HTTP_HEADER* pshhLast = NULL;
-
-    *ppshhOut = NULL;
-
-    if (!*ppshhList)
-    {
-        return hr;
-    }
-
-    SCA_HTTP_HEADER* pshh = *ppshhList;
-    while (pshh)
-    {
-        if (iParentType == pshh->iParentType && CSTR_EQUAL == ::CompareStringW(LOCALE_SYSTEM_DEFAULT, 0, wzParentValue, -1, pshh->wzParentValue, -1))
-        {
-            // Found a match, take this one out of the list and add it to the matched out list
-            pshhAdd = pshh;
-
-            if (pshhLast)
-            {
-                // 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)
-                pshhLast->pshhNext = pshhAdd->pshhNext;
-            }
-            else
-            {
-                // If we are at the beginning (no pshhLast) update the beginning (since we're taking it)
-                *ppshhList = pshh->pshhNext;
-            }
-            pshh = pshh->pshhNext; // move on
-
-            // Add the one we've removed to the beginning of the out list
-            pshhAdd->pshhNext = *ppshhOut;
-            *ppshhOut = pshhAdd;
-        }
-        else
-        {
-            pshhLast = pshh; // remember the last we that didn't match
-            pshh = pshh->pshhNext; // move on
-        }
-    }
-
-    return hr;
-}
-
-
-HRESULT ScaWriteHttpHeader(
-    __in IMSAdminBase* piMetabase,
-    __in LPCWSTR wzRoot,
-    __in SCA_HTTP_HEADER* pshhList
-    )
-{
-    Assert(piMetabase && pshhList);
-
-    HRESULT hr = S_OK;
-    METADATA_RECORD mr = { 0 };
-    DWORD cchData = 0;
-    LPWSTR pwzSearchKey = NULL;
-    LPWSTR pwz = NULL;
-    LPWSTR pwzHeaders = NULL;
-    LPWSTR pwzNewHeader = NULL;
-    DWORD_PTR dwFoundHeaderIndex = 0;
-    LPCWSTR wzFoundHeader = NULL;
-    BOOL fOldValueFound = FALSE;
-
-    ExitOnNull(wzRoot, hr, E_INVALIDARG, "Failed to write HTTP header, because no root was provided");
-
-    Assert(*wzRoot);
-
-    // Check if HTTP header already exist here.
-    mr.dwMDIdentifier = MD_HTTP_CUSTOM;
-    mr.dwMDAttributes = METADATA_INHERIT;
-    mr.dwMDUserType = IIS_MD_UT_SERVER;
-    mr.dwMDDataType = ALL_METADATA;
-    mr.dwMDDataLen = cchData = 0;
-    mr.pbMDData = NULL;
-
-    hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzRoot, &mr);
-    if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || MD_ERROR_DATA_NOT_FOUND == hr)
-    {
-        //
-        // If we don't have any HTTP Headers already, move up to get the parent headers.
-        // TODO: Make it configurable to not inherit HTTP Headers
-        //
-        hr = StrAllocConcat(&pwzSearchKey, wzRoot, 0);
-        ExitOnFailure(hr, "Failed to copy root string: %ls", wzRoot);
-
-        pwz = pwzSearchKey + lstrlenW(pwzSearchKey);
-        while (NULL == pwzHeaders)
-        {
-            // find the last slash
-            while (*pwz != '/' && pwz != pwzSearchKey)
-            {
-                --pwz;
-            }
-
-            if (pwz == pwzSearchKey)
-            {
-                break;
-            }
-
-            *pwz = L'\0';
-
-            // Try here.  If it's not found, keep walking up the path
-            hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, pwzSearchKey, &mr);
-            if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || MD_ERROR_DATA_NOT_FOUND == hr)
-            {
-                hr = S_FALSE;
-            }
-            ExitOnFailure(hr, "Failed to find search for HTTP headers for web root: %ls while walking up the tree", wzRoot);
-
-            if (S_OK == hr)
-            {
-                hr = StrAllocString(&pwzHeaders, reinterpret_cast<LPWSTR>(mr.pbMDData), 0);
-                ExitOnFailure(hr, "Failed to allocate parent HTTP header string");
-                break;
-            }
-        }
-    }
-    else
-    {
-        hr = StrAllocString(&pwzHeaders, reinterpret_cast<LPWSTR>(mr.pbMDData), 0);
-        ExitOnFailure(hr, "Failed to allocate HTTP header string");
-    }
-    ExitOnFailure(hr, "Failed while searching for default HTTP headers to start with for web root: %ls", wzRoot);
-
-    // Loop through the HTTP headers
-    for (SCA_HTTP_HEADER* pshh = pshhList; pshh; pshh = pshh->pshhNext)
-    {
-        fOldValueFound = FALSE; // assume a HTTP Header match will not be found
-
-        hr = StrAllocFormatted(&pwzNewHeader, L"%s: ", pshh->wzName);
-        ExitOnFailure(hr, "Failed to allocate header name");
-
-        if (NULL != pwzHeaders && *pwzHeaders)
-        {
-            // Try to find a matching header already in the list
-            hr = MultiSzFindSubstring(pwzHeaders, pwzNewHeader, &dwFoundHeaderIndex, &wzFoundHeader);
-            ExitOnFailure(hr, "Failed while searching for existing HTTP header.");
-
-            // If there was a substring HTTP header match, make sure the match was at the beginning 
-            // of the string because that is the HTTP header name.
-            if (S_OK == hr)
-            {
-                DWORD cchMatch = lstrlenW(pwzNewHeader);
-                if (CSTR_EQUAL == ::CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, pwzNewHeader, cchMatch, wzFoundHeader, cchMatch))
-                {
-                    fOldValueFound = TRUE;
-                    break;
-                }
-            }
-        }
-
-        // Add the value on to the header name now.
-        hr = StrAllocConcat(&pwzNewHeader, pshh->wzValue, 0);
-        ExitOnFailure(hr, "Failed to add value on to HTTP header name.");
-
-        // If we have something to replace, replace it, otherwise, put it at the beginning (order shouldn't matter)
-        if (fOldValueFound)
-        {
-            if (NULL == pwzHeaders)
-            {
-                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!");
-            }
-            hr = MultiSzReplaceString(&pwzHeaders, dwFoundHeaderIndex, pwzNewHeader);
-            ExitOnFailure(hr, "Failed to replace old HTTP header with new HTTP header");
-        }
-        else
-        {
-            hr = MultiSzPrepend(&pwzHeaders, NULL, pwzNewHeader);
-            ExitOnFailure(hr, "Failed to prepend new HTTP header");
-        }
-    }
-
-    // now write the HttpCustom to the metabase
-    hr = ScaWriteMetabaseValue(piMetabase, wzRoot, NULL, MD_HTTP_CUSTOM, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, pwzHeaders);
-    ExitOnFailure(hr, "Failed to write HTTP Headers to metabase");
-
-LExit:
-    MetaFreeValue(&mr);
-
-    ReleaseStr(pwzNewHeader);
-    ReleaseStr(pwzHeaders);
-    ReleaseStr(pwzSearchKey);
-
-    return hr;
-}
-
-
-HRESULT ScaHttpHeaderCheckList(
-    __in SCA_HTTP_HEADER* pshhList
-    )
-{
-    if (!pshhList)
-    {
-        return S_OK;
-    }
-
-    while (pshhList)
-    {
-        WcaLog(LOGMSG_STANDARD, "Http Header: %ls for parent: %ls not used!", pshhList->wzName, pshhList->wzParentValue);
-        pshhList = pshhList->pshhNext;
-    }
-
-    return E_FAIL;
-}
-
-
-static HRESULT AddHttpHeaderToList(
-    __in SCA_HTTP_HEADER** ppshhList
-    )
-{
-    HRESULT hr = S_OK;
-
-    SCA_HTTP_HEADER* pshh = static_cast<SCA_HTTP_HEADER*>(MemAlloc(sizeof(SCA_HTTP_HEADER), TRUE));
-    ExitOnNull(pshh, hr, E_OUTOFMEMORY, "failed to allocate memory for new http header list element");
-
-    pshh->pshhNext = *ppshhList;
-    *ppshhList = pshh;
-
-LExit:
-    return hr;
-}
diff --git a/src/ca/scahttpheader.h b/src/ca/scahttpheader.h
deleted file mode 100644
index a4c407a4..00000000
--- a/src/ca/scahttpheader.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#pragma once
-// 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.
-
-
-enum eHttpHeaderParentType { hhptVDir = 1, hhptWeb };
-
-struct SCA_HTTP_HEADER
-{
-    int iParentType;
-    WCHAR wzParentValue[MAX_DARWIN_KEY + 1];
-
-    WCHAR wzName[MAX_PATH];
-    WCHAR wzValue[MAX_PATH];
-    int iAttributes;
-
-    SCA_HTTP_HEADER* pshhNext;
-};
-
-// prototypes
-HRESULT ScaHttpHeaderRead(
-    __in SCA_HTTP_HEADER **ppshhList,
-    __inout LPWSTR *ppwzCustomActionData
-    );
-void ScaHttpHeaderFreeList(
-    __in SCA_HTTP_HEADER *pshhList
-    );
-HRESULT ScaHttpHeaderCheckList(
-    __in SCA_HTTP_HEADER* pshhList
-    );
-HRESULT ScaGetHttpHeader(
-    __in int iParentType,
-    __in LPCWSTR wzParentValue,
-    __in SCA_HTTP_HEADER** ppshhList,
-    __out SCA_HTTP_HEADER** ppshhOut
-    );
-HRESULT ScaWriteHttpHeader(
-    __in IMSAdminBase* piMetabase,
-    LPCWSTR wzRoot,
-    SCA_HTTP_HEADER* pshhList
-    );
diff --git a/src/ca/scahttpheader7.cpp b/src/ca/scahttpheader7.cpp
deleted file mode 100644
index 645dd8d4..00000000
--- a/src/ca/scahttpheader7.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-HRESULT ScaGetHttpHeader7(
-    __in int iParentType,
-    __in_z LPCWSTR wzParentValue,
-    __in SCA_HTTP_HEADER** ppshhList,
-    __out SCA_HTTP_HEADER** ppshhOut
-    )
-{
-    HRESULT hr = S_OK;
-    SCA_HTTP_HEADER* pshhAdd = NULL;
-    SCA_HTTP_HEADER* pshhLast = NULL;
-
-    *ppshhOut = NULL;
-
-    if (!*ppshhList)
-    {
-        return hr;
-    }
-
-    SCA_HTTP_HEADER* pshh = *ppshhList;
-    while (pshh)
-    {
-        if (iParentType == pshh->iParentType && 0 == wcscmp(wzParentValue, pshh->wzParentValue))
-        {
-            // Found a match, take this one out of the list and add it to the matched out list
-            pshhAdd = pshh;
-
-            if (pshhLast)
-            {
-                // 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)
-                pshhLast->pshhNext = pshhAdd->pshhNext;
-            }
-            else
-            {
-                // If we are at the beginning (no pshhLast) update the beginning (since we're taking it)
-                *ppshhList = pshh->pshhNext;
-            }
-            pshh = pshh->pshhNext; // move on
-
-            // Add the one we've removed to the beginning of the out list
-            pshhAdd->pshhNext = *ppshhOut;
-            *ppshhOut = pshhAdd;
-        }
-        else
-        {
-            pshhLast = pshh; // remember the last we that didn't match
-            pshh = pshh->pshhNext; // move on
-        }
-    }
-
-    return hr;
-}
-
-
-HRESULT ScaWriteHttpHeader7(
-     __in_z LPCWSTR wzWebName,
-     __in_z LPCWSTR wzRoot,
-     SCA_HTTP_HEADER* pshhList
-    )
-{
-
-    HRESULT hr = S_OK;
-
-    hr = ScaWriteConfigID(IIS_HTTP_HEADER_BEGIN);
-    ExitOnFailure(hr, "Fail to write httpHeader begin ID");
-
-    hr = ScaWriteConfigString(wzWebName);
-    ExitOnFailure(hr, "Fail to write httpHeader Web Key");
-
-    hr = ScaWriteConfigString(wzRoot);
-    ExitOnFailure(hr, "Fail to write httpHeader Vdir key");
-
-    // Loop through the HTTP headers
-    for (SCA_HTTP_HEADER* pshh = pshhList; pshh; pshh = pshh->pshhNext)
-    {
-        hr = ScaWriteConfigID(IIS_HTTP_HEADER);
-        ExitOnFailure(hr, "Fail to write httpHeader ID");
-
-        hr = ScaWriteConfigString(pshh->wzName);
-        ExitOnFailure(hr, "Fail to write httpHeader name");
-
-        hr = ScaWriteConfigString(pshh->wzValue);
-        ExitOnFailure(hr, "Fail to write httpHeader value");
-    }
-
-    hr = ScaWriteConfigID(IIS_HTTP_HEADER_END);
-    ExitOnFailure(hr, "Fail to write httpHeader end ID");
-
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaHttpHeaderCheckList7(
-    __in SCA_HTTP_HEADER* pshhList
-    )
-{
-    if (!pshhList)
-    {
-        return S_OK;
-    }
-
-    while (pshhList)
-    {
-        WcaLog(LOGMSG_STANDARD, "Http Header: %ls for parent: %ls not used!", pshhList->wzName, pshhList->wzParentValue);
-        pshhList = pshhList->pshhNext;
-    }
-
-    return E_FAIL;
-}
-
-
-//static HRESULT AddHttpHeaderToList(
-//    __in SCA_HTTP_HEADER** ppshhList
-//    )
-//{
-//    HRESULT hr = S_OK;
-//
-//    SCA_HTTP_HEADER* pshh = static_cast<SCA_HTTP_HEADER*>(MemAlloc(sizeof(SCA_HTTP_HEADER), TRUE));
-//    ExitOnNull(pshh, hr, E_OUTOFMEMORY, "failed to allocate memory for new http header list element");
-//
-//    pshh->pshhNext = *ppshhList;
-//    *ppshhList = pshh;
-//
-//LExit:
-//    return hr;
-//}
diff --git a/src/ca/scahttpheader7.h b/src/ca/scahttpheader7.h
deleted file mode 100644
index 7a873c16..00000000
--- a/src/ca/scahttpheader7.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma once
-// 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.
-
-
-HRESULT ScaGetHttpHeader7(
-    __in int iParentType,
-    __in_z LPCWSTR wzParentValue,
-    __in SCA_HTTP_HEADER** ppshhList,
-    __out SCA_HTTP_HEADER** ppshhOut
-    );
-HRESULT ScaWriteHttpHeader7(
-    __in_z LPCWSTR wzWebName,
-    __in_z LPCWSTR wzRoot,
-    SCA_HTTP_HEADER* pshhList
-    );
diff --git a/src/ca/scaiis.cpp b/src/ca/scaiis.cpp
deleted file mode 100644
index 958051ed..00000000
--- a/src/ca/scaiis.cpp
+++ /dev/null
@@ -1,481 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-// globals
-LPWSTR vpwzCustomActionData = NULL;
-DWORD vdwCustomActionCost = 0;
-
-HRESULT ScaMetabaseTransaction(__in_z LPCWSTR wzBackup)
-{
-    HRESULT hr = S_OK;
-
-    // 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
-
-    hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"StartMetabaseTransaction"), wzBackup, COST_IIS_TRANSACTIONS);
-    ExitOnFailure(hr, "Failed to schedule StartMetabaseTransaction");
-
-    hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackMetabaseTransaction"), wzBackup, 0);   // rollback cost is irrelevant
-    ExitOnFailure(hr, "Failed to schedule RollbackMetabaseTransaction");
-
-    hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CommitMetabaseTransaction"), wzBackup, 0);  // commit is free
-    ExitOnFailure(hr, "Failed to schedule StartMetabaseTransaction");
-
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaCreateWeb(IMSAdminBase* piMetabase, LPCWSTR /*wzWeb*/, LPCWSTR wzWebBase)
-{
-    Assert(piMetabase);
-
-    HRESULT hr = S_OK;
-    UINT ui = 0;
-
-    hr = ScaCreateMetabaseKey(piMetabase, wzWebBase, L"");
-    ExitOnFailure(hr, "Failed to create web");
-
-    hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsWebServer");
-    ExitOnFailure(hr, "Failed to set key type for web");
-
-    hr = ScaCreateMetabaseKey(piMetabase, wzWebBase, L"Root");
-    ExitOnFailure(hr, "Failed to create web root");
-
-    hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"Root", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsWebVirtualDir");
-    ExitOnFailure(hr, "Failed to set key type for web root");
-
-    ui = 0x4000003e; // 1073741886;    // default directory browsing rights
-    hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"Root", MD_DIRECTORY_BROWSING, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)ui));
-    ExitOnFailure(hr, "Failed to set directory browsing for web");
-
-    hr = ScaCreateMetabaseKey(piMetabase, wzWebBase, L"Filters");
-    ExitOnFailure(hr, "Failed to create web filters root");
-
-    hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"Filters", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsFilters");
-    ExitOnFailure(hr, "Failed to set key for web filters root");
-
-    hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"Filters", MD_FILTER_LOAD_ORDER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"");
-    ExitOnFailure(hr, "Failed to set empty load order for web");
-
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaDeleteApp(IMSAdminBase* piMetabase, LPCWSTR wzWebRoot)
-{
-    Assert(piMetabase);
-    Unused(piMetabase);
-
-    HRESULT hr = S_OK;
-    WCHAR wzKey[METADATA_MAX_NAME_LEN];
-
-    WCHAR* pwzCustomActionData = NULL;
-
-    hr = WcaWriteIntegerToCaData(MBA_DELETEAPP, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase delete app directive to CustomActionData");
-
-    hr = ::StringCchCopyW(wzKey, countof(wzKey), wzWebRoot);
-    ExitOnFailure(hr, "Failed to copy webroot string to key");
-    hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase key to CustomActionData");
-
-    hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_DELETEAPP);
-    ExitOnFailure(hr, "Failed to add ScaDeleteApp action data: %ls cost: %d", pwzCustomActionData, COST_IIS_DELETEAPP);
-
-LExit:
-    ReleaseStr(pwzCustomActionData);
-
-    return hr;
-}
-
-
-HRESULT ScaCreateApp(IMSAdminBase* piMetabase, LPCWSTR wzWebRoot,
-                     DWORD dwIsolation)
-{
-    Assert(piMetabase);
-    Unused(piMetabase);
-
-    HRESULT hr = S_OK;
-    WCHAR wzKey[METADATA_MAX_NAME_LEN];
-    BOOL fInProc = FALSE;
-
-    WCHAR* pwzCustomActionData = NULL;
-
-    hr = WcaWriteIntegerToCaData(MBA_CREATEAPP, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase create app directive to CustomActionData");
-
-    hr = ::StringCchCopyW(wzKey, countof(wzKey), wzWebRoot);
-    ExitOnFailure(hr, "Failed to copy webroot string to key");
-    hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase key to CustomActionData");
-
-    if (0 == dwIsolation)
-        fInProc = TRUE;
-    else
-        fInProc = FALSE;
-
-    hr = WcaWriteIntegerToCaData(fInProc, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add isolation value to CustomActionData");
-
-    hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_CREATEAPP);
-    ExitOnFailure(hr, "Failed to add ScaCreateApp action data: %ls cost: %d", pwzCustomActionData, COST_IIS_CREATEAPP);
-
-LExit:
-    ReleaseStr(pwzCustomActionData);
-
-    return hr;
-}
-
-
-HRESULT ScaCreateMetabaseKey(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
-                             LPCWSTR wzSubKey)
-{
-    Assert(piMetabase);
-    Unused(piMetabase);
-
-    HRESULT hr = S_OK;
-    WCHAR wzKey[METADATA_MAX_NAME_LEN];
-    WCHAR* pwzCustomActionData = NULL;
-
-    hr = ::StringCchCopyW(wzKey, countof(wzKey), wzRootKey);
-    ExitOnFailure(hr, "Failed to copy root key string to key");
-    if (L'/' != *(wzKey + lstrlenW(wzRootKey)))
-    {
-        hr = ::StringCchCatW(wzKey, countof(wzKey), L"/");
-        ExitOnFailure(hr, "Failed to concatenate / to key string");
-    }
-    if (wzSubKey && *wzSubKey)
-    {
-        if (L'/' == *wzSubKey)
-        {
-            hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey + 1);
-            ExitOnFailure(hr, "Failed to concatenate subkey (minus slash) to key string");
-        }
-        else
-        {
-            hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey);
-            ExitOnFailure(hr, "Failed to concatenate subkey to key string");
-        }
-    }
-
-    hr = WcaWriteIntegerToCaData(MBA_CREATEKEY, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase delete key directive to CustomActionData");
-
-    hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase key to CustomActionData");
-
-    hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_CREATEKEY);
-    ExitOnFailure(hr, "Failed to add ScaCreateMetabaseKey action data: %ls cost: %d", pwzCustomActionData, COST_IIS_CREATEKEY);
-
-LExit:
-    ReleaseStr(pwzCustomActionData);
-
-    return hr;
-}
-
-
-HRESULT ScaDeleteMetabaseKey(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
-                             LPCWSTR wzSubKey)
-{
-    Assert(piMetabase);
-    Unused(piMetabase);
-
-    HRESULT hr = S_OK;
-    WCHAR wzKey[METADATA_MAX_NAME_LEN];
-    WCHAR* pwzCustomActionData = NULL;
-
-    hr = ::StringCchCopyW(wzKey, countof(wzKey), wzRootKey);
-    ExitOnFailure(hr, "Failed to copy root key string to key");
-    if (L'/' != *(wzKey + lstrlenW(wzRootKey)))
-    {
-        hr = ::StringCchCatW(wzKey, countof(wzKey), L"/");
-        ExitOnFailure(hr, "Failed to concatenate / to key string");
-    }
-    if (*wzSubKey)
-    {
-        if (L'/' == *wzSubKey)
-        {
-            hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey + 1);
-            ExitOnFailure(hr, "Failed to concatenate subkey (minus slash) to key string");
-        }
-        else
-        {
-            hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey);
-            ExitOnFailure(hr, "Failed to concatenate subkey to key string");
-        }
-    }
-
-    hr = WcaWriteIntegerToCaData(MBA_DELETEKEY, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase delete key directive to CustomActionData");
-
-    hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase key to CustomActionData");
-
-    hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_DELETEKEY);
-    ExitOnFailure(hr, "Failed to add ScaDeleteMetabaseKey action data: %ls cost: %d", pwzCustomActionData, COST_IIS_DELETEKEY);
-
-LExit:
-    ReleaseStr(pwzCustomActionData);
-
-    return hr;
-}
-
-
-HRESULT ScaDeleteMetabaseValue(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
-                              LPCWSTR wzSubKey, DWORD dwIdentifier,
-                              DWORD dwDataType)
-{
-    Assert(piMetabase);
-    Unused(piMetabase);
-
-    HRESULT hr = S_OK;
-    WCHAR wzKey[METADATA_MAX_NAME_LEN];
-    WCHAR* pwzCustomActionData = NULL;
-
-    hr = ::StringCchCopyW(wzKey, countof(wzKey), wzRootKey);
-    ExitOnFailure(hr, "Failed to copy root key string to key");
-    if (L'/' != *(wzKey + lstrlenW(wzRootKey)))
-    {
-        hr = ::StringCchCatW(wzKey, countof(wzKey), L"/");
-        ExitOnFailure(hr, "Failed to concatenate / to key string");
-    }
-
-    if (wzSubKey && *wzSubKey)
-    {
-        if (L'/' == *wzSubKey)
-        {
-            hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey + 1);
-            ExitOnFailure(hr, "Failed to concatenate subkey (minus slash) to key string");
-        }
-        else
-        {
-            hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey);
-            ExitOnFailure(hr, "Failed to concatenate subkey to key string");
-        }
-    }
-
-    hr = WcaWriteIntegerToCaData(MBA_DELETEVALUE, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase write value directive to CustomActionData");
-
-    hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase key to CustomActionData");
-
-    hr = WcaWriteIntegerToCaData(dwIdentifier, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase identifier to CustomActionData");
-
-    hr = WcaWriteIntegerToCaData(dwDataType, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase data type to CustomActionData");
-
-    hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_DELETEVALUE);
-    ExitOnFailure(hr, "Failed to add ScaDeleteMetabaseValue action data: %ls, cost: %d", pwzCustomActionData, COST_IIS_DELETEVALUE);
-
-LExit:
-    ReleaseStr(pwzCustomActionData);
-
-    return hr;
-}
-
-
-#pragma prefast(push)
-#pragma prefast(disable:25120) // Disable "requires count parameter" warning - we do have a way to distinguish buffer sizes in all situations,
-                               // it just depends on the dwDataType, and there's no way to annotate the situation in SAL
-HRESULT ScaWriteMetabaseValue(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
-                              LPCWSTR wzSubKey, DWORD dwIdentifier,
-                              DWORD dwAttributes, DWORD dwUserType,
-                              DWORD dwDataType, LPVOID pvData)
-#pragma prefast(pop)
-{
-    Assert(piMetabase && (pvData || (DWORD_METADATA == dwDataType)));    // pvData may be 0 if it is DWORD data
-    Unused(piMetabase);
-
-    HRESULT hr = S_OK;
-    WCHAR wzKey[METADATA_MAX_NAME_LEN];
-    WCHAR* pwzCustomActionData = NULL;
-
-    if (BINARY_METADATA == dwDataType)
-    {
-        ExitOnNull(pvData, hr, E_INVALIDARG, "Failed to write binary metadata - no data available to write");
-    }
-
-    hr = ::StringCchCopyW(wzKey, countof(wzKey), wzRootKey);
-    ExitOnFailure(hr, "Failed to copy root key string to key");
-    if (L'/' != *(wzKey + lstrlenW(wzRootKey)))
-    {
-        hr = ::StringCchCatW(wzKey, countof(wzKey), L"/");
-        ExitOnFailure(hr, "Failed to concatenate / to key string");
-    }
-    if (wzSubKey && *wzSubKey)
-    {
-        if (L'/' == *wzSubKey)
-        {
-            hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey + 1);
-            ExitOnFailure(hr, "Failed to concatenate subkey (minus slash) to key string");
-        }
-        else
-        {
-            hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey);
-            ExitOnFailure(hr, "Failed to concatenate subkey to key string");
-        }
-    }
-
-    hr = WcaWriteIntegerToCaData(MBA_WRITEVALUE, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase write value directive to CustomActionData");
-
-    hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase key to CustomActionData");
-
-    hr = WcaWriteIntegerToCaData(dwIdentifier, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase identifier to CustomActionData");
-
-    hr = WcaWriteIntegerToCaData(dwAttributes, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase attributes to CustomActionData");
-
-    hr = WcaWriteIntegerToCaData(dwUserType, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase user type to CustomActionData");
-
-    hr = WcaWriteIntegerToCaData(dwDataType, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase data type to CustomActionData");
-
-    switch (dwDataType)
-    {
-    case DWORD_METADATA:
-        hr = WcaWriteIntegerToCaData((DWORD)((DWORD_PTR)pvData), &pwzCustomActionData);
-        break;
-    case STRING_METADATA:
-        hr = WcaWriteStringToCaData((LPCWSTR)pvData, &pwzCustomActionData);
-        break;
-    case MULTISZ_METADATA:
-        {
-        // change NULLs to unprintable character  to create a 'safe' MULTISZ string
-        LPWSTR pwz = (LPWSTR)pvData;
-        for (;;)
-        {
-            if ('\0' == *pwz)
-            {
-                *pwz = MAGIC_MULTISZ_CHAR;
-                if ('\0' == *(pwz + 1))    // second null back to back means end of string
-                    break;
-            }
-
-            ++pwz;
-        }
-
-        hr = WcaWriteStringToCaData((LPCWSTR)pvData, &pwzCustomActionData);
-        }
-        break;
-    case BINARY_METADATA:
-        hr = WcaWriteStreamToCaData(((BLOB*) pvData)->pBlobData, ((BLOB*) pvData)->cbSize, &pwzCustomActionData);
-        break;
-    default:
-        hr = E_UNEXPECTED;
-    }
-    ExitOnFailure(hr, "Failed to add metabase data to CustomActionData");
-
-    // TODO: maybe look the key up and make sure we're not just writing the same value that already there
-
-    hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_WRITEVALUE);
-    ExitOnFailure(hr, "Failed to add ScaWriteMetabaseValue action data: %ls, cost: %d", pwzCustomActionData, COST_IIS_WRITEVALUE);
-
-LExit:
-    ReleaseStr(pwzCustomActionData);
-
-    return hr;
-}
-
-
-HRESULT ScaAddToIisConfiguration(LPCWSTR pwzData, DWORD dwCost)
-{
-    HRESULT hr = S_OK;
-
-    hr = WcaWriteStringToCaData(pwzData, &vpwzCustomActionData);
-    ExitOnFailure(hr, "failed to add to metabase configuration data string: %ls", pwzData);
-
-    vdwCustomActionCost += dwCost;
-
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaWriteConfigurationScript(__in LPCWSTR pwzCaScriptKey)
-{
-    HRESULT hr = S_OK;
-    WCA_CASCRIPT_HANDLE hScript = NULL;
-    LPWSTR pwzHashString = NULL;
-    BYTE rgbActualHash[SHA1_HASH_LEN] = { };
-    DWORD dwHashedBytes = SHA1_HASH_LEN;
-
-    // Create CaScript for communication with WriteMetabaseChanges
-    hr = WcaCaScriptCreate(WCA_ACTION_INSTALL, WCA_CASCRIPT_SCHEDULED, FALSE, pwzCaScriptKey, FALSE, &hScript);
-    ExitOnFailure(hr, "Failed to write ca script for WriteMetabaseChanges script.");
-
-    if (vpwzCustomActionData && *vpwzCustomActionData)
-    {
-        // Write the actual custom action data to the ca script
-        WcaCaScriptWriteString(hScript, vpwzCustomActionData);
-
-        hr = CrypHashBuffer((BYTE*)vpwzCustomActionData, sizeof(vpwzCustomActionData) * sizeof(WCHAR), PROV_RSA_AES, CALG_SHA1, rgbActualHash, dwHashedBytes);
-        ExitOnFailure(hr, "Failed to calculate hash of CustomAction data.");
-
-        hr = StrAlloc(&pwzHashString, ((dwHashedBytes * 2) + 1));
-        ExitOnFailure(hr, "Failed to allocate string for script hash");
-
-        hr = StrHexEncode(rgbActualHash, dwHashedBytes, pwzHashString, ((dwHashedBytes * 2) + 1));
-        ExitOnFailure(hr, "Failed to convert hash bytes to string.");
-
-        WcaLog(LOGMSG_VERBOSE,  "Custom action data hash: %ls", pwzHashString);
-        WcaLog(LOGMSG_TRACEONLY, "Custom action data being written to ca script: %ls", vpwzCustomActionData);
-    }
-    else
-        hr = S_FALSE;
-
-LExit:
-    // Release the string
-    ReleaseStr(vpwzCustomActionData);
-    ReleaseStr(pwzHashString);
-
-    // Flush the ca script to disk as best we can
-    WcaCaScriptFlush(hScript);
-
-    WcaCaScriptClose(hScript, WCA_CASCRIPT_CLOSE_PRESERVE);
-
-    return hr;
-}
-
-
-HRESULT ScaLoadMetabase(IMSAdminBase** ppiMetabase)
-{
-    HRESULT hr = S_OK;
-    UINT er = ERROR_SUCCESS;
-
-    // if IIS was uninstalled (thus no IID_IMSAdminBase) allow the
-    // user to still uninstall this package by clicking "Ignore"
-    do
-    {
-        hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, (void**)ppiMetabase);
-        if (FAILED(hr))
-        {
-            WcaLog(LOGMSG_STANDARD, "failed to get IID_IMSAdminBase Object");
-            er = WcaErrorMessage(msierrIISCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
-            switch (er)
-            {
-            case IDABORT:
-                ExitFunction();   // bail with the error result from the CoCreate to kick off a rollback
-            case IDRETRY:
-                hr = S_FALSE;   // hit me, baby, one more time
-                break;
-            case IDIGNORE:
-                hr = S_OK;  // pretend everything is okay and bail
-                break;
-            default:  // For failure on uninstall continue
-                hr = S_OK;
-                break;
-            }
-        }
-    } while (S_FALSE == hr);
-
-LExit:
-    return hr;
-}
diff --git a/src/ca/scaiis.h b/src/ca/scaiis.h
deleted file mode 100644
index 4c743edf..00000000
--- a/src/ca/scaiis.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#pragma once
-// 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.
-
-
-HRESULT ScaMetabaseTransaction(__in_z LPCWSTR wzBackup);
-
-HRESULT ScaCreateWeb(IMSAdminBase* piMetabase, LPCWSTR wzWeb, LPCWSTR wzWebBase);
-
-HRESULT ScaDeleteApp(IMSAdminBase* piMetabase, LPCWSTR wzWebRoot);
-
-HRESULT ScaCreateApp(IMSAdminBase* piMetabase, LPCWSTR wzWebRoot,
-                     DWORD dwIsolation);
-
-HRESULT ScaCreateMetabaseKey(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
-                             LPCWSTR wzSubKey);
-
-HRESULT ScaDeleteMetabaseKey(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
-                             LPCWSTR wzSubKey);
-
-HRESULT ScaWriteMetabaseValue(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
-                              LPCWSTR wzSubKey, DWORD dwIdentifier,
-                              DWORD dwAttributes, DWORD dwUserType,
-                              DWORD dwDataType, LPVOID pvData);
-
-HRESULT ScaDeleteMetabaseValue(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
-                              LPCWSTR wzSubKey, DWORD dwIdentifier,
-                              DWORD dwDataType);
-
-HRESULT ScaWriteConfigurationScript(LPCWSTR pwzCaScriptKey);
-
-HRESULT ScaAddToIisConfiguration(LPCWSTR pwzData, DWORD dwCost);
-
-HRESULT ScaLoadMetabase(IMSAdminBase** piMetabase);
diff --git a/src/ca/scaiis7.cpp b/src/ca/scaiis7.cpp
deleted file mode 100644
index aaf307d7..00000000
--- a/src/ca/scaiis7.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-#define COST_IIS_WRITEKEY 10
-
-HRESULT ScaIIS7ConfigTransaction(LPCWSTR wzBackup)
-{
-    HRESULT hr = S_OK;
-
-    hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"StartIIS7ConfigTransaction"), wzBackup, COST_IIS_TRANSACTIONS);
-    ExitOnFailure(hr, "Failed to schedule StartIIS7ConfigTransaction");
-
-    hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackIIS7ConfigTransaction"), wzBackup, 0);   // rollback cost is irrelevant
-    ExitOnFailure(hr, "Failed to schedule RollbackIIS7ConfigTransaction");
-
-    hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CommitIIS7ConfigTransaction"), wzBackup, 0);  // commit is free
-    ExitOnFailure(hr, "Failed to schedule StartIIS7ConfigTransaction");
-
-LExit:
-    return hr;
-}
-
-HRESULT ScaWriteConfigString(const LPCWSTR wzValue)
-{
-    HRESULT hr = S_OK;
-    WCHAR* pwzCustomActionData = NULL;
-
-    hr = WcaWriteStringToCaData(wzValue, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase delete key directive to CustomActionData");
-
-    hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_WRITEKEY);
-    ExitOnFailure(hr, "Failed to add ScaWriteMetabaseValue action data: %ls, cost: %d", pwzCustomActionData, COST_IIS_WRITEKEY);
-
-LExit:
-    ReleaseStr(pwzCustomActionData);
-
-    return hr;
-}
-
-HRESULT ScaWriteConfigInteger(DWORD dwValue)
-{
-    HRESULT hr = S_OK;
-    WCHAR* pwzCustomActionData = NULL;
-
-    hr = WcaWriteIntegerToCaData(dwValue, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase delete key directive to CustomActionData");
-
-    hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_WRITEKEY);
-    ExitOnFailure(hr, "Failed to add ScaWriteMetabaseValue action data: %ls, cost: %d", pwzCustomActionData, COST_IIS_WRITEKEY);
-
-LExit:
-    ReleaseStr(pwzCustomActionData);
-
-    return hr;
-}
-
-HRESULT ScaWriteConfigID(IIS_CONFIG_ACTION emID)
-{
-    HRESULT hr = S_OK;
-    WCHAR* pwzCustomActionData = NULL;
-
-    hr = WcaWriteIntegerToCaData(emID, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add metabase delete key directive to CustomActionData");
-
-    hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_WRITEKEY);
-    ExitOnFailure(hr, "Failed to add ScaWriteMetabaseValue action data: %ls, cost: %d", pwzCustomActionData, COST_IIS_WRITEKEY);
-
-LExit:
-    ReleaseStr(pwzCustomActionData);
-
-    return hr;
-}
-
diff --git a/src/ca/scaiis7.h b/src/ca/scaiis7.h
deleted file mode 100644
index f398deca..00000000
--- a/src/ca/scaiis7.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-// 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.
-
-
-HRESULT ScaScheduleIIS7Configuration();
-
-HRESULT ScaIIS7ConfigTransaction(__in_z LPCWSTR wzBackup);
-
-HRESULT ScaCreateApp7(__in_z LPCWSTR wzWebRoot, DWORD dwIsolation);
-
-HRESULT ScaDeleteConfigElement(IIS_CONFIG_ACTION emElement, LPCWSTR wzSubKey);
-
-HRESULT ScaWriteConfigString(__in_z const LPCWSTR wzValue);
-
-HRESULT ScaWriteConfigID(IIS_CONFIG_ACTION emID);
-
-HRESULT ScaWriteConfigInteger(DWORD dwValue);
diff --git a/src/ca/scamimemap.cpp b/src/ca/scamimemap.cpp
deleted file mode 100644
index 8afe99f9..00000000
--- a/src/ca/scamimemap.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-enum eMimeMapQuery { mmqMimeMap = 1, mmqParentType, mmqParentValue, 
-                        mmqMimeType, mmqExtension};
-
-// prototypes
-static HRESULT AddMimeMapToList(SCA_MIMEMAP** ppsmmList);
-
-
-void ScaMimeMapFreeList(SCA_MIMEMAP* psmmList)
-{
-    SCA_MIMEMAP* psmmDelete = psmmList;
-    while (psmmList)
-    {
-        psmmDelete = psmmList;
-        psmmList = psmmList->psmmNext;
-
-        MemFree(psmmDelete);
-    }
-}
-
-
-HRESULT __stdcall ScaMimeMapRead(
-    SCA_MIMEMAP** ppsmmList,
-    __inout LPWSTR *ppwzCustomActionData
-    )
-{
-    HRESULT hr = S_OK;
-    MSIHANDLE hRec;
-    LPWSTR pwzData = NULL;
-    SCA_MIMEMAP* psmm;
-    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
-
-    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap query for ScaMimeMapRead");
-
-    if (0 == WcaGetQueryRecords(hWrapQuery))
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ScaMimeMapRead() - required table not present");
-        ExitFunction1(hr = S_FALSE);
-    }
-
-    // loop through all the mimemappings
-    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
-    {
-        hr = AddMimeMapToList(ppsmmList);
-        ExitOnFailure(hr, "failed to add mime map to list");
-
-        psmm = *ppsmmList;
-
-        hr = WcaGetRecordString(hRec, mmqMimeMap, &pwzData);
-        ExitOnFailure(hr, "Failed to get MimeMap.MimeMap");
-        hr = ::StringCchCopyW(psmm->wzMimeMap, countof(psmm->wzMimeMap), pwzData);
-        ExitOnFailure(hr, "Failed to copy mimemap string to mimemap object");
-
-        hr = WcaGetRecordInteger(hRec, mmqParentType, &psmm->iParentType);
-        ExitOnFailure(hr, "Failed to get MimeMap.iParentType");
-    
-        hr = WcaGetRecordString(hRec, mmqParentValue, &pwzData);
-        ExitOnFailure(hr, "Failed to get MimeMap.ParentValue");
-        hr = ::StringCchCopyW(psmm->wzParentValue, countof(psmm->wzParentValue), pwzData);
-        ExitOnFailure(hr, "Failed to copy parent value string to mimemap object");
-
-        hr = WcaGetRecordString(hRec, mmqExtension, &pwzData);
-        ExitOnFailure(hr, "Failed to get MimeMap.Extension");
-        hr = ::StringCchCopyW(psmm->wzExtension, countof(psmm->wzExtension), pwzData);
-        ExitOnFailure(hr, "Failed to copy extension string to mimemap object");
-
-        hr = WcaGetRecordString(hRec, mmqMimeType, &pwzData);
-        ExitOnFailure(hr, "Failed to get MimeMap.MimeType");
-        hr = ::StringCchCopyW(psmm->wzMimeType, countof(psmm->wzMimeType), pwzData);
-        ExitOnFailure(hr, "Failed to copy mimetype string to mimemap object");
-    }
-
-    if (E_NOMOREITEMS == hr)
-        hr = S_OK;
-    ExitOnFailure(hr, "Failure while processing mimemappings");
-
-LExit:
-    WcaFinishUnwrapQuery(hWrapQuery);
-
-    ReleaseStr(pwzData);
-
-    return hr;
-}
-
-
-HRESULT ScaGetMimeMap(int iParentType, LPCWSTR wzParentValue, SCA_MIMEMAP **ppsmmList, SCA_MIMEMAP **ppsmmOut)
-{
-    HRESULT hr = S_OK;
-    SCA_MIMEMAP* psmmAdd = NULL;
-    SCA_MIMEMAP* psmmLast = NULL;
-
-    *ppsmmOut = NULL;
-    
-    if (!*ppsmmList)
-        return hr;
-
-    SCA_MIMEMAP* psmm = *ppsmmList;
-    while (psmm)
-    {
-        if (iParentType == psmm->iParentType && 0 == lstrcmpW(wzParentValue, psmm->wzParentValue))
-        {
-            // Found a match, take this one out of the list and add it to the matched out list
-            psmmAdd = psmm;
-
-            if (psmmLast)
-            {
-                // 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)
-                psmmLast->psmmNext = psmmAdd->psmmNext;
-            }
-            else
-            {
-                // If we are at the beginning (no psmmLast) update the beginning (since we're taking it)
-                *ppsmmList = psmm->psmmNext;
-            }
-            psmm = psmm->psmmNext; // move on
-
-            // Add the one we've removed to the beginning of the out list
-            psmmAdd->psmmNext = *ppsmmOut;
-            *ppsmmOut = psmmAdd;
-        }
-        else
-        {
-            psmmLast = psmm; // remember the last we that didn't match
-            psmm = psmm->psmmNext; // move on
-        }
-    }
-
-    return hr;
-}
-
-HRESULT ScaMimeMapCheckList(SCA_MIMEMAP* psmmList)
-{
-    if (!psmmList)
-        return S_OK;
-    
-    while (psmmList)
-    {
-        WcaLog(LOGMSG_STANDARD, "MimeMapping of %ls with ParentType=%d and ParentValue=%ls not used!", psmmList->wzMimeMap, psmmList->iParentType, psmmList->wzParentValue);
-        psmmList = psmmList->psmmNext;
-    }
-
-    return E_FAIL;
-}
-
-
-HRESULT ScaWriteMimeMap(IMSAdminBase* piMetabase, LPCWSTR wzRootOfWeb, 
-                               SCA_MIMEMAP* psmmList)
-{
-    HRESULT hr = S_OK;
-
-    WCHAR wzMimeMap[8192];
-    WCHAR *pwzNext = wzMimeMap;
-    const WCHAR *pwzMac = wzMimeMap + countof(wzMimeMap); // used to properly create the MULTI_SZ
-
-    // fill the MULTI_SZ wzMimeMap buffer for the MimeMap attribute
-    ::ZeroMemory(wzMimeMap, sizeof(wzMimeMap));
-
-    for (SCA_MIMEMAP* psmm = psmmList; psmm; psmm = psmm->psmmNext)
-    {
-        hr = ::StringCchPrintfW(pwzNext, max(0, pwzMac - pwzNext), L"%s,%s", psmm->wzExtension, psmm->wzMimeType);
-        ExitOnFailure(hr, "Failed to set MimeMap string");
-
-        pwzNext += lstrlenW(pwzNext) + 1; // reserve space for null
-        Assert(pwzNext <= pwzMac);
-    }
-
-    if (pwzNext != wzMimeMap)
-    {
-        // now write the CustomErrors to the metabase
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_MIME_MAP, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, wzMimeMap);
-        ExitOnFailure(hr, "Failed to write MimeMap");
-    }
-    else
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ScaWriteMimeMap() - no mappings found.");
-        ExitFunction1(hr = S_FALSE);
-    }
-
-LExit:
-    return hr;
-}
-
-
-static HRESULT AddMimeMapToList(SCA_MIMEMAP** ppsmmList)
-{
-    HRESULT hr = S_OK;
-
-    SCA_MIMEMAP* psmm = static_cast<SCA_MIMEMAP*>(MemAlloc(sizeof(SCA_MIMEMAP), TRUE));
-    ExitOnNull(psmm, hr, E_OUTOFMEMORY, "failed to allocate memory for new mime map list element");
-
-    psmm->psmmNext = *ppsmmList;
-    *ppsmmList = psmm;
-    
-LExit:
-    return hr;
-}
diff --git a/src/ca/scamimemap.h b/src/ca/scamimemap.h
deleted file mode 100644
index b50e82e9..00000000
--- a/src/ca/scamimemap.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#pragma once
-// 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.
-
-
-enum eMimeMapParentType	{ mmptVDir = 1, mmptWeb = 2 };
-
-struct SCA_MIMEMAP
-{
-	// iis configuation information
-	WCHAR wzMimeMap[MAX_DARWIN_KEY + 1];
-	int iParentType;
-	WCHAR wzParentValue[MAX_DARWIN_KEY + 1];
-	WCHAR wzMimeType[MAX_DARWIN_KEY + 1];
-	WCHAR wzExtension[MAX_DARWIN_KEY + 1];
-
-
-	SCA_MIMEMAP* psmmNext;
-};
-
-
-// prototypes
-
-HRESULT __stdcall ScaMimeMapRead(SCA_MIMEMAP** ppsmmList, __inout LPWSTR *ppwzCustomActionData);
-
-HRESULT ScaGetMimeMap(int iParentType, LPCWSTR wzParentValue, SCA_MIMEMAP **psmmList, SCA_MIMEMAP **ppsmmOut);
-
-HRESULT ScaMimeMapCheckList(SCA_MIMEMAP* psmmList);
-
-void ScaMimeMapFreeList(SCA_MIMEMAP* psmmList);
-
-HRESULT ScaWriteMimeMap(IMSAdminBase* piMetabase, LPCWSTR wzRootOfWeb, 
-                               SCA_MIMEMAP* psmmList);
-
diff --git a/src/ca/scamimemap7.cpp b/src/ca/scamimemap7.cpp
deleted file mode 100644
index f6689720..00000000
--- a/src/ca/scamimemap7.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-// prototypes
-HRESULT ScaWriteMimeMap7(
-    __in_z LPCWSTR wzWebName,
-    __in_z LPCWSTR wzRootOfWeb,
-    SCA_MIMEMAP* psmmList
-    )
-{
-    HRESULT hr = S_OK;
-    SCA_MIMEMAP* psmm;
-
-    //create the mimemap list for this vdir application
-    //all go to same web/root location tag
-    hr = ScaWriteConfigID(IIS_MIMEMAP_BEGIN);
-    ExitOnFailure(hr, "Failed to write mimemap begin id");
-    hr = ScaWriteConfigString(wzWebName);                //site name key
-    ExitOnFailure(hr, "Failed to write mimemap web key");
-    hr = ScaWriteConfigString(wzRootOfWeb);               //app path key
-    ExitOnFailure(hr, "Failed to write mimemap app key");
-
-    psmm = psmmList;
-
-    while (psmm)
-    {
-        //create the Extension for this vdir application
-        hr = ScaWriteConfigID(IIS_MIMEMAP);
-        ExitOnFailure(hr, "Failed to write mimemap id");
-
-        if (*psmm->wzExtension)
-        {
-            hr = ScaWriteConfigString(psmm->wzExtension);
-        }
-        else   // blank means "*" (all)
-        {
-            hr = ScaWriteConfigString(L"*");
-        }
-        ExitOnFailure(hr, "Failed to write mimemap extension");
-
-        hr = ScaWriteConfigString(psmm->wzMimeType);
-        ExitOnFailure(hr, "Failed to write mimemap type");
-
-        psmm = psmm->psmmNext;
-    }
-
-    hr = ScaWriteConfigID(IIS_MIMEMAP_END);
-    ExitOnFailure(hr, "Failed to write mimemap end id");
-
-LExit:
-    return hr;
-}
-
-
-//static HRESULT AddMimeMapToList(SCA_MIMEMAP** ppsmmList)
-//{
-//    HRESULT hr = S_OK;
-//
-//    SCA_MIMEMAP* psmm = static_cast<SCA_MIMEMAP*>(MemAlloc(sizeof(SCA_MIMEMAP), TRUE));
-//    ExitOnNull(psmm, hr, E_OUTOFMEMORY, "failed to allocate memory for new mime map list element");
-//
-//    psmm->psmmNext = *ppsmmList;
-//    *ppsmmList = psmm;
-//
-//LExit:
-//    return hr;
-//}
diff --git a/src/ca/scamimemap7.h b/src/ca/scamimemap7.h
deleted file mode 100644
index 88fcdc39..00000000
--- a/src/ca/scamimemap7.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#pragma once
-// 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.
-
-
-HRESULT ScaWriteMimeMap7(
-    __in_z LPCWSTR wzWebName,
-    __in_z LPCWSTR wzRootOfWeb,
-    SCA_MIMEMAP* psmmList
-    );
-
diff --git a/src/ca/scaproperty.cpp b/src/ca/scaproperty.cpp
deleted file mode 100644
index d0e0d8a4..00000000
--- a/src/ca/scaproperty.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-/*------------------------------------------------------------------
-IIsProperty table:
-
-Property  Component_  Attributes  Value
-s72      s72         i4          s255
-------------------------------------------------------------------*/
-
-// sql queries
-enum ePropertyQuery { pqProperty = 1, pqComponent, pqAttributes, pqValue, pqInstalled, pqAction };
-
-
-// prototypes
-static HRESULT AddPropertyToList(
-    SCA_PROPERTY** ppspList
-    );
-
-
-// functions
-void ScaPropertyFreeList(
-    SCA_PROPERTY* pspList
-    )
-{
-    SCA_PROPERTY* pspDelete = pspList;
-    while (pspList)
-    {
-        pspDelete = pspList;
-        pspList = pspList->pspNext;
-
-        MemFree(pspDelete);
-    }
-}
-
-
-HRESULT ScaPropertyRead(
-    SCA_PROPERTY** ppspList,
-    __inout LPWSTR *ppwzCustomActionData
-    )
-{
-    HRESULT hr = S_OK;
-    MSIHANDLE hRec;
-
-    LPWSTR pwzData = NULL;
-    SCA_PROPERTY* pss;
-
-    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
-
-    ExitOnNull(ppspList, hr, E_INVALIDARG, "Failed to read property, because no property to read was provided");
-
-    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead");
-
-    if (0 == WcaGetQueryRecords(hWrapQuery))
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ScaInstallProperty() - required table not present");
-        ExitFunction1(hr = S_FALSE);
-    }
-
-    // loop through all the Settings
-    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
-    {
-        hr = AddPropertyToList(ppspList);
-        ExitOnFailure(hr, "failed to add property to list");
-
-        pss = *ppspList;
-
-        hr = WcaGetRecordString(hRec, pqProperty, &pwzData);
-        ExitOnFailure(hr, "failed to get IIsProperty.Property");
-        hr = ::StringCchCopyW(pss->wzProperty, countof(pss->wzProperty), pwzData);
-        ExitOnFailure(hr, "failed to copy Property name: %ls", pwzData);
-
-        hr = WcaGetRecordString(hRec, pqValue, &pwzData);
-        ExitOnFailure(hr, "failed to get IIsProperty.Value");
-        hr = ::StringCchCopyW(pss->wzValue, countof(pss->wzValue), pwzData);
-        ExitOnFailure(hr, "failed to copy Property value: %ls", pwzData);
-
-        hr = WcaGetRecordInteger(hRec, pqAttributes, &pss->iAttributes);
-        ExitOnFailure(hr, "failed to get IIsProperty.Attributes");
-
-        hr = WcaGetRecordString(hRec, pqComponent, &pwzData);
-        ExitOnFailure(hr, "failed to get IIsProperty.Component");
-        hr = ::StringCchCopyW(pss->wzComponent, countof(pss->wzComponent), pwzData);
-        ExitOnFailure(hr, "failed to copy component name: %ls", pwzData);
-
-        hr = WcaGetRecordInteger(hRec, pqInstalled, (int *)&pss->isInstalled);
-        ExitOnFailure(hr, "Failed to get Component installed state for filter");
-
-        hr = WcaGetRecordInteger(hRec, pqAction, (int *)&pss->isAction);
-        ExitOnFailure(hr, "Failed to get Component action state for filter");
-    }
-
-    if (E_NOMOREITEMS == hr)
-    {
-        hr = S_OK;
-    }
-    ExitOnFailure(hr, "failure while processing IIsProperty table");
-
-LExit:
-    WcaFinishUnwrapQuery(hWrapQuery);
-
-    ReleaseStr(pwzData);
-
-    return hr;
-}
-
-
-HRESULT ScaPropertyInstall(
-    IMSAdminBase* piMetabase, 
-    SCA_PROPERTY* pspList
-    )
-{
-    Assert(piMetabase);
-
-    HRESULT hr = S_OK;
-
-    for (SCA_PROPERTY* psp = pspList; psp; psp = psp->pspNext)
-    {
-        // if we are installing the web site
-        if (WcaIsInstalling(psp->isInstalled, psp->isAction))
-        {
-            hr = ScaWriteProperty(piMetabase, psp);
-            ExitOnFailure(hr, "failed to write Property '%ls' to metabase", psp->wzProperty);
-        }
-    }
-
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaPropertyUninstall(
-    IMSAdminBase* piMetabase, 
-    SCA_PROPERTY* pspList
-    )
-{
-    Assert(piMetabase);
-
-    HRESULT hr = S_OK;
-
-    for (SCA_PROPERTY* psp = pspList; psp; psp = psp->pspNext)
-    {
-        // if we are uninstalling the web site
-        if (WcaIsUninstalling(psp->isInstalled, psp->isAction))
-        {
-            hr = ScaRemoveProperty(piMetabase, psp);
-            ExitOnFailure(hr, "Failed to remove Property '%ls' from metabase", psp->wzProperty);
-        }
-    }
-
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaWriteProperty(
-    IMSAdminBase* piMetabase, 
-    SCA_PROPERTY* psp
-    )
-{
-    Assert(piMetabase);
-
-    HRESULT hr = S_OK;
-    DWORD dwValue;
-    LPWSTR wz = NULL;
-
-    ExitOnNull(psp, hr, E_INVALIDARG, "Failed to write property because no property to write was given");
-
-    //
-    // Figure out what setting we're writing and write it
-    //
-    if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_IIS5_ISOLATION_MODE))
-    {
-        dwValue = 1;
-        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));
-        ExitOnFailure(hr, "failed to set IIs5IsolationMode");
-    }
-    else if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_MAX_GLOBAL_BANDWIDTH))
-    {
-        dwValue = wcstoul(psp->wzValue, &wz, 10) * 1024; // remember, the value shown is in kilobytes, the value saved is in bytes
-        hr = ScaWriteMetabaseValue(piMetabase, L"/LM/W3SVC", NULL, MD_MAX_GLOBAL_BANDWIDTH, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwValue));
-        ExitOnFailure(hr, "failed to set MaxGlobalBandwidth");
-    }
-    else if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_LOG_IN_UTF8))
-    {
-        dwValue = 1;
-        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));
-        ExitOnFailure(hr, "failed to set LogInUTF8");
-    }
-    else if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_ETAG_CHANGENUMBER))
-    {
-        dwValue = wcstoul(psp->wzValue, &wz, 10);
-        hr = ScaWriteMetabaseValue(piMetabase, L"/LM/W3SVC", NULL, /*MD_ETAG_CHANGENUMBER*/ 2039, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwValue));
-        ExitOnFailure(hr, "failed to set EtagChangenumber");
-    }
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaRemoveProperty(
-    IMSAdminBase* piMetabase, 
-    SCA_PROPERTY* psp
-    )
-{
-    Assert(piMetabase);
-
-    HRESULT hr = S_OK;
-    DWORD dwValue;
-
-    ExitOnNull(psp, hr, E_INVALIDARG, "Failed to remove property because no property to remove was given");
-
-    if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_IIS5_ISOLATION_MODE))
-    {
-        dwValue = 0;
-        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));
-        ExitOnFailure(hr, "failed to clear IIs5IsolationMode");
-    }
-    else if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_MAX_GLOBAL_BANDWIDTH))
-    {
-        dwValue = 0xFFFFFFFF; // This unchecks the box
-        hr = ScaWriteMetabaseValue(piMetabase, L"/LM/W3SVC", NULL, MD_MAX_GLOBAL_BANDWIDTH, METADATA_NO_ATTRIBUTES , IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwValue));
-        ExitOnFailure(hr, "failed to clear MaxGlobalBandwidth");
-    }
-    else if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_LOG_IN_UTF8))
-    {
-        dwValue = 0;
-        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));
-        ExitOnFailure(hr, "failed to clear LogInUTF8");
-    }
-
-LExit:
-    return hr;
-}
-
-
-static HRESULT AddPropertyToList(
-    SCA_PROPERTY** ppspList
-    )
-{
-    HRESULT hr = S_OK;
-    SCA_PROPERTY* psp = static_cast<SCA_PROPERTY*>(MemAlloc(sizeof(SCA_PROPERTY), TRUE));
-    ExitOnNull(psp, hr, E_OUTOFMEMORY, "failed to allocate memory for new property list element");
-    
-    psp->pspNext = *ppspList;
-    *ppspList = psp;
-    
-LExit:
-    return hr;
-}
diff --git a/src/ca/scaproperty.h b/src/ca/scaproperty.h
deleted file mode 100644
index 21e7cfc7..00000000
--- a/src/ca/scaproperty.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#pragma once
-// 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.
-
-
-#define wzIISPROPERTY_IIS5_ISOLATION_MODE L"IIs5IsolationMode"
-#define wzIISPROPERTY_MAX_GLOBAL_BANDWIDTH L"MaxGlobalBandwidth"
-#define wzIISPROPERTY_LOG_IN_UTF8 L"LogInUTF8"
-#define wzIISPROPERTY_ETAG_CHANGENUMBER L"ETagChangeNumber"
-
-struct SCA_PROPERTY
-{
-	// iis configuation information
-	WCHAR wzProperty[MAX_DARWIN_KEY + 1];
-	WCHAR wzComponent[MAX_DARWIN_KEY + 1];
-	INSTALLSTATE isInstalled;
-	INSTALLSTATE isAction;
-	INT iAttributes;
-	WCHAR wzValue[MAX_DARWIN_COLUMN + 1];
-
-	SCA_PROPERTY *pspNext;
-};
-
-
-// prototypes
-
-HRESULT ScaPropertyRead(
-	SCA_PROPERTY** ppspList,
-    __inout LPWSTR *ppwzCustomActionData
-	);
-
-void ScaPropertyFreeList(
-	SCA_PROPERTY* pspList
-	);
-
-HRESULT ScaPropertyInstall(
-	IMSAdminBase* piMetabase, 
-	SCA_PROPERTY* pspList
-	);
-
-HRESULT ScaPropertyUninstall(
-	IMSAdminBase* piMetabase, 
-	SCA_PROPERTY* pspList
-	);
-
-HRESULT ScaWriteProperty(
-	IMSAdminBase* piMetabase, 
-	SCA_PROPERTY* psp
-	);
-
-HRESULT ScaRemoveProperty(
-	IMSAdminBase* piMetabase, 
-	SCA_PROPERTY* psp
-	);
-
diff --git a/src/ca/scaproperty7.cpp b/src/ca/scaproperty7.cpp
deleted file mode 100644
index d17eeb68..00000000
--- a/src/ca/scaproperty7.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-HRESULT ScaPropertyInstall7(
-    SCA_PROPERTY* pspList
-    )
-{
-    HRESULT hr = S_OK;
-
-    for (SCA_PROPERTY* psp = pspList; psp; psp = psp->pspNext)
-    {
-        // if we are installing the web site
-        if (WcaIsInstalling(psp->isInstalled, psp->isAction))
-        {
-            hr = ScaWriteProperty7(psp);
-            ExitOnFailure(hr, "failed to write Property '%ls' ", psp->wzProperty);
-        }
-    }
-
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaPropertyUninstall7(
-    SCA_PROPERTY* pspList
-    )
-{
-    HRESULT hr = S_OK;
-
-    for (SCA_PROPERTY* psp = pspList; psp; psp = psp->pspNext)
-    {
-        // if we are uninstalling the web site
-        if (WcaIsUninstalling(psp->isInstalled, psp->isAction))
-        {
-            hr = ScaRemoveProperty7(psp);
-            ExitOnFailure(hr, "Failed to remove Property '%ls'", psp->wzProperty);
-        }
-    }
-
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaWriteProperty7(
-    const SCA_PROPERTY* psp
-    )
-{
-    HRESULT hr = S_OK;
-    DWORD dwValue;
-    LPWSTR wz = NULL;
-
-    ExitOnNull(psp, hr, E_INVALIDARG, "Failed to write property because no property to write was given");
-    //
-    // Figure out what setting we're writing and write it
-    //
-    if (0 == wcscmp(psp->wzProperty, wzIISPROPERTY_IIS5_ISOLATION_MODE))
-    {
-        // IIs5IsolationMode not supported
-        WcaLog(LOGMSG_VERBOSE, "Not supported by IIS7: IIs5IsolationMode, ignoring");
-    }
-    else if (0 == wcscmp(psp->wzProperty, wzIISPROPERTY_MAX_GLOBAL_BANDWIDTH))
-    {
-        dwValue = wcstoul(psp->wzValue, &wz, 10) * 1024; // remember, the value shown is in kilobytes, the value saved is in bytes
-        hr = ScaWriteConfigID(IIS_PROPERTY);
-        ExitOnFailure(hr, "failed to set Property ID");
-        hr = ScaWriteConfigID(IIS_PROPERTY_MAXBAND);
-        ExitOnFailure(hr, "failed to set Property MSXBAND ID");
-        hr = ScaWriteConfigInteger(dwValue);
-        ExitOnFailure(hr, "failed to set Property MSXBAND value");
-    }
-    else if (0 == wcscmp(psp->wzProperty, wzIISPROPERTY_LOG_IN_UTF8))
-    {
-        dwValue = 1;
-        hr = ScaWriteConfigID(IIS_PROPERTY);
-        ExitOnFailure(hr, "failed to set Property ID");
-        hr = ScaWriteConfigID(IIS_PROPERTY_LOGUTF8);
-        ExitOnFailure(hr, "failed to set Property LOG ID");
-        hr = ScaWriteConfigInteger(dwValue);
-        ExitOnFailure(hr, "failed to set Property Log value");
-    }
-    else if (0 == wcscmp(psp->wzProperty, wzIISPROPERTY_ETAG_CHANGENUMBER))
-    {
-        //EtagChangenumber not supported
-        WcaLog(LOGMSG_VERBOSE, "Not supported by IIS7: EtagChangenumber, ignoring");
-    }
-
-LExit:
-    return hr;
-}
-
-HRESULT ScaRemoveProperty7(
-    __in SCA_PROPERTY* /*psp*/
-    )
-{
-
-    // NOP function for now
-    //The two global values being set by WebProperty:
-    //    <iis:WebProperty Id="MaxGlobalBandwidth" Value="1024" />
-    //    <iis:WebProperty Id ="LogInUTF8" />
-    // should should not be removed on uninstall.
-
-    HRESULT hr = S_OK;
-
-    return hr;
-}
diff --git a/src/ca/scaproperty7.h b/src/ca/scaproperty7.h
deleted file mode 100644
index bbf811e8..00000000
--- a/src/ca/scaproperty7.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma once
-// 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.
-
-
-#define wzIISPROPERTY_IIS5_ISOLATION_MODE L"IIs5IsolationMode"
-#define wzIISPROPERTY_MAX_GLOBAL_BANDWIDTH L"MaxGlobalBandwidth"
-#define wzIISPROPERTY_LOG_IN_UTF8 L"LogInUTF8"
-#define wzIISPROPERTY_ETAG_CHANGENUMBER L"ETagChangeNumber"
-
-// prototypes
-HRESULT ScaPropertyInstall7(
-    SCA_PROPERTY* pspList
-    );
-
-HRESULT ScaPropertyUninstall7(
-    SCA_PROPERTY* pspList
-    );
-
-HRESULT ScaWriteProperty7(
-    const SCA_PROPERTY* psp
-    );
-
-HRESULT ScaRemoveProperty7(
-    SCA_PROPERTY* psp
-    );
-
diff --git a/src/ca/scasched.cpp b/src/ca/scasched.cpp
deleted file mode 100644
index de021275..00000000
--- a/src/ca/scasched.cpp
+++ /dev/null
@@ -1,823 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-const int ConfigureIIsCost = 8;
-const int WriteMetabaseChangesCost = 20;
-const int WriteIIS7ConfigChangesCost = 20;
-
-// sql queries
-LPCWSTR vcsUserDeferredQuery = L"SELECT `User`, `Component_`, `Name`, `Domain`, `Password` FROM `User`";
-
-LPCWSTR vcsWebSvcExtQuery = L"SELECT `Component_`, `File`, `Description`, `Group`, `Attributes` FROM `IIsWebServiceExtension`";
-
-LPCWSTR vcsAppPoolQuery = L"SELECT `AppPool`, `Name`, `Component_`, `Attributes`, `User_`, `RecycleMinutes`, `RecycleRequests`, `RecycleTimes`, `VirtualMemory`, `PrivateMemory`, `IdleTimeout`, `QueueLimit`, `CPUMon`, `MaxProc`, `ManagedRuntimeVersion`, `ManagedPipelineMode` FROM `IIsAppPool`";
-
-LPCWSTR vcsComponentAttrQuery = L"SELECT `Component`,`Attributes` FROM `Component`";
-
-LPCWSTR vcsMimeMapQuery = L"SELECT `MimeMap`, `ParentType`, `ParentValue`, `MimeType`, `Extension` FROM `IIsMimeMap`";
-
-LPCWSTR vcsHttpHeaderQuery = L"SELECT `Name`, `ParentType`, `ParentValue`, `Value`, `Attributes` FROM `IIsHttpHeader` ORDER BY `Sequence`";
-
-LPCWSTR vcsWebErrorQuery =
-    L"SELECT `ErrorCode`, `SubCode`, `ParentType`, `ParentValue`, `File`, `URL` "
-    L"FROM `IIsWebError` ORDER BY `ErrorCode`, `SubCode`";
-
-LPCWSTR vcsWebDirPropertiesQuery = L"SELECT `DirProperties`, `Access`, `Authorization`, `AnonymousUser_`, `IIsControlledPassword`, `LogVisits`, `Index`, `DefaultDoc`, `AspDetailedError`, `HttpExpires`, `CacheControlMaxAge`, `CacheControlCustom`, `NoCustomError`, `AccessSSLFlags`, `AuthenticationProviders` "
-    L"FROM `IIsWebDirProperties`";
-
-LPCWSTR vcsSslCertificateQuery = L"SELECT `Certificate`.`StoreName`, `CertificateHash`.`Hash`, `IIsWebSiteCertificates`.`Web_` FROM `Certificate`, `CertificateHash`, `IIsWebSiteCertificates` WHERE `Certificate`.`Certificate`=`CertificateHash`.`Certificate_` AND `CertificateHash`.`Certificate_`=`IIsWebSiteCertificates`.`Certificate_`";
-
-LPCWSTR vcsWebLogQuery = L"SELECT `Log`, `Format` "
-    L"FROM `IIsWebLog`";
-
-LPCWSTR vcsWebApplicationQuery = L"SELECT `Name`, `Isolation`, `AllowSessions`, `SessionTimeout`, "
-    L"`Buffer`, `ParentPaths`, `DefaultScript`, `ScriptTimeout`, "
-    L"`ServerDebugging`, `ClientDebugging`, `AppPool_`, `Application` "
-    L"FROM `IIsWebApplication`";
-
-LPCWSTR vcsWebAppExtensionQuery = L"SELECT `Extension`, `Verbs`, `Executable`, `Attributes`, `Application_` FROM `IIsWebApplicationExtension`";
-
-LPCWSTR vcsWebQuery = L"SELECT `Web`, `Component_`, `Id`, `Description`, `ConnectionTimeout`, `Directory_`, `State`, `Attributes`, `DirProperties_`, `Application_`, "
-    L"`Address`, `IP`, `Port`, `Header`, `Secure`, `Log_` FROM `IIsWebSite`, `IIsWebAddress` "
-    L"WHERE `KeyAddress_`=`Address` ORDER BY `Sequence`";
-
-LPCWSTR vcsWebAddressQuery = L"SELECT `Address`, `Web_`, `IP`, `Port`, `Header`, `Secure` "
-    L"FROM `IIsWebAddress`";
-
-LPCWSTR vcsWebBaseQuery = L"SELECT `Web`, `Id`, `IP`, `Port`, `Header`, `Secure`, `Description` "
-    L"FROM `IIsWebSite`, `IIsWebAddress` "
-    L"WHERE `KeyAddress_`=`Address`";
-
-LPCWSTR vcsWebDirQuery = L"SELECT `Web_`, `WebDir`, `Component_`, `Path`, `DirProperties_`, `Application_` "
-    L"FROM `IIsWebDir`";
-
-LPCWSTR vcsVDirQuery = L"SELECT `Web_`, `VirtualDir`, `Component_`, `Alias`, `Directory_`, `DirProperties_`, `Application_` "
-    L"FROM `IIsWebVirtualDir`";
-
-LPCWSTR vcsFilterQuery = L"SELECT `Web_`, `Name`, `Component_`, `Path`, `Description`, `Flags`, `LoadOrder` FROM `IIsFilter` ORDER BY `Web_`";
-
-LPCWSTR vcsPropertyQuery = L"SELECT `Property`, `Component_`, `Attributes`, `Value` "
-    L"FROM `IIsProperty`";
-
-#define IIS7CONDITION L"VersionNT >= 600"
-#define USEIIS7CONDITION IIS7CONDITION L"AND NOT UseIis6Compatibility"
-
-/********************************************************************
-ConfigureIIs - CUSTOM ACTION ENTRY POINT for installing IIs settings
-
-********************************************************************/
-extern "C" UINT __stdcall ConfigureIIs(
-    __in MSIHANDLE hInstall
-    )
-{
-    //AssertSz(FALSE, "debug ConfigureIIs here");
-    HRESULT hr = S_OK;
-    UINT er = ERROR_SUCCESS;
-    LPWSTR pwzScriptKey = NULL;
-    LPWSTR pwzBackupId = NULL;
-    LPWSTR pwzCustomActionData = NULL; // CustomActionData for ConfigureIIs custom action
-
-    // initialize
-    hr = WcaInitialize(hInstall, "ConfigureIIs");
-    ExitOnFailure(hr, "Failed to initialize");
-
-    // check for the prerequsite tables
-    if (S_OK != WcaTableExists(L"IIsWebSite") && S_OK != WcaTableExists(L"IIsFilter") && S_OK != WcaTableExists(L"IIsProperty") && 
-        S_OK != WcaTableExists(L"IIsWebServiceExtension") && S_OK != WcaTableExists(L"IIsAppPool"))
-    {
-        WcaLog(LOGMSG_VERBOSE, "skipping IIs CustomAction, no IIsWebSite table, no IIsFilter table, no IIsProperty table, no IIsWebServiceExtension, and no IIsAppPool table");
-        ExitFunction1(hr = S_FALSE);
-    }
-
-    // Get a CaScript key
-    hr = WcaCaScriptCreateKey(&pwzScriptKey);
-    ExitOnFailure(hr, "Failed to get encoding key.");
-
-    // Generate a unique string to be used for this product's transaction
-    // This prevents a name collision when doing a major upgrade
-    hr = WcaGetProperty(L"ProductCode", &pwzBackupId);
-    ExitOnFailure(hr, "failed to get ProductCode");
-
-    hr = StrAllocConcat(&pwzBackupId, L"ScaConfigureIIs", 0);
-    ExitOnFailure(hr, "failed to concat ScaConfigureIIs");
-
-    // make sure the operations below are wrapped in a "transaction"
-    // use IIS7 transaction logic even if using Iis6 compat because Backup/Restore don't work with metabase compatibility
-    if (MSICONDITION_TRUE == ::MsiEvaluateConditionW(hInstall, IIS7CONDITION))
-    {
-        hr = ScaIIS7ConfigTransaction(pwzBackupId);
-        MessageExitOnFailure(hr, msierrIISFailedSchedTransaction, "failed to start IIS7 transaction");
-    }
-    else
-    {
-        hr = ScaMetabaseTransaction(pwzBackupId);
-        MessageExitOnFailure(hr, msierrIISFailedSchedTransaction, "failed to start IIS transaction");
-    }
-
-    // Write the CaScript key to the ConfigureIIS custom action data
-    hr = WcaWriteStringToCaData(pwzScriptKey, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to add encoding key to CustomActionData.");
-
-    // Wrap vcsUserDeferredQuery to send to deferred CA
-    if (S_OK == WcaTableExists(L"User"))
-    {
-        hr = WcaWrapQuery(vcsUserDeferredQuery, &pwzCustomActionData, efmcColumn3 | efmcColumn4 | efmcColumn5, 0xFFFFFFFF, 0xFFFFFFFF);
-        ExitOnFailure(hr, "Failed to wrap User query");
-    }
-    else
-    {
-        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to wrap User empty query");
-    }
-
-    // Wrap vcsWebSvcExtQuery to send to deferred CA
-    if (S_OK == WcaTableExists(L"IIsWebServiceExtension"))
-    {
-        hr = WcaWrapQuery(vcsWebSvcExtQuery, &pwzCustomActionData, efmcColumn2 | efmcColumn3 | efmcColumn4, 1, 0xFFFFFFFF);
-        ExitOnFailure(hr, "Failed to wrap IIsWebServiceExtension query");
-    }
-    else
-    {
-        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to wrap IIsWebServiceExtension empty query");
-    }
-
-    // Wrap vcsAppPoolQuery to send to deferred CA
-    if (S_OK == WcaTableExists(L"IIsAppPool"))
-    {
-        hr = WcaWrapQuery(vcsAppPoolQuery, &pwzCustomActionData, efmcColumn2 | efmcColumn15 | efmcColumn16, 3, 0xFFFFFFFF);
-        ExitOnFailure(hr, "Failed to wrap IIsAppPool query");
-
-        hr = WcaWrapQuery(vcsComponentAttrQuery, &pwzCustomActionData, 0, 0xFFFFFFFF, 0xFFFFFFFF);
-        ExitOnFailure(hr, "Failed to wrap Component query");
-    }
-    else
-    {
-        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to wrap IIsAppPool empty query");
-    }
-
-    // Wrap vcsMimeMapQuery to send to deferred CA
-    if (S_OK == WcaTableExists(L"IIsMimeMap"))
-    {
-        hr = WcaWrapQuery(vcsMimeMapQuery, &pwzCustomActionData, efmcColumn4 | efmcColumn5, 0xFFFFFFFF, 0xFFFFFFFF);
-        ExitOnFailure(hr, "Failed to wrap IIsMimeMap query");
-    }
-    else
-    {
-        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to wrap IIsMimeMap empty query");
-    }
-
-    // Wrap vcsHttpHeaderQuery to send to deferred CA
-    if (S_OK == WcaTableExists(L"IIsHttpHeader"))
-    {
-        hr = WcaWrapQuery(vcsHttpHeaderQuery, &pwzCustomActionData, efmcColumn1 | efmcColumn4, 0xFFFFFFFF, 0xFFFFFFFF);
-        ExitOnFailure(hr, "Failed to wrap IIsHttpHeader query");
-    }
-    else
-    {
-        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to wrap IIsHttpHeader empty query");
-    }
-
-    // Wrap vcsWebErrorQuery to send to deferred CA
-    if (S_OK == WcaTableExists(L"IIsWebError"))
-    {
-        hr = WcaWrapQuery(vcsWebErrorQuery, &pwzCustomActionData, efmcColumn5 | efmcColumn6, 0xFFFFFFFF, 0xFFFFFFFF);
-        ExitOnFailure(hr, "Failed to wrap IIsWebError query");
-    }
-    else
-    {
-        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to wrap IIsWebError empty query");
-    }
-
-    // Wrap vcsWebDirPropertiesQuery to send to deferred CA
-    if (S_OK == WcaTableExists(L"IIsWebDirProperties"))
-    {
-        hr = WcaWrapQuery(vcsWebDirPropertiesQuery, &pwzCustomActionData, efmcColumn8 | efmcColumn10 | efmcColumn12 | efmcColumn15, 0xFFFFFFFF, 0xFFFFFFFF);
-        ExitOnFailure(hr, "Failed to wrap IIsWebDirProperties query");
-    }
-    else
-    {
-        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to wrap IIsWebDirProperties empty query");
-    }
-
-    // Wrap vcsSslCertificateQuery to send to deferred CA
-    if (S_OK == WcaTableExists(L"Certificate") && S_OK == WcaTableExists(L"CertificateHash") && S_OK == WcaTableExists(L"IIsWebSiteCertificates"))
-    {
-        hr = WcaWrapQuery(vcsSslCertificateQuery, &pwzCustomActionData, 0, 0xFFFFFFFF, 0xFFFFFFFF);
-        ExitOnFailure(hr, "Failed to wrap SslCertificate query");
-    }
-    else
-    {
-        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to wrap SslCertificate empty query");
-    }
-
-    // Wrap vcsWebLogQuery to send to deferred CA
-    if (S_OK == WcaTableExists(L"IIsWebLog"))
-    {
-        hr = WcaWrapQuery(vcsWebLogQuery, &pwzCustomActionData, efmcColumn2, 0xFFFFFFFF, 0xFFFFFFFF);
-        ExitOnFailure(hr, "Failed to wrap IIsWebLog query");
-    }
-    else
-    {
-        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to wrap IIsWebLog empty query");
-    }
-
-    // Wrap vcsWebApplicationQuery to send to deferred CA
-    if (S_OK == WcaTableExists(L"IIsWebApplication"))
-    {
-        hr = WcaWrapQuery(vcsWebApplicationQuery, &pwzCustomActionData, efmcColumn1, 0xFFFFFFFF, 0xFFFFFFFF);
-        ExitOnFailure(hr, "Failed to wrap IIsWebApplication query");
-    }
-    else
-    {
-        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to wrap IIsWebApplication empty query");
-    }
-
-    // Wrap vcsWebAppExtensionQuery to send to deferred CA
-    if (S_OK == WcaTableExists(L"IIsWebApplicationExtension"))
-    {
-        hr = WcaWrapQuery(vcsWebAppExtensionQuery, &pwzCustomActionData, efmcColumn2 | efmcColumn3, 0xFFFFFFFF, 0xFFFFFFFF);
-        ExitOnFailure(hr, "Failed to wrap IIsWebApplicationExtension query");
-    }
-    else
-    {
-        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to wrap IIsWebApplicationExtension empty query");
-    }
-
-    // Wrap vcsWebQuery, vcsWebAddressQuery, and vcsWebBaseQuery to send to deferred CA
-    if (S_OK == WcaTableExists(L"IIsWebAddress") && S_OK == WcaTableExists(L"IIsWebSite"))
-    {
-        hr = WcaWrapQuery(vcsWebQuery, &pwzCustomActionData, efmcColumn3 | efmcColumn4 | efmcColumn12 | efmcColumn13 | efmcColumn14, 2, 6);
-        ExitOnFailure(hr, "Failed to wrap IIsWebSite query");
-
-        hr = WcaWrapQuery(vcsWebAddressQuery, &pwzCustomActionData, efmcColumn3 | efmcColumn4 | efmcColumn5, 0xFFFFFFFF, 0xFFFFFFFF);
-        ExitOnFailure(hr, "Failed to wrap IIsWebAddress query");
-
-        hr = WcaWrapQuery(vcsWebBaseQuery, &pwzCustomActionData, efmcColumn2 | efmcColumn3 | efmcColumn4 | efmcColumn5 | efmcColumn7, 0xFFFFFFFF, 0xFFFFFFFF);
-        ExitOnFailure(hr, "Failed to wrap IIsWebBase query");
-    }
-    else
-    {
-        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to wrap IIsWebSite empty query");
-
-        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to wrap IIsWebAddress empty query");
-
-        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to wrap IIsWebBase empty query");
-    }
-
-    // Wrap vcsWebDirQuery to send to deferred CA
-    if (S_OK == WcaTableExists(L"IIsWebDir"))
-    {
-        hr = WcaWrapQuery(vcsWebDirQuery, &pwzCustomActionData, efmcColumn4, 3, 0xFFFFFFFF);
-        ExitOnFailure(hr, "Failed to wrap IIsWebDir query");
-    }
-    else
-    {
-        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to wrap IIsWebDir empty query");
-    }
-
-    // Wrap vcsVDirQuery to send to deferred CA
-    if (S_OK == WcaTableExists(L"IIsWebVirtualDir"))
-    {
-        hr = WcaWrapQuery(vcsVDirQuery, &pwzCustomActionData, efmcColumn4, 3, 5);
-        ExitOnFailure(hr, "Failed to wrap IIsWebVirtualDir query");
-    }
-    else
-    {
-        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to wrap IIsWebVirtualDir empty query");
-    }
-
-    // Wrap vcsFilterQuery to send to deferred CA
-    if (S_OK == WcaTableExists(L"IIsFilter"))
-    {
-        hr = WcaWrapQuery(vcsFilterQuery, &pwzCustomActionData, efmcColumn4 | efmcColumn5, 3, 0xFFFFFFFF);
-        ExitOnFailure(hr, "Failed to wrap IIsFilter query");
-    }
-    else
-    {
-        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to wrap IIsFilter empty query");
-    }
-
-    // Wrap vcsPropertyQuery to send to deferred CA
-    if (S_OK == WcaTableExists(L"IIsProperty"))
-    {
-        hr = WcaWrapQuery(vcsPropertyQuery, &pwzCustomActionData, efmcColumn4, 2, 0xFFFFFFFF);
-        ExitOnFailure(hr, "Failed to wrap IIsProperty query");
-    }
-    else
-    {
-        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to wrap IIsProperty empty query");
-    }
-
-    if (MSICONDITION_TRUE == ::MsiEvaluateConditionW(hInstall, USEIIS7CONDITION))
-    {
-        // This must remain trace only, CA data may contain password
-        WcaLog(LOGMSG_TRACEONLY, "Custom Action Data for ConfigureIIS7Exec will be: %ls", pwzCustomActionData);
-
-        hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ConfigureIIs7Exec"), pwzCustomActionData, ConfigureIIsCost);
-        ExitOnFailure(hr, "Failed to schedule ConfigureIIs7Exec custom action");
-
-        ReleaseNullStr(pwzCustomActionData);
-
-        // Write the CaScript key to the ConfigureIIS custom action data
-        hr = WcaWriteStringToCaData(pwzScriptKey, &pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to add script key to CustomActionData.");
-
-        hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"WriteIIS7ConfigChanges"), pwzCustomActionData, WriteIIS7ConfigChangesCost);
-        ExitOnFailure(hr, "Failed to schedule WriteMetabaseChanges custom action");
-    }
-    else
-    {
-        // This must remain trace only, CA data may contain password
-        WcaLog(LOGMSG_TRACEONLY, "Custom Action Data for ConfigureIISExec will be: %ls", pwzCustomActionData);
-
-        hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ConfigureIIsExec"), pwzCustomActionData, ConfigureIIsCost);
-        ExitOnFailure(hr, "Failed to schedule ConfigureIISExec custom action");
-
-        ReleaseNullStr(pwzCustomActionData);
-
-        // Write the CaScript key to the ConfigureIIS custom action data
-        hr = WcaWriteStringToCaData(pwzScriptKey, &pwzCustomActionData);
-        ExitOnFailure(hr, "Failed to add script key to CustomActionData.");
-
-        hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"WriteMetabaseChanges"), pwzCustomActionData, WriteMetabaseChangesCost);
-        ExitOnFailure(hr, "Failed to schedule WriteMetabaseChanges custom action");
-    }
-
-LExit:
-    ReleaseStr(pwzScriptKey);
-    ReleaseStr(pwzBackupId);
-    ReleaseStr(pwzCustomActionData);
-
-    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
-    return WcaFinalize(er);
-}
-
-/********************************************************************
-ConfigureIIsExec - custom action for installing IIs settings - table
-data will be wrapped and passed in from immediate CA
-ReadIIsTables
-
-********************************************************************/
-extern "C" UINT __stdcall ConfigureIIsExec(
-    __in MSIHANDLE hInstall
-    )
-{
-    //AssertSz(FALSE, "debug ConfigureIIsExec here");
-    HRESULT hr = S_OK;
-    UINT er = ERROR_SUCCESS;
-
-    BOOL fInitializedCom = FALSE;
-    IMSAdminBase* piMetabase = NULL;
-
-    SCA_WEB* pswList = NULL;
-    SCA_WEBDIR* pswdList = NULL;
-    SCA_VDIR* psvdList = NULL;
-    SCA_FILTER* psfList = NULL;
-    SCA_APPPOOL *psapList = NULL;
-    SCA_MIMEMAP* psmmList = NULL;
-    SCA_HTTP_HEADER* pshhList = NULL;
-    SCA_PROPERTY *pspList = NULL;
-    SCA_WEBSVCEXT* psWseList = NULL;
-    SCA_WEB_ERROR* psweList = NULL;
-
-    LPWSTR pwzScriptKey = NULL;
-    LPWSTR pwzCustomActionData = NULL;
-
-    WCA_WRAPQUERY_HANDLE hUserQuery = NULL;
-    WCA_WRAPQUERY_HANDLE hWebBaseQuery = NULL;
-    WCA_WRAPQUERY_HANDLE hWebDirPropQuery = NULL;
-    WCA_WRAPQUERY_HANDLE hSslCertQuery = NULL;
-    WCA_WRAPQUERY_HANDLE hWebLogQuery = NULL;
-    WCA_WRAPQUERY_HANDLE hWebAppQuery = NULL;
-    WCA_WRAPQUERY_HANDLE hWebAppExtQuery = NULL;
-
-    // initialize
-    hr = WcaInitialize(hInstall, "ConfigureIIsExec");
-    ExitOnFailure(hr, "Failed to initialize");
-
-    hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
-    ExitOnFailure(hr, "failed to get CustomActionData");
-
-    // Get the CaScript key
-    hr = WcaReadStringFromCaData(&pwzCustomActionData, &pwzScriptKey);
-    ExitOnFailure(hr, "Failed to get CaScript key from custom action data");
-
-    hr = ::CoInitialize(NULL);
-    ExitOnFailure(hr, "failed to initialize COM");
-    fInitializedCom = TRUE;
-
-    // if IIS was uninstalled (thus no IID_IMSAdminBase) allow the
-    // user to still uninstall this package by clicking "Ignore"
-    do
-    {
-        hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, (void**)&piMetabase);
-        if (FAILED(hr))
-        {
-            WcaLog(LOGMSG_STANDARD, "failed to get IID_IMSAdminBase Object");
-            er = WcaErrorMessage(msierrIISCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
-            switch (er)
-            {
-            case IDABORT:
-                ExitFunction();   // bail with the error result from the CoCreate to kick off a rollback
-            case IDRETRY:
-                hr = S_FALSE;   // hit me, baby, one more time
-                break;
-            case IDIGNORE:
-                __fallthrough;
-            default:
-                WcaLog(LOGMSG_STANDARD, "ignoring absent IIS");
-                // We need to write the empty script to communicate to other deferred CA that there is noting to do.
-                hr = ScaWriteConfigurationScript(pwzScriptKey);
-                ExitOnFailure(hr, "failed to schedule metabase configuration");
-
-                ExitFunction1(hr = S_OK);  // pretend everything is okay
-                break;
-            }
-        }
-    } while (S_FALSE == hr);
-
-    // read the msi tables
-    hr = WcaBeginUnwrapQuery(&hUserQuery, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap user query");
-
-    hr = ScaWebSvcExtRead(&psWseList, &pwzCustomActionData);
-    MessageExitOnFailure(hr, msierrIISFailedReadWebSvcExt, "failed while processing WebServiceExtensions");
-
-    hr = ScaAppPoolRead(&psapList, hUserQuery, &pwzCustomActionData);
-    MessageExitOnFailure(hr, msierrIISFailedReadAppPool, "failed while processing WebAppPools");
-
-    // MimeMap, Error and HttpHeader need to be read before the virtual directory and web read
-    hr = ScaMimeMapRead(&psmmList, &pwzCustomActionData);
-    MessageExitOnFailure(hr, msierrIISFailedReadMimeMap, "failed while processing MimeMaps");
-
-    hr = ScaHttpHeaderRead(&pshhList, &pwzCustomActionData);
-    MessageExitOnFailure(hr, msierrIISFailedReadHttpHeader, "failed while processing HttpHeaders");
-
-    hr = ScaWebErrorRead(&psweList, &pwzCustomActionData);
-    MessageExitOnFailure(hr, msierrIISFailedReadWebError, "failed while processing WebErrors");
-
-    hr = WcaBeginUnwrapQuery(&hWebDirPropQuery, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap web dir properties query");
-
-    hr = WcaBeginUnwrapQuery(&hSslCertQuery, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap ssl certificate query");
-
-    hr = WcaBeginUnwrapQuery(&hWebLogQuery, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap web log query");
-
-    hr = WcaBeginUnwrapQuery(&hWebAppQuery, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap web application query");
-
-    hr = WcaBeginUnwrapQuery(&hWebAppExtQuery, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap web application extension query");
-
-    hr = ScaWebsRead(piMetabase, &psmmList, &pswList, &pshhList, &psweList, hUserQuery, hWebDirPropQuery, hSslCertQuery, hWebLogQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData);
-    MessageExitOnFailure(hr, msierrIISFailedReadWebSite, "failed while processing WebSites");
-
-    hr = WcaBeginUnwrapQuery(&hWebBaseQuery, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap web base query");
-
-    hr = ScaWebDirsRead(piMetabase, pswList, hUserQuery, hWebBaseQuery, hWebDirPropQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData, &pswdList);
-    MessageExitOnFailure(hr, msierrIISFailedReadWebDirs, "failed while processing WebDirs");
-
-    hr = ScaVirtualDirsRead(piMetabase, pswList, &psvdList, &psmmList, &pshhList, &psweList, hUserQuery, hWebBaseQuery, hWebDirPropQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData);
-    MessageExitOnFailure(hr, msierrIISFailedReadVDirs, "failed while processing WebVirtualDirs");
-
-    hr = ScaFiltersRead(piMetabase, pswList, hWebBaseQuery, &psfList, &pwzCustomActionData);
-    MessageExitOnFailure(hr, msierrIISFailedReadFilters, "failed while processing WebFilters");
-
-    hr = ScaPropertyRead(&pspList, &pwzCustomActionData);
-    MessageExitOnFailure(hr, msierrIISFailedReadProp, "failed while processing WebProperties");
-
-    // do uninstall actions (order is important!)
-    hr = ScaPropertyUninstall(piMetabase, pspList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallProp, "failed to uninstall IIS properties");
-
-    hr = ScaFiltersUninstall(piMetabase, psfList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallFilters, "failed to schedule uninstall of filters");
-
-    hr = ScaVirtualDirsUninstall(piMetabase, psvdList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallVDirs, "failed to schedule uninstall of virtual directories");
-
-    hr = ScaWebDirsUninstall(piMetabase, pswdList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallWebDirs, "failed to schedule uninstall of web directories");
-
-    hr = ScaWebsUninstall(piMetabase, pswList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallWebs, "failed to schedule uninstall of webs");
-
-    hr = ScaAppPoolUninstall(piMetabase, psapList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallAppPool, "failed to schedule uninstall of AppPools");
-
-
-    // do install actions (order is important!)
-    // ScaWebSvcExtCommit contains both uninstall and install actions.
-    hr = ScaWebSvcExtCommit(piMetabase, psWseList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebSvcExt, "failed to schedule install/uninstall of WebSvcExt");
-
-    hr = ScaAppPoolInstall(piMetabase, psapList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedInstallAppPool, "failed to schedule install of AppPools");
-
-    hr = ScaWebsInstall(piMetabase, pswList, psapList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebs, "failed to schedule install of webs");
-
-    hr = ScaWebDirsInstall(piMetabase, pswdList, psapList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebDirs, "failed to schedule install of web directories");
-
-    hr = ScaVirtualDirsInstall(piMetabase, psvdList, psapList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedInstallVDirs, "failed to schedule install of virtual directories");
-
-    hr = ScaFiltersInstall(piMetabase, psfList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedInstallFilters, "failed to schedule install of filters");
-
-    hr = ScaPropertyInstall(piMetabase, pspList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedInstallProp, "failed to schedule install of properties");
-
-    hr = ScaWriteConfigurationScript(pwzScriptKey);
-    ExitOnFailure(hr, "failed to schedule metabase configuration");
-
-LExit:
-    ReleaseStr(pwzScriptKey);
-    ReleaseStr(pwzCustomActionData);
-
-    WcaFinishUnwrapQuery(hUserQuery);
-    WcaFinishUnwrapQuery(hWebBaseQuery);
-    WcaFinishUnwrapQuery(hWebDirPropQuery);
-    WcaFinishUnwrapQuery(hSslCertQuery);
-    WcaFinishUnwrapQuery(hWebLogQuery);
-    WcaFinishUnwrapQuery(hWebAppQuery);
-    WcaFinishUnwrapQuery(hWebAppExtQuery);
-
-    if (psWseList)
-    {
-        ScaWebSvcExtFreeList(psWseList);
-    }
-
-    if (psfList)
-    {
-        ScaFiltersFreeList(psfList);
-    }
-
-    if (psvdList)
-    {
-        ScaVirtualDirsFreeList(psvdList);
-    }
-
-    if (pswdList)
-    {
-        ScaWebDirsFreeList(pswdList);
-    }
-
-    if (pswList)
-    {
-        ScaWebsFreeList(pswList);
-    }
-
-    if (psmmList)
-    {
-        ScaMimeMapCheckList(psmmList);
-        ScaMimeMapFreeList(psmmList);
-    }
-
-    if (pshhList)
-    {
-        ScaHttpHeaderCheckList(pshhList);
-        ScaHttpHeaderFreeList(pshhList);
-    }
-
-    if (psweList)
-    {
-        ScaWebErrorCheckList(psweList);
-        ScaWebErrorFreeList(psweList);
-    }
-
-    ReleaseObject(piMetabase);
-
-    if (fInitializedCom)
-    {
-        ::CoUninitialize();
-    }
-
-    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
-    return WcaFinalize(er);
-}
-
-
-/********************************************************************
-ConfigureIIs - CUSTOM ACTION ENTRY POINT for installing IIs settings
-
-********************************************************************/
-extern "C" UINT __stdcall ConfigureIIs7Exec(
-    __in MSIHANDLE hInstall
-    )
-{
-    //AssertSz(FALSE, "debug ConfigureIIs7Exec here");
-    HRESULT hr = S_OK;
-    UINT er = ERROR_SUCCESS;
-
-    LPWSTR pwzScriptKey = NULL;
-    LPWSTR pwzCustomActionData = NULL;
-
-    SCA_WEB7* pswList = NULL;
-    SCA_WEBDIR7* pswdList = NULL;
-    SCA_VDIR7* psvdList = NULL;
-    SCA_FILTER* psfList = NULL;
-    SCA_APPPOOL *psapList = NULL;
-    SCA_MIMEMAP* psmmList = NULL;
-    SCA_HTTP_HEADER* pshhList = NULL;
-    SCA_PROPERTY *pspList = NULL;
-    SCA_WEBSVCEXT* psWseList = NULL;
-    SCA_WEB_ERROR* psweList = NULL;
-
-    WCA_WRAPQUERY_HANDLE hUserQuery = NULL;
-    WCA_WRAPQUERY_HANDLE hWebBaseQuery = NULL;
-    WCA_WRAPQUERY_HANDLE hWebDirPropQuery = NULL;
-    WCA_WRAPQUERY_HANDLE hSslCertQuery = NULL;
-    WCA_WRAPQUERY_HANDLE hWebLogQuery = NULL;
-    WCA_WRAPQUERY_HANDLE hWebAppQuery = NULL;
-    WCA_WRAPQUERY_HANDLE hWebAppExtQuery = NULL;
-
-    // initialize
-    hr = WcaInitialize(hInstall, "ConfigureIIs7Exec");
-    ExitOnFailure(hr, "Failed to initialize");
-
-    hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
-    ExitOnFailure(hr, "failed to get CustomActionData");
-
-    // Get the CaScript key
-    hr = WcaReadStringFromCaData(&pwzCustomActionData, &pwzScriptKey);
-    ExitOnFailure(hr, "Failed to get CaScript key from custom action data");
-
-    // read the msi tables
-    hr = WcaBeginUnwrapQuery(&hUserQuery, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap user query");
-
-    hr = ScaWebSvcExtRead(&psWseList, &pwzCustomActionData);
-    MessageExitOnFailure(hr, msierrIISFailedReadWebSvcExt, "failed while processing WebServiceExtensions");
-
-    hr = ScaAppPoolRead(&psapList, hUserQuery, &pwzCustomActionData);
-    MessageExitOnFailure(hr, msierrIISFailedReadAppPool, "failed while processing WebAppPools");
-
-    // MimeMap, Error and HttpHeader need to be read before the virtual directory and web read
-    hr = ScaMimeMapRead(&psmmList, &pwzCustomActionData);
-    MessageExitOnFailure(hr, msierrIISFailedReadMimeMap, "failed while processing MimeMaps");
-
-    hr = ScaHttpHeaderRead(&pshhList, &pwzCustomActionData);
-    MessageExitOnFailure(hr, msierrIISFailedReadHttpHeader, "failed while processing HttpHeaders");
-
-    hr = ScaWebErrorRead(&psweList, &pwzCustomActionData);
-    MessageExitOnFailure(hr, msierrIISFailedReadWebError, "failed while processing WebErrors");
-
-    hr = WcaBeginUnwrapQuery(&hWebDirPropQuery, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap web dir properties query");
-
-    hr = WcaBeginUnwrapQuery(&hSslCertQuery, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap ssl certificate query");
-
-    hr = WcaBeginUnwrapQuery(&hWebLogQuery, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap web log query");
-
-    hr = WcaBeginUnwrapQuery(&hWebAppQuery, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap web application query");
-
-    hr = WcaBeginUnwrapQuery(&hWebAppExtQuery, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap web application extension query");
-
-    hr = ScaWebsRead7(&pswList, &pshhList, &psweList, hUserQuery, hWebDirPropQuery, hSslCertQuery, hWebLogQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData);
-    MessageExitOnFailure(hr, msierrIISFailedReadWebSite, "failed while processing WebSites");
-
-    hr = WcaBeginUnwrapQuery(&hWebBaseQuery, &pwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap web base query");
-
-    hr = ScaWebDirsRead7(pswList, hUserQuery, hWebBaseQuery, hWebDirPropQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData, &pswdList);
-    MessageExitOnFailure(hr, msierrIISFailedReadWebDirs, "failed while processing WebDirs");
-
-    hr = ScaVirtualDirsRead7(pswList, &psvdList, &psmmList, &pshhList, &psweList, hUserQuery, hWebBaseQuery, hWebDirPropQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData);
-    MessageExitOnFailure(hr, msierrIISFailedReadVDirs, "failed while processing WebVirtualDirs");
-
-    hr = ScaFiltersRead7(pswList, hWebBaseQuery, &psfList, &pwzCustomActionData);
-    MessageExitOnFailure(hr, msierrIISFailedReadFilters, "failed while processing WebFilters");
-
-    hr = ScaPropertyRead(&pspList, &pwzCustomActionData);
-    MessageExitOnFailure(hr, msierrIISFailedReadProp, "failed while processing WebProperties");
-
-    // do uninstall actions (order is important!)
-    hr = ScaPropertyUninstall7(pspList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallProp, "failed to uninstall IIS properties");
-
-    hr = ScaFiltersUninstall7(psfList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallFilters, "failed to schedule uninstall of filters");
-
-    hr = ScaVirtualDirsUninstall7(psvdList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallVDirs, "failed to schedule uninstall of virtual directories");
-
-    hr = ScaWebDirsUninstall7(pswdList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallWebDirs, "failed to schedule uninstall of web directories");
-
-    hr = ScaWebsUninstall7(pswList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallWebs, "failed to schedule uninstall of webs");
-
-    hr = ScaAppPoolUninstall7(psapList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallAppPool, "failed to schedule uninstall of AppPools");
-
-
-    // do install actions (order is important!)
-    // ScaWebSvcExtCommit contains both uninstall and install actions.
-    hr = ScaWebSvcExtCommit7(psWseList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebSvcExt, "failed to schedule install/uninstall of WebSvcExt");
-
-    hr = ScaAppPoolInstall7(psapList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedInstallAppPool, "failed to schedule install of AppPools");
-
-    hr = ScaWebsInstall7(pswList, psapList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebs, "failed to schedule install of webs");
-
-    hr = ScaWebDirsInstall7(pswdList, psapList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebDirs, "failed to schedule install of web directories");
-
-    hr = ScaVirtualDirsInstall7(psvdList, psapList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedInstallVDirs, "failed to schedule install of virtual directories");
-
-    hr = ScaFiltersInstall7(psfList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedInstallFilters, "failed to schedule install of filters");
-
-    hr = ScaPropertyInstall7(pspList);
-    MessageExitOnFailure(hr, msierrIISFailedSchedInstallProp, "failed to schedule install of properties");
-
-    hr = ScaWriteConfigurationScript(pwzScriptKey);
-    ExitOnFailure(hr, "failed to schedule metabase configuration");
-
-LExit:
-    ReleaseNullStr(pwzScriptKey);
-    ReleaseNullStr(pwzCustomActionData);
-
-    WcaFinishUnwrapQuery(hUserQuery);
-    WcaFinishUnwrapQuery(hWebBaseQuery);
-    WcaFinishUnwrapQuery(hWebDirPropQuery);
-    WcaFinishUnwrapQuery(hSslCertQuery);
-    WcaFinishUnwrapQuery(hWebLogQuery);
-    WcaFinishUnwrapQuery(hWebAppQuery);
-    WcaFinishUnwrapQuery(hWebAppExtQuery);
-
-    if (psWseList)
-    {
-        ScaWebSvcExtFreeList(psWseList);
-    }
-
-    if (psfList)
-    {
-        ScaFiltersFreeList(psfList);
-    }
-
-    if (psvdList)
-    {
-        ScaVirtualDirsFreeList7(psvdList);
-    }
-
-    if (pswdList)
-    {
-        ScaWebDirsFreeList7(pswdList);
-    }
-
-    if (pswList)
-    {
-        ScaWebsFreeList7(pswList);
-    }
-
-    if (psmmList)
-    {
-        ScaMimeMapFreeList(psmmList);
-    }
-
-    if (pshhList)
-    {
-        ScaHttpHeaderCheckList(pshhList);
-        ScaHttpHeaderFreeList(pshhList);
-    }
-
-    if (psweList)
-    {
-        ScaWebErrorCheckList(psweList);
-        ScaWebErrorFreeList(psweList);
-    }
-
-    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
-    return WcaFinalize(er);
-}
diff --git a/src/ca/scassl.cpp b/src/ca/scassl.cpp
deleted file mode 100644
index 4a06b77e..00000000
--- a/src/ca/scassl.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-enum eSslCertificateQuery { scqStoreName = 1, scqHash, scqWeb };
-
-static HRESULT AddSslCertificateToList(
-    __in SCA_WEB_SSL_CERTIFICATE** ppswscList
-    );
-
-
-HRESULT ScaSslCertificateRead(
-    __in LPCWSTR wzWebId,
-    __in WCA_WRAPQUERY_HANDLE hSslCertQuery,
-    __inout SCA_WEB_SSL_CERTIFICATE** ppswscList
-    )
-{
-    HRESULT hr = S_OK;
-
-    MSIHANDLE hRec;
-    SCA_WEB_SSL_CERTIFICATE* pswsc = NULL;
-    LPWSTR pwzData = NULL;
-
-    WcaFetchWrappedReset(hSslCertQuery);
-
-    // Get the certificate information.
-    while (S_OK == (hr = WcaFetchWrappedRecordWhereString(hSslCertQuery, scqWeb, wzWebId, &hRec)))
-    {
-        hr = AddSslCertificateToList(ppswscList);
-        ExitOnFailure(hr, "failed to add ssl certificate to list");
-
-        pswsc = *ppswscList;
-
-        hr = WcaGetRecordString(hRec, scqStoreName, &pwzData);
-        ExitOnFailure(hr, "Failed to get web ssl certificate store name.");
-
-        hr = ::StringCchCopyW(pswsc->wzStoreName, countof(pswsc->wzStoreName), pwzData);
-        ExitOnFailure(hr, "Failed to copy web ssl certificate store name.");
-
-        hr = WcaGetRecordString(hRec, scqHash, &pwzData);
-        ExitOnFailure(hr, "Failed to get hash for web ssl certificate.");
-
-        hr = StrHexDecode(pwzData, pswsc->rgbSHA1Hash, countof(pswsc->rgbSHA1Hash));
-        ExitOnFailure(hr, "Failed to decode certificate hash for web: %ls, data: %ls", wzWebId, pwzData);
-    }
-
-    if (E_NOMOREITEMS == hr)
-    {
-        hr = S_OK;
-    }
-    ExitOnFailure(hr, "Failed to read IIsWebSiteCertificates table.");
-
-LExit:
-    ReleaseStr(pwzData);
-    return hr;
-}
-
-
-HRESULT ScaSslCertificateWriteMetabase(
-    __in IMSAdminBase* piMetabase,
-    __in LPCWSTR wzWebBase,
-    __in SCA_WEB_SSL_CERTIFICATE* pswscList
-    )
-{
-    HRESULT hr = S_OK;
-    BLOB blob;
-
-    for (SCA_WEB_SSL_CERTIFICATE* pswsc = pswscList; pswsc; pswsc = pswsc->pNext)
-    {
-        // Write: /W3SVC/1:SslCertStoreName = "MY", "CA", "Root", etc.
-        hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_SSL_CERT_STORE_NAME, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, static_cast<LPVOID>(pswsc->wzStoreName));
-        ExitOnFailure(hr, "Failed to write SslCertStoreName");
-
-        // Write: /W3SVC/1:SslCertHash = <blob>
-        blob.pBlobData = pswsc->rgbSHA1Hash;
-        blob.cbSize = countof(pswsc->rgbSHA1Hash);
-        hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_SSL_CERT_HASH, METADATA_INHERIT, IIS_MD_UT_SERVER, BINARY_METADATA, static_cast<LPVOID>(&blob));
-        ExitOnFailure(hr, "Failed to write SslCertHash");
-    }
-
-LExit:
-    return hr;
-}
-
-
-void ScaSslCertificateFreeList(
-    __in SCA_WEB_SSL_CERTIFICATE* pswscList
-    )
-{
-    SCA_WEB_SSL_CERTIFICATE* pswscDelete = pswscList;
-    while (pswscList)
-    {
-        pswscDelete = pswscList;
-        pswscList = pswscList->pNext;
-
-        MemFree(pswscDelete);
-    }
-}
-
-
-static HRESULT AddSslCertificateToList(
-    __in SCA_WEB_SSL_CERTIFICATE** ppswscList
-    )
-{
-    HRESULT hr = S_OK;
-
-    SCA_WEB_SSL_CERTIFICATE* pswsc = static_cast<SCA_WEB_SSL_CERTIFICATE*>(MemAlloc(sizeof(SCA_WEB_SSL_CERTIFICATE), TRUE));
-    ExitOnNull(pswsc, hr, E_OUTOFMEMORY, "failed to allocate memory for new SSL certificate list element");
-
-    pswsc->pNext = *ppswscList;
-    *ppswscList = pswsc;
-
-LExit:
-    return hr;
-}
diff --git a/src/ca/scassl.h b/src/ca/scassl.h
deleted file mode 100644
index df7c473d..00000000
--- a/src/ca/scassl.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-// 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.
-
-
-#define MD_SSL_CERT_HASH                ( IIS_MD_SSL_BASE+6 )
-#define MD_SSL_CERT_STORE_NAME          ( IIS_MD_SSL_BASE+11 )
-//#define WIDE(x)		WIDE2(x)
-//#define WIDE2(x)	L ## x
-
-
-// structs
-struct SCA_WEB_SSL_CERTIFICATE
-{
-    WCHAR wzStoreName[65];
-    BYTE rgbSHA1Hash[CB_CERTIFICATE_HASH];
-
-    SCA_WEB_SSL_CERTIFICATE* pNext;
-};
-
-
-// prototypes
-HRESULT ScaSslCertificateRead(
-    __in LPCWSTR wzWebId,
-    __in WCA_WRAPQUERY_HANDLE hSslCertQuery,
-    __inout SCA_WEB_SSL_CERTIFICATE** ppswscList
-    );
-
-HRESULT ScaSslCertificateWriteMetabase(
-    __in IMSAdminBase* piMetabase,
-    __in LPCWSTR wzWebBase,
-    __in SCA_WEB_SSL_CERTIFICATE* pswscList
-    );
-
-void ScaSslCertificateFreeList(
-    __in SCA_WEB_SSL_CERTIFICATE* pswscList
-    );
diff --git a/src/ca/scassl7.cpp b/src/ca/scassl7.cpp
deleted file mode 100644
index 47c16a9d..00000000
--- a/src/ca/scassl7.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-HRESULT ScaSslCertificateWrite7(
-    __in_z LPCWSTR wzWebBase,
-    __in SCA_WEB_SSL_CERTIFICATE* pswscList
-    )
-{
-    HRESULT hr = S_OK;
-    WCHAR wzEncodedCertificateHash[CB_CERTIFICATE_HASH * 2 + 1] = { 0 };
-
-    for (SCA_WEB_SSL_CERTIFICATE* pswsc = pswscList; pswsc; pswsc = pswsc->pNext)
-    {
-        hr = ScaWriteConfigID(IIS_SSL_BINDING);
-        ExitOnFailure(hr, "Failed write SSL binding ID");
-        hr = ScaWriteConfigID(IIS_CREATE);                      // Need to determine site action
-        ExitOnFailure(hr, "Failed write binding action");
-
-        hr = ScaWriteConfigString(wzWebBase);                   //site name key
-        ExitOnFailure(hr, "Failed to write SSL website");
-        hr = ScaWriteConfigString(pswsc->wzStoreName);          //ssl store name
-        ExitOnFailure(hr, "Failed to write SSL store name");
-
-        hr = StrHexEncode(pswsc->rgbSHA1Hash, countof(pswsc->rgbSHA1Hash), wzEncodedCertificateHash, countof(wzEncodedCertificateHash));
-        ExitOnFailure(hr, "Failed to encode SSL hash");
-
-        hr = ScaWriteConfigString(wzEncodedCertificateHash);    //ssl hash
-        ExitOnFailure(hr, "Failed to write SSL hash");
-    }
-LExit:
-
-    return hr;
-}
diff --git a/src/ca/scassl7.h b/src/ca/scassl7.h
deleted file mode 100644
index 1a4b09af..00000000
--- a/src/ca/scassl7.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#pragma once
-// 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.
-
-
-HRESULT ScaSslCertificateWrite7(
-    __in_z LPCWSTR wzWebBase,
-    __in SCA_WEB_SSL_CERTIFICATE* pswscList
-    );
diff --git a/src/ca/scauser.cpp b/src/ca/scauser.cpp
deleted file mode 100644
index 0b99edff..00000000
--- a/src/ca/scauser.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-LPCWSTR vcsUserQuery = L"SELECT `User`, `Component_`, `Name`, `Domain`, `Password` FROM `User` WHERE `User`=?";
-enum eUserQuery { vuqUser = 1, vuqComponent, vuqName, vuqDomain, vuqPassword };
-
-LPCWSTR vcsGroupQuery = L"SELECT `Group`, `Component_`, `Name`, `Domain` FROM `Group` WHERE `Group`=?";
-enum eGroupQuery { vgqGroup = 1, vgqComponent, vgqName, vgqDomain };
-
-LPCWSTR vcsUserGroupQuery = L"SELECT `User_`, `Group_` FROM `UserGroup` WHERE `User_`=?";
-enum eUserGroupQuery { vugqUser = 1, vugqGroup };
-
-LPCWSTR vActionableQuery = L"SELECT `User`,`Component_`,`Name`,`Domain`,`Password`,`Attributes` FROM `User` WHERE `Component_` IS NOT NULL";
-enum eActionableQuery { vaqUser = 1, vaqComponent, vaqName, vaqDomain, vaqPassword, vaqAttributes };
-
-HRESULT __stdcall ScaGetUserDeferred(
-    __in LPCWSTR wzUser,
-    __in WCA_WRAPQUERY_HANDLE hUserQuery,
-    __out SCA_USER* pscau
-    )
-{
-    if (!wzUser || !pscau)
-    {
-        return E_INVALIDARG;
-    }
-
-    HRESULT hr = S_OK;
-    MSIHANDLE hRec, hRecTest;
-
-    LPWSTR pwzData = NULL;
-
-    // clear struct and bail right away if no user key was passed to search for
-    ::ZeroMemory(pscau, sizeof(*pscau));
-    if (!*wzUser)
-    {
-        ExitFunction1(hr = S_OK);
-    }
-
-    // Reset back to the first record
-    WcaFetchWrappedReset(hUserQuery);
-
-    hr = WcaFetchWrappedRecordWhereString(hUserQuery, vuqUser, wzUser, &hRec);
-    if (S_OK == hr)
-    {
-        hr = WcaFetchWrappedRecordWhereString(hUserQuery, vuqUser, wzUser, &hRecTest);
-        if (S_OK == hr)
-        {
-            AssertSz(FALSE, "Found multiple matching User rows");
-        }
-
-        hr = WcaGetRecordString(hRec, vuqUser, &pwzData);
-        ExitOnFailure(hr, "Failed to get User.User");
-        hr = ::StringCchCopyW(pscau->wzKey, countof(pscau->wzKey), pwzData);
-        ExitOnFailure(hr, "Failed to copy key string to user object (in deferred CA)");
-
-        hr = WcaGetRecordString(hRec, vuqComponent, &pwzData);
-        ExitOnFailure(hr, "Failed to get User.Component_");
-        hr = ::StringCchCopyW(pscau->wzComponent, countof(pscau->wzComponent), pwzData);
-        ExitOnFailure(hr, "Failed to copy component string to user object (in deferred CA)");
-
-        hr = WcaGetRecordString(hRec, vuqName, &pwzData);
-        ExitOnFailure(hr, "Failed to get User.Name");
-        hr = ::StringCchCopyW(pscau->wzName, countof(pscau->wzName), pwzData);
-        ExitOnFailure(hr, "Failed to copy name string to user object (in deferred CA)");
-
-        hr = WcaGetRecordString(hRec, vuqDomain, &pwzData);
-        ExitOnFailure(hr, "Failed to get User.Domain");
-        hr = ::StringCchCopyW(pscau->wzDomain, countof(pscau->wzDomain), pwzData);
-        ExitOnFailure(hr, "Failed to copy domain string to user object (in deferred CA)");
-
-        hr = WcaGetRecordString(hRec, vuqPassword, &pwzData);
-        ExitOnFailure(hr, "Failed to get User.Password");
-        hr = ::StringCchCopyW(pscau->wzPassword, countof(pscau->wzPassword), pwzData);
-        ExitOnFailure(hr, "Failed to copy password string to user object (in deferred CA)");
-    }
-    else if (E_NOMOREITEMS == hr)
-    {
-        WcaLog(LOGMSG_STANDARD, "Error: Cannot locate User.User='%ls'", wzUser);
-        hr = E_FAIL;
-    }
-    else
-    {
-        ExitOnFailure(hr, "Error fetching single User row");
-    }
-
-LExit:
-    ReleaseStr(pwzData);
-
-    return hr;
-}
diff --git a/src/ca/scauser.h b/src/ca/scauser.h
deleted file mode 100644
index b2b94650..00000000
--- a/src/ca/scauser.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#pragma once
-// 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.
-
-// structs
-struct SCA_GROUP
-{
-    WCHAR wzKey[MAX_DARWIN_KEY + 1];
-    WCHAR wzComponent[MAX_DARWIN_KEY + 1];
-
-    WCHAR wzDomain[MAX_DARWIN_COLUMN + 1];
-    WCHAR wzName[MAX_DARWIN_COLUMN + 1];
-
-    SCA_GROUP *psgNext;
-};
-
-struct SCA_USER
-{
-    WCHAR wzKey[MAX_DARWIN_KEY + 1];
-    WCHAR wzComponent[MAX_DARWIN_KEY + 1];
-    INSTALLSTATE isInstalled;
-    INSTALLSTATE isAction;
-
-    WCHAR wzDomain[MAX_DARWIN_COLUMN + 1];
-    WCHAR wzName[MAX_DARWIN_COLUMN + 1];
-    WCHAR wzPassword[MAX_DARWIN_COLUMN + 1];
-    INT iAttributes;
-
-    SCA_GROUP *psgGroups;
-
-    SCA_USER *psuNext;
-};
-
-
-// prototypes
-HRESULT __stdcall ScaGetUserDeferred(
-    __in LPCWSTR wzUser, 
-    __in WCA_WRAPQUERY_HANDLE hUserQuery,
-    __out SCA_USER* pscau
-    );
diff --git a/src/ca/scavdir.cpp b/src/ca/scavdir.cpp
deleted file mode 100644
index d388ce97..00000000
--- a/src/ca/scavdir.cpp
+++ /dev/null
@@ -1,331 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-// prototypes
-static HRESULT AddVirtualDirToList(
-    __in SCA_VDIR** psvdList
-    );
-
-
-HRESULT __stdcall ScaVirtualDirsRead(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_WEB* pswList,
-    __in SCA_VDIR** ppsvdList,
-    __in SCA_MIMEMAP** ppsmmList,
-    __in SCA_HTTP_HEADER** ppshhList,
-    __in SCA_WEB_ERROR** ppsweList,
-    __in WCA_WRAPQUERY_HANDLE hUserQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebBaseQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
-    __inout LPWSTR *ppwzCustomActionData
-    )
-{
-    Assert(piMetabase && ppsvdList);
-
-    HRESULT hr = S_OK;
-    MSIHANDLE hRec;
-    INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN;
-    INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN;
-
-    SCA_VDIR* pvdir = NULL;
-    LPWSTR pwzData = NULL;
-
-    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
-
-    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead");
-
-    if (0 == WcaGetQueryRecords(hWrapQuery))
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ScaVirtualDirsRead() because IIsWebVirtualDir table not present");
-        ExitFunction1(hr = S_FALSE);
-    }
-
-    // loop through all the vdirs
-    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
-    {
-        // Get the Component first.  If there is a Component and it is not being modified during
-        // this transaction, skip processing this whole record.
-        hr = WcaGetRecordString(hRec, vdqComponent, &pwzData);
-        ExitOnFailure(hr, "failed to get IIsWebVirtualDir.Component");
-
-        hr = WcaGetRecordInteger(hRec, vdqInstalled, (int *)&isInstalled);
-        ExitOnFailure(hr, "Failed to get Component installed state for virtual dir");
-
-        hr = WcaGetRecordInteger(hRec, vdqAction, (int *)&isAction);
-        ExitOnFailure(hr, "Failed to get Component action state for virtual dir");
-
-        if (!WcaIsInstalling(isInstalled, isAction) &&
-            !WcaIsReInstalling(isInstalled, isAction) &&
-            !WcaIsUninstalling(isInstalled, isAction))
-        {
-            continue; // skip this record.
-        }
-
-        hr = AddVirtualDirToList(ppsvdList);
-        ExitOnFailure(hr, "failed to add virtual dir to list");
-
-        pvdir = *ppsvdList;
-
-        hr = ::StringCchCopyW(pvdir->wzComponent, countof(pvdir->wzComponent), pwzData);
-        ExitOnFailure(hr, "failed to copy component name: %ls", pwzData);
-
-        pvdir->isInstalled = isInstalled;
-        pvdir->isAction = isAction;
-
-        // get the web key
-        hr = WcaGetRecordString(hRec, vdqWeb, &pwzData);
-        ExitOnFailure(hr, "Failed to get Web for VirtualDir");
-
-        hr = ScaWebsGetBase(piMetabase, pswList, pwzData, pvdir->wzWebBase, countof(pvdir->wzWebBase), hWebBaseQuery);
-        if (WcaIsUninstalling(isInstalled, isAction))
-        {
-            // If we're uninstalling, ignore any failure to find the existing web
-            hr = S_OK;
-        }
-        ExitOnFailure(hr, "Failed to get base of web: %ls for VirtualDir", pwzData);
-
-        hr = WcaGetRecordString(hRec, vdqAlias, &pwzData);
-        ExitOnFailure(hr, "Failed to get Alias for VirtualDir");
-
-        if (0 != lstrlenW(pvdir->wzWebBase))
-        {
-            hr = ::StringCchPrintfW(pvdir->wzVDirRoot, countof(pvdir->wzVDirRoot), L"%s/Root/%s", pvdir->wzWebBase, pwzData);
-            ExitOnFailure(hr, "Failed to set VDirRoot for VirtualDir");
-        }
-
-        // get the vdir's directory
-        hr = WcaGetRecordString(hRec, vdqDirectory, &pwzData);
-        ExitOnFailure(hr, "Failed to get Directory for VirtualDir");
-
-        // get the web's directory
-        if (INSTALLSTATE_SOURCE == pvdir->isAction)
-        {
-            hr = WcaGetRecordString(hRec, vdqSourcePath, &pwzData);
-        }
-        else
-        {
-            hr = WcaGetRecordString(hRec, vdqTargetPath, &pwzData);
-        }
-        ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory");
-
-        // remove trailing backslash(es)
-        while (lstrlenW(pwzData) > 0 && pwzData[lstrlenW(pwzData)-1] == L'\\')
-        {
-            pwzData[lstrlenW(pwzData)-1] = 0;
-        }
-        hr = ::StringCchCopyW(pvdir->wzDirectory, countof(pvdir->wzDirectory), pwzData);
-        ExitOnFailure(hr, "Failed to copy directory string to vdir object");
-
-        // get the security information for this web
-        hr = WcaGetRecordString(hRec, vdqProperties, &pwzData);
-        ExitOnFailure(hr, "Failed to get web directory identifier for VirtualDir");
-        if (*pwzData)
-        {
-            hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &pvdir->swp);
-            ExitOnFailure(hr, "Failed to get web directory for VirtualDir");
-
-            pvdir->fHasProperties = TRUE;
-        }
-
-        // get the application information for this web
-        hr = WcaGetRecordString(hRec, vdqApplication, &pwzData);
-        ExitOnFailure(hr, "Failed to get application identifier for VirtualDir");
-        if (*pwzData)
-        {
-            hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &pvdir->swapp);
-            ExitOnFailure(hr, "Failed to get application for VirtualDir");
-
-            pvdir->fHasApplication = TRUE;
-        }
-
-        hr = WcaGetRecordString(hRec, vdqVDir, &pwzData);
-        ExitOnFailure(hr, "Failed to get VDir for VirtualDir");
-
-        if (*pwzData && *ppsmmList)
-        {
-            hr = ScaGetMimeMap(mmptVDir, pwzData, ppsmmList, &pvdir->psmm);
-            ExitOnFailure(hr, "Failed to get mimemap for VirtualDir");
-        }
-
-        if (*pwzData && *ppshhList)
-        {
-            hr = ScaGetHttpHeader(hhptVDir, pwzData, ppshhList, &pvdir->pshh);
-            ExitOnFailure(hr, "Failed to get custom HTTP headers for VirtualDir: %ls", pwzData);
-        }
-
-        if (*pwzData && *ppsweList)
-        {
-            hr = ScaGetWebError(weptVDir, pwzData, ppsweList, &pvdir->pswe);
-            ExitOnFailure(hr, "Failed to get custom web errors for VirtualDir: %ls", pwzData);
-        }
-    }
-
-    if (E_NOMOREITEMS == hr)
-    {
-        hr = S_OK;
-    }
-    ExitOnFailure(hr, "Failure while processing VirtualDirs");
-
-LExit:
-    WcaFinishUnwrapQuery(hWrapQuery);
-
-    ReleaseStr(pwzData);
-    return hr;
-}
-
-
-HRESULT ScaVirtualDirsInstall(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_VDIR* psvdList,
-    __in SCA_APPPOOL * psapList
-    )
-{
-    Assert(piMetabase);
-
-    HRESULT hr = S_OK;
-    SCA_VDIR* psvd = psvdList;
-    int i;
-
-    while (psvd)
-    {
-        // On reinstall, we have to uninstall the old application, otherwise a duplicate will be created
-        if (WcaIsReInstalling(psvd->isInstalled, psvd->isAction))
-        {
-            if (psvd->fHasApplication)
-            {
-                hr = ScaDeleteApp(piMetabase, psvd->wzVDirRoot);
-                ExitOnFailure(hr, "Failed to remove application for WebVDir as part of a reinstall");
-            }
-        }
-
-        if (WcaIsInstalling(psvd->isInstalled, psvd->isAction))
-        {
-            hr = ScaCreateMetabaseKey(piMetabase, psvd->wzVDirRoot, L"");
-            ExitOnFailure(hr, "Failed to create key for VirtualDir");
-            hr = ScaWriteMetabaseValue(piMetabase, psvd->wzVDirRoot, L"", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsWebVirtualDir");
-            ExitOnFailure(hr, "Failed to write key type for for VirtualDir");
-            i = 0x4000003e; // 1073741886;	// default directory browsing rights
-            hr = ScaWriteMetabaseValue(piMetabase, psvd->wzVDirRoot, L"", MD_DIRECTORY_BROWSING, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)i));
-            ExitOnFailure(hr, "Failed to set directory browsing for VirtualDir");
-
-            hr = ScaWriteMetabaseValue(piMetabase, psvd->wzVDirRoot, L"", MD_VR_PATH, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)psvd->wzDirectory);
-            ExitOnFailure(hr, "Failed to write Directory for VirtualDir");
-
-            if (psvd->fHasProperties)
-            {
-                ScaWriteWebDirProperties(piMetabase, psvd->wzVDirRoot, &psvd->swp);
-                ExitOnFailure(hr, "Failed to write directory properties for VirtualDir");
-            }
-
-            if (psvd->fHasApplication)
-            {
-                hr = ScaWriteWebApplication(piMetabase, psvd->wzVDirRoot, &psvd->swapp, psapList);
-                ExitOnFailure(hr, "Failed to write application for VirtualDir");
-            }
-
-            if (psvd->psmm)
-            {
-                hr = ScaWriteMimeMap(piMetabase, psvd->wzVDirRoot, psvd->psmm);
-                ExitOnFailure(hr, "Failed to write mimemap for VirtualDir");
-            }
-
-            if (psvd->pshh)
-            {
-                hr = ScaWriteHttpHeader(piMetabase, psvd->wzVDirRoot, psvd->pshh);
-                ExitOnFailure(hr, "Failed to write custom HTTP headers for VirtualDir");
-            }
-
-            if (psvd->pswe)
-            {
-                hr = ScaWriteWebError(piMetabase, weptVDir, psvd->wzVDirRoot, psvd->pswe);
-                ExitOnFailure(hr, "Failed to write custom web errors for VirtualDir");
-            }
-        }
-
-        psvd = psvd->psvdNext;
-    }
-
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaVirtualDirsUninstall(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_VDIR* psvdList
-    )
-{
-    Assert(piMetabase);
-
-    HRESULT hr = S_OK;
-    SCA_VDIR* psvd = psvdList;
-
-    while (psvd)
-    {
-        if (WcaIsUninstalling(psvd->isInstalled, psvd->isAction))
-        {
-            // delete the application for this virtual directory
-            if (psvd->fHasApplication)
-            {
-                hr = ScaDeleteApp(piMetabase, psvd->wzVDirRoot);
-                ExitOnFailure(hr, "Failed to remove application for WebVDir");
-            }
-
-            if (0 != lstrlenW(psvd->wzVDirRoot))
-            {
-                hr = ScaDeleteMetabaseKey(piMetabase, psvd->wzVDirRoot, L"");
-                ExitOnFailure(hr, "Failed to remove VirtualDir '%ls' from metabase", psvd->wzKey);
-            }
-        }
-
-        psvd = psvd->psvdNext;
-    }
-
-LExit:
-    return hr;
-}
-
-
-void ScaVirtualDirsFreeList(
-    __in SCA_VDIR* psvdList
-    )
-{
-    SCA_VDIR* psvdDelete = psvdList;
-    while (psvdList)
-    {
-        psvdDelete = psvdList;
-        psvdList = psvdList->psvdNext;
-
-        if (psvdDelete->psmm)
-        {
-            ScaMimeMapFreeList(psvdDelete->psmm);
-        }
-
-        if (psvdDelete->pswe)
-        {
-            ScaWebErrorFreeList(psvdDelete->pswe);
-        }
-
-        MemFree(psvdDelete);
-    }
-}
-
-
-static HRESULT AddVirtualDirToList(
-    __in SCA_VDIR** ppsvdList
-    )
-{
-    HRESULT hr = S_OK;
-    SCA_VDIR* psvd = static_cast<SCA_VDIR*>(MemAlloc(sizeof(SCA_VDIR), TRUE));
-    ExitOnNull(psvd, hr, E_OUTOFMEMORY, "failed to allocate memory for new vdir list element");
-
-    psvd->psvdNext= *ppsvdList;
-    *ppsvdList = psvd;
-
-LExit:
-    return hr;
-}
diff --git a/src/ca/scavdir.h b/src/ca/scavdir.h
deleted file mode 100644
index c7e9661b..00000000
--- a/src/ca/scavdir.h
+++ /dev/null
@@ -1,71 +0,0 @@
-#pragma once
-// 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.
-
-
-#include "scawebprop.h"
-#include "scawebapp.h"
-#include "scamimemap.h"
-#include "scaapppool.h"
-
-enum eVDirQuery { vdqWeb = 1, vdqVDir, vdqComponent , vdqAlias, vdqDirectory, vdqProperties, vdqApplication, vdqInstalled, vdqAction, vdqSourcePath, vdqTargetPath };
-
-struct SCA_VDIR
-{
-    // darwin information
-    WCHAR wzKey[MAX_DARWIN_KEY + 1];
-    WCHAR wzComponent[MAX_DARWIN_KEY + 1];
-    INSTALLSTATE isInstalled;
-    INSTALLSTATE isAction;
-
-    // metabase information
-    WCHAR wzWebKey[MAX_DARWIN_KEY + 1];
-    WCHAR wzWebBase[METADATA_MAX_NAME_LEN + 1];
-    WCHAR wzVDirRoot[METADATA_MAX_NAME_LEN + 1];
-
-    // iis configuation information
-    WCHAR wzDirectory[MAX_PATH];
-
-    BOOL fHasProperties;
-    SCA_WEB_PROPERTIES swp;
-
-    BOOL fHasApplication;
-    SCA_WEB_APPLICATION swapp;
-
-    SCA_MIMEMAP* psmm; // mime mappings
-    SCA_HTTP_HEADER* pshh; // custom web errors
-    SCA_WEB_ERROR* pswe; // custom web errors
-
-    SCA_VDIR* psvdNext;
-};
-
-
-// prototypes
-HRESULT __stdcall ScaVirtualDirsRead(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_WEB* pswList,
-    __in SCA_VDIR** ppsvdList,
-    __in SCA_MIMEMAP** ppsmmList,
-    __in SCA_HTTP_HEADER** ppshhList,
-    __in SCA_WEB_ERROR** ppsweList,
-    __in WCA_WRAPQUERY_HANDLE hUserQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebBaseQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
-    __inout LPWSTR *ppwzCustomActionData
-    );
-
-HRESULT ScaVirtualDirsInstall(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_VDIR* psvdList,
-    __in SCA_APPPOOL * psapList
-    );
-
-HRESULT ScaVirtualDirsUninstall(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_VDIR* psvdList
-    );
-
-void ScaVirtualDirsFreeList(
-    __in SCA_VDIR* psvdList
-    );
diff --git a/src/ca/scavdir7.cpp b/src/ca/scavdir7.cpp
deleted file mode 100644
index 3f675357..00000000
--- a/src/ca/scavdir7.cpp
+++ /dev/null
@@ -1,380 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-// prototypes
-static HRESULT AddVirtualDirToList7(
-    __in SCA_VDIR7** psvdList
-    );
-
-
-HRESULT __stdcall ScaVirtualDirsRead7(
-    __in SCA_WEB7* pswList,
-    __in SCA_VDIR7** ppsvdList,
-    __in SCA_MIMEMAP** ppsmmList,
-    __in SCA_HTTP_HEADER** ppshhList,
-    __in SCA_WEB_ERROR** ppsweList,
-    __in WCA_WRAPQUERY_HANDLE hUserQuery,
-    __in WCA_WRAPQUERY_HANDLE /*hWebBaseQuery*/,
-    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
-    __inout LPWSTR *ppwzCustomActionData
-    )
-{
-    Assert(ppsvdList);
-
-    HRESULT hr = S_OK;
-    MSIHANDLE hRec;
-
-    SCA_VDIR7* pvdir = NULL;
-    LPWSTR pwzData = NULL;
-    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
-
-    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead");
-
-    if (0 == WcaGetQueryRecords(hWrapQuery))
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ScaVirtualDirsRead() because IIsWebVirtualDir table not present");
-        ExitFunction1(hr = S_FALSE);
-    }
-
-    // loop through all the vdirs
-    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
-    {
-        // Add this record's information into the list of things to process.
-        hr = AddVirtualDirToList7(ppsvdList);
-        ExitOnFailure(hr, "failed to add vdir to vdir list");
-
-        pvdir = *ppsvdList;
-
-        // get the darwin information
-        hr = WcaGetRecordString(hRec, vdqComponent, &pwzData);
-        ExitOnFailure(hr, "failed to get IIsWebVirtualDir.Component");
-
-        hr = WcaGetRecordInteger(hRec, vdqInstalled, (int *)&pvdir->isInstalled);
-        ExitOnFailure(hr, "Failed to get Component installed state for virtual dir");
-
-        hr = WcaGetRecordInteger(hRec, vdqAction, (int *)&pvdir->isAction);
-        ExitOnFailure(hr, "Failed to get Component action state for virtual dir");
-
-        // get vdir properties
-        hr = ::StringCchCopyW(pvdir->wzComponent, countof(pvdir->wzComponent), pwzData);
-        ExitOnFailure(hr, "failed to copy vdir component name: %ls", pwzData);
-
-        hr = WcaGetRecordString(hRec, vdqWeb, &pwzData);
-        ExitOnFailure(hr, "Failed to get Web for VirtualDir");
-
-        hr = ScaWebsGetBase7(pswList, pwzData, pvdir->wzWebName , countof(pvdir->wzWebName));
-        if (S_FALSE == hr)
-        {
-            hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
-            ExitOnFailure(hr, "Failed to get Web Base for VirtualDir");
-        }
-        if (WcaIsUninstalling(pvdir->isInstalled, pvdir->isAction))
-        {
-            // If we're uninstalling, ignore any failure to find the existing web
-            hr = S_OK;
-        }
-
-        hr = WcaGetRecordString(hRec, vdqAlias, &pwzData);
-        ExitOnFailure(hr, "Failed to get Alias for VirtualDir");
-
-        hr = ::StringCchCopyW(pvdir->wzVDirRoot, countof(pvdir->wzVDirRoot), pwzData);
-        ExitOnFailure(hr, "Failed to set VDirRoot for VirtualDir");
-
-        // get the vdir's directory
-        hr = WcaGetRecordString(hRec, vdqDirectory, &pwzData);
-        ExitOnFailure(hr, "Failed to get Directory for VirtualDir");
-
-        // get the web's directory
-        if (INSTALLSTATE_SOURCE == pvdir->isAction)
-        {
-            hr = WcaGetRecordString(hRec, vdqSourcePath, &pwzData);
-        }
-        else
-        {
-            hr = WcaGetRecordString(hRec, vdqTargetPath, &pwzData);
-        }
-        ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory");
-
-        // remove trailing backslash(es)
-        while (lstrlenW(pwzData) > 0 && pwzData[lstrlenW(pwzData)-1] == L'\\')
-        {
-            pwzData[lstrlenW(pwzData)-1] = 0;
-        }
-        hr = ::StringCchCopyW(pvdir->wzDirectory, countof(pvdir->wzDirectory), pwzData);
-        ExitOnFailure(hr, "Failed to copy directory string to vdir object");
-
-        // get the security information for this web
-        hr = WcaGetRecordString(hRec, vdqProperties, &pwzData);
-        ExitOnFailure(hr, "Failed to get web directory identifier for VirtualDir");
-        if (*pwzData)
-        {
-            hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &pvdir->swp);
-            ExitOnFailure(hr, "Failed to get web directory for VirtualDir");
-
-            pvdir->fHasProperties = TRUE;
-        }
-
-        // get the application information for this web
-        hr = WcaGetRecordString(hRec, vdqApplication, &pwzData);
-        ExitOnFailure(hr, "Failed to get application identifier for VirtualDir");
-        if (*pwzData)
-        {
-            hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &pvdir->swapp);
-            ExitOnFailure(hr, "Failed to get application for VirtualDir");
-
-            pvdir->fHasApplication = TRUE;
-        }
-
-        hr = WcaGetRecordString(hRec, vdqVDir, &pwzData);
-        ExitOnFailure(hr, "Failed to get VDir for VirtualDir");
-
-        if (*pwzData && *ppsmmList)
-        {
-            hr = ScaGetMimeMap(mmptVDir, pwzData, ppsmmList, &pvdir->psmm);
-            ExitOnFailure(hr, "Failed to get mimemap for VirtualDir");
-        }
-
-        if (*pwzData && *ppshhList)
-        {
-            hr = ScaGetHttpHeader(hhptVDir, pwzData, ppshhList, &pvdir->pshh);
-            ExitOnFailure(hr, "Failed to get custom HTTP headers for VirtualDir: %ls", pwzData);
-        }
-
-        if (*pwzData && *ppsweList)
-        {
-            hr = ScaGetWebError(weptVDir, pwzData, ppsweList, &pvdir->pswe);
-            ExitOnFailure(hr, "Failed to get custom web errors for VirtualDir: %ls", pwzData);
-        }
-    }
-
-    if (E_NOMOREITEMS == hr)
-    {
-        hr = S_OK;
-    }
-    ExitOnFailure(hr, "Failure while processing VirtualDirs");
-
-LExit:
-    WcaFinishUnwrapQuery(hWrapQuery);
-
-    ReleaseStr(pwzData);
-
-    return hr;
-}
-
-
-HRESULT ScaVirtualDirsInstall7(
-    __in SCA_VDIR7* psvdList,
-    __in SCA_APPPOOL * psapList
-    )
-{
-    HRESULT hr = S_OK;
-    SCA_VDIR7* psvd = psvdList;
-    LPWSTR wzPath = NULL;
-    WCHAR wzAppPoolName[MAX_PATH];
-    while (psvd)
-    {
-        if (WcaIsInstalling(psvd->isInstalled, psvd->isAction))
-        {
-            // First write all applications, this is necessary since vdirs must be nested under the applications.
-            if (psvd->fHasApplication)
-            {
-                //create the application for this vdir application
-                hr = ScaWriteConfigID(IIS_APPLICATION);
-                ExitOnFailure(hr, "Failed to write app ID");
-                hr = ScaWriteConfigID(IIS_CREATE);
-                ExitOnFailure(hr, "Failed to write app action");
-#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
-                hr = ScaWriteConfigString(psvd->wzWebName);           //site name key
-                ExitOnFailure(hr, "Failed to write app web key");
-                hr = StrAllocFormatted(&wzPath, L"/%s", psvd->wzVDirRoot);
-                ExitOnFailure(hr, "Failed to create app path");
-                hr = ScaWriteConfigString(wzPath);                    //  App Path
-                ExitOnFailure(hr, "Failed to write app path root ");
-
-                if (!*psvd->swapp.wzAppPool)
-                {
-                    //This Application goes in default appPool
-                    hr = ScaWriteConfigString(L"");                   //  App Pool
-                }
-                else
-                {
-                    //get apppool from WebApplication
-#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
-                    hr = ScaFindAppPool7(psvd->swapp.wzAppPool, wzAppPoolName, countof(wzAppPoolName), psapList);
-                    ExitOnFailure(hr, "Failed to read app pool from application");
-                    hr = ScaWriteConfigString(wzAppPoolName);           //  App Pool
-                    ExitOnFailure(hr, "Failed to write appPool for vdir");
-
-                }
-            }
-        }
-
-        psvd = psvd->psvdNext;
-    }
-
-    // Reset our linked list and write all the VDirs
-    psvd = psvdList;
-    while (psvd)
-    {
-        if (WcaIsInstalling(psvd->isInstalled, psvd->isAction))
-        {
-            //create the Vdir
-            hr = ScaWriteConfigID(IIS_VDIR);
-            ExitOnFailure(hr, "Failed write VirDir ID")
-            hr = ScaWriteConfigID(IIS_CREATE);
-            ExitOnFailure(hr, "Failed write VirDir action")
-#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
-            hr = ScaWriteConfigString(psvd->wzWebName);         //site name key
-            ExitOnFailure(hr, "Failed write VirDir web name");
-            hr = StrAllocFormatted(&wzPath, L"/%s", psvd->wzVDirRoot);
-            ExitOnFailure(hr, "Failed to create vdir path");
-            hr = ScaWriteConfigString(wzPath);                  //vdir path
-            ExitOnFailure(hr, "Failed write VirDir path")
-#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
-            hr = ScaWriteConfigString(psvd->wzDirectory);       //physical dir
-            ExitOnFailure(hr, "Failed write VirDir dir");
-
-            if (psvd->fHasProperties)
-            {
-                ScaWriteWebDirProperties7(psvd->wzWebName, psvd->wzVDirRoot, &psvd->swp);
-                ExitOnFailure(hr, "Failed to write directory properties for VirtualDir");
-            }
-
-            if (psvd->fHasApplication)
-            {
-                hr = ScaWriteWebApplication7(psvd->wzWebName, psvd->wzVDirRoot, &psvd->swapp, psapList);
-                ExitOnFailure(hr, "Failed to write application for VirtualDir");
-            }
-
-            if (psvd->psmm)
-            {
-                hr = ScaWriteMimeMap7(psvd->wzWebName, psvd->wzVDirRoot, psvd->psmm);
-                ExitOnFailure(hr, "Failed to write mimemap for VirtualDir");
-            }
-
-            if (psvd->pshh)
-            {
-                hr = ScaWriteHttpHeader7(psvd->wzWebName, psvd->wzVDirRoot, psvd->pshh);
-                ExitOnFailure(hr, "Failed to write custom HTTP headers for VirtualDir");
-            }
-
-            if (psvd->pswe)
-            {
-                hr = ScaWriteWebError7(psvd->wzWebName, psvd->wzVDirRoot, psvd->pswe);
-                ExitOnFailure(hr, "Failed to write custom web errors for VirtualDir");
-            }
-        }
-
-        psvd = psvd->psvdNext;
-    }
-
-LExit:
-    ReleaseStr(wzPath);
-    return hr;
-}
-
-
-HRESULT ScaVirtualDirsUninstall7(
-                                 __in SCA_VDIR7* psvdList
-                                 )
-{
-
-    HRESULT hr = S_OK;
-    SCA_VDIR7* psvd = psvdList;
-    LPWSTR wzPath = NULL;
-
-    while (psvd)
-    {
-        if (WcaIsUninstalling(psvd->isInstalled, psvd->isAction))
-        {
-            //init path
-            hr = StrAllocFormatted(&wzPath, L"/%s", psvd->wzVDirRoot);
-            ExitOnFailure(hr, "Failed to create vdir path");
-
-            if (psvd->fHasApplication)
-            {
-                //delete Application
-                hr = ScaWriteConfigID(IIS_APPLICATION);
-                ExitOnFailure(hr, "Failed to write app ID ");
-                hr = ScaWriteConfigID(IIS_DELETE);
-                ExitOnFailure(hr, "Failed to write delete app ID ");
-#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
-                hr = ScaWriteConfigString(psvd->wzWebName);        //site name key
-                ExitOnFailure(hr, "Failed to write App site Name");
-#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
-                hr = ScaWriteConfigString(wzPath);                 //  App Path
-                ExitOnFailure(hr, "Failed to write app path root ");
-                hr = ScaWriteConfigString(L"NOP");                 //  App pool
-                ExitOnFailure(hr, "Failed to write app path app pool ");
-            }
-            else
-            {
-                //delete VDir
-                hr = ScaWriteConfigID(IIS_VDIR);
-                ExitOnFailure(hr, "Failed to write vDir ID ");
-                hr = ScaWriteConfigID(IIS_DELETE);
-#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
-                hr = ScaWriteConfigString(psvd->wzWebName);        //site name key
-                ExitOnFailure(hr, "Failed to write App site Name");
-                hr = ScaWriteConfigString(wzPath);                 //  Vdir Path
-                ExitOnFailure(hr, "Failed to write app vdir ");
-                hr = ScaWriteConfigString(L"NOP");                 //  Phy Path
-                ExitOnFailure(hr, "Failed to write vdir path");
-            }
-
-            ExitOnFailure(hr, "Failed to remove VirtualDir '%ls' from config", psvd->wzKey);
-        }
-
-        psvd = psvd->psvdNext;
-    }
-
-LExit:
-    ReleaseStr(wzPath);
-    return hr;
-}
-
-
-void ScaVirtualDirsFreeList7(
-    __in SCA_VDIR7* psvdList
-    )
-{
-    SCA_VDIR7* psvdDelete = psvdList;
-    while (psvdList)
-    {
-        psvdDelete = psvdList;
-        psvdList = psvdList->psvdNext;
-
-        if (psvdDelete->psmm)
-        {
-            ScaMimeMapFreeList(psvdDelete->psmm);
-        }
-
-        if (psvdDelete->pswe)
-        {
-            ScaWebErrorFreeList(psvdDelete->pswe);
-        }
-
-        MemFree(psvdDelete);
-    }
-}
-
-
-static HRESULT AddVirtualDirToList7(
-    __in SCA_VDIR7** ppsvdList
-    )
-{
-    HRESULT hr = S_OK;
-
-    SCA_VDIR7* psvd = static_cast<SCA_VDIR7*>(MemAlloc(sizeof(SCA_VDIR7), TRUE));
-    ExitOnNull(psvd, hr, E_OUTOFMEMORY, "failed to allocate memory for new vdir list element");
-
-    psvd->psvdNext= *ppsvdList;
-    *ppsvdList = psvd;
-
-LExit:
-    return hr;
-}
diff --git a/src/ca/scavdir7.h b/src/ca/scavdir7.h
deleted file mode 100644
index dba25431..00000000
--- a/src/ca/scavdir7.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#pragma once
-// 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.
-
-
-#include "scawebprop.h"
-#include "scawebapp.h"
-#include "scamimemap.h"
-#include "scaapppool.h"
-
-struct SCA_VDIR7
-{
-    // darwin information
-    WCHAR wzKey[MAX_DARWIN_KEY + 1];
-    WCHAR wzComponent[MAX_DARWIN_KEY + 1];
-    INSTALLSTATE isInstalled;
-    INSTALLSTATE isAction;
-
-    // metabase information
-    WCHAR wzWebKey[MAX_DARWIN_KEY + 1];
-    WCHAR wzWebName[METADATA_MAX_NAME_LEN + 1];
-    WCHAR wzVDirRoot[METADATA_MAX_NAME_LEN + 1];
-
-    // iis configuation information
-    WCHAR wzDirectory[MAX_PATH];
-
-    BOOL fHasProperties;
-    SCA_WEB_PROPERTIES swp;
-
-    BOOL fHasApplication;
-    SCA_WEB_APPLICATION swapp;
-
-    SCA_MIMEMAP* psmm; // mime mappings
-    SCA_HTTP_HEADER* pshh; // custom web errors
-    SCA_WEB_ERROR* pswe; // custom web errors
-
-    SCA_VDIR7* psvdNext;
-};
-
-
-// prototypes
-HRESULT __stdcall ScaVirtualDirsRead7(
-    __in SCA_WEB7* pswList,
-    __in SCA_VDIR7** ppsvdList,
-    __in SCA_MIMEMAP** ppsmmList,
-    __in SCA_HTTP_HEADER** ppshhList,
-    __in SCA_WEB_ERROR** ppsweList,
-    __in WCA_WRAPQUERY_HANDLE hUserQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebBaseQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
-    __inout LPWSTR *ppwzCustomActionData
-    );
-
-HRESULT ScaVirtualDirsInstall7(
-    __in SCA_VDIR7* psvdList,
-    __in SCA_APPPOOL * psapList
-    );
-
-HRESULT ScaVirtualDirsUninstall7(
-    __in SCA_VDIR7* psvdList
-    );
-
-void ScaVirtualDirsFreeList7(
-    __in SCA_VDIR7* psvdList
-    );
diff --git a/src/ca/scaweb.cpp b/src/ca/scaweb.cpp
deleted file mode 100644
index 0452fb0b..00000000
--- a/src/ca/scaweb.cpp
+++ /dev/null
@@ -1,1187 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-//Adding this because delivery doesn't have the updated specstrings.h that windows build does
-#ifndef __in_xcount
-#define __in_xcount(size)
-#endif
-
-// sql queries
-
-enum eWebBaseQuery { wbqWeb = 1, wbqId, wbqIP, wbqPort, wbqHeader, wbqSecure, wbqDescription };
-
-
-// prototypes for private helper functions
-static SCA_WEB* NewWeb();
-static void FreeWeb(SCA_WEB *pswDelete);
-static SCA_WEB* AddWebToList(
-    __in SCA_WEB* pswList,
-    __in SCA_WEB* psw
-    );
-static HRESULT ScaWebFindBase(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_WEB* pswList,
-    __in_z LPCWSTR wzWeb,
-    __in int iSiteId,
-    __in_z LPCWSTR wzIP,
-    __in int iPort,
-    __in_z LPCWSTR wzHeader,
-    __in BOOL fSecure,
-    __in_z LPCWSTR wzDescription,
-    __out_ecount(cchWebBase) LPWSTR wzWebBase,
-    __in DWORD cchWebBase
-    );
-static HRESULT ScaWebFindFreeBase(
-    __in IMSAdminBase* piMetabase,
-    __in_xcount(unknown) SCA_WEB* pswList,
-    __in int iSiteId,
-    __in_z LPCWSTR wzDescription,
-    __out_ecount(cchWebBase) LPWSTR wzWebBase,
-    __in DWORD cchWebBase
-    );
-static HRESULT ScaWebWrite(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_WEB* psw,
-    __in SCA_APPPOOL * psapList
-    );
-static HRESULT ScaWebRemove(
-    __in IMSAdminBase* piMetabase,
-    __in const SCA_WEB* psw);
-static DWORD SiteIdFromDescription(
-    __in_z LPCWSTR wzDescription
-    );
-static void Sort(
-    __in_ecount(cArray) DWORD dwArray[],
-    __in int cArray
-    );
-
-
-HRESULT ScaWebsRead(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_MIMEMAP** ppsmmList,
-    __in SCA_WEB** ppswList,
-    __in SCA_HTTP_HEADER** ppshhList,
-    __in SCA_WEB_ERROR** ppsweList,
-    __in WCA_WRAPQUERY_HANDLE hUserQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
-    __in WCA_WRAPQUERY_HANDLE hSslCertQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebLogQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
-    __inout LPWSTR *ppwzCustomActionData
-    )
-{
-    Assert(piMetabase && ppswList);
-
-    HRESULT hr = S_OK;
-
-    MSIHANDLE hRec;
-    MSIHANDLE hRecAddresses;
-
-    SCA_WEB* psw = NULL;
-    LPWSTR pwzData = NULL;
-    int iSiteId;
-
-    DWORD dwLen = 0;
-    WCA_WRAPQUERY_HANDLE hQueryWebSite = NULL;
-    WCA_WRAPQUERY_HANDLE hQueryWebAddress = NULL;
-
-    hr = WcaBeginUnwrapQuery(&hQueryWebSite, ppwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap query for ScaWebsRead");
-
-    hr = WcaBeginUnwrapQuery(&hQueryWebAddress, ppwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap query for ScaWebsRead");
-
-    if (0 == WcaGetQueryRecords(hQueryWebSite))
-    {
-        WcaLog(LOGMSG_VERBOSE, "Required tables not present");
-        ExitFunction1(hr = S_FALSE);
-    }
-
-    // loop through all the webs
-    while (S_OK == (hr = WcaFetchWrappedRecord(hQueryWebSite, &hRec)))
-    {
-        psw = NewWeb();
-        ExitOnNull(psw, hr, E_OUTOFMEMORY, "Failed to allocate memory for web object in memory");
-
-        // get the darwin information
-        hr = WcaGetRecordString(hRec, wqWeb, &pwzData);
-        ExitOnFailure(hr, "Failed to get Web");
-        hr = ::StringCchCopyW(psw->wzKey, countof(psw->wzKey), pwzData);
-        ExitOnFailure(hr, "Failed to copy key string to web object");
-
-        if (*pwzData && *ppsmmList)
-        {
-            hr = ScaGetMimeMap(mmptWeb, pwzData, ppsmmList, &psw->psmm);
-            ExitOnFailure(hr, "Failed to get mimemap for VirtualDir");
-        }
-
-        // get component install state
-        hr = WcaGetRecordString(hRec, wqComponent, &pwzData);
-        ExitOnFailure(hr, "Failed to get Component for Web");
-        hr = ::StringCchCopyW(psw->wzComponent, countof(psw->wzComponent), pwzData);
-        ExitOnFailure(hr, "Failed to copy component string to web object");
-        if (*(psw->wzComponent))
-        {
-            psw->fHasComponent = TRUE;
-
-            hr = WcaGetRecordInteger(hRec, wqInstalled, (int *)&psw->isInstalled);
-            ExitOnFailure(hr, "Failed to get web Component's installed state");
-
-            WcaGetRecordInteger(hRec, wqAction, (int *)&psw->isAction);
-            ExitOnFailure(hr, "Failed to get web Component's action state");
-
-            if (!WcaIsInstalling(psw->isInstalled, psw->isAction) && !WcaIsUninstalling(psw->isInstalled, psw->isAction)
-                && !WcaIsReInstalling(psw->isInstalled, psw->isAction))
-            {
-                FreeWeb(psw);
-                psw = NULL;
-
-                continue; // If we aren't acting on this component, skip it
-            }
-        }
-
-        hr = WcaGetRecordInteger(hRec, wqId, &iSiteId);
-        ExitOnFailure(hr, "Failed to get SiteId for Web");
-
-        // Get the web's key address.
-        hr = WcaGetRecordString(hRec, wqAddress, &pwzData);
-        ExitOnFailure(hr, "Failed to get Address for Web");
-        hr = ::StringCchCopyW(psw->swaKey.wzKey, countof(psw->swaKey.wzKey), pwzData);
-        ExitOnFailure(hr, "Failed to copy key string to web object");
-
-        hr = WcaGetRecordString(hRec, wqIP, &pwzData);
-        ExitOnFailure(hr, "Failed to get IP for Web");
-        hr = ::StringCchCopyW(psw->swaKey.wzIP, countof(psw->swaKey.wzIP), pwzData);
-        ExitOnFailure(hr, "Failed to copy IP string to web object");
-
-        hr = WcaGetRecordString(hRec, wqPort, &pwzData);
-        ExitOnFailure(hr, "Failed to get Web Address port");
-        psw->swaKey.iPort = wcstol(pwzData, NULL, 10);
-
-        hr = WcaGetRecordString(hRec, wqHeader, &pwzData);
-        ExitOnFailure(hr, "Failed to get Header for Web");
-        hr = ::StringCchCopyW(psw->swaKey.wzHeader, countof(psw->swaKey.wzHeader), pwzData);
-        ExitOnFailure(hr, "Failed to copy header string to web object");
-
-        hr = WcaGetRecordInteger(hRec, wqSecure, &psw->swaKey.fSecure);
-        ExitOnFailure(hr, "Failed to get if Web is secure");
-        if (S_FALSE == hr)
-        {
-            psw->swaKey.fSecure = FALSE;
-        }
-
-        // Get the web's description.
-        hr = WcaGetRecordString(hRec, wqDescription, &pwzData);
-        ExitOnFailure(hr, "Failed to get Description for Web");
-        hr = ::StringCchCopyW(psw->wzDescription, countof(psw->wzDescription), pwzData);
-        ExitOnFailure(hr, "Failed to copy description string to web object");
-
-        // Try to find the web root in case it already exists.
-        dwLen = METADATA_MAX_NAME_LEN;
-        hr = ScaWebFindBase(piMetabase, *ppswList,
-                            psw->wzKey,
-                            iSiteId,
-                            psw->swaKey.wzIP,
-                            psw->swaKey.iPort,
-                            psw->swaKey.wzHeader,
-                            psw->swaKey.fSecure,
-                            psw->wzDescription,
-                            psw->wzWebBase, dwLen);
-        if (S_OK == hr)
-        {
-            psw->fBaseExists = TRUE;
-        }
-        else if (S_FALSE == hr) // didn't find the web site.
-        {
-            psw->fBaseExists = FALSE;
-
-            // If we're actually configuring the web site.
-            if (psw->fHasComponent)
-            {
-                if (WcaIsInstalling(psw->isInstalled, psw->isAction))
-                {
-                    hr = ScaWebFindFreeBase(piMetabase, *ppswList, iSiteId, psw->wzDescription, psw->wzWebBase, countof(psw->wzWebBase));
-                    ExitOnFailure(hr, "Failed to find free web root.");
-                }
-                else if (WcaIsUninstalling(psw->isInstalled, psw->isAction))
-                {
-                    WcaLog(LOGMSG_VERBOSE, "Web site: '%ls' was already removed, skipping.", psw->wzKey);
-
-                    hr = S_OK;
-                    continue;
-                }
-            }
-        }
-        ExitOnFailure(hr, "Failed to find web root");
-
-        // get any extra web addresses
-        WcaFetchWrappedReset(hQueryWebAddress);
-        while (S_OK == (hr = WcaFetchWrappedRecordWhereString(hQueryWebAddress, 2, psw->wzKey, &hRecAddresses)))
-        {
-            if (MAX_ADDRESSES_PER_WEB <= psw->cExtraAddresses)
-            {
-                hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
-                ExitOnFailure(hr, "Failure to get more extra web addresses, max exceeded.");
-            }
-
-            hr = WcaGetRecordString(hRecAddresses, waqAddress, &pwzData);
-            ExitOnFailure(hr, "Failed to get extra web Address");
-
-            // if this isn't the key address add it
-            if (0 != lstrcmpW(pwzData, psw->swaKey.wzKey))
-            {
-                hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey), pwzData);
-                ExitOnFailure(hr, "Failed to copy extra addresses key string to web object");
-
-                hr = WcaGetRecordString(hRecAddresses, waqIP, &pwzData);
-                ExitOnFailure(hr, "Failed to get extra web IP");
-                hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP), pwzData);
-                ExitOnFailure(hr, "Failed to copy extra addresses IP string to web object");
-
-                hr = WcaGetRecordString(hRecAddresses, waqPort, &pwzData);
-                ExitOnFailure(hr, "Failed to get port for extra web IP");
-                psw->swaExtraAddresses[psw->cExtraAddresses].iPort= wcstol(pwzData, NULL, 10);
-
-                hr = WcaGetRecordString(hRecAddresses, waqHeader, &pwzData);
-                ExitOnFailure(hr, "Failed to get header for extra web IP");
-                hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader), pwzData);
-                ExitOnFailure(hr, "Failed to copy extra addresses header string to web object");
-
-                hr = WcaGetRecordInteger(hRecAddresses, waqSecure, &psw->swaExtraAddresses[psw->cExtraAddresses].fSecure);
-                ExitOnFailure(hr, "Failed to get if secure extra web IP");
-                if (S_FALSE == hr)
-                    psw->swaExtraAddresses[psw->cExtraAddresses].fSecure = FALSE;
-
-                ++psw->cExtraAddresses;
-            }
-        }
-
-        if (E_NOMOREITEMS == hr)
-            hr = S_OK;
-        ExitOnFailure(hr, "Failure occured while getting extra web addresses");
-
-        hr = WcaGetRecordInteger(hRec, wqConnectionTimeout, &psw->iConnectionTimeout);
-        ExitOnFailure(hr, "Failed to get connection timeout for Web");
-
-        if (psw->fHasComponent) // If we're installing it, it needs a dir
-        {
-            // get the web's directory
-            if (INSTALLSTATE_SOURCE == psw->isAction)
-            {
-                hr = WcaGetRecordString(hRec, wqSourcePath, &pwzData);
-            }
-            else
-            {
-                hr = WcaGetRecordString(hRec, wqTargetPath, &pwzData);
-            }
-            ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory");
-
-            // remove trailing backslashes
-            while (lstrlenW(pwzData) > 0 && pwzData[lstrlenW(pwzData)-1] == L'\\')
-            {
-                pwzData[lstrlenW(pwzData)-1] = 0;
-            }
-            hr = ::StringCchCopyW(psw->wzDirectory, countof(psw->wzDirectory), pwzData);
-            ExitOnFailure(hr, "Failed to copy directory string to web object");
-        }
-
-        hr = WcaGetRecordInteger(hRec, wqState, &psw->iState);
-        ExitOnFailure(hr, "Failed to get state for Web");
-
-        hr = WcaGetRecordInteger(hRec, wqAttributes, &psw->iAttributes);
-        ExitOnFailure(hr, "Failed to get attributes for Web");
-
-        // get the dir properties for this web
-        hr = WcaGetRecordString(hRec, wqProperties, &pwzData);
-        ExitOnFailure(hr, "Failed to get directory property record for Web");
-        if (*pwzData)
-        {
-            hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &psw->swp);
-            ExitOnFailure(hr, "Failed to get directory properties for Web");
-
-            psw->fHasProperties = TRUE;
-        }
-
-        // get the application information for this web
-        hr = WcaGetRecordString(hRec, wqApplication, &pwzData);
-        ExitOnFailure(hr, "Failed to get application identifier for Web");
-        if (*pwzData)
-        {
-            hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &psw->swapp);
-            ExitOnFailure(hr, "Failed to get application for Web");
-
-            psw->fHasApplication = TRUE;
-        }
-
-        // get the SSL certificates
-        hr = ScaSslCertificateRead(psw->wzKey, hSslCertQuery, &(psw->pswscList));
-        ExitOnFailure(hr, "Failed to get SSL Certificates.");
-
-        // get the custom headers
-        if (*ppshhList)
-        {
-            hr = ScaGetHttpHeader(hhptWeb, psw->wzKey, ppshhList, &(psw->pshhList));
-            ExitOnFailure(hr, "Failed to get Custom HTTP Headers");
-        }
-
-        // get the errors
-        if (*ppsweList)
-        {
-            hr = ScaGetWebError(weptWeb, psw->wzKey, ppsweList, &(psw->psweList));
-            ExitOnFailure(hr, "Failed to get Custom Errors");
-        }
-
-        // get the log information for this web
-        hr = WcaGetRecordString(hRec, wqLog, &pwzData);
-        ExitOnFailure(hr, "Failed to get log identifier for Web");
-        if (*pwzData)
-        {
-            hr = ScaGetWebLog(piMetabase, pwzData, hWebLogQuery, &psw->swl);
-            ExitOnFailure(hr, "Failed to get Log for Web.");
-
-            psw->fHasLog = TRUE;
-        }
-
-        *ppswList = AddWebToList(*ppswList, psw);
-        psw = NULL; // set the web NULL so it doesn't accidentally get freed below
-    }
-
-    if (E_NOMOREITEMS == hr)
-    {
-        hr = S_OK;
-    }
-
-LExit:
-    // if anything was left over after an error clean it all up
-    WcaFinishUnwrapQuery(hQueryWebSite);
-    WcaFinishUnwrapQuery(hQueryWebAddress);
-
-    if (psw)
-    {
-        ScaWebsFreeList(psw);
-    }
-
-    ReleaseStr(pwzData);
-
-    return hr;
-}
-
-
-HRESULT ScaWebsGetBase(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_WEB* pswList,
-    __in LPCWSTR wzWeb,
-    __out_ecount(cchWebBase) LPWSTR wzWebBase,
-    __in DWORD cchWebBase,
-    __in WCA_WRAPQUERY_HANDLE hWrapQuery
-    )
-{
-    HRESULT hr = S_OK;
-    MSIHANDLE hRec;
-
-    int iSiteId;
-    WCHAR wzIP[MAX_PATH];
-    int iPort = -1;
-    WCHAR wzHeader[MAX_PATH];
-    BOOL fSecure = FALSE;
-
-    LPWSTR pwzData = NULL;
-
-    // get the web information
-    WcaFetchWrappedReset(hWrapQuery);
-
-    hr = WcaFetchWrappedRecordWhereString(hWrapQuery, 1, wzWeb, &hRec);
-    if (S_OK == hr)
-    {
-        // get the data to search for
-        hr = WcaGetRecordInteger(hRec, wbqId, &iSiteId);
-        ExitOnFailure(hr, "Failed to get SiteId for Web for VirtualDir");
-
-        hr = WcaGetRecordString(hRec, wbqIP, &pwzData);
-        ExitOnFailure(hr, "Failed to get IP for Web for VirtualDir");
-        hr = ::StringCchCopyW(wzIP, countof(wzIP), pwzData);
-        ExitOnFailure(hr, "Failed to copy IP for Web for VirtualDir");
-
-        hr = WcaGetRecordString(hRec, wbqPort, &pwzData);
-        ExitOnFailure(hr, "Failed to get port for extra web IP");
-        iPort = wcstol(pwzData, NULL, 10);
-
-        hr = WcaGetRecordString(hRec, wbqHeader, &pwzData);
-        ExitOnFailure(hr, "Failed to get Header for Web for VirtualDir");
-        hr = ::StringCchCopyW(wzHeader, countof(wzHeader), pwzData);
-        ExitOnFailure(hr, "Failed to copy Header for Web for VirtualDir");
-
-        hr = WcaGetRecordInteger(hRec, wbqSecure, &fSecure);
-        if (S_FALSE == hr)
-            fSecure = FALSE;
-
-        hr = WcaGetRecordString(hRec, wbqDescription, &pwzData);
-        ExitOnFailure(hr, "Failed to get Description for Web");
-
-        // find the web or find the next free web location
-        hr = ScaWebFindBase(piMetabase, pswList, wzWeb, iSiteId, wzIP, iPort, wzHeader, fSecure, pwzData, wzWebBase, cchWebBase);
-        if (S_FALSE == hr)
-            hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-        ExitOnFailure(hr, "Failed to find Web base");
-    }
-    else if (S_FALSE == hr)
-        hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
-
-    // Let's check that there isn't more than one record found - if there is, throw an assert like WcaFetchSingleRecord() would
-    HRESULT hrTemp = WcaFetchWrappedRecordWhereString(hWrapQuery, 1, wzWeb, &hRec);
-    if (SUCCEEDED(hrTemp))
-    {
-        AssertSz(E_NOMOREITEMS == hrTemp, "ScaWebsGetBase found more than one record");
-    }
-
-LExit:
-    ReleaseStr(pwzData);
-
-    return hr;
-}
-
-
-HRESULT ScaWebsInstall(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_WEB* pswList,
-    __in SCA_APPPOOL * psapList
-    )
-{
-    HRESULT hr = S_OK;
-    SCA_WEB* psw = pswList;
-
-    while (psw)
-    {
-        // if we are installing the web site
-        if (psw->fHasComponent && WcaIsInstalling(psw->isInstalled, psw->isAction))
-        {
-            hr = ScaWebWrite(piMetabase, psw, psapList);
-            ExitOnFailure(hr, "failed to write web '%ls' to metabase", psw->wzKey);
-        }
-
-        psw = psw->pswNext;
-    }
-
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaWebsUninstall(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_WEB* pswList
-    )
-{
-    HRESULT hr = S_OK;
-    SCA_WEB* psw = pswList;
-
-    while (psw)
-    {
-        // if we are uninstalling the web site
-        if (psw->fHasComponent && WcaIsUninstalling(psw->isInstalled, psw->isAction))
-        {
-            hr = ScaWebRemove(piMetabase, psw);
-            ExitOnFailure(hr, "Failed to remove web '%ls' from metabase", psw->wzKey);
-        }
-
-        psw = psw->pswNext;
-    }
-
-LExit:
-    return hr;
-}
-
-
-void ScaWebsFreeList(
-    __in SCA_WEB* pswList
-    )
-{
-    SCA_WEB* pswDelete = pswList;
-    while (pswList)
-    {
-        pswDelete = pswList;
-        pswList = pswList->pswNext;
-
-        // Free the SSL, headers and errors list first
-        FreeWeb(pswDelete);
-    }
-}
-
-
-// private helper functions
-
-static void FreeWeb(SCA_WEB *pswDelete)
-{
-    ScaSslCertificateFreeList(pswDelete->pswscList);
-    ScaHttpHeaderFreeList(pswDelete->pshhList);
-    ScaWebErrorFreeList(pswDelete->psweList);
-    MemFree(pswDelete);
-}
-
-static SCA_WEB* NewWeb()
-{
-    SCA_WEB* psw = static_cast<SCA_WEB*>(MemAlloc(sizeof(SCA_WEB), TRUE));
-    Assert(psw);
-    return psw;
-}
-
-
-static SCA_WEB* AddWebToList(
-    __in SCA_WEB* pswList,
-    __in SCA_WEB* psw
-    )
-{
-    if (pswList)
-    {
-        SCA_WEB* pswTemp = pswList;
-        while (pswTemp->pswNext)
-        {
-            pswTemp = pswTemp->pswNext;
-        }
-
-        pswTemp->pswNext = psw;
-    }
-    else
-    {
-        pswList = psw;
-    }
-
-    return pswList;
-}
-
-
-static HRESULT ScaWebFindBase(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_WEB* pswList,
-    __in_z LPCWSTR wzWeb,
-    __in int iSiteId,
-    __in_z LPCWSTR wzIP,
-    __in int iPort,
-    __in_z LPCWSTR wzHeader,
-    __in BOOL fSecure,
-    __in_z LPCWSTR wzDescription,
-    __out_ecount(cchWebBase) LPWSTR wzWebBase,
-    __in DWORD cchWebBase
-    )
-{
-    Assert(piMetabase);
-
-    HRESULT hr = S_OK;
-
-    WCHAR wzKey[METADATA_MAX_NAME_LEN];
-    WCHAR wzSubkey[METADATA_MAX_NAME_LEN];
-    LPWSTR wzFoundKey = NULL;
-
-    METADATA_RECORD mr;
-    ::ZeroMemory(&mr, sizeof(mr));
-
-    METADATA_RECORD mrCompare;
-    ::ZeroMemory(&mrCompare, sizeof(mrCompare));
-
-    // try to find the web in memory first
-    for (SCA_WEB* psw = pswList; psw; psw = psw->pswNext)
-    {
-        if (0 == lstrcmpW(wzWeb, psw->wzKey))
-        {
-            if ((0 == lstrcmpW(wzIP, psw->swaKey.wzIP) || 0 == lstrcmpW(wzIP, L"*") || 0 == lstrcmpW(psw->swaKey.wzIP, L"*")) &&
-                iPort == psw->swaKey.iPort &&
-                0 == lstrcmpW(wzHeader, psw->swaKey.wzHeader) &&
-                fSecure == psw->swaKey.fSecure)
-            {
-                if (0 == lstrlenW(psw->wzWebBase))
-                {
-                    WcaLog(LOGMSG_STANDARD, "A matching web object in memory was found, but the web object in memory has no associated base");
-                    ExitFunction1(hr = S_FALSE);
-                }
-
-                hr = ::StringCchCopyW(wzKey, countof(wzKey), psw->wzWebBase);
-                ExitOnFailure(hr, "Failed to copy web base into key.");
-
-                wzFoundKey = wzKey;
-                break;
-            }
-            else
-            {
-                WcaLog(LOGMSG_STANDARD, "Found web `%ls` but data did not match.", wzWeb);
-                hr = E_UNEXPECTED;
-                break;
-            }
-        }
-    }
-    ExitOnFailure(hr, "Failure occured while searching for web in memory");
-
-    // If we didn't find a web in memory matching look in the metabase.
-    if (!wzFoundKey)
-    {
-        mr.dwMDIdentifier = MD_KEY_TYPE;
-        mr.dwMDAttributes = METADATA_INHERIT;
-        mr.dwMDUserType = IIS_MD_UT_SERVER;
-        mr.dwMDDataType = ALL_METADATA;
-        mr.dwMDDataLen = 0;
-        mr.pbMDData = NULL;
-
-        // If we're looking based on the old WebAddress detection (NULL) or the new
-        // Web description detection (-1)
-        if (MSI_NULL_INTEGER == iSiteId || -1 == iSiteId)
-        {
-            if (MSI_NULL_INTEGER == iSiteId)
-            {
-                mrCompare.dwMDIdentifier = (fSecure) ? MD_SECURE_BINDINGS : MD_SERVER_BINDINGS;
-            }
-            else
-            {
-                mrCompare.dwMDIdentifier = MD_SERVER_COMMENT;
-            }
-            mrCompare.dwMDAttributes = METADATA_INHERIT;
-            mrCompare.dwMDUserType = IIS_MD_UT_SERVER;
-            mrCompare.dwMDDataType = ALL_METADATA;
-            mrCompare.dwMDDataLen = 0;
-            mrCompare.pbMDData = NULL;
-
-            // Loop through the "web keys" looking for the "IIsWebServer" key that matches our search criteria.
-            for (DWORD dwIndex = 0; SUCCEEDED(hr); ++dwIndex)
-            {
-                hr = piMetabase->EnumKeys(METADATA_MASTER_ROOT_HANDLE, L"/LM/W3SVC", wzSubkey, dwIndex);
-                if (SUCCEEDED(hr))
-                {
-                    hr = ::StringCchPrintfW(wzKey, countof(wzKey), L"/LM/W3SVC/%s", wzSubkey);
-                    ExitOnFailure(hr, "Failed to copy web subkey.");
-
-                    hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzKey, &mr);
-                    if (MD_ERROR_DATA_NOT_FOUND == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
-                    {
-                        hr = S_FALSE;  // didn't find anything, try next one
-                        continue;
-                    }
-                    ExitOnFailure(hr, "Failed to get key from metabase while searching for web servers");
-
-                    // If we have an IIsWebServer check to see if this is the site we are searching for.
-                    if (0 == lstrcmpW(L"IIsWebServer", (LPCWSTR)mr.pbMDData))
-                    {
-                        hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzKey, &mrCompare);
-                        if (MD_ERROR_DATA_NOT_FOUND == hr || NULL == mrCompare.pbMDData)
-                        {
-                            hr = S_FALSE;
-                            continue;
-                        }
-                        ExitOnFailure(hr, "Failed to get address/description from metabase while searching for web servers");
-
-                        LPWSTR pwzExists = (LPWSTR)mrCompare.pbMDData;
-                        if (MSI_NULL_INTEGER == iSiteId)
-                        {
-                            // Break down the address into its constituent parts (IP:Port:Header).
-                            while (S_OK == hr && *pwzExists)
-                            {
-                                LPCWSTR pwzIPExists = pwzExists;
-                                pwzExists = const_cast<LPWSTR>(wcsstr(pwzIPExists, L":"));
-                                ExitOnNull(pwzExists, hr, E_INVALIDARG, "Invalid web address. IP was not separated by a colon.");
-                                *pwzExists = L'\0';
-
-                                LPCWSTR pwzPortExists = pwzExists + 1;
-                                pwzExists = const_cast<LPWSTR>(wcsstr(pwzPortExists, L":"));
-                                ExitOnNull(pwzExists, hr, E_INVALIDARG, "Invalid web address. Port was not separated by a colon.");
-                                *pwzExists = L'\0';
-                                int iPortExists = wcstol(pwzPortExists, NULL, 10);
-
-                                LPCWSTR pwzHeaderExists = pwzExists + 1;
-
-                                // compare the passed in address with the address listed for this web
-                                if ((0 == lstrcmpW(wzIP, pwzIPExists) || 0 == lstrcmpW(wzIP, L"*")) &&
-                                    iPort == iPortExists &&
-                                    0 == lstrcmpW(wzHeader, pwzHeaderExists))
-                                {
-                                    wzFoundKey = wzKey;
-                                    break;
-                                }
-
-                                // move to the next block of data, this may move beyond the available
-                                // data and exit the while loop above.
-                                pwzExists = const_cast<LPWSTR>(pwzHeaderExists + lstrlenW(pwzHeaderExists) + 1);
-                            }
-                        }
-                        else
-                        {
-                            if (0 == lstrcmpW(wzDescription, pwzExists))
-                            {
-                                wzFoundKey = wzKey;
-                            }
-                        }
-
-                        // If we found the key we were looking for, no point in continuing to search.
-                        if (wzFoundKey)
-                        {
-                            break;
-                        }
-                    }
-                }
-            }
-
-            if (E_NOMOREITEMS == hr)
-            {
-                Assert(!wzFoundKey);
-                hr = S_FALSE;
-            }
-        }
-        else // we're looking a specific SiteId
-        {
-            hr = ::StringCchPrintfW(wzKey, countof(wzKey), L"/LM/W3SVC/%d", iSiteId);
-            ExitOnFailure(hr, "Failed to allocate metabase key string.");
-
-            // if we have an IIsWebServer store the key
-            hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzKey, &mr);
-
-            if (SUCCEEDED(hr) && NULL != mr.pbMDData && 0 == lstrcmpW(L"IIsWebServer", (LPCWSTR)mr.pbMDData))
-            {
-                wzFoundKey = wzKey;
-            }
-            else if (MD_ERROR_DATA_NOT_FOUND == hr || NULL == mrCompare.pbMDData || NULL == mr.pbMDData)
-            {
-                hr = S_FALSE;
-            }
-        }
-    }
-
-    if (wzFoundKey)
-    {
-        Assert(S_OK == hr);
-
-        hr = ::StringCchCopyW(wzWebBase, cchWebBase, wzFoundKey);
-        ExitOnFailure(hr, "Buffer not larger enough for found base key.");
-    }
-
-LExit:
-    MetaFreeValue(&mr);
-    MetaFreeValue(&mrCompare);
-
-    if (!wzFoundKey && SUCCEEDED(hr))
-    {
-        hr = S_FALSE;
-    }
-
-    return hr;
-}
-
-
-static HRESULT ScaWebFindFreeBase(
-    __in IMSAdminBase* piMetabase,
-    __in_xcount(unknown) SCA_WEB* pswList,
-    __in int iSiteId,
-    __in_z LPCWSTR wzDescription,
-    __out_ecount(cchWebBase) LPWSTR wzWebBase,
-    __in DWORD cchWebBase
-    )
-{
-    Assert(piMetabase);
-
-    HRESULT hr = S_OK;
-
-    WCHAR wzKey[METADATA_MAX_NAME_LEN];
-    WCHAR wzSubkey[METADATA_MAX_NAME_LEN];
-    DWORD* prgdwSubKeys = NULL;
-    DWORD cSubKeys = 128;
-    DWORD cSubKeysFilled = 0;
-
-    DWORD dwKey;
-
-    METADATA_RECORD mr;
-    ::ZeroMemory(&mr, sizeof(METADATA_RECORD));
-    mr.dwMDIdentifier = MD_KEY_TYPE;
-    mr.dwMDAttributes = 0;
-    mr.dwMDUserType = IIS_MD_UT_SERVER;
-    mr.dwMDDataType = STRING_METADATA;
-    mr.dwMDDataLen = 0;
-    mr.pbMDData = NULL;
-
-    if (MSI_NULL_INTEGER == iSiteId || -1 == iSiteId)
-    {
-        prgdwSubKeys = static_cast<DWORD*>(MemAlloc(cSubKeys * sizeof(DWORD), TRUE));
-        ExitOnNull(prgdwSubKeys, hr, E_OUTOFMEMORY, "failed to allocate space for web site keys");
-
-        // loop through the "web keys" looking for the "IIsWebServer" key that matches wzWeb
-        for (DWORD dwIndex = 0; SUCCEEDED(hr); ++dwIndex)
-        {
-            hr = piMetabase->EnumKeys(METADATA_MASTER_ROOT_HANDLE, L"/LM/W3SVC", wzSubkey, dwIndex);
-            if (SUCCEEDED(hr))
-            {
-                hr = ::StringCchPrintfW(wzKey, countof(wzKey), L"/LM/W3SVC/%s", wzSubkey);
-                ExitOnFailure(hr, "Failed remember key.");
-
-                hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzKey, &mr);
-                if (MD_ERROR_DATA_NOT_FOUND == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
-                {
-                    hr = S_FALSE;  // didn't find anything, try next one
-                    continue;
-                }
-                ExitOnFailure(hr, "Failed to get key from metabase while searching for free web root");
-
-                // if we have a IIsWebServer get the address information
-                if (0 == lstrcmpW(L"IIsWebServer", (LPCWSTR)mr.pbMDData))
-                {
-                    if (cSubKeysFilled >= cSubKeys)
-                    {
-                        cSubKeys = cSubKeys * 2;
-                        prgdwSubKeys = static_cast<DWORD*>(MemReAlloc(prgdwSubKeys, cSubKeys * sizeof(DWORD), FALSE));
-                        ExitOnNull(prgdwSubKeys, hr, E_OUTOFMEMORY, "failed to allocate space for web site keys");
-                    }
-
-                    prgdwSubKeys[cSubKeysFilled] = wcstol(wzSubkey, NULL, 10);
-                    ++cSubKeysFilled;
-                    Sort(prgdwSubKeys, cSubKeysFilled);
-                }
-            }
-        }
-
-        if (E_NOMOREITEMS == hr)
-        {
-            hr = S_OK;
-        }
-        ExitOnFailure(hr, "Failed to find free web root");
-
-        // Add all the webs created in memory.
-        CONST WCHAR *pcchSlash;
-        for (SCA_WEB* psw = pswList; psw; psw = psw->pswNext)
-        {
-            // Don't process webs that don't have a base
-            if (!*psw->wzWebBase)
-            {
-                continue;
-            }
-
-            // find the last slash in the web root because the root # is after it
-            pcchSlash = NULL;
-            for (CONST WCHAR *pcch = psw->wzWebBase; pcch && *pcch; ++pcch)
-            {
-                if (L'/' == *pcch)
-                {
-                    pcchSlash = pcch;
-                }
-            }
-            // In case we don't find a slash, error out
-            ExitOnNull(pcchSlash, hr, E_INVALIDARG, "Failed to find a slash in the web root: %ls", psw->wzWebBase);
-
-            prgdwSubKeys[cSubKeysFilled] = wcstol(pcchSlash + 1, NULL, 10);
-            ++cSubKeysFilled;
-            Sort(prgdwSubKeys, cSubKeysFilled);
-
-            if (cSubKeysFilled >= cSubKeys)
-            {
-                cSubKeys = cSubKeys * 2;
-                prgdwSubKeys = static_cast<DWORD*>(MemReAlloc(prgdwSubKeys, cSubKeys * sizeof(DWORD), FALSE));
-                ExitOnNull(prgdwSubKeys, hr, E_OUTOFMEMORY, "failed to allocate space for web site keys");
-            }
-        }
-
-        // Find the lowest free web root.
-        dwKey = (-1 == iSiteId) ? SiteIdFromDescription(wzDescription) : 1;
-        for (DWORD i = 0; i < cSubKeysFilled; ++i)
-        {
-            if (dwKey == prgdwSubKeys[i])
-            {
-                ++dwKey;
-            }
-            else if (dwKey < prgdwSubKeys[i])
-            {
-                break;
-            }
-        }
-    }
-    else
-    {
-        dwKey = iSiteId;
-    }
-
-    hr = ::StringCchPrintfW(wzWebBase, cchWebBase, L"/LM/W3SVC/%u", dwKey);
-    ExitOnFailure(hr, "failed to format web base with key: %u", dwKey);
-
-LExit:
-    MetaFreeValue(&mr);
-
-    if (prgdwSubKeys)
-    {
-        MemFree(prgdwSubKeys);
-    }
-
-    return hr;
-}
-
-
-static HRESULT ScaWebWrite(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_WEB* psw,
-    __in SCA_APPPOOL * psapList)
-{
-    HRESULT hr = S_OK;
-
-    UINT ui = 0;
-    WCHAR wzIP[64];
-    WCHAR wzBindings[1024];
-    WCHAR wzSecureBindings[1024];
-    WCHAR* pcchNext;        // used to properly create the MULTI_SZ
-    DWORD cchPcchNext;
-    WCHAR* pcchSecureNext ; // used to properly create the MULTI_SZ
-    DWORD cchPcchSecureNext;
-
-    // if the web root doesn't exist create it
-    if (!psw->fBaseExists)
-    {
-        hr = ScaCreateWeb(piMetabase, psw->wzKey, psw->wzWebBase);
-        ExitOnFailure(hr, "Failed to create web");
-    }
-    else if (psw->iAttributes & SWATTRIB_NOCONFIGUREIFEXISTS) // if we're not supposed to configure existing webs, bail
-    {
-        Assert(psw->fBaseExists);
-
-        hr = S_FALSE;
-        WcaLog(LOGMSG_VERBOSE, "Skipping configuration of existing web: %ls", psw->wzKey);
-        ExitFunction();
-    }
-
-    // put the secure and non-secure bindings together as MULTI_SZs
-    ::ZeroMemory(wzBindings, sizeof(wzBindings));
-    pcchNext = wzBindings;
-    cchPcchNext = countof(wzBindings);
-    ::ZeroMemory(wzSecureBindings, sizeof(wzSecureBindings));
-    pcchSecureNext = wzSecureBindings;
-    cchPcchSecureNext = countof(wzSecureBindings);
-
-    // set the IP address appropriately
-    if (0 == lstrcmpW(psw->swaKey.wzIP, L"*"))
-    {
-        ::ZeroMemory(wzIP, sizeof(wzIP));
-    }
-    else
-    {
-        hr = ::StringCchCopyW(wzIP, countof(wzIP), psw->swaKey.wzIP);
-        ExitOnFailure(hr, "Failed to copy IP string");
-    }
-
-    WCHAR wzBinding[256];
-    hr = ::StringCchPrintfW(wzBinding, countof(wzBinding), L"%s:%d:%s", wzIP, psw->swaKey.iPort, psw->swaKey.wzHeader);
-    ExitOnFailure(hr, "Failed to format IP:Port:Header binding string");
-    if (psw->swaKey.fSecure)
-    {
-        hr = ::StringCchCopyW(pcchSecureNext, cchPcchSecureNext, wzBinding);
-        ExitOnFailure(hr, "Failed to copy binding string to securenext string");
-        pcchSecureNext += lstrlenW(wzBinding) + 1;
-        cchPcchSecureNext -= lstrlenW(wzBinding) + 1;
-    }
-    else
-    {
-        hr = ::StringCchCopyW(pcchNext, cchPcchNext, wzBinding);
-        ExitOnFailure(hr, "Failed to copy binding string to next string");
-        pcchNext += lstrlenW(wzBinding) + 1;
-        cchPcchNext -= lstrlenW(wzBinding) + 1;
-    }
-
-    for (ui = 0; ui < psw->cExtraAddresses; ++ui)
-    {
-        // set the IP address appropriately
-        if (0 == lstrcmpW(psw->swaExtraAddresses[ui].wzIP, L"*"))
-        {
-            ::ZeroMemory(wzIP, sizeof(wzIP));
-        }
-        else
-        {
-            hr = ::StringCchCopyW(wzIP, countof(wzIP), psw->swaExtraAddresses[ui].wzIP);
-            ExitOnFailure(hr, "Failed to copy extra addresses IP to IP string");
-        }
-
-        hr = ::StringCchPrintfW(wzBinding, countof(wzBinding), L"%s:%d:%s", wzIP, psw->swaExtraAddresses[ui].iPort, psw->swaExtraAddresses[ui].wzHeader);
-        ExitOnFailure(hr, "Failed to format IP:Port:Header binding string for extra address");
-        if (psw->swaExtraAddresses[ui].fSecure)
-        {
-            hr = ::StringCchCopyW(pcchSecureNext, cchPcchSecureNext, wzBinding);
-            ExitOnFailure(hr, "Failed to copy binding string to securenext string for extra address");
-            pcchSecureNext += lstrlenW(wzBinding) + 1;
-            cchPcchSecureNext -= lstrlenW(wzBinding) + 1;
-        }
-        else
-        {
-            hr = ::StringCchCopyW(pcchNext, cchPcchNext, wzBinding);
-            ExitOnFailure(hr, "Failed to copy binding string to next string for extra address");
-            pcchNext += lstrlenW(wzBinding) + 1;
-            cchPcchNext -= lstrlenW(wzBinding) + 1;
-        }
-    }
-
-    // Delete the existing secure bindings metabase value, as having one while SSLCertHash and SSLStoreName aren't both set correctly can result in
-    // 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
-    // allows the two aforementioned properties to exist in an intermediate state without errors
-    hr = ScaDeleteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SECURE_BINDINGS, MULTISZ_METADATA);
-    ExitOnFailure(hr, "Failed to temporarily delete secure bindings for Web");
-
-    // now write the bindings to the metabase
-    hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SERVER_BINDINGS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, MULTISZ_METADATA, wzBindings);
-    ExitOnFailure(hr, "Failed to write server bindings for Web");
-
-    // write the target path for the web's directory to the metabase
-    hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"/Root", MD_VR_PATH, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, psw->wzDirectory);
-    ExitOnFailure(hr, "Failed to write virtual root path for Web");
-
-    // write the description for the web to the metabase
-    hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SERVER_COMMENT, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, psw->wzDescription);
-    ExitOnFailure(hr, "Failed to write description for Web");
-
-    ui = psw->iConnectionTimeout;
-    if (MSI_NULL_INTEGER != ui)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_CONNECTION_TIMEOUT, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)ui));
-        ExitOnFailure(hr, "Failed to write connection timeout for Web");
-    }
-
-    ui = psw->iState;
-    if (MSI_NULL_INTEGER != ui)
-    {
-        if (2 == ui)
-        {
-            ui = 1;
-            hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SERVER_AUTOSTART, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)ui));
-            ExitOnFailure(hr, "Failed to write auto start flag for Web");
-            ui = 2;
-        }
-
-        if (1 == ui || 2 == ui)
-        {
-            ui = 1; // start command
-            hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SERVER_COMMAND, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)ui));
-            ExitOnFailure(hr, "Failed to start Web");
-        }
-        else if (0 == ui)
-        {
-            ui = 2; // stop command
-            hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SERVER_COMMAND, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)ui));
-            ExitOnFailure(hr, "Failed to stop Web");
-        }
-        else
-        {
-            hr = E_UNEXPECTED;
-            ExitOnFailure(hr, "Unexpected value for Web State");
-        }
-    }
-
-    WCHAR wzRootOfWeb[METADATA_MAX_NAME_LEN];
-    hr = ::StringCchPrintfW(wzRootOfWeb, countof(wzRootOfWeb), L"%s/Root", psw->wzWebBase);
-    ExitOnFailure(hr, "Failed to allocate WebBase/Root string for root of web");
-
-    // write the web dirproperties information
-    if (psw->fHasProperties)
-    {
-        hr = ScaWriteWebDirProperties(piMetabase, wzRootOfWeb, &psw->swp);
-        ExitOnFailure(hr, "Failed to write web security information to metabase");
-    }
-
-    // write the application information
-    if (psw->fHasApplication)
-    {
-        // On reinstall, we have to uninstall the old application, otherwise a duplicate will be created
-        if (WcaIsReInstalling(psw->isInstalled, psw->isAction))
-        {
-            hr = ScaDeleteApp(piMetabase, wzRootOfWeb);
-            ExitOnFailure(hr, "Failed to remove application for WebDir as part of a reinstall");
-        }
-
-        hr = ScaWriteWebApplication(piMetabase, wzRootOfWeb, &psw->swapp, psapList);
-        ExitOnFailure(hr, "Failed to write web application information to metabase");
-    }
-
-    // write the SSL certificate information
-    if (psw->pswscList)
-    {
-        hr = ScaSslCertificateWriteMetabase(piMetabase, psw->wzWebBase, psw->pswscList);
-        ExitOnFailure(hr, "Failed to write SSL certificates for Web site: %ls", psw->wzKey);
-    }
-
-    hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SECURE_BINDINGS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, MULTISZ_METADATA, wzSecureBindings);
-    ExitOnFailure(hr, "Failed to write secure bindings for Web");
-
-    // write the headers
-    if (psw->pshhList)
-    {
-        hr = ScaWriteHttpHeader(piMetabase, wzRootOfWeb, psw->pshhList);
-        ExitOnFailure(hr, "Failed to write custom HTTP headers for Web site: %ls", psw->wzKey);
-    }
-
-    // write the errors
-    if (psw->psweList)
-    {
-        hr = ScaWriteWebError(piMetabase, weptWeb, psw->wzWebBase, psw->psweList);
-        ExitOnFailure(hr, "Failed to write custom web errors for Web site: %ls", psw->wzKey);
-    }
-
-    // write the mimetypes
-    if (psw->psmm)
-    {
-        hr = ScaWriteMimeMap(piMetabase, wzRootOfWeb, psw->psmm);
-        ExitOnFailure(hr, "Failed to write mimemap for Web site: %ls", psw->wzKey);
-    }
-
-    // write the log information to the metabase
-    if (psw->fHasLog)
-    {
-        hr = ScaWriteWebLog(piMetabase, psw->wzWebBase, &psw->swl);
-        ExitOnFailure(hr, "Failed to write web log information to metabase");
-    }
-
-LExit:
-    return hr;
-}
-
-
-static HRESULT ScaWebRemove(
-    __in IMSAdminBase* piMetabase,
-    __in const SCA_WEB* psw
-    )
-{
-    HRESULT hr = S_OK;
-
-    // simply remove the root key and everything else is pulled at the same time
-    hr = ScaDeleteMetabaseKey(piMetabase, psw->wzWebBase, L"");
-    ExitOnFailure(hr, "Failed to remove web '%ls' from metabase", psw->wzKey);
-
-LExit:
-    return hr;
-}
-
-
-static DWORD SiteIdFromDescription(
-    __in_z LPCWSTR wzDescription
-    )
-{
-    LPCWSTR pwz = wzDescription;
-    DWORD dwSiteId = 0;
-    while (pwz && *pwz)
-    {
-        WCHAR ch = *pwz & 0xdf;
-        dwSiteId = (dwSiteId * 101) + ch;
-        ++pwz;
-    }
-
-    return (dwSiteId % INT_MAX) + 1;
-}
-
-
-// insertion sort
-static void Sort(
-    __in_ecount(cArray) DWORD dwArray[],
-    __in int cArray
-    )
-{
-    int i, j;
-    DWORD dwData;
-
-    for (i = 1; i < cArray; ++i)
-    {
-        dwData = dwArray[i];
-
-        j = i - 1;
-        while (0 <= j && dwArray[j] > dwData)
-        {
-            dwArray[j + 1] = dwArray[j];
-            j--;
-        }
-
-        dwArray[j + 1] = dwData;
-    }
-}
diff --git a/src/ca/scaweb.h b/src/ca/scaweb.h
deleted file mode 100644
index 294030b4..00000000
--- a/src/ca/scaweb.h
+++ /dev/null
@@ -1,123 +0,0 @@
-#pragma once
-// 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.
-
-
-#include "scawebapp.h"
-#include "scawebprop.h"
-#include "scahttpheader.h"
-#include "scaweberr.h"
-#include "scassl.h"
-#include "scaapppool.h"
-#include "scaweblog.h"
-#include "scamimemap.h"
-
-// globals
-#define MAX_ADDRESSES_PER_WEB 10
-
-enum eWebQuery { wqWeb = 1, wqComponent, wqId, wqDescription, wqConnectionTimeout, wqDirectory,
-                 wqState, wqAttributes, wqProperties, wqApplication, wqAddress, wqIP, wqPort, wqHeader, wqSecure, wqLog, wqInstalled, wqAction, wqSourcePath, wqTargetPath};
-
-enum eWebAddressQuery { waqAddress = 1, waqWeb, waqIP, waqPort, waqHeader, waqSecure };
-
-enum SCA_WEB_ATTRIBUTES
-{
-    SWATTRIB_NOCONFIGUREIFEXISTS = 2
-};
-
-// structs
-struct SCA_WEB_ADDRESS
-{
-    WCHAR wzKey [MAX_DARWIN_KEY + 1];
-
-    WCHAR wzIP[MAX_DARWIN_COLUMN + 1];
-    int iPort;
-    WCHAR wzHeader[MAX_DARWIN_COLUMN + 1];
-    BOOL fSecure;
-};
-
-struct SCA_WEB
-{
-    // darwin information
-    WCHAR wzKey[MAX_DARWIN_KEY + 1];
-    WCHAR wzComponent[MAX_DARWIN_KEY + 1];
-    BOOL fHasComponent;
-    INSTALLSTATE isInstalled;
-    INSTALLSTATE isAction;
-
-    // metabase information
-    WCHAR wzWebBase[METADATA_MAX_NAME_LEN + 1];
-    BOOL fBaseExists;
-
-    // iis configuation information
-    SCA_WEB_ADDRESS swaKey;
-
-    SCA_WEB_ADDRESS swaExtraAddresses[MAX_ADDRESSES_PER_WEB + 1];
-    DWORD cExtraAddresses;
-
-    WCHAR wzDirectory[MAX_PATH];
-    WCHAR wzDescription[MAX_DARWIN_COLUMN + 1];
-
-    int iState;
-    int iAttributes;
-
-    BOOL fHasProperties;
-    SCA_WEB_PROPERTIES swp;
-
-    BOOL fHasApplication;
-    SCA_WEB_APPLICATION swapp;
-
-    BOOL fHasSecurity;
-    int dwAccessPermissions;
-    int iConnectionTimeout;
-
-    SCA_MIMEMAP* psmm; // mime mappings
-    SCA_WEB_SSL_CERTIFICATE* pswscList;
-    SCA_HTTP_HEADER* pshhList;
-    SCA_WEB_ERROR* psweList;
-
-    BOOL fHasLog;
-    SCA_WEB_LOG swl;
-
-    SCA_WEB* pswNext;
-};
-
-
-// prototypes
-HRESULT ScaWebsRead(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_MIMEMAP** ppsmmList,
-    __in SCA_WEB** ppswList,
-    __in SCA_HTTP_HEADER** pshhList,
-    __in SCA_WEB_ERROR** psweList,
-    __in WCA_WRAPQUERY_HANDLE hUserQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
-    __in WCA_WRAPQUERY_HANDLE hSslCertQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebLogQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
-    __inout LPWSTR *ppwzCustomActionData
-    );
-
-HRESULT ScaWebsGetBase(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_WEB* pswList,
-    __in LPCWSTR wzWeb,
-    __out_ecount(cchWebBase) LPWSTR wzWebBase,
-    __in DWORD cchWebBase,
-    __in WCA_WRAPQUERY_HANDLE hWrapQuery
-    );
-
-HRESULT ScaWebsInstall(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_WEB* pswList,
-    __in SCA_APPPOOL * psapList
-    );
-
-HRESULT ScaWebsUninstall(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_WEB* pswList
-    );
-
-void ScaWebsFreeList(
-    __in SCA_WEB* pswHead
-    );
diff --git a/src/ca/scaweb7.cpp b/src/ca/scaweb7.cpp
deleted file mode 100644
index 3ee781f2..00000000
--- a/src/ca/scaweb7.cpp
+++ /dev/null
@@ -1,953 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-//Adding this because delivery doesn't have the updated specstrings.h that windows build does
-#ifndef __in_xcount
-#define __in_xcount(size)
-#endif
-
-// prototypes for private helper functions
-static SCA_WEB7* NewWeb7();
-static SCA_WEB7* AddWebToList7(
-    __in SCA_WEB7* pswList,
-    __in SCA_WEB7* psw
-    );
-
-static HRESULT ScaWebFindBase7(
-    __in SCA_WEB7* pswList,
-    LPCWSTR wzDescription
-    );
-
-static HRESULT ScaWebWrite7(
-    __in SCA_WEB7* psw,
-    __in SCA_APPPOOL * psapList
-    );
-
-static HRESULT ScaWebRemove7(__in const SCA_WEB7* psw);
-
-
-HRESULT ScaWebsRead7(
-    __in SCA_WEB7** ppswList,
-    __in SCA_HTTP_HEADER** ppshhList,
-    __in SCA_WEB_ERROR** ppsweList,
-    __in WCA_WRAPQUERY_HANDLE hUserQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
-    __in WCA_WRAPQUERY_HANDLE hSslCertQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebLogQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
-    __inout LPWSTR *ppwzCustomActionData
-    )
-{
-    Assert(ppswList);
-    WcaLog(LOGMSG_VERBOSE, "Entering ScaWebsRead7()");
-
-    HRESULT hr = S_OK;
-
-    MSIHANDLE hRec;
-    MSIHANDLE hRecAddresses;
-
-    WCA_WRAPQUERY_HANDLE hQueryWebSite = NULL;
-    WCA_WRAPQUERY_HANDLE hQueryWebAddress = NULL;
-
-    SCA_WEB7* psw = NULL;
-    LPWSTR pwzData = NULL;
-
-    DWORD dwLen = 0;
-    errno_t error = EINVAL;
-
-    // check to see what tables are available
-    hr = WcaBeginUnwrapQuery(&hQueryWebSite, ppwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap query for ScaWebsRead");
-
-    hr = WcaBeginUnwrapQuery(&hQueryWebAddress, ppwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap query for ScaWebsRead");
-
-
-    if (0 == WcaGetQueryRecords(hQueryWebSite) || 0 == WcaGetQueryRecords(hQueryWebAddress))
-    {
-        WcaLog(LOGMSG_VERBOSE, "Required tables not present");
-        ExitFunction1(hr = S_FALSE);
-    }
-
-    // loop through all the webs
-    while (S_OK == (hr = WcaFetchWrappedRecord(hQueryWebSite, &hRec)))
-    {
-        psw = NewWeb7();
-        if (!psw)
-        {
-            hr = E_OUTOFMEMORY;
-            break;
-        }
-
-        // get the darwin information
-        hr = WcaGetRecordString(hRec, wqWeb, &pwzData);
-        ExitOnFailure(hr, "Failed to get Web");
-        hr = ::StringCchCopyW(psw->wzKey, countof(psw->wzKey), pwzData);
-        ExitOnFailure(hr, "Failed to copy key string to web object");
-
-        // get component install state
-        hr = WcaGetRecordString(hRec, wqComponent, &pwzData);
-        ExitOnFailure(hr, "Failed to get Component for Web");
-        hr = ::StringCchCopyW(psw->wzComponent, countof(psw->wzComponent), pwzData);
-        ExitOnFailure(hr, "Failed to copy component string to web object");
-        if (*(psw->wzComponent))
-        {
-            psw->fHasComponent = TRUE;
-
-            hr = WcaGetRecordInteger(hRec, wqInstalled, (int *)&psw->isInstalled);
-            ExitOnFailure(hr, "Failed to get web Component's installed state");
-
-            WcaGetRecordInteger(hRec, wqAction, (int *)&psw->isAction);
-            ExitOnFailure(hr, "Failed to get web Component's action state");
-        }
-
-        // Get the web's description.
-        hr = WcaGetRecordString(hRec, wqDescription, &pwzData);
-        ExitOnFailure(hr, "Failed to get Description for Web");
-        hr = ::StringCchCopyW(psw->wzDescription, countof(psw->wzDescription), pwzData);
-        ExitOnFailure(hr, "Failed to copy description string to web object");
-
-        //get web's site Id
-        hr = WcaGetRecordInteger(hRec, wqId, &psw->iSiteId);
-        ExitOnFailure(hr, "Failed to get SiteId for Web");
-
-        // get the web's key address (Bindings)
-        hr = WcaGetRecordString(hRec, wqAddress, &pwzData);
-        ExitOnFailure(hr, "Failed to get Address for Web");
-        hr = ::StringCchCopyW(psw->swaBinding.wzKey, countof(psw->swaBinding.wzKey), pwzData);
-        ExitOnFailure(hr, "Failed to copy web binding key");
-
-        hr = WcaGetRecordString(hRec, wqIP, &pwzData);
-        ExitOnFailure(hr, "Failed to get IP for Web");
-        hr = ::StringCchCopyW(psw->swaBinding.wzIP, countof(psw->swaBinding.wzIP), pwzData);
-        ExitOnFailure(hr, "Failed to copy web IP");
-
-        hr = WcaGetRecordString(hRec, wqPort, &pwzData);
-        ExitOnFailure(hr, "Failed to get Web Address port");
-        psw->swaBinding.iPort = wcstol(pwzData, NULL, 10);
-
-        hr = WcaGetRecordString(hRec, wqHeader, &pwzData);
-        ExitOnFailure(hr, "Failed to get Header for Web");
-        hr = ::StringCchCopyW(psw->swaBinding.wzHeader, countof(psw->swaBinding.wzHeader), pwzData);
-        ExitOnFailure(hr, "Failed to copy web header");
-
-        hr = WcaGetRecordInteger(hRec, wqSecure, &psw->swaBinding.fSecure);
-        ExitOnFailure(hr, "Failed to get if Web is secure");
-        if (S_FALSE == hr)
-        {
-            psw->swaBinding.fSecure = FALSE;
-        }
-
-        // look to see if site exists
-        dwLen = METADATA_MAX_NAME_LEN;
-        hr = ScaWebFindBase7(*ppswList, psw->wzDescription);
-
-        // If we didn't find a web in memory, ignore it - during execute CA
-        // if the site truly does not exist then there will be an error.
-        if (S_OK == hr)
-        {
-            // site exists in config
-            psw->fBaseExists = TRUE;
-        }
-        else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
-        {
-            hr = S_OK;
-
-            // site does not exists in config
-            psw->fBaseExists = FALSE;
-        }
-        ExitOnFailure(hr, "Failed to find web site");
-
-        // get any extra web addresses
-        WcaFetchWrappedReset(hQueryWebAddress);
-
-        while (S_OK == (hr = WcaFetchWrappedRecordWhereString(hQueryWebAddress, 2, psw->wzKey, &hRecAddresses)))
-        {
-            if (MAX_ADDRESSES_PER_WEB <= psw->cExtraAddresses)
-            {
-                hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
-                ExitOnFailure(hr, "Failure to get more extra web addresses, max exceeded.");
-            }
-
-            hr = WcaGetRecordString(hRecAddresses, waqAddress, &pwzData);
-            ExitOnFailure(hr, "Failed to get extra web Address");
-
-            // if this isn't the key address add it
-            if (0 != lstrcmpW(pwzData, psw->swaBinding.wzKey))
-            {
-                hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey,
-                    countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey), pwzData);
-                ExitOnFailure(hr, "Failed to copy web binding key");
-
-                hr = WcaGetRecordString(hRecAddresses, waqIP, &pwzData);
-                ExitOnFailure(hr, "Failed to get extra web IP");
-                hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP), pwzData);
-                ExitOnFailure(hr, "Failed to copy web binding IP");
-
-                hr = WcaGetRecordString(hRecAddresses, waqPort, &pwzData);
-                ExitOnFailure(hr, "Failed to get port for extra web IP");
-                psw->swaExtraAddresses[psw->cExtraAddresses].iPort= wcstol(pwzData, NULL, 10);
-
-                // errno is set to ERANGE if overflow or underflow occurs
-                _get_errno(&error);
-
-                if (ERANGE == error)
-                {
-                    hr = E_INVALIDARG;
-                    ExitOnFailure(hr, "Failed to convert web Port address");
-                }
-
-                hr = WcaGetRecordString(hRecAddresses, waqHeader, &pwzData);
-                ExitOnFailure(hr, "Failed to get header for extra web IP");
-                hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader), pwzData);
-                ExitOnFailure(hr, "Failed to copy web binding header");
-
-                hr = WcaGetRecordInteger(hRecAddresses, waqSecure, &psw->swaExtraAddresses[psw->cExtraAddresses].fSecure);
-                ExitOnFailure(hr, "Failed to get if secure extra web IP");
-                if (S_FALSE == hr)
-                {
-                    psw->swaExtraAddresses[psw->cExtraAddresses].fSecure = FALSE;
-                }
-
-                ++psw->cExtraAddresses;
-            }
-        }
-
-        if (E_NOMOREITEMS == hr)
-        {
-            hr = S_OK;
-        }
-        ExitOnFailure(hr, "Failure occured while getting extra web addresses");
-
-        //
-        // Connection time out
-        //
-        hr = WcaGetRecordInteger(hRec, wqConnectionTimeout, &psw->iConnectionTimeout);
-        ExitOnFailure(hr, "Failed to get connection timeout for Web");
-
-        if (psw->fHasComponent) // If we're installing it, it needs a dir
-        {
-            // get the web's directory
-            if (INSTALLSTATE_SOURCE == psw->isAction)
-            {
-                hr = WcaGetRecordString(hRec, wqSourcePath, &pwzData);
-            }
-            else
-            {
-                hr = WcaGetRecordString(hRec, wqTargetPath, &pwzData);
-            }
-            ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory");
-
-            dwLen = lstrlenW(pwzData);
-            // remove trailing backslash
-            if (dwLen > 0 && pwzData[dwLen-1] == L'\\')
-            {
-                pwzData[dwLen-1] = 0;
-            }
-            hr = ::StringCchCopyW(psw->wzDirectory, countof(psw->wzDirectory), pwzData);
-            ExitOnFailure(hr, "Failed to copy web dir: '%ls'", pwzData);
-
-        }
-
-        hr = WcaGetRecordInteger(hRec, wqState, &psw->iState);
-        ExitOnFailure(hr, "Failed to get state for Web");
-
-        hr = WcaGetRecordInteger(hRec, wqAttributes, &psw->iAttributes);
-        ExitOnFailure(hr, "Failed to get attributes for Web");
-
-        // get the dir properties for this web
-        hr = WcaGetRecordString(hRec, wqProperties, &pwzData);
-        ExitOnFailure(hr, "Failed to get directory properties for Web");
-        if (*pwzData)
-        {
-            hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &psw->swp);
-            ExitOnFailure(hr, "Failed to get directory properties for Web");
-
-            psw->fHasProperties = TRUE;
-        }
-
-        // get the application information for this web
-        hr = WcaGetRecordString(hRec, wqApplication, &pwzData);
-        ExitOnFailure(hr, "Failed to get application identifier for Web");
-        if (*pwzData)
-        {
-            hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &psw->swapp);
-            ExitOnFailure(hr, "Failed to get application for Web");
-
-            psw->fHasApplication = TRUE;
-        }
-
-        // get the SSL certificates
-        hr = ScaSslCertificateRead(psw->wzKey, hSslCertQuery, &(psw->pswscList));
-        ExitOnFailure(hr, "Failed to get SSL Certificates.");
-
-        // get the custom headers
-        if (*ppshhList)
-        {
-            hr = ScaGetHttpHeader(hhptWeb, psw->wzKey, ppshhList, &(psw->pshhList));
-            ExitOnFailure(hr, "Failed to get Custom HTTP Headers");
-        }
-
-        // get the errors
-        if (*ppsweList)
-        {
-            hr = ScaGetWebError(weptWeb, psw->wzKey, ppsweList, &(psw->psweList));
-            ExitOnFailure(hr, "Failed to get Custom Errors");
-        }
-
-        // get the log information for this web
-        hr = WcaGetRecordString(hRec, wqLog, &pwzData);
-        ExitOnFailure(hr, "Failed to get log identifier for Web");
-        if (*pwzData)
-        {
-            hr = ScaGetWebLog7(pwzData, hWebLogQuery, &psw->swl);
-            ExitOnFailure(hr, "Failed to get Log for Web.");
-            psw->fHasLog = TRUE;
-        }
-
-        *ppswList = AddWebToList7(*ppswList, psw);
-        psw = NULL; // set the web NULL so it doesn't accidentally get freed below
-    }
-
-    if (E_NOMOREITEMS == hr)
-    {
-        hr = S_OK;
-    }
-
-LExit:
-    // if anything was left over after an error clean it all up
-    WcaFinishUnwrapQuery(hQueryWebSite);
-    WcaFinishUnwrapQuery(hQueryWebAddress);
-
-    ScaWebsFreeList7(psw);
-
-    ReleaseStr(pwzData);
-    WcaLog(LOGMSG_VERBOSE, "Exiting ScaWebsRead7()");
-
-    return hr;
-}
-
-BOOL CompareBinding(
-    __in IAppHostElement* pBinding,
-    __in LPVOID pContext
-    )
-{
-    BOOL fFound = FALSE;
-    HRESULT hr = S_OK;
-    LPWSTR pwzBindingInfo = NULL;
-    SCA_WEB7* psw = (SCA_WEB7*)pContext;
-
-    hr = Iis7GetPropertyString(pBinding, IIS_CONFIG_BINDINGINFO, &pwzBindingInfo);
-    ExitOnFailure(hr, "Failed to get bindinginfo for binding element");
-
-    LPWSTR pwzExists = pwzBindingInfo;
-    // Break down the address into its constituent parts (IP:Port:Header).
-    // Taken from IIS6 CA code for compatibility
-    while (S_OK == hr && *pwzExists)
-    {
-        LPCWSTR pwzIPExists = pwzExists;
-        pwzExists = const_cast<LPWSTR>(wcsstr(pwzIPExists, L":"));
-        if (NULL == pwzExists)
-        {
-            ExitFunction();
-        }
-        *pwzExists = L'\0';
-
-        LPCWSTR pwzPortExists = pwzExists + 1;
-        pwzExists = const_cast<LPWSTR>(wcsstr(pwzPortExists, L":"));
-        if (NULL == pwzExists)
-        {
-            ExitFunction();
-        }
-        *pwzExists = L'\0';
-        int iPortExists = wcstol(pwzPortExists, NULL, 10);
-
-        LPCWSTR pwzHeaderExists = pwzExists + 1;
-
-        BOOL fIpMatches = (0 == lstrcmpW(psw->swaBinding.wzIP, pwzIPExists));   // Explicit IP match
-        fIpMatches |= (0 == lstrcmpW(psw->swaBinding.wzIP, L"*"));              // Authored * matches any IP
-        fIpMatches |= ('\0' != psw->swaBinding.wzIP) &&                         // Unauthored IP
-                      (0 == lstrcmpW(pwzIPExists, L"*"));                       // matches the All Unassigned IP : '*'
-
-        // compare the passed in address with the address listed for this web
-        if (fIpMatches && psw->swaBinding.iPort == iPortExists &&
-            0 == lstrcmpW(psw->swaBinding.wzHeader, pwzHeaderExists))
-        {
-            fFound = TRUE;
-            break;
-        }
-
-        // move to the next block of data, this may move beyond the available
-        // data and exit the while loop above.
-        pwzExists = const_cast<LPWSTR>(pwzHeaderExists + lstrlenW(pwzHeaderExists));
-    }
-
-LExit:
-    WcaLog(LOGMSG_VERBOSE, "Site with binding %ls %s a match", pwzBindingInfo, fFound ? "is" : "is not");
-    ReleaseNullStr(pwzBindingInfo);
-    return fFound;
-}
-
-BOOL EnumSiteCompareBinding(
-    __in IAppHostElement* pSite,
-    __in LPVOID pContext
-    )
-{
-    BOOL fFound = FALSE;
-    HRESULT hr = S_OK;
-    SCA_WEB7* psw = (SCA_WEB7*)pContext;
-    IAppHostChildElementCollection *pSiteChildren = NULL;
-    IAppHostElement *pBindings = NULL;
-    IAppHostElementCollection *pBindingsCollection = NULL;
-    IAppHostElement *pBinding = NULL;
-    VARIANT vtProp;
-    VariantInit(&vtProp);
-
-    hr = pSite->get_ChildElements(&pSiteChildren);
-    ExitOnFailure(hr, "Failed get site child elements collection");
-
-    vtProp.vt = VT_BSTR;
-    vtProp.bstrVal = ::SysAllocString(IIS_CONFIG_BINDINGS);
-    hr = pSiteChildren->get_Item(vtProp, &pBindings);
-    ExitOnFailure(hr, "Failed get bindings element");
-
-    hr = pBindings->get_Collection(&pBindingsCollection);
-    ExitOnFailure(hr, "Failed get bindings collection");
-
-    WcaLog(LOGMSG_VERBOSE, "Searching for site with binding %ls:%d:%ls", psw->swaBinding.wzIP, psw->swaBinding.iPort, psw->swaBinding.wzHeader);
-
-    hr = Iis7EnumAppHostElements(pBindingsCollection, CompareBinding, psw, &pBinding, NULL);
-    ExitOnFailure(hr, "Failed search bindings collection");
-
-    fFound = NULL != pBinding;
-LExit:
-    VariantClear(&vtProp);
-    ReleaseNullObject(pSiteChildren);
-    ReleaseNullObject(pBindings);
-    ReleaseNullObject(pBindingsCollection);
-    ReleaseNullObject(pBinding);
-    return fFound;
-}
-
-HRESULT ScaWebSearch7(
-    __in SCA_WEB7* psw,
-    __deref_out_z_opt LPWSTR* pswWeb,
-    __out_opt BOOL* pfFound
-    )
-{
-    HRESULT hr = S_OK;
-    BOOL fInitializedCom = FALSE;
-    BSTR bstrSites = NULL;
-    BSTR bstrAppHostRoot = NULL;
-    IAppHostAdminManager *pAdminMgr = NULL;
-    IAppHostElement *pSites = NULL;
-    IAppHostElementCollection *pCollection = NULL;
-    IAppHostElement *pSite = NULL;
-
-    if (NULL != pswWeb)
-    {
-        ReleaseNullStr(*pswWeb);
-    }
-
-    if (NULL != pfFound)
-    {
-        *pfFound = FALSE;
-    }
-
-    hr = ::CoInitialize(NULL);
-    ExitOnFailure(hr, "Failed to initialize COM");
-    fInitializedCom = TRUE;
-
-    hr = CoCreateInstance(__uuidof(AppHostAdminManager), NULL, CLSCTX_INPROC_SERVER, __uuidof(IAppHostAdminManager), reinterpret_cast<void**> (&pAdminMgr));
-    if (REGDB_E_CLASSNOTREG == hr)
-    {
-        WcaLog(LOGMSG_VERBOSE, "AppHostAdminManager was not registered, cannot find site.");
-        hr = S_OK;
-        ExitFunction();
-    }
-    ExitOnFailure(hr, "Failed to CoCreate IAppHostAdminManager");
-
-    bstrSites = ::SysAllocString(IIS_CONFIG_SITES_SECTION);
-    ExitOnNull(bstrSites, hr, E_OUTOFMEMORY, "Failed to allocate sites string.");
-
-    bstrAppHostRoot = ::SysAllocString(IIS_CONFIG_APPHOST_ROOT);
-    ExitOnNull(bstrAppHostRoot, hr, E_OUTOFMEMORY, "Failed to allocate host root string.");
-
-    hr = pAdminMgr->GetAdminSection(bstrSites, bstrAppHostRoot, &pSites);
-    ExitOnFailure(hr, "Failed get sites section");
-    ExitOnNull(pSites, hr, ERROR_FILE_NOT_FOUND, "Failed get sites section object");
-
-    hr = pSites->get_Collection(&pCollection);
-    ExitOnFailure(hr, "Failed get sites collection");
-
-    // not explicitly doing a Description search
-    if (-1 != psw->iSiteId)
-    {
-        if (MSI_NULL_INTEGER == psw->iSiteId)
-        {
-            // Enumerate sites & determine if the binding matches
-            hr = Iis7EnumAppHostElements(pCollection, EnumSiteCompareBinding, psw, &pSite, NULL);
-            ExitOnFailure(hr, "Failed locate site by ID");
-        }
-        else
-        {
-            // Find a site with ID matches
-            hr = Iis7FindAppHostElementInteger(pCollection, IIS_CONFIG_SITE, IIS_CONFIG_ID, psw->iSiteId, &pSite, NULL);
-            ExitOnFailure(hr, "Failed locate site by ID");
-        }
-    }
-
-    if (NULL == pSite)
-    {
-        // Find a site with Name that matches
-        hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_SITE, IIS_CONFIG_NAME, psw->wzDescription, &pSite, NULL);
-        ExitOnFailure(hr, "Failed locate site by ID");
-    }
-
-    if (NULL != pSite)
-    {
-        if (NULL != pfFound)
-        {
-            *pfFound = TRUE;
-        }
-
-        if (NULL != pswWeb)
-        {
-            // We found a site, return its description
-            hr = Iis7GetPropertyString(pSite, IIS_CONFIG_NAME, pswWeb);
-            ExitOnFailure(hr, "Failed get site name");
-        }
-    }
-LExit:
-    ReleaseNullObject(pAdminMgr);
-    ReleaseNullObject(pSites);
-    ReleaseNullObject(pCollection);
-    ReleaseNullObject(pSite);
-    ReleaseBSTR(bstrAppHostRoot);
-    ReleaseBSTR(bstrSites);
-
-    if (fInitializedCom)
-    {
-        ::CoUninitialize();
-    }
-    return hr;
-}
-
-
-HRESULT ScaWebsGetBase7(
-    __in SCA_WEB7* pswList,
-    __in LPCWSTR pswWebKey,
-    __out_ecount(cchDest) LPWSTR pswWeb,
-    __in DWORD_PTR cchDest
-    )
-{
-    HRESULT hr = S_OK;
-    BOOL fFound = FALSE;
-    SCA_WEB7* psw = pswList;
-    LPWSTR wzSiteName = NULL;
-
-    *pswWeb = '/0';
-
-    //looking for psw->wzKey == pswWebKey
-    while(psw)
-    {
-        if (0 == wcscmp(pswWebKey, psw->wzKey))
-        {
-            fFound = TRUE;
-            break;
-        }
-        psw = psw->pswNext;
-    }
-
-    if (!fFound)
-    {
-        ExitFunction1(hr = S_FALSE);
-    }
-
-    // Search if we're not installing the site
-    if (!psw->fHasComponent || (psw->iAttributes & SWATTRIB_NOCONFIGUREIFEXISTS))
-    {
-        // We are not installing this website.  Search for it in IIS config
-        hr = ScaWebSearch7(psw, &wzSiteName, NULL);
-        ExitOnFailure(hr, "Failed to search for Website");
-
-        if (NULL != wzSiteName)
-        {
-            hr = ::StringCchCopyW(pswWeb, cchDest, wzSiteName);
-            ExitOnFailure(hr, "Failed to set Website description for located Website");
-        }
-    }
-
-    if ('/0' == *pswWeb)
-    {
-        WcaLog(LOGMSG_VERBOSE, "Could not find Web: %ls, defaulting to %ls", psw->wzKey, psw->wzDescription);
-        // Default to the provided description, the Exec CA will locate by description
-        hr = ::StringCchCopyW(pswWeb, cchDest, psw->wzDescription);
-        ExitOnFailure(hr, "Failed to set Website description to default");
-    }
-LExit:
-    ReleaseNullStr(wzSiteName);
-    return hr;
-}
-
-HRESULT ScaWebsInstall7(
-    __in SCA_WEB7* pswList,
-    __in SCA_APPPOOL * psapList
-    )
-{
-    HRESULT hr = S_OK;
-    SCA_WEB7* psw = pswList;
-
-    while (psw)
-    {
-        // if we are installing the web site
-        if (psw->fHasComponent && WcaIsInstalling(psw->isInstalled, psw->isAction))
-        {
-            hr = ScaWebWrite7(psw, psapList);
-            ExitOnFailure(hr, "failed to write web '%ls' to metabase", psw->wzKey);
-        }
-
-        psw = psw->pswNext;
-    }
-
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaWebsUninstall7(
-    __in SCA_WEB7* pswList
-    )
-{
-    HRESULT hr = S_OK;
-    SCA_WEB7* psw = pswList;
-
-    while (psw)
-    {
-        if (psw->fHasComponent && WcaIsUninstalling(psw->isInstalled, psw->isAction))
-        {
-            // If someone
-            hr = ScaWebRemove7(psw);
-            ExitOnFailure(hr, "Failed to remove web '%ls' ", psw->wzKey);
-        }
-
-        psw = psw->pswNext;
-    }
-
-LExit:
-    return hr;
-}
-
-
-void ScaWebsFreeList7(__in SCA_WEB7* pswList)
-{
-    SCA_WEB7* pswDelete = pswList;
-    while (pswList)
-    {
-        pswDelete = pswList;
-        pswList = pswList->pswNext;
-
-        // Free the SSL, headers and errors list first
-        ScaSslCertificateFreeList(pswDelete->pswscList);
-        ScaHttpHeaderFreeList(pswDelete->pshhList);
-        ScaWebErrorFreeList(pswDelete->psweList);
-
-        MemFree(pswDelete);
-    }
-}
-
-
-// private helper functions
-
-static SCA_WEB7* NewWeb7()
-{
-    SCA_WEB7* psw = (SCA_WEB7*)MemAlloc(sizeof(SCA_WEB7), TRUE);
-    Assert(psw);
-    return psw;
-}
-
-
-static SCA_WEB7* AddWebToList7(
-    __in SCA_WEB7* pswList,
-    __in SCA_WEB7* psw
-    )
-{
-    if (pswList)
-    {
-        SCA_WEB7* pswTemp = pswList;
-        while (pswTemp->pswNext)
-        {
-            pswTemp = pswTemp->pswNext;
-        }
-
-        pswTemp->pswNext = psw;
-    }
-    else
-    {
-        pswList = psw;
-    }
-
-    return pswList;
-}
-
-
-static HRESULT ScaWebFindBase7(
-    __in SCA_WEB7* pswList,
-    __in_z LPCWSTR wzDescription
-    )
-{
-    HRESULT hr = S_OK;
-    BOOL fFound = FALSE;
-
-    // try to find the web in memory first
-    for (SCA_WEB7* psw = pswList; psw; psw = psw->pswNext)
-    {
-        if (0 == wcscmp(wzDescription, psw->wzDescription))
-        {
-            fFound = TRUE;
-            break;
-        }
-    }
-
-    if (!fFound)
-    {
-        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-    }
-
-    return hr;
-}
-
-
-static HRESULT ScaWebWrite7(
-    __in SCA_WEB7* psw,
-    __in SCA_APPPOOL * psapList
-    )
-{
-    HRESULT hr = S_OK;
-
-    BOOL fExists = FALSE;
-    UINT ui = 0;
-    WCHAR wzIP[64];
-    WCHAR wzBinding[1024];
-    WCHAR wzAppPoolName[MAX_PATH];
-
-    //
-    // determine if site must be new
-    //
-    if (psw->iAttributes & SWATTRIB_NOCONFIGUREIFEXISTS)
-    {
-        // Check if site already exists.
-        hr = ScaWebSearch7(psw, NULL, &fExists);
-        ExitOnFailure(hr, "Failed to search for web: %ls", psw->wzKey);
-
-        if (fExists)
-        {
-            hr = S_FALSE;
-            WcaLog(LOGMSG_VERBOSE, "Skipping configuration of existing web: %ls", psw->wzKey);
-            ExitFunction();
-        }
-    }
-
-    //create a site
-    hr = ScaWriteConfigID(IIS_SITE);
-    ExitOnFailure(hr, "Failed write site ID");
-
-    hr = ScaWriteConfigID(IIS_CREATE);
-    ExitOnFailure(hr, "Failed write site ID create action");
-
-    //Site Name
-    hr = ScaWriteConfigString(psw->wzDescription);                  //Site Name
-    ExitOnFailure(hr, "Failed write site desc");
-
-    //Site Id -- value is MSI_NULL_INTEGER if not set in WIX
-    hr = ScaWriteConfigInteger(psw->iSiteId);                        //SiteID
-    ExitOnFailure(hr, "Failed write site id value");
-
-    //Site Auto Start -- value is MSI_NULL_INTEGER if not set in WIX
-    hr = ScaWriteConfigInteger(psw->iState);                        // serverAutoStart
-    ExitOnFailure(hr, "Failed write site autostart");
-
-    hr = ScaWriteConfigInteger(psw->iConnectionTimeout);            //limits/connectionTimeout
-    ExitOnFailure(hr, "Failed write site timeout");
-
-    //create default application
-    hr = ScaWriteConfigID(IIS_APPLICATION);
-    ExitOnFailure(hr, "Failed write app ID");
-    hr = ScaWriteConfigID(IIS_CREATE);
-    ExitOnFailure(hr, "Failed write app action ID");
-    hr = ScaWriteConfigString(psw->wzDescription);      //site name key
-    ExitOnFailure(hr, "Failed write app desc");
-    hr = ScaWriteConfigString(L"/");                    //  App Path (default)
-    ExitOnFailure(hr, "Failed write app def path /");
-
-    if (psw->fHasApplication && *psw->swapp.wzAppPool)
-    {
-        hr = ScaFindAppPool7(psw->swapp.wzAppPool, wzAppPoolName, countof(wzAppPoolName), psapList);
-        ExitOnFailure(hr, "Failed to read app pool from application");
-
-        hr = ScaWriteConfigString(wzAppPoolName);
-        ExitOnFailure(hr, "Failed write app appPool");
-    }
-    else
-    {
-        hr = ScaWriteConfigString(L"");
-        ExitOnFailure(hr, "Failed write app appPool");
-    }
-
-    //create vdir for default application
-    hr = ScaWriteConfigID(IIS_VDIR);
-    ExitOnFailure(hr, "Failed write vdir ID");
-    hr = ScaWriteConfigID(IIS_CREATE);
-    ExitOnFailure(hr, "Failed write vdir action");
-    hr = ScaWriteConfigString(psw->wzDescription);      //site name key
-    ExitOnFailure(hr, "Failed write vdir desc");
-    hr = ScaWriteConfigString(L"/");                    //vdir path (default)
-    ExitOnFailure(hr, "Failed write vdir app");
-    hr = ScaWriteConfigString(psw->wzDirectory);         //physical dir
-    ExitOnFailure(hr, "Failed write vdir dir");
-
-    //create bindings for site
-    hr = ScaWriteConfigID(IIS_BINDING);
-    ExitOnFailure(hr, "Failed write binding ID");
-    hr = ScaWriteConfigID(IIS_CREATE);
-    ExitOnFailure(hr, "Failed write binding action ID");
-    hr = ScaWriteConfigString(psw->wzDescription);      //site name key
-    ExitOnFailure(hr, "Failed write binding site key");
-
-    if (psw->swaBinding.fSecure)
-    {
-        hr = ScaWriteConfigString(L"https");            // binding protocol
-        ExitOnFailure(hr, "Failed write binding https");
-    }
-    else
-    {
-        hr = ScaWriteConfigString(L"http");             // binding protocol
-        ExitOnFailure(hr, "Failed write binding http");
-    }
-
-    // set the IP address appropriately
-    if (0 == wcscmp(psw->swaBinding.wzIP, L""))
-    {
-        hr = ::StringCchCopyW(wzIP, countof(wzIP), L"*"); // if no IP specified = add *
-    }
-    else
-    {
-#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
-        hr = ::StringCchCopyW(wzIP, countof(wzIP), psw->swaBinding.wzIP); // else leave untouched
-    }
-    ExitOnFailure(hr, "Failed to copy IP string");
-
-    hr = ::StringCchPrintfW(wzBinding, countof(wzBinding), L"%s:%d:%s", wzIP, psw->swaBinding.iPort, psw->swaBinding.wzHeader);
-    ExitOnFailure(hr, "Failed to format IP:Port:Header binding string");
-
-    // write bindings CAData
-    hr = ScaWriteConfigString(wzBinding) ;            //binding info
-    ExitOnFailure(hr, "Failed to create web bindings");
-
-    for (ui = 0; (ui < MAX_ADDRESSES_PER_WEB) && (ui < psw->cExtraAddresses); ++ui)
-    {
-        // set the IP address appropriately
-        if (0 == wcscmp(psw->swaExtraAddresses[ui].wzIP, L""))
-        {
-            hr = ::StringCchCopyW(wzIP, countof(wzIP), L"*"); // if no IP specified = add *
-        }
-        else
-        {
-#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
-            hr = ::StringCchCopyW(wzIP, countof(wzIP), psw->swaExtraAddresses[ui].wzIP); //else leave untouched
-        }
-        ExitOnFailure(hr, "Failed to copy web IP string");
-
-        hr = ::StringCchPrintfW(wzBinding, countof(wzBinding), L"%s:%d:%s", wzIP, psw->swaExtraAddresses[ui].iPort, psw->swaExtraAddresses[ui].wzHeader);
-        ExitOnFailure(hr, "Failed to copy web IP");
-
-        //create bindings for site
-        hr = ScaWriteConfigID(IIS_BINDING);
-        ExitOnFailure(hr, "Failed write binding ID");
-        hr = ScaWriteConfigID(IIS_CREATE);
-        ExitOnFailure(hr, "Failed write binding action");
-        hr = ScaWriteConfigString(psw->wzDescription);      //site name key
-        ExitOnFailure(hr, "Failed write binding web name");
-
-        if (psw->swaExtraAddresses[ui].fSecure)
-        {
-            hr = ScaWriteConfigString(L"https");            // binding protocol
-        }
-        else
-        {
-            hr = ScaWriteConfigString(L"http");             // binding protocol
-        }
-        ExitOnFailure(hr, "Failed write binding http(s)");
-
-        // write bindings CAData
-        hr = ScaWriteConfigString(wzBinding) ;              //binding info
-        ExitOnFailure(hr, "Failed write binding info");
-    }
-
-    // write the web dirproperties information
-    if (psw->fHasProperties)
-    {
-        // dir properties are for the default application of the web
-        // with location '/'
-        hr = ScaWriteWebDirProperties7(psw->wzDescription, L"/", &psw->swp);
-        ExitOnFailure(hr, "Failed to write web security information to metabase");
-    }
-
-    //// write the application information
-    if (psw->fHasApplication)
-    {
-        hr = ScaWriteWebApplication7(psw->wzDescription, L"/", &psw->swapp, psapList);
-        ExitOnFailure(hr, "Failed to write web application information to metabase");
-    }
-
-    // write the SSL certificate information
-    if (psw->pswscList)
-    {
-        hr = ScaSslCertificateWrite7(psw->wzDescription, psw->pswscList);
-        ExitOnFailure(hr, "Failed to write SSL certificates for Web site: %ls", psw->wzKey);
-    }
-
-    // write the headers
-    if (psw->pshhList)
-    {
-        hr = ScaWriteHttpHeader7(psw->wzDescription, L"/", psw->pshhList);
-        ExitOnFailure(hr, "Failed to write custom HTTP headers for Web site: %ls", psw->wzKey);
-    }
-
-    // write the errors
-    if (psw->psweList)
-    {
-        hr = ScaWriteWebError7(psw->wzDescription, L"/", psw->psweList);
-        ExitOnFailure(hr, "Failed to write custom web errors for Web site: %ls", psw->wzKey);
-    }
-
-    // write the log information to the metabase
-    if (psw->fHasLog)
-    {
-        hr = ScaWriteWebLog7(psw->wzDescription, &psw->swl);
-        ExitOnFailure(hr, "Failed to write web log information to metabase");
-    }
-
-LExit:
-    return hr;
-}
-
-
-static HRESULT ScaWebRemove7(
-    __in const SCA_WEB7* psw
-    )
-{
-    HRESULT hr = S_OK;
-
-    hr = ScaWriteConfigID(IIS_SITE);
-    ExitOnFailure(hr, "Failed write site ID");
-    hr = ScaWriteConfigID(IIS_DELETE);
-    ExitOnFailure(hr, "Failed write site action");
-    hr = ScaWriteConfigString(psw->wzDescription);  //Site Name
-    ExitOnFailure(hr, "Failed write site name");
-
-LExit:
-    return hr;
-}
diff --git a/src/ca/scaweb7.h b/src/ca/scaweb7.h
deleted file mode 100644
index 78946756..00000000
--- a/src/ca/scaweb7.h
+++ /dev/null
@@ -1,97 +0,0 @@
-#pragma once
-// 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.
-
-
-#include "scawebapp.h"
-#include "scawebprop.h"
-#include "scahttpheader.h"
-#include "scaweberr.h"
-#include "scassl.h"
-#include "scaapppool.h"
-#include "scaweblog.h"
-
-// globals
-#define MAX_ADDRESSES_PER_WEB 10
-
-// structs
-struct SCA_WEB7
-{
-    // darwin information
-    WCHAR wzKey[MAX_DARWIN_KEY + 1];
-    WCHAR wzComponent[MAX_DARWIN_KEY + 1];
-    BOOL fHasComponent;
-    INSTALLSTATE isInstalled;
-    INSTALLSTATE isAction;
-
-    int iSiteId;
-
-    // metabase information
-    WCHAR wzWebBase[METADATA_MAX_NAME_LEN + 1];
-    BOOL fBaseExists;
-
-    // iis configuation information
-    SCA_WEB_ADDRESS swaBinding;
-
-    SCA_WEB_ADDRESS swaExtraAddresses[MAX_ADDRESSES_PER_WEB + 1];
-    DWORD cExtraAddresses;
-
-    WCHAR wzDirectory[MAX_PATH];
-    WCHAR wzDescription[MAX_DARWIN_COLUMN + 1];
-
-    int iState;
-    int iAttributes;
-
-    BOOL fHasProperties;
-    SCA_WEB_PROPERTIES swp;
-
-    BOOL fHasApplication;
-    SCA_WEB_APPLICATION swapp;
-
-    BOOL fHasSecurity;
-    int dwAccessPermissions;
-    int iConnectionTimeout;
-
-    SCA_WEB_SSL_CERTIFICATE* pswscList;
-    SCA_HTTP_HEADER* pshhList;
-    SCA_WEB_ERROR* psweList;
-
-    BOOL fHasLog;
-    SCA_WEB_LOG swl;
-
-    SCA_WEB7* pswNext;
-};
-
-
-// prototypes
-HRESULT ScaWebsRead7(
-    __in SCA_WEB7** ppswList,
-    __in SCA_HTTP_HEADER** ppshhList,
-    __in SCA_WEB_ERROR** ppsweList,
-    __in WCA_WRAPQUERY_HANDLE hUserQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
-    __in WCA_WRAPQUERY_HANDLE hSslCertQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebLogQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
-    __inout LPWSTR *ppwzCustomActionData
-    );
-
-HRESULT ScaWebsGetBase7(
-    __in SCA_WEB7* pswList,
-    __in LPCWSTR pswWebKey,
-    __out_ecount(cchDest) LPWSTR pswWeb,
-    __in DWORD_PTR cchDest
-    );
-
-HRESULT ScaWebsInstall7(
-    __in SCA_WEB7* pswList,
-    __in SCA_APPPOOL * psapList
-    );
-
-HRESULT ScaWebsUninstall7(
-    __in SCA_WEB7* pswList
-    );
-
-void ScaWebsFreeList7(
-    __in SCA_WEB7* pswHead
-    );
diff --git a/src/ca/scawebapp.cpp b/src/ca/scawebapp.cpp
deleted file mode 100644
index a7e9cf82..00000000
--- a/src/ca/scawebapp.cpp
+++ /dev/null
@@ -1,194 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-// sql queries
-enum eWebApplicationQuery { wappqName = 1, wappqIsolation, wappqAllowSession,
-                            wappqSessionTimeout, wappqBuffer, wappqParentPaths,
-                            wappqDefaultScript, wappqScriptTimeout,
-                            wappqServerDebugging, wappqClientDebugging, wappqAppPool, wappqApplication};
-
-
-HRESULT ScaGetWebApplication(MSIHANDLE /*hViewApplications*/, 
-                             LPCWSTR pwzApplication,
-                             __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
-                             __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
-                             SCA_WEB_APPLICATION* pswapp)
-{
-    HRESULT hr = S_OK;
-
-    MSIHANDLE hRec;
-    LPWSTR pwzData = NULL;
-
-    // Reset back to the first record
-    WcaFetchWrappedReset(hWebAppQuery);
-
-    // get the application information
-    hr = WcaFetchWrappedRecordWhereString(hWebAppQuery, wappqApplication, pwzApplication, &hRec);
-    if (S_OK == hr)
-    {
-        // application name
-        hr = WcaGetRecordString(hRec, wappqName, &pwzData);
-        ExitOnFailure(hr, "Failed to get Name of App");
-        hr = ::StringCchCopyW(pswapp->wzName, countof(pswapp->wzName), pwzData);
-        if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr)
-        {
-            // The application name is sometimes truncated to IIS's supported length, so ignore insufficient buffer errors here
-            WcaLog(LOGMSG_VERBOSE, "Application name \"%ls\" truncated to fit IIS's supported %d-character length", pwzData, MAX_APP_NAME);
-            hr = S_OK;
-        }
-        ExitOnFailure(hr, "Failed to copy name string to webapp object");
-
-        hr = WcaGetRecordInteger(hRec, wappqIsolation, &pswapp->iIsolation);
-        ExitOnFailure(hr, "Failed to get App isolation: '%ls'", pswapp->wzName);
-
-        hr = WcaGetRecordInteger(hRec, wappqAllowSession, &pswapp->fAllowSessionState);
-
-        hr = WcaGetRecordInteger(hRec, wappqSessionTimeout, &pswapp->iSessionTimeout);
-
-        hr = WcaGetRecordInteger(hRec, wappqBuffer, &pswapp->fBuffer);
-
-        hr = WcaGetRecordInteger(hRec, wappqParentPaths, &pswapp->fParentPaths);
-
-        hr = WcaGetRecordString(hRec, wappqDefaultScript, &pwzData);
-        ExitOnFailure(hr, "Failed to get default scripting language for App: '%ls'", pswapp->wzName);
-        hr = ::StringCchCopyW(pswapp->wzDefaultScript, countof(pswapp->wzDefaultScript), pwzData);
-        ExitOnFailure(hr, "Failed to copy default script string to webapp object");
-
-        // asp script timeout
-        hr = WcaGetRecordInteger(hRec, wappqScriptTimeout, &pswapp->iScriptTimeout);
-        ExitOnFailure(hr, "Failed to get scripting timeout for App: '%ls'", pswapp->wzName);
-
-        // asp server-side script debugging
-        hr = WcaGetRecordInteger(hRec, wappqServerDebugging, &pswapp->fServerDebugging);
-
-        // asp client-side script debugging
-        hr = WcaGetRecordInteger(hRec, wappqClientDebugging, &pswapp->fClientDebugging);
-
-        hr = WcaGetRecordString(hRec, wappqAppPool, &pwzData);
-        ExitOnFailure(hr, "Failed to get AppPool for App: '%ls'", pswapp->wzName);
-        hr = ::StringCchCopyW(pswapp->wzAppPool, countof(pswapp->wzAppPool), pwzData);
-        ExitOnFailure(hr, "failed to copy AppPool: '%ls' for App: '%ls'", pwzData, pswapp->wzName);
-
-        // app extensions
-         hr = ScaWebAppExtensionsRead(pwzApplication, hWebAppExtQuery, &pswapp->pswappextList);
-        ExitOnFailure(hr, "Failed to read AppExtensions for App: '%ls'", pswapp->wzName);
-
-        hr = S_OK;
-    }
-    else if (E_NOMOREITEMS == hr)
-    {
-        WcaLog(LOGMSG_STANDARD, "Error: Cannot locate IIsWebApplication.Application='%ls'", pwzApplication);
-        hr = E_FAIL;
-    }
-    else
-        ExitOnFailure(hr, "Error matching Application rows");
-
-    // Let's check that there isn't more than one record found - if there is, throw an assert like WcaFetchSingleRecord() would
-    HRESULT hrTemp = WcaFetchWrappedRecordWhereString(hWebAppQuery, wappqApplication, pwzApplication, &hRec);
-    if (SUCCEEDED(hrTemp))
-    {
-        AssertSz(E_NOMOREITEMS == hrTemp, "ScaGetWebApplication found more than one record");
-    }
-
-LExit:
-    ReleaseStr(pwzData);
-
-    return hr;
-}
-
-
-HRESULT ScaWriteWebApplication(IMSAdminBase* piMetabase, LPCWSTR wzRootOfWeb, 
-                               SCA_WEB_APPLICATION* pswapp, SCA_APPPOOL * psapList)
-{
-    HRESULT hr = S_OK;
-    WCHAR wzAppPoolName[MAX_PATH];
-
-    hr = ScaCreateApp(piMetabase, wzRootOfWeb, pswapp->iIsolation);
-    ExitOnFailure(hr, "Failed to create ASP App");
-
-    // Medium Isolation seems to have to be set through the metabase
-    if (2 == pswapp->iIsolation)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_APP_ISOLATED, METADATA_INHERIT, IIS_MD_UT_WAM, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->iIsolation));
-        ExitOnFailure(hr, "Failed to write isolation value for App: '%ls'", pswapp->wzName);
-    }
-
-    // application name
-    hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_APP_FRIENDLY_NAME, METADATA_INHERIT, IIS_MD_UT_WAM, STRING_METADATA, pswapp->wzName);
-    ExitOnFailure(hr, "Failed to write Name of App: '%ls'", pswapp->wzName);
-
-    // allow session state
-    if (MSI_NULL_INTEGER != pswapp->fAllowSessionState)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_ALLOWSESSIONSTATE, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->fAllowSessionState));
-        ExitOnFailure(hr, "Failed to write allow session information for App: '%ls'", pswapp->wzName);
-    }
-
-    // session timeout
-    if (MSI_NULL_INTEGER != pswapp->iSessionTimeout)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_SESSIONTIMEOUT, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->iSessionTimeout));
-        ExitOnFailure(hr, "Failed to write session timeout for App: '%ls'", pswapp->wzName);
-    }
-
-    // asp buffering
-    if (MSI_NULL_INTEGER != pswapp->fBuffer)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_BUFFERINGON, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->fBuffer));
-        ExitOnFailure(hr, "Failed to write buffering flag for App: '%ls'", pswapp->wzName);
-    }
-
-    // asp parent paths
-    if (MSI_NULL_INTEGER != pswapp->fParentPaths)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_ENABLEPARENTPATHS, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->fParentPaths));
-        ExitOnFailure(hr, "Failed to write parent paths flag for App: '%ls'", pswapp->wzName);
-    }
-
-    // default scripting language
-    if (*pswapp->wzDefaultScript)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_SCRIPTLANGUAGE, METADATA_INHERIT, ASP_MD_UT_APP, STRING_METADATA, pswapp->wzDefaultScript);
-        ExitOnFailure(hr, "Failed to write default scripting language for App: '%ls'", pswapp->wzName);
-    }
-
-    // asp script timeout
-    if (MSI_NULL_INTEGER != pswapp->iScriptTimeout)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_SCRIPTTIMEOUT, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->iScriptTimeout));
-        ExitOnFailure(hr, "Failed to write script timeout for App: '%ls'", pswapp->wzName);
-    }
-
-    // asp server-side script debugging
-    if (MSI_NULL_INTEGER != pswapp->fServerDebugging)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_ENABLESERVERDEBUG, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->fServerDebugging));
-        ExitOnFailure(hr, "Failed to write ASP server-side script debugging flag for App: '%ls'", pswapp->wzName);
-    }
-
-    // asp server-side script debugging
-    if (MSI_NULL_INTEGER != pswapp->fClientDebugging)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_ENABLECLIENTDEBUG, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->fClientDebugging));
-        ExitOnFailure(hr, "Failed to write ASP client-side script debugging flag for App: '%ls'", pswapp->wzName);
-    }
-
-    // AppPool
-    if (*pswapp->wzAppPool && NULL != psapList)
-    {
-        hr = ScaFindAppPool(piMetabase, pswapp->wzAppPool, wzAppPoolName, countof(wzAppPoolName), psapList);
-        ExitOnFailure(hr, "failed to find app pool: %ls", pswapp->wzAppPool);
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_APP_APPPOOL_ID, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, wzAppPoolName);
-        ExitOnFailure(hr, "Failed to write default AppPool for App: '%ls'", pswapp->wzName);
-    }
-
-    if (pswapp->pswappextList)
-    {
-        hr = ScaWebAppExtensionsWrite(piMetabase, wzRootOfWeb, pswapp->pswappextList);
-        ExitOnFailure(hr, "Failed to write AppExtensions for App: '%ls'", pswapp->wzName);
-    }
-
-LExit:
-    return hr;
-}
diff --git a/src/ca/scawebapp.h b/src/ca/scawebapp.h
deleted file mode 100644
index a4152116..00000000
--- a/src/ca/scawebapp.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#pragma once
-// 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.
-
-
-#include "scaapppool.h"
-#include "scawebappext.h"
-
-// global sql queries provided for optimization
-extern LPCWSTR vcsWebApplicationQuery;
-const int MAX_APP_NAME = 255;
-
-// structs
-struct SCA_WEB_APPLICATION
-{
-	WCHAR wzName[MAX_APP_NAME + 1];
-
-	int iIsolation;
-	BOOL fAllowSessionState;
-	int iSessionTimeout;
-	BOOL fBuffer;
-	BOOL fParentPaths;
-
-	WCHAR wzDefaultScript[MAX_DARWIN_COLUMN + 1];
-	int iScriptTimeout;
-	BOOL fServerDebugging;
-	BOOL fClientDebugging;
-	WCHAR wzAppPool[MAX_DARWIN_COLUMN + 1];
-
-	SCA_WEB_APPLICATION_EXTENSION* pswappextList;
-};
-
-
-// prototypes
-HRESULT ScaGetWebApplication(MSIHANDLE hViewApplications, 
-                             LPCWSTR pwzApplication,
-                             __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
-                             __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
-                             SCA_WEB_APPLICATION* pswapp);
-
-HRESULT ScaWriteWebApplication(IMSAdminBase* piMetabase, LPCWSTR wzRootOfWeb, 
-                               SCA_WEB_APPLICATION* pswapp, SCA_APPPOOL * psapList);
-
diff --git a/src/ca/scawebapp7.cpp b/src/ca/scawebapp7.cpp
deleted file mode 100644
index 94e6bb18..00000000
--- a/src/ca/scawebapp7.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-// 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.
-
-#include "precomp.h"
-HRESULT ScaWriteWebApplication7(
-    __in_z LPCWSTR wzWebName,
-    __in_z LPCWSTR wzRootOfWeb,
-    SCA_WEB_APPLICATION* pswapp,
-    SCA_APPPOOL * /*psapList*/
-    )
-{
-    HRESULT hr = S_OK;
-
-    //all go to same web/root location tag
-    hr = ScaWriteConfigID(IIS_ASP_BEGIN);
-    ExitOnFailure(hr, "Failed to write WebApp ASP begin id");
-    hr = ScaWriteConfigString(wzWebName);                //site name key
-    ExitOnFailure(hr, "Failed to write app web key");
-    hr = ScaWriteConfigString(wzRootOfWeb);               //app path key
-    ExitOnFailure(hr, "Failed to write app web root");
-
-    // IIS7 Not Supported: Isolation
-    if (MSI_NULL_INTEGER != pswapp->iIsolation)
-    {
-        WcaLog(LOGMSG_TRACEONLY, "Not supported by IIS7: Isolation Mode, ignoring");
-    }
-
-    // allow session state
-    if (MSI_NULL_INTEGER != pswapp->fAllowSessionState)
-    {
-        //system.webServer/asp /session | allowSessionState
-        hr = ScaWriteConfigID(IIS_ASP_SESSIONSTATE);
-        ExitOnFailure(hr, "Failed to write WebApp ASP sessionstate id");
-        hr = ScaWriteConfigInteger(pswapp->fAllowSessionState);
-        ExitOnFailure(hr, "Failed to write allow session information for App: '%ls'", pswapp->wzName);
-    }
-
-    // session timeout
-    if (MSI_NULL_INTEGER != pswapp->iSessionTimeout)
-    {
-        //system.webServer/asp /session | timeout
-        hr = ScaWriteConfigID(IIS_ASP_SESSIONTIMEOUT);
-        ExitOnFailure(hr, "Failed to write WebApp ASP sessiontimepot id");
-        hr = ScaWriteConfigInteger(pswapp->iSessionTimeout);
-        ExitOnFailure(hr, "Failed to write session timeout for App: '%ls'", pswapp->wzName);
-    }
-
-    // asp buffering
-    if (MSI_NULL_INTEGER != pswapp->fBuffer)
-    {
-        //system.webServer/asp | bufferingOn
-        hr = ScaWriteConfigID(IIS_ASP_BUFFER);
-        ExitOnFailure(hr, "Failed to write WebApp ASP buffer id");
-        hr = ScaWriteConfigInteger(pswapp->fBuffer);
-        ExitOnFailure(hr, "Failed to write buffering flag for App: '%ls'", pswapp->wzName);
-    }
-
-    // asp parent paths
-    if (MSI_NULL_INTEGER != pswapp->fParentPaths)
-    {
-        //system.webServer/asp | enableParentPaths
-        hr = ScaWriteConfigID(IIS_ASP_PARENTPATHS);
-        ExitOnFailure(hr, "Failed to write WebApp ASP parentpaths id");
-        hr = ScaWriteConfigInteger(pswapp->fParentPaths);
-        ExitOnFailure(hr, "Failed to write parent paths flag for App: '%ls'", pswapp->wzName);
-    }
-
-    // default scripting language
-    if (*pswapp->wzDefaultScript)
-    {
-        //system.webServer/asp | scriptLanguage
-        hr = ScaWriteConfigID(IIS_ASP_SCRIPTLANG);
-        ExitOnFailure(hr, "Failed to write WebApp ASP script lang id");
-        hr = ScaWriteConfigString(pswapp->wzDefaultScript);
-        ExitOnFailure(hr, "Failed to write default scripting language for App: '%ls'", pswapp->wzName);
-    }
-
-    // asp script timeout
-    if (MSI_NULL_INTEGER != pswapp->iScriptTimeout)
-    {
-        //system.webServer/asp /limits | scriptTimeout
-        hr = ScaWriteConfigID(IIS_ASP_SCRIPTTIMEOUT);
-        ExitOnFailure(hr, "Failed to write WebApp ASP script timeout id");
-        hr = ScaWriteConfigInteger(pswapp->iScriptTimeout);
-        ExitOnFailure(hr, "Failed to write script timeout for App: '%ls'", pswapp->wzName);
-    }
-
-    // asp server-side script debugging
-    if (MSI_NULL_INTEGER != pswapp->fServerDebugging)
-    {
-        //system.webServer/asp | appAllowDebugging
-        hr = ScaWriteConfigID(IIS_ASP_SCRIPTSERVERDEBUG);
-        ExitOnFailure(hr, "Failed to write WebApp ASP script debug id");
-        hr = ScaWriteConfigInteger(pswapp->fServerDebugging);
-        ExitOnFailure(hr, "Failed to write ASP server-side script debugging flag for App: '%ls'", pswapp->wzName);
-    }
-
-    // asp client-side script debugging
-    if (MSI_NULL_INTEGER != pswapp->fClientDebugging)
-    {
-        //system.webServer/asp | appAllowClientDebug
-        hr = ScaWriteConfigID(IIS_ASP_SCRIPTCLIENTDEBUG);
-        ExitOnFailure(hr, "Failed to write WebApp ASP script debug id");
-        hr = ScaWriteConfigInteger(pswapp->fClientDebugging);
-        ExitOnFailure(hr, "Failed to write ASP client-side script debugging flag for App: '%ls'", pswapp->wzName);
-    }
-
-    //done with ASP application properties
-    hr = ScaWriteConfigID(IIS_ASP_END);
-    ExitOnFailure(hr, "Failed to write WebApp ASP begin id");
-
-    //write out app estensions
-    if (pswapp->pswappextList)
-    {
-        hr = ScaWebAppExtensionsWrite7(wzWebName, wzRootOfWeb, pswapp->pswappextList);
-        ExitOnFailure(hr, "Failed to write AppExtensions for App: '%ls'", pswapp->wzName);
-    }
-
-LExit:
-    return hr;
-}
diff --git a/src/ca/scawebapp7.h b/src/ca/scawebapp7.h
deleted file mode 100644
index e1d87f53..00000000
--- a/src/ca/scawebapp7.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#pragma once
-// 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.
-
-
-HRESULT ScaWriteWebApplication7(
-    __in_z LPCWSTR wzWebName,
-    __in_z LPCWSTR wzRootOfWeb,
-    SCA_WEB_APPLICATION* pswapp,
-    SCA_APPPOOL * psapList
-    );
diff --git a/src/ca/scawebappext.cpp b/src/ca/scawebappext.cpp
deleted file mode 100644
index cf3b9dd3..00000000
--- a/src/ca/scawebappext.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-enum eWebAppExtensionQuery { wappextqExtension = 1, wappextqVerbs, wappextqExecutable, wappextqAttributes, wappextqApplication };
-
-// prototypes for private helper functions
-static HRESULT NewAppExt(
-    __out SCA_WEB_APPLICATION_EXTENSION** ppswappext
-    );
-static SCA_WEB_APPLICATION_EXTENSION* AddAppExtToList(
-    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList,
-    __in SCA_WEB_APPLICATION_EXTENSION* pswappext
-    );
-
-
-
-HRESULT ScaWebAppExtensionsRead(
-    __in LPCWSTR wzApplication,
-    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
-    __inout SCA_WEB_APPLICATION_EXTENSION** ppswappextList
-    )
-{
-    HRESULT hr = S_OK;
-    MSIHANDLE hRec;
-
-    SCA_WEB_APPLICATION_EXTENSION* pswappext = NULL;
-    LPWSTR pwzData = NULL;
-
-    // Reset back to the first record
-    WcaFetchWrappedReset(hWebAppExtQuery);
-
-    // get the application extension information
-    while (S_OK == (hr = WcaFetchWrappedRecordWhereString(hWebAppExtQuery, wappextqApplication, wzApplication, &hRec)))
-    {
-        hr = NewAppExt(&pswappext);
-        ExitOnFailure(hr, "failed to create new web app extension");
-
-        // get the extension
-        hr = WcaGetRecordString(hRec, wappextqExtension, &pwzData);
-        ExitOnFailure(hr, "Failed to get Web Application Extension");
-        hr = ::StringCchCopyW(pswappext->wzExtension, countof(pswappext->wzExtension), pwzData);
-        ExitOnFailure(hr, "Failed to copy extension string to webappext object");
-
-        // application extension verbs
-        hr = WcaGetRecordString(hRec, wappextqVerbs, &pwzData);
-        ExitOnFailure(hr, "Failed to get Verbs for Application: '%ls'", wzApplication);
-        hr = ::StringCchCopyW(pswappext->wzVerbs, countof(pswappext->wzVerbs), pwzData);
-        ExitOnFailure(hr, "Failed to copy verbs string to webappext object");
-
-        // extension executeable
-        hr = WcaGetRecordString(hRec, wappextqExecutable, &pwzData);
-        ExitOnFailure(hr, "Failed to get Executable for Application: '%ls'", wzApplication);
-        hr = ::StringCchCopyW(pswappext->wzExecutable, countof(pswappext->wzExecutable), pwzData);
-        ExitOnFailure(hr, "Failed to copy executable string to webappext object");
-
-        hr = WcaGetRecordInteger(hRec, wappextqAttributes, &pswappext->iAttributes);
-        if (S_FALSE == hr)
-        {
-            pswappext->iAttributes = 0;
-            hr = S_OK;
-        }
-        ExitOnFailure(hr, "Failed to get App isolation");
-
-        *ppswappextList = AddAppExtToList(*ppswappextList, pswappext);
-        pswappext = NULL; // set the appext NULL so it doesn't accidentally get freed below
-    }
-
-    if (E_NOMOREITEMS == hr)
-    {
-        hr = S_OK;
-    }
-
-LExit:
-    // if anything was left over after an error clean it all up
-    if (pswappext)
-    {
-        ScaWebAppExtensionsFreeList(pswappext);
-    }
-
-    ReleaseStr(pwzData);
-
-    return hr;
-}
-
-
-
-HRESULT ScaWebAppExtensionsWrite(
-    __in IMSAdminBase* piMetabase,
-    __in LPCWSTR wzRootOfWeb,
-    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList
-    )
-{
-    HRESULT hr = S_OK;
-
-    LPWSTR wzAppExt = NULL;
-    DWORD cchAppExt;
-    WCHAR wzAppExtension[1024];
-    WCHAR wzAppExtensions[65536];
-    SCA_WEB_APPLICATION_EXTENSION* pswappext = NULL;
-
-    if (!pswappextList)
-    {
-        ExitFunction();
-    }
-
-    ::ZeroMemory(wzAppExtensions, sizeof(wzAppExtensions));
-    wzAppExt = wzAppExtensions;
-    cchAppExt = countof(wzAppExtensions);
-    pswappext = pswappextList;
-
-    while (pswappext)
-    {
-        // if all (represented by "*" or blank)
-        if (0 == lstrcmpW(pswappext->wzExtension, L"*") || 0 == lstrlenW(pswappext->wzExtension))
-        {
-            hr = ::StringCchPrintfW(wzAppExtension, countof(wzAppExtension), L"*,%s,%d", pswappext->wzExecutable, pswappext->iAttributes);
-            ExitOnFailure(hr, "Failed to format *,executable,attributes string");
-        }
-        else
-        {
-            hr = ::StringCchPrintfW(wzAppExtension, countof(wzAppExtension), L".%s,%s,%d", pswappext->wzExtension, pswappext->wzExecutable, pswappext->iAttributes);
-            ExitOnFailure(hr, "Failed to format extension,executable,attributes string");
-        }
-
-        // if verbs were specified and not the keyword "all"
-        if (pswappext->wzVerbs[0] && CSTR_EQUAL != CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pswappext->wzVerbs, -1, L"all", -1))
-        {
-            hr = ::StringCchCatW(wzAppExtension, countof(wzAppExtension), L",");
-            ExitOnFailure(hr, "Failed to concatenate comma to app extension string");
-            hr = ::StringCchCatW(wzAppExtension, countof(wzAppExtension), pswappext->wzVerbs);
-            ExitOnFailure(hr, "Failed to concatenate verb to app extension string");
-        }
-
-        hr = ::StringCchCopyW(wzAppExt, cchAppExt, wzAppExtension);
-        ExitOnFailure(hr, "Failed to copy app extension string");
-        wzAppExt += lstrlenW(wzAppExtension) + 1;
-        cchAppExt -= lstrlenW(wzAppExtension) + 1;
-        pswappext = pswappext->pswappextNext;
-    }
-
-    if (*wzAppExtensions)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_SCRIPT_MAPS, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, wzAppExtensions);
-        ExitOnFailure(hr, "Failed to write AppExtension: '%ls'", wzAppExtension);
-    }
-
-LExit:
-    return hr;
-}
-
-
-void ScaWebAppExtensionsFreeList(
-    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList
-    )
-{
-    SCA_WEB_APPLICATION_EXTENSION* pswappextDelete = pswappextList;
-    while (pswappextList)
-    {
-        pswappextDelete = pswappextList;
-        pswappextList = pswappextList->pswappextNext;
-
-        MemFree(pswappextDelete);
-    }
-}
-
-
-
-// private helper functions
-
-static HRESULT NewAppExt(
-    __out SCA_WEB_APPLICATION_EXTENSION** ppswappext
-    )
-{
-    HRESULT hr = S_OK;
-    SCA_WEB_APPLICATION_EXTENSION* pswappext = static_cast<SCA_WEB_APPLICATION_EXTENSION*>(MemAlloc(sizeof(SCA_WEB_APPLICATION_EXTENSION), TRUE));
-    ExitOnNull(pswappext, hr, E_OUTOFMEMORY, "failed to allocate memory for new web app ext element");
-
-    *ppswappext = pswappext;
-
-LExit:
-    return hr;
-}
-
-
-static SCA_WEB_APPLICATION_EXTENSION* AddAppExtToList(
-    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList,
-    __in SCA_WEB_APPLICATION_EXTENSION* pswappext
-    )
-{
-    if (pswappextList)
-    {
-        SCA_WEB_APPLICATION_EXTENSION* pswappextT = pswappextList;
-        while (pswappextT->pswappextNext)
-        {
-            pswappextT = pswappextT->pswappextNext;
-        }
-
-        pswappextT->pswappextNext = pswappext;
-    }
-    else
-    {
-        pswappextList = pswappext;
-    }
-
-    return pswappextList;
-}
diff --git a/src/ca/scawebappext.h b/src/ca/scawebappext.h
deleted file mode 100644
index 71adfd00..00000000
--- a/src/ca/scawebappext.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#pragma once
-// 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.
-
-
-struct SCA_WEB_APPLICATION_EXTENSION
-{
-    WCHAR wzExtension[MAX_DARWIN_COLUMN + 1];
-
-    WCHAR wzVerbs[MAX_DARWIN_COLUMN + 1];
-    WCHAR wzExecutable[MAX_DARWIN_COLUMN + 1];
-    int iAttributes;
-
-    SCA_WEB_APPLICATION_EXTENSION* pswappextNext;
-};
-
-
-// prototypes
-HRESULT ScaWebAppExtensionsRead(
-    __in LPCWSTR wzApplication,
-    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
-    __inout SCA_WEB_APPLICATION_EXTENSION** ppswappextList
-    );
-
-HRESULT ScaWebAppExtensionsWrite(
-    __in IMSAdminBase* piMetabase,
-    __in LPCWSTR wzRootOfWeb,
-    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList
-    );
-
-void ScaWebAppExtensionsFreeList(
-    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList
-    );
diff --git a/src/ca/scawebappext7.cpp b/src/ca/scawebappext7.cpp
deleted file mode 100644
index 50d3172f..00000000
--- a/src/ca/scawebappext7.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-HRESULT ScaWebAppExtensionsWrite7(
-    __in_z LPCWSTR wzWebName,
-    __in_z LPCWSTR wzRootOfWeb,
-    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList
-    )
-{
-    HRESULT hr = S_OK;
-    SCA_WEB_APPLICATION_EXTENSION* pswappext = NULL;
-
-    if (!pswappextList)
-    {
-        ExitFunction1(hr = S_OK);
-    }
-
-    //create the Extension for this vdir application
-    //all go to same web/root location tag
-    hr = ScaWriteConfigID(IIS_APPEXT_BEGIN);
-    ExitOnFailure(hr, "Failed to write webappext begin id");
-    hr = ScaWriteConfigString(wzWebName);                //site name key
-    ExitOnFailure(hr, "Failed to write app web key");
-    hr = ScaWriteConfigString(wzRootOfWeb);               //app path key
-    ExitOnFailure(hr, "Failed to write app web key");
-
-    pswappext = pswappextList;
-
-    while (pswappext)
-    {
-        //create the Extension for this vdir application
-        hr = ScaWriteConfigID(IIS_APPEXT);
-        ExitOnFailure(hr, "Failed to write webappext begin id");
-
-        if (*pswappext->wzExtension)
-        {
-            hr = ScaWriteConfigString(pswappext->wzExtension);
-        }
-        else   // blank means "*" (all)
-        {
-            hr = ScaWriteConfigString(L"*");
-        }
-        ExitOnFailure(hr, "Failed to write extension");
-
-        hr = ScaWriteConfigString(pswappext->wzExecutable);
-        ExitOnFailure(hr, "Failed to write extension executable");
-
-        hr = ScaWriteConfigString(pswappext->wzVerbs);
-        ExitOnFailure(hr, "Failed to write extension verbs");
-
-        pswappext = pswappext->pswappextNext;
-    }
-
-    hr = ScaWriteConfigID(IIS_APPEXT_END);
-    ExitOnFailure(hr, "Failed to write webappext begin id");
-
-LExit:
-    return hr;
-}
-
diff --git a/src/ca/scawebappext7.h b/src/ca/scawebappext7.h
deleted file mode 100644
index 55c8b5fc..00000000
--- a/src/ca/scawebappext7.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#pragma once
-// 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.
-
-
-HRESULT ScaWebAppExtensionsWrite7(
-    __in_z LPCWSTR wzWebName,
-    __in_z LPCWSTR wzRootOfWeb,
-    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList
-    );
diff --git a/src/ca/scawebdir.cpp b/src/ca/scawebdir.cpp
deleted file mode 100644
index 26a7b32b..00000000
--- a/src/ca/scawebdir.cpp
+++ /dev/null
@@ -1,241 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-// sql queries
-enum eWebDirQuery { wdqWeb = 1, wdqWebDir, wdqComponent , wdqPath, wdqProperties, wdqApplication, wdqInstalled, wdqAction };
-
-// prototypes
-static void AddWebDirToList(SCA_WEBDIR** ppswdList, SCA_WEBDIR *pswd);
-
-static SCA_WEBDIR* NewWebDir();
-static void FreeWebDir(SCA_WEBDIR *pswd);
-
-
-UINT __stdcall ScaWebDirsRead(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_WEB* pswList,
-    __in WCA_WRAPQUERY_HANDLE hUserQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebBaseQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
-    __inout LPWSTR *ppwzCustomActionData,
-    __out SCA_WEBDIR** ppswdList
-    )
-{
-    Assert(piMetabase && ppswdList);
-
-    HRESULT hr = S_OK;
-    MSIHANDLE hRec;
-
-    LPWSTR pwzData = NULL;
-    SCA_WEBDIR* pswd;
-    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
-
-    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap query for ScaWebDirsRead");
-
-    if (0 == WcaGetQueryRecords(hWrapQuery))
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ScaInstallWebDirs() because IIsWebDir table not present");
-        ExitFunction1(hr = S_FALSE);
-    }
-
-    // loop through all the web directories
-    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
-    {
-        pswd = NewWebDir();
-        ExitOnNull(pswd, hr, E_OUTOFMEMORY, "Failed to allocate memory for web dir object in memory");
-
-        // get component install state
-        hr = WcaGetRecordString(hRec, wdqComponent, &pwzData);
-        ExitOnFailure(hr, "Failed to get Component for WebDirs");
-        hr = ::StringCchCopyW(pswd->wzComponent, countof(pswd->wzComponent), pwzData);
-        ExitOnFailure(hr, "Failed to copy component string to webdir object");
-
-        hr = WcaGetRecordInteger(hRec, wdqInstalled, (int *)&pswd->isInstalled);
-        ExitOnFailure(hr, "Failed to get Component installed state for webdir");
-
-        hr = WcaGetRecordInteger(hRec, wdqAction, (int *)&pswd->isAction);
-        ExitOnFailure(hr, "Failed to get Component action state for webdir");
-
-        // If this record has a component and no action is being taken for it, skip processing it entirely
-        if (0 < lstrlenW(pswd->wzComponent) && !WcaIsInstalling(pswd->isInstalled, pswd->isAction)
-            && !WcaIsUninstalling(pswd->isInstalled, pswd->isAction) && !WcaIsReInstalling(pswd->isInstalled, pswd->isAction))
-        {
-            FreeWebDir(pswd);
-            pswd = NULL;
-            continue;
-        }
-
-        hr = WcaGetRecordString(hRec, wdqWeb, &pwzData);
-        ExitOnFailure(hr, "Failed to get Web for WebDir");
-
-        hr = ScaWebsGetBase(piMetabase, pswList, pwzData, pswd->wzWebBase, countof(pswd->wzWebBase), hWebBaseQuery);
-        if (WcaIsUninstalling(pswd->isInstalled, pswd->isAction))
-        {
-            // If we're uninstalling, ignore any failure to find the existing web
-            hr = S_OK;
-        }
-
-        ExitOnFailure(hr, "Failed to get base of web for WebDir");
-
-        hr = WcaGetRecordString(hRec, wdqPath, &pwzData);
-        ExitOnFailure(hr, "Failed to get Path for WebDir");
-
-        hr = ::StringCchPrintfW(pswd->wzWebDirRoot, countof(pswd->wzWebDirRoot), L"%s/Root/%s", pswd->wzWebBase, pwzData);
-        ExitOnFailure(hr, "Failed to format webdir root string");
-
-        // get the directory properties for this web
-        hr = WcaGetRecordString(hRec, wdqProperties, &pwzData);
-        ExitOnFailure(hr, "Failed to get security identifier for WebDir");
-        if (*pwzData)
-        {
-            hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &pswd->swp);
-            ExitOnFailure(hr, "Failed to get properties for WebDir");
-
-            pswd->fHasProperties = TRUE;
-        }
-
-        // get the application information for this web directory
-        hr = WcaGetRecordString(hRec, wdqApplication, &pwzData);
-        ExitOnFailure(hr, "Failed to get application identifier for WebDir");
-        if (*pwzData)
-        {
-            hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &pswd->swapp);
-            ExitOnFailure(hr, "Failed to get application for WebDir");
-
-            pswd->fHasApplication = TRUE;
-        }
-
-        AddWebDirToList(ppswdList, pswd);
-    }
-
-    if (E_NOMOREITEMS == hr)
-    {
-        hr = S_OK;
-    }
-    ExitOnFailure(hr, "Failure while processing WebDirs");
-
-LExit:
-    WcaFinishUnwrapQuery(hWrapQuery);
-
-    ReleaseStr(pwzData);
-
-    return hr;
-}
-
-
-HRESULT ScaWebDirsInstall(IMSAdminBase* piMetabase, SCA_WEBDIR* pswdList, SCA_APPPOOL * psapList)
-{
-    HRESULT hr = S_OK;
-    SCA_WEBDIR* pswd = pswdList;
-    int i;
-
-    while (pswd)
-    {
-        // On reinstall, we have to uninstall the old application, otherwise a duplicate will be created
-        if (WcaIsReInstalling(pswd->isInstalled, pswd->isAction))
-        {
-            if (pswd->fHasApplication)
-            {
-                hr = ScaDeleteApp(piMetabase, pswd->wzWebDirRoot);
-                ExitOnFailure(hr, "Failed to remove application for WebDir as part of a reinstall");
-            }
-        }
-
-        // if we are installing the web site
-        if (WcaIsInstalling(pswd->isInstalled, pswd->isAction))
-        {
-            hr = ScaCreateMetabaseKey(piMetabase, pswd->wzWebDirRoot, L"");
-            ExitOnFailure(hr, "Failed to create key for WebDir");
-            hr = ScaWriteMetabaseValue(piMetabase, pswd->wzWebDirRoot, L"", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsWebDirectory");
-            ExitOnFailure(hr, "Failed to write key type for for WebDir");
-            i = 0x4000003e; // 1073741886: default directory browsing rights
-            hr = ScaWriteMetabaseValue(piMetabase, pswd->wzWebDirRoot, L"", MD_DIRECTORY_BROWSING, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)i));
-            ExitOnFailure(hr, "Failed to set directory browsing for WebDir");
-
-            // get the security information for this web
-            if (pswd->fHasProperties)
-            {
-                ScaWriteWebDirProperties(piMetabase, pswd->wzWebDirRoot, &pswd->swp);
-                ExitOnFailure(hr, "Failed to write properties for WebDir");
-            }
-
-            // get the application information for this web directory
-            if (pswd->fHasApplication)
-            {
-                hr = ScaWriteWebApplication(piMetabase, pswd->wzWebDirRoot, &pswd->swapp, psapList);
-                ExitOnFailure(hr, "Failed to write application for WebDir");
-            }
-        }
-
-        pswd = pswd->pswdNext;
-    }
-
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaWebDirsUninstall(IMSAdminBase* piMetabase, SCA_WEBDIR* pswdList)
-{
-    Assert(piMetabase);
-
-    HRESULT hr = S_OK;
-    SCA_WEBDIR* pswd = pswdList;
-
-    while (pswd)
-    {
-        if (WcaIsUninstalling(pswd->isInstalled, pswd->isAction))
-        {
-            // remove the application from this web directory
-            if (pswd->fHasApplication)
-            {
-                hr = ScaDeleteApp(piMetabase, pswd->wzWebDirRoot);
-                ExitOnFailure(hr, "Failed to remove application for WebDir");
-            }
-
-            hr = ScaDeleteMetabaseKey(piMetabase, pswd->wzWebDirRoot, L"");
-            ExitOnFailure(hr, "Failed to remove WebDir '%ls' from metabase", pswd->wzKey);
-        }
-
-        pswd = pswd->pswdNext;
-    }
-
-LExit:
-    return hr;
-}
-
-
-static SCA_WEBDIR* NewWebDir()
-{
-    SCA_WEBDIR* pswd = static_cast<SCA_WEBDIR*>(MemAlloc(sizeof(SCA_WEBDIR), TRUE));
-    Assert(pswd);
-    return pswd;
-}
-
-static void FreeWebDir(SCA_WEBDIR *pswd)
-{
-    MemFree(pswd);
-}
-
-void ScaWebDirsFreeList(SCA_WEBDIR* pswdList)
-{
-    SCA_WEBDIR* pswdDelete = pswdList;
-    while (pswdList)
-    {
-        pswdDelete = pswdList;
-        pswdList = pswdList->pswdNext;
-
-        FreeWebDir(pswdDelete);
-    }
-}
-
-
-static void AddWebDirToList(SCA_WEBDIR** ppswdList, SCA_WEBDIR *pswd)
-{
-    pswd->pswdNext = *ppswdList;
-    *ppswdList = pswd;
-}
diff --git a/src/ca/scawebdir.h b/src/ca/scawebdir.h
deleted file mode 100644
index 0b594532..00000000
--- a/src/ca/scawebdir.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#pragma once
-// 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.
-
-
-struct SCA_WEBDIR
-{
-    // darwin information
-    WCHAR wzKey[MAX_DARWIN_KEY + 1];
-    WCHAR wzComponent[MAX_DARWIN_KEY + 1];
-    INSTALLSTATE isInstalled;
-    INSTALLSTATE isAction;
-
-    // metabase information
-    WCHAR wzWebKey[MAX_DARWIN_KEY + 1];
-    WCHAR wzWebBase[METADATA_MAX_NAME_LEN + 1];
-    WCHAR wzWebDirRoot[METADATA_MAX_NAME_LEN + 1];
-
-    // iis configuation information
-    WCHAR wzDirectory[MAX_PATH];
-
-    BOOL fHasProperties;
-    SCA_WEB_PROPERTIES swp;
-
-    BOOL fHasApplication;
-    SCA_WEB_APPLICATION swapp;
-
-    SCA_WEBDIR* pswdNext;
-};
-
-
-// prototypes
-UINT __stdcall ScaWebDirsRead(
-    __in IMSAdminBase* piMetabase, 
-    __in SCA_WEB* pswList,
-    __in WCA_WRAPQUERY_HANDLE hUserQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebBaseQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
-    __inout LPWSTR *ppwzCustomActionData,
-    __out SCA_WEBDIR** ppswdList
-    );
-
-HRESULT ScaWebDirsInstall(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_WEBDIR* pswdList,
-    __in SCA_APPPOOL* psapList
-    );
-
-HRESULT ScaWebDirsUninstall(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_WEBDIR* pswdList
-    );
-
-void ScaWebDirsFreeList(
-    __in SCA_WEBDIR* pswdList
-    );
diff --git a/src/ca/scawebdir7.cpp b/src/ca/scawebdir7.cpp
deleted file mode 100644
index 5ead0470..00000000
--- a/src/ca/scawebdir7.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-// sql queries
-static LPCWSTR vcsWebDirQuery7 = L"SELECT `Web_`, `WebDir`, `Component_`, `Path`, `DirProperties_`, `Application_`"
-                                       L"FROM `IIsWebDir`";
-
-enum eWebDirQuery { wdqWeb = 1, wdqWebDir, wdqComponent , wdqPath, wdqProperties, wdqApplication, wdqInstalled, wdqAction };
-
-// prototypes
-static HRESULT AddWebDirToList(SCA_WEBDIR7** ppswdList);
-
-
-UINT __stdcall ScaWebDirsRead7(
-    __in SCA_WEB7* pswList,
-    __in WCA_WRAPQUERY_HANDLE hUserQuery,
-    __in WCA_WRAPQUERY_HANDLE /*hWebBaseQuery*/,
-    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
-    __inout LPWSTR *ppwzCustomActionData,
-    __out SCA_WEBDIR7** ppswdList
-    )
-{
-    HRESULT hr = S_OK;
-    MSIHANDLE hRec;
-
-    LPWSTR pwzData = NULL;
-    SCA_WEBDIR7* pswd;
-    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
-
-    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap query for ScaWebDirsRead7");
-
-    if (0 == WcaGetQueryRecords(hWrapQuery))
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ScaInstallWebDirs7() because IIsWebDir table not present");
-        ExitFunction1(hr = S_FALSE);
-    }
-
-    // loop through all the web directories
-    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
-    {
-        hr = AddWebDirToList(ppswdList);
-        ExitOnFailure(hr, "failed to add web dir to list");
-
-        pswd = *ppswdList;
-        ExitOnNull(pswd, hr, E_INVALIDARG, "No web dir provided");
-
-        // get component install state
-        hr = WcaGetRecordString(hRec, wdqComponent, &pwzData);
-        ExitOnFailure(hr, "Failed to get Component for WebDirs");
-        hr = ::StringCchCopyW(pswd->wzComponent, countof(pswd->wzComponent), pwzData);
-        ExitOnFailure(hr, "Failed to copy component string to webdir object");
-
-        hr = WcaGetRecordInteger(hRec, wdqInstalled, (int *)&pswd->isInstalled);
-        ExitOnFailure(hr, "Failed to get Component installed state for webdir");
-
-        hr = WcaGetRecordInteger(hRec, wdqAction, (int *)&pswd->isAction);
-        ExitOnFailure(hr, "Failed to get Component action state for webdir");
-
-        hr = WcaGetRecordString(hRec, wdqWeb, &pwzData);
-        ExitOnFailure(hr, "Failed to get Web for WebDir");
-
-        // get the web key
-        hr = ScaWebsGetBase7(pswList, pwzData, pswd->wzWebSite, countof(pswd->wzWebSite));
-        if (S_FALSE == hr)
-        {
-            hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
-            ExitOnFailure(hr, "Failed to get base of web for WebDir");
-        }
-        ExitOnFailure(hr, "Failed to format webdir root string");
-
-        hr = WcaGetRecordString(hRec, wdqPath, &pwzData);
-        ExitOnFailure(hr, "Failed to get Path for WebDir");
-
-        hr = ::StringCchCopyW(pswd->wzPath, countof(pswd->wzPath), pwzData);
-        ExitOnFailure(hr, "Failed to copy path for WebDir");
-
-        // get the directory properties for this web
-        hr = WcaGetRecordString(hRec, wdqProperties, &pwzData);
-        ExitOnFailure(hr, "Failed to get security identifier for WebDir");
-        if (*pwzData)
-        {
-            hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &pswd->swp);
-            ExitOnFailure(hr, "Failed to get properties for WebDir");
-
-            pswd->fHasProperties = TRUE;
-        }
-
-        // get the application information for this web directory
-        hr = WcaGetRecordString(hRec, wdqApplication, &pwzData);
-        ExitOnFailure(hr, "Failed to get application identifier for WebDir");
-        if (*pwzData)
-        {
-            hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &pswd->swapp);
-            ExitOnFailure(hr, "Failed to get application for WebDir");
-
-            pswd->fHasApplication = TRUE;
-        }
-    }
-
-    if (E_NOMOREITEMS == hr)
-    {
-        hr = S_OK;
-    }
-    ExitOnFailure(hr, "Failure while processing WebDirs");
-
-LExit:
-    WcaFinishUnwrapQuery(hWrapQuery);
-
-    ReleaseStr(pwzData);
-
-    return hr;
-}
-
-
-HRESULT ScaWebDirsInstall7(SCA_WEBDIR7* pswdList, SCA_APPPOOL * psapList)
-{
-    HRESULT hr = S_OK;
-    SCA_WEBDIR7* pswd = pswdList;
-
-    while (pswd)
-    {
-        // if we are installing the web site
-        if (WcaIsInstalling(pswd->isInstalled, pswd->isAction))
-        {
-            hr = ScaWriteConfigID(IIS_WEBDIR);
-            ExitOnFailure(hr, "Failed to write WebDir ID");
-
-            hr = ScaWriteConfigID(IIS_CREATE);
-            ExitOnFailure(hr, "Failed to write WebDir action ID");
-
-            hr = ScaWriteConfigString(pswd->wzWebSite);
-            ExitOnFailure(hr, "Failed to write WebDir site");
-
-            hr = ScaWriteConfigString(pswd->wzPath);
-            ExitOnFailure(hr, "Failed to write WebDir path");
-
-            // get the security information for this web
-            if (pswd->fHasProperties)
-            {
-                ScaWriteWebDirProperties7(pswd->wzWebSite, pswd->wzPath, &pswd->swp);
-                ExitOnFailure(hr, "Failed to write properties for WebDir");
-            }
-
-            // get the application information for this web directory
-            if (pswd->fHasApplication)
-            {
-                hr = ScaWriteWebApplication7(pswd->wzWebSite, pswd->wzPath, &pswd->swapp, psapList);
-                ExitOnFailure(hr, "Failed to write application for WebDir");
-            }
-        }
-
-        pswd = pswd->pswdNext;
-    }
-
-LExit:
-    return hr;
-}
-
-
-HRESULT ScaWebDirsUninstall7(SCA_WEBDIR7* pswdList)
-{
-    HRESULT hr = S_OK;
-    SCA_WEBDIR7* pswd = pswdList;
-
-    while (pswd)
-    {
-        if (WcaIsUninstalling(pswd->isInstalled, pswd->isAction))
-        {
-            hr = ScaWriteConfigID(IIS_WEBDIR);
-            ExitOnFailure(hr, "Failed to write WebDir ID");
-
-            hr = ScaWriteConfigID(IIS_DELETE);
-            ExitOnFailure(hr, "Failed to write WebDir action ID");
-
-            hr = ScaWriteConfigString(pswd->wzWebSite);
-            ExitOnFailure(hr, "Failed to write WebDir site");
-
-            hr = ScaWriteConfigString(pswd->wzPath);
-            ExitOnFailure(hr, "Failed to write WebDir path");
-        }
-
-        pswd = pswd->pswdNext;
-    }
-
-LExit:
-    return hr;
-}
-
-
-void ScaWebDirsFreeList7(SCA_WEBDIR7* pswdList)
-{
-    SCA_WEBDIR7* pswdDelete = pswdList;
-    while (pswdList)
-    {
-        pswdDelete = pswdList;
-        pswdList = pswdList->pswdNext;
-
-        MemFree(pswdDelete);
-    }
-}
-
-
-static HRESULT AddWebDirToList(SCA_WEBDIR7** ppswdList)
-{
-    HRESULT hr = S_OK;
-
-    SCA_WEBDIR7* pswd = static_cast<SCA_WEBDIR7*>(MemAlloc(sizeof(SCA_WEBDIR7), TRUE));
-    ExitOnNull(pswd, hr, E_OUTOFMEMORY, "failed to allocate element for web dir list");
-
-    pswd->pswdNext = *ppswdList;
-    *ppswdList = pswd;
-
-LExit:
-    return hr;
-}
diff --git a/src/ca/scawebdir7.h b/src/ca/scawebdir7.h
deleted file mode 100644
index c5c87e17..00000000
--- a/src/ca/scawebdir7.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#pragma once
-// 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.
-
-
-struct SCA_WEBDIR7
-{
-    // darwin information
-    WCHAR wzKey[MAX_DARWIN_KEY + 1];
-    WCHAR wzComponent[MAX_DARWIN_KEY + 1];
-    INSTALLSTATE isInstalled;
-    INSTALLSTATE isAction;
-
-
-    // iis configuation information
-    WCHAR wzPath[MAX_PATH];
-    WCHAR wzWebSite[MAX_PATH];
-
-    BOOL fHasProperties;
-    SCA_WEB_PROPERTIES swp;
-
-    BOOL fHasApplication;
-    SCA_WEB_APPLICATION swapp;
-
-    SCA_WEBDIR7* pswdNext;
-};
-
-
-// prototypes
-UINT __stdcall ScaWebDirsRead7(
-    __in SCA_WEB7* pswList,
-    __in WCA_WRAPQUERY_HANDLE hUserQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebBaseQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
-    __inout LPWSTR *ppwzCustomActionData,
-    __out SCA_WEBDIR7** ppswdList
-    );
-
-HRESULT ScaWebDirsInstall7(
-    __in SCA_WEBDIR7* pswdList,
-    __in SCA_APPPOOL* psapList
-    );
-
-HRESULT ScaWebDirsUninstall7(
-    __in SCA_WEBDIR7* pswdList
-    );
-
-void ScaWebDirsFreeList7(
-    __in SCA_WEBDIR7* pswdList
-    );
diff --git a/src/ca/scaweberr.cpp b/src/ca/scaweberr.cpp
deleted file mode 100644
index 2441f006..00000000
--- a/src/ca/scaweberr.cpp
+++ /dev/null
@@ -1,371 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-enum eWebErrorQuery { weqErrorCode = 1, weqSubCode, weqParentType, weqParentValue, weqFile, weqURL };
-
-static HRESULT AddWebErrorToList(SCA_WEB_ERROR** ppsweList);
-
-void ScaWebErrorFreeList(SCA_WEB_ERROR *psweList)
-{
-    SCA_WEB_ERROR *psweDelete = psweList;
-    while (psweList)
-    {
-        psweDelete = psweList;
-        psweList = psweList->psweNext;
-
-        MemFree(psweDelete);
-    }
-}
-
-HRESULT ScaWebErrorRead(
-                        SCA_WEB_ERROR **ppsweList,
-                        __inout LPWSTR *ppwzCustomActionData
-                        )
-{
-//    AssertSz(0, "Debug ScaWebErrorRead here");
-    HRESULT hr = S_OK;
-    MSIHANDLE hRec;
-    LPWSTR pwzData = NULL;
-    SCA_WEB_ERROR* pswe;
-    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
-
-    ExitOnNull(ppsweList, hr, E_INVALIDARG, "Failed to read web error, because no web error was provided to read");
-
-    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead");
-
-    if (0 == WcaGetQueryRecords(hWrapQuery))
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ScaWebErrorRead() - required tables not present.");
-        ExitFunction1(hr = S_FALSE);
-    }
-
-    // loop through all the web errors
-    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
-    {
-        hr = AddWebErrorToList(ppsweList);
-        ExitOnFailure(hr, "failed to add web error to list");
-
-        pswe = *ppsweList;
-
-        hr = WcaGetRecordInteger(hRec, weqErrorCode, &(pswe->iErrorCode));
-        ExitOnFailure(hr, "failed to get IIsWebError.ErrorCode");
-
-        hr = WcaGetRecordInteger(hRec, weqSubCode, &(pswe->iSubCode));
-        ExitOnFailure(hr, "failed to get IIsWebError.SubCode");
-
-        hr = WcaGetRecordInteger(hRec, weqParentType, &(pswe->iParentType));
-        ExitOnFailure(hr, "failed to get IIsWebError.ParentType");
-
-        hr = WcaGetRecordString(hRec, weqParentValue, &pwzData);
-        ExitOnFailure(hr, "Failed to get IIsWebError.ParentValue");
-        hr = ::StringCchCopyW(pswe->wzParentValue, countof(pswe->wzParentValue), pwzData);
-        ExitOnFailure(hr, "Failed to copy IIsWebError.ParentValue");
-
-        hr = WcaGetRecordString(hRec, weqFile, &pwzData);
-        ExitOnFailure(hr, "Failed to get IIsWebError.File");
-        hr = ::StringCchCopyW(pswe->wzFile, countof(pswe->wzFile), pwzData);
-        ExitOnFailure(hr, "Failed to copy IIsWebError.File");
-
-        hr = WcaGetRecordString(hRec, weqURL, &pwzData);
-        ExitOnFailure(hr, "Failed to get IIsWebError.URL");
-        hr = ::StringCchCopyW(pswe->wzURL, countof(pswe->wzURL), pwzData);
-        ExitOnFailure(hr, "Failed to copy IIsWebError.URL");
-
-        // If they've specified both a file and a URL, that's invalid
-        if (*(pswe->wzFile) && *(pswe->wzURL))
-            ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA), "Both File and URL specified for web error.  File: %ls, URL: %ls", pswe->wzFile, pswe->wzURL);
-    }
-
-    if (E_NOMOREITEMS == hr)
-    {
-        hr = S_OK;
-    }
-    ExitOnFailure(hr, "Failure while processing web errors");
-
-LExit:
-    WcaFinishUnwrapQuery(hWrapQuery);
-
-    ReleaseStr(pwzData);
-
-    return hr;
-}
-
-HRESULT ScaGetWebError(int iParentType, LPCWSTR wzParentValue, SCA_WEB_ERROR **ppsweList, SCA_WEB_ERROR **ppsweOut)
-{
-    HRESULT hr = S_OK;
-    SCA_WEB_ERROR* psweAdd = NULL;
-    SCA_WEB_ERROR* psweLast = NULL;
-
-    *ppsweOut = NULL;
-    
-    if (!*ppsweList)
-        return hr;
-
-    SCA_WEB_ERROR* pswe = *ppsweList;
-    while (pswe)
-    {
-        if (iParentType == pswe->iParentType && 0 == lstrcmpW(wzParentValue, pswe->wzParentValue))
-        {
-            // Found a match, take this one out of the list and add it to the matched out list
-            psweAdd = pswe;
-
-            if (psweLast)
-            {
-                // 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)
-                psweLast->psweNext = psweAdd->psweNext;
-            }
-            else
-            {
-                // If we are at the beginning (no psweLast) update the beginning (since we're taking it)
-                *ppsweList = pswe->psweNext;
-            }
-            pswe = pswe->psweNext; // move on
-
-            // Add the one we've removed to the beginning of the out list
-            psweAdd->psweNext = *ppsweOut;
-            *ppsweOut = psweAdd;
-        }
-        else
-        {
-            psweLast = pswe; // remember the last we that didn't match
-            pswe = pswe->psweNext; // move on
-        }
-    }
-
-    return hr;
-}
-
-HRESULT ScaWriteWebError(IMSAdminBase* piMetabase, int iParentType, LPCWSTR wzRoot, SCA_WEB_ERROR* psweList)
-{
-//    AssertSz(0, "Debug ScaWriteWebError here");
-    Assert(*wzRoot && psweList);
-
-    HRESULT hr = S_OK;
-
-    DWORD cchData = 0;
-    LPWSTR pwzSearchKey = NULL;
-    LPWSTR pwz = NULL;
-    LPWSTR pwzErrors = NULL;
-
-    LPWSTR pwzCodeSubCode = NULL;
-    LPWSTR pwzAcceptableCodeSubCode = NULL;
-    LPCWSTR wzFoundCodeSubCode = NULL;
-    DWORD_PTR dwFoundCodeSubCodeIndex = 0xFFFFFFFF;
-    BOOL fOldValueFound = FALSE;
-    LPWSTR pwzAcceptableErrors = NULL;
-
-    LPWSTR pwzNewError = NULL;
-
-    METADATA_RECORD mr;
-    ::ZeroMemory(&mr, sizeof(mr));
-
-    ExitOnNull(piMetabase, hr, E_INVALIDARG, "Failed to write web error, because no metabase was provided");
-    ExitOnNull(wzRoot, hr, E_INVALIDARG, "Failed to write web error, because no root was provided");
-
-    // get the set of all valid custom errors from the metabase
-    mr.dwMDIdentifier = MD_CUSTOM_ERROR_DESC;
-    mr.dwMDAttributes = METADATA_INHERIT;
-    mr.dwMDUserType = IIS_MD_UT_SERVER;
-    mr.dwMDDataType = ALL_METADATA;
-    mr.dwMDDataLen = cchData = 0;
-    mr.pbMDData = NULL;
-
-    hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, L"/LM/W3SVC/Info", &mr);
-    ExitOnFailure(hr, "Unable to get set of acceptable error codes for this server.");
-
-    pwzAcceptableErrors = reinterpret_cast<LPWSTR>(mr.pbMDData);
-
-    // Check if web errors already exist here
-    mr.dwMDIdentifier = MD_CUSTOM_ERROR;
-    mr.dwMDAttributes = METADATA_INHERIT;
-    mr.dwMDUserType = IIS_MD_UT_SERVER;
-    mr.dwMDDataType = ALL_METADATA;
-    mr.dwMDDataLen = cchData = 0;
-    mr.pbMDData = NULL;
-
-    hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzRoot, &mr);
-    if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || MD_ERROR_DATA_NOT_FOUND == hr)
-    {
-        //
-        // If we don't have one already, find an appropriate one to start with
-        //
-
-        // we can walk up key by key and look for custom errors to inherit
-
-        hr = StrAllocConcat(&pwzSearchKey, wzRoot, 0);
-        ExitOnFailure(hr, "Failed to copy root string: %ls", wzRoot);
-
-        pwz = pwzSearchKey + lstrlenW(pwzSearchKey);
-
-        while (NULL == pwzErrors)
-        {
-            // find the last slash
-            while (*pwz != '/' && pwz != pwzSearchKey)
-                pwz --;
-
-            if (pwz == pwzSearchKey)
-                break;
-
-            *pwz = L'\0';
-
-            // Try here.  If it's not found, keep walking up the path
-            hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, pwzSearchKey, &mr);
-            if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || MD_ERROR_DATA_NOT_FOUND == hr)
-                hr = S_FALSE;
-            ExitOnFailure(hr, "failed to discover default error values to start with for web root: %ls while walking up the tree", wzRoot);
-
-            if (S_OK == hr)
-            {
-                pwzErrors = reinterpret_cast<LPWSTR>(mr.pbMDData);
-                break;
-            }
-
-            // Don't keep going if we're at the root
-            if (0 == lstrcmpW(pwz + 1, L"W3SVC"))
-                break;
-        }
-    }
-    else
-    {
-        pwzErrors = reinterpret_cast<LPWSTR>(mr.pbMDData);
-    }
-    ExitOnFailure(hr, "failed to discover default error values to start with for web root: %ls", wzRoot);
-
-    // The above code should have come up with some value to start pwzErrors off with.  Make sure it did.
-    if (NULL == pwzErrors)
-    {
-        ExitOnFailure(hr = E_UNEXPECTED, "failed to discover default error values to start with for web root: %ls", wzRoot);
-    }
-
-    // Loop through the web errors
-    for (SCA_WEB_ERROR* pswe = psweList; pswe; pswe = pswe->psweNext)
-    {
-        // Assume that we will have to replace 
-        fOldValueFound = TRUE;
-
-        // If the subcode is 0, that means "*" in MD_CUSTOM_ERROR (thus the special formatting logic)
-        if (0 == pswe->iSubCode)
-        {
-            hr = StrAllocFormatted(&pwzCodeSubCode, L"%d,*", pswe->iErrorCode);
-            ExitOnFailure(hr, "failed to create error code string while installing web error");
-        }
-        else
-        {
-            hr = StrAllocFormatted(&pwzCodeSubCode, L"%d,%d", pswe->iErrorCode, pswe->iSubCode);
-            ExitOnFailure(hr, "failed to create error code,subcode string while installing web error");
-        }
-
-        hr = MultiSzFindSubstring(pwzErrors, pwzCodeSubCode, &dwFoundCodeSubCodeIndex, &wzFoundCodeSubCode);
-        ExitOnFailure(hr, "failed to find existing error code,subcode: %ls", pwzCodeSubCode);
-
-        // If we didn't find this error code/sub code pair in the list already, make sure it's acceptable to add
-        if (S_FALSE == hr)
-        {
-            //
-            // Make sure this error code/sub code pair is in the "acceptable" list
-            //
-
-            // If the subcode is 0, that means "0" in MD_CUSTOM_ERROR_DESC (no special formatting logic needed)
-            hr = StrAllocFormatted(&pwzAcceptableCodeSubCode, L"%d,%d", pswe->iErrorCode, pswe->iSubCode);
-            ExitOnFailure(hr, "failed to create error code,subcode string while installing web error");
-
-            // We don't care where it is, just whether it's there or not
-            hr = MultiSzFindSubstring(pwzAcceptableErrors, pwzAcceptableCodeSubCode, NULL, NULL);
-            ExitOnFailure(hr, "failed to find whether or not error code, subcode: %ls is supported", pwzCodeSubCode);
-
-            if (S_FALSE == hr)
-            {
-                WcaLog(LOGMSG_VERBOSE, "Skipping error code, subcode: %ls because it is not supported by the server.", pwzCodeSubCode);
-                continue;
-            }
-
-            // If we didn't find it (and its an acceptable error) then we have nothing to replace
-            fOldValueFound = FALSE;
-        }
-
-        // Set up the new error string if needed
-        if (*(pswe->wzFile))
-        {
-            hr = StrAllocFormatted(&pwzNewError, L"%s,FILE,%s", pwzCodeSubCode, pswe->wzFile);
-            ExitOnFailure(hr, "failed to create new error code string with code,subcode: %ls, file: %ls", pwzCodeSubCode, pswe->wzFile);
-        }
-        else if (*(pswe->wzURL))
-        {
-            hr = StrAllocFormatted(&pwzNewError, L"%s,URL,%s", pwzCodeSubCode, pswe->wzURL);
-            ExitOnFailure(hr, "failed to create new error code string with code,subcode: %ls, file: %ls", pwzCodeSubCode, pswe->wzFile);
-        }
-        else if (fOldValueFound)
-        {
-            // If no File or URL was specified, they want a default error so remove the old value from the MULTISZ and move on
-            hr = MultiSzRemoveString(&pwzErrors, dwFoundCodeSubCodeIndex);
-            ExitOnFailure(hr, "failed to remove string for error code sub code: %ls in order to make it 'default'", pwzCodeSubCode);
-            continue;
-        }
-
-        // If we have something to replace, replace it, otherwise, put it at the beginning (order shouldn't matter)
-        if (fOldValueFound)
-        {
-            hr = MultiSzReplaceString(&pwzErrors, dwFoundCodeSubCodeIndex, pwzNewError);
-            ExitOnFailure(hr, "failed to replace old error string with new error string for error code,subcode: %ls", pwzCodeSubCode);
-        }
-        else
-        {
-            hr = MultiSzPrepend(&pwzErrors, NULL, pwzNewError);
-            ExitOnFailure(hr, "failed to prepend new error string for error code,subcode: %ls", pwzCodeSubCode);
-        }
-    }
-
-    // now write the CustomErrors to the metabase
-    if (weptWeb == iParentType)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRoot, L"/Root", MD_CUSTOM_ERROR, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, pwzErrors);
-        ExitOnFailure(hr, "Failed to write Web Error to /Root");
-    }
-    else
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRoot, NULL, MD_CUSTOM_ERROR, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, pwzErrors);
-        ExitOnFailure(hr, "Failed to write Web Error");
-    }
-
-LExit:
-    ReleaseStr(pwzErrors);
-    ReleaseStr(pwzSearchKey);
-    ReleaseStr(pwzCodeSubCode);
-    ReleaseStr(pwzAcceptableCodeSubCode);
-    ReleaseStr(pwzAcceptableErrors);
-
-    return hr;
-}
-
-static HRESULT AddWebErrorToList(SCA_WEB_ERROR** ppsweList)
-{
-    HRESULT hr = S_OK;
-
-    SCA_WEB_ERROR* pswe = static_cast<SCA_WEB_ERROR*>(MemAlloc(sizeof(SCA_WEB_ERROR), TRUE));
-    ExitOnNull(pswe, hr, E_OUTOFMEMORY, "failed to allocate memory for new web error list element");
-
-    pswe->psweNext = *ppsweList;
-    *ppsweList = pswe;
-
-LExit:
-    return hr;
-}
-
-HRESULT ScaWebErrorCheckList(SCA_WEB_ERROR* psweList)
-{
-    if (!psweList)
-    {
-        return S_OK;
-    }
-    
-    while (psweList)
-    {
-        WcaLog(LOGMSG_STANDARD, "WebError code: %d subcode: %d for parent: %ls not used!", psweList->iErrorCode, psweList->iSubCode, psweList->wzParentValue);
-        psweList = psweList->psweNext;
-    }
-
-    return E_FAIL;
-}
-
diff --git a/src/ca/scaweberr.h b/src/ca/scaweberr.h
deleted file mode 100644
index ad8ff4f5..00000000
--- a/src/ca/scaweberr.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#pragma once
-// 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.
-
-
-enum eWebErrorParentType { weptVDir = 1, weptWeb };
-
-struct SCA_WEB_ERROR
-{
-	int iErrorCode;
-	int iSubCode;
-
-	int iParentType;
-	WCHAR wzParentValue[MAX_DARWIN_KEY + 1];
-
-	WCHAR wzFile[MAX_PATH];
-	WCHAR wzURL[MAX_PATH]; // TODO: this needs to be bigger than MAX_PATH
-	
-	SCA_WEB_ERROR *psweNext;
-};
-
-// prototypes
-HRESULT ScaWebErrorRead(
-                        SCA_WEB_ERROR **ppsweList,
-                        __inout LPWSTR *ppwzCustomActionData
-                        );
-void ScaWebErrorFreeList(SCA_WEB_ERROR *psweList);
-HRESULT ScaWebErrorCheckList(SCA_WEB_ERROR* psweList);
-HRESULT ScaGetWebError(int iParentType, LPCWSTR wzParentValue, SCA_WEB_ERROR **ppsweList, SCA_WEB_ERROR **ppsweOut);
-HRESULT ScaWriteWebError(IMSAdminBase* piMetabase, int iParentType, LPCWSTR wzRoot, SCA_WEB_ERROR* psweList);
-
diff --git a/src/ca/scaweberr7.cpp b/src/ca/scaweberr7.cpp
deleted file mode 100644
index 33c2f1bd..00000000
--- a/src/ca/scaweberr7.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-HRESULT ScaWriteWebError7(
-    __in_z LPCWSTR wzWebName,
-    __in_z LPCWSTR wzRoot,
-    SCA_WEB_ERROR* psweList
-    )
-{
-    HRESULT hr = S_OK;
-
-    hr = ScaWriteConfigID(IIS_WEBERROR_BEGIN);
-    ExitOnFailure(hr, "Fail to write webError begin ID");
-
-    hr = ScaWriteConfigString(wzWebName);
-    ExitOnFailure(hr, "Fail to write webError Web Key");
-
-    hr = ScaWriteConfigString(wzRoot);
-    ExitOnFailure(hr, "Fail to write webError Vdir key");
-
-    // Loop through the HTTP headers
-    for (SCA_WEB_ERROR* pswe = psweList; pswe; pswe = pswe->psweNext)
-    {
-        hr = ScaWriteConfigID(IIS_WEBERROR);
-        ExitOnFailure(hr, "Fail to write webError ID");
-
-        hr = ScaWriteConfigInteger(pswe->iErrorCode);
-        ExitOnFailure(hr, "Fail to write webError code");
-
-        hr = ScaWriteConfigInteger(pswe->iSubCode);
-        ExitOnFailure(hr, "Fail to write webError subcode");
-
-        //just write one
-        if (*(pswe->wzFile))
-        {
-            hr = ScaWriteConfigString(pswe->wzFile);
-            ExitOnFailure(hr, "Fail to write webError file");
-            hr = ScaWriteConfigInteger(0);
-            ExitOnFailure(hr, "Fail to write webError file code");
-        }
-        else if (*(pswe->wzURL))
-        {
-            hr = ScaWriteConfigString(pswe->wzURL);
-            ExitOnFailure(hr, "Fail to write webError URL");
-            hr = ScaWriteConfigInteger(1);
-            ExitOnFailure(hr, "Fail to write webError URL code");
-        }
-    }
-
-    hr = ScaWriteConfigID(IIS_WEBERROR_END);
-    ExitOnFailure(hr, "Fail to write httpHeader end ID");
-
-LExit:
-    return hr;
-
-}
-
-//static HRESULT AddWebErrorToList(SCA_WEB_ERROR** ppsweList)
-//{
-//    HRESULT hr = S_OK;
-//
-//    SCA_WEB_ERROR* pswe = static_cast<SCA_WEB_ERROR*>(MemAlloc(sizeof(SCA_WEB_ERROR), TRUE));
-//    ExitOnNull(pswe, hr, E_OUTOFMEMORY, "failed to allocate memory for new web error list element");
-//
-//    pswe->psweNext = *ppsweList;
-//    *ppsweList = pswe;
-//
-//LExit:
-//    return hr;
-//}
-
-HRESULT ScaWebErrorCheckList7(SCA_WEB_ERROR* psweList)
-{
-    if (!psweList)
-    {
-        return S_OK;
-    }
-
-    while (psweList)
-    {
-        WcaLog(LOGMSG_STANDARD, "WebError code: %d subcode: %d for parent: %ls not used!", psweList->iErrorCode, psweList->iSubCode, psweList->wzParentValue);
-        psweList = psweList->psweNext;
-    }
-
-    return E_FAIL;
-}
-
diff --git a/src/ca/scaweberr7.h b/src/ca/scaweberr7.h
deleted file mode 100644
index 62448211..00000000
--- a/src/ca/scaweberr7.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#pragma once
-// 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.
-
-
-HRESULT ScaWriteWebError7(
-    __in_z LPCWSTR wzWebName,
-    __in_z LPCWSTR wzRoot,
-    SCA_WEB_ERROR* psweList
-    );
-
diff --git a/src/ca/scaweblog.cpp b/src/ca/scaweblog.cpp
deleted file mode 100644
index 01147848..00000000
--- a/src/ca/scaweblog.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-enum eWebLogQuery { wlqLog = 1, wlqFormat };
-
-/* ****************************************************************
- * LookupLogFormatGUID -Looks up a given IIS Log format type in 
- * the metabase and returns the GUID for it.
- * ****************************************************************/
-static HRESULT LookupLogFormatGUID(
-    __in IMSAdminBase* piMetabase,
-    __in LPCWSTR wzLogFormat,
-    __out_ecount(cchGUID) LPWSTR wzGUID,
-    __in int cchGUID
-    )
-{
-    WCHAR wzKey[METADATA_MAX_NAME_LEN];
-    HRESULT hr = S_OK;
-
-    METADATA_RECORD mrKeyType;
-    ::ZeroMemory(&mrKeyType, sizeof(mrKeyType));
-
-    mrKeyType.dwMDIdentifier = MD_KEY_TYPE;
-    mrKeyType.dwMDAttributes = METADATA_NO_ATTRIBUTES;
-    mrKeyType.dwMDUserType = IIS_MD_UT_SERVER;
-    mrKeyType.dwMDDataType = ALL_METADATA;
-    mrKeyType.dwMDDataLen = 0;
-    mrKeyType.pbMDData = NULL;
-
-    METADATA_RECORD mrPluginId;
-    ::ZeroMemory(&mrPluginId, sizeof(mrPluginId));
-
-    mrPluginId.dwMDIdentifier = MD_LOG_PLUGIN_MOD_ID;
-    mrPluginId.dwMDAttributes = METADATA_INHERIT;
-    mrPluginId.dwMDUserType = IIS_MD_UT_SERVER;
-    mrPluginId.dwMDDataType = ALL_METADATA;
-    mrPluginId.dwMDDataLen = 0;
-    mrPluginId.pbMDData = NULL;
-    
-    hr = ::StringCchPrintfW(wzKey, countof(wzKey), L"/LM/Logging/%s", wzLogFormat);
-    ExitOnFailure(hr, "failed to format logging metabase key name");
-
-    // verify that we have this log format available in IIS
-    hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzKey, &mrKeyType);
-    ExitOnFailure(hr, "Failed to find specified Log format key in IIS for log format: %ls", wzLogFormat);
-    ExitOnNull(mrKeyType.pbMDData, hr, E_POINTER, "Request for Log format key in IIS for log format returned success, but value was NULL");
-
-    if (0 != lstrcmpW(L"IIsLogModule", (LPCWSTR)mrKeyType.pbMDData))
-    {
-        ExitOnFailure(hr = E_UNEXPECTED, "Found invalid log format in IIS: %ls", (LPCWSTR)mrKeyType.pbMDData);
-    }
-
-    // find the GUID for that log format
-    hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzKey, &mrPluginId);
-    ExitOnFailure(hr, "Failed to retrieve IISLog format GUID. Key: %ls", wzKey);
-    ExitOnNull(mrPluginId.pbMDData, hr, E_POINTER, "Retrieval of IISLog format GUID returned success, but value was NULL");
-
-    hr = ::StringCchCopyW(wzGUID, cchGUID, (LPCWSTR)mrPluginId.pbMDData);
-    ExitOnFailure(hr, "failed to copy metabase value: %ls", (LPCWSTR)mrPluginId.pbMDData);
-
-LExit:
-
-    if (mrKeyType.pbMDData)
-    {
-        MetaFreeValue(&mrKeyType);
-    }
-
-    if (mrPluginId.pbMDData)
-    {
-        MetaFreeValue(&mrPluginId);
-    }
-
-    return hr;
-}
-
-
-/* ****************************************************************
- * ScaGetWebLog -Retrieves Log table data for the specified Log key
- *
- * ****************************************************************/
-HRESULT ScaGetWebLog(
-    IMSAdminBase* piMetabase,
-    LPCWSTR wzLog,
-    __in WCA_WRAPQUERY_HANDLE hWebLogQuery,
-    SCA_WEB_LOG* pswl
-    )
-{
-    HRESULT hr = S_OK;
-    LPWSTR pwzData = NULL;
-    MSIHANDLE hRec;
-
-    if (0 == WcaGetQueryRecords(hWebLogQuery))
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ScaGetWebLog() - no records to process");
-        ExitFunction1(hr = S_FALSE);
-    }
-
-    WcaFetchWrappedReset(hWebLogQuery);
-
-    hr = WcaFetchWrappedRecordWhereString(hWebLogQuery, wlqLog, wzLog, &hRec);
-    if (E_NOMOREITEMS == hr)
-    {
-        ExitOnFailure(hr, "cannot locate IIsWebLog.Log='%ls'", wzLog);
-    }
-    HRESULT hrTemp = WcaFetchWrappedRecordWhereString(hWebLogQuery, wlqLog, wzLog, &hRec);
-
-    if (SUCCEEDED(hrTemp))
-    {
-        ExitOnFailure(hr, "error - found multiple matching IIsWebLog rows");
-    }
-
-    ::ZeroMemory(pswl, sizeof(SCA_WEB_LOG));
-
-    // check that log key matches
-    hr = WcaGetRecordString(hRec, wlqLog, &pwzData);
-    ExitOnFailure(hr, "failed to get IIsWebLog.Log for Log: %ls", wzLog);
-    hr = ::StringCchCopyW(pswl->wzLog, countof(pswl->wzLog), pwzData);
-    ExitOnFailure(hr, "failed to copy log name: %ls", pwzData);
-
-    hr = WcaGetRecordString(hRec, wlqFormat, &pwzData);
-    ExitOnFailure(hr, "failed to get IIsWebLog.Format for Log:", wzLog);
-    hr = ::StringCchCopyW(pswl->wzFormat, countof(pswl->wzFormat), pwzData);
-    ExitOnFailure(hr, "failed to copy log format: %ls", pwzData);
-
-    // if they specified a log format, look up its GUID in the metabase
-    if (*pswl->wzFormat && 0 != lstrcmpW(pswl->wzFormat, L"none"))
-    {
-        hr = LookupLogFormatGUID(piMetabase, pswl->wzFormat, pswl->wzFormatGUID, countof(pswl->wzFormatGUID));
-        ExitOnFailure(hr, "Failed to get Log Format GUID for Log: %ls", wzLog);
-    }
-
-LExit:
-    ReleaseStr(pwzData);
-
-    return hr;
-}
-
-
-/* ****************************************************************
- * ScaWriteWebLog -Writes the IIS log values to the metabase.
- *
- * ****************************************************************/
-HRESULT ScaWriteWebLog(
-    IMSAdminBase* piMetabase,
-    LPCWSTR wzWebBase,
-    SCA_WEB_LOG *pswl
-    )
-{
-    HRESULT hr = S_OK;
-
-    if (*pswl->wzFormat)
-    {
-        if (0 == lstrcmpW(pswl->wzFormat, L"none"))
-        {
-            // user wishes for Logging to be turned 'off'
-            hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_LOG_TYPE, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)0));
-            ExitOnFailure(hr, "Failed to write Log Type for Web: %ls", wzWebBase);
-        }
-        else
-        {
-            Assert(*pswl->wzFormatGUID);
-            
-            // write the GUID for the log format for the web to the metabase
-            hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_LOG_PLUGIN_ORDER, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, pswl->wzFormatGUID);
-            ExitOnFailure(hr, "Failed to write Log GUID for Web: %ls", wzWebBase);
-
-            hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_LOG_TYPE, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)1));
-            ExitOnFailure(hr, "Failed to write Log Type for Web: %ls", wzWebBase);
-        }
-    }
-
-LExit:
-    return hr;
-}
-
-
diff --git a/src/ca/scaweblog.h b/src/ca/scaweblog.h
deleted file mode 100644
index 1a690cce..00000000
--- a/src/ca/scaweblog.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#pragma once
-// 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.
-
-
-struct SCA_WEB_LOG
-{
-	// iis configuation information
-	WCHAR wzLog[MAX_DARWIN_KEY + 1];
-
-	// for specifying the log format
-	WCHAR wzFormat[MAX_DARWIN_KEY + 1];
-	WCHAR wzFormatGUID[MAX_DARWIN_KEY + 1];
-};
-
-
-// prototypes
-HRESULT ScaGetWebLog(
-	IMSAdminBase* piMetabase,
-	LPCWSTR wzLog,
-    __in WCA_WRAPQUERY_HANDLE hWebLogQuery,
-	SCA_WEB_LOG* pswl
-	);
-HRESULT ScaWriteWebLog(
-	IMSAdminBase* piMetabase,
-	LPCWSTR wzRootOfWeb,
-	SCA_WEB_LOG *pswl
-	);
diff --git a/src/ca/scaweblog7.cpp b/src/ca/scaweblog7.cpp
deleted file mode 100644
index c857c46f..00000000
--- a/src/ca/scaweblog7.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-// 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.
-
-#include "precomp.h"
-// sql queries
-LPCWSTR vcsWebLogQuery7 = L"SELECT `Log`, `Format` "
-                         L"FROM `IIsWebLog`  WHERE `Log`=?";
-
-enum eWebLogQuery { wlqLog = 1, wlqFormat };
-
-/* ****************************************************************
- * ScaGetWebLog7 -Retrieves Log table data for the specified Log key
- *
- * ****************************************************************/
-HRESULT ScaGetWebLog7(
-    __in_z LPCWSTR wzLog,
-    __in WCA_WRAPQUERY_HANDLE hWebLogQuery,
-    __out SCA_WEB_LOG* pswl
-    )
-{
-    HRESULT hr = S_OK;
-    LPWSTR pwzData = NULL;
-    MSIHANDLE hRec;
-
-    if (0 == WcaGetQueryRecords(hWebLogQuery))
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ScaGetWebLog() - no records to process");
-        ExitFunction1(hr = S_FALSE);
-    }
-
-    WcaFetchWrappedReset(hWebLogQuery);
-
-    hr = WcaFetchWrappedRecordWhereString(hWebLogQuery, wlqLog, wzLog, &hRec);
-    if (E_NOMOREITEMS == hr)
-    {
-        ExitOnFailure(hr, "cannot locate IIsWebLog.Log='%ls'", wzLog);
-    }
-    HRESULT hrTemp = WcaFetchWrappedRecordWhereString(hWebLogQuery, wlqLog, wzLog, &hRec);
-
-    if (SUCCEEDED(hrTemp))
-    {
-        ExitOnFailure(hr, "error - found multiple matching IIsWebLog rows");
-    }
-
-    ::ZeroMemory(pswl, sizeof(SCA_WEB_LOG));
-
-    // check that log key matches
-    hr = WcaGetRecordString(hRec, wlqLog, &pwzData);
-    ExitOnFailure(hr, "failed to get IIsWebLog.Log for Log: %ls", wzLog);
-    hr = ::StringCchCopyW(pswl->wzLog, countof(pswl->wzLog), pwzData);
-    ExitOnFailure(hr, "failed to copy log name: %ls", pwzData);
-
-    hr = WcaGetRecordString(hRec, wlqFormat, &pwzData);
-    ExitOnFailure(hr, "failed to get IIsWebLog.Format for Log:", wzLog);
-
-    //translate WIX log format name strings to IIS7
-    if (0 == lstrcmpW(pwzData, L"Microsoft IIS Log File Format"))
-    {
-        hr = ::StringCchCopyW(pswl->wzFormat, countof(pswl->wzFormat), L"IIS");
-        ExitOnFailure(hr, "failed to copy log format: %ls", pwzData);
-    }
-    else if (0 == lstrcmpW(pwzData, L"NCSA Common Log File Format"))
-    {
-        hr = ::StringCchCopyW(pswl->wzFormat, countof(pswl->wzFormat), L"NCSA");
-        ExitOnFailure(hr, "failed to copy log format: %ls", pwzData);
-    }
-    else if (0 == lstrcmpW(pwzData, L"none"))
-    {
-        hr = ::StringCchCopyW(pswl->wzFormat, countof(pswl->wzFormat), L"none");
-        ExitOnFailure(hr, "failed to copy log format: %ls", pwzData);
-    }
-    else if (0 == lstrcmpW(pwzData, L"ODBC Logging"))
-    {
-        hr = ::StringCchCopyW(pswl->wzFormat, countof(pswl->wzFormat), L"W3C");
-        ExitOnFailure(hr, "failed to copy log format: %ls", pwzData);
-    }
-    else if (0 == lstrcmpW(pwzData, L"W3C Extended Log File Format"))
-    {
-        hr = ::StringCchCopyW(pswl->wzFormat, countof(pswl->wzFormat), L"W3C");
-        ExitOnFailure(hr, "failed to copy log format: %ls", pwzData);
-    }
-    else
-    {
-        hr = HRESULT_FROM_WIN32(ERROR_INVALID_INDEX);
-        ExitOnFailure(hr, "Invalid log file format: %ls", pwzData);
-    }
-
-LExit:
-    ReleaseStr(pwzData);
-
-    return hr;
-}
-
-
-/* ****************************************************************
- * ScaWriteWebLog -Writes the IIS log values to the metabase.
- *
- * ****************************************************************/
-HRESULT ScaWriteWebLog7(
-    LPCWSTR wzWebBase,
-    const SCA_WEB_LOG *pswl
-    )
-{
-    HRESULT hr = S_OK;
-
-    if (*pswl->wzFormat)
-    {
-        //write pswl->wzFormat
-        hr = ScaWriteConfigID(IIS_WEBLOG);
-        ExitOnFailure(hr, "Failed to write log format id");
-        hr = ScaWriteConfigString(wzWebBase);
-        ExitOnFailure(hr, "Failed to write log web key");
-        hr = ScaWriteConfigString(pswl->wzFormat);
-        ExitOnFailure(hr, "Failed to write log format string");
-    }
-
-LExit:
-    return hr;
-}
-
-
diff --git a/src/ca/scaweblog7.h b/src/ca/scaweblog7.h
deleted file mode 100644
index f2bb60d7..00000000
--- a/src/ca/scaweblog7.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#pragma once
-// 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.
-
-
-HRESULT ScaGetWebLog7(
-    __in_z LPCWSTR wzLog,
-    __in WCA_WRAPQUERY_HANDLE hWebLogQuery,
-    __out SCA_WEB_LOG* pswl
-    );
-
-HRESULT ScaWriteWebLog7(
-    __in_z LPCWSTR wzRootOfWeb,
-    const SCA_WEB_LOG *pswl
-    );
diff --git a/src/ca/scawebprop.cpp b/src/ca/scawebprop.cpp
deleted file mode 100644
index b5e38467..00000000
--- a/src/ca/scawebprop.cpp
+++ /dev/null
@@ -1,301 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-// sql queries
-enum eWebDirPropertiesQuery { wpqProperties = 1, wpqAccess, wpqAuthorization, wpqUser, wpqControlledPassword, wpqLogVisits, wpqIndex, wpqDefaultDoc,  wpqAspDetailedError, wpqHttpExp, wpqCCMaxAge, wpqCCCustom, wpqNoCustomError, wpqAccessSSLFlags, wpqAuthenticationProviders };
-
-HRESULT ScaGetWebDirProperties(
-    __in LPCWSTR wzProperties,
-    __in WCA_WRAPQUERY_HANDLE hUserQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
-    __inout SCA_WEB_PROPERTIES* pswp
-    )
-{
-    Assert(*wzProperties && pswp);
-
-    HRESULT hr = S_OK;
-    MSIHANDLE hRec;
-    LPWSTR pwzData = NULL;
-
-    ExitOnNull(wzProperties, hr, E_INVALIDARG, "Failed to get web directory properties because no properties were provided to get");
-
-    WcaFetchWrappedReset(hWebDirPropQuery);
-
-    hr = WcaFetchWrappedRecordWhereString(hWebDirPropQuery, 1, wzProperties, &hRec);
-    if (S_OK == hr)
-    {
-        hr = WcaGetRecordString(hRec, wpqProperties, &pwzData);
-        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.DirProperties");
-        hr = ::StringCchCopyW(pswp->wzKey, countof(pswp->wzKey), pwzData);
-        ExitOnFailure(hr, "Failed to copy key string to webdirproperties object");
-
-        Assert(0 == lstrcmpW(pswp->wzKey, wzProperties));
-
-        hr = WcaGetRecordInteger(hRec, wpqAccess, &pswp->iAccess);
-        ExitOnFailure(hr, "Failed to get access value");
-
-        hr = WcaGetRecordInteger(hRec, wpqAuthorization, &pswp->iAuthorization);
-        ExitOnFailure(hr, "Failed to get authorization value");
-
-        // if allow anonymous users
-        if (S_OK == hr && pswp->iAuthorization & 1)
-        {
-            // if there is an anonymous user specified
-            hr = WcaGetRecordString(hRec, wpqUser, &pwzData);
-            ExitOnFailure(hr, "Failed to get AnonymousUser_");
-            if (pwzData && *pwzData)
-            {
-                hr = WcaGetRecordInteger(hRec, wpqControlledPassword, &pswp->fIIsControlledPassword);
-                ExitOnFailure(hr, "Failed to get IIsControlledPassword");
-                if (S_FALSE == hr)
-                {
-                    pswp->fIIsControlledPassword = FALSE;
-                    hr = S_OK;
-                }
-
-                hr = ScaGetUserDeferred(pwzData, hUserQuery, &pswp->scau);
-                ExitOnFailure(hr, "Failed to get User information for Web");
-
-                pswp->fHasUser = TRUE;
-            }
-            else
-                pswp->fHasUser = FALSE;
-        }
-
-        hr = WcaGetRecordInteger(hRec, wpqLogVisits, &pswp->fLogVisits);
-        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.LogVisits");
-
-        hr = WcaGetRecordInteger(hRec, wpqIndex, &pswp->fIndex);
-        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.Index");
-
-        hr = WcaGetRecordString(hRec, wpqDefaultDoc, &pwzData);
-        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.DefaultDoc");
-        if (pwzData && *pwzData)
-        {
-            pswp->fHasDefaultDoc = TRUE;
-            if (0 == lstrcmpW(L"-", pwzData))   // remove any existing default documents by setting them blank
-            {
-                pswp->wzDefaultDoc[0] = L'\0';
-            }
-            else   // set the default documents
-            {
-                hr = ::StringCchCopyW(pswp->wzDefaultDoc, countof(pswp->wzDefaultDoc), pwzData);
-                ExitOnFailure(hr, "Failed to copy default document string to webdirproperties object");
-            }
-        }
-        else
-        {
-            pswp->fHasDefaultDoc = FALSE;
-        }
-
-        hr = WcaGetRecordInteger(hRec, wpqAspDetailedError, &pswp->fAspDetailedError);
-        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.AspDetailedError");
-
-        hr = WcaGetRecordString(hRec, wpqHttpExp, &pwzData);
-        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.HttpExp");
-        if (pwzData && *pwzData)
-        {
-            pswp->fHasHttpExp = TRUE;
-            if (0 == lstrcmpW(L"-", pwzData))   // remove any existing default expiration settings by setting them blank
-            {
-                pswp->wzHttpExp[0] = L'\0';
-            }
-            else   // set the expiration setting
-            {
-                hr = ::StringCchCopyW(pswp->wzHttpExp, countof(pswp->wzHttpExp), pwzData);
-                ExitOnFailure(hr, "Failed to copy http expiration string to webdirproperties object");
-            }
-        }
-        else
-        {
-            pswp->fHasHttpExp = FALSE;
-        }
-
-        hr = WcaGetRecordInteger(hRec, wpqCCMaxAge, &pswp->iCacheControlMaxAge);
-        ExitOnFailure(hr, "failed to get IIsWebDirProperties.CacheControlMaxAge");
-
-        hr = WcaGetRecordString(hRec, wpqCCCustom, &pwzData);
-        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.CacheControlCustom");
-        if (pwzData && *pwzData)
-        {
-            pswp->fHasCacheControlCustom = TRUE;
-            if (0 == lstrcmpW(L"-", pwzData))   // remove any existing default cache control custom settings by setting them blank
-            {
-                pswp->wzCacheControlCustom[0] = L'\0';
-            }
-            else   // set the custom cache control setting
-            {
-                hr = ::StringCchCopyW(pswp->wzCacheControlCustom, countof(pswp->wzCacheControlCustom), pwzData);
-                ExitOnFailure(hr, "Failed to copy cache control custom settings to webdirproperites object");
-            }
-        }
-        else
-        {
-            pswp->fHasCacheControlCustom = FALSE;
-        }
-
-        hr = WcaGetRecordInteger(hRec, wpqNoCustomError, &pswp->fNoCustomError);
-        ExitOnFailure(hr, "failed to get IIsWebDirProperties.NoCustomError");
-        if (MSI_NULL_INTEGER == pswp->fNoCustomError)
-            pswp->fNoCustomError = FALSE;
-
-        hr = WcaGetRecordInteger(hRec, wpqAccessSSLFlags, &pswp->iAccessSSLFlags);
-        ExitOnFailure(hr, "failed to get IIsWebDirProperties.AccessSSLFlags");
-
-        hr = WcaGetRecordString(hRec, wpqAuthenticationProviders, &pwzData);
-        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.AuthenticationProviders");
-        if (pwzData && *pwzData)
-        {
-            hr = ::StringCchCopyW(pswp->wzAuthenticationProviders, countof(pswp->wzAuthenticationProviders), pwzData);
-            ExitOnFailure(hr, "Failed to copy authentication providers string to webdirproperties object");
-        }
-        else
-        {
-            pswp->wzAuthenticationProviders[0] = L'\0';
-        }
-    }
-    else if (E_NOMOREITEMS == hr)
-    {
-        WcaLog(LOGMSG_STANDARD, "Error: Cannot locate IIsWebDirProperties.DirProperties='%ls'", wzProperties);
-        hr = E_FAIL;
-    }
-    else
-    {
-        ExitOnFailure(hr, "Error getting appropriate webdirproperty");
-    }
-
-    // Let's check that there isn't more than one record found - if there is, throw an assert like WcaFetchSingleRecord() would
-    HRESULT hrTemp = WcaFetchWrappedRecordWhereString(hWebDirPropQuery, 1, wzProperties, &hRec);
-    if (SUCCEEDED(hrTemp))
-    {
-        AssertSz(E_NOMOREITEMS == hrTemp, "ScaGetWebDirProperties found more than one record");
-    }
-
-LExit:
-    ReleaseStr(pwzData);
-
-    return hr;
-}
-
-
-HRESULT ScaWriteWebDirProperties(
-    __in IMSAdminBase* piMetabase,
-    __in LPCWSTR wzRootOfWeb,
-    __inout SCA_WEB_PROPERTIES* pswp
-    )
-{
-    HRESULT hr = S_OK;
-    DWORD dw = 0;
-    WCHAR wz[METADATA_MAX_NAME_LEN + 1];
-
-    // write the access permissions to the metabase
-    if (MSI_NULL_INTEGER != pswp->iAccess)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ACCESS_PERM, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswp->iAccess));
-        ExitOnFailure(hr, "Failed to write access permissions for Web");
-    }
-
-    if (MSI_NULL_INTEGER != pswp->iAuthorization)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_AUTHORIZATION, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswp->iAuthorization));
-        ExitOnFailure(hr, "Failed to write authorization for Web");
-    }
-
-    if (pswp->fHasUser)
-    {
-        Assert(pswp->scau.wzName);
-        // write the user name
-        if (*pswp->scau.wzDomain)
-        {
-            hr = ::StringCchPrintfW(wz, countof(wz), L"%s\\%s", pswp->scau.wzDomain, pswp->scau.wzName);
-            ExitOnFailure(hr, "Failed to format domain\\username string");
-        }
-        else
-        {
-            hr = ::StringCchCopyW(wz, countof(wz), pswp->scau.wzName);
-            ExitOnFailure(hr, "Failed to copy user name");
-        }
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ANONYMOUS_USER_NAME, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)wz);
-        ExitOnFailure(hr, "Failed to write anonymous user name for Web");
-
-        // write the password
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ANONYMOUS_PWD, METADATA_INHERIT | METADATA_SECURE, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pswp->scau.wzPassword);
-        ExitOnFailure(hr, "Failed to write anonymous user password for Web");
-
-        // store whether IIs controls password
-        dw = (pswp->fIIsControlledPassword) ? TRUE : FALSE;
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ANONYMOUS_USE_SUBAUTH, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)dw));
-        ExitOnFailure(hr, "Failed to write if IIs controls user password for Web");
-    }
-
-    if (MSI_NULL_INTEGER != pswp->fLogVisits)
-    {
-        // The sense of this boolean value is reversed - it is "don't log", not "log visits."
-        dw = (pswp->fLogVisits) ? FALSE : TRUE;
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_DONT_LOG, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)dw));
-        ExitOnFailure(hr, "Failed to write authorization for Web");
-    }
-
-    if (MSI_NULL_INTEGER != pswp->fIndex)
-    {
-        dw = (pswp->fIndex) ? TRUE : FALSE;
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_IS_CONTENT_INDEXED, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)dw));
-        ExitOnFailure(hr, "Failed to write authorization for Web");
-    }
-
-    if (pswp->fHasDefaultDoc)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_DEFAULT_LOAD_FILE, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pswp->wzDefaultDoc);
-        ExitOnFailure(hr, "Failed to write default documents for Web");
-    }
-
-    if (MSI_NULL_INTEGER != pswp->fAspDetailedError)
-    {
-        dw = (pswp->fAspDetailedError) ? TRUE : FALSE;
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_SCRIPTERRORSSENTTOBROWSER, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)dw));
-        ExitOnFailure(hr, "Failed to write ASP script error for Web");
-    }
-
-    if (pswp->fHasHttpExp)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_HTTP_EXPIRES, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pswp->wzHttpExp);
-        ExitOnFailure(hr, "Failed to write HTTP Expiration for Web");
-    }
-
-    if (MSI_NULL_INTEGER != pswp->iCacheControlMaxAge)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_CC_MAX_AGE, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswp->iCacheControlMaxAge));
-        ExitOnFailure(hr, "Failed to write Cache Control Max Age for Web");
-    }
-
-    if (pswp->fHasCacheControlCustom)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_CC_OTHER, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pswp->wzCacheControlCustom);
-        ExitOnFailure(hr, "Failed to write Cache Control Custom for Web");
-    }
-
-    if (pswp->fNoCustomError)
-    {
-        memset(wz, 0, sizeof(wz));
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_CUSTOM_ERROR, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, wz);
-        ExitOnFailure(hr, "Failed to write Custom Error for Web");
-    }
-
-    if (MSI_NULL_INTEGER != pswp->iAccessSSLFlags)
-    {
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_SSL_ACCESS_PERM, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswp->iAccessSSLFlags));
-        ExitOnFailure(hr, "Failed to write AccessSSLFlags for Web");
-    }
-
-    if (*pswp->wzAuthenticationProviders)
-    {
-        hr = ::StringCchCopyW(wz, countof(wz), pswp->wzAuthenticationProviders);
-        ExitOnFailure(hr, "Failed to copy authentication providers string");
-        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_NTAUTHENTICATION_PROVIDERS, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)wz);
-        ExitOnFailure(hr, "Failed to write AuthenticationProviders for Web");
-    }
-
-LExit:
-    return hr;
-}
diff --git a/src/ca/scawebprop.h b/src/ca/scawebprop.h
deleted file mode 100644
index 7a3ae5c9..00000000
--- a/src/ca/scawebprop.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#pragma once
-// 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.
-
-
-#include "scauser.h"
- 
-// global sql queries provided for optimization
-extern LPCWSTR vcsWebDirPropertiesQuery;
-
-
-// structs
-struct SCA_WEB_PROPERTIES
-{
-	WCHAR wzKey[MAX_DARWIN_KEY + 1];
-
-	int iAccess;
-
-	int iAuthorization;
-	BOOL fHasUser;
-	SCA_USER scau;
-	BOOL fIIsControlledPassword;
-
-	BOOL fLogVisits;
-	BOOL fIndex;
-
-	BOOL fHasDefaultDoc;
-	WCHAR wzDefaultDoc[MAX_DARWIN_COLUMN + 1];
-
-	BOOL fHasHttpExp;
-	WCHAR wzHttpExp[MAX_DARWIN_COLUMN + 1];
-
-	BOOL fAspDetailedError;
-
-	int iCacheControlMaxAge;
-
-	BOOL fHasCacheControlCustom;
-	WCHAR wzCacheControlCustom[MAX_DARWIN_COLUMN + 1];
-
-	BOOL fNoCustomError;
-
-	int iAccessSSLFlags;
-
-	WCHAR wzAuthenticationProviders[MAX_DARWIN_COLUMN + 1];
-};
- 
-
-// prototypes
-HRESULT ScaGetWebDirProperties(
-    __in LPCWSTR pwzProperties,
-    __in WCA_WRAPQUERY_HANDLE hUserQuery,
-    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
-    __inout SCA_WEB_PROPERTIES* pswp
-    );
-
-HRESULT ScaWriteWebDirProperties(
-    __in IMSAdminBase* piMetabase,
-    __in LPCWSTR wzRootOfWeb, 
-    __inout SCA_WEB_PROPERTIES* pswp
-    );
-
diff --git a/src/ca/scawebprop7.cpp b/src/ca/scawebprop7.cpp
deleted file mode 100644
index b8d99b0a..00000000
--- a/src/ca/scawebprop7.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-HRESULT ScaWriteWebDirProperties7(
-    __in_z LPCWSTR wzWebName,
-    __in_z LPCWSTR wzRootOfWeb,
-    __in const SCA_WEB_PROPERTIES* pswp
-    )
-{
-    HRESULT hr = S_OK;
-    WCHAR wz[METADATA_MAX_NAME_LEN + 1];
-
-    //all go to same web/root location tag
-    hr = ScaWriteConfigID(IIS_DIRPROP_BEGIN);
-    ExitOnFailure(hr, "Failed to write DirProp begin id");
-    hr = ScaWriteConfigString(wzWebName);                //site name key
-    ExitOnFailure(hr, "Failed to write DirProp web key");
-    hr = ScaWriteConfigString(wzRootOfWeb);               //app path key
-    ExitOnFailure(hr, "Failed to write DirProp app key");
-
-    // write the access permissions to the metabase
-    if (MSI_NULL_INTEGER != pswp->iAccess)
-    {
-        hr = ScaWriteConfigID(IIS_DIRPROP_ACCESS);
-        ExitOnFailure(hr, "Failed to write DirProp access id");
-        hr = ScaWriteConfigInteger(pswp->iAccess);
-        ExitOnFailure(hr, "Failed to write access permissions for Web");
-    }
-
-    if (MSI_NULL_INTEGER != pswp->iAuthorization)
-    {
-        hr = ScaWriteConfigID(IIS_DIRPROP_AUTH);
-        ExitOnFailure(hr, "Failed to write DirProp auth id");
-        hr = ScaWriteConfigInteger(pswp->iAuthorization);
-        ExitOnFailure(hr, "Failed to write authorization for Web");
-    }
-
-    if (pswp->fHasUser)
-    {
-        Assert(pswp->scau.wzName);
-        // write the user name
-        if (*pswp->scau.wzDomain)
-        {
-            hr = ::StringCchPrintfW(wz, countof(wz), L"%s\\%s", pswp->scau.wzDomain, pswp->scau.wzName);
-            ExitOnFailure(hr, "Failed to format domain\\username string");
-        }
-        else
-        {
-#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
-            hr = ::StringCchCopyW(wz, countof(wz), pswp->scau.wzName);
-            ExitOnFailure(hr, "Failed to copy user name");
-        }
-        hr = ScaWriteConfigID(IIS_DIRPROP_USER);
-        ExitOnFailure(hr, "Failed to write DirProp user id");
-        hr = ScaWriteConfigString(wz);
-        ExitOnFailure(hr, "Failed to write anonymous user name for Web");
-
-        // write the password
-        hr = ScaWriteConfigID(IIS_DIRPROP_PWD);
-        ExitOnFailure(hr, "Failed to write DirProp pwd id");
-        hr = ScaWriteConfigString(pswp->scau.wzPassword);
-        ExitOnFailure(hr, "Failed to write anonymous user password for Web");
-
-        if (pswp->fIIsControlledPassword)
-        {
-            //Not Supported by IIS7 : pswp->fIIsControlledPassword
-            WcaLog(LOGMSG_VERBOSE, "Not supported by IIS7: WebDirProperties.IIsControlledPassword, ignoring");
-        }
-    }
-
-    if (MSI_NULL_INTEGER != pswp->fLogVisits)
-    {
-        hr = ScaWriteConfigID(IIS_DIRPROP_LOGVISITS);
-        ExitOnFailure(hr, "Failed to write DirProp logVisits id");
-        hr = ScaWriteConfigInteger(pswp->fLogVisits ? FALSE : TRUE); // we capture "should log" but IIS7 wants "should not log"
-        ExitOnFailure(hr, "Failed to write DirProp logVisits");
-    }
-
-    if (MSI_NULL_INTEGER != pswp->fIndex)
-    {
-        //Not Supported by IIS7 : pswp->fIndex
-        WcaLog(LOGMSG_VERBOSE, "Not supported by IIS7: WebDirProperties.Index, ignoring");
-    }
-
-    if (pswp->fHasDefaultDoc)
-    {
-        hr = ScaWriteConfigID(IIS_DIRPROP_DEFDOCS);
-        ExitOnFailure(hr, "Failed to write DirProp defdocs id");
-        hr = ScaWriteConfigString(pswp->wzDefaultDoc);
-        ExitOnFailure(hr, "Failed to write default documents for Web");
-    }
-
-    if (MSI_NULL_INTEGER != pswp->fAspDetailedError)
-    {
-        hr = ScaWriteConfigID(IIS_DIRPROP_ASPERROR);
-        ExitOnFailure(hr, "Failed to write ASP script error id");
-        hr = ScaWriteConfigInteger(pswp->fAspDetailedError);
-        ExitOnFailure(hr, "Failed to write ASP script error for Web");
-    }
-
-    if (pswp->fHasHttpExp)
-    {
-        hr = ScaWriteConfigID(IIS_DIRPROP_HTTPEXPIRES);
-        ExitOnFailure(hr, "Failed to write DirProp HttpExpires id");
-        hr = ScaWriteConfigString(pswp->wzHttpExp);
-        ExitOnFailure(hr, "Failed to write DirProp HttpExpires value");
-    }
-
-    if (MSI_NULL_INTEGER != pswp->iCacheControlMaxAge)
-    {
-        hr = ScaWriteConfigID(IIS_DIRPROP_MAXAGE);
-        ExitOnFailure(hr, "Failed to write DirProp MaxAge id");
-        hr = ScaWriteConfigInteger(pswp->iCacheControlMaxAge);
-        ExitOnFailure(hr, "Failed to write DirProp MaxAge value");
-    }
-
-    if (pswp->fHasCacheControlCustom)
-    {
-        hr = ScaWriteConfigID(IIS_DIRPROP_CACHECUST);
-        ExitOnFailure(hr, "Failed to write DirProp Cache Control Custom id");
-        hr = ScaWriteConfigString(pswp->wzCacheControlCustom);
-        ExitOnFailure(hr, "Failed to write Cache Control Custom for Web");
-    }
-
-    if (pswp->fNoCustomError)
-    {
-        hr = ScaWriteConfigID(IIS_DIRPROP_NOCUSTERROR);
-        ExitOnFailure(hr, "Failed to write DirProp clear Cust Errors id");
-    }
-
-    if (MSI_NULL_INTEGER != pswp->iAccessSSLFlags)
-    {
-        hr = ScaWriteConfigID(IIS_DIRPROP_SSLFLAGS);
-        ExitOnFailure(hr, "Failed to write DirProp sslFlags id");
-        hr = ScaWriteConfigInteger(pswp->iAccessSSLFlags);
-        ExitOnFailure(hr, "Failed to write AccessSSLFlags for Web");
-    }
-
-    if (*pswp->wzAuthenticationProviders)
-    {
-        hr = ::StringCchCopyW(wz, countof(wz), pswp->wzAuthenticationProviders);
-        ExitOnFailure(hr, "Failed to copy authentication providers string");
-        hr = ScaWriteConfigID(IIS_DIRPROP_AUTHPROVID);
-        ExitOnFailure(hr, "Failed to write DirProp AuthProvid id");
-        hr = ScaWriteConfigString(wz);
-        ExitOnFailure(hr, "Failed to write AuthenticationProviders for Web");
-    }
-    //End of Dir Properties
-    hr = ScaWriteConfigID(IIS_DIRPROP_END);
-    ExitOnFailure(hr, "Failed to write DirProp end id");
-
-LExit:
-    return hr;
-}
diff --git a/src/ca/scawebprop7.h b/src/ca/scawebprop7.h
deleted file mode 100644
index a97e8679..00000000
--- a/src/ca/scawebprop7.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#pragma once
-// 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.
-
-
-#include "scauser.h"
-
-HRESULT ScaWriteWebDirProperties7(
-    __in_z LPCWSTR wzwWebName,
-    __in_z LPCWSTR wzRootOfWeb,
-    const SCA_WEB_PROPERTIES* pswp
-    );
-
diff --git a/src/ca/scawebsvcext.cpp b/src/ca/scawebsvcext.cpp
deleted file mode 100644
index 369e951b..00000000
--- a/src/ca/scawebsvcext.cpp
+++ /dev/null
@@ -1,343 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-// sql queries
-enum eWebSvcExtQuery { ldqComponent=1 , ldqFile, ldqDescription, ldqGroup, ldqAttributes, ldqInstalled, ldqAction };
-
-
-LPCWSTR vcsWebSvcExtRoot = L"/LM/W3SVC";
-
-// prototypes for private helper functions
-static HRESULT AddWebSvcExtToList(
-    __in SCA_WEBSVCEXT** ppsWseList
-    );
-
-//static HRESULT ScaCheckWebSvcExtValue(
-//    __in IMSAdminBase* piMetabase,
-//    __in DWORD dwMDIdentifier
-//    );
-
-static HRESULT ScaWebSvcExtInstall(
-    __in LPWSTR *pwzWebSvcExtList,
-    __in DWORD_PTR *pcchWebSvcExtList,
-    __in SCA_WEBSVCEXT* psWseList
-    );
-
-static HRESULT ScaWebSvcExtUninstall(
-    __in LPWSTR *pwzWebSvcExtList,
-    __in const DWORD *pcchWebSvcExtList,
-    __in SCA_WEBSVCEXT* psWseList
-    );
-
-// functions
-
-HRESULT __stdcall ScaWebSvcExtRead(
-    __in SCA_WEBSVCEXT** ppsWseList,
-    __inout LPWSTR *ppwzCustomActionData
-    )
-{
-    Assert(ppsWseList);
-
-    HRESULT hr = S_OK;
-    MSIHANDLE hRec;
-    LPWSTR pwzData = NULL;
-    INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN;
-    INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN;
-    SCA_WEBSVCEXT* psWebSvcExt = NULL;
-    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
-
-    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
-    ExitOnFailure(hr, "Failed to unwrap query for ScaWebSvcExtRead");
-
-    if (0 == WcaGetQueryRecords(hWrapQuery))
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ScaWebSvcExtRead() because IIsWebServiceExtension data not present");
-        ExitFunction1(hr = S_FALSE);
-    }
-
-    // loop through all the web service extensions
-    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
-    {
-        // Get the Component first.  If the Component is not being modified during
-        // this transaction, skip processing this whole record.
-        hr = WcaGetRecordString(hRec, ldqComponent, &pwzData);
-        ExitOnFailure(hr, "Failed to get Component for WebSvcExt");
-
-        hr = WcaGetRecordInteger(hRec, ldqInstalled, (int *)&isInstalled);
-        ExitOnFailure(hr, "Failed to get Component installed state for WebSvcExt");
-
-        hr = WcaGetRecordInteger(hRec, ldqAction, (int *)&isAction);
-        ExitOnFailure(hr, "Failed to get Component action state for WebSvcExt");
-
-        if (!WcaIsInstalling(isInstalled, isAction) &&
-            !WcaIsReInstalling(isInstalled, isAction) &&
-            !WcaIsUninstalling(isInstalled, isAction))
-        {
-            continue; // skip this record.
-        }
-
-        hr = AddWebSvcExtToList(ppsWseList);
-        ExitOnFailure(hr, "failed to add element to web svc ext list");
-
-        psWebSvcExt = *ppsWseList;
-        Assert(psWebSvcExt);
-
-        psWebSvcExt->isInstalled = isInstalled;
-        psWebSvcExt->isAction = isAction;
-
-        hr = WcaGetRecordString(hRec, ldqFile, &pwzData);
-        ExitOnFailure(hr, "Failed to get File for WebSvcExt");
-        hr = ::StringCchCopyW(psWebSvcExt->wzFile, countof(psWebSvcExt->wzFile), pwzData);
-        ExitOnFailure(hr, "Failed to copy File for WebSvcExt");
-
-        hr = WcaGetRecordString(hRec, ldqDescription, &pwzData);
-        ExitOnFailure(hr, "Failed to get Description for WebSvcExt");
-        hr = ::StringCchCopyW(psWebSvcExt->wzDescription, countof(psWebSvcExt->wzDescription), pwzData);
-        ExitOnFailure(hr, "Failed to copy Description for WebSvcExt");
-
-        hr = WcaGetRecordString(hRec, ldqGroup, &pwzData);
-        ExitOnFailure(hr, "Failed to get Group for WebSvcExt");
-        hr = ::StringCchCopyW(psWebSvcExt->wzGroup, countof(psWebSvcExt->wzGroup), pwzData);
-        ExitOnFailure(hr, "Failed to copy Group for WebSvcExt");
-
-        hr = WcaGetRecordInteger(hRec, ldqAttributes, &psWebSvcExt->iAttributes);
-        ExitOnFailure(hr, "Failed to get Attributes for WebSvcExt");
-    }
-
-    if (E_NOMOREITEMS == hr)
-        hr = S_OK;
-    ExitOnFailure(hr, "Failure while processing WebSvcExt");
-
-LExit:
-    WcaFinishUnwrapQuery(hWrapQuery);
-
-    ReleaseStr(pwzData);
-
-    return hr;
-}
-
-
-// Commit does both install and uninstall
-HRESULT __stdcall ScaWebSvcExtCommit(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_WEBSVCEXT* psWseList
-    )
-{
-    Assert(piMetabase);
-
-    HRESULT hr = S_OK;
-    METADATA_RECORD mr;
-
-    LPWSTR wzWebSvcExtList = NULL;
-    DWORD cbWebSvcExtList = 0;
-    DWORD_PTR cchWebSvcExtList = 0;
-
-    if (!psWseList)
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ScaWebSvcExtCommit() because there are no web service extensions in the list");
-        ExitFunction();
-    }
-
-    // Get current set of web service extensions.
-    ::ZeroMemory(&mr, sizeof(mr));
-    mr.dwMDIdentifier = MD_WEB_SVC_EXT_RESTRICTION_LIST;
-    mr.dwMDAttributes = 0;
-    mr.dwMDUserType  = IIS_MD_UT_SERVER;
-    mr.dwMDDataType = ALL_METADATA;
-    mr.pbMDData = NULL;
-    mr.dwMDDataLen = 0;
-
-    hr = piMetabase->GetData(METADATA_MASTER_ROOT_HANDLE, vcsWebSvcExtRoot, &mr, &cbWebSvcExtList);
-    if (MD_ERROR_DATA_NOT_FOUND == hr)
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ScaWebSvcExtCommit() because WebSvcExtRestrictionList value is not present");
-        ExitFunction1(hr = S_FALSE);
-    }
-    else if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr)
-    {
-        // cchWebSvcExtList is returned in bytes. Convert to WCHAR size to call StrAlloc
-        cchWebSvcExtList = cbWebSvcExtList / sizeof(WCHAR);
-        hr = StrAlloc(&wzWebSvcExtList, cchWebSvcExtList);
-        ExitOnFailure(hr, "Failed allocating space for web service extensions");
-    }
-    else
-    {
-        ExitOnFailure(hr, "Failed retrieving web service extensions");
-    }
-
-    mr.pbMDData = (unsigned char*)wzWebSvcExtList;
-    mr.dwMDDataLen = cbWebSvcExtList;
-
-    hr = piMetabase->GetData(METADATA_MASTER_ROOT_HANDLE, vcsWebSvcExtRoot, &mr, &cbWebSvcExtList);
-    ExitOnFailure(hr, "Failed retrieving web service extensions");
-
-    // Make changes to local copy of metabase
-    while (psWseList)
-    {
-        if (WcaIsInstalling(psWseList->isInstalled, psWseList->isAction))
-        {
-            hr = ScaWebSvcExtInstall(&wzWebSvcExtList, &cchWebSvcExtList, psWseList);
-            ExitOnFailure(hr, "Failed to install Web Service extension");
-        }
-        else if (WcaIsUninstalling(psWseList->isInstalled, psWseList->isAction))
-        {
-            hr = ScaWebSvcExtUninstall(&wzWebSvcExtList, (DWORD *)&cchWebSvcExtList, psWseList);
-            ExitOnFailure(hr, "Failed to uninstall Web Service extension");
-        }
-
-        psWseList = psWseList->psWseNext;
-    }
-
-    // Write Metabase
-    hr = ScaWriteMetabaseValue(piMetabase, vcsWebSvcExtRoot, NULL, MD_WEB_SVC_EXT_RESTRICTION_LIST, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, wzWebSvcExtList);
-    ExitOnFailure(hr, "Failed to write WebServiceExtensions: '%ls'", wzWebSvcExtList);
-
-LExit:
-    ReleaseStr(wzWebSvcExtList);
-
-    return hr;
-}
-
-
-static HRESULT ScaWebSvcExtInstall(
-    __in LPWSTR *ppwzWebSvcExtList,
-    __in DWORD_PTR *pcchWebSvcExtList,
-    __in SCA_WEBSVCEXT* psWseList
-    )
-{
-    Assert( ppwzWebSvcExtList && pcchWebSvcExtList && psWseList);
-    Assert(*ppwzWebSvcExtList);
-
-    HRESULT hr = S_OK;
-
-    LPWSTR pwzWebSvcExt = NULL;
-    int iAllow;
-    int iUiDeletable;
-
-    BOOL fAlreadyExists = FALSE;
-    DWORD_PTR dwIndex = 0xFFFFFFFF;
-    LPCWSTR wzFoundString = NULL;
-
-    // Check if it's already in there
-    hr = MultiSzFindSubstring(*ppwzWebSvcExtList, psWseList->wzFile, &dwIndex, &wzFoundString);
-    ExitOnFailure(hr, "failed to search for string:%ls in web service extension MULTISZ", psWseList->wzFile);
-
-    if (S_FALSE != hr && NULL != wcsstr(wzFoundString, psWseList->wzGroup) && NULL != wcsstr(wzFoundString, psWseList->wzDescription))
-    {
-        fAlreadyExists = TRUE;
-    }
-
-    // Construct the single string in the format required for the WebSvc Ext list in metabase
-    iAllow = (psWseList->iAttributes & 1);
-    iUiDeletable = ((psWseList->iAttributes >> 1) & 1);
-    hr = StrAllocFormatted(&pwzWebSvcExt, L"%d,%s,%d,%s,%s", iAllow, psWseList->wzFile, iUiDeletable, psWseList->wzGroup, psWseList->wzDescription);
-    ExitOnFailure(hr, "Failure allocating space for web service extensions");
-
-    if (fAlreadyExists)
-    {
-        hr = MultiSzReplaceString(ppwzWebSvcExtList, dwIndex, pwzWebSvcExt);
-        ExitOnFailure(hr, "failed to update web service extension string: %ls", pwzWebSvcExt);
-    }
-    else
-    {
-        hr = MultiSzPrepend(ppwzWebSvcExtList, pcchWebSvcExtList, pwzWebSvcExt);
-        ExitOnFailure(hr, "failed to prepend web service extension string: %ls", pwzWebSvcExt);
-    }
-
-LExit:
-    ReleaseStr(pwzWebSvcExt);
-
-    return hr;
-}
-
-
-static HRESULT ScaWebSvcExtUninstall(
-    __in LPWSTR *ppwzWebSvcExtList,
-    __in const DWORD* /*pcchWebSvcExtList*/,
-    __in SCA_WEBSVCEXT* psWseList
-    )
-{
-    Assert(ppwzWebSvcExtList && *ppwzWebSvcExtList && psWseList);
-    Assert(*ppwzWebSvcExtList);
-
-    HRESULT hr = S_OK;
-    DWORD_PTR dwIndex = 0xFFFFFFFF;
-    LPCWSTR wzFoundString = NULL;
-
-    // Find the string to remove
-    hr = MultiSzFindSubstring(*ppwzWebSvcExtList, psWseList->wzFile, &dwIndex, &wzFoundString);
-    ExitOnFailure(hr, "failed to search for string:%ls in web service extension MULTISZ", psWseList->wzFile);
-
-    // If we found a match (ignoring the Allow and Deletable flags)
-    if (S_FALSE != hr && NULL != wcsstr(wzFoundString, psWseList->wzGroup) && NULL != wcsstr(wzFoundString, psWseList->wzDescription))
-    {
-        hr = MultiSzRemoveString(ppwzWebSvcExtList, dwIndex);
-        ExitOnFailure(hr, "failed to remove string: %d from web service extension MULTISZ", dwIndex);
-    }
-
-LExit:
-    return hr;
-}
-
-
-//static HRESULT ScaCheckWebSvcExtValue(
-//    __in IMSAdminBase* piMetabase,
-//    __in DWORD dwMDIdentifier
-//    )
-//{
-//    if (!piMetabase)
-//    {
-//        return E_INVALIDARG;
-//    }
-//
-//    HRESULT hr = S_OK;
-//    METADATA_RECORD mr = { 0 };
-//    DWORD cch = 0;
-//
-//    mr.dwMDIdentifier = dwMDIdentifier;
-//    mr.dwMDUserType  = IIS_MD_UT_SERVER;
-//
-//    hr = piMetabase->GetData(METADATA_MASTER_ROOT_HANDLE, vcsWebSvcExtRoot, &mr, &cch);
-//    if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr)
-//    {
-//        hr = S_OK;
-//    }
-//    else if (MD_ERROR_DATA_NOT_FOUND == hr)
-//    {
-//        hr = S_FALSE;
-//    }
-//
-//    return hr;
-//}
-
-
-void ScaWebSvcExtFreeList(
-    __in SCA_WEBSVCEXT* psWseList
-    )
-{
-    SCA_WEBSVCEXT* psWseDelete = psWseList;
-    while (psWseList)
-    {
-        psWseDelete = psWseList;
-        psWseList = psWseList->psWseNext;
-        MemFree(psWseDelete);
-    }
-}
-
-
-static HRESULT AddWebSvcExtToList(
-    __in SCA_WEBSVCEXT** ppsWseList
-    )
-{
-    HRESULT hr = S_OK;
-
-    SCA_WEBSVCEXT* psWse = static_cast<SCA_WEBSVCEXT*>(MemAlloc(sizeof(SCA_WEBSVCEXT), TRUE));
-    ExitOnNull(psWse, hr, E_OUTOFMEMORY, "failed to allocate element for web svc ext list");
-
-    psWse->psWseNext = *ppsWseList;
-    *ppsWseList = psWse;
-
-LExit:
-    return hr;
-}
diff --git a/src/ca/scawebsvcext.h b/src/ca/scawebsvcext.h
deleted file mode 100644
index 4d225b09..00000000
--- a/src/ca/scawebsvcext.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#pragma once
-// 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.
-
-
-enum SCA_WEBSVCEXT_ATTRIBUTES { SWSEATTRIB_ALLOW = 1, SWSEATTRIB_UIDELETABLE = 2 };
-
-struct SCA_WEBSVCEXT
-{
-    // darwin information
-    INSTALLSTATE isInstalled;
-    INSTALLSTATE isAction;
-
-    // iis configuation information
-    WCHAR wzFile[MAX_PATH + 1];
-    WCHAR wzDescription[MAX_DARWIN_COLUMN + 1];
-    WCHAR wzGroup[MAX_DARWIN_COLUMN + 1];
-
-    int iAttributes;
-
-    SCA_WEBSVCEXT* psWseNext;
-};
-
-HRESULT __stdcall ScaWebSvcExtRead(
-    __in SCA_WEBSVCEXT** ppsWseList,
-    __inout LPWSTR *ppwzCustomActionData
-    );
-
-HRESULT ScaWebSvcExtCommit(
-    __in IMSAdminBase* piMetabase,
-    __in SCA_WEBSVCEXT* psWseList
-    );
-
-void ScaWebSvcExtFreeList(
-    __in SCA_WEBSVCEXT* psWseList
-    );
diff --git a/src/ca/scawebsvcext7.cpp b/src/ca/scawebsvcext7.cpp
deleted file mode 100644
index dcf2f7f8..00000000
--- a/src/ca/scawebsvcext7.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-// 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.
-
-#include "precomp.h"
-
-static HRESULT ScaWebSvcExtInstall(
-    const SCA_WEBSVCEXT* psWseList
-    );
-
-static HRESULT ScaWebSvcExtUninstall(
-    const SCA_WEBSVCEXT* psWseList
-    );
-
-// functions
-// Commit does both install and uninstall
-HRESULT __stdcall ScaWebSvcExtCommit7(
-    __in SCA_WEBSVCEXT* psWseList
-    )
-{
-    HRESULT hr = S_OK;
-
-    if (!psWseList)
-    {
-        WcaLog(LOGMSG_VERBOSE, "Skipping ScaWebSvcExtCommit() because there are no web service extensions in the list");
-        ExitFunction();
-    }
-
-    // Make changes to local copy of metabase
-    while (psWseList)
-    {
-        if (WcaIsInstalling(psWseList->isInstalled, psWseList->isAction))
-        {
-            hr = ScaWebSvcExtInstall(psWseList);
-            ExitOnFailure(hr, "Failed to install Web Service extension");
-        }
-        else if (WcaIsUninstalling(psWseList->isInstalled, psWseList->isAction))
-        {
-            hr = ScaWebSvcExtUninstall(psWseList);
-            ExitOnFailure(hr, "Failed to uninstall Web Service extension");
-        }
-
-        psWseList = psWseList->psWseNext;
-    }
-
-
-LExit:
-
-    return hr;
-}
-
-
-static HRESULT ScaWebSvcExtInstall(
-    const SCA_WEBSVCEXT* psWseList
-    )
-{
-    HRESULT hr = S_OK;
-    int iAllow;
-
-    //Write CAData actions
-    hr = ScaWriteConfigID(IIS_WEB_SVC_EXT);
-    ExitOnFailure(hr, "failed add web svc ext ID");
-    hr = ScaWriteConfigID(IIS_CREATE);
-    ExitOnFailure(hr, "failed add web svc ext action");
-
-    // write File path
-    hr = ScaWriteConfigString(psWseList->wzFile);
-    ExitOnFailure(hr, "failed add web svc ext file path");
-
-    // write allowed
-    // unDeleatable n/a in IIS7
-    iAllow = (psWseList->iAttributes & 1);
-    hr = ScaWriteConfigInteger(iAllow);
-    ExitOnFailure(hr, "failed add web svc ext Allowed");
-
-    //write group
-    hr = ScaWriteConfigString(psWseList->wzGroup);
-    ExitOnFailure(hr, "failed add web svc ext group");
-
-    //write description
-    hr = ScaWriteConfigString(psWseList->wzDescription);
-    ExitOnFailure(hr, "failed add web svc ext description");
-
-LExit:
-
-    return hr;
-}
-
-
-static HRESULT ScaWebSvcExtUninstall(
-    const SCA_WEBSVCEXT* psWseList
-    )
-{
-    HRESULT hr = S_OK;
-
-    //Write CAData actions
-    hr = ScaWriteConfigID(IIS_WEB_SVC_EXT);
-    ExitOnFailure(hr, "failed add web svc ext ID");
-    hr = ScaWriteConfigID(IIS_DELETE);
-    ExitOnFailure(hr, "failed add web svc ext action");
-
-    // write File path (Key)
-    hr = ScaWriteConfigString(psWseList->wzFile);
-    ExitOnFailure(hr, "failed add web svc ext file path");
-
-LExit:
-    return hr;
-}
diff --git a/src/ca/scawebsvcext7.h b/src/ca/scawebsvcext7.h
deleted file mode 100644
index 1a686aed..00000000
--- a/src/ca/scawebsvcext7.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#pragma once
-// 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.
-
-
-HRESULT ScaWebSvcExtCommit7(
-    __in SCA_WEBSVCEXT* psWseList
-    );
-
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 @@
+<!-- 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. -->
+<!--
+  Do NOT modify this file. Update the canonical version in Home\repo-template\src\CSharp.Build.props
+  then update all of the repos.
+-->
+<Project>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)wix.snk))</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+</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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<Project>
+  <PropertyGroup>
+    <Platform Condition=" '$(Platform)' == '' OR '$(Platform)' == 'AnyCPU' ">Win32</Platform>
+    <IntDir>$(BaseIntermediateOutputPath)$(Configuration)\$(Platform)\</IntDir>
+    <OutDir>$(OutputPath)$(Platform)\</OutDir>
+  </PropertyGroup>
+
+  <PropertyGroup Condition="'$(WindowsTargetPlatformVersion)'=='' AND '$(VisualStudioVersion)'>='15.0'">
+    <WindowsTargetPlatformVersion>$([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0'))</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <DisableSpecificWarnings>$(DisableSpecificCompilerWarnings)</DisableSpecificWarnings>
+      <WarningLevel>Level4</WarningLevel>
+      <AdditionalIncludeDirectories>$(ProjectDir)inc;$(MSBuildProjectDirectory);$(IntDir);$(SqlCESdkIncludePath);$(ProjectAdditionalIncludeDirectories);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;_WIN32_MSI=500;_WIN32_WINNT=0x0501;$(ArmPreprocessorDefinitions);$(UnicodePreprocessorDefinitions);_CRT_STDIO_LEGACY_WIDE_SPECIFIERS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
+      <CallingConvention Condition="'$(Platform)'=='Win32'">StdCall</CallingConvention>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <ExceptionHandling>false</ExceptionHandling>
+      <AdditionalOptions>-YlprecompDefine</AdditionalOptions>
+      <AdditionalOptions Condition=" $(PlatformToolset.StartsWith('v14')) ">/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
+      <MultiProcessorCompilation Condition=" $(NUMBER_OF_PROCESSORS) &gt; 4 ">true</MultiProcessorCompilation>
+    </ClCompile>
+    <ResourceCompile>
+      <PreprocessorDefinitions>$(ArmPreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectAdditionalResourceIncludeDirectories);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+    <Lib>
+      <AdditionalLibraryDirectories>$(OutDir);$(AdditionalMultiTargetLibraryPath);$(ProjectAdditionalLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+    </Lib>
+    <Link>
+      <SubSystem>$(ProjectSubSystem)</SubSystem>
+      <ModuleDefinitionFile>$(ProjectModuleDefinitionFile)</ModuleDefinitionFile>
+      <NoEntryPoint>$(ResourceOnlyDll)</NoEntryPoint>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>$(ProjectAdditionalLinkLibraries);advapi32.lib;comdlg32.lib;user32.lib;oleaut32.lib;gdi32.lib;shell32.lib;ole32.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(OutDir);$(AdditionalMultiTargetLibraryPath);$(ArmLibraryDirectories);$(ProjectAdditionalLinkLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalOptions Condition=" $(PlatformToolset.StartsWith('v14')) ">/IGNORE:4099 %(AdditionalOptions)</AdditionalOptions>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemDefinitionGroup Condition=" '$(Platform)'=='Win32' and '$(PlatformToolset)'!='v100'">
+    <ClCompile>
+      <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition=" '$(Platform)'=='arm' ">
+    <ClCompile>
+      <CallingConvention>CDecl</CallingConvention>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition=" '$(ConfigurationType)'=='StaticLibrary' ">
+    <ClCompile>
+      <DebugInformationFormat>OldStyle</DebugInformationFormat>
+      <OmitDefaultLibName>true</OmitDefaultLibName>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition=" '$(Configuration)'=='Debug' ">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <PreprocessorDefinitions>_DEBUG;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition=" '$(Configuration)'=='Release' ">
+    <ClCompile>
+      <Optimization>MinSpace</Optimization>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+</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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+<!--
+  Do NOT modify this file. Update the canonical version in Home\repo-template\src\Directory.Build.props
+  then update all of the repos.
+-->
+<Project>
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <EnableSourceLink Condition=" '$(NCrunch)' == '1' ">false</EnableSourceLink>
+    <MSBuildWarningsAsMessages>MSB3246</MSBuildWarningsAsMessages>
+
+    <ProjectName Condition=" '$(ProjectName)' == '' ">$(MSBuildProjectName)</ProjectName>
+    <BaseOutputPath>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\build\))</BaseOutputPath>
+    <BaseIntermediateOutputPath>$(BaseOutputPath)obj\$(ProjectName)\</BaseIntermediateOutputPath>
+    <OutputPath>$(BaseOutputPath)$(Configuration)\</OutputPath>
+
+    <Authors>WiX Toolset Team</Authors>
+    <Company>WiX Toolset</Company>
+    <Copyright>Copyright (c) .NET Foundation and contributors. All rights reserved.</Copyright>
+    <PackageLicenseExpression>MS-RL</PackageLicenseExpression>
+    <Product>WiX Toolset</Product>
+  </PropertyGroup>
+
+  <Import Project="CSharp.Build.props" Condition=" '$(MSBuildProjectExtension)'=='.csproj' and Exists('CSharp.Build.props') " />
+  <Import Project="Cpp.Build.props" Condition=" Exists('Cpp.Build.props') And '$(MSBuildProjectExtension)'=='.vcxproj' " />
+  <Import Project="Wix.Build.props" Condition=" Exists('Wix.Build.props') And '$(MSBuildProjectExtension)'=='.wixproj' " />
+  <Import Project="Custom.Build.props" Condition=" Exists('Custom.Build.props') " />
+</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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+<!--
+  Do NOT modify this file. Update the canonical version in Home\repo-template\src\Directory.Build.targets
+  then update all of the repos.
+-->
+<!--
+  Replace PackageReferences with ProjectReferences when the projects can be found in .sln.
+  See the original here: https://github.com/dotnet/sdk/issues/1151#issuecomment-385133284
+-->
+<Project>
+  <PropertyGroup>
+    <ReplacePackageReferences>true</ReplacePackageReferences>
+    <TheSolutionPath Condition=" '$(NCrunch)'=='' ">$(SolutionPath)</TheSolutionPath>
+    <TheSolutionPath Condition=" '$(NCrunch)'=='1' ">$(NCrunchOriginalSolutionPath)</TheSolutionPath>
+  </PropertyGroup>
+
+  <Choose>
+    <When Condition="$(ReplacePackageReferences) AND '$(TheSolutionPath)' != '' AND '$(TheSolutionPath)' != '*undefined*' AND Exists('$(TheSolutionPath)')">
+
+      <PropertyGroup>
+        <SolutionFileContent>$([System.IO.File]::ReadAllText($(TheSolutionPath)))</SolutionFileContent>
+        <SmartSolutionDir>$([System.IO.Path]::GetDirectoryName( $(TheSolutionPath) ))</SmartSolutionDir>
+        <RegexPattern>(?&lt;="[PackageName]", ")(.*)(?=", ")</RegexPattern>
+      </PropertyGroup>
+
+      <ItemGroup>
+        <!-- Keep the identity of the PackageReference -->
+        <SmartPackageReference Include="@(PackageReference)">
+          <PackageName>%(Identity)</PackageName>
+          <InSolution>$(SolutionFileContent.Contains('\%(Identity).csproj'))</InSolution>
+        </SmartPackageReference>
+
+        <!-- Filter them by mapping them to another ItemGroup using the WithMetadataValue item function -->
+        <PackageInSolution Include="@(SmartPackageReference->WithMetadataValue('InSolution', True))">
+          <Pattern>$(RegexPattern.Replace('[PackageName]','%(PackageName)') )</Pattern>
+          <SmartPath>$([System.Text.RegularExpressions.Regex]::Match('$(SolutionFileContent)', '%(Pattern)'))</SmartPath>
+        </PackageInSolution>
+
+        <ProjectReference  Include="@(PackageInSolution->'$(SmartSolutionDir)\%(SmartPath)' )"/>
+
+        <!-- Remove the package references that are now referenced as projects -->
+        <PackageReference Remove="@(PackageInSolution->'%(PackageName)' )"/>
+      </ItemGroup>
+
+    </When>
+  </Choose>
+</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 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30204.135
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iisca", "src\ca\iisca.vcxproj", "{CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}"
+EndProject
+Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "iis", "src\wixlib\iis.wixproj", "{92FE99D2-355D-4F52-A7C1-10EECB4A5BB1}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Iis.wixext", "src\wixext\WixToolset.Iis.wixext.csproj", "{612029FB-B5D4-4D7E-B794-A0E202BFE493}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.Iis", "src\test\WixToolsetTest.Iis\WixToolsetTest.Iis.csproj", "{E62712D7-31A1-49E4-B1F4-0084FAD14193}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Debug|x86 = Debug|x86
+		Release|Any CPU = Release|Any CPU
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}.Debug|Any CPU.ActiveCfg = Debug|Win32
+		{CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}.Debug|Any CPU.Build.0 = Debug|Win32
+		{CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}.Debug|x86.ActiveCfg = Debug|Win32
+		{CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}.Debug|x86.Build.0 = Debug|Win32
+		{CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}.Release|Any CPU.ActiveCfg = Release|Win32
+		{CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}.Release|x86.ActiveCfg = Release|Win32
+		{CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}.Release|x86.Build.0 = Release|Win32
+		{92FE99D2-355D-4F52-A7C1-10EECB4A5BB1}.Debug|Any CPU.ActiveCfg = Debug|x86
+		{92FE99D2-355D-4F52-A7C1-10EECB4A5BB1}.Debug|x86.ActiveCfg = Debug|x86
+		{92FE99D2-355D-4F52-A7C1-10EECB4A5BB1}.Debug|x86.Build.0 = Debug|x86
+		{92FE99D2-355D-4F52-A7C1-10EECB4A5BB1}.Release|Any CPU.ActiveCfg = Release|x86
+		{92FE99D2-355D-4F52-A7C1-10EECB4A5BB1}.Release|x86.ActiveCfg = Release|x86
+		{92FE99D2-355D-4F52-A7C1-10EECB4A5BB1}.Release|x86.Build.0 = Release|x86
+		{612029FB-B5D4-4D7E-B794-A0E202BFE493}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{612029FB-B5D4-4D7E-B794-A0E202BFE493}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{612029FB-B5D4-4D7E-B794-A0E202BFE493}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{612029FB-B5D4-4D7E-B794-A0E202BFE493}.Debug|x86.Build.0 = Debug|Any CPU
+		{612029FB-B5D4-4D7E-B794-A0E202BFE493}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{612029FB-B5D4-4D7E-B794-A0E202BFE493}.Release|Any CPU.Build.0 = Release|Any CPU
+		{612029FB-B5D4-4D7E-B794-A0E202BFE493}.Release|x86.ActiveCfg = Release|Any CPU
+		{612029FB-B5D4-4D7E-B794-A0E202BFE493}.Release|x86.Build.0 = Release|Any CPU
+		{E62712D7-31A1-49E4-B1F4-0084FAD14193}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{E62712D7-31A1-49E4-B1F4-0084FAD14193}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{E62712D7-31A1-49E4-B1F4-0084FAD14193}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{E62712D7-31A1-49E4-B1F4-0084FAD14193}.Debug|x86.Build.0 = Debug|Any CPU
+		{E62712D7-31A1-49E4-B1F4-0084FAD14193}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{E62712D7-31A1-49E4-B1F4-0084FAD14193}.Release|Any CPU.Build.0 = Release|Any CPU
+		{E62712D7-31A1-49E4-B1F4-0084FAD14193}.Release|x86.ActiveCfg = Release|Any CPU
+		{E62712D7-31A1-49E4-B1F4-0084FAD14193}.Release|x86.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {89256463-14A3-4968-8688-F75EC230B021}
+	EndGlobalSection
+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 @@
+# Iis.wixext
+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 @@
+@setlocal
+@pushd %~dp0
+
+nuget restore || exit /b
+
+msbuild -p:Configuration=Release -t:Restore || exit /b
+
+msbuild -p:Configuration=Release src\test\WixToolsetTest.Iis\WixToolsetTest.Iis.csproj || exit /b
+dotnet test -c Release --no-build src\test\WixToolsetTest.Iis || exit /b
+
+msbuild -p:Configuration=Release -t:Pack src\wixext\WixToolset.Iis.wixext.csproj || exit /b
+
+@popd
+@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 @@
+# 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.
+#
+#  Do NOT modify this file. Update the canonical version in Home\repo-template\src\appveyor.yml
+#  then update all of the repos.
+
+branches:
+  only:
+    - master
+    - develop
+
+image: Visual Studio 2019
+
+version: 0.0.0.{build}
+configuration: Release
+
+environment:
+  DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
+  DOTNET_CLI_TELEMETRY_OPTOUT: 1
+  NUGET_XMLDOC_MODE: skip
+
+build_script:
+  - appveyor.cmd
+
+pull_requests:
+  do_not_increment_build_number: true
+
+nuget:
+  disable_publish_on_pr: true
+
+skip_branch_with_pr: true
+skip_tags: true
+
+artifacts:
+- path: build\Release\**\*.nupkg
+  name: nuget
+
+notifications:
+- provider: Slack
+  incoming_webhook:
+    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 @@
+#pragma once
+// 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.
+
+#define msierrIISCannotConnect                 26001
+#define msierrIISFailedReadWebSite             26002
+#define msierrIISFailedReadWebDirs             26003
+#define msierrIISFailedReadVDirs               26004
+#define msierrIISFailedReadFilters             26005
+#define msierrIISFailedReadAppPool             26006
+#define msierrIISFailedReadMimeMap             26007
+#define msierrIISFailedReadProp                26008
+#define msierrIISFailedReadWebSvcExt           26009
+#define msierrIISFailedReadWebError            26010
+#define msierrIISFailedReadHttpHeader          26011
+
+#define msierrIISFailedSchedTransaction        26031
+#define msierrIISFailedSchedInstallWebs        26032
+#define msierrIISFailedSchedInstallWebDirs     26033
+#define msierrIISFailedSchedInstallVDirs       26034
+#define msierrIISFailedSchedInstallFilters     26035
+#define msierrIISFailedSchedInstallAppPool     26036
+#define msierrIISFailedSchedInstallProp        26037
+#define msierrIISFailedSchedInstallWebSvcExt   26038
+
+#define msierrIISFailedSchedUninstallWebs      26051
+#define msierrIISFailedSchedUninstallWebDirs   26052
+#define msierrIISFailedSchedUninstallVDirs     26053
+#define msierrIISFailedSchedUninstallFilters   26054
+#define msierrIISFailedSchedUninstallAppPool   26055
+#define msierrIISFailedSchedUninstallProp      26056
+#define msierrIISFailedSchedUninstallWebSvcExt 26057
+
+#define msierrIISFailedStartTransaction        26101
+#define msierrIISFailedOpenKey                 26102
+#define msierrIISFailedCreateKey               26103
+#define msierrIISFailedWriteData               26104
+#define msierrIISFailedCreateApp               26105
+#define msierrIISFailedDeleteKey               26106
+#define msierrIISFailedDeleteApp               26107
+#define msierrIISFailedDeleteValue             26108
+#define msierrIISFailedCommitInUse             26109
+
+// Last available value 26200
+
+#define msierrCERTFailedOpen                   26351
+#define msierrCERTFailedAdd                    26352
+
+// 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 @@
+#pragma once
+// 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.
+
+
+#if defined(_M_ARM64)
+#define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_A64"
+#elif defined(_M_AMD64)
+#define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_X64"
+#elif defined(_M_ARM)
+#define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_ARM"
+#else
+#define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_X86"
+#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 @@
+// 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.
+
+#include "precomp.h"
+
+/********************************************************************
+DllMain - standard entry point for all WiX custom actions
+
+********************************************************************/
+extern "C" BOOL WINAPI DllMain(
+    IN HINSTANCE hInst,
+    IN ULONG ulReason,
+    IN LPVOID)
+{
+    switch(ulReason)
+    {
+    case DLL_PROCESS_ATTACH:
+        WcaGlobalInitialize(hInst);
+        break;
+
+    case DLL_PROCESS_DETACH:
+        WcaGlobalFinalize();
+        break;
+    }
+
+    return TRUE;
+}
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 @@
+// 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.
+
+#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 @@
+; 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.
+
+
+LIBRARY      "iisca"
+
+EXPORTS
+;scacert.cpp
+    InstallCertificates
+    UninstallCertificates
+;scacertexec.cpp
+    AddUserCertificate
+    AddMachineCertificate
+    DeleteUserCertificate
+    DeleteMachineCertificate
+;scaexec.cpp
+    StartMetabaseTransaction
+    RollbackMetabaseTransaction
+    CommitMetabaseTransaction
+
+    WriteMetabaseChanges
+
+    StartIIS7ConfigTransaction
+    RollbackIIS7ConfigTransaction
+    CommitIIS7ConfigTransaction
+
+    WriteIIS7ConfigChanges  
+;scasched.cpp
+    ConfigureIIs
+    ConfigureIIsExec
+    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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\..\packages\WixToolset.DUtil.4.0.30\build\WixToolset.DUtil.props" Condition="Exists('..\..\packages\WixToolset.DUtil.4.0.30\build\WixToolset.DUtil.props')" />
+  <Import Project="..\..\packages\WixToolset.WcaUtil.4.0.16\build\WixToolset.WcaUtil.props" Condition="Exists('..\..\packages\WixToolset.WcaUtil.4.0.16\build\WixToolset.WcaUtil.props')" />
+
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|ARM64">
+      <Configuration>Debug</Configuration>
+      <Platform>ARM64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|ARM64">
+      <Configuration>Release</Configuration>
+      <Platform>ARM64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{CB3FB8C4-14BF-4EA6-9F01-7FB258E5AEF3}</ProjectGuid>
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <TargetName>iisca</TargetName>
+    <PlatformToolset>v142</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+    <ProjectModuleDefinitionFile>iisca.def</ProjectModuleDefinitionFile>
+    <Description>WiX Toolset Iis CustomAction</Description>
+  </PropertyGroup>
+  
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  
+  <PropertyGroup>
+    <ProjectAdditionalLinkLibraries>crypt32.lib;msi.lib;Ws2_32.lib</ProjectAdditionalLinkLibraries>
+  </PropertyGroup>
+  
+  <ItemGroup>
+    <ClCompile Include="dllmain.cpp">
+      <PrecompiledHeader>Create</PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="iisca.cpp" />
+    <ClCompile Include="scaapppool.cpp" />
+    <ClCompile Include="scaapppool7.cpp" />
+    <ClCompile Include="scacert.cpp" />
+    <ClCompile Include="scacertexec.cpp" />
+    <ClCompile Include="scaexec.cpp" />
+    <ClCompile Include="scaexecIIS7.cpp" />
+    <ClCompile Include="scafilter.cpp" />
+    <ClCompile Include="scafilter7.cpp" />
+    <ClCompile Include="scahttpheader.cpp" />
+    <ClCompile Include="scahttpheader7.cpp" />
+    <ClCompile Include="scaiis.cpp" />
+    <ClCompile Include="scaiis7.cpp" />
+    <ClCompile Include="scamimemap.cpp" />
+    <ClCompile Include="scamimemap7.cpp" />
+    <ClCompile Include="scaproperty.cpp" />
+    <ClCompile Include="scaproperty7.cpp" />
+    <ClCompile Include="scasched.cpp" />
+    <ClCompile Include="scassl.cpp" />
+    <ClCompile Include="scassl7.cpp" />
+    <ClCompile Include="scauser.cpp" />
+    <ClCompile Include="scavdir.cpp" />
+    <ClCompile Include="scavdir7.cpp" />
+    <ClCompile Include="scaweb.cpp" />
+    <ClCompile Include="scaweb7.cpp" />
+    <ClCompile Include="scawebapp.cpp" />
+    <ClCompile Include="scawebapp7.cpp" />
+    <ClCompile Include="scawebappext.cpp" />
+    <ClCompile Include="scawebappext7.cpp" />
+    <ClCompile Include="scawebdir.cpp" />
+    <ClCompile Include="scawebdir7.cpp" />
+    <ClCompile Include="scaweberr.cpp" />
+    <ClCompile Include="scaweberr7.cpp" />
+    <ClCompile Include="scaweblog.cpp" />
+    <ClCompile Include="scaweblog7.cpp" />
+    <ClCompile Include="scawebprop.cpp" />
+    <ClCompile Include="scawebprop7.cpp" />
+    <ClCompile Include="scawebsvcext.cpp" />
+    <ClCompile Include="scawebsvcext7.cpp" />
+    <ClInclude Include="caSuffix.h" />
+    <ClInclude Include="CustomMsiErrors.h" />
+    <ClInclude Include="precomp.h" />
+    <ClInclude Include="sca.h" />
+    <ClInclude Include="scaapppool.h" />
+    <ClInclude Include="scaapppool7.h" />
+    <ClInclude Include="scacert.h" />
+    <ClInclude Include="scacost.h" />
+    <ClInclude Include="scaexecIIS7.h" />
+    <ClInclude Include="scafilter.h" />
+    <ClInclude Include="scafilter7.h" />
+    <ClInclude Include="scahttpheader.h" />
+    <ClInclude Include="scahttpheader7.h" />
+    <ClInclude Include="scaiis.h" />
+    <ClInclude Include="scaiis7.h" />
+    <ClInclude Include="scamimemap.h" />
+    <ClInclude Include="scamimemap7.h" />
+    <ClInclude Include="scaproperty.h" />
+    <ClInclude Include="scaproperty7.h" />
+    <ClInclude Include="scassl.h" />
+    <ClInclude Include="scassl7.h" />
+    <ClInclude Include="scauser.h" />
+    <ClInclude Include="scavdir.h" />
+    <ClInclude Include="scavdir7.h" />
+    <ClInclude Include="scaweb.h" />
+    <ClInclude Include="scaweb7.h" />
+    <ClInclude Include="scawebapp.h" />
+    <ClInclude Include="scawebapp7.h" />
+    <ClInclude Include="scawebappext.h" />
+    <ClInclude Include="scawebappext7.h" />
+    <ClInclude Include="scawebdir.h" />
+    <ClInclude Include="scawebdir7.h" />
+    <ClInclude Include="scaweberr.h" />
+    <ClInclude Include="scaweberr7.h" />
+    <ClInclude Include="scaweblog.h" />
+    <ClInclude Include="scaweblog7.h" />
+    <ClInclude Include="scawebprop.h" />
+    <ClInclude Include="scawebprop7.h" />
+    <ClInclude Include="scawebsvcext.h" />
+    <ClInclude Include="scawebsvcext7.h" />
+    <None Include="packages.config" />
+    <None Include="iisca.def" />
+  </ItemGroup>
+  
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <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>
+    </PropertyGroup>
+    <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'))" />
+    <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'))" />
+  </Target>
+</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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="WixToolset.DUtil" version="4.0.30" targetFramework="native" />
+  <package id="WixToolset.WcaUtil" version="4.0.16" targetFramework="native" />
+</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 @@
+#pragma once
+// 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.
+
+
+#if _WIN32_MSI < 150
+#define _WIN32_MSI 150
+#endif
+
+#include <windows.h>
+#include <msiquery.h>
+#include <msidefs.h>
+#include <strsafe.h>
+
+#include <lm.h>        // NetApi32.lib
+
+#include <Dsgetdc.h>
+#include <ComAdmin.h>
+#include <ahadmin.h>    // IIS 7 config
+
+#define MAXUINT USHRT_MAX
+
+#include "wcautil.h"
+#include "wcawow64.h"
+#include "wcawrapquery.h"
+
+#include "certutil.h"
+#include "cryputil.h"
+#include "fileutil.h"
+#include "iis7util.h"
+#include "memutil.h"
+#include "metautil.h"
+#include "strutil.h"
+#include "userutil.h"
+#include "wiutil.h"
+
+#include "CustomMsiErrors.h"
+#include "sca.h"
+#include "scacost.h"
+#include "scacert.h"
+#include "scafilter.h"
+
+#include "scaiis.h"
+#include "scaiis7.h"
+#include "scaproperty.h"
+#include "scaweb.h"
+#include "scawebdir.h"
+#include "scawebsvcext.h"
+#include "scavdir.h"
+#include "scaweb7.h"
+#include "scaapppool7.h"
+#include "scavdir7.h"
+#include "scawebapp7.h"
+#include "scawebappext7.h"
+#include "scamimemap7.h"
+#include "scawebprop7.h"
+#include "scaweblog7.h"
+#include "scafilter7.h"
+#include "scahttpheader7.h"
+#include "scaweberr7.h"
+#include "scawebsvcext7.h"
+#include "scaproperty7.h"
+#include "scawebdir7.h"
+#include "scassl7.h"
+#include "scaexecIIS7.h"
+
+#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 @@
+#pragma once
+// 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.
+
+
+#define MAGIC_MULTISZ_CHAR 127
+
+// Generic action enum.
+enum SCA_ACTION
+{
+    SCA_ACTION_NONE,
+    SCA_ACTION_INSTALL,
+    SCA_ACTION_UNINSTALL
+};
+
+
+// IIS Metabase actions
+enum METABASE_ACTION
+{
+    MBA_UNKNOWNACTION = 0,
+    MBA_CREATEKEY,
+    MBA_DELETEKEY,
+    MBA_WRITEVALUE,
+    MBA_DELETEVALUE,
+    MBA_CREATEAPP,
+    MBA_DELETEAPP,
+};
+
+// IIS 7 Config actions
+enum IIS_CONFIG_ACTION
+{
+    IIS_CREATE,
+    IIS_DELETE,
+    IIS_SITE,
+    IIS_APPLICATION,
+    IIS_APPPOOL,
+    IIS_APPPOOL_RECYCLE_MIN,
+    IIS_APPPOOL_RECYCLE_REQ,
+    IIS_APPPOOL_RECYCLE_TIMES,
+    IIS_APPPOOL_RECYCLE_VIRMEM,
+    IIS_APPPOOL_RECYCLE_PRIVMEM,
+    IIS_APPPOOL_RECYCLE_IDLTIMEOUT,
+    IIS_APPPOOL_RECYCLE_QUEUELIMIT,
+    IIS_APPPOOL_RECYCLE_CPU_PCT,
+    IIS_APPPOOL_RECYCLE_CPU_REFRESH,
+    IIS_APPPOOL_RECYCLE_CPU_ACTION,
+    IIS_APPPOOL_MAXPROCESS,
+    IIS_APPPOOL_IDENTITY,
+    IIS_APPPOOL_USER,
+    IIS_APPPOOL_PWD,
+    IIS_APPPOOL_32BIT,
+    IIS_APPPOOL_MANAGED_PIPELINE_MODE,
+    IIS_APPPOOL_MANAGED_RUNTIME_VERSION,
+    IIS_APPPOOL_END,
+    IIS_APPEXT_BEGIN,
+    IIS_APPEXT,
+    IIS_APPEXT_END,
+    IIS_VDIR,
+    IIS_BINDING,
+    IIS_MIMEMAP_BEGIN,
+    IIS_MIMEMAP,
+    IIS_MIMEMAP_END,
+    IIS_DIRPROP_BEGIN,
+    IIS_DIRPROP_ACCESS,
+    IIS_DIRPROP_AUTH,
+    IIS_DIRPROP_USER,
+    IIS_DIRPROP_PWD,
+    IIS_DIRPROP_PWDCTRL,
+    IIS_DIRPROP_LOG,
+    IIS_DIRPROP_DEFDOCS,
+    IIS_DIRPROP_SSLFLAGS,
+    IIS_DIRPROP_AUTHPROVID,
+    IIS_DIRPROP_ASPERROR,
+    IIS_DIRPROP_HTTPEXPIRES,
+    IIS_DIRPROP_MAXAGE,
+    IIS_DIRPROP_CACHECUST,
+    IIS_DIRPROP_NOCUSTERROR,
+    IIS_DIRPROP_LOGVISITS,
+    IIS_DIRPROP_END,
+    IIS_WEBLOG,
+    IIS_FILTER_BEGIN,
+    IIS_FILTER_GLOBAL_BEGIN,
+    IIS_FILTER,
+    IIS_FILTER_END,
+    IIS_HTTP_HEADER_BEGIN,
+    IIS_HTTP_HEADER,
+    IIS_HTTP_HEADER_END,
+    IIS_WEBERROR_BEGIN,
+    IIS_WEBERROR,
+    IIS_WEBERROR_END,
+    IIS_WEB_SVC_EXT,
+    IIS_PROPERTY,
+    IIS_PROPERTY_MAXBAND,
+    IIS_PROPERTY_LOGUTF8,
+    IIS_WEBDIR,
+    IIS_ASP_BEGIN,
+    IIS_ASP_SESSIONSTATE,
+    IIS_ASP_SESSIONTIMEOUT,
+    IIS_ASP_BUFFER,
+    IIS_ASP_PARENTPATHS,
+    IIS_ASP_SCRIPTLANG,
+    IIS_ASP_SCRIPTTIMEOUT,
+    IIS_ASP_SCRIPTSERVERDEBUG,
+    IIS_ASP_SCRIPTCLIENTDEBUG,
+    IIS_ASP_END,
+    IIS_SSL_BINDING
+};
+
+
+// user creation attributes definitions
+enum SCAU_ATTRIBUTES
+{
+    SCAU_DONT_EXPIRE_PASSWRD = 0x00000001,
+    SCAU_PASSWD_CANT_CHANGE = 0x00000002,
+    SCAU_PASSWD_CHANGE_REQD_ON_LOGIN = 0x00000004,
+    SCAU_DISABLE_ACCOUNT = 0x00000008,
+    SCAU_FAIL_IF_EXISTS = 0x00000010,
+    SCAU_UPDATE_IF_EXISTS = 0x00000020,
+    SCAU_ALLOW_LOGON_AS_SERVICE = 0x00000040,
+    SCAU_ALLOW_LOGON_AS_BATCH = 0x00000080,
+
+    SCAU_DONT_REMOVE_ON_UNINSTALL = 0x00000100,
+    SCAU_DONT_CREATE_USER = 0x00000200,
+    SCAU_NON_VITAL = 0x00000400,
+};
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 @@
+// 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.
+
+#include "precomp.h"
+
+/*------------------------------------------------------------------
+AppPool table:
+
+Column                Type   Nullable     Example Value
+AppPool               s72    No           TestPool
+Name                  s72    No           "TestPool"
+Component_            s72    No           ComponentName
+Attributes            i2     No           8 (APATTR_OTHERUSER)
+User_                 s72    Yes          UserKey
+RecycleMinutes        i2     Yes          500
+RecycleRequests       i2     Yes          5000
+RecycleTimes          s72    Yes          "1:45,13:30,22:00"
+IdleTimeout           i2     Yes          15
+QueueLimit            i2     Yes          500
+CPUMon                s72    Yes          "65,500,1" (65% CPU usage, 500 minutes, Shutdown Action)
+MaxProc               i2     Yes          5
+ManagedRuntimeVersion s72    Yes          "v2.0"
+ManagedPipelineMode   s72    Yes          "Integrated"
+
+Notes:
+RecycleTimes is a comma delimeted list of times.  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).
+
+------------------------------------------------------------------*/
+
+enum eAppPoolQuery { apqAppPool = 1, apqName, apqComponent, apqAttributes, apqUser, apqRecycleMinutes, apqRecycleRequests, apqRecycleTimes, apqVirtualMemory, apqPrivateMemory, apqIdleTimeout, apqQueueLimit, apqCpuMon, apqMaxProc, apqManagedRuntimeVersion, apqManagedPipelineMode, apqInstalled, apqAction };
+
+enum eComponentAttrQuery { caqComponent = 1, caqAttributes };
+
+// prototypes
+static HRESULT AppPoolExists(
+    __in IMSAdminBase* piMetabase,
+    __in LPCWSTR wzAppPool
+    );
+
+// functions
+
+void ScaAppPoolFreeList(
+    __in SCA_APPPOOL* psapList
+    )
+{
+    SCA_APPPOOL* psapDelete = psapList;
+    while (psapList)
+    {
+        psapDelete = psapList;
+        psapList = psapList->psapNext;
+
+        MemFree(psapDelete);
+    }
+}
+
+
+HRESULT ScaAppPoolRead(
+    __inout SCA_APPPOOL** ppsapList,
+    __in WCA_WRAPQUERY_HANDLE hUserQuery,
+    __inout LPWSTR *ppwzCustomActionData
+    )
+{
+    Assert(ppsapList);
+
+    HRESULT hr = S_OK;
+
+    MSIHANDLE hRec, hRecComp;
+    LPWSTR pwzData = NULL;
+    SCA_APPPOOL* psap = NULL;
+    WCA_WRAPQUERY_HANDLE hAppPoolQuery = NULL;
+    WCA_WRAPQUERY_HANDLE hComponentQuery = NULL;
+
+    hr = WcaBeginUnwrapQuery(&hAppPoolQuery, ppwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead");
+
+    if (0 == WcaGetQueryRecords(hAppPoolQuery))
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ScaAppPoolRead() - required table not present");
+        ExitFunction1(hr = S_FALSE);
+    }
+    
+    hr = WcaBeginUnwrapQuery(&hComponentQuery, ppwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead");
+
+    // loop through all the AppPools
+    while (S_OK == (hr = WcaFetchWrappedRecord(hAppPoolQuery, &hRec)))
+    {
+        // Add this record's information into the list of things to process.
+        hr = AddAppPoolToList(ppsapList);
+        ExitOnFailure(hr, "failed to add app pool to app pool list");
+
+        psap = *ppsapList;
+
+        hr = WcaGetRecordString(hRec, apqComponent, &pwzData);
+        ExitOnFailure(hr, "failed to get AppPool.Component");
+
+        if (pwzData && *pwzData)
+        {
+            psap->fHasComponent = TRUE;
+
+            hr = ::StringCchCopyW(psap->wzComponent, countof(psap->wzComponent), pwzData);
+            ExitOnFailure(hr, "failed to copy component name: %ls", pwzData);
+
+            hr = WcaGetRecordInteger(hRec, apqInstalled, (int *)&psap->isInstalled);
+            ExitOnFailure(hr, "Failed to get Component installed state for app pool");
+
+            hr = WcaGetRecordInteger(hRec, apqAction, (int *)&psap->isAction);
+            ExitOnFailure(hr, "Failed to get Component action state for app pool");
+
+            WcaFetchWrappedReset(hComponentQuery);
+            hr = WcaFetchWrappedRecordWhereString(hComponentQuery, caqComponent, psap->wzComponent, &hRecComp);
+            ExitOnFailure(hr, "Failed to fetch Component.Attributes for Component '%ls'", psap->wzComponent);
+
+            hr = WcaGetRecordInteger(hRecComp, caqAttributes, &psap->iCompAttributes);
+            ExitOnFailure(hr, "failed to get Component.Attributes");
+        }
+
+        hr = WcaGetRecordString(hRec, apqAppPool, &pwzData);
+        ExitOnFailure(hr, "failed to get AppPool.AppPool");
+        hr = ::StringCchCopyW(psap->wzAppPool, countof(psap->wzAppPool), pwzData);
+        ExitOnFailure(hr, "failed to copy AppPool name: %ls", pwzData);
+
+        hr = WcaGetRecordString(hRec, apqName, &pwzData);
+        ExitOnFailure(hr, "failed to get AppPool.Name");
+        hr = ::StringCchCopyW(psap->wzName, countof(psap->wzName), pwzData);
+        ExitOnFailure(hr, "failed to copy app pool name: %ls", pwzData);
+        hr = ::StringCchPrintfW(psap->wzKey, countof(psap->wzKey), L"/LM/W3SVC/AppPools/%s", pwzData);
+        ExitOnFailure(hr, "failed to format app pool key name");
+
+        hr = WcaGetRecordInteger(hRec, apqAttributes, &psap->iAttributes);
+        ExitOnFailure(hr, "failed to get AppPool.Attributes");
+
+        hr = WcaGetRecordString(hRec, apqUser, &pwzData);
+        ExitOnFailure(hr, "failed to get AppPool.User");
+        hr = ScaGetUserDeferred(pwzData, hUserQuery, &psap->suUser);
+        ExitOnFailure(hr, "failed to get user: %ls", pwzData);
+
+        hr = WcaGetRecordInteger(hRec, apqRecycleRequests, &psap->iRecycleRequests);
+        ExitOnFailure(hr, "failed to get AppPool.RecycleRequests");
+
+        hr = WcaGetRecordInteger(hRec, apqRecycleMinutes, &psap->iRecycleMinutes);
+        ExitOnFailure(hr, "failed to get AppPool.Minutes");
+
+        hr = WcaGetRecordString(hRec, apqRecycleTimes, &pwzData);
+        ExitOnFailure(hr, "failed to get AppPool.RecycleTimes");
+        hr = ::StringCchCopyW(psap->wzRecycleTimes, countof(psap->wzRecycleTimes), pwzData);
+        ExitOnFailure(hr, "failed to copy recycle value: %ls", pwzData);
+
+        hr = WcaGetRecordInteger(hRec, apqVirtualMemory, &psap->iVirtualMemory);
+        ExitOnFailure(hr, "failed to get AppPool.VirtualMemory");
+
+        hr = WcaGetRecordInteger(hRec, apqPrivateMemory, &psap->iPrivateMemory);
+        ExitOnFailure(hr, "failed to get AppPool.PrivateMemory");
+
+        hr = WcaGetRecordInteger(hRec, apqIdleTimeout, &psap->iIdleTimeout);
+        ExitOnFailure(hr, "failed to get AppPool.IdleTimeout");
+
+        hr = WcaGetRecordInteger(hRec, apqQueueLimit, &psap->iQueueLimit);
+        ExitOnFailure(hr, "failed to get AppPool.QueueLimit");
+
+        hr = WcaGetRecordString(hRec, apqCpuMon, &pwzData);
+        ExitOnFailure(hr, "failed to get AppPool.CPUMon");
+        hr = ::StringCchCopyW(psap->wzCpuMon, countof(psap->wzCpuMon), pwzData);
+        ExitOnFailure(hr, "failed to copy cpu monitor value: %ls", pwzData);
+
+        hr = WcaGetRecordInteger(hRec, apqMaxProc, &psap->iMaxProcesses);
+        ExitOnFailure(hr, "failed to get AppPool.MaxProc");
+
+        hr = WcaGetRecordString(hRec, apqManagedRuntimeVersion, &pwzData);
+        ExitOnFailure(hr, "failed to get AppPool.ManagedRuntimeVersion");
+        hr = ::StringCchCopyW(psap->wzManagedRuntimeVersion, countof(psap->wzManagedRuntimeVersion), pwzData);
+        ExitOnFailure(hr, "failed to copy ManagedRuntimeVersion value: %ls", pwzData);
+
+        hr = WcaGetRecordString(hRec, apqManagedPipelineMode, &pwzData);
+        ExitOnFailure(hr, "failed to get AppPool.ManagedPipelineMode");
+        hr = ::StringCchCopyW(psap->wzManagedPipelineMode, countof(psap->wzManagedPipelineMode), pwzData);
+        ExitOnFailure(hr, "failed to copy ManagedPipelineMode value: %ls", pwzData);
+
+    }
+
+    if (E_NOMOREITEMS == hr)
+    {
+        hr = S_OK;
+    }
+    ExitOnFailure(hr, "failure while processing AppPools");
+
+LExit:
+    WcaFinishUnwrapQuery(hAppPoolQuery);
+    WcaFinishUnwrapQuery(hComponentQuery);
+
+    ReleaseStr(pwzData);
+    return hr;
+}
+
+
+HRESULT ScaFindAppPool(
+    __in IMSAdminBase* piMetabase,
+    __in LPCWSTR wzAppPool,
+    __out_ecount(cchName) LPWSTR wzName,
+    __in DWORD cchName,
+    __in SCA_APPPOOL *psapList
+    )
+{
+    Assert(piMetabase && wzAppPool && *wzAppPool && wzName && *wzName);
+
+    HRESULT hr = S_OK;
+
+    // check memory first
+    SCA_APPPOOL* psap = psapList;
+    for (; psap; psap = psap->psapNext)
+    {
+        if (0 == lstrcmpW(psap->wzAppPool, wzAppPool))
+        {
+            break;
+        }
+    }
+    ExitOnNull(psap, hr, HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Could not find the app pool: %ls", wzAppPool);
+
+    // copy the web app pool name
+    hr = ::StringCchCopyW(wzName, cchName, psap->wzName);
+    ExitOnFailure(hr, "failed to copy app pool name while finding app pool: %ls", psap->wzName);
+
+    // if it's not being installed now, check if it exists already
+    if (!psap->fHasComponent)
+    {
+        hr = AppPoolExists(piMetabase, psap->wzName);
+        ExitOnFailure(hr, "failed to check for existence of app pool: %ls", psap->wzName);
+    }
+
+LExit:
+    return hr;
+}
+
+
+static HRESULT AppPoolExists(
+    __in IMSAdminBase* piMetabase,
+    __in LPCWSTR wzAppPool
+    )
+{
+    Assert(piMetabase && wzAppPool && *wzAppPool);
+
+    HRESULT hr = S_OK;
+    WCHAR wzSubKey[METADATA_MAX_NAME_LEN];
+
+    for (DWORD dwIndex = 0; SUCCEEDED(hr); ++dwIndex)
+    {
+        hr = piMetabase->EnumKeys(METADATA_MASTER_ROOT_HANDLE, L"/LM/W3SVC/AppPools", wzSubKey, dwIndex);
+        if (SUCCEEDED(hr) && 0 == lstrcmpW(wzSubKey, wzAppPool))
+        {
+            hr = S_OK;
+            break;
+        }
+    }
+
+    if (E_NOMOREITEMS == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
+    {
+        hr = S_FALSE;
+    }
+
+    return hr;
+}
+
+
+HRESULT ScaAppPoolInstall(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_APPPOOL* psapList
+    )
+{
+    Assert(piMetabase);
+
+    HRESULT hr = S_OK;
+
+    for (SCA_APPPOOL* psap = psapList; psap; psap = psap->psapNext)
+    {
+        // if we are installing the app pool
+        if (psap->fHasComponent && WcaIsInstalling(psap->isInstalled, psap->isAction))
+        {
+            hr = ScaWriteAppPool(piMetabase, psap);
+            ExitOnFailure(hr, "failed to write AppPool '%ls' to metabase", psap->wzAppPool);
+        }
+    }
+
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaAppPoolUninstall(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_APPPOOL* psapList
+    )
+{
+    Assert(piMetabase);
+
+    HRESULT hr = S_OK;
+
+    for (SCA_APPPOOL* psap = psapList; psap; psap = psap->psapNext)
+    {
+        // if we are uninstalling the app pool
+        if (psap->fHasComponent && WcaIsUninstalling(psap->isInstalled, psap->isAction))
+        {
+            hr = ScaRemoveAppPool(piMetabase, psap);
+            ExitOnFailure(hr, "Failed to remove AppPool '%ls' from metabase", psap->wzAppPool);
+        }
+    }
+
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaWriteAppPool(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_APPPOOL* psap
+    )
+{
+    Assert(piMetabase && psap);
+
+    HRESULT hr = S_OK;
+    DWORD dwIdentity = 0xFFFFFFFF;
+    BOOL fExists = FALSE;
+    LPWSTR pwzValue = NULL;
+    LPWSTR wz = NULL;
+
+    hr = AppPoolExists(piMetabase, psap->wzName);
+    ExitOnFailure(hr, "failed to check if app pool already exists");
+    if (S_FALSE == hr)
+    {
+        // didn't find the AppPool key, so we need to create it
+        hr = ScaCreateMetabaseKey(piMetabase, psap->wzKey, L"");
+        ExitOnFailure(hr, "failed to create AppPool key: %ls", psap->wzKey);
+
+        // mark it as an AppPool
+        hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsApplicationPool");
+        ExitOnFailure(hr, "failed to mark key as AppPool key: %ls", psap->wzKey);
+
+        // TODO: Make this an Attribute?
+        // set autostart value
+        hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_AUTO_START, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)1);
+        ExitOnFailure(hr, "failed to mark key as AppPool key: %ls", psap->wzKey);
+    }
+    else
+    {
+        fExists = TRUE;
+    }
+
+    //
+    // Set the AppPool Recycling Tab
+    //
+    if (MSI_NULL_INTEGER != psap->iRecycleMinutes)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_PERIODIC_RESTART_TIME, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iRecycleMinutes));
+        ExitOnFailure(hr, "failed to set periodic restart time");
+    }
+
+    if (MSI_NULL_INTEGER != psap->iRecycleRequests)
+    {
+        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));
+        ExitOnFailure(hr, "failed to set periodic restart request count");
+    }
+
+    if (*psap->wzRecycleTimes)
+    {
+        // Add another NULL' onto pwz since it's a 'MULTISZ'
+        hr = StrAllocString(&pwzValue, psap->wzRecycleTimes, 0);
+        ExitOnFailure(hr, "failed to allocate string for MULTISZ");
+        hr = StrAllocConcat(&pwzValue, L"\0", 1);
+        ExitOnFailure(hr, "failed to add second null to RecycleTime multisz");
+
+        // Replace the commas with NULLs
+        wz = pwzValue;
+        while (NULL != (wz = wcschr(wz, L',')))
+        {
+            *wz = L'\0';
+            ++wz;
+        }
+
+        hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_PERIODIC_RESTART_SCHEDULE, METADATA_INHERIT, IIS_MD_UT_SERVER, MULTISZ_METADATA, (LPVOID)pwzValue);
+        ExitOnFailure(hr, "failed to set periodic restart schedule");
+    }
+
+    if (MSI_NULL_INTEGER != psap->iVirtualMemory)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_PERIODIC_RESTART_MEMORY, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iVirtualMemory));
+        ExitOnFailure(hr, "failed to set periodic restart memory count");
+    }
+
+    if (MSI_NULL_INTEGER != psap->iPrivateMemory)
+    {
+        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));
+        ExitOnFailure(hr, "failed to set periodic restart private memory count");
+    }
+
+
+    //
+    // Set AppPool Performance Tab
+    //
+    if (MSI_NULL_INTEGER != psap->iIdleTimeout)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_IDLE_TIMEOUT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iIdleTimeout));
+        ExitOnFailure(hr, "failed to set idle timeout value");
+    }
+
+    if (MSI_NULL_INTEGER != psap->iQueueLimit)
+    {
+        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));
+        ExitOnFailure(hr, "failed to set request queue limit value");
+    }
+
+    if (*psap->wzCpuMon)
+    {
+        hr = StrAllocString(&pwzValue, psap->wzCpuMon, 0);
+        ExitOnFailure(hr, "failed to allocate CPUMonitor string");
+
+        DWORD dwPercent = 0;
+        DWORD dwRefreshMinutes = 0;
+        DWORD dwAction = 0;
+
+        dwPercent = wcstoul(pwzValue, &wz, 10);
+        if (100  < dwPercent)
+        {
+            ExitOnFailure(hr = E_INVALIDARG, "invalid maximum cpu percentage value: %d", dwPercent);
+        }
+        if (wz && L',' == *wz)
+        {
+            ++wz;
+            dwRefreshMinutes = wcstoul(wz, &wz, 10);
+            if (wz && L',' == *wz)
+            {
+                ++wz;
+                dwAction = wcstoul(wz, &wz, 10);
+            }
+        }
+
+        if (dwPercent)
+        {
+            hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_CPU_LIMIT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)(dwPercent * 1000)));
+            ExitOnFailure(hr, "failed to set CPU percentage max");
+        }
+        if (dwRefreshMinutes)
+        {
+            hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_CPU_RESET_INTERVAL, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwRefreshMinutes));
+            ExitOnFailure(hr, "failed to set refresh CPU minutes");
+        }
+        if (dwAction)
+        {
+            // 0 = No Action
+            // 1 = Shutdown
+            hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_CPU_ACTION, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwAction));
+            ExitOnFailure(hr, "failed to set CPU action");
+        }
+    }
+
+    if (MSI_NULL_INTEGER != psap->iMaxProcesses)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_MAX_PROCESS_COUNT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iMaxProcesses));
+        ExitOnFailure(hr, "failed to set web garden maximum worker processes");
+    }
+
+    // TODO: Health Tab if anyone wants it?
+
+    //
+    // Set the AppPool Identity tab
+    //
+    if (psap->iAttributes & APATTR_NETSERVICE)
+    {
+        dwIdentity = MD_APPPOOL_IDENTITY_TYPE_NETWORKSERVICE;
+    }
+    else if (psap->iAttributes & APATTR_LOCSERVICE)
+    {
+        dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSERVICE;
+    }
+    else if (psap->iAttributes & APATTR_LOCSYSTEM)
+    {
+        dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSYSTEM;
+    }
+    else if (psap->iAttributes & APATTR_OTHERUSER)
+    {
+        if (!*psap->suUser.wzDomain || CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzDomain, -1, L".", -1))
+        {
+            if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"NetworkService", -1))
+            {
+                dwIdentity = MD_APPPOOL_IDENTITY_TYPE_NETWORKSERVICE;
+            }
+            else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"LocalService", -1))
+            {
+                dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSERVICE;
+            }
+            else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"LocalSystem", -1))
+            {
+                dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSYSTEM;
+            }
+            else
+            {
+                dwIdentity = MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER;
+            }
+        }
+        else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzDomain, -1, L"NT AUTHORITY", -1))
+        {
+            if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"NETWORK SERVICE", -1))
+            {
+                dwIdentity = MD_APPPOOL_IDENTITY_TYPE_NETWORKSERVICE;
+            }
+            else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"SERVICE", -1))
+            {
+                dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSERVICE;
+            }
+            else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"SYSTEM", -1))
+            {
+                dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSYSTEM;
+            }
+            else
+            {
+                dwIdentity = MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER;
+            }
+        }
+        else
+        {
+            dwIdentity = MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER;
+        }
+    }
+
+    if (-1 != dwIdentity)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_IDENTITY_TYPE, METADATA_INHERIT , IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwIdentity));
+        ExitOnFailure(hr, "failed to set app pool identity");
+
+        if (MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER == dwIdentity)
+        {
+            if (*psap->suUser.wzDomain)
+            {
+                hr = StrAllocFormatted(&pwzValue, L"%s\\%s", psap->suUser.wzDomain, psap->suUser.wzName);
+                ExitOnFailure(hr, "failed to format user name: %ls domain: %ls", psap->suUser.wzName, psap->suUser.wzDomain);
+            }
+            else
+            {
+                hr = StrAllocFormatted(&pwzValue, L"%s", psap->suUser.wzName);
+                ExitOnFailure(hr, "failed to format user name: %ls", psap->suUser.wzName);
+            }
+
+            hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_WAM_USER_NAME, METADATA_INHERIT , IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pwzValue);
+            ExitOnFailure(hr, "failed to set app pool identity name");
+
+            hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_WAM_PWD, METADATA_INHERIT | METADATA_SECURE, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)psap->suUser.wzPassword);
+            ExitOnFailure(hr, "failed to set app pool identity password");
+        }
+    }
+
+LExit:
+    ReleaseStr(pwzValue);
+
+    return hr;
+}
+
+
+HRESULT ScaRemoveAppPool(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_APPPOOL* psap
+    )
+{
+    Assert(piMetabase && psap);
+
+    HRESULT hr = S_OK;
+
+    // simply remove the root key and everything else is pulled at the same time
+    if (0 != lstrlenW(psap->wzKey))
+    {
+        hr = ScaDeleteMetabaseKey(piMetabase, psap->wzKey, L"");
+        ExitOnFailure(hr, "failed to delete AppPool key: %ls", psap->wzKey);
+    }
+
+    // TODO: Maybe check to make sure any web sites that are using this AppPool are put back in the 'DefaultAppPool'
+
+LExit:
+    return hr;
+}
+
+
+HRESULT AddAppPoolToList(
+    __in SCA_APPPOOL** ppsapList
+    )
+{
+    HRESULT hr = S_OK;
+    SCA_APPPOOL* psap = static_cast<SCA_APPPOOL*>(MemAlloc(sizeof(SCA_APPPOOL), TRUE));
+    ExitOnNull(psap, hr, E_OUTOFMEMORY, "failed to allocate memory for new element in app pool list");
+
+    psap->psapNext = *ppsapList;
+    *ppsapList = psap;
+
+LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+#include "scauser.h"
+
+// Identity
+#define APATTR_NETSERVICE 0x0001 // Network Service
+#define APATTR_LOCSERVICE 0x0002 // Local Service
+#define APATTR_LOCSYSTEM 0x0004 // Local System
+#define APATTR_OTHERUSER 0x0008 // Other User
+
+struct SCA_APPPOOL
+{
+    // iis app pool configuation information
+    WCHAR wzAppPool[MAX_DARWIN_KEY + 1];
+    WCHAR wzName[METADATA_MAX_NAME_LEN + 1];
+    WCHAR wzKey[METADATA_MAX_NAME_LEN + 1];
+    WCHAR wzComponent[METADATA_MAX_NAME_LEN + 1];
+    BOOL fHasComponent;
+    INSTALLSTATE isInstalled;
+    INSTALLSTATE isAction;
+    INT iAttributes;
+
+    SCA_USER suUser;
+
+    INT iRecycleRequests;
+    INT iRecycleMinutes;
+    WCHAR wzRecycleTimes[MAX_DARWIN_KEY + 1];
+    INT iVirtualMemory;
+    INT iPrivateMemory;
+
+    INT iIdleTimeout;
+    INT iQueueLimit;
+    WCHAR wzCpuMon[MAX_DARWIN_KEY + 1];
+    INT iMaxProcesses;
+    WCHAR wzManagedPipelineMode[MAX_DARWIN_KEY + 1];
+    WCHAR wzManagedRuntimeVersion[MAX_DARWIN_KEY + 1];
+
+    int iCompAttributes;
+
+    SCA_APPPOOL *psapNext;
+};
+
+
+// prototypes
+
+HRESULT ScaAppPoolRead(
+    __inout SCA_APPPOOL** ppsapList,
+    __in WCA_WRAPQUERY_HANDLE hUserQuery,
+    __inout LPWSTR *ppwzCustomActionData
+    );
+
+void ScaAppPoolFreeList(
+    __in SCA_APPPOOL* psapList
+    );
+
+HRESULT ScaFindAppPool(
+    __in IMSAdminBase* piMetabase,
+    __in LPCWSTR wzAppPool,
+    __out_ecount(cchName) LPWSTR wzName,
+    __in DWORD cchName,
+    __in SCA_APPPOOL *psapList
+    );
+
+HRESULT ScaAppPoolInstall(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_APPPOOL* psapList
+    );
+
+HRESULT ScaAppPoolUninstall(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_APPPOOL* psapList
+    );
+
+HRESULT ScaWriteAppPool(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_APPPOOL* psap
+    );
+
+HRESULT ScaRemoveAppPool(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_APPPOOL* psap
+    );
+
+HRESULT AddAppPoolToList(
+    __in SCA_APPPOOL** ppsapList
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+// prototypes
+static HRESULT AppPoolExists(
+    __in LPCWSTR wzAppPool
+    );
+
+// functions
+HRESULT ScaFindAppPool7(
+    __in LPCWSTR wzAppPool,
+    __out_ecount(cchName) LPWSTR wzName,
+    __in DWORD cchName,
+    __in SCA_APPPOOL *psapList
+    )
+{
+    Assert(wzAppPool && *wzAppPool && wzName && *wzName);
+
+    HRESULT hr = S_OK;
+
+    // check memory first
+    SCA_APPPOOL* psap = psapList;
+    for (; psap; psap = psap->psapNext)
+    {
+        if (0 == wcscmp(psap->wzAppPool, wzAppPool))
+        {
+            break;
+        }
+    }
+    ExitOnNull(psap, hr, HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Could not find the app pool: %ls", wzAppPool);
+
+    // copy the web app pool name
+#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
+    hr = ::StringCchCopyW(wzName, cchName, psap->wzName);
+    ExitOnFailure(hr, "failed to copy app pool name while finding app pool: %ls", psap->wzName);
+
+    // if it's not being installed now, check if it exists already
+    if (!psap->fHasComponent)
+    {
+        hr = AppPoolExists(psap->wzName);
+        ExitOnFailure(hr, "failed to check for existence of app pool: %ls", psap->wzName);
+    }
+
+LExit:
+    return hr;
+}
+
+
+static HRESULT AppPoolExists(
+    __in LPCWSTR /*wzAppPool*/
+    )
+{
+    HRESULT hr = S_OK;
+
+    //this function checks for existance of app pool in IIS7 config
+    //at schedule time, we will defer this to execute time.
+
+    return hr;
+}
+
+
+HRESULT ScaAppPoolInstall7(
+    __in SCA_APPPOOL* psapList
+    )
+{
+    HRESULT hr = S_OK;
+
+    for (SCA_APPPOOL* psap = psapList; psap; psap = psap->psapNext)
+    {
+        // if we are installing the app pool
+        if (psap->fHasComponent && WcaIsInstalling(psap->isInstalled, psap->isAction))
+        {
+            hr = ScaWriteAppPool7(psap);
+            ExitOnFailure(hr, "failed to write AppPool '%ls' to metabase", psap->wzAppPool);
+        }
+    }
+
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaAppPoolUninstall7(
+    __in SCA_APPPOOL* psapList
+    )
+{
+
+    HRESULT hr = S_OK;
+
+    for (SCA_APPPOOL* psap = psapList; psap; psap = psap->psapNext)
+    {
+        // if we are uninstalling the app pool
+        if (psap->fHasComponent && WcaIsUninstalling(psap->isInstalled, psap->isAction))
+        {
+            hr = ScaRemoveAppPool7(psap);
+            ExitOnFailure(hr, "Failed to remove AppPool '%ls' from metabase", psap->wzAppPool);
+        }
+    }
+
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaWriteAppPool7(
+    __in const SCA_APPPOOL* psap
+    )
+{
+    Assert(psap);
+
+    HRESULT hr = S_OK;
+    DWORD dwIdentity = 0xFFFFFFFF;
+    LPWSTR pwzValue = NULL;
+    LPWSTR wz = NULL;
+
+    //create the app pool
+    hr = ScaWriteConfigID(IIS_APPPOOL);
+    ExitOnFailure(hr, "failed to write AppPool key.");
+
+    hr = ScaWriteConfigID(IIS_CREATE);
+    ExitOnFailure(hr, "failed to write AppPool create action.");
+
+    hr = ScaWriteConfigString(psap->wzName);
+    ExitOnFailure(hr, "failed to write AppPool name: %ls", psap->wzName);
+
+    // Now do all the optional stuff
+
+    // Set the AppPool Recycling Tab
+    if (MSI_NULL_INTEGER != psap->iRecycleMinutes)
+    {
+        hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_MIN);
+        ExitOnFailure(hr, "failed to set periodic restart time id");
+        hr = ScaWriteConfigInteger(psap->iRecycleMinutes);
+        ExitOnFailure(hr, "failed to set periodic restart time");
+    }
+
+    if (MSI_NULL_INTEGER != psap->iRecycleRequests)
+    {
+        hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_REQ);
+        ExitOnFailure(hr, "failed to set periodic restart request count id");
+        hr = ScaWriteConfigInteger(psap->iRecycleRequests);
+        ExitOnFailure(hr, "failed to set periodic restart request count");
+    }
+
+    if (*psap->wzRecycleTimes)
+    {
+        hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_TIMES);
+        ExitOnFailure(hr, "failed to set periodic restart schedule id");
+        hr = ScaWriteConfigString(psap->wzRecycleTimes);
+        ExitOnFailure(hr, "failed to set periodic restart schedule");
+    }
+
+    if (MSI_NULL_INTEGER != psap->iVirtualMemory)
+    {
+        hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_VIRMEM);
+        ExitOnFailure(hr, "failed to set periodic restart memory count id");
+        hr = ScaWriteConfigInteger(psap->iVirtualMemory);
+        ExitOnFailure(hr, "failed to set periodic restart memory count");
+    }
+
+    if (MSI_NULL_INTEGER != psap->iPrivateMemory)
+    {
+        hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_PRIVMEM);
+        ExitOnFailure(hr, "failed to set periodic restart private memory count id");
+        hr = ScaWriteConfigInteger(psap->iPrivateMemory);
+        ExitOnFailure(hr, "failed to set periodic restart private memory count");
+    }
+
+    // Set AppPool Performance Tab
+    if (MSI_NULL_INTEGER != psap->iIdleTimeout)
+    {
+        hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_IDLTIMEOUT);
+        ExitOnFailure(hr, "failed to set idle timeout value id");
+        hr = ScaWriteConfigInteger(psap->iIdleTimeout);
+        ExitOnFailure(hr, "failed to set idle timeout value");
+    }
+
+    if (MSI_NULL_INTEGER != psap->iQueueLimit)
+    {
+        hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_QUEUELIMIT);
+        ExitOnFailure(hr, "failed to set request queue limit value id");
+        hr = ScaWriteConfigInteger(psap->iQueueLimit);
+        ExitOnFailure(hr, "failed to set request queue limit value");
+    }
+    if (*psap->wzCpuMon)
+    {
+#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
+        hr = ::StrAllocString(&pwzValue, psap->wzCpuMon, 0);
+        ExitOnFailure(hr, "failed to allocate CPUMonitor string");
+
+        DWORD dwPercent = 0;
+        DWORD dwRefreshMinutes = 0;
+        DWORD dwAction = 0;
+
+        dwPercent = wcstoul(pwzValue, &wz, 10);
+        if (100  < dwPercent)
+        {
+            ExitOnFailure(hr = E_INVALIDARG, "invalid maximum cpu percentage value: %d", dwPercent);
+        }
+        if (wz && L',' == *wz)
+        {
+            ++wz;
+            dwRefreshMinutes = wcstoul(wz, &wz, 10);
+            if (wz && L',' == *wz)
+            {
+                ++wz;
+                dwAction = wcstoul(wz, &wz, 10);
+            }
+        }
+        if (dwPercent)
+        {
+            hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_CPU_PCT);
+            ExitOnFailure(hr, "failed to set recycle pct id");
+            hr = ScaWriteConfigInteger(dwPercent);
+            ExitOnFailure(hr, "failed to set CPU percentage max");
+        }
+        if (dwRefreshMinutes)
+        {
+            hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_CPU_REFRESH);
+            ExitOnFailure(hr, "failed to set recycle refresh id");
+            hr = ScaWriteConfigInteger(dwRefreshMinutes);
+            ExitOnFailure(hr, "failed to set refresh CPU minutes");
+        }
+        if (dwAction)
+        {
+            // 0 = No Action
+            // 1 = Shutdown
+            hr = ScaWriteConfigID(IIS_APPPOOL_RECYCLE_CPU_ACTION);
+            ExitOnFailure(hr, "failed to set recycle refresh id");
+            hr = ScaWriteConfigInteger(dwAction);
+            ExitOnFailure(hr, "failed to set CPU action");
+        }
+    }
+
+    if (MSI_NULL_INTEGER != psap->iMaxProcesses)
+    {
+        hr = ScaWriteConfigID(IIS_APPPOOL_MAXPROCESS);
+        ExitOnFailure(hr, "Failed to write max processes config ID");
+
+        hr = ScaWriteConfigInteger(psap->iMaxProcesses);
+        ExitOnFailure(hr, "failed to set web garden maximum worker processes");
+    }
+
+    hr = ScaWriteConfigID(IIS_APPPOOL_32BIT);
+    ExitOnFailure(hr, "Failed to write 32 bit app pool config ID");
+    hr = ScaWriteConfigInteger(psap->iCompAttributes & msidbComponentAttributes64bit ? 0 : 1);
+    ExitOnFailure(hr, "Failed to write 32 bit app pool config value");
+
+    //
+    // Set the AppPool Identity tab
+    //
+    if (psap->iAttributes & APATTR_APPPOOLIDENTITY)
+    {
+        dwIdentity = 4;
+    }
+    else if (psap->iAttributes & APATTR_NETSERVICE)
+    {
+        dwIdentity = 2;
+    }
+    else if (psap->iAttributes & APATTR_LOCSERVICE)
+    {
+        dwIdentity = 1;
+    }
+    else if (psap->iAttributes & APATTR_LOCSYSTEM)
+    {
+        dwIdentity = 0;
+    }
+    else if (psap->iAttributes & APATTR_OTHERUSER)
+    {
+        if (!*psap->suUser.wzDomain || 0 == _wcsicmp(psap->suUser.wzDomain, L"."))
+        {
+            if (0 == _wcsicmp(psap->suUser.wzName, L"NetworkService"))
+            {
+                dwIdentity = 2;
+            }
+            else if (0 == _wcsicmp(psap->suUser.wzName, L"LocalService"))
+            {
+                dwIdentity = 1;
+            }
+            else if (0 == _wcsicmp(psap->suUser.wzName, L"LocalSystem"))
+            {
+                dwIdentity = 0;
+            }
+            else
+            {
+                dwIdentity = 3;
+            }
+        }
+        else if (0 == _wcsicmp(psap->suUser.wzDomain, L"NT AUTHORITY"))
+        {
+            if (0 == _wcsicmp(psap->suUser.wzName, L"NETWORK SERVICE"))
+            {
+                dwIdentity = 2;
+            }
+            else if (0 == _wcsicmp(psap->suUser.wzName, L"SERVICE"))
+            {
+                dwIdentity = 1;
+            }
+            else if (0 == _wcsicmp(psap->suUser.wzName, L"SYSTEM"))
+            {
+                dwIdentity = 0;
+            }
+            else
+            {
+                dwIdentity = 3;
+            }
+        }
+        else
+        {
+            dwIdentity = 3;
+        }
+    }
+
+    if (-1 != dwIdentity)
+    {
+        hr = ScaWriteConfigID(IIS_APPPOOL_IDENTITY);
+        ExitOnFailure(hr, "failed to set app pool identity id");
+        hr = ScaWriteConfigInteger(dwIdentity);
+        ExitOnFailure(hr, "failed to set app pool identity");
+
+        if (3 == dwIdentity)
+        {
+            if (*psap->suUser.wzDomain)
+            {
+                hr = StrAllocFormatted(&pwzValue, L"%s\\%s", psap->suUser.wzDomain, psap->suUser.wzName);
+                ExitOnFailure(hr, "failed to format user name: %ls domain: %ls", psap->suUser.wzName, psap->suUser.wzDomain);
+            }
+            else
+            {
+                hr = StrAllocFormatted(&pwzValue, L"%s", psap->suUser.wzName);
+                ExitOnFailure(hr, "failed to format user name: %ls", psap->suUser.wzName);
+            }
+
+            hr = ScaWriteConfigID(IIS_APPPOOL_USER);
+            ExitOnFailure(hr, "failed to set app pool identity name id");
+            hr = ScaWriteConfigString(pwzValue);
+            ExitOnFailure(hr, "failed to set app pool identity name");
+
+            hr = ScaWriteConfigID(IIS_APPPOOL_PWD);
+            ExitOnFailure(hr, "failed to set app pool identity password id");
+            hr = ScaWriteConfigString(psap->suUser.wzPassword);
+            ExitOnFailure(hr, "failed to set app pool identity password");
+        }
+    }
+    
+    if (*psap->wzManagedPipelineMode)
+    {
+        hr = ScaWriteConfigID(IIS_APPPOOL_MANAGED_PIPELINE_MODE);
+        ExitOnFailure(hr, "failed to set app pool integrated mode");
+        hr = ScaWriteConfigString(psap->wzManagedPipelineMode);
+        ExitOnFailure(hr, "failed to set app pool managed pipeline mode value");
+    }
+
+    if (*psap->wzManagedRuntimeVersion)
+    {
+        hr = ScaWriteConfigID(IIS_APPPOOL_MANAGED_RUNTIME_VERSION);
+        ExitOnFailure(hr, "failed to set app pool managed runtime version mode");
+        hr = ScaWriteConfigString(psap->wzManagedRuntimeVersion);
+        ExitOnFailure(hr, "failed to set app pool managed runtime version value");
+    }
+
+    //
+    //The number of properties above is variable so we put an end tag in so the
+    //execute CA will know when to stop looking for AppPool properties
+    //
+    hr = ScaWriteConfigID(IIS_APPPOOL_END);
+    ExitOnFailure(hr, "failed to set app pool end of properties id");
+
+LExit:
+    ReleaseStr(pwzValue);
+
+    return hr;
+}
+
+
+HRESULT ScaRemoveAppPool7(
+    __in const SCA_APPPOOL* psap
+    )
+{
+    Assert(psap);
+
+    HRESULT hr = S_OK;
+
+    //do not delete the default App Pool
+    if (0 != _wcsicmp(psap->wzAppPool, L"DefaultAppPool"))
+    {
+        //delete the app pool
+        hr = ScaWriteConfigID(IIS_APPPOOL);
+        ExitOnFailure(hr, "failed to write AppPool key.");
+
+        hr = ScaWriteConfigID(IIS_DELETE);
+        ExitOnFailure(hr, "failed to write AppPool delete action.");
+
+        hr = ScaWriteConfigString(psap->wzName);
+        ExitOnFailure(hr, "failed to delete AppPool: %ls", psap->wzName);
+    }
+
+LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+#include "scauser.h"
+
+// Identity
+#define APATTR_NETSERVICE 0x0001 // Network Service
+#define APATTR_LOCSERVICE 0x0002 // Local Service
+#define APATTR_LOCSYSTEM 0x0004 // Local System
+#define APATTR_OTHERUSER 0x0008 // Other User
+#define APATTR_APPPOOLIDENTITY 0x0010 // ApplicationPoolIdentity
+
+// prototypes
+HRESULT ScaFindAppPool7(
+    __in LPCWSTR wzAppPool,
+    __out_ecount(cchName) LPWSTR wzName,
+    __in DWORD cchName,
+    __in SCA_APPPOOL *psapList
+    );
+
+HRESULT ScaAppPoolInstall7(
+    __in SCA_APPPOOL* psapList
+    );
+
+HRESULT ScaAppPoolUninstall7(
+    __in SCA_APPPOOL* psapList
+    );
+
+HRESULT ScaWriteAppPool7(
+    __in const SCA_APPPOOL* psap
+    );
+
+HRESULT ScaRemoveAppPool7(
+    __in const SCA_APPPOOL* psap
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+// prototypes
+static HRESULT ConfigureCertificates(
+    __in SCA_ACTION saAction
+    );
+
+static LPCWSTR StoreMapping(
+    __in int iStore
+    );
+
+static HRESULT FindExistingCertificate(
+    __in LPCWSTR wzName,
+    __in DWORD dwStoreLocation,
+    __in LPCWSTR wzStore,
+    __out BYTE** prgbCertificate,
+    __out DWORD* pcbCertificate
+    );
+
+static HRESULT ResolveCertificate(
+    __in LPCWSTR wzId,
+    __in LPCWSTR wzName,
+    __in DWORD dwStoreLocation,
+    __in LPCWSTR wzStoreName,
+    __in DWORD dwAttributess,
+    __in LPCWSTR wzData,
+    __in LPCWSTR wzPFXPassword,
+    __out BYTE** ppbCertificate,
+    __out DWORD* pcbCertificate
+    );
+
+static HRESULT ReadCertificateFile(
+    __in LPCWSTR wzPath,
+    __out BYTE** prgbData,
+    __out DWORD* pcbData
+    );
+
+static HRESULT CertificateToHash(
+    __in BYTE* pbCertificate,
+    __in DWORD cbCertificate,
+    __in DWORD dwStoreLocation,
+    __in LPCWSTR wzPFXPassword,
+    __in BYTE rgbHash[],
+    __in DWORD cbHash
+    );
+
+/*
+HRESULT ScaGetCertificateByPath(LPCWSTR pwzName, BOOL fIsInstalling,
+                                BOOL fIsUninstalling, INT iStore,
+                                INT iStoreLocation, LPCWSTR wzSslCertificate,
+                                LPCWSTR wzPFXPassword, BSTR* pbstrCertificate,
+                                DWORD* pcbCertificate, BYTE* pbaHashBuffer);
+
+HRESULT ScaGetCertificateByRequest(LPCWSTR pwzName, BOOL fIsInstalling,
+                                   BOOL fIsUninstalling, INT iStore,
+                                   INT iStoreLocation, LPCWSTR wzDistinguishedName,
+                                   LPCWSTR wzCA, BSTR* pbstrCertificate,
+                                   DWORD* pcbCertificate, BYTE* pbaHashBuffer);
+
+HRESULT ScaSslNewCertificate(LPCWSTR pwzName, INT iStore,
+                            INT iStoreLocation, LPCWSTR wzComputerName,
+                            LPCWSTR wzDistinguishedName, LPCWSTR wzCertificateAuthorityOrig,
+                            BSTR* pbstrCertificate, DWORD* pcbCertificate,
+                            BYTE* pbaHashBuffer);
+
+HRESULT ScaSslExistingCertificateByName(LPCWSTR pwzName, INT iStore,
+                                       INT iStoreLocation, BSTR* pbstrCertificate,
+                                       DWORD* pcbCertificate, BYTE* pbaHashBuffer);
+
+HRESULT ScaSslExistingCertificateByBinaryData(INT iStore, INT iStoreLocation,
+                                             BYTE* pwzData, DWORD cchData);
+
+HRESULT CreateEnroll(ICEnroll2 **hEnroll, INT iStore,
+                     INT iStoreLocation);
+
+HRESULT RequestCertificate(LPCWSTR pwzName, INT iStore,
+                           INT iStoreLocation, LPCWSTR wzComputerName,
+                           LPCWSTR wzDistinguishedName, LPCWSTR wzCertificateAuthority,
+                           BSTR *pbstrCertificate);
+
+VOID ParseCertificateAuthority(__in LPCWSTR wzCertificateAuthorityOrig, __out LPWSTR *pwzBuffer,
+                               __out LPWSTR **hwzCAArray, __out int *piCAArray);
+*/
+
+
+LPCWSTR vcsCertQuery = L"SELECT `Certificate`, `Name`, `Component_`, `StoreLocation`, `StoreName`, `Attributes`, `Binary_`, `CertificatePath`, `PFXPassword` FROM `Certificate`";
+enum eCertQuery { cqCertificate = 1, cqName, cqComponent, cqStoreLocation, cqStoreName, cqAttributes, cqCertificateBinary, cqCertificatePath, cqPFXPassword };
+
+
+/********************************************************************
+InstallCertificates - CUSTOM ACTION ENTRY POINT for installing
+                      certificates
+
+********************************************************************/
+extern "C" UINT __stdcall InstallCertificates(
+    __in MSIHANDLE hInstall
+    )
+{
+    HRESULT hr = S_OK;
+    UINT er = ERROR_SUCCESS;
+
+    // initialize
+    hr = WcaInitialize(hInstall, "InstallCertificates");
+    ExitOnFailure(hr, "Failed to initialize");
+
+    hr = ConfigureCertificates(SCA_ACTION_INSTALL);
+
+LExit:
+    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
+    return WcaFinalize(er);
+}
+
+
+/********************************************************************
+UninstallCertificates - CUSTOM ACTION ENTRY POINT for uninstalling
+                        certificates
+
+********************************************************************/
+extern "C" UINT __stdcall UninstallCertificates(
+    __in MSIHANDLE hInstall
+    )
+{
+    HRESULT hr = S_OK;
+    UINT er = ERROR_SUCCESS;
+
+    // initialize
+    hr = WcaInitialize(hInstall, "UninstallCertificates");
+    ExitOnFailure(hr, "Failed to initialize");
+
+    hr = ConfigureCertificates(SCA_ACTION_UNINSTALL);
+
+LExit:
+    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
+    return WcaFinalize(er);
+}
+
+
+static HRESULT ConfigureCertificates(
+    __in SCA_ACTION saAction
+    )
+{
+    //AssertSz(FALSE, "debug ConfigureCertificates().");
+
+    HRESULT hr = S_OK;
+    DWORD er = ERROR_SUCCESS;
+
+    PMSIHANDLE hViewCertificate;
+    PMSIHANDLE hRecCertificate;
+    INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN;
+    INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN;
+
+    WCHAR* pwzId = NULL;
+    WCHAR* pwzName = NULL;
+    WCHAR* pwzComponent = NULL;
+    int iData = 0;
+    DWORD dwStoreLocation = 0;
+    LPWSTR pwzStoreName = 0;
+    DWORD dwAttributes = 0;
+    WCHAR* pwzData = NULL;
+    WCHAR* pwzPFXPassword = NULL;
+    WCHAR* pwzCaData = NULL;
+    WCHAR* pwzRollbackCaData = NULL;
+
+    BYTE* pbCertificate = NULL;
+    DWORD cbCertificate = 0;
+    DWORD_PTR cbPFXPassword = 0;
+
+    // Bail quickly if the Certificate table isn't around.
+    if (S_OK != WcaTableExists(L"Certificate"))
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ConfigureCertificates() - required table not present.");
+        ExitFunction1(hr = S_FALSE);
+    }
+
+    // Process the Certificate table.
+    hr = WcaOpenExecuteView(vcsCertQuery, &hViewCertificate);
+    ExitOnFailure(hr, "failed to open view on Certificate table");
+
+    while (SUCCEEDED(hr = WcaFetchRecord(hViewCertificate, &hRecCertificate)))
+    {
+        hr = WcaGetRecordString(hRecCertificate, cqCertificate, &pwzId); // the id is just useful to have up front
+        ExitOnFailure(hr, "failed to get Certificate.Certificate");
+
+        hr = WcaGetRecordString(hRecCertificate, cqComponent, &pwzComponent);
+        ExitOnFailure(hr, "failed to get Certificate.Component_");
+
+        er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzComponent, &isInstalled, &isAction);
+        hr = HRESULT_FROM_WIN32(er);
+        ExitOnFailure(hr, "failed to get state for component: %ls", pwzComponent);
+
+        if (!(WcaIsInstalling(isInstalled, isAction) && SCA_ACTION_INSTALL == saAction) &&
+            !(WcaIsUninstalling(isInstalled, isAction) && SCA_ACTION_UNINSTALL == saAction) &&
+            !(WcaIsReInstalling(isInstalled, isAction)))
+        {
+            WcaLog(LOGMSG_VERBOSE, "Skipping non-action certificate: %ls", pwzId);
+            continue;
+        }
+
+        // extract the rest of the data from the Certificate table
+        hr = WcaGetRecordFormattedString(hRecCertificate, cqName, &pwzName);
+        ExitOnFailure(hr, "failed to get Certificate.Name");
+
+        hr = WcaGetRecordInteger(hRecCertificate, cqStoreLocation, &iData);
+        ExitOnFailure(hr, "failed to get Certificate.StoreLocation");
+
+        switch (iData)
+        {
+        case SCA_CERTSYSTEMSTORE_CURRENTUSER:
+            dwStoreLocation = CERT_SYSTEM_STORE_CURRENT_USER;
+            break;
+        case SCA_CERTSYSTEMSTORE_LOCALMACHINE:
+            dwStoreLocation = CERT_SYSTEM_STORE_LOCAL_MACHINE;
+            break;
+        default:
+            hr = E_INVALIDARG;
+            ExitOnFailure(hr, "Invalid store location value: %d", iData);
+        }
+
+        hr = WcaGetRecordString(hRecCertificate, cqStoreName, &pwzStoreName);
+        ExitOnFailure(hr, "failed to get Certificate.StoreName");
+
+        hr = WcaGetRecordInteger(hRecCertificate, cqAttributes, reinterpret_cast<int*>(&dwAttributes));
+        ExitOnFailure(hr, "failed to get Certificate.Attributes");
+
+        if (dwAttributes & SCA_CERT_ATTRIBUTE_BINARYDATA)
+        {
+            hr = WcaGetRecordString(hRecCertificate, cqCertificateBinary, &pwzData);
+            ExitOnFailure(hr, "failed to get Certificate.Binary_");
+        }
+        else
+        {
+            hr = WcaGetRecordFormattedString(hRecCertificate, cqCertificatePath, &pwzData);
+            ExitOnFailure(hr, "failed to get Certificate.CertificatePath");
+        }
+
+        hr = WcaGetRecordFormattedString(hRecCertificate, cqPFXPassword, &pwzPFXPassword);
+        ExitOnFailure(hr, "failed to get Certificate.PFXPassword");
+
+        // Write the common data (for both install and uninstall) to the CustomActionData
+        // to pass data to the deferred CustomAction.
+        hr = StrAllocString(&pwzCaData, pwzName, 0);
+        ExitOnFailure(hr, "Failed to pass Certificate.Certificate to deferred CustomAction.");
+        hr = WcaWriteStringToCaData(pwzStoreName, &pwzCaData);
+        ExitOnFailure(hr, "Failed to pass Certificate.StoreName to deferred CustomAction.");
+        hr = WcaWriteIntegerToCaData(dwAttributes, &pwzCaData);
+        ExitOnFailure(hr, "Failed to pass Certificate.Attributes to deferred CustomAction.");
+
+        // Copy the rollback data from the deferred data because it's the same up to this point.
+        hr = StrAllocString(&pwzRollbackCaData, pwzCaData, 0);
+        ExitOnFailure(hr, "Failed to allocate string for rollback CustomAction.");
+
+        // Finally, schedule the correct deferred CustomAction to actually do work.
+        LPCWSTR wzAction = NULL;
+        LPCWSTR wzRollbackAction = NULL;
+        DWORD dwCost = 0;
+        if (SCA_ACTION_UNINSTALL == saAction)
+        {
+            // Find an existing certificate one (if there is one) to so we have it for rollback.
+            hr = FindExistingCertificate(pwzName, dwStoreLocation, pwzStoreName, &pbCertificate, &cbCertificate);
+            ExitOnFailure(hr, "Failed to search for existing certificate with friendly name: %ls", pwzName);
+
+            if (pbCertificate)
+            {
+                hr = WcaWriteStreamToCaData(pbCertificate, cbCertificate, &pwzRollbackCaData);
+                ExitOnFailure(hr, "Failed to pass Certificate.Data to rollback CustomAction.");
+
+                hr = WcaWriteStringToCaData(pwzPFXPassword, &pwzRollbackCaData);
+                ExitOnFailure(hr, "Failed to pass Certificate.PFXPassword to rollback CustomAction.");
+
+                hr = WcaWriteIntegerToCaData(dwAttributes, &pwzCaData);
+                ExitOnFailure(hr, "Failed to pass Certificate.Attributes to deferred CustomAction.");
+            }
+
+            // Pick the right action to run based on what store we're uninstalling from.
+            if (CERT_SYSTEM_STORE_LOCAL_MACHINE == dwStoreLocation)
+            {
+                wzAction = CUSTOM_ACTION_DECORATION(L"DeleteMachineCertificate");
+                if (pbCertificate)
+                {
+                    wzRollbackAction = L"RollbackDeleteMachineCertificate";
+                }
+            }
+            else
+            {
+                wzAction = CUSTOM_ACTION_DECORATION(L"DeleteUserCertificate");
+                if (pbCertificate)
+                {
+                    wzRollbackAction = L"RollbackDeleteUserCertificate";
+                }
+            }
+            dwCost = COST_CERT_DELETE;
+        }
+        else
+        {
+            // Actually get the certificate, resolve it to a blob, and get the blob's hash.
+            hr = ResolveCertificate(pwzId, pwzName, dwStoreLocation, pwzStoreName, dwAttributes, pwzData, pwzPFXPassword, &pbCertificate, &cbCertificate);
+            ExitOnFailure(hr, "Failed to resolve certificate: %ls", pwzId);
+
+            hr = WcaWriteStreamToCaData(pbCertificate, cbCertificate, &pwzCaData);
+            ExitOnFailure(hr, "Failed to pass Certificate.Data to deferred CustomAction.");
+
+            hr = WcaWriteStringToCaData(pwzPFXPassword, &pwzCaData);
+            ExitOnFailure(hr, "Failed to pass Certificate.PFXPassword to deferred CustomAction.");
+
+            // Pick the right action to run based on what store we're installing into.
+            if (CERT_SYSTEM_STORE_LOCAL_MACHINE == dwStoreLocation)
+            {
+                wzAction = CUSTOM_ACTION_DECORATION(L"AddMachineCertificate");
+                wzRollbackAction = CUSTOM_ACTION_DECORATION(L"RollbackAddMachineCertificate");
+            }
+            else
+            {
+                wzAction = CUSTOM_ACTION_DECORATION(L"AddUserCertificate");
+                wzRollbackAction = CUSTOM_ACTION_DECORATION(L"RollbackAddUserCertificate");
+            }
+            dwCost = COST_CERT_ADD;
+        }
+
+        if (wzRollbackAction)
+        {
+            hr = WcaDoDeferredAction(wzRollbackAction, pwzRollbackCaData, dwCost);
+            ExitOnFailure(hr, "Failed to schedule rollback certificate action '%ls' for: %ls", wzRollbackAction, pwzId);
+        }
+
+        hr = WcaDoDeferredAction(wzAction, pwzCaData, dwCost);
+        ExitOnFailure(hr, "Failed to schedule certificate action '%ls' for: %ls", wzAction, pwzId);
+
+        // Clean up for the next certificate.
+        ReleaseNullMem(pbCertificate);
+    }
+
+    if (E_NOMOREITEMS == hr)
+    {
+        hr = S_OK;
+    }
+
+LExit:
+    if (NULL != pwzPFXPassword && SUCCEEDED(StrSize(pwzPFXPassword, &cbPFXPassword)))
+    {
+        SecureZeroMemory(pwzPFXPassword, cbPFXPassword);
+    }
+
+    ReleaseMem(pbCertificate);
+    ReleaseStr(pwzCaData);
+    ReleaseStr(pwzPFXPassword);
+    ReleaseStr(pwzData);
+    ReleaseStr(pwzName);
+    ReleaseStr(pwzStoreName);
+    ReleaseStr(pwzComponent);
+    ReleaseStr(pwzId);
+
+    return hr;
+}
+
+
+static HRESULT ResolveCertificate(
+    __in LPCWSTR wzId,
+    __in LPCWSTR /*wzName*/,
+    __in DWORD dwStoreLocation,
+    __in LPCWSTR /*wzStoreName*/,
+    __in DWORD dwAttributes,
+    __in LPCWSTR wzData,
+    __in LPCWSTR wzPFXPassword,
+    __out BYTE** ppbCertificate,
+    __out DWORD* pcbCertificate
+    )
+{
+    HRESULT hr = S_OK;
+
+    LPWSTR pwzSql = NULL;
+    PMSIHANDLE hView;
+    PMSIHANDLE hRec;
+    MSIHANDLE hCertificateHashView = NULL;
+    MSIHANDLE hCertificateHashColumns = NULL;
+
+    BYTE rgbCertificateHash[CB_CERTIFICATE_HASH] = { 0 };
+    WCHAR wzEncodedCertificateHash[CB_CERTIFICATE_HASH * 2 + 1] = { 0 };
+
+    PMSIHANDLE hViewCertificateRequest, hRecCertificateRequest;
+
+    WCHAR* pwzDistinguishedName = NULL;
+    WCHAR* pwzCA = NULL;
+
+    BYTE* pbData = NULL;
+    DWORD cbData = 0;
+
+    if (dwAttributes & SCA_CERT_ATTRIBUTE_REQUEST)
+    {
+        hr = E_NOTIMPL;
+        ExitOnFailure(hr, "Installing certificates by requesting them from a certificate authority is not currently supported");
+        //if (dwAttributes & SCA_CERT_ATTRIBUTE_OVERWRITE)
+        //{
+        //    // try to overwrite with the patch to a cert file
+        //    WcaLog(LOGMSG_VERBOSE, "ConfigureCertificates - Overwrite with SSLCERTIFICATE");
+        //    hr = ScaGetCertificateByPath(pwzName, fIsInstalling, fIsUninstalling,
+        //        iStore, iStoreLocation, pwzData, wzPFXPassword, pbstrCertificate, pcbCertificate, pbaHashBuffer);
+        //}
+        //if (hr != S_OK)
+        //{
+        //    if (fIsUninstalling && !fIsInstalling)
+        //    {
+        //        // for uninstall, we just want to find the existing certificate
+        //        hr = ScaSslExistingCertificateByName(pwzName, iStore, iStoreLocation, pbstrCertificate, pcbCertificate, pbaHashBuffer);
+        //        ExitOnFailure(hr, "Failed Retrieving existing certificate during uninstall");
+        //        // ok if no existing cert
+        //        if (S_OK != hr)
+        //            hr = S_OK;
+        //    }
+        //    else
+        //    {
+        //        // still no certificate
+        //        // user has request this certificate, try to locate DistinguishedName and CA
+        //        hr = WcaTableExists(L"CertificateRequest");
+        //        ExitOnFailure(hr, "CertificateRequest is referenced but not found");
+        //        WcaLog(LOGMSG_VERBOSE, "ConfigureCertificates - CertificateRequest table present");
+        //        cchSQLView = 255 + lstrlenW(pwzName);
+        //        pwzSQLView = new WCHAR[cchSQLView];
+        //        if (pwzSQLView)
+        //        {
+        //            hr = ::StringCchPrintfW(pwzSQLView, cchSQLView, L"SELECT `DistinguishedName`, `CA` FROM `CertificateRequest` WHERE `Certificate_`=\'%s\'", pwzName);
+        //            ExitOnFailure(hr, "::StringCchPrintfW failed");
+        //            hr = WcaOpenExecuteView(pwzSQLView, &hViewCertificateRequest);
+        //            ExitOnFailure(hr, "failed to open view on CertificateRequest table");
+        //            hr = WcaFetchSingleRecord(hViewCertificateRequest, &hRecCertificateRequest);
+        //            ExitOnFailure(hr, "failed to retrieve request from CertificateRequest table");
+        //            hr = WcaGetRecordString(hRecCertificateRequest,  1, &pwzDistinguishedName);
+        //            ExitOnFailure(hr, "failed to get DistinguishedName");
+        //            hr = WcaGetRecordString(hRecCertificateRequest,  2, &pwzCA);
+        //            ExitOnFailure(hr, "failed to get CA");
+        //            if (pwzDistinguishedName && pwzCA && *pwzDistinguishedName && *pwzCA)
+        //            {
+        //                hr = ScaGetCertificateByRequest(pwzName, fIsInstalling, fIsUninstalling, iStore, iStoreLocation, pwzDistinguishedName, pwzCA, pbstrCertificate, pcbCertificate, pbaHashBuffer);
+        //            }
+        //            else
+        //            {
+        //                hr = E_FAIL;
+        //                ExitOnFailure(hr, "CertificateRequest entry is empty");
+        //            }
+        //        }
+        //        else
+        //        {
+        //            hr = E_FAIL;
+        //            ExitOnFailure(hr, "Out of memory");
+        //        }
+        //    }
+        //}
+    }
+    else if (dwAttributes & SCA_CERT_ATTRIBUTE_BINARYDATA)
+    {
+        // get the binary stream in Binary
+        hr = WcaTableExists(L"Binary");
+        if (S_OK != hr)
+        {
+            if (SUCCEEDED(hr))
+            {
+                hr = E_UNEXPECTED;
+            }
+            ExitOnFailure(hr, "Binary was referenced but there is no Binary table.");
+        }
+
+        hr = StrAllocFormatted(&pwzSql, L"SELECT `Data` FROM `Binary` WHERE `Name`=\'%s\'", wzData);
+        ExitOnFailure(hr, "Failed to allocate Binary table query.");
+
+        hr = WcaOpenExecuteView(pwzSql, &hView);
+        ExitOnFailure(hr, "Failed to open view on Binary table");
+
+        hr = WcaFetchSingleRecord(hView, &hRec);
+        ExitOnFailure(hr, "Failed to retrieve request from Binary table");
+
+        hr = WcaGetRecordStream(hRec, 1, &pbData, &cbData);
+        ExitOnFailure(hr, "Failed to ready Binary.Data for certificate.");
+    }
+    else if (dwAttributes == SCA_CERT_ATTRIBUTE_DEFAULT)
+    {
+        hr = ReadCertificateFile(wzData, &pbData, &cbData);
+        ExitOnFailure(hr, "Failed to read certificate from file path.");
+    }
+    else
+    {
+        hr = E_INVALIDARG;
+        ExitOnFailure(hr, "Invalid Certificate.Attributes.");
+    }
+
+    // If we have loaded a certificate, update the Certificate.Hash column.
+    if (pbData)
+    {
+        hr = CertificateToHash(pbData, cbData, dwStoreLocation, wzPFXPassword, rgbCertificateHash, countof(rgbCertificateHash));
+        ExitOnFailure(hr, "Failed to get SHA1 hash of certificate.");
+
+        hr = StrHexEncode(rgbCertificateHash, countof(rgbCertificateHash), wzEncodedCertificateHash, countof(wzEncodedCertificateHash));
+        ExitOnFailure(hr, "Failed to hex encode SHA1 hash of certificate.");
+
+        // Update the CertificateHash table.
+        hr = WcaAddTempRecord(&hCertificateHashView, &hCertificateHashColumns, L"CertificateHash", NULL, 0, 2, wzId, wzEncodedCertificateHash);
+        ExitOnFailure(hr, "Failed to add encoded has for certificate: %ls", wzId);
+    }
+
+    *ppbCertificate = pbData;
+    *pcbCertificate = cbData;
+    pbData = NULL;
+
+LExit:
+    if (hCertificateHashColumns)
+    {
+        ::MsiCloseHandle(hCertificateHashColumns);
+    }
+
+    if (hCertificateHashView)
+    {
+        ::MsiCloseHandle(hCertificateHashView);
+    }
+
+    ReleaseStr(pwzDistinguishedName);
+    ReleaseStr(pwzCA);
+    ReleaseMem(pbData);
+    ReleaseStr(pwzSql);
+
+    return hr;
+}
+
+
+static HRESULT ReadCertificateFile(
+    __in LPCWSTR wzPath,
+    __out BYTE** prgbData,
+    __out DWORD* pcbData
+    )
+{
+    HRESULT hr = S_OK;
+
+    PCCERT_CONTEXT pCertContext = NULL;
+    DWORD dwContentType;
+    BYTE* pbData = NULL;
+    DWORD cbData = 0;
+
+    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))
+    {
+        ExitOnFailure(hr, "Failed to read certificate from file: %ls", wzPath);
+    }
+
+    if (pCertContext)
+    {
+        cbData = pCertContext->cbCertEncoded;
+        pbData = static_cast<BYTE*>(MemAlloc(cbData, FALSE));
+        ExitOnNull(pbData, hr, E_OUTOFMEMORY, "Failed to allocate memory to read certificate from file: %ls", wzPath);
+
+        CopyMemory(pbData, pCertContext->pbCertEncoded, pCertContext->cbCertEncoded);
+    }
+    else
+    {
+        // If we have a PFX blob, get the first certificate out of the PFX and use that instead of the PFX.
+        if (dwContentType & CERT_QUERY_CONTENT_PFX)
+        {
+            hr = FileRead(&pbData, &cbData, wzPath);
+            ExitOnFailure(hr, "Failed to read PFX file: %ls", wzPath);
+        }
+        else
+        {
+            hr = E_UNEXPECTED;
+            ExitOnFailure(hr, "Unexpected certificate type read from disk.");
+        }
+    }
+
+    *pcbData = cbData;
+    *prgbData = pbData;
+    pbData = NULL;
+
+LExit:
+    ReleaseMem(pbData);
+    return hr;
+}
+
+
+static HRESULT CertificateToHash(
+    __in BYTE* pbCertificate,
+    __in DWORD cbCertificate,
+    __in DWORD dwStoreLocation,
+    __in LPCWSTR wzPFXPassword,
+    __in BYTE rgbHash[],
+    __in DWORD cbHash
+    )
+{
+    HRESULT hr = S_OK;
+
+    HCERTSTORE hPfxCertStore = NULL;
+    PCCERT_CONTEXT pCertContext = NULL;
+    PCCERT_CONTEXT pCertContextEnum = NULL;
+    CRYPT_DATA_BLOB blob = { 0 };
+    CRYPT_KEY_PROV_INFO* pPfxInfo = NULL;
+    DWORD dwKeyset = (CERT_SYSTEM_STORE_CURRENT_USER == dwStoreLocation) ? CRYPT_USER_KEYSET : CRYPT_MACHINE_KEYSET;
+    DWORD dwEncodingType;
+    DWORD dwContentType;
+    DWORD dwFormatType;
+
+    blob.pbData = pbCertificate;
+    blob.cbData = cbCertificate;
+
+    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))
+    {
+        ExitWithLastError(hr, "Failed to process certificate as a valid certificate.");
+    }
+
+    if (!pCertContext)
+    {
+        // If we have a PFX blob, get the first certificate out of the PFX and use that instead of the PFX.
+        if (dwContentType & CERT_QUERY_CONTENT_PFX)
+        {
+            // If we fail and our password is blank, also try passing in NULL for the password (according to the docs)
+            hPfxCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, wzPFXPassword, dwKeyset);
+            if (NULL == hPfxCertStore && !*wzPFXPassword)
+            {
+                hPfxCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, NULL, dwKeyset);
+            }
+            ExitOnNullWithLastError(hPfxCertStore, hr, "Failed to open PFX file.");
+
+            // Find the first cert with a private key, or just use the last one
+            for (pCertContextEnum = ::CertEnumCertificatesInStore(hPfxCertStore, pCertContextEnum);
+                 pCertContextEnum;
+                 pCertContextEnum = ::CertEnumCertificatesInStore(hPfxCertStore, pCertContextEnum))
+            {
+                pCertContext = pCertContextEnum;
+
+                if (pCertContext && CertHasPrivateKey(pCertContext, NULL))
+                {
+                    break;
+                }
+            }
+
+            ExitOnNullWithLastError(pCertContext, hr, "Failed to read first certificate out of PFX file.");
+
+            // Ignore failures, the worst that happens is some parts of the PFX get left behind.
+            CertReadProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, &pPfxInfo, NULL);
+        }
+        else
+        {
+            hr = E_UNEXPECTED;
+            ExitOnFailure(hr, "Unexpected certificate type processed.");
+        }
+    }
+
+    DWORD cb = cbHash;
+    if (!::CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, static_cast<LPVOID>(rgbHash), &cb))
+    {
+        ExitWithLastError(hr, "Failed to get certificate SHA1 hash property.");
+    }
+    AssertSz(cb == cbHash, "Did not correctly read certificate SHA1 hash.");
+
+LExit:
+    if (pCertContext)
+    {
+        ::CertFreeCertificateContext(pCertContext);
+    }
+
+    if (hPfxCertStore)
+    {
+        ::CertCloseStore(hPfxCertStore, 0);
+    }
+
+    if (pPfxInfo)
+    {
+        HCRYPTPROV hProvIgnored = NULL; // ignored on deletes.
+        ::CryptAcquireContextW(&hProvIgnored, pPfxInfo->pwszContainerName, pPfxInfo->pwszProvName, pPfxInfo->dwProvType, dwKeyset | CRYPT_DELETEKEYSET | CRYPT_SILENT);
+
+        MemFree(pPfxInfo);
+    }
+
+    return hr;
+}
+
+
+static HRESULT FindExistingCertificate(
+    __in LPCWSTR wzName,
+    __in DWORD dwStoreLocation,
+    __in LPCWSTR wzStore,
+    __out BYTE** prgbCertificate,
+    __out DWORD* pcbCertificate
+    )
+{
+    HRESULT hr = S_OK;
+    HCERTSTORE hCertStore = NULL;
+    PCCERT_CONTEXT pCertContext = NULL;
+    BYTE* pbCertificate = NULL;
+    DWORD cbCertificate = 0;
+
+    hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, dwStoreLocation | CERT_STORE_READONLY_FLAG, wzStore);
+    MessageExitOnNullWithLastError(hCertStore, hr, msierrCERTFailedOpen, "Failed to open certificate store.");
+
+    // Loop through the certificate, looking for certificates that match our friendly name.
+    pCertContext = CertFindCertificateInStore(hCertStore, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL);
+    while (pCertContext)
+    {
+        WCHAR wzFriendlyName[256] = { 0 };
+        DWORD cbFriendlyName = sizeof(wzFriendlyName);
+
+        if (::CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, reinterpret_cast<BYTE*>(wzFriendlyName), &cbFriendlyName) &&
+            CSTR_EQUAL == ::CompareStringW(LOCALE_SYSTEM_DEFAULT, 0, wzName, -1, wzFriendlyName, -1))
+        {
+            // If the certificate with matching friendly name is valid, let's use that.
+            long lVerify = ::CertVerifyTimeValidity(NULL, pCertContext->pCertInfo);
+            if (0 == lVerify)
+            {
+                cbCertificate = pCertContext->cbCertEncoded;
+                pbCertificate = static_cast<BYTE*>(MemAlloc(cbCertificate, FALSE));
+                ExitOnNull(pbCertificate, hr, E_OUTOFMEMORY, "Failed to allocate memory to copy out exist certificate.");
+
+                CopyMemory(pbCertificate, pCertContext->pbCertEncoded, cbCertificate);
+                break; // found a matching certificate, no more searching necessary
+            }
+        }
+
+         // Next certificate in the store.
+        PCCERT_CONTEXT pNext = ::CertFindCertificateInStore(hCertStore, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, pCertContext);
+        // old pCertContext is freed by CertFindCertificateInStore
+        pCertContext = pNext;
+    }
+
+    *prgbCertificate = pbCertificate;
+    *pcbCertificate = cbCertificate;
+    pbCertificate = NULL;
+
+LExit:
+    ReleaseMem(pbCertificate);
+
+    if (pCertContext)
+    {
+        ::CertFreeCertificateContext(pCertContext);
+    }
+
+    if (hCertStore)
+    {
+        ::CertCloseStore(hCertStore, 0);
+    }
+
+    return hr;
+}
+
+/*
+HRESULT CreateEnroll(ICEnroll2 **hEnroll, INT iStore, INT iStoreLocation)
+{
+    ICEnroll2 *pEnroll = NULL;
+    HRESULT hr = S_OK;
+    LONG lFlags;
+    DWORD dwFlags = iStoreLocation << CERT_SYSTEM_STORE_LOCATION_SHIFT;
+
+    // create IEntroll
+    hr = CoCreateInstance( CLSID_CEnroll, NULL, CLSCTX_INPROC_SERVER, IID_ICEnroll2, (void **)&pEnroll );
+    if (FAILED(hr))
+        return hr;
+
+    switch (iStore)
+    {
+    case SCA_CERT_STORENAME_MY:
+        pEnroll->get_MyStoreFlags(&lFlags);
+        lFlags &= ~CERT_SYSTEM_STORE_LOCATION_MASK;
+        lFlags |= dwFlags;
+        // following call will change Request store flags also
+        pEnroll->put_MyStoreFlags(lFlags);
+        break;
+    case SCA_CERT_STORENAME_CA:
+        pEnroll->get_CAStoreFlags(&lFlags);
+        lFlags &= ~CERT_SYSTEM_STORE_LOCATION_MASK;
+        lFlags |= dwFlags;
+        // following call will change Request store flags also
+        pEnroll->put_CAStoreFlags(lFlags);
+        break;
+    case SCA_CERT_STORENAME_REQUEST:
+        pEnroll->get_RequestStoreFlags(&lFlags);
+        lFlags &= ~CERT_SYSTEM_STORE_LOCATION_MASK;
+        lFlags |= dwFlags;
+        // following call will change Request store flags also
+        pEnroll->put_RequestStoreFlags(lFlags);
+        break;
+    case SCA_CERT_STORENAME_ROOT:
+        pEnroll->get_RootStoreFlags(&lFlags);
+        lFlags &= ~CERT_SYSTEM_STORE_LOCATION_MASK;
+        lFlags |= dwFlags;
+        // following call will change Request store flags also
+        pEnroll->put_RootStoreFlags(lFlags);
+        break;
+    default:
+        hr = E_FAIL;
+        return hr;
+    }
+
+    pEnroll->get_GenKeyFlags(&lFlags);
+    lFlags |= CRYPT_EXPORTABLE;
+    pEnroll->put_GenKeyFlags(lFlags);
+
+    pEnroll->put_KeySpec(AT_KEYEXCHANGE);
+    pEnroll->put_ProviderType(PROV_RSA_SCHANNEL);
+    pEnroll->put_DeleteRequestCert(TRUE);
+
+    *hEnroll = pEnroll;
+    return hr;
+}
+
+
+HRESULT RequestCertificate(LPCWSTR pwzName, INT iStore, INT iStoreLocation,
+                           LPCWSTR wzComputerName, LPCWSTR wzDistinguishedName, LPCWSTR wzCertificateAuthority,
+                           BSTR *pbstrCertificate)
+{
+    if (pbstrCertificate == NULL)
+        return E_INVALIDARG;
+
+    HRESULT hr;
+    ICEnroll2 *pEnroll = NULL;
+    ICertRequest *pCertRequest = NULL;
+    BSTR bstrRequest = NULL;
+    LONG nDisposition;
+
+    BSTR bstrCertificateUsage = NULL;
+    BSTR bstrCertificateAttributes = NULL;
+    BSTR bstrCertificateAuthority = NULL;
+
+    // equivalent to: sprintf(bstrDistinguishedName, L"%s,CN=%s", wzDistinguishedName, wzComputerName);
+    DWORD cchComputerName = lstrlenW(wzComputerName);
+    DWORD cchDistinguishedName = lstrlenW(wzDistinguishedName);
+    CONST DWORD cchbstrDistinguishedName = 5 + cchComputerName + cchDistinguishedName;
+    BSTR bstrDistinguishedName = SysAllocStringLen(NULL, cchbstrDistinguishedName);
+    ExitOnNull(bstrDistinguishedName, hr, E_OUTOFMEMORY, "Failed to allocate space for distinguished name.");
+    ::StringCchCopyW((WCHAR*) bstrDistinguishedName, cchbstrDistinguishedName, wzDistinguishedName);
+    ::StringCchCatW((WCHAR*) bstrDistinguishedName, cchbstrDistinguishedName, L",CN=");
+    ::StringCchCatW((WCHAR*) bstrDistinguishedName, cchbstrDistinguishedName, wzComputerName);
+
+    bstrCertificateUsage = SysAllocString(WIDE(szOID_PKIX_KP_SERVER_AUTH));
+    ExitOnNull(bstrCertificateUsage, hr, E_OUTOFMEMORY, "Failed to allocate space for Certificate Usage.");
+    bstrCertificateAttributes = SysAllocString(L"CertificateTemplate:WebServer");
+    bstrCertificateAuthority = SysAllocString(wzCertificateAuthority);
+    ExitOnNull(bstrCertificateAuthority, hr, E_OUTOFMEMORY, "Failed to allocate space for Certificate Authority.");
+
+    hr = CreateEnroll(&pEnroll, iStore, iStoreLocation);
+    ExitOnFailure(hr, "failed CoCreateInstance IEnroll");
+
+    hr = pEnroll->createPKCS10(bstrDistinguishedName, bstrCertificateUsage, &bstrRequest);
+    ExitOnFailure(hr, "failed createPKCS10");
+
+    hr = CoCreateInstance(CLSID_CCertRequest, NULL, CLSCTX_INPROC_SERVER, IID_ICertRequest, (void **)&pCertRequest);
+    ExitOnFailure(hr, "failed CoCreateInstance ICertRequest");
+
+    hr = pCertRequest->Submit(CR_IN_BASE64 | CR_IN_PKCS10, bstrRequest, bstrCertificateAttributes, bstrCertificateAuthority, &nDisposition);
+    ExitOnFailure(hr, "failed ICertRequest.Submit");
+
+    hr = (nDisposition == CR_DISP_ISSUED) ? S_OK : E_FAIL;
+    ExitOnFailure(hr, "failed CR_DISP_ISSUED");
+
+    hr = pCertRequest->GetCertificate(CR_OUT_BASE64, pbstrCertificate);
+    ExitOnFailure(hr, "failed ICertRequest.GetCertificate");
+
+    // save the certificate in place, cannot be passed to a deferred custom action
+    hr = pEnroll->acceptPKCS7(*pbstrCertificate);
+    ExitOnFailure(hr, "failed accept certificate into MY store");
+
+LExit:
+    ReleaseObject(pCertRequest);
+    ReleaseBSTR(bstrRequest);
+    ReleaseObject(pEnroll);
+    ReleaseBSTR(bstrCertificateAuthority);
+    ReleaseBSTR(bstrCertificateAttributes);
+    ReleaseBSTR(bstrDistinguishedName);
+
+    return hr;
+}
+
+
+VOID ParseCertificateAuthority(__in LPCWSTR wzCertificateAuthorityOrig, __out LPWSTR *pwzBuffer, __out LPWSTR **hwzCAArray, __out int *piCAArray)
+{
+    // @asAuthorities = split /;/, $sAuthority;
+    CONST WCHAR wchDelimiter = L';';
+
+    // copy constant into a buffer
+    Assert(wzCertificateAuthorityOrig);
+
+    INT cchCA = lstrlenW(wzCertificateAuthorityOrig) + 1;
+    WCHAR* wzBuffer = new WCHAR[cchCA];
+    if (!wzBuffer)
+        return;
+
+    ::StringCchCopyW(wzBuffer, cchCA, wzCertificateAuthorityOrig);
+
+    // determine the number of strings in the field
+    int iCAArray = 1;
+    int i;
+    for (i = 0; i < cchCA; ++i)
+    {
+        if (wzBuffer[i] == wchDelimiter)
+            ++iCAArray;
+    }
+    LPWSTR *pwzCAArray = (LPWSTR*) new BYTE[iCAArray * sizeof(LPWSTR)];
+    if (!pwzCAArray)
+    {
+        return;
+    }
+
+    pwzCAArray[0] = wzBuffer;
+    iCAArray = 0;
+    for (i = 0; i < cchCA; ++i)
+    {
+        if (wzBuffer[i] != wchDelimiter)
+            continue;
+        wzBuffer[i] = 0; // convert buffer into MULTISZ
+        pwzCAArray[iCAArray] = &wzBuffer[i+1];
+        ++iCAArray;
+    }
+
+    *pwzBuffer = wzBuffer;
+    *hwzCAArray = pwzCAArray;
+    *piCAArray = iCAArray;
+}
+
+
+HRESULT ScaSslExistingCertificateByBinaryData(INT iStore, INT iStoreLocation, BYTE* pwzData, DWORD cchData)
+{
+    HRESULT hr = S_FALSE;
+    HCERTSTORE hCertStore = NULL;
+    PCCERT_CONTEXT pCertCtx = NULL, pCertCtxExisting = NULL;
+    DWORD dwFlags = 0;
+    LPCWSTR wzStore = StoreMapping(iStore);
+    CERT_BLOB blob;
+
+    dwFlags = iStoreLocation << CERT_SYSTEM_STORE_LOCATION_SHIFT;
+    hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, dwFlags, wzStore);
+    MessageExitOnNullWithLastError(hCertStore, hr, msierrCERTFailedOpen, "failed to open certificate store, OK on uninstall");
+
+    blob.pbData = pwzData;
+    blob.cbData = cchData;
+
+    if (!::CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL,
+        0, NULL, NULL, NULL, NULL, NULL, (LPCVOID*)&pCertCtx))
+        ExitOnLastError(hr, "failed to parse the certificate blob, OK on uninstall");
+
+    pCertCtxExisting = CertFindCertificateInStore(
+        hCertStore,
+        PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+        0,
+        CERT_FIND_EXISTING,
+        pCertCtx,
+        NULL);
+
+    if (pCertCtxExisting)
+    {
+        hr = S_OK;
+    }
+
+LExit:
+    if (pCertCtx)
+    {
+        CertFreeCertificateContext(pCertCtx);
+        pCertCtx = NULL;
+    }
+    if (pCertCtxExisting)
+    {
+        CertFreeCertificateContext(pCertCtxExisting);
+        pCertCtxExisting = NULL;
+    }
+    if (hCertStore)
+    {
+        CertCloseStore(hCertStore, 0);
+        hCertStore = NULL;
+    }
+
+    return hr;
+}
+
+
+HRESULT ScaSslExistingCertificateByName(LPCWSTR pwzName, INT iStore, INT iStoreLocation,
+                                       BSTR* pbstrCertificate, DWORD* pcbCertificate, BYTE* pbaHashBuffer)
+{
+    HRESULT hr = S_FALSE;
+    HCERTSTORE hSystemStore = NULL;
+    PCCERT_CONTEXT pTargetCert = NULL;
+    WCHAR wzFriendlyName[MAX_PATH] = {0};
+    DWORD dwFriendlyNameLen = sizeof(wzFriendlyName);
+
+    // Call CertOpenStore to open the CA store.
+    hSystemStore = CertOpenStore(
+        CERT_STORE_PROV_SYSTEM_REGISTRY,
+        0,
+        NULL,
+        (iStoreLocation << CERT_SYSTEM_STORE_LOCATION_SHIFT) | CERT_STORE_OPEN_EXISTING_FLAG,
+        StoreMapping(iStore));
+    if (hSystemStore == NULL)
+        ExitFunction();
+
+    // Get a particular certificate using CertFindCertificateInStore.
+    pTargetCert = CertFindCertificateInStore(
+        hSystemStore,
+        PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+        0,
+        CERT_FIND_ANY,
+        NULL,
+        NULL);
+    while (pTargetCert != NULL)
+    {
+        if ((CertGetCertificateContextProperty(pTargetCert, CERT_FRIENDLY_NAME_PROP_ID,
+            (BYTE*)wzFriendlyName, &dwFriendlyNameLen)) &&
+            lstrcmpW(wzFriendlyName, pwzName) == 0)
+        {
+            // pTargetCert is a pointer to the desired certificate.
+            // Check the certificate's validity.
+            switch (CertVerifyTimeValidity(
+                NULL,
+                pTargetCert->pCertInfo))
+            {
+            case 1:
+                // Certificate is expired
+                WcaLog(LOGMSG_STANDARD, "The SSL certificate has expired");
+                // always remove it
+                {
+                    PCCERT_CONTEXT pDupCertContext = CertDuplicateCertificateContext(pTargetCert);
+                    if (pDupCertContext && CertDeleteCertificateFromStore(pDupCertContext))
+                    {
+                        WcaLog(LOGMSG_STANDARD, "A SSL certificate has removed");
+                    }
+                }
+                break;
+            case 0:
+                // Certificate is valid
+                WcaLog(LOGMSG_STANDARD, "The SSL certificate is valid");
+                hr = S_OK;
+                if (pbaHashBuffer)
+                {
+                    // if the certificate already exists and is valid, use that one
+                    DWORD dwHashSize = CB_CERTIFICATE_HASH;
+                    hr = CertGetCertificateContextProperty(pTargetCert, CERT_SHA1_HASH_PROP_ID, (VOID*)pbaHashBuffer, &dwHashSize)
+                        ? S_OK : E_FAIL;
+                    ExitOnFailure(hr, "failed CertGetCertificateContextProperty CERT_SHA1_HASH_PROP_ID");
+                    Assert(pbstrCertificate);
+                    Assert(pcbCertificate);
+                    ReleaseBSTR(*pbstrCertificate);
+
+                    *pbstrCertificate = SysAllocStringByteLen((LPCSTR)(pTargetCert->pbCertEncoded), pTargetCert->cbCertEncoded);
+                    *pcbCertificate = pTargetCert->cbCertEncoded;
+                }
+                ExitFunction();
+                break;
+            default:
+                // Certificate not valid yet, ignore it
+                WcaLog(LOGMSG_STANDARD, "The SSL certificate is not valid");
+                break;
+            }
+        }
+        pTargetCert = CertFindCertificateInStore(
+            hSystemStore,
+            PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+            0,
+            CERT_FIND_ANY,
+            NULL,
+            pTargetCert);
+        wzFriendlyName[0] = 0;
+        dwFriendlyNameLen = sizeof(wzFriendlyName);
+    }
+
+LExit:
+    // Clean up memory and quit.
+    if (pTargetCert)
+    {
+        CertFreeCertificateContext(pTargetCert);
+        pTargetCert = NULL;
+    }
+    if (hSystemStore)
+    {
+        CertCloseStore(hSystemStore, CERT_CLOSE_STORE_CHECK_FLAG);
+        hSystemStore = NULL;
+    }
+
+    return hr;
+}
+
+
+HRESULT ScaSslNewCertificate(LPCWSTR pwzName, INT iStore, INT iStoreLocation, LPCWSTR wzComputerName, LPCWSTR wzDistinguishedName, LPCWSTR wzCertificateAuthorityOrig,
+                            BSTR* pbstrCertificate, DWORD* pcbCertificate, BYTE* pbaHashBuffer)
+{
+
+    if (pbstrCertificate == NULL)
+        return E_INVALIDARG;
+
+    HRESULT hr = S_OK;
+    LPWSTR wzCABuffer = NULL;
+    LPWSTR *wzCAArray = NULL;
+    int iCAArray = 0;
+
+    // otherwise call the CA for one
+    ParseCertificateAuthority(wzCertificateAuthorityOrig, &wzCABuffer, &wzCAArray, &iCAArray);
+
+    // try each authority three times
+    for (int i = 0; i < 3 * iCAArray; ++i)
+    {
+        LPCWSTR wzCA = wzCAArray[i % iCAArray];
+        if (NULL == wzCA || NULL == wzCA[0]) continue;
+        WcaLog(LOGMSG_STANDARD, "Requesting SSL certificate from %ls", wzCA);
+        hr = RequestCertificate(pwzName, iStore, iStoreLocation, wzComputerName, wzDistinguishedName, wzCA, pbstrCertificate);
+        if (hr == S_OK && pbstrCertificate)
+        {
+            // set the friendly name
+            CRYPT_HASH_BLOB hblob;
+            CERT_BLOB blob;
+            HCERTSTORE hCertStore = NULL;
+            PCCERT_CONTEXT pCertCtxExisting = NULL;
+
+            blob.pbData = (BYTE*)pwzName;
+            blob.cbData = (lstrlenW(pwzName) + 1) * sizeof(pwzName[0]); // including terminating null
+
+            *pcbCertificate = SysStringByteLen(*pbstrCertificate);
+            hr = CertificateToHash(*pbstrCertificate, pbaHashBuffer);
+            ExitOnFailure(hr, "failed to CertificateToHash for an existing certificate");
+
+            hblob.pbData = pbaHashBuffer;
+            hblob.cbData = CB_CERTIFICATE_HASH;
+
+            hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, (iStoreLocation << CERT_SYSTEM_STORE_LOCATION_SHIFT), StoreMapping(iStore));
+            MessageExitOnNullWithLastError(hCertStore, hr, msierrCERTFailedOpen, "failed to open certificate store");
+
+            pCertCtxExisting = CertFindCertificateInStore(
+                hCertStore,
+                PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+                0,
+                CERT_FIND_HASH,
+                &hblob,
+                NULL);
+
+            if (pCertCtxExisting)
+            {
+                CertSetCertificateContextProperty(
+                    pCertCtxExisting,
+                    CERT_FRIENDLY_NAME_PROP_ID,
+                    0,
+                    &blob);
+            }
+
+            if (pCertCtxExisting)
+            {
+                CertFreeCertificateContext(pCertCtxExisting);
+                pCertCtxExisting = NULL;
+            }
+            if (hCertStore)
+            {
+                CertCloseStore(hCertStore, 0);
+                hCertStore = NULL;
+            }
+            ExitFunction();
+        }
+        if (pbstrCertificate && *pbstrCertificate)
+        {
+            SysFreeString(*pbstrCertificate);
+            pbstrCertificate = NULL;
+        }
+    }
+    hr = E_FAIL;
+    ExitOnFailure(hr, "failed to RequestCertificate");
+
+LExit:
+    if (wzCABuffer)
+    {
+        delete wzCABuffer;
+    }
+    if (wzCAArray)
+    {
+        delete wzCAArray;
+    }
+
+    return hr;
+}
+
+
+HRESULT ScaGetCertificateByRequest(LPCWSTR pwzName, BOOL fIsInstalling, BOOL fIsUninstalling,
+                                   INT iStore, INT iStoreLocation,
+                                   LPCWSTR wzDistinguishedName, LPCWSTR wzCA,
+                                   BSTR* pbstrCertificate, DWORD* pcbCertificate, BYTE* pbaHashBuffer)
+{
+    HRESULT hr = S_OK;
+    WCHAR wzComputerName[MAX_COMPUTER_NAME] = {0};
+    WCHAR* pwzData = NULL;
+    DWORD cchData = 0;
+
+    // override %COMPUTERNAME% with DOMAINNAME property
+    hr = WcaGetProperty( L"DOMAINNAME", &pwzData);
+    ExitOnFailure(hr, "Failed to get Property DOMAINNAME");
+    if (*pwzData)
+    {
+        // if DOMAINNAME is set, use it
+        ::StringCchCopyW(wzComputerName, MAX_COMPUTER_NAME, pwzData);
+    }
+    else
+    {
+        // otherwise get the intranet name given by %COMPUTERNAME%
+        GetEnvironmentVariableW(L"COMPUTERNAME", wzComputerName, MAX_COMPUTER_NAME);
+    }
+
+    hr = ScaSslExistingCertificateByName(pwzName, iStore, iStoreLocation, pbstrCertificate, pcbCertificate, pbaHashBuffer);
+    ExitOnFailure(hr, "Failed ScaSslExistingCertificateByName");
+    if (S_OK != hr)
+    {
+        if (!fIsUninstalling && fIsInstalling)
+        {
+            // if no existing cert and not on uninstall, hit the authority
+            WcaLog(LOGMSG_STANDARD, "Adding certificate: requested, %ls", wzDistinguishedName);
+            hr = ScaSslNewCertificate(pwzName, iStore, iStoreLocation, wzComputerName, wzDistinguishedName, wzCA,
+                pbstrCertificate, pcbCertificate, pbaHashBuffer);
+            ExitOnFailure(hr, "Failed ScaSslNewCertificate");
+        }
+        else
+        {
+            // if no existing cert and uninstall
+            hr = S_OK;
+        }
+    }
+
+LExit:
+    ReleaseStr(pwzData);
+
+    return hr;
+}
+
+
+HRESULT ScaInstallCertificateByContext(LPCWSTR pwzName, INT iStore, INT iStoreLocation,
+                                       PCCERT_CONTEXT pCertContext)
+{
+    HRESULT hr = S_OK;
+    HCERTSTORE hCertStore = NULL;
+    DWORD dwFlags = iStoreLocation << CERT_SYSTEM_STORE_LOCATION_SHIFT;
+    CERT_BLOB blob;
+
+    hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, dwFlags, StoreMapping(iStore));
+    if (hCertStore == NULL)
+        MessageExitOnLastError(hr, msierrCERTFailedOpen, "failed to open certificate store");
+
+    blob.pbData = (BYTE*)pwzName;
+    blob.cbData = (lstrlenW(pwzName) + 1) * sizeof(pwzName[0]); // including terminating null
+    CertSetCertificateContextProperty(
+        pCertContext,
+        CERT_FRIENDLY_NAME_PROP_ID,
+        0,
+        &blob);
+
+    if (!CertAddCertificateContextToStore(
+        hCertStore,
+        pCertContext,
+        CERT_STORE_ADD_REPLACE_EXISTING,
+        NULL))
+    {
+        hr = E_FAIL;
+        MessageExitOnLastError(hr, msierrCERTFailedAdd, "failed to add certificate to the store");
+    }
+
+LExit:
+    if (hCertStore)
+    {
+        CertCloseStore(hCertStore, 0);
+        hCertStore = NULL;
+    }
+
+    return hr;
+}
+
+
+HRESULT ScaGetCertificateByPath(LPCWSTR pwzName, BOOL fIsInstalling, BOOL fIsUninstalling,
+                                INT iStore, INT iStoreLocation, LPCWSTR wzSslCertificate, LPCWSTR wzPFXPassword,
+                                BSTR* pbstrCertificate, DWORD* pcbCertificate, BYTE* pbaHashBuffer)
+{
+    Assert(wzSslCertificate);
+    HRESULT hr = S_OK;
+    PCCERT_CONTEXT pCertContext = NULL;
+    DWORD dwEncodingType = 0;
+    DWORD dwContentType = 0;
+    DWORD dwFormatType = 0;
+    DWORD dwHashSize = CB_CERTIFICATE_HASH;
+    HANDLE hPfxFile = INVALID_HANDLE_VALUE;
+    CRYPT_DATA_BLOB blob;
+
+    blob.pbData = NULL;
+    blob.cbData = 0;
+
+    if (wzSslCertificate && wzSslCertificate[0] != 0)
+    {
+        if (!::CryptQueryObject(CERT_QUERY_OBJECT_FILE, (LPVOID)wzSslCertificate, CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL,
+            0, &dwEncodingType, &dwContentType, &dwFormatType, NULL, NULL, (LPCVOID*)&pCertContext))
+            hr = fIsUninstalling ? S_FALSE : HRESULT_FROM_WIN32(::GetLastError());  // don't fail on uninstall
+        ExitOnFailure(hr, "failed CryptQueryObject");
+    }
+    else
+    {
+        hr = S_FALSE;
+        ExitFunction();
+    }
+
+    if (!pCertContext)
+    {
+        // this is a pfx?
+        // make sure to exit this block of code properly for clean up blob.pbData
+        if (dwContentType & CERT_QUERY_CONTENT_PFX)
+        {
+            DWORD iSize = 0, iReadSize = 0;
+            HCERTSTORE hPfxCertStore = NULL;
+
+            hPfxFile = ::CreateFileW(wzSslCertificate, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+            hr = (hPfxFile != INVALID_HANDLE_VALUE) ? S_OK : E_FAIL;
+            ExitOnFailure(hr, "failed CryptQueryObject, file handle is null");
+            iSize = ::GetFileSize(hPfxFile, NULL);
+            hr = (iSize > 0) ? S_OK : E_FAIL;
+            ExitOnFailure(hr, "failed CryptQueryObject, file size is 0");
+            blob.pbData = new BYTE[iSize];
+            blob.cbData = iSize;
+            hr = (blob.pbData) ? S_OK : E_FAIL;
+            ExitOnFailure(hr, "out of memory for blob");
+
+            if (::ReadFile(hPfxFile, (LPVOID)blob.pbData, iSize, &iReadSize, NULL))
+            {
+                hPfxCertStore = PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, wzPFXPassword,
+                    (iStoreLocation == SCA_CERTSYSTEMSTORE_CURRENTUSER) ? CRYPT_USER_KEYSET : CRYPT_MACHINE_KEYSET);
+                if (hPfxCertStore)
+                {
+                    pCertContext = CertEnumCertificatesInStore(hPfxCertStore, NULL);
+                    // work only with the first certificate in pfx
+                    if (pCertContext)
+                    {
+                        hr = CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, (VOID*)pbaHashBuffer, &dwHashSize)
+                            ? S_OK : E_FAIL;
+                        ExitOnFailure(hr, "failed CertGetCertificateContextProperty CERT_SHA1_HASH_PROP_ID");
+                        ReleaseBSTR(*pbstrCertificate);
+
+                        *pbstrCertificate = SysAllocStringByteLen((LPCSTR)(pCertContext->pbCertEncoded), pCertContext->cbCertEncoded);
+                        *pcbCertificate = pCertContext->cbCertEncoded;
+                        if (fIsInstalling)
+                        {
+                            // install the certificate, cannot defer because the data required cannot be passed
+                            hr = ScaInstallCertificateByContext(pwzName, iStore, iStoreLocation, pCertContext);
+                        }
+                    }
+                    else
+                        hr = E_FAIL;
+                }
+                else
+                    hr = E_FAIL;
+            }
+            else
+                hr = E_FAIL;
+        }
+        else
+        {
+            ExitOnFailure(hr = E_FAIL, "failed CryptQueryObject, unknown data");
+        }
+    }
+    else
+    {
+        // return cert and its hash
+        hr = CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, (VOID*)pbaHashBuffer, &dwHashSize)
+            ? S_OK : E_FAIL;
+        ExitOnFailure(hr, "failed CertGetCertificateContextProperty CERT_SHA1_HASH_PROP_ID");
+        ReleaseBSTR(*pbstrCertificate);
+
+        *pbstrCertificate = SysAllocStringByteLen((LPCSTR)(pCertContext->pbCertEncoded), pCertContext->cbCertEncoded);
+        *pcbCertificate = pCertContext->cbCertEncoded;
+        if (fIsInstalling)
+        {
+            // install the certificate, cannot defer because the data required cannot be passed
+            hr = ScaInstallCertificateByContext(pwzName, iStore, iStoreLocation, pCertContext);
+        }
+    }
+
+LExit:
+    if (pCertContext)
+    {
+        CertFreeCertificateContext(pCertContext);
+        pCertContext = NULL;
+    }
+    if (hPfxFile != INVALID_HANDLE_VALUE)
+    {
+        CloseHandle(hPfxFile);
+        hPfxFile = INVALID_HANDLE_VALUE;
+    }
+    if (blob.pbData)
+    {
+        delete [] blob.pbData;
+        blob.pbData = NULL;
+        blob.cbData = 0;
+    }
+
+    return hr;
+}
+
+
+HRESULT ScaInstallCertificateByBinaryData(BOOL fAddCert, INT iStore, INT iStoreLocation, LPCWSTR wzName, BYTE* pwzData, DWORD cchData,
+                                          LPCWSTR wzPFXPassword)
+{
+    Assert(wzName);
+    Assert(pwzData);
+    Assert(cchData);
+    HRESULT hr = S_OK;
+    HCERTSTORE hCertStore = NULL, hPfxCertStore = NULL;
+    PCCERT_CONTEXT pCertCtx = NULL, pCertCtxExisting = NULL;
+    DWORD dwFlags, dwEncodingType, dwContentType, dwFormatType;
+    CERT_BLOB blob;
+    LPCWSTR wzStore = StoreMapping(iStore);
+
+    dwFlags = iStoreLocation << CERT_SYSTEM_STORE_LOCATION_SHIFT;
+    hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, dwFlags, wzStore);
+    MessageExitOnNullWithLastError(hCertStore, hr, msierrCERTFailedOpen, "failed to open certificate store");
+
+    blob.pbData = pwzData;
+    blob.cbData = cchData;
+
+    if (!::CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL,
+        0, &dwEncodingType, &dwContentType, &dwFormatType, NULL, NULL, (LPCVOID*)&pCertCtx))
+        ExitOnLastError(hr, "failed to parse the certificate blob");
+    ExitOnNull(pCertCtx, hr, E_UNEXPECTED, "failed to parse the certificate blob");
+
+    blob.pbData = (BYTE*)wzName;
+    blob.cbData = (lstrlenW(wzName) + 1) * sizeof(wzName[0]); // including terminating null
+
+    CertSetCertificateContextProperty(
+        pCertCtx,
+        CERT_FRIENDLY_NAME_PROP_ID,
+        0,
+        &blob);
+
+    if (fAddCert)
+    {
+        // Add
+        WcaLog(LOGMSG_STANDARD, "Adding certificate: binary name, %ls", wzName);
+        if (!CertAddCertificateContextToStore(
+            hCertStore,
+            pCertCtx,
+            CERT_STORE_ADD_REPLACE_EXISTING,
+            NULL))
+        {
+            hr = E_FAIL;
+            MessageExitOnLastError(hr, msierrCERTFailedAdd, "failed to add certificate to the store");
+        }
+    }
+    else
+    {
+        // Delete
+        WcaLog(LOGMSG_STANDARD, "Deleting certificate provided: binary name, %ls", wzName);
+        pCertCtxExisting = CertFindCertificateInStore(
+            hCertStore,
+            PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+            0,
+            CERT_FIND_EXISTING,
+            pCertCtx,
+            NULL);
+
+        if (pCertCtxExisting)
+        {
+            if (!CertDeleteCertificateFromStore(pCertCtxExisting))
+            {
+                ExitOnLastError(hr, "failed to delete certificate");
+            }
+            else
+            {
+                pCertCtxExisting = NULL;
+            }
+        }
+    }
+
+LExit:
+    if (pCertCtx)
+    {
+        CertFreeCertificateContext(pCertCtx);
+        pCertCtx = NULL;
+    }
+    if (pCertCtxExisting)
+    {
+        CertFreeCertificateContext(pCertCtxExisting);
+        pCertCtxExisting = NULL;
+    }
+    // order is important for store
+    if (hCertStore)
+    {
+        CertCloseStore(hCertStore, 0);
+        hCertStore = NULL;
+    }
+    if (hPfxCertStore)
+    {
+        CertCloseStore(hPfxCertStore, 0);
+        hPfxCertStore = NULL;
+    }
+
+    return hr;
+}
+*/
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 @@
+#pragma once
+// 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.
+
+
+#define CB_CERTIFICATE_HASH 20
+
+// Certificate.Attribute
+enum SCA_CERT_ATTRIBUTES
+{
+    SCA_CERT_ATTRIBUTE_DEFAULT = 0,
+    SCA_CERT_ATTRIBUTE_REQUEST = 1,
+    SCA_CERT_ATTRIBUTE_BINARYDATA = 2,
+    SCA_CERT_ATTRIBUTE_OVERWRITE = 4,
+    SCA_CERT_ATTRIBUTE_VITAL = 8,
+};
+
+
+// Certificate.StoreLocation
+enum SCA_CERTSYSTEMSTORE
+{
+    SCA_CERTSYSTEMSTORE_CURRENTUSER = 1,
+    SCA_CERTSYSTEMSTORE_LOCALMACHINE = 2,
+};
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 @@
+// 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.
+
+#include "precomp.h"
+
+#define SIXTY_FOUR_MEG 64 * 1024 * 1024
+
+// prototypes
+static HRESULT ExecuteCertificateOperation(
+    __in MSIHANDLE hInstall,
+    __in SCA_ACTION saAction,
+    __in DWORD dwStoreRoot
+    );
+
+static HRESULT ReadCertificateFile(
+    __in LPCWSTR wzPath,
+    __out BYTE** prgbData,
+    __out DWORD* pcbData
+    );
+
+static HRESULT InstallCertificatePackage(
+    __in HCERTSTORE hStore,
+    __in BOOL fUserCertificateStore,
+    __in LPCWSTR wzName,
+    __in_opt BYTE* rgbData,
+    __in DWORD cbData,
+    __in BOOL fVital,
+    __in_opt LPCWSTR wzPFXPassword
+    );
+
+static HRESULT UninstallCertificatePackage(
+    __in HCERTSTORE hStore,
+    __in BOOL fUserCertificateStore,
+    __in LPCWSTR wzName
+    );
+
+static HRESULT AddCertificate(
+    __in HCERTSTORE hStore,
+    __in PCCERT_CONTEXT pCertContext,
+    __in LPCWSTR wzCertificateUniqueName,
+    __in BOOL fVital
+);
+
+/* ****************************************************************
+ AddUserCertificate - CUSTOM ACTION ENTRY POINT for adding per-user
+                      certificates
+
+ * ***************************************************************/
+extern "C" UINT __stdcall AddUserCertificate(
+    __in MSIHANDLE hInstall
+    )
+{
+    HRESULT hr = S_OK;
+    DWORD er = ERROR_SUCCESS;
+
+    hr = WcaInitialize(hInstall, "AddUserCertificate");
+    ExitOnFailure(hr, "Failed to initialize AddUserCertificate.");
+
+    hr = ExecuteCertificateOperation(hInstall, SCA_ACTION_INSTALL, CERT_SYSTEM_STORE_CURRENT_USER);
+    ExitOnFailure(hr, "Failed to install per-user certificate.");
+
+LExit:
+    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
+    return WcaFinalize(er);
+}
+
+
+/* ****************************************************************
+ AddMachineCertificate - CUSTOM ACTION ENTRY POINT for adding 
+                         per-machine certificates
+
+ * ***************************************************************/
+extern "C" UINT __stdcall AddMachineCertificate(
+    __in MSIHANDLE hInstall
+    )
+{
+    HRESULT hr = S_OK;
+    DWORD er = ERROR_SUCCESS;
+
+    hr = WcaInitialize(hInstall, "AddMachineCertificate");
+    ExitOnFailure(hr, "Failed to initialize AddMachineCertificate.");
+
+    hr = ExecuteCertificateOperation(hInstall, SCA_ACTION_INSTALL, CERT_SYSTEM_STORE_LOCAL_MACHINE);
+    ExitOnFailure(hr, "Failed to install per-machine certificate.");
+
+LExit:
+    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
+    return WcaFinalize(er);
+}
+
+
+/* ****************************************************************
+ DeleteUserCertificate - CUSTOM ACTION ENTRY POINT for deleting 
+                         per-user certificates
+
+ * ***************************************************************/
+extern "C" UINT __stdcall DeleteUserCertificate(
+    __in MSIHANDLE hInstall
+    )
+{
+    HRESULT hr = S_OK;
+    DWORD er = ERROR_SUCCESS;
+
+    hr = WcaInitialize(hInstall, "DeleteUserCertificate");
+    ExitOnFailure(hr, "Failed to initialize DeleteUserCertificate.");
+
+    hr = ExecuteCertificateOperation(hInstall, SCA_ACTION_UNINSTALL, CERT_SYSTEM_STORE_CURRENT_USER);
+    ExitOnFailure(hr, "Failed to uninstall per-user certificate.");
+
+LExit:
+    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
+    return WcaFinalize(er);
+}
+
+
+/* ****************************************************************
+ DeleteMachineCertificate - CUSTOM ACTION ENTRY POINT for deleting
+                            per-machine certificates
+
+ * ***************************************************************/
+extern "C" UINT __stdcall DeleteMachineCertificate(
+    __in MSIHANDLE hInstall
+    )
+{
+    HRESULT hr = S_OK;
+    DWORD er = ERROR_SUCCESS;
+
+    hr = WcaInitialize(hInstall, "DeleteMachineCertificate");
+    ExitOnFailure(hr, "Failed to initialize DeleteMachineCertificate.");
+
+    hr = ExecuteCertificateOperation(hInstall, SCA_ACTION_UNINSTALL, CERT_SYSTEM_STORE_LOCAL_MACHINE);
+    ExitOnFailure(hr, "Failed to uninstall per-machine certificate.");
+
+LExit:
+    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
+    return WcaFinalize(er);
+}
+
+
+static HRESULT ExecuteCertificateOperation(
+    __in MSIHANDLE /*hInstall*/,
+    __in SCA_ACTION saAction,
+    __in DWORD dwStoreLocation
+    )
+{
+    //AssertSz(FALSE, "Debug ExecuteCertificateOperation() here.");
+    Assert(saAction & SCA_ACTION_INSTALL || saAction & SCA_ACTION_UNINSTALL);
+
+    HRESULT hr = S_OK;
+    LPWSTR pwzCaData = NULL;
+    LPWSTR pwz;
+    LPWSTR pwzName = NULL;
+    LPWSTR pwzStore = NULL;
+    int iAttributes = 0;
+    LPWSTR pwzPFXPassword = NULL;
+    LPWSTR pwzFilePath = NULL;
+    BYTE* pbData = NULL;
+    DWORD cbData = 0;
+    DWORD_PTR cbPFXPassword = 0;
+
+    BOOL fUserStoreLocation = (CERT_SYSTEM_STORE_CURRENT_USER == dwStoreLocation);
+    HCERTSTORE hCertStore = NULL;
+
+    hr = WcaGetProperty(L"CustomActionData", &pwzCaData);
+    ExitOnFailure(hr, "Failed to get CustomActionData");
+
+    WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCaData);
+
+    pwz = pwzCaData;
+    hr = WcaReadStringFromCaData(&pwz, &pwzName);
+    ExitOnFailure(hr, "Failed to parse certificate name.");
+    hr = WcaReadStringFromCaData(&pwz, &pwzStore);
+    ExitOnFailure(hr, "Failed to parse CustomActionData, StoreName");
+    hr = WcaReadIntegerFromCaData(&pwz, &iAttributes);
+    ExitOnFailure(hr, "Failed to parse certificate attribute");
+    if (SCA_ACTION_INSTALL == saAction) // install operations need more data
+    {
+        hr = WcaReadStreamFromCaData(&pwz, &pbData, (DWORD_PTR*)&cbData);
+        ExitOnFailure(hr, "Failed to parse certificate stream.");
+
+        hr = WcaReadStringFromCaData(&pwz, &pwzPFXPassword);
+        ExitOnFailure(hr, "Failed to parse certificate password.");
+    }
+
+    // Open the right store.
+    hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, dwStoreLocation | CERT_STORE_MAXIMUM_ALLOWED_FLAG, pwzStore);
+    MessageExitOnNullWithLastError(hCertStore, hr, msierrCERTFailedOpen, "Failed to open certificate store: %ls", pwzStore);
+
+    if (SCA_ACTION_INSTALL == saAction) // install operations need more data
+    {
+        // Uninstall existing versions of this package.  Ignore any failures
+        // This is needed to clean up the private key of a cert when we replace an existing cert
+        // CertAddCertificateContextToStore(CERT_STORE_ADD_REPLACE_EXISTING) does not remove the private key if the cert is replaced
+        UninstallCertificatePackage(hCertStore, fUserStoreLocation, pwzName);
+
+        hr = InstallCertificatePackage(hCertStore, fUserStoreLocation, pwzName, pbData, cbData, iAttributes & SCA_CERT_ATTRIBUTE_VITAL, pwzPFXPassword);
+        ExitOnFailure(hr, "Failed to install certificate.");
+    }
+    else
+    {
+        Assert(SCA_ACTION_UNINSTALL == saAction);
+
+        hr = UninstallCertificatePackage(hCertStore, fUserStoreLocation, pwzName);
+        ExitOnFailure(hr, "Failed to uninstall certificate.");
+    }
+
+LExit:
+    if (NULL != pwzPFXPassword && SUCCEEDED(StrSize(pwzPFXPassword, &cbPFXPassword)))
+    {
+        SecureZeroMemory(pwzPFXPassword, cbPFXPassword);
+    }
+
+    if (hCertStore)
+    {
+        if (!::CertCloseStore(hCertStore, CERT_CLOSE_STORE_CHECK_FLAG))
+        {
+            WcaLog(LOGMSG_VERBOSE, "Cert store was closed but not all resources were freed.  Error 0x%x", GetLastError());
+        }
+    }
+
+    ReleaseMem(pbData);
+    ReleaseStr(pwzFilePath);
+    ReleaseStr(pwzPFXPassword);
+    ReleaseStr(pwzStore);
+    ReleaseStr(pwzName);
+    ReleaseStr(pwzCaData);
+    return hr;
+}
+
+
+static HRESULT InstallCertificatePackage(
+    __in HCERTSTORE hStore,
+    __in BOOL fUserCertificateStore,
+    __in LPCWSTR wzName,
+    __in_opt BYTE* rgbData,
+    __in DWORD cbData,
+    __in BOOL fVital,
+    __in_opt LPCWSTR wzPFXPassword
+    )
+{
+    HRESULT hr = S_OK;
+
+    HCERTSTORE hPfxCertStore = NULL;
+    PCCERT_CONTEXT pCertContext = NULL;
+    CERT_BLOB blob = { 0 };
+    DWORD dwKeyset = fUserCertificateStore ? CRYPT_USER_KEYSET : CRYPT_MACHINE_KEYSET;
+    DWORD dwEncodingType;
+    DWORD dwContentType;
+    DWORD dwFormatType;
+    LPWSTR pwzUniqueName = NULL;
+    int iUniqueId = 0;
+
+    // Figure out what type of blob (certificate or PFX) we're dealing with here.
+    blob.pbData = rgbData;
+    blob.cbData = cbData;
+
+    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))
+    {
+        ExitWithLastError(hr, "Failed to parse the certificate blob: %ls", wzName);
+    }
+
+    hr = StrAllocFormatted(&pwzUniqueName, L"%s_wixCert_%d", wzName, ++iUniqueId);
+    ExitOnFailure(hr, "Failed to format unique name");
+
+    if (!pCertContext)
+    {
+        // If we have a PFX blob, get the first certificate out of the PFX and use that instead of the PFX.
+        if (dwContentType & CERT_QUERY_CONTENT_PFX)
+        {
+            ExitOnNull(wzPFXPassword, hr, E_INVALIDARG, "Failed to import PFX blob because no password was provided");
+
+            // If we fail and our password is blank, also try passing in NULL for the password (according to the docs)
+            hPfxCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, wzPFXPassword, dwKeyset);
+            if (NULL == hPfxCertStore && !*wzPFXPassword)
+            {
+                hPfxCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, NULL, dwKeyset);
+            }
+            ExitOnNullWithLastError(hPfxCertStore, hr, "Failed to open PFX file.");
+
+            // Install all certificates in the PFX
+            for (pCertContext = ::CertEnumCertificatesInStore(hPfxCertStore, pCertContext);
+                 pCertContext;
+                 pCertContext = ::CertEnumCertificatesInStore(hPfxCertStore, pCertContext))
+            {
+                hr = AddCertificate(hStore, pCertContext, pwzUniqueName, fVital);
+                MessageExitOnFailure(hr, msierrCERTFailedAdd, "Failed to add certificate to the store.");
+
+                hr = StrAllocFormatted(&pwzUniqueName, L"%s_wixCert_%d", wzName, ++iUniqueId);
+                ExitOnFailure(hr, "Failed to format unique name");
+            }
+        }
+        else
+        {
+            hr = E_UNEXPECTED;
+            ExitOnFailure(hr, "Unexpected certificate type processed.");
+        }
+    }
+    else
+    {
+        hr = AddCertificate(hStore, pCertContext, pwzUniqueName, fVital);
+        MessageExitOnFailure(hr, msierrCERTFailedAdd, "Failed to add certificate to the store.");
+    }
+
+    hr = WcaProgressMessage(COST_CERT_ADD, FALSE);
+    ExitOnFailure(hr, "Failed to send install progress message.");
+
+LExit:
+    ReleaseStr(pwzUniqueName);
+
+    if (pCertContext)
+    {
+        ::CertFreeCertificateContext(pCertContext);
+    }
+
+    // Close the stores after the context's are released.
+    if (hPfxCertStore)
+    {
+        if (!::CertCloseStore(hPfxCertStore, CERT_CLOSE_STORE_CHECK_FLAG))
+        {
+            WcaLog(LOGMSG_VERBOSE, "PFX cert store was closed but not all resources were freed.  Error 0x%x", GetLastError());
+        }
+    }
+
+    return hr;
+}
+
+
+static HRESULT UninstallCertificatePackage(
+    __in HCERTSTORE hStore,
+    __in BOOL fUserCertificateStore,
+    __in LPCWSTR wzName
+    )
+{
+    HRESULT hr = S_OK;
+    DWORD er = ERROR_SUCCESS;
+    PCCERT_CONTEXT pCertContext = NULL;
+    CRYPT_KEY_PROV_INFO* pPrivateKeyInfo = NULL;
+    LPWSTR pwzUniquePrefix = NULL;
+    int ccUniquePrefix = 0;
+
+    hr = StrAllocFormatted(&pwzUniquePrefix, L"%s_wixCert_", wzName);
+    ExitOnFailure(hr, "Failed to format unique name");
+    ccUniquePrefix = ::lstrlenW(pwzUniquePrefix);
+
+    WcaLog(LOGMSG_STANDARD, "Deleting certificate that begin with friendly name: %ls", pwzUniquePrefix);
+
+    // Loop through all certificates in the store, deleting the ones that begin with our prefix.
+    while (NULL != (pCertContext = ::CertFindCertificateInStore(hStore, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, pCertContext)))
+    {
+        WCHAR wzFriendlyName[256] = { 0 };
+        DWORD cbFriendlyName = sizeof(wzFriendlyName);
+
+        if (::CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, reinterpret_cast<BYTE*>(wzFriendlyName), &cbFriendlyName) &&
+            lstrlenW(wzFriendlyName) >= ccUniquePrefix &&
+            CSTR_EQUAL == ::CompareStringW(LOCALE_SYSTEM_DEFAULT, 0, pwzUniquePrefix, ccUniquePrefix, wzFriendlyName, ccUniquePrefix))
+        {
+            PCCERT_CONTEXT pCertContextDelete = ::CertDuplicateCertificateContext(pCertContext); // duplicate the context so we can delete it with out disrupting the looping
+            if(pCertContextDelete)
+            {
+                // Delete the certificate and if successful delete the matching private key as well.
+                if (::CertDeleteCertificateFromStore(pCertContextDelete))
+                {
+                    // If we found private key info, delete it.
+                    hr = CertReadProperty(pCertContextDelete, CERT_KEY_PROV_INFO_PROP_ID, &pPrivateKeyInfo, NULL);
+                    if (SUCCEEDED(hr))
+                    {
+                        HCRYPTPROV hProvIgnored = NULL; // ignored on deletes.
+                        DWORD dwKeyset = fUserCertificateStore ? CRYPT_USER_KEYSET : CRYPT_MACHINE_KEYSET;
+
+                        if (!::CryptAcquireContextW(&hProvIgnored, pPrivateKeyInfo->pwszContainerName, pPrivateKeyInfo->pwszProvName, pPrivateKeyInfo->dwProvType, dwKeyset | CRYPT_DELETEKEYSET | CRYPT_SILENT))
+                        {
+                            er = ::GetLastError();
+                            hr = HRESULT_FROM_WIN32(er);
+                        }
+
+                        ReleaseNullMem(pPrivateKeyInfo);
+                    }
+                    else // don't worry about failures to delete private keys.
+                    {
+                        hr = S_OK;
+                    }
+                }
+                else
+                {
+                    er = ::GetLastError();
+                    hr = HRESULT_FROM_WIN32(er);
+                }
+
+                if (FAILED(hr))
+                {
+                    WcaLog(LOGMSG_STANDARD, "Failed to delete certificate with friendly name: %ls, continuing anyway.  Error: 0x%x", wzFriendlyName, hr);
+                }
+
+                pCertContextDelete = NULL;
+            }
+        }
+    }
+
+    hr = WcaProgressMessage(COST_CERT_DELETE, FALSE);
+    ExitOnFailure(hr, "Failed to send uninstall progress message.");
+
+LExit:
+    ReleaseStr(pwzUniquePrefix);
+    ReleaseMem(pPrivateKeyInfo);
+    if(pCertContext)
+    {
+        ::CertFreeCertificateContext(pCertContext);
+    }
+
+    return hr;
+}
+
+static HRESULT AddCertificate(
+    __in HCERTSTORE hStore,
+    __in PCCERT_CONTEXT pCertContext,
+    __in LPCWSTR wzCertificateUniqueName,
+    __in BOOL fVital
+)
+{
+    HRESULT hr = S_OK;
+
+    WcaLog(LOGMSG_STANDARD, "Adding certificate: %ls", wzCertificateUniqueName);
+
+    hr = CertInstallSingleCertificate(hStore, pCertContext, wzCertificateUniqueName);
+    if (FAILED(hr) && !fVital)
+    {
+        WcaLog(LOGMSG_STANDARD, "Could not add non-vital certificate: %ls due to error: 0x%x, continuing...", wzCertificateUniqueName, hr);
+        hr = S_FALSE;
+    }
+
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+const UINT COST_IIS_TRANSACTIONS = 10000;
+
+const UINT COST_IIS_CREATEKEY = 5000;
+const UINT COST_IIS_DELETEKEY = 5000;
+const UINT COST_IIS_WRITEVALUE = 5000;
+const UINT COST_IIS_DELETEVALUE = 5000;
+const UINT COST_IIS_CREATEAPP = 5000;
+const UINT COST_IIS_DELETEAPP = 5000;
+
+const UINT COST_CERT_ADD = 5000;
+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 @@
+// 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.
+
+#include "precomp.h"
+
+
+/********************************************************************
+ StartMetabaseTransaction - CUSTOM ACTION ENTRY POINT for backing up metabase
+
+  Input:  deferred CustomActionData - BackupName
+********************************************************************/
+extern "C" UINT __stdcall StartMetabaseTransaction(MSIHANDLE hInstall)
+{
+//AssertSz(FALSE, "debug StartMetabaseTransaction here");
+    HRESULT hr = S_OK;
+    UINT er = ERROR_SUCCESS;
+
+    IMSAdminBase* piMetabase = NULL;
+    LPWSTR pwzData = NULL;
+    BOOL fInitializedCom = FALSE;
+
+    // initialize
+    hr = WcaInitialize(hInstall, "StartMetabaseTransaction");
+    ExitOnFailure(hr, "failed to initialize StartMetabaseTransaction");
+
+    hr = ::CoInitialize(NULL);
+    ExitOnFailure(hr, "failed to initialize COM");
+    fInitializedCom = TRUE;
+    hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase));
+    if (hr == REGDB_E_CLASSNOTREG)
+    {
+        WcaLog(LOGMSG_STANDARD, "Failed to get IIMSAdminBase to backup - continuing");
+        hr = S_OK;
+    }
+    else
+    {
+        MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IIMSAdminBase object");
+
+        hr = WcaGetProperty(L"CustomActionData", &pwzData);
+        ExitOnFailure(hr, "failed to get CustomActionData");
+
+        // back up the metabase
+        Assert(lstrlenW(pwzData) < MD_BACKUP_MAX_LEN);
+
+        // MD_BACKUP_OVERWRITE = Overwrite if a backup of the same name and version exists in the backup location
+        hr = piMetabase->Backup(pwzData, MD_BACKUP_NEXT_VERSION, MD_BACKUP_OVERWRITE | MD_BACKUP_FORCE_BACKUP | MD_BACKUP_SAVE_FIRST);
+        if (MD_WARNING_SAVE_FAILED == hr)
+        {
+            WcaLog(LOGMSG_STANDARD, "Failed to save metabase before backing up - continuing");
+            hr = S_OK;
+        }
+        MessageExitOnFailure(hr, msierrIISFailedStartTransaction, "failed to begin metabase transaction: '%ls'", pwzData);
+    }
+    hr = WcaProgressMessage(COST_IIS_TRANSACTIONS, FALSE);
+LExit:
+    ReleaseStr(pwzData);
+    ReleaseObject(piMetabase);
+
+    if (fInitializedCom)
+    {
+        ::CoUninitialize();
+    }
+
+    if (FAILED(hr))
+        er = ERROR_INSTALL_FAILURE;
+    return WcaFinalize(er);
+}
+
+
+/********************************************************************
+ RollbackMetabaseTransaction - CUSTOM ACTION ENTRY POINT for unbacking up metabase
+
+  Input:  deferred CustomActionData - BackupName
+********************************************************************/
+extern "C" UINT __stdcall RollbackMetabaseTransaction(MSIHANDLE hInstall)
+{
+//AssertSz(FALSE, "debug RollbackMetabaseTransaction here");
+    HRESULT hr = S_OK;
+    UINT er = ERROR_SUCCESS;
+
+    IMSAdminBase* piMetabase = NULL;
+    LPWSTR pwzData = NULL;
+    BOOL fInitializedCom = FALSE;
+
+    hr = WcaInitialize(hInstall, "RollbackMetabaseTransaction");
+    ExitOnFailure(hr, "failed to initialize");
+
+    hr = ::CoInitialize(NULL);
+    ExitOnFailure(hr, "failed to initialize COM");
+    fInitializedCom = TRUE;
+    hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase));
+    if (hr == REGDB_E_CLASSNOTREG)
+    {
+        WcaLog(LOGMSG_STANDARD, "Failed to get IIMSAdminBase to rollback - continuing");
+        hr = S_OK;
+        ExitFunction();
+    }
+    ExitOnFailure(hr, "failed to get IID_IIMSAdminBase object");
+
+
+    hr = WcaGetProperty( L"CustomActionData", &pwzData);
+    ExitOnFailure(hr, "failed to get CustomActionData");
+
+    hr = piMetabase->Restore(pwzData, MD_BACKUP_HIGHEST_VERSION, 0);
+    ExitOnFailure(hr, "failed to rollback metabase transaction: '%ls'", pwzData);
+
+    hr = piMetabase->DeleteBackup(pwzData, MD_BACKUP_HIGHEST_VERSION);
+    ExitOnFailure(hr, "failed to cleanup metabase transaction '%ls', continuing", pwzData);
+
+LExit:
+    ReleaseStr(pwzData);
+    ReleaseObject(piMetabase);
+
+    if (fInitializedCom)
+    {
+        ::CoUninitialize();
+    }
+
+    if (FAILED(hr))
+    {
+        er = ERROR_INSTALL_FAILURE;
+    }
+    return WcaFinalize(er);
+}
+
+
+/********************************************************************
+ CommitMetabaseTransaction - CUSTOM ACTION ENTRY POINT for unbacking up metabase
+
+  Input:  deferred CustomActionData - BackupName
+ * *****************************************************************/
+extern "C" UINT __stdcall CommitMetabaseTransaction(MSIHANDLE hInstall)
+{
+    HRESULT hr = S_OK;
+    UINT er = ERROR_SUCCESS;
+
+    IMSAdminBase* piMetabase = NULL;
+    LPWSTR pwzData = NULL;
+    BOOL fInitializedCom = FALSE;
+
+    hr = WcaInitialize(hInstall, "CommitMetabaseTransaction");
+    ExitOnFailure(hr, "failed to initialize");
+
+    hr = ::CoInitialize(NULL);
+    ExitOnFailure(hr, "failed to initialize COM");
+    fInitializedCom = TRUE;
+    hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase));
+    if (hr == REGDB_E_CLASSNOTREG)
+    {
+        WcaLog(LOGMSG_STANDARD, "Failed to get IIMSAdminBase to commit - continuing");
+        hr = S_OK;
+        ExitFunction();
+    }
+    ExitOnFailure(hr, "failed to get IID_IIMSAdminBase object");
+
+    hr = WcaGetProperty( L"CustomActionData", &pwzData);
+    ExitOnFailure(hr, "failed to get CustomActionData");
+
+    hr = piMetabase->DeleteBackup(pwzData, MD_BACKUP_HIGHEST_VERSION);
+    ExitOnFailure(hr, "failed to cleanup metabase transaction: '%ls'", pwzData);
+
+LExit:
+    ReleaseStr(pwzData);
+    ReleaseObject(piMetabase);
+
+    if (fInitializedCom)
+    {
+        ::CoUninitialize();
+    }
+
+    if (FAILED(hr))
+    {
+        er = ERROR_INSTALL_FAILURE;
+    }
+    return WcaFinalize(er);
+}
+
+
+/********************************************************************
+ CreateMetabaseKey - Installs metabase keys
+
+  Input:  deferred CustomActionData - Key
+ * *****************************************************************/
+static HRESULT CreateMetabaseKey(__in LPWSTR* ppwzCustomActionData, __in IMSAdminBase* piMetabase)
+{
+//AssertSz(FALSE, "debug CreateMetabaseKey here");
+    HRESULT hr = S_OK;
+    METADATA_HANDLE mhRoot = 0;
+    LPWSTR pwzData = NULL;
+    LPCWSTR pwzKey;
+
+    int i;
+
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+    ExitOnFailure(hr, "failed to read key from custom action data");
+
+    hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhRoot);
+    for (i = 30; i > 0 && HRESULT_FROM_WIN32(ERROR_PATH_BUSY) == hr; i--)
+    {
+        ::Sleep(1000);
+        WcaLog(LOGMSG_STANDARD, "failed to open root key, retrying %d time(s)...", i);
+        hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhRoot);
+    }
+    MessageExitOnFailure(hr, msierrIISFailedOpenKey, "failed to open metabase key: %ls", L"/LM");
+
+    pwzKey = pwzData + 3;
+
+    WcaLog(LOGMSG_VERBOSE, "Creating Metabase Key: %ls", pwzKey);
+
+    hr = piMetabase->AddKey(mhRoot, pwzKey);
+    if (HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hr)
+    {
+        WcaLog(LOGMSG_VERBOSE, "Key `%ls` already existed, continuing.", pwzData);
+        hr = S_OK;
+    }
+    MessageExitOnFailure(hr, msierrIISFailedCreateKey, "failed to create metabase key: %ls", pwzKey);
+
+    hr = WcaProgressMessage(COST_IIS_CREATEKEY, FALSE);
+
+LExit:
+    if (mhRoot)
+    {
+        piMetabase->CloseKey(mhRoot);
+    }
+
+    return hr;
+}
+
+
+/********************************************************************
+ WriteMetabaseValue -Installs metabase values
+
+  Input:  deferred CustomActionData - Key\tIdentifier\tAttributes\tUserType\tDataType\tData
+ * *****************************************************************/
+static HRESULT WriteMetabaseValue(__in LPWSTR* ppwzCustomActionData, __in IMSAdminBase* piMetabase)
+{
+    //AssertSz(FALSE, "debug WriteMetabaseValue here");
+    HRESULT hr = S_OK;
+
+    METADATA_HANDLE mhKey = 0;
+
+    LPWSTR pwzKey = NULL;
+    LPWSTR pwzTemp = NULL;
+    DWORD dwData = 0;
+    DWORD dwTemp = 0;
+    BOOL fFreeData = FALSE;
+    METADATA_RECORD mr;
+    ::ZeroMemory((LPVOID)&mr, sizeof(mr));
+    METADATA_RECORD mrGet;
+    ::ZeroMemory((LPVOID)&mrGet, sizeof(mrGet));
+
+    int i;
+
+    // get the key first
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzKey);
+    ExitOnFailure(hr, "failed to read key");
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&mr.dwMDIdentifier));
+    ExitOnFailure(hr, "failed to read identifier");
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&mr.dwMDAttributes));
+    ExitOnFailure(hr, "failed to read attributes");
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&mr.dwMDUserType));
+    ExitOnFailure(hr, "failed to read user type");
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&mr.dwMDDataType));
+    ExitOnFailure(hr, "failed to read data type");
+
+    switch (mr.dwMDDataType) // data
+    {
+    case DWORD_METADATA:
+        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&dwData));
+        mr.dwMDDataLen = sizeof(dwData);
+        mr.pbMDData = reinterpret_cast<BYTE*>(&dwData);
+        break;
+    case STRING_METADATA:
+        hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzTemp);
+        mr.dwMDDataLen = (lstrlenW(pwzTemp) + 1) * sizeof(WCHAR);
+        mr.pbMDData = reinterpret_cast<BYTE*>(pwzTemp);
+        break;
+    case MULTISZ_METADATA:
+        {
+        hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzTemp);
+        mr.dwMDDataLen = (lstrlenW(pwzTemp) + 1) * sizeof(WCHAR);
+        for (LPWSTR pwzT = pwzTemp; *pwzT; ++pwzT)
+        {
+            if (MAGIC_MULTISZ_CHAR == *pwzT)
+            {
+                *pwzT = L'\0';
+            }
+        }
+        mr.pbMDData = reinterpret_cast<BYTE*>(pwzTemp);
+        }
+        break;
+    case BINARY_METADATA:
+        hr = WcaReadStreamFromCaData(ppwzCustomActionData, &mr.pbMDData, reinterpret_cast<DWORD_PTR *>(&mr.dwMDDataLen));
+        fFreeData = TRUE;
+        break;
+    default:
+        hr = E_UNEXPECTED;
+        break;
+    }
+    ExitOnFailure(hr, "failed to parse CustomActionData into metabase record");
+
+    WcaLog(LOGMSG_VERBOSE, "Writing Metabase Value Under Key: %ls ID: %d", pwzKey, mr.dwMDIdentifier);
+
+    hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhKey);
+    for (i = 30; i > 0 && HRESULT_FROM_WIN32(ERROR_PATH_BUSY) == hr; i--)
+    {
+        ::Sleep(1000);
+        WcaLog(LOGMSG_STANDARD, "failed to open '%ls' key, retrying %d time(s)...", pwzKey, i);
+        hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhKey);
+    }
+    MessageExitOnFailure(hr, msierrIISFailedOpenKey, "failed to open metabase key: %ls", pwzKey);
+
+    if (lstrlenW(pwzKey) < 3)
+    {
+        ExitOnFailure(hr = E_INVALIDARG, "Key didn't begin with \"/LM\" as expected - key value: %ls", pwzKey);
+    }
+
+    hr = piMetabase->SetData(mhKey, pwzKey + 3, &mr); // pwzKey + 3 to skip "/LM" that was used to open the key.
+
+    // 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
+    if (MD_ERROR_CANNOT_REMOVE_SECURE_ATTRIBUTE == hr)
+    {
+        mr.dwMDAttributes |= METADATA_SECURE;
+        hr = piMetabase->SetData(mhKey, pwzKey + 3, &mr);
+    }
+
+    // If IIS6 returned failure, let's check if the correct value exists in the metabase before actually failing the CA
+    if (FAILED(hr))
+    {
+        // Backup the original failure error, so we can log it below if necessary
+        HRESULT hrOldValue = hr;
+
+        mrGet.dwMDIdentifier = mr.dwMDIdentifier;
+        mrGet.dwMDAttributes = METADATA_NO_ATTRIBUTES;
+        mrGet.dwMDUserType = mr.dwMDUserType;
+        mrGet.dwMDDataType = mr.dwMDDataType;
+        mrGet.dwMDDataLen = mr.dwMDDataLen;
+        mrGet.pbMDData = static_cast<BYTE*>(MemAlloc(mr.dwMDDataLen, TRUE));
+
+        hr = piMetabase->GetData(mhKey, pwzKey + 3, &mrGet, &dwTemp);
+        if (SUCCEEDED(hr))
+        {
+            if (mrGet.dwMDDataType == mr.dwMDDataType && mrGet.dwMDDataLen == mr.dwMDDataLen && 0 == memcmp(mrGet.pbMDData, mr.pbMDData, mr.dwMDDataLen))
+            {
+                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);
+                hr = S_OK;
+            }
+            else
+            {
+                WcaLog(LOGMSG_VERBOSE, "Succeeded in checking metabase value after write value, but the values didn't match");
+                hr = hrOldValue;
+            }
+        }
+        else
+        {
+            WcaLog(LOGMSG_VERBOSE, "Failed to check value after metabase write failure (error code 0x%x)", hr);
+            hr = hrOldValue;
+        }
+    }
+    MessageExitOnFailure(hr, msierrIISFailedWriteData, "failed to write data to metabase key: %ls", pwzKey);
+
+    hr = WcaProgressMessage(COST_IIS_WRITEVALUE, FALSE);
+
+LExit:
+    ReleaseStr(pwzTemp);
+    ReleaseStr(pwzKey);
+
+    if (mhKey)
+    {
+        piMetabase->CloseKey(mhKey);
+    }
+
+    if (fFreeData && mr.pbMDData)
+    {
+        MemFree(mr.pbMDData);
+    }
+
+    return hr;
+}
+
+
+/********************************************************************
+ DeleteMetabaseValue -Installs metabase values
+
+  Input:  deferred CustomActionData - Key\tIdentifier\tAttributes\tUserType\tDataType\tData
+ * *****************************************************************/
+static HRESULT DeleteMetabaseValue(__in LPWSTR* ppwzCustomActionData, __in IMSAdminBase* piMetabase)
+{
+    //AssertSz(FALSE, "debug DeleteMetabaseValue here");
+    HRESULT hr = S_OK;
+
+    METADATA_HANDLE mhKey = 0;
+
+    LPWSTR pwzKey = NULL;
+    DWORD dwIdentifier = 0;
+    DWORD dwDataType = 0;
+
+    int i;
+
+    // get the key first
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzKey);
+    ExitOnFailure(hr, "failed to read key");
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&dwIdentifier));
+    ExitOnFailure(hr, "failed to read identifier");
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&dwDataType));
+    ExitOnFailure(hr, "failed to read data type");
+
+    WcaLog(LOGMSG_VERBOSE, "Deleting Metabase Value Under Key: %ls ID: %d", pwzKey, dwIdentifier);
+
+    hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhKey);
+    for (i = 30; i > 0 && HRESULT_FROM_WIN32(ERROR_PATH_BUSY) == hr; i--)
+    {
+        ::Sleep(1000);
+        WcaLog(LOGMSG_STANDARD, "failed to open '%ls' key, retrying %d time(s)...", pwzKey, i);
+        hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhKey);
+    }
+    MessageExitOnFailure(hr, msierrIISFailedOpenKey, "failed to open metabase key: %ls", pwzKey);
+
+    if (lstrlenW(pwzKey) < 3)
+    {
+        ExitOnFailure(hr = E_INVALIDARG, "Key didn't begin with \"/LM\" as expected - key value: %ls", pwzKey);
+    }
+
+    hr = piMetabase->DeleteData(mhKey, pwzKey + 3, dwIdentifier, dwDataType); // pwzKey + 3 to skip "/LM" that was used to open the key.
+    if (MD_ERROR_DATA_NOT_FOUND == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
+    {
+        hr = S_OK;
+    }
+    MessageExitOnFailure(hr, msierrIISFailedDeleteValue, "failed to delete value %d from metabase key: %ls", dwIdentifier, pwzKey);
+
+    hr = WcaProgressMessage(COST_IIS_DELETEVALUE, FALSE);
+LExit:
+    ReleaseStr(pwzKey);
+
+    if (mhKey)
+        piMetabase->CloseKey(mhKey);
+
+    return hr;
+}
+
+
+/********************************************************************
+ DeleteAspApp - Deletes applications in IIS
+
+  Input:  deferred CustomActionData - MetabaseRoot\tRecursive
+ * *****************************************************************/
+static HRESULT DeleteAspApp(__in LPWSTR* ppwzCustomActionData, __in IMSAdminBase* piMetabase, __in ICatalogCollection* pApplicationCollection, __in IWamAdmin* piWam)
+{
+    const int BUFFER_BYTES = 512;
+    const BSTR bstrPropName = SysAllocString(L"Deleteable");
+
+    HRESULT hr = S_OK;
+    ICatalogObject* pApplication = NULL;
+
+    LPWSTR pwzRoot = NULL;
+    DWORD dwActualBufferSize = 0;
+    long lSize = 0;
+    long lIndex = 0;
+    long lChanges = 0;
+
+    VARIANT keyValue;
+    ::VariantInit(&keyValue);
+    VARIANT propValue;
+    propValue.vt = VT_BOOL;
+    propValue.boolVal = TRUE;
+
+    METADATA_RECORD mr;
+    // Get current set of web service extensions.
+    ::ZeroMemory(&mr, sizeof(mr));
+    mr.dwMDIdentifier = MD_APP_PACKAGE_ID;
+    mr.dwMDAttributes = 0;
+    mr.dwMDUserType  = ASP_MD_UT_APP;
+    mr.dwMDDataType = STRING_METADATA;
+    mr.pbMDData = new unsigned char[BUFFER_BYTES];
+    mr.dwMDDataLen = BUFFER_BYTES;
+
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzRoot); // MetabaseRoot
+    ExitOnFailure(hr, "failed to get metabase root");
+
+    hr = piMetabase->GetData(METADATA_MASTER_ROOT_HANDLE, pwzRoot, &mr, &dwActualBufferSize);
+    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)
+    {
+        // This one doesn't have an independent app GUID associated with it - it may have been already partially deleted, or a low isolation app
+        WcaLog(LOGMSG_VERBOSE, "No independent COM+ application found associated with %ls. It either doesn't exist, or was already removed - continuing", pwzRoot);
+        ExitFunction1(hr = S_OK);
+    }
+    MessageExitOnFailure(hr, msierrIISFailedDeleteApp, "failed to get GUID for application at path: %ls", pwzRoot);
+
+    WcaLog(LOGMSG_VERBOSE, "Deleting ASP App (used query: %ls) with GUID: %ls", pwzRoot, (LPWSTR)(mr.pbMDData));
+
+    // Delete the application association from IIS's point of view before it's obliterated from the application collection
+    hr = piWam->AppDelete(pwzRoot, FALSE);
+    if (FAILED(hr))
+    {
+        // This isn't necessarily an error if we fail here, but let's log a failure if it happens
+        WcaLog(LOGMSG_VERBOSE, "error 0x%x: failed to call IWamAdmin::AppDelete() while removing web application - continuing");
+        hr = S_OK;
+    }
+
+    if (!pApplicationCollection)
+    {
+        WcaLog(LOGMSG_STANDARD, "Could not remove application with GUID %ls because the application collection could not be found", (LPWSTR)(mr.pbMDData));
+        ExitFunction1(hr = S_OK);
+    }
+
+    hr = pApplicationCollection->Populate();
+    MessageExitOnFailure(hr, msierrIISFailedDeleteApp, "failed to populate Application collection");
+
+    hr = pApplicationCollection->get_Count(&lSize);
+    MessageExitOnFailure(hr, msierrIISFailedDeleteApp, "failed to get size of Application collection");
+    WcaLog(LOGMSG_TRACEONLY, "Found %u items in application collection", lSize);
+
+    // No need to check this too early, as we may not even need this to have successfully allocated
+    ExitOnNull(bstrPropName, hr, E_OUTOFMEMORY, "failed to allocate memory for \"Deleteable\" string");
+
+    for (lIndex = 0; lIndex < lSize; ++lIndex)
+    {
+        hr = pApplicationCollection->get_Item(lIndex, reinterpret_cast<IDispatch**>(&pApplication));
+        MessageExitOnFailure(hr, msierrIISFailedDeleteApp, "failed to get COM+ application while enumerating through COM+ applications");
+
+        hr = pApplication->get_Key(&keyValue);
+        MessageExitOnFailure(hr, msierrIISFailedDeleteApp, "failed to get key of COM+ application while enumerating through COM+ applications");
+
+        WcaLog(LOGMSG_TRACEONLY, "While enumerating through COM+ applications, found an application with GUID: %ls", (LPWSTR)keyValue.bstrVal);
+
+        if (VT_BSTR == keyValue.vt && 0 == lstrcmpW((LPWSTR)keyValue.bstrVal, (LPWSTR)(mr.pbMDData)))
+        {
+            hr = pApplication->put_Value(bstrPropName, propValue);
+            if (FAILED(hr))
+            {
+                // This isn't necessarily a critical error unless we fail to actually delete it in the next step
+                WcaLog(LOGMSG_VERBOSE, "error 0x%x: failed to ensure COM+ application with guid %ls is deletable - continuing", hr, (LPWSTR)(mr.pbMDData));
+            }
+
+            hr = pApplicationCollection->SaveChanges(&lChanges);
+            if (FAILED(hr))
+            {
+                // This isn't necessarily a critical error unless we fail to actually delete it in the next step
+                WcaLog(LOGMSG_VERBOSE, "error 0x%x: failed to save changes while ensuring COM+ application with guid %ls is deletable - continuing", hr, (LPWSTR)(mr.pbMDData));
+            }
+
+            hr = pApplicationCollection->Remove(lIndex);
+            if (FAILED(hr))
+            {
+                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));
+            }
+            else
+            {
+                hr = pApplicationCollection->SaveChanges(&lChanges);
+                if (FAILED(hr))
+                {
+                    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));
+                }
+                else
+                {
+                    WcaLog(LOGMSG_VERBOSE, "Found and removed application with GUID %ls", (LPWSTR)(mr.pbMDData));
+                }
+            }
+
+            // We've found the right key and successfully deleted the app - let's exit the loop now
+            lIndex = lSize;
+        }
+    }
+    // If we didn't find it, it isn't an error, because the application we want to delete doesn't seem to exist!
+
+    hr = WcaProgressMessage(COST_IIS_DELETEAPP, FALSE);
+LExit:
+    ReleaseBSTR(bstrPropName);
+
+    ReleaseStr(pwzRoot);
+    // Don't release pApplication, because it points to an object within the collection
+
+    delete [] mr.pbMDData;
+
+    return hr;
+}
+
+
+/********************************************************************
+ CreateAspApp - Creates applications in IIS
+
+  Input:  deferred CustomActionData - MetabaseRoot\tInProc
+ * ****************************************************************/
+static HRESULT CreateAspApp(__in LPWSTR* ppwzCustomActionData, __in IWamAdmin* piWam)
+{
+    HRESULT hr = S_OK;
+
+    LPWSTR pwzRoot = NULL;
+    BOOL fInProc;
+
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzRoot); // MetabaseRoot
+    ExitOnFailure(hr, "failed to get metabase root");
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, reinterpret_cast<int *>(&fInProc)); // InProc
+    ExitOnFailure(hr, "failed to get in proc flag");
+
+    WcaLog(LOGMSG_VERBOSE, "Creating ASP App: %ls", pwzRoot);
+
+    hr = piWam->AppCreate(pwzRoot, fInProc);
+    MessageExitOnFailure(hr, msierrIISFailedCreateApp, "failed to create web application: %ls", pwzRoot);
+
+    hr = WcaProgressMessage(COST_IIS_CREATEAPP, FALSE);
+LExit:
+    return hr;
+}
+
+
+/********************************************************************
+ DeleteMetabaseKey - Deletes metabase keys
+
+  Input:  deferred CustomActionData - Key
+ ******************************************************************/
+static HRESULT DeleteMetabaseKey(__in LPWSTR *ppwzCustomActionData, __in IMSAdminBase* piMetabase)
+{
+    HRESULT hr = S_OK;
+
+    METADATA_HANDLE mhRoot = 0;
+
+    LPWSTR pwzData = NULL;
+
+    LPCWSTR pwzKey;
+    int i;
+
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+    ExitOnFailure(hr, "failed to read key to be deleted");
+
+    hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhRoot);
+    for (i = 30; i > 0 && HRESULT_FROM_WIN32(ERROR_PATH_BUSY) == hr; i--)
+    {
+        ::Sleep(1000);
+        WcaLog(LOGMSG_STANDARD, "failed to open root key, retrying %d time(s)...", i);
+        hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_WRITE, 10, &mhRoot);
+    }
+    MessageExitOnFailure(hr, msierrIISFailedOpenKey, "failed to open metabase key: %ls", L"/LM");
+
+    pwzKey = pwzData + 3;
+
+    WcaLog(LOGMSG_VERBOSE, "Deleting Metabase Key: %ls", pwzKey);
+
+    hr = piMetabase->DeleteKey(mhRoot, pwzKey);
+    if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
+    {
+        WcaLog(LOGMSG_STANDARD, "Key `%ls` did not exist, continuing.", pwzData);
+        hr = S_OK;
+    }
+    MessageExitOnFailure(hr, msierrIISFailedDeleteKey, "failed to delete metabase key: %ls", pwzData);
+
+    hr = WcaProgressMessage(COST_IIS_DELETEKEY, FALSE);
+LExit:
+    if (mhRoot)
+    {
+        piMetabase->CloseKey(mhRoot);
+    }
+
+    return hr;
+}
+
+
+/********************************************************************
+ WriteMetabaseChanges - CUSTOM ACTION ENTRY POINT for IIS Metabase changes
+
+ *******************************************************************/
+extern "C" UINT __stdcall WriteMetabaseChanges(MSIHANDLE hInstall)
+{
+//AssertSz(FALSE, "debug WriteMetabaseChanges here");
+    HRESULT hr = S_OK;
+    UINT er = ERROR_SUCCESS;
+    IMSAdminBase* piMetabase = NULL;
+    IWamAdmin* piWam = NULL;
+    ICOMAdminCatalog* pCatalog = NULL;
+    ICatalogCollection* pApplicationCollection = NULL;
+    WCA_CASCRIPT_HANDLE hWriteMetabaseScript = NULL;
+    BSTR bstrApplications = SysAllocString(L"Applications");
+    BOOL fInitializedCom = FALSE;
+
+    LPWSTR pwzData = NULL;
+    LPWSTR pwz = NULL;
+    LPWSTR pwzScriptKey = NULL;
+    METABASE_ACTION maAction = MBA_UNKNOWNACTION;
+
+    hr = WcaInitialize(hInstall, "WriteMetabaseChanges");
+    ExitOnFailure(hr, "failed to initialize");
+
+    hr = ::CoInitialize(NULL);
+    ExitOnFailure(hr, "failed to initialize COM");
+    fInitializedCom = TRUE;
+
+    hr = WcaGetProperty( L"CustomActionData", &pwzData);
+    ExitOnFailure(hr, "failed to get CustomActionData");
+
+    WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData);
+
+    // Get the CaScript key
+    hr = WcaReadStringFromCaData(&pwzData, &pwzScriptKey);
+    ExitOnFailure(hr, "Failed to get CaScript key from custom action data");
+
+    hr = WcaCaScriptOpen(WCA_ACTION_INSTALL, WCA_CASCRIPT_SCHEDULED, FALSE, pwzScriptKey, &hWriteMetabaseScript);
+    ExitOnFailure(hr, "Failed to open CaScript file");
+
+    // The rest of our existing custom action data string should be empty - go ahead and overwrite it
+    ReleaseNullStr(pwzData);
+    hr = WcaCaScriptReadAsCustomActionData(hWriteMetabaseScript, &pwzData);
+    ExitOnFailure(hr, "Failed to read script into CustomAction data.");
+
+    pwz = pwzData;
+
+    while (S_OK == (hr = WcaReadIntegerFromCaData(&pwz, (int *)&maAction)))
+    {
+        switch (maAction)
+        {
+        case MBA_CREATEAPP:
+            if (NULL == piWam)
+            {
+                hr = ::CoCreateInstance(CLSID_WamAdmin, NULL, CLSCTX_ALL, IID_IWamAdmin, reinterpret_cast<void**>(&piWam));
+                MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IWamAdmin object");
+            }
+
+            hr = CreateAspApp(&pwz, piWam);
+            ExitOnFailure(hr, "failed to create ASP App");
+            break;
+        case MBA_DELETEAPP:
+            if (NULL == piMetabase)
+            {
+                hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase));
+                MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IIMSAdminBase object");
+            }
+
+            if (NULL == pCatalog)
+            {
+                hr = CoCreateInstance(CLSID_COMAdminCatalog, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pCatalog);
+                MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_ICOMAdmin object");
+
+                hr = pCatalog->GetCollection(bstrApplications, reinterpret_cast<IDispatch**>(&pApplicationCollection));
+                if (FAILED(hr))
+                {
+                    hr = S_OK;
+                    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);
+                }
+            }
+
+            if (NULL == piWam)
+            {
+                hr = ::CoCreateInstance(CLSID_WamAdmin, NULL, CLSCTX_ALL, IID_IWamAdmin, reinterpret_cast<void**>(&piWam));
+                MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IWamAdmin object");
+            }
+
+            hr = DeleteAspApp(&pwz, piMetabase, pApplicationCollection, piWam);
+            ExitOnFailure(hr, "failed to delete ASP App");
+            break;
+        case MBA_CREATEKEY:
+            if (NULL == piMetabase)
+            {
+                hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase));
+                MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IIMSAdminBase object");
+            }
+
+            hr = CreateMetabaseKey(&pwz, piMetabase);
+            ExitOnFailure(hr, "failed to create metabase key");
+            break;
+        case MBA_DELETEKEY:
+            if (NULL == piMetabase)
+            {
+                hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase));
+                MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IIMSAdminBase object");
+            }
+
+            hr = DeleteMetabaseKey(&pwz, piMetabase);
+            ExitOnFailure(hr, "failed to delete metabase key");
+            break;
+        case MBA_WRITEVALUE:
+            if (NULL == piMetabase)
+            {
+                hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase));
+                MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IIMSAdminBase object");
+            }
+
+            hr = WriteMetabaseValue(&pwz, piMetabase);
+            ExitOnFailure(hr, "failed to write metabase value");
+            break;
+        case MBA_DELETEVALUE:
+            if (NULL == piMetabase)
+            {
+                hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, reinterpret_cast<void**>(&piMetabase));
+                MessageExitOnFailure(hr, msierrIISCannotConnect, "failed to get IID_IIMSAdminBase object");
+            }
+
+            hr = DeleteMetabaseValue(&pwz, piMetabase);
+            ExitOnFailure(hr, "failed to delete metabase value");
+            break;
+        default:
+            ExitOnFailure(hr = E_UNEXPECTED, "Unexpected metabase action specified: %d", maAction);
+            break;
+        }
+    }
+    if (E_NOMOREITEMS == hr) // If there are no more items, all is well
+    {
+        if (NULL != piMetabase)
+        {
+            hr = piMetabase->SaveData();
+            for (int i = 30; i > 0 && HRESULT_FROM_WIN32(ERROR_PATH_BUSY) == hr; i--)
+            {
+                ::Sleep(1000);
+                WcaLog(LOGMSG_VERBOSE, "Failed to force save of metabase data, retrying %d time(s)...", i);
+                hr = piMetabase->SaveData();
+            }
+            if (FAILED(hr))
+            {
+                WcaLog(LOGMSG_VERBOSE, "Failed to force save of metabase data: 0x%x - continuing", hr);
+            }
+            hr = S_OK;
+        }
+        else
+        {
+            hr = S_OK;
+        }
+    }
+
+LExit:
+    WcaCaScriptClose(hWriteMetabaseScript, WCA_CASCRIPT_CLOSE_DELETE);
+
+    ReleaseBSTR(bstrApplications);
+    ReleaseStr(pwzScriptKey);
+    ReleaseStr(pwzData);
+    ReleaseObject(piMetabase);
+    ReleaseObject(piWam);
+    ReleaseObject(pCatalog);
+    ReleaseObject(pApplicationCollection);
+
+    if (fInitializedCom)
+    {
+        ::CoUninitialize();
+    }
+
+    if (FAILED(hr))
+    {
+        er = ERROR_INSTALL_FAILURE;
+    }
+    return WcaFinalize(er);
+}
+/********************************************************************
+ WriteIIS7ConfigChanges - CUSTOM ACTION ENTRY POINT for IIS7 config changes
+
+ *******************************************************************/
+extern "C" UINT __stdcall WriteIIS7ConfigChanges(MSIHANDLE hInstall)
+{
+    //AssertSz(FALSE, "debug WriteIIS7ConfigChanges here");
+    HRESULT hr = S_OK;
+    UINT er = ERROR_SUCCESS;
+    LPWSTR pwzData = NULL;
+    LPWSTR pwzScriptKey = NULL;
+    LPWSTR pwzHashString = NULL;
+    BYTE rgbActualHash[SHA1_HASH_LEN] = { };
+    DWORD dwHashedBytes = SHA1_HASH_LEN;
+
+    WCA_CASCRIPT_HANDLE hWriteIis7Script = NULL;
+
+    hr = WcaInitialize(hInstall, "WriteIIS7ConfigChanges");
+    ExitOnFailure(hr, "Failed to initialize");
+
+    hr = WcaGetProperty( L"CustomActionData", &pwzScriptKey);
+    ExitOnFailure(hr, "Failed to get CustomActionData");
+    WcaLog(LOGMSG_TRACEONLY, "Script WriteIIS7ConfigChanges: %ls", pwzScriptKey);
+
+    hr = WcaCaScriptOpen(WCA_ACTION_INSTALL, WCA_CASCRIPT_SCHEDULED, FALSE, pwzScriptKey, &hWriteIis7Script);
+    ExitOnFailure(hr, "Failed to open CaScript file");
+
+    hr = WcaCaScriptReadAsCustomActionData(hWriteIis7Script, &pwzData);
+    ExitOnFailure(hr, "Failed to read script into CustomAction data.");
+
+    hr = CrypHashBuffer((BYTE*)pwzData, sizeof(pwzData) * sizeof(WCHAR), PROV_RSA_AES, CALG_SHA1, rgbActualHash, dwHashedBytes);
+    ExitOnFailure(hr, "Failed to calculate hash of CustomAction data.");
+
+    hr = StrAlloc(&pwzHashString, ((dwHashedBytes * 2) + 1));
+    ExitOnFailure(hr, "Failed to allocate string for script hash");
+
+    hr = StrHexEncode(rgbActualHash, dwHashedBytes, pwzHashString, ((dwHashedBytes * 2) + 1));
+    ExitOnFailure(hr, "Failed to convert hash bytes to string.");
+
+    WcaLog(LOGMSG_TRACEONLY, "CustomActionData WriteIIS7ConfigChanges: %ls", pwzData);
+    WcaLog(LOGMSG_VERBOSE,  "Custom action data hash: %ls", pwzHashString);
+    WcaLog(LOGMSG_VERBOSE, "CustomActionData WriteIIS7ConfigChanges length: %d", wcslen(pwzData));
+
+    hr = IIS7ConfigChanges(hInstall, pwzData);
+    ExitOnFailure(hr, "WriteIIS7ConfigChanges Failed.");
+
+LExit:
+    WcaCaScriptClose(hWriteIis7Script, WCA_CASCRIPT_CLOSE_DELETE);
+    ReleaseStr(pwzScriptKey);
+    ReleaseStr(pwzData);
+    ReleaseStr(pwzHashString);
+
+    if (FAILED(hr))
+    {
+        er = ERROR_INSTALL_FAILURE;
+    }
+
+    return WcaFinalize(er);
+}
+
+
+/********************************************************************
+ CommitIIS7ConfigTransaction - CUSTOM ACTION ENTRY POINT for unbacking up config
+
+  Input:  deferred CustomActionData - BackupName
+ * *****************************************************************/
+extern "C" UINT __stdcall CommitIIS7ConfigTransaction(MSIHANDLE hInstall)
+{
+    HRESULT hr = S_OK;
+    UINT er = ERROR_SUCCESS;
+    LPWSTR pwzData = NULL;
+    WCHAR wzConfigCopy[MAX_PATH];
+    DWORD dwSize = 0;
+
+    BOOL fIsWow64Process = FALSE;
+    BOOL fIsFSRedirectDisabled = FALSE;
+
+    hr = WcaInitialize(hInstall, "CommitIIS7ConfigTransaction");
+    ExitOnFailure(hr, "failed to initialize IIS7 commit transaction");
+
+    WcaInitializeWow64();
+    fIsWow64Process = WcaIsWow64Process();
+    if (fIsWow64Process)
+    {
+        hr = WcaDisableWow64FSRedirection();
+        if(FAILED(hr))
+        {
+            //eat this error
+            hr = S_OK;
+        }
+        else
+        {
+            fIsFSRedirectDisabled = TRUE;
+        }
+    }
+
+    hr = WcaGetProperty( L"CustomActionData", &pwzData);
+    ExitOnFailure(hr, "failed to get CustomActionData");
+
+    // Config AdminMgr changes already committed, just
+    // delete backup config file.
+
+    dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\applicationHost.config",
+                                      wzConfigCopy,
+                                      MAX_PATH
+                                      );
+    if ( dwSize == 0 )
+    {
+        ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings");
+    }
+
+    hr = ::StringCchCatW(wzConfigCopy, MAX_PATH, L".");
+    ExitOnFailure(hr, "Commit IIS7 failed StringCchCatW of .");
+
+    hr = ::StringCchCatW(wzConfigCopy, MAX_PATH, pwzData);
+    ExitOnFailure(hr, "Commit IIS7 failed StringCchCatW of extension");
+
+    if (!::DeleteFileW(wzConfigCopy))
+    {
+        hr = HRESULT_FROM_WIN32(GetLastError());
+        if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr ||
+            HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
+        {
+            WcaLog(LOGMSG_STANDARD, "Failed to delete backup applicationHost, not found - continuing");
+            hr = S_OK;
+        }
+        else
+        {
+            ExitOnFailure(hr, "failed to delete config backup");
+        }
+    }
+
+LExit:
+    ReleaseStr(pwzData);
+
+    // Make sure we revert FS Redirection if necessary before exiting
+    if (fIsFSRedirectDisabled)
+    {
+        fIsFSRedirectDisabled = FALSE;
+        WcaRevertWow64FSRedirection();
+    }
+    WcaFinalizeWow64();
+
+
+    if (FAILED(hr))
+    {
+        er = ERROR_INSTALL_FAILURE;
+    }
+    return WcaFinalize(er);
+}
+/********************************************************************
+ StartIIS7Config Transaction - CUSTOM ACTION ENTRY POINT for backing up config
+
+  Input:  deferred CustomActionData - BackupName
+********************************************************************/
+extern "C" UINT __stdcall StartIIS7ConfigTransaction(MSIHANDLE hInstall)
+{
+    HRESULT hr = S_OK;
+    UINT er = ERROR_SUCCESS;
+    LPWSTR pwzData = NULL;
+    WCHAR wzConfigSource[MAX_PATH];
+    WCHAR wzConfigCopy[MAX_PATH];
+    DWORD dwSize = 0;
+
+
+    BOOL fIsWow64Process = FALSE;
+    BOOL fIsFSRedirectDisabled = FALSE;
+
+    // initialize
+    hr = WcaInitialize(hInstall, "StartIIS7ConfigTransaction");
+    ExitOnFailure(hr, "failed to initialize StartIIS7ConfigTransaction");
+
+    WcaInitializeWow64();
+    fIsWow64Process = WcaIsWow64Process();
+    if (fIsWow64Process)
+    {
+        hr = WcaDisableWow64FSRedirection();
+        if(FAILED(hr))
+        {
+            //eat this error
+            hr = S_OK;
+        }
+        else
+        {
+            fIsFSRedirectDisabled = TRUE;
+        }
+    }
+
+    hr = WcaGetProperty(L"CustomActionData", &pwzData);
+    ExitOnFailure(hr, "failed to get CustomActionData");
+
+
+    dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\applicationHost.config",
+                                      wzConfigSource,
+                                      MAX_PATH
+                                      );
+    if ( dwSize == 0 )
+    {
+        ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings");
+    }
+    hr = ::StringCchCopyW(wzConfigCopy, MAX_PATH, wzConfigSource);
+    ExitOnFailure(hr, "Commit IIS7 failed StringCchCopyW");
+
+    //add ca action as extension
+
+    hr = ::StringCchCatW(wzConfigCopy, MAX_PATH, L".");
+    ExitOnFailure(hr, "Commit IIS7 failed StringCchCatW of .");
+
+    hr = ::StringCchCatW(wzConfigCopy, MAX_PATH, pwzData);
+    ExitOnFailure(hr, "Commit IIS7 failed StringCchCatW of extension");
+
+    if ( !::CopyFileW(wzConfigSource, wzConfigCopy, FALSE) )
+    {
+        hr = HRESULT_FROM_WIN32(GetLastError());
+        if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr ||
+            HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
+        {
+            // IIS may not be installed on the machine, we'll fail later if we try to install anything
+            WcaLog(LOGMSG_STANDARD, "Failed to back up applicationHost, not found - continuing");
+            hr = S_OK;
+        }
+        else
+        {
+            ExitOnFailure(hr, "Failed to copy config backup %ls -> %ls", wzConfigSource, wzConfigCopy);
+        }
+    }
+
+
+    hr = WcaProgressMessage(COST_IIS_TRANSACTIONS, FALSE);
+
+
+LExit:
+
+    ReleaseStr(pwzData);
+
+    // Make sure we revert FS Redirection if necessary before exiting
+    if (fIsFSRedirectDisabled)
+    {
+        fIsFSRedirectDisabled = FALSE;
+        WcaRevertWow64FSRedirection();
+    }
+    WcaFinalizeWow64();
+
+    if (FAILED(hr))
+        er = ERROR_INSTALL_FAILURE;
+    return WcaFinalize(er);
+}
+
+
+/********************************************************************
+ RollbackIIS7ConfigTransaction - CUSTOM ACTION ENTRY POINT for unbacking up config
+
+  Input:  deferred CustomActionData - BackupName
+********************************************************************/
+extern "C" UINT __stdcall RollbackIIS7ConfigTransaction(MSIHANDLE hInstall)
+{
+    HRESULT hr = S_OK;
+    UINT er = ERROR_SUCCESS;
+    LPWSTR pwzData = NULL;
+    WCHAR wzConfigSource[MAX_PATH];
+    WCHAR wzConfigCopy[MAX_PATH];
+    DWORD dwSize = 0;
+
+    BOOL fIsWow64Process = FALSE;
+    BOOL fIsFSRedirectDisabled = FALSE;
+
+    hr = WcaInitialize(hInstall, "RollbackIIS7ConfigTransaction");
+    ExitOnFailure(hr, "failed to initialize");
+
+    WcaInitializeWow64();
+    fIsWow64Process = WcaIsWow64Process();
+    if (fIsWow64Process)
+    {
+        hr = WcaDisableWow64FSRedirection();
+        if(FAILED(hr))
+        {
+            //eat this error
+            hr = S_OK;
+        }
+        else
+        {
+            fIsFSRedirectDisabled = TRUE;
+        }
+    }
+
+    hr = WcaGetProperty( L"CustomActionData", &pwzData);
+    ExitOnFailure(hr, "failed to get CustomActionData");
+
+    dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\applicationHost.config",
+                                      wzConfigSource,
+                                      MAX_PATH
+                                      );
+    if ( dwSize == 0 )
+    {
+        ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings");
+    }
+    hr = ::StringCchCopyW(wzConfigCopy, MAX_PATH, wzConfigSource);
+    ExitOnFailure(hr, "Commit IIS7 failed StringCchCopyW");
+
+    //add ca action as extension
+
+    hr = ::StringCchCatW(wzConfigCopy, MAX_PATH, L".");
+    ExitOnFailure(hr, "Commit IIS7 failed StringCchCatW of .");
+
+    hr = ::StringCchCatW(wzConfigCopy, MAX_PATH, pwzData);
+    ExitOnFailure(hr, "Commit IIS7 failed StringCchCatW of extension");
+
+    //copy is reverse of start transaction
+    if (!::CopyFileW(wzConfigCopy, wzConfigSource, FALSE))
+    {
+        hr = HRESULT_FROM_WIN32(GetLastError());
+        if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr ||
+            HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
+        {
+            WcaLog(LOGMSG_STANDARD, "Failed to restore applicationHost, not found - continuing");
+            hr = S_OK;
+        }
+        else
+        {
+            ExitOnFailure(hr, "failed to restore config backup");
+        }
+    }
+
+    if (!::DeleteFileW(wzConfigCopy))
+    {
+        ExitWithLastError(hr, "failed to delete config backup");
+    }
+
+    hr = WcaProgressMessage(COST_IIS_TRANSACTIONS, FALSE);
+
+LExit:
+    ReleaseStr(pwzData);
+
+    // Make sure we revert FS Redirection if necessary before exiting
+    if (fIsFSRedirectDisabled)
+    {
+        fIsFSRedirectDisabled = FALSE;
+        WcaRevertWow64FSRedirection();
+    }
+    WcaFinalizeWow64();
+
+    if (FAILED(hr))
+    {
+        er = ERROR_INSTALL_FAILURE;
+    }
+    return WcaFinalize(er);
+}
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 @@
+#pragma once
+// 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.
+
+
+#include "precomp.h"
+
+//local CAData action functions
+HRESULT IIS7Site(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    );
+
+HRESULT IIS7Application(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    );
+HRESULT IIS7VDir(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    );
+HRESULT IIS7Binding(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    );
+HRESULT IIS7AppPool(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    );
+HRESULT IIS7AppExtension(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    );
+HRESULT IIS7MimeMap(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    );
+HRESULT IIS7DirProperties(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    );
+HRESULT IIS7WebLog(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    );
+HRESULT IIS7FilterGlobal(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    );
+HRESULT IIS7FilterSite(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    );
+HRESULT IIS7HttpHeader(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    );
+HRESULT IIS7WebError(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    );
+HRESULT IIS7WebSvcExt(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    );
+HRESULT IIS7WebProperty(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    );
+HRESULT IIS7WebDir(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    );
+HRESULT IIS7AspProperty(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    );
+HRESULT IIS7SslBinding(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    );
+//local helper functions
+
+static HRESULT GetNextAvailableSiteId(
+    IAppHostWritableAdminManager *pAdminMgr,
+    DWORD *plSiteId
+    );
+static HRESULT GetSiteElement(
+    IAppHostWritableAdminManager *pAdminMgr,
+    LPCWSTR swSiteName,
+    IAppHostElement **pSiteElement,
+    BOOL* fFound
+    );
+static HRESULT GetApplicationElement(
+    IAppHostElement *pSiteElement,
+    LPCWSTR swAppPath,
+    IAppHostElement **pAppElement,
+    BOOL* fFound
+    );
+static HRESULT GetApplicationElementForVDir(
+    IAppHostElement *pSiteElement,
+    LPCWSTR swVDirPath,
+    IAppHostElement **ppAppElement,
+    LPCWSTR *ppwzVDirSubPath,
+    BOOL* fFound
+    );
+
+static HRESULT CreateApplication(
+    IAppHostElement *pSiteElement,
+    LPCWSTR swAppPath,
+    IAppHostElement **pAppElement
+    );
+static HRESULT DeleteApplication(
+    IAppHostElement *pSiteElement,
+    LPCWSTR swAppPath
+    );
+
+static HRESULT SetAppPool(
+    IAppHostElement *pAppElementpAppElement,
+    LPCWSTR pwzAppPool
+    );
+static HRESULT CreateVdir(
+    IAppHostElement *pAppElement,
+    LPCWSTR pwzVDirPath,
+    LPCWSTR pwzVDirPhyDir
+    );
+static HRESULT DeleteVdir(
+    IAppHostElement *pAppElement,
+    LPCWSTR pwzVDirPath
+    );
+
+static HRESULT CreateBinding(
+    IAppHostElement *pSiteElem,
+    LPCWSTR pwzProtocol,
+    LPCWSTR pwzInfo
+    );
+static HRESULT DeleteBinding(
+    IAppHostElement *pSiteElem,
+    LPCWSTR pwzProtocol,
+    LPCWSTR pwzInfo
+    );
+
+static HRESULT CreateSslBinding(
+    IAppHostElement *pSiteElem,
+    LPCWSTR pwzStoreName,
+    LPCWSTR pwzEncodedCertificateHash
+    );
+static HRESULT DeleteSslBinding(
+    IAppHostElement *pSiteElem,
+    LPCWSTR pwzStoreName,
+    LPCWSTR pwzEncodedCertificateHash
+    );
+
+static HRESULT CreateSite(
+    IAppHostElementCollection *pAdminMgr,
+    LPCWSTR swSiteName,
+    IAppHostElement **pSiteElement
+    );
+
+static HRESULT DeleteAppPool(
+    IAppHostWritableAdminManager *pAdminMgr,
+    LPCWSTR swAppPoolName
+    );
+static HRESULT CreateAppPool(
+    __inout LPWSTR *ppwzCustomActionData,
+    IAppHostWritableAdminManager *pAdminMgr,
+    LPCWSTR swAppPoolName
+    );
+
+static HRESULT SetDirPropAuthentications(
+    IAppHostWritableAdminManager *pAdminMgr,
+    LPCWSTR wcConfigPath,
+    DWORD dwData
+    );
+static HRESULT SetDirPropAuthProvider(
+    IAppHostWritableAdminManager *pAdminMgr,
+    LPCWSTR wszConfigPath,
+    __in LPWSTR wszData
+    );
+static HRESULT SetDirPropDefDoc(
+    IAppHostWritableAdminManager *pAdminMgr,
+    LPCWSTR wszConfigPath,
+    __in LPWSTR wszData
+    );
+
+static HRESULT ClearLocationTag(
+    IAppHostWritableAdminManager *pAdminMgr,
+    LPCWSTR swLocationPath
+    );
+
+static HRESULT CreateWebLog(
+    IAppHostElement *pSiteElem,
+    LPCWSTR pwzFormat
+    );
+
+static HRESULT CreateGlobalFilter(
+    __inout LPWSTR *ppwzCustomActionData,
+    IAppHostElement *pSection
+    );
+static HRESULT DeleteGlobalFilter(
+    __inout LPWSTR *ppwzCustomActionData,
+    IAppHostElement *pSection
+    );
+
+static HRESULT CreateSiteFilter(
+    __inout LPWSTR *ppwzCustomActionData,
+    IAppHostWritableAdminManager *pAdminMgr
+    );
+static HRESULT DeleteSiteFilter(
+    __inout LPWSTR *ppwzCustomActionData,
+    IAppHostWritableAdminManager *pAdminMgr
+    );
+
+static HRESULT DeleteCollectionElement(
+    __in IAppHostElementCollection *pCollection,
+    __in LPCWSTR pwzElementName,
+    __in LPCWSTR pwzAttributeName,
+    __in LPCWSTR pwzAttributeValue
+    );
+
+struct SCA_WEB_ERROR_SERVER
+{
+    int iErrorCode;
+    int iSubCode;
+    WCHAR wzFile[MAX_PATH];
+    WCHAR wzLangPath[MAX_PATH];
+    int iResponseMode;
+    SCA_WEB_ERROR_SERVER *psweNext;
+};
+static HRESULT AddWebErrorToList(
+    SCA_WEB_ERROR_SERVER** ppsweList
+    );
+static void ScaWebErrorFreeList7(
+    SCA_WEB_ERROR_SERVER *psweList
+    );
+static HRESULT PopulateHttpErrors(
+    IAppHostElement *pSection,
+    SCA_WEB_ERROR_SERVER **psweList
+    );
+static HRESULT GetErrorFromList(
+    const SCA_WEB_ERROR_SERVER & we,
+    SCA_WEB_ERROR_SERVER **ppsweList,
+    SCA_WEB_ERROR_SERVER **pswe,
+    BOOL *fFound
+    );
+
+static void ConvSecToHMS(
+    int Sec,
+    __out_ecount(cchDest) LPWSTR wcTime,
+    size_t cchDest
+    );
+static void ConvSecToDHMS(
+    unsigned int Sec,
+    __out_ecount(cchDest) LPWSTR wcTime,
+    size_t cchDest
+    );
+
+////////////////////////////////////////////////////////////////////
+// ScopeBSTR: Local helper class to construct & free BSTR from LPWSTR
+//
+/////////////////////////////////////////////////////////////////////
+class ScopeBSTR
+{
+public:
+    BSTR m_str;
+
+    ScopeBSTR()
+    {
+        m_str = NULL;
+    }
+
+    ScopeBSTR( __in LPCWSTR pSrc)
+    {
+        if (pSrc == NULL)
+        {
+            m_str = NULL;
+        }
+        else
+        {
+            m_str = ::SysAllocString(pSrc);
+
+        }
+    }
+
+    ~ScopeBSTR()
+    {
+        ::SysFreeString(m_str);
+    }
+
+    operator BSTR()
+    {
+        return m_str;
+    }
+};
+
+
+/********************************************************************
+ IIS7ConfigChanges - Start of IIS7 config changes
+
+ *******************************************************************/
+HRESULT IIS7ConfigChanges(MSIHANDLE /*hInstall*/, __inout LPWSTR pwzData)
+{
+    HRESULT hr = S_OK;
+    BOOL fInitializedCom = FALSE;
+
+    IAppHostWritableAdminManager *pAdminMgr = NULL;
+
+    LPWSTR pwz = NULL;
+    LPWSTR pwzLast = NULL;
+    LPWSTR pwzBackup = NULL;
+    DWORD cchData = lstrlenW(pwzData);
+    int iAction = -1;
+
+    int iRetryCount = 0;
+
+    hr = ::CoInitialize(NULL);
+    ExitOnFailure(hr, "Failed to initialize COM");
+    fInitializedCom = TRUE;
+
+    pwz = pwzLast = pwzData;
+
+    hr = StrAllocString(&pwzBackup, pwz, 0);
+    ExitOnFailure(hr, "Failed to backup custom action data");
+
+    while (S_OK == (hr = WcaReadIntegerFromCaData(&pwz, &iAction)))
+    {
+        if (NULL == pAdminMgr)
+        {
+            hr = ::CoCreateInstance( __uuidof(AppHostWritableAdminManager),
+                                    NULL,
+                                    CLSCTX_INPROC_SERVER,
+                                    __uuidof(IAppHostWritableAdminManager),
+                                    reinterpret_cast<void**> (&pAdminMgr));
+            ExitOnFailure(hr , "Failed to open AppHostWritableAdminManager to configure IIS7");
+        }
+
+        switch (iAction)
+        {
+        case IIS_SITE:
+            {
+#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
+                hr = IIS7Site(&pwz, pAdminMgr);
+                ExitOnFailure(hr, "Failed to configure IIS site.");
+                break;
+            }
+        case IIS_APPLICATION:
+            {
+#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
+                hr = IIS7Application(&pwz, pAdminMgr);
+                ExitOnFailure(hr, "Failed to configure IIS application.");
+                break;
+            }
+        case IIS_VDIR:
+            {
+#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
+                hr = IIS7VDir(&pwz, pAdminMgr);
+                ExitOnFailure(hr, "Failed to configure IIS VDir.");
+                break;
+            }
+        case IIS_BINDING:
+            {
+#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
+                hr = IIS7Binding(&pwz, pAdminMgr);
+                ExitOnFailure(hr, "Failed to configure IIS site binding.");
+                break;
+            }
+        case IIS_APPPOOL:
+            {
+#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
+                hr = IIS7AppPool(&pwz, pAdminMgr);
+                ExitOnFailure(hr, "Failed to configure IIS appPool.");
+                break;
+            }
+        case IIS_APPEXT_BEGIN:
+            {
+#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
+                hr = IIS7AppExtension(&pwz, pAdminMgr);
+                ExitOnFailure(hr, "Failed to configure IIS AppExtension.");
+                break;
+            }
+        case IIS_MIMEMAP_BEGIN:
+            {
+#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
+                hr = IIS7MimeMap(&pwz, pAdminMgr);
+                ExitOnFailure(hr, "Failed to configure IIS MimeMap.");
+                break;
+            }
+        case IIS_DIRPROP_BEGIN:
+            {
+#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
+                hr = IIS7DirProperties(&pwz, pAdminMgr);
+                ExitOnFailure(hr, "Failed to configure IIS DirProperties.");
+                break;
+            }
+        case IIS_WEBLOG:
+            {
+#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
+                hr = IIS7WebLog(&pwz, pAdminMgr);
+                ExitOnFailure(hr, "Failed to configure IIS WebLog.");
+                break;
+            }
+        case IIS_FILTER_GLOBAL_BEGIN:
+            {
+#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
+                hr = IIS7FilterGlobal(&pwz, pAdminMgr);
+                ExitOnFailure(hr, "Failed to configure IIS filter global.");
+                break;
+            }
+        case IIS_FILTER_BEGIN:
+            {
+#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
+                hr = IIS7FilterSite(&pwz, pAdminMgr);
+                ExitOnFailure(hr, "Failed to configure IIS Filter.");
+                break;
+            }
+        case IIS_HTTP_HEADER_BEGIN:
+            {
+#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
+                hr = IIS7HttpHeader(&pwz, pAdminMgr);
+                ExitOnFailure(hr, "Failed to configure IIS http Header.");
+                break;
+            }
+        case IIS_WEBERROR_BEGIN:
+            {
+#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
+                hr = IIS7WebError(&pwz, pAdminMgr);
+                ExitOnFailure(hr, "Failed to configure IIS http Errors.");
+                break;
+            }
+        case IIS_WEB_SVC_EXT:
+            {
+#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
+                hr = IIS7WebSvcExt(&pwz, pAdminMgr);
+                ExitOnFailure(hr, "Failed to configure IIS web svc ext.");
+                break;
+            }
+        case IIS_PROPERTY:
+            {
+#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
+                hr = IIS7WebProperty(&pwz, pAdminMgr);
+                ExitOnFailure(hr, "Failed to configure IIS web property.");
+                break;
+            }
+        case IIS_WEBDIR:
+            {
+#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
+                hr = IIS7WebDir(&pwz, pAdminMgr);
+                ExitOnFailure(hr, "Failed to configure IIS web directory.");
+                break;
+            }
+        case IIS_ASP_BEGIN:
+            {
+#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
+                hr = IIS7AspProperty(&pwz, pAdminMgr);
+                ExitOnFailure(hr, "Failed to configure IIS Asp property.");
+                break;
+            }
+        case IIS_SSL_BINDING:
+#pragma prefast(suppress:26010, "This is a prefast issue - pAdminMgr is correctly allocated")
+                hr = IIS7SslBinding(&pwz, pAdminMgr);
+                ExitOnFailure(hr, "Failed to configure IIS SSL binding.");
+                break;
+
+        default:
+            ExitOnFailure(hr = E_UNEXPECTED, "IIS7ConfigChanges: Unexpected IIS Config action specified: %d", iAction);
+            break;
+        }
+        if (S_OK == hr)
+        {
+            // commit config changes now to close out IIS Admin changes,
+            // the Rollback or Commit defered CAs will determine final commit status.
+            hr = pAdminMgr->CommitChanges();
+
+            // Our transaction may have been interrupted.
+            if (hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) || hr == HRESULT_FROM_WIN32(ERROR_TRANSACTIONAL_CONFLICT))
+            {
+                WcaLog(LOGMSG_VERBOSE, "Sharing violation or transactional conflict during attempt to save changes to applicationHost.config");
+                if (++iRetryCount > 30)
+                {
+                    if (IDRETRY == WcaErrorMessage(msierrIISFailedCommitInUse, hr, INSTALLMESSAGE_ERROR | MB_RETRYCANCEL, 0))
+                    {
+                        iRetryCount = 0;
+                    }
+                    else
+                    {
+                        ExitOnFailure(hr, "Failed to Commit IIS Config Changes, in silent mode or user has chosen to cancel");
+                    }
+                }
+
+                // Throw away the changes since IIS has no way to remove uncommited changes from an AdminManager.
+                ReleaseNullObject(pAdminMgr);
+
+                // Restore our CA data backup
+                pwz = pwzLast;
+                hr = ::StringCchCopyW(pwz, cchData - (pwz - pwzData) + 1, pwzBackup);
+                ExitOnFailure(hr , "Failed to restore custom action data backup");
+
+            }
+            else if (FAILED(hr))
+            {
+                ExitOnFailure(hr , "Failed to Commit IIS Config Changes");
+            }
+            else
+            {
+                // store a backup of CA data @ the last place that we successfully commited changes unless we are done.
+                if(NULL != pwz)
+                {
+                    pwzLast = pwz;
+                    hr = StrAllocString(&pwzBackup, pwz, 0);
+                    ExitOnFailure(hr, "Failed to backup custom action data");
+                }
+            }
+        }
+    }
+    if (E_NOMOREITEMS == hr) // If there are no more items, all is well
+    {
+        hr = S_OK;
+    }
+LExit:
+    ReleaseObject(pAdminMgr);
+    ReleaseStr(pwzBackup);
+
+    if (fInitializedCom)
+    {
+        ::CoUninitialize();
+    }
+
+    return hr;
+}
+//-------------------------------------------------------------------------------------------------
+// IIS7AspProperty
+// Called by WriteIIS7ConfigChanges
+// Processes asp properties for WebApplication
+//
+//-------------------------------------------------------------------------------------------------
+
+HRESULT IIS7AspProperty(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    )
+{
+    HRESULT hr = S_OK;
+
+    int iAction = -1;
+    int iData   =  0;
+
+    LPWSTR pwzData = NULL;
+    LPWSTR pwzSiteName = NULL;
+    LPWSTR pwzPathName = NULL;
+    LPWSTR pwzLocationPath = NULL;
+    WCHAR wcTime[60];
+
+    IAppHostElement *pSection = NULL;
+    IAppHostElement *pElement = NULL;
+
+    //read web site key
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
+    ExitOnFailure(hr, "Failed read webDir webkey");
+
+    //read path key
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzPathName);
+    ExitOnFailure(hr, "Failed read webDir path");
+
+    //Construct Location path
+    hr = StrAllocFormatted(&pwzLocationPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzSiteName);
+    ExitOnFailure(hr, "failed to format webDir location");
+    //
+    //Do not append trailing '/' for default vDir
+    //
+    if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzPathName, -1, L"/", -1))
+    {
+        hr = StrAllocConcat(&pwzLocationPath, L"/", 0);
+        ExitOnFailure(hr, "failed to copy location WebDir '/'");
+        hr = StrAllocConcat(&pwzLocationPath, pwzPathName, 0);
+        ExitOnFailure(hr, "failed to copy location WebDir path");
+    }
+
+    //get asp section at config path location tag
+    hr = pAdminMgr->GetAdminSection( ScopeBSTR(IIS_CONFIG_ASP_SECTION), pwzLocationPath, &pSection);
+    ExitOnFailure(hr, "Failed get httpErrors section");
+
+    // Get  action
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+    ExitOnFailure(hr, "Failed to read property action");
+
+    while (IIS_ASP_END != iAction)
+    {
+        switch (iAction)
+        {
+            case IIS_ASP_SESSIONSTATE:
+            {
+                //system.webServer/asp /session | allowSessionState
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read asp session state");
+                hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_SESSION), &pElement);
+                ExitOnFailure(hr, "Failed to get asp session element");
+                hr = Iis7PutPropertyBool( pElement, IIS_CONFIG_ALLOWSTATE, iData);
+                ExitOnFailure(hr, "Failed to put asp session value");
+                ReleaseNullObject(pElement);
+                break;
+            }
+            case IIS_ASP_SESSIONTIMEOUT:
+            {
+                //system.webServer/asp /session | timeout
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read asp session timeout");
+                hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_SESSION), &pElement);
+                ExitOnFailure(hr, "Failed to get asp session timeout");
+                *wcTime = '\0';
+                ConvSecToHMS(iData * 60, wcTime, countof( wcTime));
+                hr = Iis7PutPropertyString( pElement, IIS_CONFIG_TIMEOUT, wcTime);
+                ExitOnFailure(hr, "Failed to put asp timeout value");
+                ReleaseNullObject(pElement);
+                break;
+            }
+            case IIS_ASP_BUFFER:
+            {
+                //system.webServer/asp | bufferingOn
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read asp bufferingOn");
+                hr = Iis7PutPropertyBool( pSection, IIS_CONFIG_BUFFERING, iData);
+                ExitOnFailure(hr, "Failed to put asp bufferingOn value");
+                break;
+            }
+            case IIS_ASP_PARENTPATHS:
+            {
+                //system.webServer/asp | enableParentPaths
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read asp ParentPaths");
+                hr = Iis7PutPropertyBool( pSection, IIS_CONFIG_PARENTPATHS, iData);
+                ExitOnFailure(hr, "Failed to put asp ParentPaths value");
+                break;
+            }
+            case IIS_ASP_SCRIPTLANG:
+            {
+                //system.webServer/asp | scriptLanguage
+                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+                ExitOnFailure(hr, "Failed to read asp scriptLanguage");
+                hr = Iis7PutPropertyString( pSection, IIS_CONFIG_SCRIPTLANG, pwzData);
+                ExitOnFailure(hr, "Failed to put asp scriptLanguage value");
+                break;
+            }
+            case IIS_ASP_SCRIPTTIMEOUT:
+            {
+                //system.webServer/asp /limits | scriptTimeout
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read asp scriptTimeout");
+                hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_LIMITS), &pElement);
+                ExitOnFailure(hr, "Failed to get asp session element");
+                *wcTime = '\0';
+                ConvSecToHMS(iData, wcTime, countof( wcTime));
+                hr = Iis7PutPropertyString( pElement, IIS_CONFIG_SCRIPTTIMEOUT, wcTime);
+                ExitOnFailure(hr, "Failed to put asp scriptTimeout value");
+                ReleaseNullObject(pElement);
+                break;
+
+            }
+            case IIS_ASP_SCRIPTSERVERDEBUG:
+            {
+                //system.webServer/asp | appAllowDebugging
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read asp appAllowDebugging");
+                hr = Iis7PutPropertyBool( pSection, IIS_CONFIG_ALLOWDEBUG, iData);
+                ExitOnFailure(hr, "Failed to put asp appAllowDebugging value");
+                break;
+            }
+            case IIS_ASP_SCRIPTCLIENTDEBUG:
+            {
+                //system.webServer/asp | appAllowClientDebug
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read asp appAllowClientDebug");
+                hr = Iis7PutPropertyBool( pSection, IIS_CONFIG_ALLOWCLIENTDEBUG, iData);
+                ExitOnFailure(hr, "Failed to put asp appAllowClientDebug value");
+                break;
+            }
+            default:
+            {
+                ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for asp properties");
+                break;
+            }
+        }
+        // Get next action
+        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+        ExitOnFailure(hr, "Failed to read asp prop action");
+    }
+
+LExit:
+    ReleaseStr(pwzData);
+    ReleaseStr(pwzSiteName);
+    ReleaseStr(pwzPathName);
+    ReleaseStr(pwzLocationPath);
+    ReleaseObject(pSection);
+    ReleaseObject(pElement);
+
+    return hr;
+}
+
+//-------------------------------------------------------------------------------------------------
+// IIS7WebDir
+// Called by WriteIIS7ConfigChanges
+// Processes WebDir
+//
+//-------------------------------------------------------------------------------------------------
+HRESULT IIS7WebDir(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    )
+{
+    HRESULT hr = S_OK;
+
+    int iAction = -1;
+
+    LPWSTR pwzSiteName = NULL;
+    LPWSTR pwzPathName = NULL;
+    LPWSTR pwzLocationPath = NULL;
+
+    // Get  action
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+    ExitOnFailure(hr, "Failed to read property action");
+
+    //read web site key
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
+    ExitOnFailure(hr, "Failed read webDir webkey");
+
+    //read path key
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzPathName);
+    ExitOnFailure(hr, "Failed read webDir path");
+
+    switch (iAction)
+    {
+        case IIS_CREATE:
+        {
+            //no action needed for create since WebDir has a
+            //WebDirProperties element that will create and populate
+            //location tag
+            break;
+        }
+        case IIS_DELETE:
+        {
+            //Construct Location path
+            hr = StrAllocString(&pwzLocationPath, pwzSiteName, 0);
+            ExitOnFailure(hr, "failed to copy location WebDir web name");
+            //
+            //Do not append trailing '/' for default vDir
+            //
+            if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzPathName, -1, L"/", -1))
+            {
+                hr = StrAllocConcat(&pwzLocationPath, L"/", 0);
+                ExitOnFailure(hr, "failed to copy location WebDir '/'");
+                hr = StrAllocConcat(&pwzLocationPath, pwzPathName, 0);
+                ExitOnFailure(hr, "failed to copy location WebDir path");
+            }
+            // and delete location tag for this application
+            hr = ClearLocationTag(pAdminMgr, pwzLocationPath);
+            ExitOnFailure(hr, "failed to clear location tag for %ls", pwzLocationPath)
+            break;
+        }
+        default:
+        {
+            ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for WebDir");
+            break;
+        }
+    }
+LExit:
+    ReleaseStr(pwzSiteName);
+    ReleaseStr(pwzPathName);
+    ReleaseStr(pwzLocationPath);
+
+    return hr;
+}
+
+//-------------------------------------------------------------------------------------------------
+// IIS7WebProperty
+// Called by WriteIIS7ConfigChanges
+// Processes isapiCgiRestriction
+//
+//-------------------------------------------------------------------------------------------------
+HRESULT IIS7WebProperty(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    )
+{
+    HRESULT hr = S_OK;
+
+    int iAction = -1;
+    int iData   =  0;
+
+    IAppHostElement *pSection = NULL;
+
+    // Get  action
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+    ExitOnFailure(hr, "Failed to read property action");
+
+    switch (iAction)
+    {
+        case IIS_PROPERTY_MAXBAND:
+        {
+            hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+            ExitOnFailure(hr, "Failed to read property max band");
+            //set value at system.applicationHost/webLimits | maxGlobalBandwidth
+            //Get IIS config section
+            hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_WEBLIMITS_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pSection);
+            ExitOnFailure(hr, "Failed get isapiCgiRestriction section");
+            if (!pSection)
+            {
+                hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+                ExitOnFailure(hr, "Failed get isapiCgiRestriction section object");
+            }
+            hr = Iis7PutPropertyInteger(pSection, IIS_CONFIG_WEBLIMITS_MAXBAND, iData);
+
+            break;
+        }
+        case IIS_PROPERTY_LOGUTF8:
+        {
+            hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+            ExitOnFailure(hr, "Failed to read property log");
+            //set value at system.applicationHost/log | logInUTF8
+            //Get IIS config section
+            hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_LOG_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pSection);
+            ExitOnFailure(hr, "Failed get isapiCgiRestriction section");
+            if (!pSection)
+            {
+                hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+                ExitOnFailure(hr, "Failed get isapiCgiRestriction section object");
+            }
+            hr = Iis7PutPropertyBool(pSection, IIS_CONFIG_LOG_UTF8, iData);
+
+            break;
+        }
+        default:
+        {
+            ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for Web Property");
+            break;
+        }
+    }
+
+LExit:
+    ReleaseObject(pSection);
+
+    return hr;
+}
+
+//-------------------------------------------------------------------------------------------------
+// IIS7WebSvcExt
+// Called by WriteIIS7ConfigChanges
+// Processes isapiCgiRestriction
+//
+//-------------------------------------------------------------------------------------------------
+HRESULT IIS7WebSvcExt(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    )
+{
+    HRESULT hr = S_OK;
+
+    int iAction = -1;
+    int iData   =  0;
+    BOOL fFound = FALSE;
+    LPWSTR pwzData = NULL;
+    LPWSTR pwzPath = NULL;
+
+    IAppHostElement *pSection = NULL;
+    IAppHostElement *pElement = NULL;
+    IAppHostElementCollection *pCollection = NULL;
+
+    // Get  action
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+    ExitOnFailure(hr, "Failed to read WebSvcExt action");
+
+    //get path
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzPath);
+    ExitOnFailure(hr, "Failed to read WebSvcExt key");
+
+    //Get IIS config section
+    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_RESTRICTION_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pSection);
+    ExitOnFailure(hr, "Failed get isapiCgiRestriction section");
+    if (!pSection)
+    {
+        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+        ExitOnFailure(hr, "Failed get isapiCgiRestriction section object");
+    }
+    //get collection
+    hr = pSection->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get isapiCgiRestriction collection");
+
+    //find element
+    hr = Iis7FindAppHostElementPath(pCollection, IIS_CONFIG_ADD, IIS_CONFIG_PATH, pwzPath, &pElement, NULL);
+    ExitOnFailure(hr, "Failed get isapiCgiRestriction element");
+    fFound = (NULL != pElement);
+
+    switch (iAction)
+    {
+        case IIS_CREATE:
+        {
+            if (!fFound)
+            {
+                //create a restriction element
+                hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pElement);
+                ExitOnFailure(hr, "Failed create isapiCgiRestriction element");
+                //put path
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PATH, pwzPath);
+                ExitOnFailure(hr, "Failed set isapiCgiRestriction path property");
+            }
+            //update common properties
+
+            //update allowed
+            hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+            ExitOnFailure(hr, "Failed to read WebSvcExt allowed");
+            hr = Iis7PutPropertyBool(pElement, IIS_CONFIG_ALLOWED, iData);
+            ExitOnFailure(hr, "Failed set isapiCgiRestriction allowed property");
+
+            //update groupId
+            hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+            ExitOnFailure(hr, "Failed to read WebSvcExt group ID");
+            if (*pwzData)
+            {
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_GROUPID, pwzData);
+                ExitOnFailure(hr, "Failed set isapiCgiRestriction groupId property");
+            }
+            //update description
+            hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+            ExitOnFailure(hr, "Failed to read WebSvcExt description");
+            if (*pwzData)
+            {
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_DESC, pwzData);
+                ExitOnFailure(hr, "Failed set isapiCgiRestriction description property");
+            }
+            // add element if new
+            if (!fFound)
+            {
+                hr = pCollection->AddElement(pElement);
+                ExitOnFailure(hr, "Failed add isapiCgiRestriction element");
+            }
+
+            break;
+        }
+        case IIS_DELETE:
+        {
+            hr = DeleteCollectionElement(pCollection, IIS_CONFIG_ADD, IIS_CONFIG_PATH, pwzPath);
+            ExitOnFailure(hr, "Failed delete isapiCgiRestriction element");
+            break;
+        }
+        default:
+        {
+            ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for WebSvcExt");
+            break;
+        }
+    }
+
+LExit:
+    ReleaseStr(pwzPath);
+    ReleaseStr(pwzData);
+    ReleaseObject(pSection);
+    ReleaseObject(pElement);
+    ReleaseObject(pCollection);
+
+    return hr;
+
+}
+
+//-------------------------------------------------------------------------------------------------
+// IIS7WebError
+// Called by WriteIIS7ConfigChanges
+// Processes http header CA Data
+//
+//-------------------------------------------------------------------------------------------------
+
+HRESULT IIS7WebError(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    )
+{
+    HRESULT hr = S_OK;
+    LPWSTR pwzConfigPath = NULL;
+    LPWSTR pwzSiteName = NULL;
+    LPWSTR pwzAppName = NULL;
+
+    IAppHostElement *pElement = NULL;
+    IAppHostElement *pSection = NULL;
+    IAppHostElementCollection *pCollection = NULL;
+
+    SCA_WEB_ERROR_SERVER *psweList = NULL;
+    SCA_WEB_ERROR_SERVER* pswe = NULL;
+    SCA_WEB_ERROR_SERVER we;
+    BOOL fFound = FALSE;
+
+    int iAction = -1;
+    LPWSTR pwzData = NULL;
+
+    //read web site key
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
+    ExitOnFailure(hr, "Failed read web error site name");
+
+    //read app key
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzAppName);
+    ExitOnFailure(hr, "Failed read web error app name");
+
+    //Construct config root path
+    hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzSiteName);
+    ExitOnFailure(hr, "failed to format web error config path");
+
+    if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzAppName, -1, L"/", -1))
+    {
+        hr = StrAllocConcat(&pwzConfigPath, L"/", 0);
+        ExitOnFailure(hr, "failed to copy web error config path delim");
+        hr = StrAllocConcat(&pwzConfigPath, pwzAppName, 0);
+        ExitOnFailure(hr, "failed to app name to web error config path");
+    }
+
+    //get httpErrors section at config path location tag
+    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_HTTPERRORS_SECTION), pwzConfigPath, &pSection);
+    ExitOnFailure(hr, "Failed get httpErrors section");
+
+    //get existing httpErrors list & clear collection
+    hr = PopulateHttpErrors(pSection, &psweList);
+    ExitOnFailure(hr, "Failed to read httpErrors list");
+
+    //get collection
+    hr = pSection->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get httpErrors collection");
+
+    DWORD cErrors = 0;
+    hr = pCollection->get_Count(&cErrors);
+
+   // Get web error action
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+    ExitOnFailure(hr, "Failed to read filter action");
+    while (IIS_WEBERROR_END != iAction)
+    {
+        //Process property action
+        if (IIS_WEBERROR == iAction)
+        {
+            hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &(we.iErrorCode));
+            ExitOnFailure(hr, "failed to get httpErrors ErrorCode");
+
+            hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &(we.iSubCode));
+            ExitOnFailure(hr, "failed to get httpErrors SubCode");
+            //0 is the sub error code wild card for IIS6, change to -1 for IIS7
+            if (we.iSubCode == 0)
+            {
+                we.iSubCode = -1;
+            }
+            hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+            ExitOnFailure(hr, "Failed to get httpErrors File");
+            hr = ::StringCchCopyW(we.wzFile, countof(we.wzFile), pwzData);
+            ExitOnFailure(hr, "Failed to copy httpErrors File");
+
+            hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &(we.iResponseMode));
+            ExitOnFailure(hr, "Failed to get httpErrors File code");
+
+            fFound = FALSE;
+            hr = GetErrorFromList( we, &psweList, &pswe, &fFound);
+            if (!fFound)
+            {
+                hr = AddWebErrorToList(&psweList);
+                ExitOnFailure(hr, "failed to add web error to list");
+                pswe = psweList;
+            }
+            else
+            {
+                //if overwriting existing http errors element then clear lang path
+                hr = ::StringCchCopyW(pswe->wzLangPath, countof(pswe->wzLangPath), L"");
+                ExitOnFailure(hr, "Failed to copy httpErrors lang path value");
+            }
+            pswe->iErrorCode = we.iErrorCode;
+            pswe->iSubCode   = we.iSubCode;
+            hr = ::StringCchCopyW(pswe->wzFile, countof(pswe->wzFile), we.wzFile);
+            ExitOnFailure(hr, "Failed to copy httpErrors File value");
+            pswe->iResponseMode = we.iResponseMode;
+
+        }
+        else
+        {
+            ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for http header");
+        }
+
+        // Get AppExt action
+        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+        ExitOnFailure(hr, "Failed to read filter action");
+    }
+
+    //No inheritance - put a clear in at this loc tag
+    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_CLEAR), &pElement);
+    ExitOnFailure(hr, "Failed create httpErrors clear");
+    hr = pCollection->AddElement(pElement);
+    ExitOnFailure(hr, "Failed add httpErrors clear");
+
+    //now we have merged new, from MSI, http errors with global list
+    //write this back out at location tag.
+    // Loop through the HTTP headers
+    for ( pswe = psweList; pswe; pswe = pswe->psweNext)
+    {
+        hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ERROR), &pElement);
+        ExitOnFailure(hr, "Failed create httpErrors element");
+
+        // status code
+        hr = Iis7PutPropertyInteger(pElement, IIS_CONFIG_STATUSCODE, pswe->iErrorCode);
+        ExitOnFailure(hr, "Failed set httpErrors code value");
+
+        //sub status
+        hr = Iis7PutPropertyInteger(pElement, IIS_CONFIG_SUBSTATUS, pswe->iSubCode);
+        ExitOnFailure(hr, "Failed set httpErrors sub code value");
+
+        //lang path
+        hr = Iis7PutPropertyString(pElement, IIS_CONFIG_LANGPATH, pswe->wzLangPath);
+        ExitOnFailure(hr, "Failed set httpErrors lang path value");
+
+        //path
+        hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PATH, pswe->wzFile);
+        ExitOnFailure(hr, "Failed set httpErrors path value");
+
+        //response mode
+        hr = Iis7PutPropertyInteger(pElement, IIS_CONFIG_RESPMODE, pswe->iResponseMode);
+        ExitOnFailure(hr, "Failed set httpErrors resp mode value");
+
+        //add the element
+        hr = pCollection->AddElement(pElement);
+        ExitOnFailure(hr, "Failed add httpErrors element");
+        ReleaseNullObject(pElement);
+    }
+
+LExit:
+    ScaWebErrorFreeList7(psweList);
+
+    ReleaseStr(pwzConfigPath);
+    ReleaseStr(pwzSiteName);
+    ReleaseStr(pwzAppName);
+    ReleaseStr(pwzData);
+    ReleaseObject(pElement);
+    ReleaseObject(pSection);
+    ReleaseObject(pCollection);
+
+    return hr;
+}
+
+static HRESULT PopulateHttpErrors(IAppHostElement *pSection, SCA_WEB_ERROR_SERVER **ppsweList)
+{
+    HRESULT hr = S_OK;
+
+    IAppHostElement *pElement = NULL;
+    IAppHostElementCollection *pCollection = NULL;
+    IAppHostProperty *pProperty = NULL;
+
+    DWORD cErrors = 0;
+    SCA_WEB_ERROR_SERVER *pswe = NULL;
+
+    VARIANT vPropValue;
+    VARIANT vtIndex;
+
+    VariantInit(&vPropValue);
+    VariantInit(&vtIndex);
+
+    hr = pSection->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get httpErrors collection");
+
+    hr = pCollection->get_Count(&cErrors);
+    ExitOnFailure(hr, "Failed get sites collection count");
+
+    vtIndex.vt = VT_UI4;
+    for (DWORD i = 0; i < cErrors; ++i)
+    {
+        vtIndex.ulVal = i;
+        hr = pCollection->get_Item(vtIndex , &pElement);
+        ExitOnFailure(hr, "Failed get httpErrors collection item");
+
+        hr = AddWebErrorToList(ppsweList);
+        ExitOnFailure(hr, "Failed add web error list item");
+        pswe = *ppsweList;
+
+        //get all properties
+        //
+        // statusCode UINT
+        // subStatusCode INT
+        // prefixLanguageFilePath type="string"
+        // path type="string"
+        // responseMode type="enum" defaultValue="File">
+        //  <enum name="File" value="0" />
+        //  <enum name="ExecuteURL" value="1" />
+        //  <enum name="Redirect" value="2" />
+
+        // status code
+        hr = pElement->GetPropertyByName(ScopeBSTR(IIS_CONFIG_STATUSCODE), &pProperty);
+        ExitOnFailure(hr, "Failed get httpErrors code property");
+        hr = pProperty->get_Value(&vPropValue);
+        ExitOnFailure(hr, "Failed get httpErrors code value");
+        pswe->iErrorCode = vPropValue.uintVal;
+        ReleaseVariant(vPropValue);
+
+        //sub status
+        hr = pElement->GetPropertyByName(ScopeBSTR(IIS_CONFIG_SUBSTATUS), &pProperty);
+        ExitOnFailure(hr, "Failed get httpErrors sub code property");
+        hr = pProperty->get_Value(&vPropValue);
+        ExitOnFailure(hr, "Failed get httpErrors sub code value");
+        pswe->iSubCode = vPropValue.intVal;
+        ReleaseVariant(vPropValue);
+
+        //lang path
+        hr = pElement->GetPropertyByName(ScopeBSTR(IIS_CONFIG_LANGPATH), &pProperty);
+        ExitOnFailure(hr, "Failed get httpErrors lang path property");
+        hr = pProperty->get_Value(&vPropValue);
+        ExitOnFailure(hr, "Failed get httpErrors lang path value");
+        hr = ::StringCchCopyW(pswe->wzLangPath, countof(pswe->wzLangPath), vPropValue.bstrVal);
+        ExitOnFailure(hr, "Failed to copy httpErrors lang path");
+        ReleaseVariant(vPropValue);
+
+        //path
+        hr = pElement->GetPropertyByName(ScopeBSTR(IIS_CONFIG_PATH), &pProperty);
+        ExitOnFailure(hr, "Failed get httpErrors path property");
+        hr = pProperty->get_Value(&vPropValue);
+        ExitOnFailure(hr, "Failed get httpErrors path value");
+        hr = ::StringCchCopyW(pswe->wzFile, countof(pswe->wzFile), vPropValue.bstrVal);
+        ExitOnFailure(hr, "Failed to copy httpErrors File");
+        ReleaseVariant(vPropValue);
+
+        //response mode
+        hr = pElement->GetPropertyByName(ScopeBSTR(IIS_CONFIG_RESPMODE), &pProperty);
+        ExitOnFailure(hr, "Failed get httpErrors resp mode property");
+        hr = pProperty->get_Value(&vPropValue);
+        ExitOnFailure(hr, "Failed get httpErrors resp mode value");
+        pswe->iResponseMode = vPropValue.intVal;
+        ReleaseVariant(vPropValue);
+
+        ReleaseNullObject(pElement);
+        ReleaseNullObject(pProperty);
+    }
+
+    //remove the elements from connection so we can add back later
+    hr = pCollection->Clear();
+    ExitOnFailure(hr, "Failed clear httpErrors collection");
+
+LExit:
+    ReleaseVariant(vPropValue);
+    ReleaseObject(pProperty);
+    ReleaseObject(pElement);
+    ReleaseObject(pCollection);
+
+    return hr;
+}
+
+static void ScaWebErrorFreeList7(SCA_WEB_ERROR_SERVER *psweList)
+{
+    SCA_WEB_ERROR_SERVER *psweDelete = psweList;
+    while (psweList)
+    {
+        psweDelete = psweList;
+        psweList = psweList->psweNext;
+
+        MemFree(psweDelete);
+    }
+}
+static HRESULT AddWebErrorToList(SCA_WEB_ERROR_SERVER **ppsweList)
+{
+    HRESULT hr = S_OK;
+
+    SCA_WEB_ERROR_SERVER* pswe = static_cast<SCA_WEB_ERROR_SERVER*>(MemAlloc(sizeof(SCA_WEB_ERROR_SERVER), TRUE));
+
+    ExitOnNull(pswe, hr, E_OUTOFMEMORY, "failed to allocate memory for new web error list element");
+
+    pswe->psweNext = *ppsweList;
+    *ppsweList = pswe;
+
+LExit:
+    return hr;
+}
+static HRESULT GetErrorFromList( const SCA_WEB_ERROR_SERVER& we,
+                                    SCA_WEB_ERROR_SERVER **ppsweList,
+                                    SCA_WEB_ERROR_SERVER **ppswe,
+                                    BOOL *fFound)
+{
+    HRESULT hr = S_OK;
+
+    *fFound = FALSE;
+
+    SCA_WEB_ERROR_SERVER *pswe;
+
+    for ( pswe = *ppsweList; pswe; pswe = pswe->psweNext)
+    {
+        if ((pswe->iErrorCode == we.iErrorCode) && (pswe->iSubCode == we.iSubCode))
+        {
+            *fFound = TRUE;
+            *ppswe = pswe;
+            break;
+        }
+    }
+
+    return hr;
+}
+
+//-------------------------------------------------------------------------------------------------
+// IIS7HttpHeader
+// Called by WriteIIS7ConfigChanges
+// Processes http header CA Data
+//
+//-------------------------------------------------------------------------------------------------
+
+HRESULT IIS7HttpHeader(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    )
+{
+    HRESULT hr = S_OK;
+    LPWSTR pwzConfigPath = NULL;
+    LPWSTR pwzSiteName = NULL;
+    LPWSTR pwzAppName = NULL;
+
+    LPWSTR pwzHeaderName = NULL;
+    LPWSTR pwzHeaderValue = NULL;
+
+    IAppHostElement *pElement = NULL;
+    IAppHostElement *pSection = NULL;
+    IAppHostElementCollection *pCollection = NULL;
+    IAppHostElement *pElementHeaders = NULL;
+
+    int iAction = -1;
+    BOOL fFound = FALSE;
+
+    //read web site key
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
+    ExitOnFailure(hr, "Failed read header web site name");
+
+    //read app key
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzAppName);
+    ExitOnFailure(hr, "Failed read header appkey");
+
+    //Construct config root path
+    hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzSiteName);
+    ExitOnFailure(hr, "failed to format web error config path");
+
+    if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzAppName, -1, L"/", -1))
+    {
+        hr = StrAllocConcat(&pwzConfigPath, L"/", 0);
+        ExitOnFailure(hr, "failed to copy web error config path delim");
+        hr = StrAllocConcat(&pwzConfigPath, pwzAppName, 0);
+        ExitOnFailure(hr, "failed to app name to web error config path");
+    }
+
+    //get admin handlers section at config path location tag
+    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_HTTPPROTO_SECTION), pwzConfigPath, &pSection);
+    ExitOnFailure(hr, "Failed get http protocol section");
+
+    hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_HEADERS), &pElementHeaders);
+    ExitOnFailure(hr, "Failed get http customHeaders section");
+
+    hr = pElementHeaders->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get http customHeaders collection");
+
+   // Get filter action
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+    ExitOnFailure(hr, "Failed to read filter action");
+    while (IIS_HTTP_HEADER_END != iAction)
+    {
+        //Process property action
+        if (IIS_HTTP_HEADER == iAction)
+        {
+            hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzHeaderName);
+            ExitOnFailure(hr, "Fail to read httpHeader name");
+
+            hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzHeaderValue);
+            ExitOnFailure(hr, "Fail to read httpHeader value");
+
+            hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_ADD, IIS_CONFIG_NAME, pwzHeaderName, &pElement, NULL);
+            ExitOnFailure(hr, "Failed get isapiCgiRestriction element");
+            fFound = (NULL != pElement);
+
+            if (!fFound)
+            {
+                //make a new element
+                hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pElement);
+                ExitOnFailure(hr, "Failed to create filter config element");
+
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_NAME, pwzHeaderName);
+                ExitOnFailure(hr, "Failed to set header name");
+            }
+
+            hr = Iis7PutPropertyString(pElement, IIS_CONFIG_VALUE, pwzHeaderValue);
+            ExitOnFailure(hr, "Failed to set header Value");
+
+            if (!fFound)
+            {
+                hr = pCollection->AddElement(pElement);
+                ExitOnFailure(hr, "Failed add http header");
+            }
+
+        }
+        else
+        {
+            ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for http header");
+        }
+
+        // Get AppExt action
+        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+        ExitOnFailure(hr, "Failed to read filter action");
+    }
+
+LExit:
+    ReleaseStr(pwzConfigPath);
+    ReleaseStr(pwzSiteName);
+    ReleaseStr(pwzAppName);
+    ReleaseStr(pwzHeaderName);
+    ReleaseStr(pwzHeaderValue);
+    ReleaseObject(pElementHeaders);
+    ReleaseObject(pElement);
+    ReleaseObject(pSection);
+    ReleaseObject(pCollection);
+
+    return hr;
+}
+
+//-------------------------------------------------------------------------------------------------
+// IIS7FilterGlobal
+// Called by WriteIIS7ConfigChanges
+// Processes Filter CA Data
+//
+//-------------------------------------------------------------------------------------------------
+HRESULT IIS7FilterGlobal(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    )
+{
+    HRESULT hr = S_OK;
+    int iAction = 0;
+
+    IAppHostElement *pSection = NULL;
+
+    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_ISAPI_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pSection);
+    ExitOnFailure(hr, "Failed get sites section");
+
+    if (!pSection)
+    {
+        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+        ExitOnFailure(hr, "Failed get isapiFilters section object");
+    }
+
+   // Get filter action
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+    ExitOnFailure(hr, "Failed to read filter action");
+
+    while (IIS_FILTER_END != iAction)
+    {
+        //Process property action
+        switch (iAction)
+        {
+            case IIS_FILTER :
+            {
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+                ExitOnFailure(hr, "Failed to read filter action");
+
+                if (iAction == IIS_CREATE)
+                {
+                    hr = CreateGlobalFilter(ppwzCustomActionData, pSection);
+                }
+                else
+                {
+                    hr = DeleteGlobalFilter(ppwzCustomActionData, pSection);
+                }
+                break;
+            }
+            default:
+            {
+                ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for global filter");
+                break;
+            }
+        }
+        // Get AppExt action
+        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+        ExitOnFailure(hr, "Failed to read filter action");
+
+    }
+
+LExit:
+    ReleaseObject(pSection);
+
+    return hr;
+}
+
+static HRESULT CreateGlobalFilter( __inout LPWSTR *ppwzCustomActionData, IAppHostElement *pSection)
+{
+    HRESULT hr = S_OK;
+
+    LPWSTR pwzFilterName = NULL;
+    LPWSTR pwzSiteName = NULL;
+    LPWSTR pwzFilterPath = NULL;
+    int iLoadOrder = 0;
+    DWORD cFilters = 0;
+
+    IAppHostElement *pElement = NULL;
+    IAppHostElementCollection *pCollection = NULL;
+
+    hr = pSection->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get filter collection");
+
+    hr = pCollection->get_Count(&cFilters);
+    ExitOnFailure(hr, "Failed get filter collection count");
+
+    // Attempt to delete, we will we recreate with desired property values and order
+    hr = DeleteCollectionElement(pCollection, IIS_CONFIG_FILTER, IIS_CONFIG_NAME, pwzFilterName);
+    ExitOnFailure(hr, "Failed to delete filter");
+
+    //make a new element
+    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_FILTER), &pElement);
+    ExitOnFailure(hr, "Failed to create filter config element");
+
+    //filter Name key
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzFilterName);
+    ExitOnFailure(hr, "Failed to read filter name");
+    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_NAME, pwzFilterName);
+    ExitOnFailure(hr, "Failed to set filter name");
+
+    //web site name
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
+    ExitOnFailure(hr, "Failed to read filter site name");
+
+    // filter path
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzFilterPath);
+    ExitOnFailure(hr, "Failed to read filter path");
+    hr = Iis7PutPropertyString(pElement,IIS_CONFIG_PATH, pwzFilterPath);
+    ExitOnFailure(hr, "Failed to set filter path");
+
+    //filter load order
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iLoadOrder);
+    ExitOnFailure(hr, "Failed to read filter load order");
+
+    //  put element in order in list
+    int iPosition = -1;
+    int icFilters = cFilters;
+    switch (iLoadOrder)
+    {
+        case 0 :
+        {
+            iPosition = -1;
+            break;
+        }
+        case -1 :
+        {
+            iPosition = icFilters;
+            break;
+        }
+        case MSI_NULL_INTEGER :
+        {
+             iPosition = icFilters;
+             break;
+        }
+        default:
+        {
+            if (iLoadOrder > icFilters)
+            {
+                iPosition = icFilters;
+            }
+            else
+            {
+                iPosition = iLoadOrder;
+            }
+            break;
+        }
+    }
+    hr = pCollection->AddElement(pElement, iPosition);
+    ExitOnFailure(hr, "Failed to add filter element");
+
+LExit:
+    ReleaseStr(pwzFilterName);
+    ReleaseStr(pwzSiteName);
+    ReleaseStr(pwzFilterPath);
+    ReleaseObject(pCollection);
+    ReleaseObject(pElement);
+
+    return hr;
+}
+
+static HRESULT DeleteGlobalFilter( __inout LPWSTR *ppwzCustomActionData, IAppHostElement *pSection)
+{
+    HRESULT hr = S_OK;
+
+    LPWSTR pwzFilterName = NULL;
+    LPWSTR pwzSiteName = NULL;
+
+    IAppHostElementCollection *pCollection = NULL;
+
+    hr = pSection->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get filter collection");
+
+    //filter Name key
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzFilterName);
+    ExitOnFailure(hr, "Failed to read filter name");
+
+    //web site name
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName); // TODO: unused?
+    ExitOnFailure(hr, "Failed to read filter site name");
+
+    DeleteCollectionElement(pCollection, IIS_CONFIG_FILTER, IIS_CONFIG_NAME, pwzFilterName);
+    ExitOnFailure(hr, "Failed to delete filter %ls", pwzFilterName);
+
+LExit:
+    ReleaseStr(pwzFilterName);
+    ReleaseStr(pwzSiteName);
+    ReleaseObject(pCollection);
+
+    return hr;
+}
+
+//-------------------------------------------------------------------------------------------------
+// IIS7FilterSite
+// Called by WriteIIS7ConfigChanges
+// Processes Filter CA Data
+//
+//-------------------------------------------------------------------------------------------------
+HRESULT IIS7FilterSite(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    )
+{
+    HRESULT hr = S_OK;
+    int iAction = 0;
+
+   // Get filter action
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+    ExitOnFailure(hr, "Failed to read filter action");
+
+    while (IIS_FILTER_END != iAction)
+    {
+        //Process property action
+        switch (iAction)
+        {
+            case IIS_FILTER :
+            {
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+                ExitOnFailure(hr, "Failed to read filter action");
+
+                if (iAction == IIS_CREATE)
+                {
+                    hr = CreateSiteFilter(ppwzCustomActionData, pAdminMgr);
+                }
+                else
+                {
+                    hr = DeleteSiteFilter(ppwzCustomActionData, pAdminMgr);
+                }
+                break;
+            }
+            default:
+            {
+                ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for global filter");
+                break;
+            }
+        }
+
+        // Get AppExt action
+        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+        ExitOnFailure(hr, "Failed to read filter action");
+    }
+
+LExit:
+    return hr;
+
+}
+
+static HRESULT CreateSiteFilter(__inout LPWSTR *ppwzCustomActionData, IAppHostWritableAdminManager *pAdminMgr)
+{
+    HRESULT hr = S_OK;
+    LPWSTR pwzFilterName = NULL;
+    LPWSTR pwzSiteName = NULL;
+    LPWSTR pwzFilterPath = NULL;
+    LPWSTR pwzConfigPath = NULL;
+    int iLoadOrder = 0;
+    DWORD cFilters;
+
+    IAppHostElement *pElement = NULL;
+    IAppHostElement *pSection = NULL;
+    IAppHostElementCollection *pCollection = NULL;
+
+    //filter Name key
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzFilterName);
+    ExitOnFailure(hr, "Failed to read filter name");
+
+    //web site name
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
+    ExitOnFailure(hr, "Failed to read filter site name");
+
+     //Construct config root
+    hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzSiteName);
+    ExitOnFailure(hr, "failed to format filter config path");
+
+    //get admin isapiFilters section at config path location tag
+    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_ISAPI_SECTION), pwzConfigPath, &pSection);
+    ExitOnFailure(hr, "Failed get isapiFilters section");
+
+    hr = pSection->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get filter collection");
+
+    hr = pCollection->get_Count(&cFilters);
+    ExitOnFailure(hr, "Failed get filter collection count");
+
+    // Attempt to delete, we will we recreate with desired property values and order
+    hr = DeleteCollectionElement(pCollection, IIS_CONFIG_FILTER, IIS_CONFIG_NAME, pwzFilterName);
+    ExitOnFailure(hr, "Failed to delete filter");
+
+     //make a new element
+    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_FILTER), &pElement);
+    ExitOnFailure(hr, "Failed to create filter config element");
+
+    hr = Iis7PutPropertyString(pElement,IIS_CONFIG_NAME, pwzFilterName);
+    ExitOnFailure(hr, "Failed to set filter name");
+
+    // filter path
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzFilterPath);
+    ExitOnFailure(hr, "Failed to read filter path");
+
+    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PATH, pwzFilterPath);
+    ExitOnFailure(hr, "Failed to set filter path");
+
+    //filter load order
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iLoadOrder);
+    ExitOnFailure(hr, "Failed to read filter load order");
+
+    //  put element in order in list
+    int iPosition = -1;
+    int icFilters = cFilters;
+    switch (iLoadOrder)
+    {
+        case 0 :
+        {
+            iPosition = -1;
+            break;
+        }
+        case -1 :
+        {
+            iPosition = icFilters;
+            break;
+        }
+        case MSI_NULL_INTEGER :
+        {
+            iPosition = icFilters;
+            break;
+        }
+        default:
+        {
+            if (iLoadOrder > icFilters)
+            {
+                iPosition = icFilters;
+            }
+            else
+            {
+                iPosition = iLoadOrder;
+            }
+            break;
+        }
+    }
+
+    hr = pCollection->AddElement(pElement, iPosition);
+    ExitOnFailure(hr, "Failed to add filter element");
+
+LExit:
+    ReleaseStr(pwzFilterName);
+    ReleaseStr(pwzSiteName);
+    ReleaseStr(pwzFilterPath);
+    ReleaseStr(pwzConfigPath);
+    ReleaseObject(pElement);
+    ReleaseObject(pSection);
+    ReleaseObject(pCollection);
+
+    return hr;
+}
+
+static HRESULT DeleteSiteFilter(__inout LPWSTR *ppwzCustomActionData, IAppHostWritableAdminManager *pAdminMgr)
+{
+    HRESULT hr = S_OK;
+    LPWSTR pwzFilterName = NULL;
+    LPWSTR pwzSiteName = NULL;
+    LPWSTR pwzConfigPath = NULL;
+
+    IAppHostElement *pSection = NULL;
+    IAppHostElementCollection *pCollection = NULL;
+
+    //filter Name key
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzFilterName);
+    ExitOnFailure(hr, "Failed to read filter name");
+
+    //web site name
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
+    ExitOnFailure(hr, "Failed to read filter site name");
+
+     //Construct config root
+    hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzSiteName);
+    ExitOnFailure(hr, "failed to format filter config path");
+
+    //get admin isapiFilters section at config path location tag
+    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_ISAPI_SECTION), pwzConfigPath, &pSection);
+    ExitOnFailure(hr, "Failed get isapiFilters section");
+
+    hr = pSection->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get filter collection");
+
+    DeleteCollectionElement(pCollection, IIS_CONFIG_FILTER, IIS_CONFIG_NAME, pwzFilterName);
+    ExitOnFailure(hr, "Failed to delete filter %ls", pwzFilterName);
+
+LExit:
+    ReleaseStr(pwzFilterName);
+    ReleaseStr(pwzSiteName);
+    ReleaseStr(pwzConfigPath);
+    ReleaseObject(pSection);
+    ReleaseObject(pCollection);
+
+    return hr;
+}
+
+//-------------------------------------------------------------------------------------------------
+// IIS7Site
+// Called by WriteIIS7ConfigChanges
+// Processes WebSite CA Data
+//
+//-------------------------------------------------------------------------------------------------
+HRESULT IIS7Site(
+    __inout LPWSTR *ppwzCustomActionData,
+    __in    IAppHostWritableAdminManager *pAdminMgr)
+{
+    HRESULT hr  = S_OK;
+    int iAction = -1;
+    int iData   =  0;
+    BOOL fFound = FALSE;
+
+    LPWSTR pwzSiteName = NULL;
+    IAppHostElement *pSites = NULL;
+    IAppHostElementCollection *pCollection = NULL;
+    IAppHostElement *pSiteElem = NULL;
+    IAppHostElement *pElement = NULL;
+
+    // Get site action
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+    ExitOnFailure(hr, "Failed to read site action");
+
+    //get site name
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
+    ExitOnFailure(hr, "Failed to read site key");
+
+    //Get site if it exists
+    hr = GetSiteElement(pAdminMgr, pwzSiteName, &pSiteElem, &fFound);
+    ExitOnFailure(hr, "Failed to read sites from config");
+
+    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_SITES_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pSites);
+    ExitOnFailure(hr, "Failed get sites section");
+    ExitOnNull(pSites, hr, ERROR_FILE_NOT_FOUND, "Failed get sites section object");
+
+    hr = pSites->get_Collection( &pCollection);
+    ExitOnFailure(hr, "Failed get site collection");
+    switch (iAction)
+    {
+        case IIS_DELETE :
+        {
+            if (fFound)
+            {
+                hr = DeleteCollectionElement(pCollection, IIS_CONFIG_SITE, IIS_CONFIG_NAME, pwzSiteName);
+                ExitOnFailure(hr, "Failed to delete website");
+            }
+            ExitFunction();
+            break;
+        }
+        case IIS_CREATE :
+        {
+            if (!fFound)
+            {
+                //Create the site
+                hr = CreateSite(pCollection, pwzSiteName, &pSiteElem);
+                ExitOnFailure(hr, "Failed to create site");
+
+            }
+        }
+    }
+    //
+    //Set other Site properties
+    //
+    //set site Id
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+    ExitOnFailure(hr, "Failed to read site Id");
+    if (iData != MSI_NULL_INTEGER && -1 != iData)
+    {
+        hr = Iis7PutPropertyInteger(pSiteElem, IIS_CONFIG_SITE_ID, iData);
+        ExitOnFailure(hr, "Failed set site Id data");
+    }
+    //Set Site AutoStart
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+    ExitOnFailure(hr, "Failed to read site autostart");
+    if (MSI_NULL_INTEGER != iData)
+    {
+        hr = Iis7PutPropertyBool(pSiteElem, IIS_CONFIG_AUTOSTART, iData);
+        ExitOnFailure(hr, "Failed set site config data");
+    }
+
+    //Set Site Connection timeout
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+    ExitOnFailure(hr, "Failed to read site connection tomeout data");
+    if (MSI_NULL_INTEGER != iData)
+    {
+        // get limits element, get connectionTimeout property
+        hr = pSiteElem->GetElementByName(ScopeBSTR(IIS_CONFIG_LIMITS), &pElement);
+        ExitOnFailure(hr, "Failed to read limits from config");
+        //convert iData in seconds to timeSpan hh:mm:ss
+        WCHAR wcTime[60];
+        *wcTime = '\0';
+        ConvSecToHMS( iData, wcTime, countof( wcTime));
+
+        hr = Iis7PutPropertyString(pElement, IIS_CONFIG_CONNECTTIMEOUT, wcTime);
+        ExitOnFailure(hr, "IIS: failed set connection timeout config data");
+   }
+
+LExit:
+    ReleaseStr(pwzSiteName);
+    ReleaseObject(pSites);
+    ReleaseObject(pCollection);
+    ReleaseObject(pSiteElem);
+    ReleaseObject(pElement);
+
+    return hr;
+}
+//-------------------------------------------------------------------------------------------------
+// IIS7Application
+//  Processes Application CA Data
+//
+//
+//-------------------------------------------------------------------------------------------------
+
+HRESULT IIS7Application(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr)
+{
+    HRESULT hr = S_OK;
+
+    int iAction = -1;
+    BOOL fSiteFound = FALSE;
+    BOOL fAppFound = FALSE;
+
+    LPWSTR pwzSiteName = NULL;
+    LPWSTR pwzAppPath = NULL;
+    LPWSTR pwzAppPool = NULL;
+    LPWSTR pwzLocationPath = NULL;
+    IAppHostElement *pSiteElem = NULL;
+    IAppHostElement *pAppElement = NULL;
+    // Get Application action
+    hr = WcaReadIntegerFromCaData( ppwzCustomActionData, &iAction);
+    ExitOnFailure(hr, "Failed to read application action")
+    //get site key name
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
+    ExitOnFailure(hr, "Failed to read app site key");
+    //get application path
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzAppPath);
+    ExitOnFailure(hr, "Failed to read app path key");
+    //get application Pool
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzAppPool);
+    ExitOnFailure(hr, "Failed to read app pool key");
+
+    //Get site if it exists
+    hr = GetSiteElement(pAdminMgr, pwzSiteName, &pSiteElem, &fSiteFound);
+    ExitOnFailure(hr, "Failed to read sites from config");
+
+    switch (iAction)
+    {
+        case IIS_CREATE :
+        {
+            if (fSiteFound)
+            {
+                //have site get application collection
+                hr = GetApplicationElement(pSiteElem,
+                                            pwzAppPath,
+                                            &pAppElement,
+                                            &fAppFound);
+                ExitOnFailure(hr, "Error reading application from config");
+
+                if (!fAppFound)
+                {
+                    //Create Application
+                    hr = CreateApplication(pSiteElem, pwzAppPath, &pAppElement);
+                    ExitOnFailure(hr, "Error creating application in config");
+                }
+                //Update application properties:
+                //
+                //Set appPool
+                hr = SetAppPool(pAppElement, pwzAppPool);
+                ExitOnFailure(hr, "Unable to set appPool for application");
+            }
+            else
+            {
+                hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+                ExitOnFailure(hr, "Site not found for create application");
+            }
+            break;
+        }
+        case IIS_DELETE :
+        {
+            if (fSiteFound)
+            {
+                //have site get application collection
+                hr = GetApplicationElement( pSiteElem,
+                                            pwzAppPath,
+                                            &pAppElement,
+                                            &fAppFound);
+                ExitOnFailure(hr, "Error reading application from config")
+                if (fAppFound)
+                {
+                    //delete Application
+                    hr = DeleteApplication(pSiteElem, pwzAppPath);
+                    ExitOnFailure(hr, "Error deleating application from config")
+                    //Construct Location path
+                    // TODO: it seems odd that these are just
+                    // jammed together, need to determine if this requires a '\'
+                    hr = StrAllocString(&pwzLocationPath, pwzSiteName, 0);
+                    ExitOnFailure(hr, "failed to copy location config path web name");
+                    hr = StrAllocConcat(&pwzLocationPath, pwzAppPath, 0);
+                    ExitOnFailure(hr, "failed to copy location config path appPath ");
+
+                    // and delete location tag for this application
+                    hr = ClearLocationTag(pAdminMgr, pwzLocationPath);
+                    ExitOnFailure(hr, "failed to clear location tag for %ls", pwzLocationPath);
+                }
+            }
+            break;
+        }
+        default:
+            ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for Application");
+            break;
+    }
+
+LExit:
+    ReleaseStr(pwzSiteName);
+    ReleaseStr(pwzAppPath);
+    ReleaseStr(pwzAppPool);
+    ReleaseStr(pwzLocationPath);
+    ReleaseObject(pSiteElem);
+    ReleaseObject(pAppElement);
+
+    return hr;
+}
+//-------------------------------------------------------------------------------------------------
+// IIS7VDir
+//  Processes VDir CA Data
+//
+//
+//-------------------------------------------------------------------------------------------------
+HRESULT IIS7VDir(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr)
+{
+    HRESULT hr = S_OK;
+
+    int iAction = -1;
+    BOOL fSiteFound = FALSE;
+    BOOL fAppFound = FALSE;
+
+    LPWSTR pwzSiteName = NULL;
+    LPWSTR pwzVDirPath = NULL;
+    LPWSTR pwzVDirPhyDir = NULL;
+    LPCWSTR pwzVDirSubPath = NULL;
+
+    IAppHostElement *pSiteElem = NULL;
+    IAppHostElement *pAppElement = NULL;
+    IAppHostElementCollection *pElement = NULL;
+
+    // Get Application action
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+    ExitOnFailure(hr, "Failed to read VDir action");
+
+    //get site key name
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
+    ExitOnFailure(hr, "Failed to read site key");
+    //get VDir path
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzVDirPath);
+    ExitOnFailure(hr, "Failed to read VDir key");
+    //get physical dir path
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzVDirPhyDir);
+    ExitOnFailure(hr, "Failed to read VDirPath key");
+
+    //Get site if it exists
+    hr = GetSiteElement(pAdminMgr, pwzSiteName, &pSiteElem, &fSiteFound);
+    ExitOnFailure(hr, "Failed to read sites from config");
+
+    if (IIS_CREATE == iAction)
+    {
+        if (fSiteFound)
+        {
+            //have site get application
+            hr = GetApplicationElementForVDir( pSiteElem,
+                                               pwzVDirPath,
+                                               &pAppElement,
+                                               &pwzVDirSubPath,
+                                               &fAppFound);
+            ExitOnFailure(hr, "Error reading application element from config");
+
+            if (!fAppFound)
+            {
+                // need application to add vDir
+                hr = E_FILENOTFOUND;
+                ExitOnFailure(hr, "Error application not found for create VDir");
+            }
+            //
+            // create the virDir
+            //
+            hr = CreateVdir(pAppElement, pwzVDirSubPath, pwzVDirPhyDir);
+            ExitOnFailure(hr, "Failed to create vdir for application");
+        }
+        else
+        {
+            hr = E_FILENOTFOUND;
+            ExitOnFailure(hr, "IIS: site not found for create VDir");
+        }
+    }
+    else if (IIS_DELETE == iAction)
+    {
+        if (fSiteFound)
+        {
+            //have site get application
+            hr = GetApplicationElementForVDir( pSiteElem,
+                                               pwzVDirPath,
+                                               &pAppElement,
+                                               &pwzVDirSubPath,
+                                               &fAppFound);
+            ExitOnFailure(hr, "Error reading application from config")
+            if (fAppFound)
+            {
+                //delete vdir
+                hr = DeleteVdir(pAppElement, pwzVDirSubPath);
+                ExitOnFailure(hr, "Unable to delete vdir for application");
+            }
+        }
+    }
+
+ LExit:
+    ReleaseStr(pwzSiteName);
+    ReleaseStr(pwzVDirPath);
+    ReleaseStr(pwzVDirPhyDir);
+    ReleaseObject(pSiteElem);
+    ReleaseObject(pAppElement);
+    ReleaseObject(pElement);
+
+    return hr;
+}
+
+//-------------------------------------------------------------------------------------------------
+// IIS7Binding
+//  Processes Bindings CA Data
+//
+//
+//-------------------------------------------------------------------------------------------------
+HRESULT IIS7Binding(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr)
+{
+    HRESULT hr = S_OK;
+
+    int iAction = -1;
+    BOOL fSiteFound = FALSE;
+
+    LPWSTR pwzSiteName = NULL;
+    LPWSTR pwzProtocol = NULL;
+    LPWSTR pwzInfo = NULL;
+
+    IAppHostElement *pSiteElem = NULL;
+
+    // Get Application action
+    hr = WcaReadIntegerFromCaData( ppwzCustomActionData, &iAction);
+    ExitOnFailure(hr, "Failed to read binding action");
+
+    //get site key name
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
+    ExitOnFailure(hr, "Failed to read binding site name key");
+
+    //get binding protocol
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzProtocol);
+    ExitOnFailure(hr, "Failed to read binding protocol");
+
+    //get binding info
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzInfo);
+    ExitOnFailure(hr, "Failed to read binding info");
+
+    //Get site if it exists
+    hr = GetSiteElement(pAdminMgr, pwzSiteName, &pSiteElem, &fSiteFound);
+    ExitOnFailure(hr, "Failed to read sites from config");
+
+    if (IIS_CREATE == iAction)
+    {
+        if (fSiteFound)
+        {
+            //add binding
+            hr = CreateBinding(pSiteElem, pwzProtocol, pwzInfo);
+            ExitOnFailure(hr, "Failed to create site binding");
+        }
+        else
+        {
+            hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+            ExitOnFailure(hr, "Site not found for create binding");
+        }
+    }
+    else if (IIS_DELETE == iAction)
+    {
+        if (fSiteFound)
+        {
+            //delete binding
+            hr = DeleteBinding(pSiteElem, pwzProtocol, pwzInfo);
+            ExitOnFailure(hr, "Failed to delete binding");
+        }
+    }
+
+ LExit:
+    ReleaseStr(pwzSiteName);
+    ReleaseStr(pwzProtocol);
+    ReleaseStr(pwzInfo);
+    ReleaseObject(pSiteElem);
+
+    return hr;
+}
+//-------------------------------------------------------------------------------------------------
+// IIS7Binding
+//  Processes WebLog CA Data
+//
+//
+//-------------------------------------------------------------------------------------------------
+HRESULT IIS7WebLog(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr)
+{
+    HRESULT hr = S_OK;
+
+    BOOL fSiteFound = FALSE;
+
+    LPWSTR pwzSiteName = NULL;
+    LPWSTR pwzLogFormat = NULL;
+
+    IAppHostElement *pSiteElem = NULL;
+
+    //get site key name
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
+    ExitOnFailure(hr, "Failed to read web log site name key");
+
+    //get log format
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzLogFormat);
+    ExitOnFailure(hr, "Failed to read web log protocol");
+
+    //Get site if it exists
+    hr = GetSiteElement(pAdminMgr, pwzSiteName, &pSiteElem, &fSiteFound);
+    ExitOnFailure(hr, "Failed to read web log sites from config");
+
+    if (fSiteFound)
+    {
+        //add log format
+        hr = CreateWebLog(pSiteElem, pwzLogFormat);
+        ExitOnFailure(hr, "Failed to create weblog file format");
+    }
+    else
+    {
+        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+        ExitOnFailure(hr, "Site not found for create weblog file format");
+    }
+
+ LExit:
+    ReleaseStr(pwzSiteName);
+    ReleaseStr(pwzLogFormat);
+    ReleaseObject(pSiteElem);
+
+    return hr;
+}
+//-------------------------------------------------------------------------------------------------
+// IIS7AppPool
+//  Processes AppPool CA Data
+//
+//
+//-------------------------------------------------------------------------------------------------
+HRESULT IIS7AppPool(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    )
+{
+    HRESULT hr = S_OK;
+
+    int iAction = -1;
+
+    LPWSTR pwzAppPoolName = NULL;
+
+    // Get AppPool action
+    hr = WcaReadIntegerFromCaData( ppwzCustomActionData, &iAction);
+    ExitOnFailure(hr, "Failed to read AppPool action");
+
+    //get appPool name
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzAppPoolName);
+    ExitOnFailure(hr, "Failed to read AppPool name key");
+
+    switch (iAction)
+    {
+        case IIS_CREATE :
+        {
+            hr = CreateAppPool(ppwzCustomActionData, pAdminMgr, pwzAppPoolName);
+            break;
+        }
+        case IIS_DELETE:
+        {
+            hr = DeleteAppPool(pAdminMgr, pwzAppPoolName);
+            break;
+        }
+        default:
+            ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for appPool");
+            break;
+    }
+
+LExit:
+    ReleaseStr(pwzAppPoolName);
+    return hr;
+}
+
+//-------------------------------------------------------------------------------------------------
+// IIS7AppExtension
+//  Processes AppExtension (config handlers) CA Data
+//
+//
+//-------------------------------------------------------------------------------------------------
+HRESULT IIS7AppExtension(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr)
+{
+   HRESULT hr = S_OK;
+
+   LPWSTR pwzWebName = NULL;
+   LPWSTR pwzWebRoot = NULL;
+   LPWSTR pwzData = NULL;
+   LPWSTR pwzConfigPath = NULL;
+   LPWSTR pwzHandlerName = NULL;
+   LPWSTR pwzPath = NULL;
+   int iAction = -1;
+
+   IAppHostElement *pSection = NULL;
+   IAppHostElement *pElement = NULL;
+   IAppHostElementCollection *pCollection = NULL;
+
+   BOOL fFound = FALSE;
+   DWORD cHandlers = 1000;
+
+    //get web name
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzWebName);
+    ExitOnFailure(hr, "Failed to read appExt Web name key");
+
+    //get root name
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzWebRoot);
+    ExitOnFailure(hr, "Failed to read appExt Web name key");
+
+    //Construct config root
+    hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s", IIS_CONFIG_APPHOST_ROOT, pwzWebName);
+    ExitOnFailure(hr, "failed to format appext config path");
+    //
+    //Do not append trailing '/' for default vDir
+    //
+    if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzWebRoot, -1, L"/", -1))
+    {
+        hr = StrAllocConcat(&pwzConfigPath, L"/", 0);
+        ExitOnFailure(hr, "failed to copy appext config path delim");
+        hr = StrAllocConcat(&pwzConfigPath, pwzWebRoot, 0);
+        ExitOnFailure(hr, "failed to copy appext config path root name");
+    }
+    //get admin handlers section at config path location tag
+    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_HANDLERS_SECTION), pwzConfigPath, &pSection);
+    ExitOnFailure(hr, "Failed get appext section");
+
+    if (!pSection)
+    {
+        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+        ExitOnFailure(hr, "Failed get appext section object");
+    }
+
+    // Get AppExt action
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+    ExitOnFailure(hr, "Failed to read appExt action");
+
+    hr = pSection->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get handlers collection for appext");
+
+    while (IIS_APPEXT_END != iAction)
+    {
+        fFound = FALSE;
+
+        //Process property action
+        switch (iAction)
+        {
+            case IIS_APPEXT :
+            {
+                // These IDs aren't really stable but this is stable enough to support repair since the MSI won't change
+                hr = StrAllocFormatted(&pwzHandlerName, L"MsiCustom-%u", ++cHandlers);
+                ExitOnFailure(hr, "Failed increment handler name");
+
+                hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_ADD, IIS_CONFIG_NAME, pwzHandlerName, &pElement, NULL);
+                ExitOnFailure(hr, "Failed to find mimemap extension");
+
+                fFound = (NULL != pElement);
+                if (!fFound)
+                {
+                    //create new handler element
+                    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pElement);
+                    ExitOnFailure(hr, "Failed get create handler element for appext");
+
+                    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_NAME, pwzHandlerName);
+                    ExitOnFailure(hr, "Failed set appext name property");
+                }
+
+                //BUGBUG: For compat we are assuming these are all ISAPI MODULES so we are
+                //setting the modules property to IsapiModule.
+                //Currently can't deal with handlers of different module types.
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_MODULES, L"IsapiModule");
+                ExitOnFailure(hr, "Failed set site appExt path property");
+
+                //get extension (path)
+                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+                ExitOnFailure(hr, "Failed to read appExt extension");
+                hr = StrAllocFormatted(&pwzPath, L"*.%s", pwzData);
+                ExitOnFailure(hr, "Failed decorate appExt path");
+                //put property
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PATH, pwzPath);
+                ExitOnFailure(hr, "Failed set site appExt path property");
+
+                //get executable
+                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+                ExitOnFailure(hr, "Failed to read appExt executable");
+                //put property
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_EXECUTABLE, pwzData);
+                ExitOnFailure(hr, "Failed set site appExt executable property");
+
+                //get verbs
+                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+                ExitOnFailure(hr, "Failed to read appExt verbs");
+                //put property
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_VERBS, pwzData);
+                ExitOnFailure(hr, "Failed set site appExt verbs property");
+
+                break;
+            }
+            default:
+            {
+                ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for AppExt");
+                break;
+            }
+        }
+
+        if (!fFound)
+        {
+            //  put handler element at beginning of list
+            hr = pCollection->AddElement(pElement, 0);
+            ExitOnFailure(hr, "Failed add handler element for appext");
+        }
+
+        ReleaseNullObject(pElement);
+
+        // Get AppExt action
+        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+        ExitOnFailure(hr, "Failed to read AppPool Property action");
+    }
+
+LExit:
+    ReleaseStr(pwzWebName);
+    ReleaseStr(pwzWebRoot);
+    ReleaseStr(pwzData);
+    ReleaseStr(pwzConfigPath);
+    ReleaseStr(pwzHandlerName);
+    ReleaseStr(pwzPath);
+    ReleaseObject(pSection);
+    ReleaseObject(pElement);
+    ReleaseObject(pCollection);
+
+    return hr;
+}
+
+//-------------------------------------------------------------------------------------------------
+// IIS7MimeMap
+//  Processes Mime Map (config handlers) CA Data
+//
+//
+//-------------------------------------------------------------------------------------------------
+ HRESULT IIS7MimeMap(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    )
+{
+    HRESULT hr = S_OK;
+    LPWSTR pwzConfigPath = NULL;
+    LPWSTR pwzWebName = NULL;
+    LPWSTR pwzWebRoot = NULL;
+    LPWSTR pwzData = NULL;
+    int iAction = -1;
+
+    IAppHostElement *pSection = NULL;
+    IAppHostElement *pElement = NULL;
+    IAppHostElementCollection *pCollection = NULL;
+
+    BOOL fFound = FALSE;
+
+    //get web name
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzWebName);
+    ExitOnFailure(hr, "Failed to read mime map Web name key");
+
+    //get vdir root name
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzWebRoot);
+    ExitOnFailure(hr, "Failed to read vdir root name key");
+
+    //Construct config root
+    hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s",  IIS_CONFIG_APPHOST_ROOT, pwzWebName);
+    ExitOnFailure(hr, "failed to format mime map config path web name");
+    //
+    //Do not append trailing '/' for default vDir
+    //
+    if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzWebRoot, -1, L"/", -1))
+    {
+        hr = StrAllocConcat(&pwzConfigPath, L"/", 0);
+        ExitOnFailure(hr, "failed to copy appext config path delim");
+        hr = StrAllocConcat(&pwzConfigPath, pwzWebRoot, 0);
+        ExitOnFailure(hr, "failed to copy appext config path root name");
+    }
+
+    //get admin section <staticContent> at config path location tag
+    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_STATICCONTENT_SECTION), pwzConfigPath, &pSection);
+    ExitOnFailure(hr, "Failed get staticContent section for mimemap");
+
+    if (!pSection)
+    {
+        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+        ExitOnFailure(hr, "Failed get staticContent section object");
+    }
+
+    // Get mimemap action
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+    ExitOnFailure(hr, "Failed to read mimemap action");
+
+    hr = pSection->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get staticContent collection for mimemap");
+
+    while (IIS_MIMEMAP_END != iAction)
+    {
+        //Process property action
+        switch (iAction)
+        {
+            case IIS_MIMEMAP :
+            {
+                //get extension
+                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+                ExitOnFailure(hr, "Failed to read mimemap extension");
+
+                hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_MIMEMAP, IIS_CONFIG_FILEEXT, pwzData, &pElement, NULL);
+                ExitOnFailure(hr, "Failed to find mimemap extension");
+                fFound = (NULL != pElement);
+
+                if (!fFound)
+                {
+                    //create new mimeMap element
+                    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_MIMEMAP), &pElement);
+                    ExitOnFailure(hr, "Failed get create MimeMap element");
+                }
+
+                //put property
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_FILEEXT, pwzData);
+                ExitOnFailure(hr, "Failed set mimemap extension property");
+
+                //get type
+                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+                ExitOnFailure(hr, "Failed to read mimemap type");
+                //put property
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_MIMETYPE, pwzData);
+                ExitOnFailure(hr, "Failed set mimemap type property");
+
+                break;
+            }
+            default:
+            {
+                ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for mimeMap");
+                break;
+            }
+        }
+
+        if (!fFound)
+        {
+            //  put mimeMap element at beginning of list
+            hr = pCollection->AddElement(pElement, -1);
+            ExitOnFailure(hr, "Failed add mimemap");
+        }
+
+        // Get AppExt action
+        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+        ExitOnFailure(hr, "Failed to read mimemap action");
+
+        ReleaseNullObject(pElement);
+    }
+
+LExit:
+    ReleaseStr(pwzConfigPath);
+    ReleaseStr(pwzWebName);
+    ReleaseStr(pwzWebRoot);
+    ReleaseStr(pwzData);
+    ReleaseObject(pSection);
+    ReleaseObject(pElement);
+    ReleaseObject(pCollection);
+
+    return hr;
+}
+
+//-------------------------------------------------------------------------------------------------
+// IIS7DirProperties
+//  ProcessesVdir Properties  CA Data
+//
+//
+//-------------------------------------------------------------------------------------------------
+HRESULT IIS7DirProperties(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    )
+{
+    HRESULT hr = S_OK;
+    WCHAR wcTime[60];
+    LPWSTR pwzConfigPath = NULL;
+    LPWSTR pwzWebName = NULL;
+    LPWSTR pwzWebRoot = NULL;
+    LPWSTR pwzData = NULL;
+    int iAction = -1;
+    int iData   =  0;
+    DWORD dwData = 0;
+
+    IAppHostElement *pSection = NULL;
+    IAppHostElement *pElement = NULL;
+    IAppHostElementCollection *pCollection = NULL;
+
+    //get web name
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzWebName);
+    ExitOnFailure(hr, "Failed to read DirProp Web name key");
+
+    //get vdir root name
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzWebRoot);
+    ExitOnFailure(hr, "Failed to read DirProp Web name key");
+
+    //Construct config root
+    hr = StrAllocFormatted(&pwzConfigPath, L"%s/%s",  IIS_CONFIG_APPHOST_ROOT, pwzWebName);
+    ExitOnFailure(hr, "failed to format mime map config path web name");
+    //
+    //Do not append trailing '/' for default vDir
+    //
+    if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzWebRoot, -1, L"/", -1))
+    {
+        hr = StrAllocConcat(&pwzConfigPath, L"/", 0);
+        ExitOnFailure(hr, "failed to copy appext config path delim");
+        hr = StrAllocConcat(&pwzConfigPath, pwzWebRoot, 0);
+        ExitOnFailure(hr, "failed to copy appext config path root name");
+    }
+
+    // Get DirProps action
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+    ExitOnFailure(hr, "Failed to read DirProps action");
+
+    while (IIS_DIRPROP_END != iAction)
+    {
+        //Process property action
+        switch (iAction)
+        {
+            case IIS_DIRPROP_ACCESS :
+            {
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read DirProps access");
+                //iData contains bit flags for <handlers accessPolicy="">
+                //no translation required
+                //get admin section at config path location tag
+                hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_HANDLERS_SECTION), pwzConfigPath, &pSection);
+                ExitOnFailure(hr, "Failed get handlers section for DirProp");
+                if (!pSection)
+                {
+                    hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+                    ExitOnFailure(hr, "Failed get handlers section object for DirProps");
+                }
+                dwData = iData;
+                hr = Iis7PutPropertyInteger( pSection, L"accessPolicy", dwData);
+                ExitOnFailure(hr, "Failed set accessPolicy for DirProps");
+                ReleaseNullObject(pSection);
+                break;
+            }
+            case IIS_DIRPROP_USER :
+            {
+                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+                ExitOnFailure(hr, "Failed to read DirProps user");
+                hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/anonymousAuthentication"), pwzConfigPath, &pSection);
+                ExitOnFailure(hr, "Failed get AnonymousAuthentication section for DirProp");
+                hr = Iis7PutPropertyString( pSection, IIS_CONFIG_USERNAME, pwzData);
+                ExitOnFailure(hr, "Failed set accessPolicy for DirProps");
+                ReleaseNullObject(pSection);
+                break;
+            }
+            case IIS_DIRPROP_PWD :
+            {
+                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+                ExitOnFailure(hr, "Failed to read DirProps pwd");
+                hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/anonymousAuthentication"), pwzConfigPath, &pSection);
+                ExitOnFailure(hr, "Failed get AnonymousAuthentication section for DirProp");
+                hr = Iis7PutPropertyString( pSection, IIS_CONFIG_PASSWORD, pwzData);
+                ExitOnFailure(hr, "Failed set accessPolicy for DirProps");
+                ReleaseNullObject(pSection);
+                break;
+            }
+            case IIS_DIRPROP_DEFDOCS :
+            {
+                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+                ExitOnFailure(hr, "Failed to read DirProps def doc");
+                hr = SetDirPropDefDoc(pAdminMgr, pwzConfigPath, pwzData);
+                ExitOnFailure(hr, "Failed to set DirProps Default Documents");
+                break;
+            }
+            case IIS_DIRPROP_AUTH :
+            {
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read DirProps auth");
+                //iData contains bit flags for /security/authentication/<...>
+                // Anonymous    = 1
+                // Basic        = 2
+                // Windows      = 4
+                // Digest       =16
+                // Passport     =64  *not supported
+                //translation required from bit map to section
+                // E.G security/authentication/windowsAuthentication [property enabled true|false]
+                dwData= iData;
+                hr = SetDirPropAuthentications(pAdminMgr, pwzConfigPath, dwData);
+                ExitOnFailure(hr, "Failed set Authentication for DirProps");
+                break;
+            }
+            case IIS_DIRPROP_SSLFLAGS :
+            {
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read DirProps sslFlags");
+                //iData contains bit flags for /security/access sslFlags
+                //no translation required
+                hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/access"), pwzConfigPath, &pSection);
+                ExitOnFailure(hr, "Failed get security/access section for DirProp");
+                dwData = iData;
+                hr = Iis7PutPropertyInteger( pSection, L"sslFlags", dwData);
+                ExitOnFailure(hr, "Failed set security/access for DirProps");
+                ReleaseNullObject(pSection);
+                break;
+            }
+            case IIS_DIRPROP_AUTHPROVID :
+            {
+                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+                ExitOnFailure(hr, "Failed to read DirProps auth provider");
+                hr = SetDirPropAuthProvider(pAdminMgr, pwzConfigPath, pwzData);
+                ExitOnFailure(hr, "Failed to set DirProps auth provider");
+                break;
+            }
+            case IIS_DIRPROP_ASPERROR:
+            {
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read DirProps aspDetailedError");
+                hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_ASP_SECTION), pwzConfigPath, &pSection);
+                ExitOnFailure(hr, "Failed get asp section for DirProp");
+                hr = Iis7PutPropertyBool(pSection, IIS_CONFIG_SCRIPTERROR, iData);
+                ExitOnFailure(hr, "Failed to set DirProps aspDetailedError");
+                ReleaseNullObject(pSection);
+                break;
+            }
+            case IIS_DIRPROP_HTTPEXPIRES:
+            {
+                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+                ExitOnFailure(hr, "Failed to read DirProps httpExpires provider");
+                hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_STATICCONTENT_SECTION), pwzConfigPath, &pSection);
+                ExitOnFailure(hr, "Failed get staticContent section for DirProp");
+                hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_CLIENTCACHE), &pElement);
+                ExitOnFailure(hr, "Failed to get clientCache element");
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_HTTPEXPIRES, pwzData);
+                ExitOnFailure(hr, "Failed to set clientCache httpExpires value");
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_CACHECONTROLMODE, IIS_CONFIG_USEEXPIRES);
+                ExitOnFailure(hr, "Failed to set clientCache cacheControlMode value");
+                ReleaseNullObject(pSection);
+                ReleaseNullObject(pElement);
+                break;
+            }
+            case IIS_DIRPROP_MAXAGE:
+            {
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read DirProps httpExpires provider");
+                hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_STATICCONTENT_SECTION), pwzConfigPath, &pSection);
+                ExitOnFailure(hr, "Failed get staticContent section for DirProp");
+                hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_CLIENTCACHE), &pElement);
+                ExitOnFailure(hr, "Failed to get clientCache element");
+                *wcTime = '\0';
+                ConvSecToDHMS(iData, wcTime, countof(wcTime));
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_MAXAGE, wcTime);
+                ExitOnFailure(hr, "Failed to set clientCache maxAge value");
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_CACHECONTROLMODE, IIS_CONFIG_USEMAXAGE);
+                ExitOnFailure(hr, "Failed to set clientCache cacheControlMode value");
+                ReleaseNullObject(pSection);
+                ReleaseNullObject(pElement);
+                break;
+            }
+            case IIS_DIRPROP_CACHECUST:
+            {
+                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+                ExitOnFailure(hr, "Failed to read DirProps cacheControlCustom");
+                hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_STATICCONTENT_SECTION), pwzConfigPath, &pSection);
+                ExitOnFailure(hr, "Failed get staticContent section for DirProp");
+                hr = pSection->GetElementByName(ScopeBSTR(IIS_CONFIG_CLIENTCACHE), &pElement);
+                ExitOnFailure(hr, "Failed to get clientCache element");
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_CACHECUST, pwzData);
+                ExitOnFailure(hr, "Failed to set clientCache cacheControlCustom value");
+                ReleaseNullObject(pSection);
+                ReleaseNullObject(pElement);
+                break;
+            }
+            case IIS_DIRPROP_NOCUSTERROR:
+            {
+                //no value, if have ID tag write clear to system.webServer/httpErrors
+                //error collection
+                hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_HTTPERRORS_SECTION), pwzConfigPath, &pSection);
+                ExitOnFailure(hr, "Failed get httperrors section for DirProp");
+                hr = pSection->get_Collection(&pCollection);
+                ExitOnFailure(hr, "Failed get error collection for DirProp");
+                hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_CLEAR), &pElement);
+                ExitOnFailure(hr, "Failed to create clear element for error collection for DirProp");
+                hr = pCollection->AddElement(pElement);
+                ExitOnFailure(hr, "Failed to add lear element for error collection for DirProp");
+                ReleaseNullObject(pSection);
+                ReleaseNullObject(pElement);
+                break;
+            }
+            case IIS_DIRPROP_LOGVISITS:
+            {
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read DirProps logVisits");
+                hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_HTTPLOGGING_SECTION), pwzConfigPath, &pSection);
+                ExitOnFailure(hr, "Failed get httpLogging section for DirProp");
+                hr = Iis7PutPropertyBool(pSection, IIS_CONFIG_DONTLOG, iData);
+                ExitOnFailure(hr, "Failed to set DirProps aspDetailedError");
+                ReleaseNullObject(pSection);
+                break;
+            }
+            default:
+            {
+                ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for WebDirProperties");
+                break;
+            }
+        }
+
+        // Get AppExt action
+        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+        ExitOnFailure(hr, "Failed to read DirProps Property action");
+    }
+LExit:
+    ReleaseStr(pwzConfigPath);
+    ReleaseStr(pwzWebName);
+    ReleaseStr(pwzWebRoot);
+    ReleaseStr(pwzData);
+    ReleaseObject(pSection);
+    ReleaseObject(pElement);
+    ReleaseObject(pCollection);
+
+    return hr;
+}
+
+//-------------------------------------------------------------------------------------------------
+// IIS7SslBinding
+//  ProcessesVdir Properties  CA Data
+//
+//
+//-------------------------------------------------------------------------------------------------
+HRESULT IIS7SslBinding(
+    __inout  LPWSTR *ppwzCustomActionData,
+    __in     IAppHostWritableAdminManager *pAdminMgr
+    )
+{
+    HRESULT hr = S_OK;
+    int iAction = -1;
+    BOOL fSiteFound = FALSE;
+
+    LPWSTR pwzSiteName = NULL;
+    LPWSTR pwzStoreName = NULL;
+    LPWSTR pwzEncodedCertificateHash = NULL;
+
+    IAppHostElement *pSiteElem = NULL;
+
+    // Get Application action
+    hr = WcaReadIntegerFromCaData( ppwzCustomActionData, &iAction);
+    ExitOnFailure(hr, "Failed to read binding action");
+
+    //get site key name
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzSiteName);
+    ExitOnFailure(hr, "Failed to read binding site name key");
+
+    //get binding protocol
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzStoreName);
+    ExitOnFailure(hr, "Failed to read binding protocol");
+
+    //get binding info
+    hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzEncodedCertificateHash);
+    ExitOnFailure(hr, "Failed to read binding info");
+
+    //Get site if it exists
+    hr = GetSiteElement(pAdminMgr, pwzSiteName, &pSiteElem, &fSiteFound);
+    ExitOnFailure(hr, "Failed to read sites from config");
+
+    if (IIS_CREATE == iAction)
+    {
+        if (fSiteFound)
+        {
+            //add SSL cert to binding
+            hr = CreateSslBinding(pSiteElem, pwzStoreName, pwzEncodedCertificateHash);
+            ExitOnFailure(hr, "Failed to create site binding");
+        }
+        else
+        {
+            hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+            ExitOnFailure(hr, "Site not found for create binding");
+        }
+    }
+    else if (IIS_DELETE == iAction)
+    {
+        if (fSiteFound)
+        {
+            //delete binding
+            hr = DeleteSslBinding(pSiteElem, pwzStoreName, pwzEncodedCertificateHash);
+            ExitOnFailure(hr, "Failed to delete binding");
+        }
+    }
+
+ LExit:
+    ReleaseStr(pwzSiteName);
+    ReleaseStr(pwzStoreName);
+    ReleaseStr(pwzEncodedCertificateHash);
+    ReleaseObject(pSiteElem);
+
+    return hr;
+}
+
+//-------------------------------------------------------------------------------------------------
+// Helper Functions
+//
+//
+//
+//-------------------------------------------------------------------------------------------------
+
+static HRESULT GetNextAvailableSiteId(
+    IAppHostElementCollection *pCollection,
+    DWORD *plSiteId
+    )
+{
+   HRESULT hr = S_OK;
+   IAppHostElement *pElement = NULL;
+   IAppHostProperty *pProperty = NULL;
+
+   DWORD cSites;
+   DWORD plNextAvailSite  = 0;
+   VARIANT vPropValue;
+   VARIANT vtIndex;
+
+   VariantInit(&vPropValue);
+   VariantInit(&vtIndex);
+
+   *plSiteId = 0;
+
+    hr = pCollection->get_Count(&cSites);
+    ExitOnFailure(hr, "Failed get sites collection count");
+
+    vtIndex.vt = VT_UI4;
+    for (DWORD i = 0; i < cSites; ++i)
+    {
+        vtIndex.ulVal = i;
+        hr = pCollection->get_Item(vtIndex , &pElement);
+        ExitOnFailure(hr, "Failed get sites collection item");
+
+        hr = pElement->GetPropertyByName(ScopeBSTR(IIS_CONFIG_ID), &pProperty);
+        ExitOnFailure(hr, "Failed get site property");
+
+        hr = pProperty->get_Value(&vPropValue);
+        ExitOnFailure(hr, "Failed get site property value");
+
+        *plSiteId = vPropValue.lVal;
+        if (*plSiteId > plNextAvailSite)
+        {
+            plNextAvailSite = *plSiteId;
+        }
+        ReleaseNullObject(pElement);
+        ReleaseNullObject(pProperty);
+    }
+    *plSiteId = ++plNextAvailSite;
+
+LExit:
+    ReleaseVariant(vPropValue);
+    ReleaseVariant(vtIndex);
+
+    ReleaseObject(pElement);
+    ReleaseObject(pProperty);
+
+    return hr;
+}
+
+static HRESULT GetSiteElement(
+    IAppHostWritableAdminManager *pAdminMgr,
+    LPCWSTR swSiteName,
+    IAppHostElement **ppSiteElement,
+    BOOL* fFound
+    )
+{
+   HRESULT hr = S_OK;
+   IAppHostElement *pSites = NULL;
+   IAppHostElementCollection *pCollection = NULL;
+
+   *fFound = FALSE;
+
+    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_SITES_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pSites);
+    ExitOnFailure(hr, "Failed get sites section");
+    ExitOnNull(pSites, hr, ERROR_FILE_NOT_FOUND, "Failed get sites section object");
+
+    hr = pSites->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get sites collection");
+
+    hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_SITE, IIS_CONFIG_NAME, swSiteName, ppSiteElement, NULL);
+    ExitOnFailure(hr, "Failed to find site %ls", swSiteName);
+
+    *fFound = ppSiteElement != NULL && *ppSiteElement != NULL;
+
+LExit:
+    ReleaseObject(pSites);
+    ReleaseObject(pCollection);
+
+    return hr;
+}
+
+static HRESULT GetApplicationElement( IAppHostElement *pSiteElement,
+                                      LPCWSTR swAppPath,
+                                      IAppHostElement **ppAppElement,
+                                      BOOL* fFound)
+{
+   HRESULT hr = S_OK;
+   IAppHostElementCollection *pCollection = NULL;
+
+   *fFound = FALSE;
+
+    hr = pSiteElement->get_Collection( &pCollection);
+    ExitOnFailure(hr, "Failed get site app collection");
+
+    hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_APPLICATION, IIS_CONFIG_PATH, swAppPath, ppAppElement, NULL);
+    ExitOnFailure(hr, "Failed to find app %ls", swAppPath);
+
+    *fFound = ppAppElement != NULL && *ppAppElement != NULL;
+
+LExit:
+    ReleaseObject(pCollection);
+
+    return hr;
+}
+
+static HRESULT GetApplicationElementForVDir( IAppHostElement *pSiteElement,
+                                             LPCWSTR pwzVDirPath,
+                                             IAppHostElement **ppAppElement,
+                                             LPCWSTR *ppwzVDirSubPath,
+                                             BOOL* fFound)
+{
+    HRESULT hr = S_OK;
+    IAppHostElementCollection *pCollection = NULL;
+    LPWSTR pwzAppPath = NULL;
+    *fFound = FALSE;
+    *ppwzVDirSubPath = NULL;
+
+    hr = pSiteElement->get_Collection( &pCollection);
+    ExitOnFailure(hr, "Failed get site app collection");
+
+    // Start with full path
+    int iLastPathIndex = lstrlenW(pwzVDirPath) - 1;
+    hr = StrAllocString(&pwzAppPath, pwzVDirPath, 0);
+    ExitOnFailure(hr, "Failed allocate application path");
+
+    for (int iSubPathIndex = iLastPathIndex; (iSubPathIndex >= 0) && (!*fFound); --iSubPathIndex)
+    {
+        // We are looking at the full path, or at a directory boundary, or at the root
+        if (iSubPathIndex == iLastPathIndex ||
+            '/' == pwzAppPath[iSubPathIndex] ||
+            0 == iSubPathIndex)
+        {
+            // break the path if needed
+            if ('/' == pwzAppPath[iSubPathIndex])
+            {
+                pwzAppPath[iSubPathIndex] = '\0';
+            }
+
+            // Special case for root path, need an empty app path
+            LPCWSTR pwzAppSearchPath = 0 == iSubPathIndex ? L"/" : pwzAppPath;
+
+            // Try to find an app with the specified path
+            hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_APPLICATION, IIS_CONFIG_PATH, pwzAppSearchPath, ppAppElement, NULL);
+            ExitOnFailure(hr, "Failed to search for app %ls", pwzAppSearchPath);
+            *fFound = ppAppElement != NULL && *ppAppElement != NULL;
+
+            if (*fFound)
+            {
+                // set return value for sub path
+                // special case for app path == vdir path, need an empty subpath.
+                *ppwzVDirSubPath = (iSubPathIndex == iLastPathIndex) ? L"/" : pwzVDirPath + iSubPathIndex;
+            }
+        }
+    }
+
+LExit:
+    ReleaseObject(pCollection);
+    ReleaseStr(pwzAppPath);
+
+    return hr;
+}
+
+static HRESULT CreateSite(
+    __in IAppHostElementCollection *pCollection,
+    __in LPCWSTR swSiteName,
+    __out IAppHostElement **pSiteElement
+    )
+{
+    HRESULT hr = S_OK;
+    IAppHostElement *pNewElement = NULL;
+
+    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_SITE), &pNewElement);
+    ExitOnFailure(hr, "Failed create site element");
+
+    hr = Iis7PutPropertyString(pNewElement, IIS_CONFIG_NAME, swSiteName);
+    ExitOnFailure(hr, "Failed set site name property");
+
+    DWORD lSiteId = 0;
+    hr = GetNextAvailableSiteId(pCollection, &lSiteId);
+    ExitOnFailure(hr, "Failed get next site id");
+
+    Iis7PutPropertyInteger(pNewElement, IIS_CONFIG_ID, lSiteId);
+    ExitOnFailure(hr, "Failed set site id property");
+
+    hr = pCollection->AddElement(pNewElement);
+    ExitOnFailure(hr, "Failed add site element");
+
+    *pSiteElement = pNewElement;
+    pNewElement = NULL;
+
+LExit:
+    ReleaseObject(pNewElement);
+
+    return hr;
+}
+
+static HRESULT CreateApplication(
+    IAppHostElement *pSiteElement,
+    LPCWSTR swAppPath,
+    IAppHostElement **pAppElement
+    )
+{
+    HRESULT hr = S_OK;
+    IAppHostElement *pNewElement = NULL;
+    IAppHostElementCollection *pCollection = NULL;
+
+    hr = pSiteElement->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get application collection");
+
+    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_APPLICATION), &pNewElement);
+    ExitOnFailure(hr, "Failed get application element");
+
+    hr = Iis7PutPropertyString(pNewElement, IIS_CONFIG_PATH, swAppPath);
+    ExitOnFailure(hr, "Failed set application path property");
+
+    hr = pCollection->AddElement(pNewElement);
+    ExitOnFailure(hr, "Failed add application to collection");
+
+    *pAppElement = pNewElement;
+    pNewElement = NULL;
+
+LExit:
+    ReleaseObject(pCollection);
+    ReleaseObject(pNewElement);
+
+    return hr;
+}
+
+static HRESULT DeleteApplication(
+    IAppHostElement *pSiteElement,
+    LPCWSTR swAppPath
+    )
+{
+    HRESULT hr = S_OK;
+    IAppHostElementCollection *pCollection = NULL;
+
+    hr = pSiteElement->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get application collection");
+
+    hr = DeleteCollectionElement(pCollection, IIS_CONFIG_APPLICATION, IIS_CONFIG_PATH, swAppPath);
+    ExitOnFailure(hr, "Failed to delete website");
+
+LExit:
+    ReleaseObject(pCollection);
+
+    return hr;
+}
+
+static HRESULT SetAppPool(
+    IAppHostElement *pAppElement,
+    LPCWSTR pwzAppPool
+    )
+{
+    HRESULT hr = S_OK;
+
+    if (*pwzAppPool != 0)
+    {
+        hr = Iis7PutPropertyString(pAppElement, IIS_CONFIG_APPPOOL, pwzAppPool);
+        ExitOnFailure(hr, "Failed set application appPool property");
+    }
+LExit:
+    return hr;
+}
+
+static HRESULT CreateVdir(
+    IAppHostElement *pAppElement,
+    LPCWSTR pwzVDirPath,
+    LPCWSTR pwzVDirPhyDir
+    )
+{
+    HRESULT hr = S_OK;
+    IAppHostElement *pElement = NULL;
+    IAppHostElementCollection *pCollection = NULL;
+    BOOL fFound;
+
+    hr = pAppElement->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get application VDir collection");
+
+    hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_VDIR, IIS_CONFIG_PATH, pwzVDirPath, &pElement, NULL);
+    ExitOnFailure(hr, "Failed while finding virtualDir");
+    fFound = (NULL != pElement);
+
+    if (!fFound)
+    {
+        hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_VDIR), &pElement);
+        ExitOnFailure(hr, "Failed create application VDir collection");
+
+        hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PATH, pwzVDirPath);
+        ExitOnFailure(hr, "Failed set VDir path property");
+    }
+
+    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PHYSPATH, pwzVDirPhyDir);
+    ExitOnFailure(hr, "Failed set VDir phys path property");
+
+    if (!fFound)
+    {
+        hr = pCollection->AddElement(pElement);
+        ExitOnFailure(hr, "Failed add application VDir element");
+    }
+
+LExit:
+    ReleaseObject(pCollection);
+    ReleaseObject(pElement);
+
+    return hr;
+}
+
+static HRESULT DeleteVdir(
+    IAppHostElement *pAppElement,
+    LPCWSTR pwzVDirPath
+    )
+{
+    HRESULT hr = S_OK;
+    IAppHostElementCollection *pCollection = NULL;
+
+    hr = pAppElement->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get application VDir collection");
+
+    hr = DeleteCollectionElement(pCollection, IIS_CONFIG_VDIR, IIS_CONFIG_PATH, pwzVDirPath);
+    ExitOnFailure(hr, "Failed to delete vdir");
+
+LExit:
+    ReleaseObject(pCollection);
+
+    return hr;
+}
+
+static HRESULT CreateBinding(
+    IAppHostElement *pSiteElem,
+    LPCWSTR pwzProtocol,
+    LPCWSTR pwzInfo
+    )
+{
+    HRESULT hr = S_OK;
+    IAppHostChildElementCollection *pChildElems = NULL;
+    IAppHostElement *pBindings = NULL;
+    IAppHostElement *pBindingElement = NULL;
+    IAppHostElementCollection *pCollection = NULL;
+
+    VARIANT vtProp;
+
+    VariantInit(&vtProp);
+
+    hr = pSiteElem->get_ChildElements(&pChildElems);
+    ExitOnFailure(hr, "Failed get site child elements collection");
+
+    vtProp.vt = VT_BSTR;
+    vtProp.bstrVal = ::SysAllocString(IIS_CONFIG_BINDINGS);
+    hr = pChildElems->get_Item(vtProp, &pBindings);
+    ExitOnFailure(hr, "Failed get bindings element");
+    ReleaseVariant(vtProp);
+
+    hr = pBindings->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get bindings collection");
+
+    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_BINDING), &pBindingElement);
+    ExitOnFailure(hr, "Failed get binding element");
+
+    hr = Iis7PutPropertyString(pBindingElement, IIS_CONFIG_PROTOCOL, pwzProtocol);
+    ExitOnFailure(hr, "Failed set binding protocol property");
+
+    hr = Iis7PutPropertyString(pBindingElement, IIS_CONFIG_BINDINGINFO, pwzInfo);
+    ExitOnFailure(hr, "Failed set binding information property");
+
+    hr = pCollection->AddElement(pBindingElement);
+    if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS))
+    {
+        //Eat this error. Binding is there and nothing to repair since
+        //identity == protocol + info so all is OK
+        hr = S_OK;
+    }
+    else
+    {
+        ExitOnFailure(hr, "Failed add binding to site");
+    }
+
+LExit:
+    ReleaseVariant(vtProp);
+
+    ReleaseObject(pCollection);
+    ReleaseObject(pChildElems);
+    ReleaseObject(pBindingElement);
+    ReleaseObject(pBindings);
+
+    return hr;
+}
+static HRESULT CreateWebLog(
+    IAppHostElement *pSiteElem,
+    LPCWSTR pwzFormat
+    )
+{
+    HRESULT hr = S_OK;
+    IAppHostChildElementCollection *pChildElems = NULL;
+    IAppHostElement *pLogFile = NULL;
+
+    VARIANT vtProp;
+
+    VariantInit(&vtProp);
+
+    hr = pSiteElem->get_ChildElements(&pChildElems);
+    ExitOnFailure(hr, "Failed get site child elements collection");
+
+    vtProp.vt = VT_BSTR;
+    vtProp.bstrVal = ::SysAllocString(IIS_CONFIG_WEBLOG);
+    hr = pChildElems->get_Item(vtProp, &pLogFile);
+    ExitOnFailure(hr, "Failed get logfile element");
+    ReleaseVariant(vtProp);
+
+    if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pwzFormat, -1, L"none", -1))
+    {
+        hr = Iis7PutPropertyString(pLogFile, IIS_CONFIG_LOGFORMAT, pwzFormat);
+        ExitOnFailure(hr, "Failed set logfile format property");
+        hr = Iis7PutPropertyString(pLogFile, IIS_CONFIG_ENABLED, IIS_CONFIG_TRUE);
+        ExitOnFailure(hr, "Failed set logfile enabled property");
+    }
+    else
+    {
+        hr = Iis7PutPropertyString(pLogFile, IIS_CONFIG_ENABLED, IIS_CONFIG_FALSE);
+        ExitOnFailure(hr, "Failed set logfile enabled property");
+    }
+
+LExit:
+    ReleaseVariant(vtProp);
+
+    ReleaseObject(pLogFile);
+    ReleaseObject(pChildElems);
+
+    return hr;
+}
+
+static HRESULT DeleteBinding(
+    IAppHostElement* /*pSiteElem*/,
+    LPCWSTR /*pwzProtocol*/,
+    LPCWSTR /*pwzInfo*/
+    )
+{
+    HRESULT hr = S_OK;
+    //
+    //this isn't supported right now, we should support this for the SiteSearch scenario
+    return hr;
+}
+
+struct SCA_SSLBINDINGINFO
+{
+    IIS7_APPHOSTELEMENTCOMPARISON comparison;
+    LPCWSTR pwzStoreName;
+    LPCWSTR pwzEncodedCertificateHash;
+    HRESULT hr;
+};
+
+static BOOL AddSslCertificateToBindingCallback(IAppHostElement *pBindingElement, LPVOID pContext)
+{
+    HRESULT hr = S_OK;
+    VARIANT vtProp;
+    VariantInit(&vtProp);
+    SCA_SSLBINDINGINFO* pBindingInfo = (SCA_SSLBINDINGINFO*)pContext;
+    IAppHostMethodCollection *pAppHostMethodCollection = NULL;
+    IAppHostMethod *pAddSslMethod = NULL;
+    IAppHostMethodInstance *pAddSslMethodInstance = NULL;
+    IAppHostElement *pAddSslInput = NULL;
+    int iWsaError = 0;
+    WSADATA wsaData = {};
+    BOOL fWsaInitialized = FALSE;
+
+    // IIS's AddSslCertificate doesn't initialize WinSock on 2008 before using it to parse the IP
+    // Initialize before calling to workaround the failure.
+    iWsaError = WSAStartup(MAKEWORD(2, 2), &wsaData);
+    if (0 != iWsaError)
+    {
+        ExitOnWin32Error(iWsaError, hr, "Failed to initialize WinSock");
+    }
+
+    fWsaInitialized = TRUE;
+
+    if (Iis7IsMatchingAppHostElement(pBindingElement, &pBindingInfo->comparison))
+    {
+        hr = pBindingElement->get_Methods(&pAppHostMethodCollection);
+        ExitOnFailure(hr, "failed to get binding method collection");
+
+        hr = Iis7FindAppHostMethod(pAppHostMethodCollection, L"AddSslCertificate", &pAddSslMethod, NULL);
+        if (FAILED(hr))
+        {
+            WcaLog(LOGMSG_STANDARD, "The AddSslCertificate method is not supported by the binding element, SSL certificate will not be associated with the website");
+            ExitFunction();
+        }
+
+        pAddSslMethod->CreateInstance(&pAddSslMethodInstance);
+        ExitOnFailure(hr, "failed to create an instance of AddSslCertificate method");
+
+        pAddSslMethodInstance->get_Input(&pAddSslInput);
+        ExitOnFailure(hr, "failed to get input element of AddSslCertificate method");
+
+        Iis7PutPropertyString(pAddSslInput, IIS_CONFIG_CERTIFICATESTORENAME, pBindingInfo->pwzStoreName);
+        ExitOnFailure(hr, "failed to set certificateStoreName input parameter of AddSslCertificate method");
+
+        Iis7PutPropertyString(pAddSslInput, IIS_CONFIG_CERTIFICATEHASH, pBindingInfo->pwzEncodedCertificateHash);
+        ExitOnFailure(hr, "failed to set certificateHash input parameter of AddSslCertificate method");
+
+        hr = pAddSslMethodInstance->Execute();
+        ExitOnFailure(hr, "failed to execute AddSslCertificate method");
+    }
+LExit:
+    pBindingInfo->hr = hr;
+    ReleaseObject(pAppHostMethodCollection);
+    ReleaseObject(pAddSslMethod);
+    ReleaseObject(pAddSslMethodInstance);
+    ReleaseObject(pAddSslInput);
+    if (fWsaInitialized)
+    {
+        WSACleanup();
+    }
+
+    return FAILED(hr);
+}
+
+static HRESULT CreateSslBinding( IAppHostElement *pSiteElem, LPCWSTR pwzStoreName, LPCWSTR pwzEncodedCertificateHash)
+{
+    HRESULT hr = S_OK;
+    IAppHostChildElementCollection *pChildElems = NULL;
+    IAppHostElement *pBindingsElement = NULL;
+    IAppHostElementCollection *pBindingsCollection = NULL;
+    SCA_SSLBINDINGINFO bindingInfo = {};
+    VARIANT vtProp;
+    VariantInit(&vtProp);
+
+    hr = pSiteElem->get_ChildElements(&pChildElems);
+    ExitOnFailure(hr, "Failed get site child elements collection");
+
+    vtProp.vt = VT_BSTR;
+    vtProp.bstrVal = ::SysAllocString(IIS_CONFIG_BINDINGS);
+    hr = pChildElems->get_Item(vtProp, &pBindingsElement);
+    ExitOnFailure(hr, "Failed get bindings element");
+    ReleaseVariant(vtProp);
+
+    hr = pBindingsElement->get_Collection(&pBindingsCollection);
+    ExitOnFailure(hr, "Failed get bindings collection");
+
+    bindingInfo.comparison.sczElementName = IIS_CONFIG_BINDING;
+    bindingInfo.comparison.sczAttributeName = IIS_CONFIG_PROTOCOL;
+    vtProp.vt = VT_BSTR;
+    vtProp.bstrVal = ::SysAllocString(L"https");
+    bindingInfo.comparison.pvAttributeValue = &vtProp;
+    bindingInfo.pwzStoreName = pwzStoreName;
+    bindingInfo.pwzEncodedCertificateHash = pwzEncodedCertificateHash;
+
+    // Our current IISWebSiteCertificates schema does not allow specification of the website binding
+    // to associate the certificate with.  For now just associate it with all secure bindings.
+
+    hr = Iis7EnumAppHostElements(pBindingsCollection, AddSslCertificateToBindingCallback, &bindingInfo, NULL, NULL);
+    ExitOnFailure(hr, "Failed to enumerate bindings collection");
+    hr = bindingInfo.hr;
+    ExitOnFailure(hr, "Failed to add ssl binding");
+
+LExit:
+    ReleaseVariant(vtProp);
+
+    ReleaseObject(pChildElems);
+    ReleaseObject(pBindingsElement);
+    ReleaseObject(pBindingsCollection);
+
+    return hr;
+}
+
+static HRESULT DeleteSslBinding(
+    IAppHostElement * /*pSiteElem*/,
+    LPCWSTR /*pwzStoreName*/,
+    LPCWSTR /*pwzEncodedCertificateHash*/
+    )
+{
+    HRESULT hr = S_OK;
+    //
+    //this isn't supported right now, we should support this for the SiteSearch scenario
+    return hr;
+}
+
+static HRESULT DeleteAppPool( IAppHostWritableAdminManager *pAdminMgr,
+                            LPCWSTR swAppPoolName)
+{
+    HRESULT hr = S_OK;
+    IAppHostElement *pAppPools = NULL;
+    IAppHostElementCollection *pCollection = NULL;
+
+    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_APPPOOL_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pAppPools);
+    ExitOnFailure(hr, "Failed get AppPools section");
+    ExitOnNull(pAppPools, hr, E_UNEXPECTED, "Failed get appPools section object");
+
+    hr = pAppPools->get_Collection( &pCollection);
+    ExitOnFailure(hr, "Failed get AppPools collection");
+
+    hr = DeleteCollectionElement(pCollection, IIS_CONFIG_ADD, IIS_CONFIG_NAME, swAppPoolName);
+    ExitOnFailure(hr, "Failed to delete app pool %ls", swAppPoolName);
+
+LExit:
+    ReleaseObject(pAppPools);
+    ReleaseObject(pCollection);
+
+    return hr;
+}
+
+static HRESULT CreateAppPool(
+    __inout LPWSTR *ppwzCustomActionData,
+    IAppHostWritableAdminManager *pAdminMgr,
+    LPCWSTR swAppPoolName
+    )
+{
+    HRESULT hr = S_OK;
+    IAppHostElement *pAppPools = NULL;
+    IAppHostElement *pAppPoolElement = NULL;
+    IAppHostElement *pElement = NULL;
+    IAppHostElement *pElement2 = NULL;
+    IAppHostElement *pElement3 = NULL;
+    IAppHostElementCollection *pCollection = NULL;
+    IAppHostElementCollection *pCollection2 = NULL;
+    int iAction = -1;
+    int iData   =  0;
+    LPWSTR pwzData = NULL;
+    WCHAR wcData[512];
+    WCHAR wcTime[60];
+    BOOL fFound = FALSE;
+
+    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_APPPOOL_SECTION), ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pAppPools);
+    ExitOnFailure(hr, "Failed get AppPools section");
+    ExitOnNull(pAppPools, hr, ERROR_FILE_NOT_FOUND, "Failed get AppPools section object");
+
+    hr = pAppPools->get_Collection( &pCollection);
+    ExitOnFailure(hr, "Failed get AppPools collection");
+
+    hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_ADD, IIS_CONFIG_NAME, swAppPoolName, &pAppPoolElement, NULL);
+    ExitOnFailure(hr, "Failed find AppPool element");
+    fFound = (NULL != pAppPoolElement);
+
+    if (!fFound)
+    {
+        hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pAppPoolElement);
+        ExitOnFailure(hr, "Failed create AppPool element");
+    }
+
+    hr = Iis7PutPropertyString(pAppPoolElement, IIS_CONFIG_NAME, swAppPoolName);
+    ExitOnFailure(hr, "Failed set AppPool name property");
+
+    //For WiX II6 /ABO compat we will default managedPipelineMode="Classic"
+    hr = Iis7PutPropertyString(pAppPoolElement, IIS_CONFIG_PIPELINEMODE, L"Classic");
+    ExitOnFailure(hr, "Failed set AppPool managedPipelineMode property");
+    //For WiX II6 /ABO compat we will be hardcoding autostart="true"
+    hr = Iis7PutPropertyString(pAppPoolElement, IIS_CONFIG_APPPOOL_AUTO, L"true");
+    ExitOnFailure(hr, "Failed set AppPool autoStart property");
+
+    if (!fFound)
+    {
+        hr = pCollection->AddElement(pAppPoolElement);
+        ExitOnFailure(hr, "Failed to add appPool element");
+    }
+
+    // Get AppPool Property action
+    hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+    ExitOnFailure(hr, "Failed to read AppPool Property action");
+    while (IIS_APPPOOL_END != iAction)
+    {
+        //Process property action
+        switch (iAction)
+        {
+            case IIS_APPPOOL_RECYCLE_MIN :
+            {
+            // /recycling / periodicRestart | time
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read AppPool recycle min");
+                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_RECYCLING), &pElement);
+                ExitOnFailure(hr, "Failed to get AppPool recycling element");
+                hr = pElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PEROIDRESTART), &pElement2);
+                ExitOnFailure(hr, "Failed to get AppPool periodicRestart element");
+                *wcTime = '\0';
+                ConvSecToHMS(iData * 60, wcTime, countof(wcTime));
+                hr = Iis7PutPropertyString(pElement2, IIS_CONFIG_TIME, wcTime);
+                ExitOnFailure(hr, "Failed to set AppPool periodicRestart time value");
+                ReleaseNullObject(pElement);
+                ReleaseNullObject(pElement2);
+                break;
+            }
+            case IIS_APPPOOL_RECYCLE_REQ :
+            {
+            // /recycling / periodicRestart | requests
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read AppPool recycle req");
+                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_RECYCLING), &pElement);
+                ExitOnFailure(hr, "Failed to get AppPool recycling element");
+                hr = pElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PEROIDRESTART), &pElement2);
+                ExitOnFailure(hr, "Failed to get AppPool periodicRestart element");
+                hr = Iis7PutPropertyInteger(pElement2, IIS_CONFIG_REQUESTS, iData);
+                ExitOnFailure(hr, "Failed to set AppPool periodicRestart time value");
+                ReleaseNullObject(pElement);
+                ReleaseNullObject(pElement2);
+                break;
+            }
+            case IIS_APPPOOL_RECYCLE_TIMES :
+            {
+            // /recycling / periodicRestart | schedule
+                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+                ExitOnFailure(hr, "Failed to read AppPool recycle times");
+                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_RECYCLING), &pElement);
+                ExitOnFailure(hr, "Failed to get AppPool recycling element");
+                hr = pElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PEROIDRESTART), &pElement2);
+                ExitOnFailure(hr, "Failed to get AppPool periodicRestart element");
+                hr = pElement2->GetElementByName(ScopeBSTR(IIS_CONFIG_SCHEDULE), &pElement3);
+                ExitOnFailure(hr, "Failed to get AppPool schedule element");
+                hr = pElement3->get_Collection(&pCollection2);
+                ExitOnFailure(hr, "Failed to get AppPool schedule collection");
+
+                WCHAR wcDelim[] = L",";
+                const WCHAR *wszToken = NULL;
+                WCHAR *wszNextToken = NULL;
+                wszToken = wcstok_s( pwzData, wcDelim, &wszNextToken);
+
+                while (wszToken)
+                {
+                    *wcData = '\0';
+                    hr = ::StringCchCopyW(wcData, countof(wcData), wszToken);
+                    ExitOnFailure(hr, "failed to copy AppPool schedule");
+                    hr = ::StringCchCatW(wcData, countof(wcData), L":00");
+                    ExitOnFailure(hr, "failed to append AppPool schedule");
+
+                    hr = pCollection2->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pElement3);
+                    ExitOnFailure(hr, "Failed to create AppPool schedule element");
+
+                    hr = Iis7PutPropertyString(pElement3, IIS_CONFIG_VALUE, wcData);
+                    ExitOnFailure(hr, "Failed to set AppPool schedule value");
+
+                    hr = pCollection2->AddElement(pElement3);
+                    if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS))
+                    {
+                        //Eat this error, recycle time already exists NBD
+                        hr = S_OK;
+                    }
+                    ExitOnFailure(hr, "Failed to add win auth providers element");
+                    ReleaseNullObject(pElement3);
+                    wszToken = wcstok_s( NULL, wcDelim, &wszNextToken);
+                }
+                ReleaseNullObject(pElement);
+                ReleaseNullObject(pElement2);
+                ReleaseNullObject(pElement3);
+                ReleaseNullObject(pCollection2);
+                break;
+            }
+            case IIS_APPPOOL_RECYCLE_VIRMEM :
+            {
+            // /recycling / periodicRestart | memory
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read AppPool recycle vir memory");
+                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_RECYCLING), &pElement);
+                ExitOnFailure(hr, "Failed to get AppPool recycling element");
+                hr = pElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PEROIDRESTART), &pElement2);
+                ExitOnFailure(hr, "Failed to get AppPool periodicRestart element");
+                hr = Iis7PutPropertyInteger(pElement2, IIS_CONFIG_MEMORY, iData);
+                ExitOnFailure(hr, "Failed to set AppPool periodicRestart memory");
+                ReleaseNullObject(pElement);
+                ReleaseNullObject(pElement2);
+                break;
+            }
+            case IIS_APPPOOL_RECYCLE_PRIVMEM :
+            {
+            // /recycling / periodicRestart | privateMemory
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read AppPool recycle priv mem");
+                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_RECYCLING), &pElement);
+                ExitOnFailure(hr, "Failed to get AppPool recycling element");
+                hr = pElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PEROIDRESTART), &pElement2);
+                ExitOnFailure(hr, "Failed to get AppPool periodicRestart element");
+                hr = Iis7PutPropertyInteger(pElement2, IIS_CONFIG_PRIVMEMORY, iData);
+                ExitOnFailure(hr, "Failed to set AppPool periodicRestart private memory");
+                ReleaseNullObject(pElement);
+                ReleaseNullObject(pElement2);
+                break;
+            }
+            case IIS_APPPOOL_RECYCLE_IDLTIMEOUT :
+            {
+            //  /processModel | idleTimeout
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read AppPool idle timeout");
+                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PROCESSMODEL), &pElement);
+                ExitOnFailure(hr, "Failed to get AppPool processModel element");
+                *wcTime = '\0';
+                ConvSecToHMS(iData * 60, wcTime, countof(wcTime));
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_IDLETIMEOUT, wcTime);
+                ExitOnFailure(hr, "Failed to set AppPool processModel idle timeout value");
+                ReleaseNullObject(pElement);
+                break;
+            }
+            case IIS_APPPOOL_RECYCLE_QUEUELIMIT :
+            {
+            //  /applicationPools | queueLength
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read AppPool recycle queue limit");
+                hr = Iis7PutPropertyInteger(pAppPoolElement, IIS_CONFIG_QUEUELENGTH, iData);
+                ExitOnFailure(hr, "Failed to set AppPool recycle queue limit value");
+                break;
+            }
+            case IIS_APPPOOL_MAXPROCESS :
+            {
+            //  /processModel | maxProcesses
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read AppPool max processes");
+                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PROCESSMODEL), &pElement);
+                ExitOnFailure(hr, "Failed to get AppPool processModel element");
+                hr = Iis7PutPropertyInteger(pElement, IIS_CONFIG_MAXWRKPROCESSES, iData);
+                ExitOnFailure(hr, "Failed to set AppPool processModel maxProcesses value");
+                ReleaseNullObject(pElement);
+                break;
+            }
+            case IIS_APPPOOL_IDENTITY :
+            {
+            //"LocalSystem" 0
+            //"LocalService" 1
+            //"NetworkService" 2
+            //"SpecificUser" 3
+            //"ApplicationPoolIdentity" 4
+            //  /processModel | identityType
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read AppPool identity");
+                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PROCESSMODEL), &pElement);
+                ExitOnFailure(hr, "Failed to get AppPool processModel element");
+                if (iData == 0)
+                {
+                    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_IDENITITYTYPE, IIS_CONFIG_LOCALSYSTEM);
+                }
+                else if (iData == 1)
+                {
+                    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_IDENITITYTYPE, IIS_CONFIG_LOCALSERVICE);
+                }
+                else if (iData == 2)
+                {
+                    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_IDENITITYTYPE, IIS_CONFIG_NETWORKSERVICE);
+                }
+                else if (iData == 3)
+                {
+                    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_IDENITITYTYPE, IIS_CONFIG_SPECIFICUSER);
+                }
+                else if (iData == 4)
+                {
+                    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_IDENITITYTYPE, IIS_CONFIG_APPLICATIONPOOLIDENTITY);
+                }
+                ExitOnFailure(hr, "Failed to set AppPool processModel identityType value");
+                ReleaseNullObject(pElement);
+                break;
+            }
+            case IIS_APPPOOL_USER :
+            {
+            //  /processModel | userName
+                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+                ExitOnFailure(hr, "Failed to read AppPool user");
+                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PROCESSMODEL), &pElement);
+                ExitOnFailure(hr, "Failed to get AppPool processModel element");
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_USERNAME, pwzData);
+                ExitOnFailure(hr, "Failed to set AppPool processModel username value");
+                ReleaseNullObject(pElement);
+                break;
+            }
+            case IIS_APPPOOL_PWD :
+            {
+            //  /processModel | password
+                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+                ExitOnFailure(hr, "Failed to read AppPool pwd");
+                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_PROCESSMODEL), &pElement);
+                ExitOnFailure(hr, "Failed to get AppPool processModel element");
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_PASSWORD, pwzData);
+                ExitOnFailure(hr, "Failed to set AppPool processModel password value");
+                ReleaseNullObject(pElement);
+                break;
+            }
+            case  IIS_APPPOOL_RECYCLE_CPU_PCT:
+            {
+            // /cpu | limit
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read cpu pct");
+                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_CPU), &pElement);
+                ExitOnFailure(hr, "Failed to get AppPool cpu element");
+                // limit is maximum percentage of CPU time (in 1/1000ths of one percent)
+                hr = Iis7PutPropertyInteger(pElement, IIS_CONFIG_LIMIT, iData * 1000);
+                ExitOnFailure(hr, "Failed to set AppPool cpu limit");
+                ReleaseNullObject(pElement);
+                break;
+            }
+            case  IIS_APPPOOL_RECYCLE_CPU_REFRESH:
+            {
+            // /cpu | resetInterval
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read cpu refresh pwd");
+                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_CPU), &pElement);
+                ExitOnFailure(hr, "Failed to get AppPool cpu element");
+                *wcTime = '\0';
+                ConvSecToHMS(iData * 60, wcTime, countof(wcTime));
+                hr = Iis7PutPropertyString(pElement, IIS_CONFIG_RESETINTERVAL, wcTime);
+                ExitOnFailure(hr, "Failed to set AppPool cpu resetInterval value");
+                ReleaseNullObject(pElement);
+                break;
+            }
+            case  IIS_APPPOOL_RECYCLE_CPU_ACTION:
+            {
+            // /cpu | action
+            //"NoAction" 0
+            //"KillW3wp" 1
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read cpu action");
+                hr = pAppPoolElement->GetElementByName(ScopeBSTR(IIS_CONFIG_CPU), &pElement);
+                ExitOnFailure(hr, "Failed to get AppPool cpu element");
+                if (iData)
+                {
+                    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_CPU_ACTION, IIS_CONFIG_KILLW3WP);
+                }
+                else
+                {
+                    hr = Iis7PutPropertyString(pElement, IIS_CONFIG_CPU_ACTION, IIS_CONFIG_NOACTION);
+                }
+                ExitOnFailure(hr, "Failed to set AppPool cpu action value");
+                ReleaseNullObject(pElement);
+                break;
+            }
+            case IIS_APPPOOL_32BIT:
+            {
+                hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iData);
+                ExitOnFailure(hr, "Failed to read enable32BitAppOnWin64 value");
+                //  enable32BitAppOnWin64
+                hr = Iis7PutPropertyBool(pAppPoolElement, IIS_CONFIG_ENABLE32, iData ? TRUE : FALSE);
+                ExitOnFailure(hr, "Failed to set AppPool enable32BitAppOnWin64 value");
+                break;
+            }
+            case IIS_APPPOOL_MANAGED_PIPELINE_MODE:
+            {
+                // managedPipelineMode
+                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+                ExitOnFailure(hr, "Failed to read AppPool managedRuntimeVersion");
+                hr = Iis7PutPropertyString(pAppPoolElement, IIS_CONFIG_PIPELINEMODE, pwzData);
+                ExitOnFailure(hr, "Failed set AppPool managedPipelineMode property");
+                break;
+            }
+            case IIS_APPPOOL_MANAGED_RUNTIME_VERSION:
+            {
+                // managedRuntimeVersion
+                hr = WcaReadStringFromCaData(ppwzCustomActionData, &pwzData);
+                ExitOnFailure(hr, "Failed to read AppPool managedRuntimeVersion");
+                hr = Iis7PutPropertyString(pAppPoolElement, IIS_CONFIG_MANAGEDRUNTIMEVERSION, pwzData);
+                ExitOnFailure(hr, "Failed set AppPool managedRuntimeVersion property");
+                break;
+            }
+
+            default:
+            ExitOnFailure(hr = E_UNEXPECTED, "Unexpected IIS Config action specified for AppPool");
+            break;
+
+        }
+        // Get AppPool property action
+        hr = WcaReadIntegerFromCaData(ppwzCustomActionData, &iAction);
+        ExitOnFailure(hr, "Failed to read AppPool Property action");
+    }
+
+LExit:
+    ReleaseObject(pAppPools);
+    ReleaseObject(pCollection);
+    ReleaseObject(pCollection2);
+    ReleaseObject(pAppPoolElement);
+    ReleaseObject(pElement);
+    ReleaseObject(pElement2);
+    ReleaseObject(pElement3);
+
+    return hr;
+}
+
+static HRESULT SetDirPropAuthentications(IAppHostWritableAdminManager *pAdminMgr,
+                                         LPCWSTR wszConfigPath,
+                                         DWORD dwData)
+{
+    HRESULT hr = S_OK;
+    IAppHostElement *pSection = NULL;
+
+    //dwData contains bit flags for /security/authentication/<...>
+    // Anonymous    = 1
+    // Basic        = 2
+    // Windows      = 4
+    // Digest       =16
+    // Passport     =64  *not supported
+    //translation required from bit map to section name
+    // E.G security/authentication/windowsAuthentication [property enabled true|false]
+
+    // AnonymousAuthentication = 1
+    hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/anonymousAuthentication"), ScopeBSTR(wszConfigPath), &pSection);
+    ExitOnFailure(hr, "Failed get AnonymousAuthentication section for DirProp");
+    if (!pSection)
+    {
+        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+        ExitOnFailure(hr, "Failed get AnonymousAuthentication section object for DirProps");
+    }
+
+    hr = Iis7PutPropertyBool(pSection, L"enabled", (BOOL)(dwData & 0x1));
+    ExitOnFailure(hr, "Failed set AnonymousAuthentication enabled for DirProps");
+    ReleaseNullObject(pSection);
+
+    // basicAuthentication = 2
+    hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/basicAuthentication"), ScopeBSTR(wszConfigPath), &pSection);
+    ExitOnFailure(hr, "Failed get basicAuthentication section for DirProp");
+    if (!pSection)
+    {
+        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+        ExitOnFailure(hr, "Failed get basicAuthentication section object for DirProps");
+    }
+
+    hr = Iis7PutPropertyBool(pSection, L"enabled", (BOOL)(dwData & 0x2));
+    ExitOnFailure(hr, "Failed set basicAuthentication enabled for DirProps");
+    ReleaseNullObject(pSection);
+
+    // WindowsAuthentication = 4
+    hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/windowsAuthentication"), ScopeBSTR(wszConfigPath), &pSection);
+    ExitOnFailure(hr, "Failed get windowsAuthentication section for DirProp");
+    if (!pSection)
+    {
+        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+        ExitOnFailure(hr, "Failed get windowsAuthentication section object for DirProps");
+    }
+
+    hr = Iis7PutPropertyBool(pSection, L"enabled", (BOOL)(dwData & 0x4));
+    ExitOnFailure(hr, "Failed set windowsAuthentication enabled for DirProps");
+    ReleaseNullObject(pSection);
+
+    // digestAuthentication = 16
+    hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/digestAuthentication"), ScopeBSTR(wszConfigPath), &pSection);
+    ExitOnFailure(hr, "Failed get digestAuthentication section for DirProp");
+    if (!pSection)
+    {
+        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+        ExitOnFailure(hr, "Failed get digestAuthentication section object for DirProps");
+    }
+
+    hr = Iis7PutPropertyBool(pSection, L"enabled", (BOOL)(dwData & 0x10));
+    ExitOnFailure(hr, "Failed set digestAuthentication enabled for DirProps");
+    ReleaseNullObject(pSection);
+
+LExit:
+    ReleaseObject(pSection);
+
+    return hr;
+}
+
+static HRESULT SetDirPropAuthProvider(IAppHostWritableAdminManager *pAdminMgr,
+                                         LPCWSTR wszConfigPath,
+                                         __in LPWSTR wszData)
+{
+    HRESULT hr = S_OK;
+    IAppHostElement *pSection = NULL;
+    IAppHostElement *pElement = NULL;
+    IAppHostElement *pNewElement = NULL;
+    IAppHostElementCollection *pCollection = NULL;
+
+    WCHAR wcDelim[] = L",";
+    const WCHAR *wszToken = NULL;
+    WCHAR *wszNextToken = NULL;
+
+    hr = pAdminMgr->GetAdminSection(ScopeBSTR(L"system.webServer/security/authentication/windowsAuthentication"), ScopeBSTR(wszConfigPath), &pSection);
+    ExitOnFailure(hr, "Failed get windowsAuthentication section for DirProp providers");
+
+    hr = pSection->GetElementByName(ScopeBSTR(L"providers"), &pElement);
+    ExitOnFailure(hr, "Failed get win auth providers section");
+
+    hr = pElement->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get win auth providers collection");
+
+    hr = pCollection->Clear();
+    ExitOnFailure(hr, "Failed to clear win auth providers collection");
+
+    //Clear out inherited items - add clear
+    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_CLEAR), &pNewElement);
+    ExitOnFailure(hr, "Failed to create win auth providers clear element");
+    hr = pCollection->AddElement(pNewElement);
+    ExitOnFailure(hr, "Failed to add win auth providers clear element");
+    ReleaseNullObject(pNewElement);
+
+    wszToken = wcstok_s( wszData, wcDelim, &wszNextToken);
+    for (int i = 0; (wszToken); ++i)
+    {
+        hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pNewElement);
+        ExitOnFailure(hr, "Failed to create win auth providers element");
+
+        hr = Iis7PutPropertyString( pNewElement, IIS_CONFIG_VALUE, wszToken);
+        ExitOnFailure(hr, "Failed to set win auth providers value");
+
+        hr = pCollection->AddElement(pNewElement, i);
+        ExitOnFailure(hr, "Failed to add win auth providers element");
+        ReleaseNullObject(pNewElement);
+
+        wszToken = wcstok_s( NULL, wcDelim, &wszNextToken);
+    }
+
+LExit:
+    ReleaseObject(pSection);
+    ReleaseObject(pCollection);
+    ReleaseObject(pElement);
+    ReleaseObject(pNewElement);
+
+    return hr;
+}
+
+static HRESULT SetDirPropDefDoc(
+    IAppHostWritableAdminManager *pAdminMgr,
+    LPCWSTR wszConfigPath,
+    __in LPWSTR wszData)
+{
+    HRESULT hr = S_OK;
+    IAppHostElement *pSection = NULL;
+    IAppHostElement *pElement = NULL;
+    IAppHostElement *pNewElement = NULL;
+    IAppHostElementCollection *pCollection = NULL;
+
+    WCHAR wcDelim[] = L",";
+    const WCHAR *wszToken = NULL;
+    WCHAR *wszNextToken = NULL;
+
+    hr = pAdminMgr->GetAdminSection(ScopeBSTR(IIS_CONFIG_DEFAULTDOC_SECTION), ScopeBSTR(wszConfigPath), &pSection);
+    ExitOnFailure(hr, "Failed get defaultDocument section for DirProp");
+
+    hr = pSection->GetElementByName(ScopeBSTR(L"files"), &pElement);
+    ExitOnFailure(hr, "Failed get win files section");
+
+    hr = pElement->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get files collection");
+
+    hr = pCollection->Clear();
+    ExitOnFailure(hr, "Failed clear files collection");
+
+    //Clear out inherited items - add clear
+    hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_CLEAR), &pNewElement);
+    ExitOnFailure(hr, "Failed to create files clear element");
+    hr = pCollection->AddElement(pNewElement);
+    ExitOnFailure(hr, "Failed to add files clear element");
+
+    wszToken = wcstok_s( wszData, wcDelim, &wszNextToken);
+    for (int i = 0; (wszToken); ++i)
+    {
+        hr = pCollection->CreateNewElement(ScopeBSTR(IIS_CONFIG_ADD), &pNewElement);
+        ExitOnFailure(hr, "Failed to create win auth providers element");
+
+        hr = Iis7PutPropertyString( pNewElement, IIS_CONFIG_VALUE, wszToken);
+        ExitOnFailure(hr, "Failed to set win auth providers value");
+
+        hr = pCollection->AddElement(pNewElement, i);
+        ExitOnFailure(hr, "Failed to add defaultDocument Files element");
+        ReleaseNullObject(pNewElement);
+
+        wszToken = wcstok_s( NULL, wcDelim, &wszNextToken);
+    }
+
+LExit:
+    ReleaseObject(pSection);
+    ReleaseObject(pCollection);
+    ReleaseObject(pNewElement);
+
+    return hr;
+}
+
+static HRESULT ClearLocationTag(
+    IAppHostWritableAdminManager *pAdminMgr,
+    LPCWSTR swLocationPath
+    )
+{
+    HRESULT hr = S_OK;
+    IAppHostConfigManager *pConfigMgr = NULL;
+    IAppHostConfigFile    *pConfigFile = NULL;
+    IAppHostConfigLocationCollection *pLocationCollection = NULL;
+    IAppHostConfigLocation *pLocation = NULL;
+
+    DWORD dwCount = 0;
+    BSTR bstrLocationPath = NULL;
+
+    hr = pAdminMgr->get_ConfigManager(&pConfigMgr);
+    ExitOnFailure(hr, "Failed to get IIS ConfigManager interface");
+
+    hr = pConfigMgr->GetConfigFile(ScopeBSTR(IIS_CONFIG_APPHOST_ROOT), &pConfigFile);
+    ExitOnFailure(hr, "Failed to get IIS ConfigFile interface");
+
+    hr = pConfigFile->get_Locations(&pLocationCollection);
+    ExitOnFailure(hr, "Failed to get IIS location tag collection");
+
+    hr = pLocationCollection->get_Count(&dwCount);
+    ExitOnFailure(hr, "Failed to get IIS location collection count");
+
+    VARIANT vtIndex;
+    vtIndex.vt = VT_UI4;
+    for (DWORD i = 0; i < dwCount; ++i)
+    {
+        vtIndex.ulVal = i;
+        hr = pLocationCollection->get_Item(vtIndex, &pLocation);
+        ExitOnFailure(hr, "Failed to get IIS location collection count");
+
+        hr = pLocation->get_Path(&bstrLocationPath);
+        if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, swLocationPath, -1, bstrLocationPath, -1))
+        {
+            hr = pLocationCollection->DeleteLocation(vtIndex);
+            ExitOnFailure(hr, "Failed to delete IIS location tag %ls",swLocationPath);
+            break;
+        }
+
+        ReleaseNullObject(pLocation);
+        ::SysFreeString(bstrLocationPath);
+        bstrLocationPath = NULL;
+    }
+LExit:
+    ReleaseObject(pConfigMgr);
+    ReleaseObject(pConfigFile);
+    ReleaseObject(pLocationCollection);
+    ReleaseObject(pLocation);
+    ReleaseBSTR(bstrLocationPath);
+
+    return hr;
+
+}
+
+static HRESULT DeleteCollectionElement(
+    __in IAppHostElementCollection *pCollection,
+    __in LPCWSTR pwzElementName,
+    __in LPCWSTR pwzAttributeName,
+    __in LPCWSTR pwzAttributeValue
+    )
+{
+    HRESULT hr = S_OK;
+
+    DWORD dwIndex;
+    VARIANT vtIndex;
+    VariantInit(&vtIndex);
+
+    hr = Iis7FindAppHostElementString(pCollection, pwzElementName, pwzAttributeName, pwzAttributeValue, NULL, &dwIndex);
+    ExitOnFailure(hr, "Failed while finding IAppHostElement %ls/@%ls=%ls", pwzElementName, pwzAttributeName, pwzAttributeValue);
+
+    if (MAXDWORD != dwIndex)
+    {
+        vtIndex.vt = VT_UI4;
+        vtIndex.ulVal = dwIndex;
+        hr = pCollection->DeleteElement(vtIndex);
+        ExitOnFailure(hr, "Failed to delete IAppHostElement %ls/@%ls=%ls", pwzElementName, pwzAttributeName, pwzAttributeValue);
+    }
+    // else : nothing to do, already deleted
+LExit:
+    ReleaseVariant(vtIndex);
+
+    return hr;
+}
+static void ConvSecToHMS( int Sec,  __out_ecount(cchDest) LPWSTR wcTime, size_t cchDest)
+{
+    int ZH, ZM, ZS = 0;
+
+    ZH = (Sec / 3600);
+    Sec = Sec - ZH * 3600;
+    ZM = (Sec / 60) ;
+    Sec = Sec - ZM * 60;
+    ZS = Sec ;
+
+    HRESULT hr = ::StringCchPrintfW(wcTime, cchDest, L"%02d:%02d:%02d", ZH, ZM, ZS);
+    if (S_OK != hr)
+    {
+        *wcTime = '\0';
+    }
+}
+static void ConvSecToDHMS( unsigned int Sec,  __out_ecount(cchDest) LPWSTR wcTime, size_t cchDest)
+{
+    int ZD, ZH, ZM, ZS = 0;
+
+    ZD = Sec / 86400;
+    Sec = Sec - ZD * 86400;
+    ZH = (Sec / 3600);
+    Sec = Sec - ZH * 3600;
+    ZM = (Sec / 60) ;
+    Sec = Sec - ZM * 60;
+    ZS = Sec ;
+
+    HRESULT hr = ::StringCchPrintfW(wcTime, cchDest, L"%d.%02d:%02d:%02d", ZD, ZH, ZM, ZS);
+    if (S_OK != hr)
+    {
+        *wcTime = '\0';
+    }
+}
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 @@
+#pragma once
+// 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.
+
+
+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 @@
+// 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.
+
+#include "precomp.h"
+
+// prototypes
+static HRESULT ReadFilterLoadOrder(
+    __in IMSAdminBase* piMetabase,
+    __in LPCWSTR wzFilterRoot,
+    __out LPWSTR *ppwzLoadOrder
+    );
+static HRESULT AddFilterToLoadOrder(
+    __in LPCWSTR wzFilter,
+    __in int iLoadOrder,
+    __inout LPWSTR *ppwzLoadOrder
+    );
+static HRESULT RemoveFilterFromLoadOrder(
+    __in LPCWSTR wzFilter,
+    __inout LPWSTR *ppwzLoadOrder
+    );
+
+
+UINT __stdcall ScaFiltersRead(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_WEB* pswList,
+    __in WCA_WRAPQUERY_HANDLE hWebBaseQuery,
+    __inout SCA_FILTER** ppsfList,
+    __inout LPWSTR *ppwzCustomActionData
+    )
+{
+    HRESULT hr = S_OK;
+    MSIHANDLE hRec;
+    INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN;
+    INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN;
+
+    LPWSTR pwzData = NULL;
+
+    SCA_FILTER* psf = NULL;
+    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
+
+    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead");
+
+    if (0 == WcaGetQueryRecords(hWrapQuery))
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ScaFiltersRead() - no IIsFilter table");
+        ExitFunction1(hr = S_FALSE);
+    }
+
+    // loop through all the filters
+    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
+    {
+        // Get the Component first.  If the component is not being modified during
+        // this transaction, skip processing this whole record.
+        hr = WcaGetRecordString(hRec, fqComponent, &pwzData);
+        ExitOnFailure(hr, "failed to get IIsFilter.Component");
+
+        hr = WcaGetRecordInteger(hRec, fqInstalled, (int *)&isInstalled);
+        ExitOnFailure(hr, "Failed to get Component installed state for IIs filter");
+
+        hr = WcaGetRecordInteger(hRec, fqAction, (int *)&isAction);
+        ExitOnFailure(hr, "Failed to get Component action state for IIs filter");
+
+        if (!WcaIsInstalling(isInstalled, isAction) &&
+            !WcaIsReInstalling(isInstalled, isAction) &&
+            !WcaIsUninstalling(isInstalled, isAction))
+        {
+            continue; // skip this record.
+        }
+
+        hr = AddFilterToList(ppsfList);
+        ExitOnFailure(hr, "failed to add filter to list");
+
+        psf = *ppsfList;
+
+        hr = ::StringCchCopyW(psf->wzComponent, countof(psf->wzComponent), pwzData);
+        ExitOnFailure(hr, "failed to copy component name: %ls", pwzData);
+
+        psf->isInstalled = isInstalled;
+        psf->isAction = isAction;
+
+        hr = WcaGetRecordString(hRec, fqWeb, &pwzData);
+        ExitOnFailure(hr, "Failed to get Web for VirtualDir");
+
+        if (*pwzData)
+        {
+            hr = ScaWebsGetBase(piMetabase, pswList, pwzData, psf->wzWebBase, countof(psf->wzWebBase), hWebBaseQuery);
+            if (FAILED(hr) && WcaIsUninstalling(isInstalled, isAction))
+            {
+                // If we're uninstalling, don't bother finding the existing web, just leave the filter root empty
+                hr = S_OK;
+            }
+            ExitOnFailure(hr, "Failed to get base of web for Filter");
+
+            if (0 != lstrlenW(psf->wzWebBase))
+            {
+                hr = ::StringCchPrintfW(psf->wzFilterRoot, countof(psf->wzFilterRoot), L"%s/Filters", psf->wzWebBase);
+                ExitOnFailure(hr, "Failed to allocate filter base string");
+            }
+        }
+        else
+        {
+            hr = ::StringCchCopyW(psf->wzFilterRoot, countof(psf->wzFilterRoot), L"/LM/W3SVC/Filters");
+            ExitOnFailure(hr, "Failed to allocate global filter base string");
+        }
+
+        // filter key
+        hr = WcaGetRecordString(hRec, fqFilter, &pwzData);
+        ExitOnFailure(hr, "Failed to get Filter.Filter");
+        hr = ::StringCchCopyW(psf->wzKey, countof(psf->wzKey), pwzData);
+        ExitOnFailure(hr, "Failed to copy key string to filter object");
+
+        // filter path
+        hr = WcaGetRecordString(hRec, fqPath, &pwzData);
+        ExitOnFailure(hr, "Failed to get Filter.Path");
+        hr = ::StringCchCopyW(psf->wzPath, countof(psf->wzPath), pwzData);
+        ExitOnFailure(hr, "Failed to copy path string to filter object");
+
+        // filter description
+        hr = WcaGetRecordString(hRec, fqDescription, &pwzData);
+        ExitOnFailure(hr, "Failed to get Filter.Description");
+        hr = ::StringCchCopyW(psf->wzDescription, countof(psf->wzDescription), pwzData);
+        ExitOnFailure(hr, "Failed to copy description string to filter object");
+
+        // filter flags
+        hr = WcaGetRecordInteger(hRec, fqFlags, &psf->iFlags);
+        ExitOnFailure(hr, "Failed to get Filter.Flags");
+
+        // filter load order
+        hr = WcaGetRecordInteger(hRec, fqLoadOrder, &psf->iLoadOrder);
+        ExitOnFailure(hr, "Failed to get Filter.LoadOrder");
+    }
+
+    if (E_NOMOREITEMS == hr)
+    {
+        hr = S_OK;
+    }
+    ExitOnFailure(hr, "Failure while processing filters");
+
+LExit:
+    WcaFinishUnwrapQuery(hWrapQuery);
+
+    ReleaseStr(pwzData);
+    return hr;
+}
+
+
+HRESULT ScaFiltersInstall(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_FILTER* psfList
+    )
+{
+    HRESULT hr = S_OK;
+    SCA_FILTER* psf = psfList;
+    LPCWSTR wzPreviousFilterRoot = NULL;
+    LPWSTR pwzLoadOrder = NULL;
+
+    while (psf)
+    {
+        if (WcaIsInstalling(psf->isInstalled, psf->isAction))
+        {
+            if (!wzPreviousFilterRoot || CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, 0, wzPreviousFilterRoot, -1, psf->wzFilterRoot, -1))
+            {
+                if (pwzLoadOrder)
+                {
+                    hr = ScaWriteMetabaseValue(piMetabase, wzPreviousFilterRoot, L"", MD_FILTER_LOAD_ORDER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)pwzLoadOrder);
+                    ExitOnFailure(hr, "Failed to write filter load order to metabase");
+
+                    ReleaseNullStr(pwzLoadOrder);
+                }
+
+                hr = ReadFilterLoadOrder(piMetabase, psf->wzFilterRoot, &pwzLoadOrder);
+                ExitOnFailure(hr, "Failed to read filter load order.");
+
+                wzPreviousFilterRoot = psf->wzFilterRoot;
+            }
+
+            hr = ScaCreateMetabaseKey(piMetabase, psf->wzFilterRoot, psf->wzKey);
+            ExitOnFailure(hr, "Failed to create key for filter '%ls'", psf->wzKey);
+
+            hr = ScaWriteMetabaseValue(piMetabase, psf->wzFilterRoot, psf->wzKey, MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsFilter");
+            ExitOnFailure(hr, "Failed to write key type for filter '%ls'", psf->wzKey);
+
+            // filter path
+            hr = ScaWriteMetabaseValue(piMetabase, psf->wzFilterRoot, psf->wzKey, MD_FILTER_IMAGE_PATH, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)psf->wzPath);
+            ExitOnFailure(hr, "Failed to write Path for filter '%ls'", psf->wzKey);
+
+            // filter description
+            hr = ScaWriteMetabaseValue(piMetabase, psf->wzFilterRoot, psf->wzKey, MD_FILTER_DESCRIPTION, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)psf->wzDescription);
+            ExitOnFailure(hr, "Failed to write Description for filter '%ls'", psf->wzKey);
+
+            // filter flags
+            if (MSI_NULL_INTEGER != psf->iFlags)
+            {
+                hr = ScaWriteMetabaseValue(piMetabase, psf->wzFilterRoot, psf->wzKey, MD_FILTER_FLAGS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psf->iFlags));
+                ExitOnFailure(hr, "Failed to write Flags for filter '%ls'", psf->wzKey);
+            }
+
+            // filter load order
+            if (MSI_NULL_INTEGER != psf->iLoadOrder)
+            {
+                hr = AddFilterToLoadOrder(psf->wzKey, psf->iLoadOrder, &pwzLoadOrder);
+                ExitOnFailure(hr, "Failed to add filter '%ls' to load order.", psf->wzKey);
+            }
+        }
+
+        psf = psf->psfNext;
+    }
+
+    if (pwzLoadOrder)
+    {
+        Assert(wzPreviousFilterRoot && *wzPreviousFilterRoot);
+
+        hr = ScaWriteMetabaseValue(piMetabase, wzPreviousFilterRoot, L"", MD_FILTER_LOAD_ORDER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)pwzLoadOrder);
+        ExitOnFailure(hr, "Failed to write filter load order to metabase");
+    }
+
+LExit:
+    ReleaseStr(pwzLoadOrder);
+    return hr;
+}
+
+
+HRESULT ScaFiltersUninstall(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_FILTER* psfList
+    )
+{
+    HRESULT hr = S_OK;
+    SCA_FILTER* psf = psfList;
+    LPCWSTR wzPreviousFilterRoot = NULL;
+    LPWSTR pwzLoadOrder = NULL;
+
+    while (psf)
+    {
+        if (WcaIsUninstalling(psf->isInstalled, psf->isAction))
+        {
+            if (!wzPreviousFilterRoot || CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, 0, wzPreviousFilterRoot, -1, psf->wzFilterRoot, -1))
+            {
+                if (pwzLoadOrder)
+                {
+                    hr = ScaWriteMetabaseValue(piMetabase, wzPreviousFilterRoot, L"", MD_FILTER_LOAD_ORDER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)pwzLoadOrder);
+                    ExitOnFailure(hr, "Failed to write filter load order to metabase");
+
+                    ReleaseNullStr(pwzLoadOrder);
+                }
+
+                hr = ReadFilterLoadOrder(piMetabase, psf->wzFilterRoot, &pwzLoadOrder);
+                ExitOnFailure(hr, "Failed to read filter load order.");
+
+                wzPreviousFilterRoot = psf->wzFilterRoot;
+            }
+
+            hr = RemoveFilterFromLoadOrder(psf->wzKey, &pwzLoadOrder);
+            ExitOnFailure(hr, "Failed to remove filter '%ls' from load order", psf->wzKey);
+
+            // remove the filter from the load order and remove the filter's key
+            if (0 != lstrlenW(psf->wzFilterRoot))
+            {
+                hr = ScaDeleteMetabaseKey(piMetabase, psf->wzFilterRoot, psf->wzKey);
+                ExitOnFailure(hr, "Failed to remove web '%ls' from metabase", psf->wzKey);
+            }
+        }
+
+        psf = psf->psfNext;
+    }
+
+    if (pwzLoadOrder)
+    {
+        Assert(wzPreviousFilterRoot && *wzPreviousFilterRoot);
+
+        hr = ScaWriteMetabaseValue(piMetabase, wzPreviousFilterRoot, L"", MD_FILTER_LOAD_ORDER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)pwzLoadOrder);
+        ExitOnFailure(hr, "Failed to write filter load order to metabase");
+    }
+
+LExit:
+    return hr;
+}
+
+
+void ScaFiltersFreeList(
+    __in SCA_FILTER* psfList
+    )
+{
+    SCA_FILTER* psfDelete = psfList;
+    while (psfList)
+    {
+        psfDelete = psfList;
+        psfList = psfList->psfNext;
+
+        MemFree(psfDelete);
+    }
+}
+
+HRESULT AddFilterToList(
+    __inout SCA_FILTER** ppsfList)
+{
+    HRESULT hr = S_OK;
+    SCA_FILTER* psf = static_cast<SCA_FILTER*>(MemAlloc(sizeof(SCA_FILTER), TRUE));
+    ExitOnNull(psf, hr, E_OUTOFMEMORY, "failed to add filter to filter list");
+
+    psf->psfNext = *ppsfList;
+    *ppsfList = psf;
+
+LExit:
+    return hr;
+}
+
+// private helper functions
+
+
+static HRESULT ReadFilterLoadOrder(
+    __in IMSAdminBase* piMetabase,
+    __in LPCWSTR wzFilterRoot,
+    __out LPWSTR *ppwzLoadOrder
+    )
+{
+    HRESULT hr = S_OK;
+    METADATA_HANDLE mhRoot = NULL;
+
+    METADATA_RECORD mr;
+    DWORD dwRequired = 0;
+    DWORD cchData = 255;
+
+    ::ZeroMemory(&mr, sizeof(mr));
+    mr.dwMDIdentifier = MD_FILTER_LOAD_ORDER;
+    mr.dwMDAttributes = METADATA_NO_ATTRIBUTES;
+    mr.dwMDUserType = IIS_MD_UT_SERVER;
+    mr.dwMDDataType = ALL_METADATA;
+    mr.dwMDDataLen = cchData;
+    mr.pbMDData = static_cast<BYTE*>(MemAlloc(mr.dwMDDataLen * sizeof(WCHAR), TRUE));
+    ExitOnNull(mr.pbMDData, hr, E_OUTOFMEMORY, "failed to allocate memory for MDData in metadata record");
+
+    hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, wzFilterRoot, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE, 10, &mhRoot);
+    for (int i = 30; i > 0 && HRESULT_FROM_WIN32(ERROR_PATH_BUSY) == hr; i--)
+    {
+        ::Sleep(1000);
+        WcaLog(LOGMSG_STANDARD, "Failed to open root key, retrying %d time(s)...", i);
+        hr = piMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, wzFilterRoot, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE, 10, &mhRoot);
+    }
+
+    if (SUCCEEDED(hr))
+    {
+        hr = piMetabase->GetData(mhRoot, L"", &mr, &dwRequired);
+        if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr)
+        {
+            mr.dwMDDataLen = cchData = dwRequired;
+
+            LPVOID pv = MemReAlloc(mr.pbMDData, mr.dwMDDataLen * sizeof(WCHAR), TRUE);
+            ExitOnNull(pv, hr, E_OUTOFMEMORY, "failed to allocate memory for MDData in metadata record");
+            mr.pbMDData = static_cast<BYTE*>(pv);
+
+            hr = piMetabase->GetData(mhRoot, L"", &mr, &dwRequired);
+        }
+    }
+
+    // The /Filters node or /Filters/FilterLoadOrder property might not exist (yet).
+    if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || MD_ERROR_DATA_NOT_FOUND == hr)
+    {
+        hr = S_OK;
+    }
+    ExitOnFailure(hr, "Failed to get filter load order.");
+
+    hr = StrAllocString(ppwzLoadOrder, reinterpret_cast<LPCWSTR>(mr.pbMDData), 0);
+    ExitOnFailure(hr, "Failed to allocate string for filter load order.");
+
+LExit:
+    ReleaseMem(mr.pbMDData);
+
+    if (mhRoot)
+    {
+        piMetabase->CloseKey(mhRoot);
+    }
+
+    return hr;
+}
+
+
+static HRESULT AddFilterToLoadOrder(
+    __in LPCWSTR wzFilter,
+    __in int iLoadOrder,
+    __inout LPWSTR *ppwzLoadOrder
+    )
+{
+    HRESULT hr = S_OK;
+    LPCWSTR wzLoadOrder = *ppwzLoadOrder;
+    int cchFilter = lstrlenW(wzFilter);
+    LPWSTR pwzTemp = NULL;
+
+    // If the filter name ends with '\0' or ',' and
+    // the filter name begins at the beginning of the list or with ','
+    // Then we've found the exact filter by name.
+    //
+    // If the filter isn't already in the load order, add it
+    if (wzLoadOrder && *wzLoadOrder)
+    {
+        LPCWSTR pwz = wcsstr(wzLoadOrder, wzFilter);
+
+        if (NULL != pwz &&
+            (L'\0' == *(pwz + cchFilter) || L',' == *(pwz + cchFilter)) &&
+            (pwz == wzLoadOrder || L',' == *(pwz - 1)))
+        {
+            // Filter already in the load order, no work to do.
+        }
+        else
+        {
+            pwz = NULL;
+            if (0 <= iLoadOrder)
+            {
+                pwz = wzLoadOrder;
+                for (int i = 0; i < iLoadOrder && pwz; ++i)
+                {
+                    pwz = wcsstr(pwz, L",");
+                }
+            }
+
+            if (NULL == pwz) // put the filter at the end of the order
+            {
+                Assert(wzLoadOrder && *wzLoadOrder);
+
+                // tack on a comma since there are other filters in the order
+                hr = StrAllocConcat(ppwzLoadOrder, L",", 1);
+                ExitOnFailure(hr, "Failed to append a comma to filter load order.");
+
+                hr = StrAllocConcat(ppwzLoadOrder, wzFilter, cchFilter);
+                ExitOnFailure(hr, "Failed to append the filter on to the load order.");
+            }
+            else if (L',' == *pwz) // put the filter in the middle of the order
+            {
+                hr = StrAllocString(&pwzTemp, wzLoadOrder, pwz - wzLoadOrder + 1);
+                ExitOnFailure(hr, "Failed to copy first half of filter load order to temp string.");
+
+                hr = StrAllocConcat(&pwzTemp, wzFilter, 0);
+                ExitOnFailure(hr, "Failed to copy filter into load order.");
+
+                hr = StrAllocConcat(&pwzTemp, pwz, 0);
+                ExitOnFailure(hr, "Failed to copy remaining filter load order back onto load order.");
+
+                hr = StrAllocString(ppwzLoadOrder, pwzTemp, 0);
+                ExitOnFailure(hr, "Failed to copy temp string to load order string.");
+            }
+            else // put the filter at the beginning of the order
+            {
+                hr = StrAllocPrefix(ppwzLoadOrder, L",", 1);
+                ExitOnFailure(hr, "Failed to prepend a comma to filter load order.");
+
+                hr = StrAllocPrefix(ppwzLoadOrder, wzFilter, cchFilter);
+                ExitOnFailure(hr, "Failed to prepend the filter on to the load order.");
+            }
+        }
+    }
+    else
+    {
+        hr = StrAllocString(ppwzLoadOrder, wzFilter, cchFilter);
+        ExitOnFailure(hr, "Failed to add filter to load order.");
+    }
+
+LExit:
+    ReleaseStr(pwzTemp);
+    return hr;
+}
+
+
+static HRESULT RemoveFilterFromLoadOrder(
+    __in LPCWSTR wzFilter,
+    __inout LPWSTR *ppwzLoadOrder
+    )
+{
+    HRESULT hr = S_OK;
+    int cchFilter = lstrlenW(wzFilter);
+
+    LPCWSTR pwzStart = NULL;
+    LPWSTR pwzFind = NULL;
+
+    pwzStart = pwzFind = *ppwzLoadOrder;
+    while (NULL != (pwzFind = wcsstr(pwzFind, wzFilter)))
+    {
+        // Make sure to only match [wzFilter] and NOT foo[wzFilter]bar
+        if (pwzFind == pwzStart || L',' == *(pwzFind - 1))
+        {
+            int cchRemainder = lstrlenW(pwzFind) - cchFilter + 1; // add one to include the null terminator
+
+            if (L'\0' == *(pwzFind + cchFilter))
+            {
+                if (pwzFind == pwzStart)
+                {
+                    memmove(pwzFind, pwzFind + cchFilter, cchRemainder * sizeof(WCHAR)); // copy down the null terminator
+                }
+                else
+                {
+                    memmove(pwzFind - 1, pwzFind + cchFilter, cchRemainder * sizeof(WCHAR)); // copy down the null terminator over top the trailing ","
+                }
+            }
+            else if (L',' == *(pwzFind + cchFilter))
+            {
+                memmove(pwzFind, pwzFind + cchFilter + 1, (cchRemainder - 1) * sizeof(WCHAR)); // skip copying the ","
+            }
+            else // skip past the partial match
+            {
+                pwzFind = pwzFind + cchFilter;
+            }
+        }
+        else // skip past the partial match
+        {
+            pwzFind = pwzFind + cchFilter;
+        }
+    }
+
+//LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+#include "scaweb.h"
+
+enum eFilterQuery { fqWeb = 1, fqFilter, fqComponent , fqPath, fqDescription, fqFlags, fqLoadOrder, fqInstalled, fqAction };
+
+struct SCA_FILTER
+{
+	// darwin information
+	WCHAR wzKey[MAX_DARWIN_KEY + 1];
+	WCHAR wzComponent[MAX_DARWIN_KEY + 1];
+	INSTALLSTATE isInstalled;
+	INSTALLSTATE isAction;
+
+	// metabase information
+	WCHAR wzWebKey[MAX_DARWIN_KEY + 1];
+	WCHAR wzWebBase[METADATA_MAX_NAME_LEN + 1];
+	WCHAR wzFilterRoot[METADATA_MAX_NAME_LEN + 1];
+
+	// iis configuation information
+	WCHAR wzPath[MAX_PATH];
+	WCHAR wzDescription[MAX_DARWIN_COLUMN + 1];
+	int iFlags;
+	int iLoadOrder;
+
+	SCA_FILTER* psfNext;
+};
+
+
+// prototypes
+HRESULT AddFilterToList(
+    __in SCA_FILTER** ppsfList
+    );
+
+UINT __stdcall ScaFiltersRead(IMSAdminBase* piMetabase,
+                              SCA_WEB* pswList, __in WCA_WRAPQUERY_HANDLE hWebBaseQuery, SCA_FILTER** ppsfList,
+                              __inout LPWSTR *ppwzCustomActionData);
+
+HRESULT ScaFiltersInstall(IMSAdminBase* piMetabase, SCA_FILTER* psfList);
+
+HRESULT ScaFiltersUninstall(IMSAdminBase* piMetabase, SCA_FILTER* psfList);
+
+void ScaFiltersFreeList(SCA_FILTER* psfList);
+
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 @@
+// 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.
+
+#include "precomp.h"
+
+static HRESULT WriteFilter(const SCA_FILTER* psf);
+
+UINT __stdcall ScaFiltersRead7(
+    __in SCA_WEB7* pswList,
+    __in WCA_WRAPQUERY_HANDLE /*hWebBaseQuery*/,
+    __inout SCA_FILTER** ppsfList,
+    __inout LPWSTR *ppwzCustomActionData
+    )
+{
+    HRESULT hr = S_OK;
+    MSIHANDLE hRec;
+    INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN;
+    INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN;
+    SCA_FILTER* psf;
+
+    LPWSTR pwzData = NULL;
+    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
+    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead");
+
+    if (0 == WcaGetQueryRecords(hWrapQuery))
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ScaFiltersRead() - no IIsFilter table");
+        ExitFunction1(hr = S_FALSE);
+    }
+
+    // loop through all the filters
+    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
+    {
+        // Get the Component first.  If the component is not being modified during
+        // this transaction, skip processing this whole record.
+        // get the darwin information
+        hr = WcaGetRecordString(hRec, fqComponent, &pwzData);
+        ExitOnFailure(hr, "failed to get IIsFilter.Component");
+
+        hr = WcaGetRecordInteger(hRec, fqInstalled, (int *)&isInstalled);
+        ExitOnFailure(hr, "Failed to get Component installed state for IIs filter");
+
+        hr = WcaGetRecordInteger(hRec, fqAction, (int *)&isAction);
+        ExitOnFailure(hr, "Failed to get Component action state for IIs filter");
+
+        if (!WcaIsInstalling(isInstalled, isAction) &&
+            !WcaIsReInstalling(isInstalled, isAction) &&
+            !WcaIsUninstalling(isInstalled, isAction))
+        {
+            continue; // skip this record.
+        }
+
+        hr = AddFilterToList(ppsfList);
+        ExitOnFailure(hr, "failed to add filter to list");
+
+        psf = *ppsfList;
+
+        hr = ::StringCchCopyW(psf->wzComponent, countof(psf->wzComponent), pwzData);
+        ExitOnFailure(hr, "failed to copy component name: %ls", pwzData);
+
+        psf->isInstalled = isInstalled;
+        psf->isAction = isAction;
+
+        hr = WcaGetRecordString(hRec, fqWeb, &pwzData);
+        ExitOnFailure(hr, "Failed to get Web for VirtualDir");
+
+        if (*pwzData)
+        {
+            hr = ScaWebsGetBase7(pswList, pwzData, psf->wzFilterRoot, countof(psf->wzFilterRoot));
+            if (FAILED(hr))
+            {
+                WcaLog(LOGMSG_VERBOSE, "Could not find site for filter: %ls. Result 0x%x ", psf->wzFilterRoot, hr);
+                hr = S_OK;
+            }
+        }
+        else
+        {
+            hr = ::StringCchCopyW(psf->wzFilterRoot, countof(psf->wzFilterRoot), L"/");
+            ExitOnFailure(hr, "Failed to allocate global filter base string");
+        }
+
+        // filter Name key
+        hr = WcaGetRecordString(hRec, fqFilter, &pwzData);
+        ExitOnFailure(hr, "Failed to get Filter.Filter");
+        hr = ::StringCchCopyW(psf->wzKey, countof(psf->wzKey), pwzData);
+        ExitOnFailure(hr, "Failed to copy key string to filter object");
+
+        // filter path
+        hr = WcaGetRecordString(hRec, fqPath, &pwzData);
+        ExitOnFailure(hr, "Failed to get Filter.Path");
+        hr = ::StringCchCopyW(psf->wzPath, countof(psf->wzPath), pwzData);
+        ExitOnFailure(hr, "Failed to copy path string to filter object");
+
+        // filter description -- not supported in iis 7
+        hr = WcaGetRecordString(hRec, fqDescription, &pwzData);
+        ExitOnFailure(hr, "Failed to get Filter.Description");
+        hr = ::StringCchCopyW(psf->wzDescription, countof(psf->wzDescription), pwzData);
+        ExitOnFailure(hr, "Failed to copy description string to filter object");
+
+        // filter flags
+        //What are these
+        hr = WcaGetRecordInteger(hRec, fqFlags, &psf->iFlags);
+        ExitOnFailure(hr, "Failed to get Filter.Flags");
+
+        // filter load order
+        hr = WcaGetRecordInteger(hRec, fqLoadOrder, &psf->iLoadOrder);
+        ExitOnFailure(hr, "Failed to get Filter.LoadOrder");
+    }
+
+    if (E_NOMOREITEMS == hr)
+    {
+        hr = S_OK;
+    }
+    ExitOnFailure(hr, "Failure while processing filters");
+
+LExit:
+    WcaFinishUnwrapQuery(hWrapQuery);
+
+    ReleaseStr(pwzData);
+
+    return hr;
+}
+
+
+HRESULT ScaFiltersInstall7(
+    __in SCA_FILTER* psfList
+    )
+{
+    HRESULT hr = S_OK;
+    SCA_FILTER* psf = psfList;
+
+    if (!psf)
+    {
+        ExitFunction();
+    }
+    //write global filters
+    hr = ScaWriteConfigID(IIS_FILTER_GLOBAL_BEGIN);
+    ExitOnFailure(hr, "Failed to write filter begin ID");
+    while (psf)
+    {
+        if (WcaIsInstalling(psf->isInstalled, psf->isAction))
+        {
+            if (0 == wcscmp(psf->wzFilterRoot, L"/"))
+            {
+                hr = WriteFilter(psf);
+            }
+        }
+        psf = psf->psfNext;
+    }
+    hr = ScaWriteConfigID(IIS_FILTER_END);
+    ExitOnFailure(hr, "Failed to write filter ID");
+
+    psf = psfList;
+
+    //Write Web Site Filters
+    hr = ScaWriteConfigID(IIS_FILTER_BEGIN);
+    ExitOnFailure(hr, "Failed to write filter begin ID");
+    while (psf)
+    {
+        if (WcaIsInstalling(psf->isInstalled, psf->isAction))
+        {
+            if (0 != wcscmp(psf->wzFilterRoot, L"/"))
+            {
+                hr = WriteFilter(psf);
+            }
+        }
+        psf = psf->psfNext;
+    }
+    hr = ScaWriteConfigID(IIS_FILTER_END);
+    ExitOnFailure(hr, "Failed to write filter ID");
+
+LExit:
+
+    return hr;
+}
+static HRESULT WriteFilter(const SCA_FILTER* psf)
+{
+    HRESULT hr = S_OK;
+
+    hr = ScaWriteConfigID(IIS_FILTER);
+    ExitOnFailure(hr, "Failed to write filter begin ID");
+
+    hr = ScaWriteConfigID(IIS_CREATE);
+    ExitOnFailure(hr, "Failed to write filter create ID");
+
+    //filter Name key
+    hr = ScaWriteConfigString(psf->wzKey);
+    ExitOnFailure(hr, "Failed to write key name for filter '%ls'", psf->wzKey);
+
+    //web site name
+    hr = ScaWriteConfigString(psf->wzFilterRoot);
+    ExitOnFailure(hr, "Failed to write filter web root ");
+
+    // filter path
+    hr = ScaWriteConfigString(psf->wzPath);
+    ExitOnFailure(hr, "Failed to write Path for filter '%ls'", psf->wzKey);
+
+    //filter load order
+    hr = ScaWriteConfigInteger(psf->iLoadOrder);
+    ExitOnFailure(hr, "Failed to write load order for filter '%ls'", psf->wzKey);
+
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaFiltersUninstall7(
+    __in SCA_FILTER* psfList
+    )
+{
+    HRESULT hr = S_OK;
+    SCA_FILTER* psf = psfList;
+
+    if (!psf)
+    {
+        ExitFunction1(hr = S_OK);
+    }
+
+    //Uninstall global filters
+    hr = ScaWriteConfigID(IIS_FILTER_GLOBAL_BEGIN);
+    ExitOnFailure(hr, "Failed to write filter begin ID");
+
+    while (psf)
+    {
+        if (WcaIsUninstalling(psf->isInstalled, psf->isAction))
+        {
+            if (0 == wcscmp(psf->wzFilterRoot, L"/"))
+            {
+                hr = ScaWriteConfigID(IIS_FILTER);
+                ExitOnFailure(hr, "Failed to write filter begin ID");
+
+                hr = ScaWriteConfigID(IIS_DELETE);
+                ExitOnFailure(hr, "Failed to write filter create ID");
+
+                //filter Name key
+                hr = ScaWriteConfigString(psf->wzKey);
+                ExitOnFailure(hr, "Failed to write key name for filter '%ls'", psf->wzKey);
+
+                //web site name
+                hr = ScaWriteConfigString(psf->wzFilterRoot);
+                ExitOnFailure(hr, "Failed to write filter web root ");
+
+            }
+        }
+        psf = psf->psfNext;
+    }
+
+    hr = ScaWriteConfigID(IIS_FILTER_END);
+    ExitOnFailure(hr, "Failed to write filter ID");
+
+    psf = psfList;
+
+    //Uninstall website filters
+    hr = ScaWriteConfigID(IIS_FILTER_BEGIN);
+    ExitOnFailure(hr, "Failed to write filter begin ID");
+    while (psf)
+    {
+        if (WcaIsUninstalling(psf->isInstalled, psf->isAction))
+        {
+            if (0 != wcscmp(psf->wzFilterRoot, L"/"))
+            {
+                hr = ScaWriteConfigID(IIS_FILTER);
+                ExitOnFailure(hr, "Failed to write filter begin ID");
+
+                hr = ScaWriteConfigID(IIS_DELETE);
+                ExitOnFailure(hr, "Failed to write filter create ID");
+
+                //filter Name key
+                hr = ScaWriteConfigString(psf->wzKey);
+                ExitOnFailure(hr, "Failed to write key name for filter '%ls'", psf->wzKey);
+
+                //web site name
+                hr = ScaWriteConfigString(psf->wzFilterRoot);
+                ExitOnFailure(hr, "Failed to write filter web root ");
+            }
+        }
+        psf = psf->psfNext;
+    }
+    hr = ScaWriteConfigID(IIS_FILTER_END);
+    ExitOnFailure(hr, "Failed to write filter ID");
+
+LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+#include "scaweb.h"
+
+// prototypes
+UINT __stdcall ScaFiltersRead7(
+    __in SCA_WEB7* pswList,
+    __in WCA_WRAPQUERY_HANDLE hWebBaseQuery, 
+    __inout SCA_FILTER** ppsfList,
+    __inout LPWSTR *ppwzCustomActionData
+    );
+
+HRESULT ScaFiltersInstall7(
+    SCA_FILTER* psfList
+    );
+
+HRESULT ScaFiltersUninstall7(
+    SCA_FILTER* psfList
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+enum eHttpHeaderQuery { hhqName = 1, hhqParentType, hhqParentValue, hhqValue, hhqAttributes};
+
+static HRESULT AddHttpHeaderToList(
+    __in SCA_HTTP_HEADER** ppshhList
+    );
+
+
+void ScaHttpHeaderFreeList(
+    __in SCA_HTTP_HEADER* pshhList
+    )
+{
+    SCA_HTTP_HEADER* pshhDelete = pshhList;
+    while (pshhList)
+    {
+        pshhDelete = pshhList;
+        pshhList = pshhList->pshhNext;
+
+        MemFree(pshhDelete);
+    }
+}
+
+
+HRESULT ScaHttpHeaderRead(
+    __in SCA_HTTP_HEADER** ppshhList,
+    __inout LPWSTR *ppwzCustomActionData
+    )
+{
+    Assert(ppshhList);
+
+    HRESULT hr = S_OK;
+        MSIHANDLE hRec;
+    LPWSTR pwzData = NULL;
+    SCA_HTTP_HEADER* pshh = NULL;
+    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
+
+    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead");
+
+    if (0 == WcaGetQueryRecords(hWrapQuery))
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ScaHttpHeaderRead() - required tables not present.");
+        ExitFunction1(hr = S_FALSE);
+    }
+
+    // loop through all the HTTP headers
+    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
+    {
+        hr = AddHttpHeaderToList(ppshhList);
+        ExitOnFailure(hr, "failed to add http header to list");
+
+        pshh = *ppshhList;
+
+        hr = WcaGetRecordInteger(hRec, hhqParentType, &(pshh->iParentType));
+        ExitOnFailure(hr, "failed to get IIsHttpHeader.ParentType");
+
+        hr = WcaGetRecordString(hRec, hhqParentValue, &pwzData);
+        ExitOnFailure(hr, "Failed to get IIsHttpHeader.ParentValue");
+        hr = ::StringCchCopyW(pshh->wzParentValue, countof(pshh->wzParentValue), pwzData);
+        ExitOnFailure(hr, "Failed to copy IIsHttpHeader.ParentValue");
+
+        hr = WcaGetRecordString(hRec, hhqName, &pwzData);
+        ExitOnFailure(hr, "Failed to get IIsHttpHeader.Name");
+        hr = ::StringCchCopyW(pshh->wzName, countof(pshh->wzName), pwzData);
+        ExitOnFailure(hr, "Failed to copy IIsHttpHeader.Name");
+
+        hr = WcaGetRecordString(hRec, hhqValue, &pwzData);
+        ExitOnFailure(hr, "Failed to get IIsHttpHeader.Value");
+        hr = ::StringCchCopyW(pshh->wzValue, countof(pshh->wzValue), pwzData);
+        ExitOnFailure(hr, "Failed to copy IIsHttpHeader.Value");
+
+        hr = WcaGetRecordInteger(hRec, hhqAttributes, &(pshh->iAttributes));
+        ExitOnFailure(hr, "failed to get IIsHttpHeader.Attributes");
+    }
+
+    if (E_NOMOREITEMS == hr)
+    {
+        hr = S_OK;
+    }
+    ExitOnFailure(hr, "Failure while processing web errors");
+
+LExit:
+    WcaFinishUnwrapQuery(hWrapQuery);
+
+    ReleaseStr(pwzData);
+
+    return hr;
+}
+
+
+HRESULT ScaGetHttpHeader(
+    __in int iParentType,
+    __in LPCWSTR wzParentValue,
+    __in SCA_HTTP_HEADER** ppshhList,
+    __out SCA_HTTP_HEADER** ppshhOut
+    )
+{
+    HRESULT hr = S_OK;
+    SCA_HTTP_HEADER* pshhAdd = NULL;
+    SCA_HTTP_HEADER* pshhLast = NULL;
+
+    *ppshhOut = NULL;
+
+    if (!*ppshhList)
+    {
+        return hr;
+    }
+
+    SCA_HTTP_HEADER* pshh = *ppshhList;
+    while (pshh)
+    {
+        if (iParentType == pshh->iParentType && CSTR_EQUAL == ::CompareStringW(LOCALE_SYSTEM_DEFAULT, 0, wzParentValue, -1, pshh->wzParentValue, -1))
+        {
+            // Found a match, take this one out of the list and add it to the matched out list
+            pshhAdd = pshh;
+
+            if (pshhLast)
+            {
+                // 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)
+                pshhLast->pshhNext = pshhAdd->pshhNext;
+            }
+            else
+            {
+                // If we are at the beginning (no pshhLast) update the beginning (since we're taking it)
+                *ppshhList = pshh->pshhNext;
+            }
+            pshh = pshh->pshhNext; // move on
+
+            // Add the one we've removed to the beginning of the out list
+            pshhAdd->pshhNext = *ppshhOut;
+            *ppshhOut = pshhAdd;
+        }
+        else
+        {
+            pshhLast = pshh; // remember the last we that didn't match
+            pshh = pshh->pshhNext; // move on
+        }
+    }
+
+    return hr;
+}
+
+
+HRESULT ScaWriteHttpHeader(
+    __in IMSAdminBase* piMetabase,
+    __in LPCWSTR wzRoot,
+    __in SCA_HTTP_HEADER* pshhList
+    )
+{
+    Assert(piMetabase && pshhList);
+
+    HRESULT hr = S_OK;
+    METADATA_RECORD mr = { 0 };
+    DWORD cchData = 0;
+    LPWSTR pwzSearchKey = NULL;
+    LPWSTR pwz = NULL;
+    LPWSTR pwzHeaders = NULL;
+    LPWSTR pwzNewHeader = NULL;
+    DWORD_PTR dwFoundHeaderIndex = 0;
+    LPCWSTR wzFoundHeader = NULL;
+    BOOL fOldValueFound = FALSE;
+
+    ExitOnNull(wzRoot, hr, E_INVALIDARG, "Failed to write HTTP header, because no root was provided");
+
+    Assert(*wzRoot);
+
+    // Check if HTTP header already exist here.
+    mr.dwMDIdentifier = MD_HTTP_CUSTOM;
+    mr.dwMDAttributes = METADATA_INHERIT;
+    mr.dwMDUserType = IIS_MD_UT_SERVER;
+    mr.dwMDDataType = ALL_METADATA;
+    mr.dwMDDataLen = cchData = 0;
+    mr.pbMDData = NULL;
+
+    hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzRoot, &mr);
+    if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || MD_ERROR_DATA_NOT_FOUND == hr)
+    {
+        //
+        // If we don't have any HTTP Headers already, move up to get the parent headers.
+        // TODO: Make it configurable to not inherit HTTP Headers
+        //
+        hr = StrAllocConcat(&pwzSearchKey, wzRoot, 0);
+        ExitOnFailure(hr, "Failed to copy root string: %ls", wzRoot);
+
+        pwz = pwzSearchKey + lstrlenW(pwzSearchKey);
+        while (NULL == pwzHeaders)
+        {
+            // find the last slash
+            while (*pwz != '/' && pwz != pwzSearchKey)
+            {
+                --pwz;
+            }
+
+            if (pwz == pwzSearchKey)
+            {
+                break;
+            }
+
+            *pwz = L'\0';
+
+            // Try here.  If it's not found, keep walking up the path
+            hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, pwzSearchKey, &mr);
+            if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || MD_ERROR_DATA_NOT_FOUND == hr)
+            {
+                hr = S_FALSE;
+            }
+            ExitOnFailure(hr, "Failed to find search for HTTP headers for web root: %ls while walking up the tree", wzRoot);
+
+            if (S_OK == hr)
+            {
+                hr = StrAllocString(&pwzHeaders, reinterpret_cast<LPWSTR>(mr.pbMDData), 0);
+                ExitOnFailure(hr, "Failed to allocate parent HTTP header string");
+                break;
+            }
+        }
+    }
+    else
+    {
+        hr = StrAllocString(&pwzHeaders, reinterpret_cast<LPWSTR>(mr.pbMDData), 0);
+        ExitOnFailure(hr, "Failed to allocate HTTP header string");
+    }
+    ExitOnFailure(hr, "Failed while searching for default HTTP headers to start with for web root: %ls", wzRoot);
+
+    // Loop through the HTTP headers
+    for (SCA_HTTP_HEADER* pshh = pshhList; pshh; pshh = pshh->pshhNext)
+    {
+        fOldValueFound = FALSE; // assume a HTTP Header match will not be found
+
+        hr = StrAllocFormatted(&pwzNewHeader, L"%s: ", pshh->wzName);
+        ExitOnFailure(hr, "Failed to allocate header name");
+
+        if (NULL != pwzHeaders && *pwzHeaders)
+        {
+            // Try to find a matching header already in the list
+            hr = MultiSzFindSubstring(pwzHeaders, pwzNewHeader, &dwFoundHeaderIndex, &wzFoundHeader);
+            ExitOnFailure(hr, "Failed while searching for existing HTTP header.");
+
+            // If there was a substring HTTP header match, make sure the match was at the beginning 
+            // of the string because that is the HTTP header name.
+            if (S_OK == hr)
+            {
+                DWORD cchMatch = lstrlenW(pwzNewHeader);
+                if (CSTR_EQUAL == ::CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, pwzNewHeader, cchMatch, wzFoundHeader, cchMatch))
+                {
+                    fOldValueFound = TRUE;
+                    break;
+                }
+            }
+        }
+
+        // Add the value on to the header name now.
+        hr = StrAllocConcat(&pwzNewHeader, pshh->wzValue, 0);
+        ExitOnFailure(hr, "Failed to add value on to HTTP header name.");
+
+        // If we have something to replace, replace it, otherwise, put it at the beginning (order shouldn't matter)
+        if (fOldValueFound)
+        {
+            if (NULL == pwzHeaders)
+            {
+                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!");
+            }
+            hr = MultiSzReplaceString(&pwzHeaders, dwFoundHeaderIndex, pwzNewHeader);
+            ExitOnFailure(hr, "Failed to replace old HTTP header with new HTTP header");
+        }
+        else
+        {
+            hr = MultiSzPrepend(&pwzHeaders, NULL, pwzNewHeader);
+            ExitOnFailure(hr, "Failed to prepend new HTTP header");
+        }
+    }
+
+    // now write the HttpCustom to the metabase
+    hr = ScaWriteMetabaseValue(piMetabase, wzRoot, NULL, MD_HTTP_CUSTOM, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, pwzHeaders);
+    ExitOnFailure(hr, "Failed to write HTTP Headers to metabase");
+
+LExit:
+    MetaFreeValue(&mr);
+
+    ReleaseStr(pwzNewHeader);
+    ReleaseStr(pwzHeaders);
+    ReleaseStr(pwzSearchKey);
+
+    return hr;
+}
+
+
+HRESULT ScaHttpHeaderCheckList(
+    __in SCA_HTTP_HEADER* pshhList
+    )
+{
+    if (!pshhList)
+    {
+        return S_OK;
+    }
+
+    while (pshhList)
+    {
+        WcaLog(LOGMSG_STANDARD, "Http Header: %ls for parent: %ls not used!", pshhList->wzName, pshhList->wzParentValue);
+        pshhList = pshhList->pshhNext;
+    }
+
+    return E_FAIL;
+}
+
+
+static HRESULT AddHttpHeaderToList(
+    __in SCA_HTTP_HEADER** ppshhList
+    )
+{
+    HRESULT hr = S_OK;
+
+    SCA_HTTP_HEADER* pshh = static_cast<SCA_HTTP_HEADER*>(MemAlloc(sizeof(SCA_HTTP_HEADER), TRUE));
+    ExitOnNull(pshh, hr, E_OUTOFMEMORY, "failed to allocate memory for new http header list element");
+
+    pshh->pshhNext = *ppshhList;
+    *ppshhList = pshh;
+
+LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+enum eHttpHeaderParentType { hhptVDir = 1, hhptWeb };
+
+struct SCA_HTTP_HEADER
+{
+    int iParentType;
+    WCHAR wzParentValue[MAX_DARWIN_KEY + 1];
+
+    WCHAR wzName[MAX_PATH];
+    WCHAR wzValue[MAX_PATH];
+    int iAttributes;
+
+    SCA_HTTP_HEADER* pshhNext;
+};
+
+// prototypes
+HRESULT ScaHttpHeaderRead(
+    __in SCA_HTTP_HEADER **ppshhList,
+    __inout LPWSTR *ppwzCustomActionData
+    );
+void ScaHttpHeaderFreeList(
+    __in SCA_HTTP_HEADER *pshhList
+    );
+HRESULT ScaHttpHeaderCheckList(
+    __in SCA_HTTP_HEADER* pshhList
+    );
+HRESULT ScaGetHttpHeader(
+    __in int iParentType,
+    __in LPCWSTR wzParentValue,
+    __in SCA_HTTP_HEADER** ppshhList,
+    __out SCA_HTTP_HEADER** ppshhOut
+    );
+HRESULT ScaWriteHttpHeader(
+    __in IMSAdminBase* piMetabase,
+    LPCWSTR wzRoot,
+    SCA_HTTP_HEADER* pshhList
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+HRESULT ScaGetHttpHeader7(
+    __in int iParentType,
+    __in_z LPCWSTR wzParentValue,
+    __in SCA_HTTP_HEADER** ppshhList,
+    __out SCA_HTTP_HEADER** ppshhOut
+    )
+{
+    HRESULT hr = S_OK;
+    SCA_HTTP_HEADER* pshhAdd = NULL;
+    SCA_HTTP_HEADER* pshhLast = NULL;
+
+    *ppshhOut = NULL;
+
+    if (!*ppshhList)
+    {
+        return hr;
+    }
+
+    SCA_HTTP_HEADER* pshh = *ppshhList;
+    while (pshh)
+    {
+        if (iParentType == pshh->iParentType && 0 == wcscmp(wzParentValue, pshh->wzParentValue))
+        {
+            // Found a match, take this one out of the list and add it to the matched out list
+            pshhAdd = pshh;
+
+            if (pshhLast)
+            {
+                // 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)
+                pshhLast->pshhNext = pshhAdd->pshhNext;
+            }
+            else
+            {
+                // If we are at the beginning (no pshhLast) update the beginning (since we're taking it)
+                *ppshhList = pshh->pshhNext;
+            }
+            pshh = pshh->pshhNext; // move on
+
+            // Add the one we've removed to the beginning of the out list
+            pshhAdd->pshhNext = *ppshhOut;
+            *ppshhOut = pshhAdd;
+        }
+        else
+        {
+            pshhLast = pshh; // remember the last we that didn't match
+            pshh = pshh->pshhNext; // move on
+        }
+    }
+
+    return hr;
+}
+
+
+HRESULT ScaWriteHttpHeader7(
+     __in_z LPCWSTR wzWebName,
+     __in_z LPCWSTR wzRoot,
+     SCA_HTTP_HEADER* pshhList
+    )
+{
+
+    HRESULT hr = S_OK;
+
+    hr = ScaWriteConfigID(IIS_HTTP_HEADER_BEGIN);
+    ExitOnFailure(hr, "Fail to write httpHeader begin ID");
+
+    hr = ScaWriteConfigString(wzWebName);
+    ExitOnFailure(hr, "Fail to write httpHeader Web Key");
+
+    hr = ScaWriteConfigString(wzRoot);
+    ExitOnFailure(hr, "Fail to write httpHeader Vdir key");
+
+    // Loop through the HTTP headers
+    for (SCA_HTTP_HEADER* pshh = pshhList; pshh; pshh = pshh->pshhNext)
+    {
+        hr = ScaWriteConfigID(IIS_HTTP_HEADER);
+        ExitOnFailure(hr, "Fail to write httpHeader ID");
+
+        hr = ScaWriteConfigString(pshh->wzName);
+        ExitOnFailure(hr, "Fail to write httpHeader name");
+
+        hr = ScaWriteConfigString(pshh->wzValue);
+        ExitOnFailure(hr, "Fail to write httpHeader value");
+    }
+
+    hr = ScaWriteConfigID(IIS_HTTP_HEADER_END);
+    ExitOnFailure(hr, "Fail to write httpHeader end ID");
+
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaHttpHeaderCheckList7(
+    __in SCA_HTTP_HEADER* pshhList
+    )
+{
+    if (!pshhList)
+    {
+        return S_OK;
+    }
+
+    while (pshhList)
+    {
+        WcaLog(LOGMSG_STANDARD, "Http Header: %ls for parent: %ls not used!", pshhList->wzName, pshhList->wzParentValue);
+        pshhList = pshhList->pshhNext;
+    }
+
+    return E_FAIL;
+}
+
+
+//static HRESULT AddHttpHeaderToList(
+//    __in SCA_HTTP_HEADER** ppshhList
+//    )
+//{
+//    HRESULT hr = S_OK;
+//
+//    SCA_HTTP_HEADER* pshh = static_cast<SCA_HTTP_HEADER*>(MemAlloc(sizeof(SCA_HTTP_HEADER), TRUE));
+//    ExitOnNull(pshh, hr, E_OUTOFMEMORY, "failed to allocate memory for new http header list element");
+//
+//    pshh->pshhNext = *ppshhList;
+//    *ppshhList = pshh;
+//
+//LExit:
+//    return hr;
+//}
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 @@
+#pragma once
+// 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.
+
+
+HRESULT ScaGetHttpHeader7(
+    __in int iParentType,
+    __in_z LPCWSTR wzParentValue,
+    __in SCA_HTTP_HEADER** ppshhList,
+    __out SCA_HTTP_HEADER** ppshhOut
+    );
+HRESULT ScaWriteHttpHeader7(
+    __in_z LPCWSTR wzWebName,
+    __in_z LPCWSTR wzRoot,
+    SCA_HTTP_HEADER* pshhList
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+// globals
+LPWSTR vpwzCustomActionData = NULL;
+DWORD vdwCustomActionCost = 0;
+
+HRESULT ScaMetabaseTransaction(__in_z LPCWSTR wzBackup)
+{
+    HRESULT hr = S_OK;
+
+    // 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
+
+    hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"StartMetabaseTransaction"), wzBackup, COST_IIS_TRANSACTIONS);
+    ExitOnFailure(hr, "Failed to schedule StartMetabaseTransaction");
+
+    hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackMetabaseTransaction"), wzBackup, 0);   // rollback cost is irrelevant
+    ExitOnFailure(hr, "Failed to schedule RollbackMetabaseTransaction");
+
+    hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CommitMetabaseTransaction"), wzBackup, 0);  // commit is free
+    ExitOnFailure(hr, "Failed to schedule StartMetabaseTransaction");
+
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaCreateWeb(IMSAdminBase* piMetabase, LPCWSTR /*wzWeb*/, LPCWSTR wzWebBase)
+{
+    Assert(piMetabase);
+
+    HRESULT hr = S_OK;
+    UINT ui = 0;
+
+    hr = ScaCreateMetabaseKey(piMetabase, wzWebBase, L"");
+    ExitOnFailure(hr, "Failed to create web");
+
+    hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsWebServer");
+    ExitOnFailure(hr, "Failed to set key type for web");
+
+    hr = ScaCreateMetabaseKey(piMetabase, wzWebBase, L"Root");
+    ExitOnFailure(hr, "Failed to create web root");
+
+    hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"Root", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsWebVirtualDir");
+    ExitOnFailure(hr, "Failed to set key type for web root");
+
+    ui = 0x4000003e; // 1073741886;    // default directory browsing rights
+    hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"Root", MD_DIRECTORY_BROWSING, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)ui));
+    ExitOnFailure(hr, "Failed to set directory browsing for web");
+
+    hr = ScaCreateMetabaseKey(piMetabase, wzWebBase, L"Filters");
+    ExitOnFailure(hr, "Failed to create web filters root");
+
+    hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"Filters", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsFilters");
+    ExitOnFailure(hr, "Failed to set key for web filters root");
+
+    hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"Filters", MD_FILTER_LOAD_ORDER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"");
+    ExitOnFailure(hr, "Failed to set empty load order for web");
+
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaDeleteApp(IMSAdminBase* piMetabase, LPCWSTR wzWebRoot)
+{
+    Assert(piMetabase);
+    Unused(piMetabase);
+
+    HRESULT hr = S_OK;
+    WCHAR wzKey[METADATA_MAX_NAME_LEN];
+
+    WCHAR* pwzCustomActionData = NULL;
+
+    hr = WcaWriteIntegerToCaData(MBA_DELETEAPP, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase delete app directive to CustomActionData");
+
+    hr = ::StringCchCopyW(wzKey, countof(wzKey), wzWebRoot);
+    ExitOnFailure(hr, "Failed to copy webroot string to key");
+    hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase key to CustomActionData");
+
+    hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_DELETEAPP);
+    ExitOnFailure(hr, "Failed to add ScaDeleteApp action data: %ls cost: %d", pwzCustomActionData, COST_IIS_DELETEAPP);
+
+LExit:
+    ReleaseStr(pwzCustomActionData);
+
+    return hr;
+}
+
+
+HRESULT ScaCreateApp(IMSAdminBase* piMetabase, LPCWSTR wzWebRoot,
+                     DWORD dwIsolation)
+{
+    Assert(piMetabase);
+    Unused(piMetabase);
+
+    HRESULT hr = S_OK;
+    WCHAR wzKey[METADATA_MAX_NAME_LEN];
+    BOOL fInProc = FALSE;
+
+    WCHAR* pwzCustomActionData = NULL;
+
+    hr = WcaWriteIntegerToCaData(MBA_CREATEAPP, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase create app directive to CustomActionData");
+
+    hr = ::StringCchCopyW(wzKey, countof(wzKey), wzWebRoot);
+    ExitOnFailure(hr, "Failed to copy webroot string to key");
+    hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase key to CustomActionData");
+
+    if (0 == dwIsolation)
+        fInProc = TRUE;
+    else
+        fInProc = FALSE;
+
+    hr = WcaWriteIntegerToCaData(fInProc, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add isolation value to CustomActionData");
+
+    hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_CREATEAPP);
+    ExitOnFailure(hr, "Failed to add ScaCreateApp action data: %ls cost: %d", pwzCustomActionData, COST_IIS_CREATEAPP);
+
+LExit:
+    ReleaseStr(pwzCustomActionData);
+
+    return hr;
+}
+
+
+HRESULT ScaCreateMetabaseKey(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
+                             LPCWSTR wzSubKey)
+{
+    Assert(piMetabase);
+    Unused(piMetabase);
+
+    HRESULT hr = S_OK;
+    WCHAR wzKey[METADATA_MAX_NAME_LEN];
+    WCHAR* pwzCustomActionData = NULL;
+
+    hr = ::StringCchCopyW(wzKey, countof(wzKey), wzRootKey);
+    ExitOnFailure(hr, "Failed to copy root key string to key");
+    if (L'/' != *(wzKey + lstrlenW(wzRootKey)))
+    {
+        hr = ::StringCchCatW(wzKey, countof(wzKey), L"/");
+        ExitOnFailure(hr, "Failed to concatenate / to key string");
+    }
+    if (wzSubKey && *wzSubKey)
+    {
+        if (L'/' == *wzSubKey)
+        {
+            hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey + 1);
+            ExitOnFailure(hr, "Failed to concatenate subkey (minus slash) to key string");
+        }
+        else
+        {
+            hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey);
+            ExitOnFailure(hr, "Failed to concatenate subkey to key string");
+        }
+    }
+
+    hr = WcaWriteIntegerToCaData(MBA_CREATEKEY, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase delete key directive to CustomActionData");
+
+    hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase key to CustomActionData");
+
+    hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_CREATEKEY);
+    ExitOnFailure(hr, "Failed to add ScaCreateMetabaseKey action data: %ls cost: %d", pwzCustomActionData, COST_IIS_CREATEKEY);
+
+LExit:
+    ReleaseStr(pwzCustomActionData);
+
+    return hr;
+}
+
+
+HRESULT ScaDeleteMetabaseKey(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
+                             LPCWSTR wzSubKey)
+{
+    Assert(piMetabase);
+    Unused(piMetabase);
+
+    HRESULT hr = S_OK;
+    WCHAR wzKey[METADATA_MAX_NAME_LEN];
+    WCHAR* pwzCustomActionData = NULL;
+
+    hr = ::StringCchCopyW(wzKey, countof(wzKey), wzRootKey);
+    ExitOnFailure(hr, "Failed to copy root key string to key");
+    if (L'/' != *(wzKey + lstrlenW(wzRootKey)))
+    {
+        hr = ::StringCchCatW(wzKey, countof(wzKey), L"/");
+        ExitOnFailure(hr, "Failed to concatenate / to key string");
+    }
+    if (*wzSubKey)
+    {
+        if (L'/' == *wzSubKey)
+        {
+            hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey + 1);
+            ExitOnFailure(hr, "Failed to concatenate subkey (minus slash) to key string");
+        }
+        else
+        {
+            hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey);
+            ExitOnFailure(hr, "Failed to concatenate subkey to key string");
+        }
+    }
+
+    hr = WcaWriteIntegerToCaData(MBA_DELETEKEY, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase delete key directive to CustomActionData");
+
+    hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase key to CustomActionData");
+
+    hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_DELETEKEY);
+    ExitOnFailure(hr, "Failed to add ScaDeleteMetabaseKey action data: %ls cost: %d", pwzCustomActionData, COST_IIS_DELETEKEY);
+
+LExit:
+    ReleaseStr(pwzCustomActionData);
+
+    return hr;
+}
+
+
+HRESULT ScaDeleteMetabaseValue(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
+                              LPCWSTR wzSubKey, DWORD dwIdentifier,
+                              DWORD dwDataType)
+{
+    Assert(piMetabase);
+    Unused(piMetabase);
+
+    HRESULT hr = S_OK;
+    WCHAR wzKey[METADATA_MAX_NAME_LEN];
+    WCHAR* pwzCustomActionData = NULL;
+
+    hr = ::StringCchCopyW(wzKey, countof(wzKey), wzRootKey);
+    ExitOnFailure(hr, "Failed to copy root key string to key");
+    if (L'/' != *(wzKey + lstrlenW(wzRootKey)))
+    {
+        hr = ::StringCchCatW(wzKey, countof(wzKey), L"/");
+        ExitOnFailure(hr, "Failed to concatenate / to key string");
+    }
+
+    if (wzSubKey && *wzSubKey)
+    {
+        if (L'/' == *wzSubKey)
+        {
+            hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey + 1);
+            ExitOnFailure(hr, "Failed to concatenate subkey (minus slash) to key string");
+        }
+        else
+        {
+            hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey);
+            ExitOnFailure(hr, "Failed to concatenate subkey to key string");
+        }
+    }
+
+    hr = WcaWriteIntegerToCaData(MBA_DELETEVALUE, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase write value directive to CustomActionData");
+
+    hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase key to CustomActionData");
+
+    hr = WcaWriteIntegerToCaData(dwIdentifier, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase identifier to CustomActionData");
+
+    hr = WcaWriteIntegerToCaData(dwDataType, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase data type to CustomActionData");
+
+    hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_DELETEVALUE);
+    ExitOnFailure(hr, "Failed to add ScaDeleteMetabaseValue action data: %ls, cost: %d", pwzCustomActionData, COST_IIS_DELETEVALUE);
+
+LExit:
+    ReleaseStr(pwzCustomActionData);
+
+    return hr;
+}
+
+
+#pragma prefast(push)
+#pragma prefast(disable:25120) // Disable "requires count parameter" warning - we do have a way to distinguish buffer sizes in all situations,
+                               // it just depends on the dwDataType, and there's no way to annotate the situation in SAL
+HRESULT ScaWriteMetabaseValue(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
+                              LPCWSTR wzSubKey, DWORD dwIdentifier,
+                              DWORD dwAttributes, DWORD dwUserType,
+                              DWORD dwDataType, LPVOID pvData)
+#pragma prefast(pop)
+{
+    Assert(piMetabase && (pvData || (DWORD_METADATA == dwDataType)));    // pvData may be 0 if it is DWORD data
+    Unused(piMetabase);
+
+    HRESULT hr = S_OK;
+    WCHAR wzKey[METADATA_MAX_NAME_LEN];
+    WCHAR* pwzCustomActionData = NULL;
+
+    if (BINARY_METADATA == dwDataType)
+    {
+        ExitOnNull(pvData, hr, E_INVALIDARG, "Failed to write binary metadata - no data available to write");
+    }
+
+    hr = ::StringCchCopyW(wzKey, countof(wzKey), wzRootKey);
+    ExitOnFailure(hr, "Failed to copy root key string to key");
+    if (L'/' != *(wzKey + lstrlenW(wzRootKey)))
+    {
+        hr = ::StringCchCatW(wzKey, countof(wzKey), L"/");
+        ExitOnFailure(hr, "Failed to concatenate / to key string");
+    }
+    if (wzSubKey && *wzSubKey)
+    {
+        if (L'/' == *wzSubKey)
+        {
+            hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey + 1);
+            ExitOnFailure(hr, "Failed to concatenate subkey (minus slash) to key string");
+        }
+        else
+        {
+            hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey);
+            ExitOnFailure(hr, "Failed to concatenate subkey to key string");
+        }
+    }
+
+    hr = WcaWriteIntegerToCaData(MBA_WRITEVALUE, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase write value directive to CustomActionData");
+
+    hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase key to CustomActionData");
+
+    hr = WcaWriteIntegerToCaData(dwIdentifier, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase identifier to CustomActionData");
+
+    hr = WcaWriteIntegerToCaData(dwAttributes, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase attributes to CustomActionData");
+
+    hr = WcaWriteIntegerToCaData(dwUserType, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase user type to CustomActionData");
+
+    hr = WcaWriteIntegerToCaData(dwDataType, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase data type to CustomActionData");
+
+    switch (dwDataType)
+    {
+    case DWORD_METADATA:
+        hr = WcaWriteIntegerToCaData((DWORD)((DWORD_PTR)pvData), &pwzCustomActionData);
+        break;
+    case STRING_METADATA:
+        hr = WcaWriteStringToCaData((LPCWSTR)pvData, &pwzCustomActionData);
+        break;
+    case MULTISZ_METADATA:
+        {
+        // change NULLs to unprintable character  to create a 'safe' MULTISZ string
+        LPWSTR pwz = (LPWSTR)pvData;
+        for (;;)
+        {
+            if ('\0' == *pwz)
+            {
+                *pwz = MAGIC_MULTISZ_CHAR;
+                if ('\0' == *(pwz + 1))    // second null back to back means end of string
+                    break;
+            }
+
+            ++pwz;
+        }
+
+        hr = WcaWriteStringToCaData((LPCWSTR)pvData, &pwzCustomActionData);
+        }
+        break;
+    case BINARY_METADATA:
+        hr = WcaWriteStreamToCaData(((BLOB*) pvData)->pBlobData, ((BLOB*) pvData)->cbSize, &pwzCustomActionData);
+        break;
+    default:
+        hr = E_UNEXPECTED;
+    }
+    ExitOnFailure(hr, "Failed to add metabase data to CustomActionData");
+
+    // TODO: maybe look the key up and make sure we're not just writing the same value that already there
+
+    hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_WRITEVALUE);
+    ExitOnFailure(hr, "Failed to add ScaWriteMetabaseValue action data: %ls, cost: %d", pwzCustomActionData, COST_IIS_WRITEVALUE);
+
+LExit:
+    ReleaseStr(pwzCustomActionData);
+
+    return hr;
+}
+
+
+HRESULT ScaAddToIisConfiguration(LPCWSTR pwzData, DWORD dwCost)
+{
+    HRESULT hr = S_OK;
+
+    hr = WcaWriteStringToCaData(pwzData, &vpwzCustomActionData);
+    ExitOnFailure(hr, "failed to add to metabase configuration data string: %ls", pwzData);
+
+    vdwCustomActionCost += dwCost;
+
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaWriteConfigurationScript(__in LPCWSTR pwzCaScriptKey)
+{
+    HRESULT hr = S_OK;
+    WCA_CASCRIPT_HANDLE hScript = NULL;
+    LPWSTR pwzHashString = NULL;
+    BYTE rgbActualHash[SHA1_HASH_LEN] = { };
+    DWORD dwHashedBytes = SHA1_HASH_LEN;
+
+    // Create CaScript for communication with WriteMetabaseChanges
+    hr = WcaCaScriptCreate(WCA_ACTION_INSTALL, WCA_CASCRIPT_SCHEDULED, FALSE, pwzCaScriptKey, FALSE, &hScript);
+    ExitOnFailure(hr, "Failed to write ca script for WriteMetabaseChanges script.");
+
+    if (vpwzCustomActionData && *vpwzCustomActionData)
+    {
+        // Write the actual custom action data to the ca script
+        WcaCaScriptWriteString(hScript, vpwzCustomActionData);
+
+        hr = CrypHashBuffer((BYTE*)vpwzCustomActionData, sizeof(vpwzCustomActionData) * sizeof(WCHAR), PROV_RSA_AES, CALG_SHA1, rgbActualHash, dwHashedBytes);
+        ExitOnFailure(hr, "Failed to calculate hash of CustomAction data.");
+
+        hr = StrAlloc(&pwzHashString, ((dwHashedBytes * 2) + 1));
+        ExitOnFailure(hr, "Failed to allocate string for script hash");
+
+        hr = StrHexEncode(rgbActualHash, dwHashedBytes, pwzHashString, ((dwHashedBytes * 2) + 1));
+        ExitOnFailure(hr, "Failed to convert hash bytes to string.");
+
+        WcaLog(LOGMSG_VERBOSE,  "Custom action data hash: %ls", pwzHashString);
+        WcaLog(LOGMSG_TRACEONLY, "Custom action data being written to ca script: %ls", vpwzCustomActionData);
+    }
+    else
+        hr = S_FALSE;
+
+LExit:
+    // Release the string
+    ReleaseStr(vpwzCustomActionData);
+    ReleaseStr(pwzHashString);
+
+    // Flush the ca script to disk as best we can
+    WcaCaScriptFlush(hScript);
+
+    WcaCaScriptClose(hScript, WCA_CASCRIPT_CLOSE_PRESERVE);
+
+    return hr;
+}
+
+
+HRESULT ScaLoadMetabase(IMSAdminBase** ppiMetabase)
+{
+    HRESULT hr = S_OK;
+    UINT er = ERROR_SUCCESS;
+
+    // if IIS was uninstalled (thus no IID_IMSAdminBase) allow the
+    // user to still uninstall this package by clicking "Ignore"
+    do
+    {
+        hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, (void**)ppiMetabase);
+        if (FAILED(hr))
+        {
+            WcaLog(LOGMSG_STANDARD, "failed to get IID_IMSAdminBase Object");
+            er = WcaErrorMessage(msierrIISCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
+            switch (er)
+            {
+            case IDABORT:
+                ExitFunction();   // bail with the error result from the CoCreate to kick off a rollback
+            case IDRETRY:
+                hr = S_FALSE;   // hit me, baby, one more time
+                break;
+            case IDIGNORE:
+                hr = S_OK;  // pretend everything is okay and bail
+                break;
+            default:  // For failure on uninstall continue
+                hr = S_OK;
+                break;
+            }
+        }
+    } while (S_FALSE == hr);
+
+LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+HRESULT ScaMetabaseTransaction(__in_z LPCWSTR wzBackup);
+
+HRESULT ScaCreateWeb(IMSAdminBase* piMetabase, LPCWSTR wzWeb, LPCWSTR wzWebBase);
+
+HRESULT ScaDeleteApp(IMSAdminBase* piMetabase, LPCWSTR wzWebRoot);
+
+HRESULT ScaCreateApp(IMSAdminBase* piMetabase, LPCWSTR wzWebRoot,
+                     DWORD dwIsolation);
+
+HRESULT ScaCreateMetabaseKey(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
+                             LPCWSTR wzSubKey);
+
+HRESULT ScaDeleteMetabaseKey(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
+                             LPCWSTR wzSubKey);
+
+HRESULT ScaWriteMetabaseValue(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
+                              LPCWSTR wzSubKey, DWORD dwIdentifier,
+                              DWORD dwAttributes, DWORD dwUserType,
+                              DWORD dwDataType, LPVOID pvData);
+
+HRESULT ScaDeleteMetabaseValue(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
+                              LPCWSTR wzSubKey, DWORD dwIdentifier,
+                              DWORD dwDataType);
+
+HRESULT ScaWriteConfigurationScript(LPCWSTR pwzCaScriptKey);
+
+HRESULT ScaAddToIisConfiguration(LPCWSTR pwzData, DWORD dwCost);
+
+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 @@
+// 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.
+
+#include "precomp.h"
+
+#define COST_IIS_WRITEKEY 10
+
+HRESULT ScaIIS7ConfigTransaction(LPCWSTR wzBackup)
+{
+    HRESULT hr = S_OK;
+
+    hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"StartIIS7ConfigTransaction"), wzBackup, COST_IIS_TRANSACTIONS);
+    ExitOnFailure(hr, "Failed to schedule StartIIS7ConfigTransaction");
+
+    hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackIIS7ConfigTransaction"), wzBackup, 0);   // rollback cost is irrelevant
+    ExitOnFailure(hr, "Failed to schedule RollbackIIS7ConfigTransaction");
+
+    hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CommitIIS7ConfigTransaction"), wzBackup, 0);  // commit is free
+    ExitOnFailure(hr, "Failed to schedule StartIIS7ConfigTransaction");
+
+LExit:
+    return hr;
+}
+
+HRESULT ScaWriteConfigString(const LPCWSTR wzValue)
+{
+    HRESULT hr = S_OK;
+    WCHAR* pwzCustomActionData = NULL;
+
+    hr = WcaWriteStringToCaData(wzValue, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase delete key directive to CustomActionData");
+
+    hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_WRITEKEY);
+    ExitOnFailure(hr, "Failed to add ScaWriteMetabaseValue action data: %ls, cost: %d", pwzCustomActionData, COST_IIS_WRITEKEY);
+
+LExit:
+    ReleaseStr(pwzCustomActionData);
+
+    return hr;
+}
+
+HRESULT ScaWriteConfigInteger(DWORD dwValue)
+{
+    HRESULT hr = S_OK;
+    WCHAR* pwzCustomActionData = NULL;
+
+    hr = WcaWriteIntegerToCaData(dwValue, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase delete key directive to CustomActionData");
+
+    hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_WRITEKEY);
+    ExitOnFailure(hr, "Failed to add ScaWriteMetabaseValue action data: %ls, cost: %d", pwzCustomActionData, COST_IIS_WRITEKEY);
+
+LExit:
+    ReleaseStr(pwzCustomActionData);
+
+    return hr;
+}
+
+HRESULT ScaWriteConfigID(IIS_CONFIG_ACTION emID)
+{
+    HRESULT hr = S_OK;
+    WCHAR* pwzCustomActionData = NULL;
+
+    hr = WcaWriteIntegerToCaData(emID, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add metabase delete key directive to CustomActionData");
+
+    hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_WRITEKEY);
+    ExitOnFailure(hr, "Failed to add ScaWriteMetabaseValue action data: %ls, cost: %d", pwzCustomActionData, COST_IIS_WRITEKEY);
+
+LExit:
+    ReleaseStr(pwzCustomActionData);
+
+    return hr;
+}
+
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 @@
+#pragma once
+// 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.
+
+
+HRESULT ScaScheduleIIS7Configuration();
+
+HRESULT ScaIIS7ConfigTransaction(__in_z LPCWSTR wzBackup);
+
+HRESULT ScaCreateApp7(__in_z LPCWSTR wzWebRoot, DWORD dwIsolation);
+
+HRESULT ScaDeleteConfigElement(IIS_CONFIG_ACTION emElement, LPCWSTR wzSubKey);
+
+HRESULT ScaWriteConfigString(__in_z const LPCWSTR wzValue);
+
+HRESULT ScaWriteConfigID(IIS_CONFIG_ACTION emID);
+
+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 @@
+// 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.
+
+#include "precomp.h"
+
+enum eMimeMapQuery { mmqMimeMap = 1, mmqParentType, mmqParentValue, 
+                        mmqMimeType, mmqExtension};
+
+// prototypes
+static HRESULT AddMimeMapToList(SCA_MIMEMAP** ppsmmList);
+
+
+void ScaMimeMapFreeList(SCA_MIMEMAP* psmmList)
+{
+    SCA_MIMEMAP* psmmDelete = psmmList;
+    while (psmmList)
+    {
+        psmmDelete = psmmList;
+        psmmList = psmmList->psmmNext;
+
+        MemFree(psmmDelete);
+    }
+}
+
+
+HRESULT __stdcall ScaMimeMapRead(
+    SCA_MIMEMAP** ppsmmList,
+    __inout LPWSTR *ppwzCustomActionData
+    )
+{
+    HRESULT hr = S_OK;
+    MSIHANDLE hRec;
+    LPWSTR pwzData = NULL;
+    SCA_MIMEMAP* psmm;
+    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
+
+    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap query for ScaMimeMapRead");
+
+    if (0 == WcaGetQueryRecords(hWrapQuery))
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ScaMimeMapRead() - required table not present");
+        ExitFunction1(hr = S_FALSE);
+    }
+
+    // loop through all the mimemappings
+    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
+    {
+        hr = AddMimeMapToList(ppsmmList);
+        ExitOnFailure(hr, "failed to add mime map to list");
+
+        psmm = *ppsmmList;
+
+        hr = WcaGetRecordString(hRec, mmqMimeMap, &pwzData);
+        ExitOnFailure(hr, "Failed to get MimeMap.MimeMap");
+        hr = ::StringCchCopyW(psmm->wzMimeMap, countof(psmm->wzMimeMap), pwzData);
+        ExitOnFailure(hr, "Failed to copy mimemap string to mimemap object");
+
+        hr = WcaGetRecordInteger(hRec, mmqParentType, &psmm->iParentType);
+        ExitOnFailure(hr, "Failed to get MimeMap.iParentType");
+    
+        hr = WcaGetRecordString(hRec, mmqParentValue, &pwzData);
+        ExitOnFailure(hr, "Failed to get MimeMap.ParentValue");
+        hr = ::StringCchCopyW(psmm->wzParentValue, countof(psmm->wzParentValue), pwzData);
+        ExitOnFailure(hr, "Failed to copy parent value string to mimemap object");
+
+        hr = WcaGetRecordString(hRec, mmqExtension, &pwzData);
+        ExitOnFailure(hr, "Failed to get MimeMap.Extension");
+        hr = ::StringCchCopyW(psmm->wzExtension, countof(psmm->wzExtension), pwzData);
+        ExitOnFailure(hr, "Failed to copy extension string to mimemap object");
+
+        hr = WcaGetRecordString(hRec, mmqMimeType, &pwzData);
+        ExitOnFailure(hr, "Failed to get MimeMap.MimeType");
+        hr = ::StringCchCopyW(psmm->wzMimeType, countof(psmm->wzMimeType), pwzData);
+        ExitOnFailure(hr, "Failed to copy mimetype string to mimemap object");
+    }
+
+    if (E_NOMOREITEMS == hr)
+        hr = S_OK;
+    ExitOnFailure(hr, "Failure while processing mimemappings");
+
+LExit:
+    WcaFinishUnwrapQuery(hWrapQuery);
+
+    ReleaseStr(pwzData);
+
+    return hr;
+}
+
+
+HRESULT ScaGetMimeMap(int iParentType, LPCWSTR wzParentValue, SCA_MIMEMAP **ppsmmList, SCA_MIMEMAP **ppsmmOut)
+{
+    HRESULT hr = S_OK;
+    SCA_MIMEMAP* psmmAdd = NULL;
+    SCA_MIMEMAP* psmmLast = NULL;
+
+    *ppsmmOut = NULL;
+    
+    if (!*ppsmmList)
+        return hr;
+
+    SCA_MIMEMAP* psmm = *ppsmmList;
+    while (psmm)
+    {
+        if (iParentType == psmm->iParentType && 0 == lstrcmpW(wzParentValue, psmm->wzParentValue))
+        {
+            // Found a match, take this one out of the list and add it to the matched out list
+            psmmAdd = psmm;
+
+            if (psmmLast)
+            {
+                // 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)
+                psmmLast->psmmNext = psmmAdd->psmmNext;
+            }
+            else
+            {
+                // If we are at the beginning (no psmmLast) update the beginning (since we're taking it)
+                *ppsmmList = psmm->psmmNext;
+            }
+            psmm = psmm->psmmNext; // move on
+
+            // Add the one we've removed to the beginning of the out list
+            psmmAdd->psmmNext = *ppsmmOut;
+            *ppsmmOut = psmmAdd;
+        }
+        else
+        {
+            psmmLast = psmm; // remember the last we that didn't match
+            psmm = psmm->psmmNext; // move on
+        }
+    }
+
+    return hr;
+}
+
+HRESULT ScaMimeMapCheckList(SCA_MIMEMAP* psmmList)
+{
+    if (!psmmList)
+        return S_OK;
+    
+    while (psmmList)
+    {
+        WcaLog(LOGMSG_STANDARD, "MimeMapping of %ls with ParentType=%d and ParentValue=%ls not used!", psmmList->wzMimeMap, psmmList->iParentType, psmmList->wzParentValue);
+        psmmList = psmmList->psmmNext;
+    }
+
+    return E_FAIL;
+}
+
+
+HRESULT ScaWriteMimeMap(IMSAdminBase* piMetabase, LPCWSTR wzRootOfWeb, 
+                               SCA_MIMEMAP* psmmList)
+{
+    HRESULT hr = S_OK;
+
+    WCHAR wzMimeMap[8192];
+    WCHAR *pwzNext = wzMimeMap;
+    const WCHAR *pwzMac = wzMimeMap + countof(wzMimeMap); // used to properly create the MULTI_SZ
+
+    // fill the MULTI_SZ wzMimeMap buffer for the MimeMap attribute
+    ::ZeroMemory(wzMimeMap, sizeof(wzMimeMap));
+
+    for (SCA_MIMEMAP* psmm = psmmList; psmm; psmm = psmm->psmmNext)
+    {
+        hr = ::StringCchPrintfW(pwzNext, max(0, pwzMac - pwzNext), L"%s,%s", psmm->wzExtension, psmm->wzMimeType);
+        ExitOnFailure(hr, "Failed to set MimeMap string");
+
+        pwzNext += lstrlenW(pwzNext) + 1; // reserve space for null
+        Assert(pwzNext <= pwzMac);
+    }
+
+    if (pwzNext != wzMimeMap)
+    {
+        // now write the CustomErrors to the metabase
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_MIME_MAP, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, wzMimeMap);
+        ExitOnFailure(hr, "Failed to write MimeMap");
+    }
+    else
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ScaWriteMimeMap() - no mappings found.");
+        ExitFunction1(hr = S_FALSE);
+    }
+
+LExit:
+    return hr;
+}
+
+
+static HRESULT AddMimeMapToList(SCA_MIMEMAP** ppsmmList)
+{
+    HRESULT hr = S_OK;
+
+    SCA_MIMEMAP* psmm = static_cast<SCA_MIMEMAP*>(MemAlloc(sizeof(SCA_MIMEMAP), TRUE));
+    ExitOnNull(psmm, hr, E_OUTOFMEMORY, "failed to allocate memory for new mime map list element");
+
+    psmm->psmmNext = *ppsmmList;
+    *ppsmmList = psmm;
+    
+LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+enum eMimeMapParentType	{ mmptVDir = 1, mmptWeb = 2 };
+
+struct SCA_MIMEMAP
+{
+	// iis configuation information
+	WCHAR wzMimeMap[MAX_DARWIN_KEY + 1];
+	int iParentType;
+	WCHAR wzParentValue[MAX_DARWIN_KEY + 1];
+	WCHAR wzMimeType[MAX_DARWIN_KEY + 1];
+	WCHAR wzExtension[MAX_DARWIN_KEY + 1];
+
+
+	SCA_MIMEMAP* psmmNext;
+};
+
+
+// prototypes
+
+HRESULT __stdcall ScaMimeMapRead(SCA_MIMEMAP** ppsmmList, __inout LPWSTR *ppwzCustomActionData);
+
+HRESULT ScaGetMimeMap(int iParentType, LPCWSTR wzParentValue, SCA_MIMEMAP **psmmList, SCA_MIMEMAP **ppsmmOut);
+
+HRESULT ScaMimeMapCheckList(SCA_MIMEMAP* psmmList);
+
+void ScaMimeMapFreeList(SCA_MIMEMAP* psmmList);
+
+HRESULT ScaWriteMimeMap(IMSAdminBase* piMetabase, LPCWSTR wzRootOfWeb, 
+                               SCA_MIMEMAP* psmmList);
+
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 @@
+// 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.
+
+#include "precomp.h"
+
+// prototypes
+HRESULT ScaWriteMimeMap7(
+    __in_z LPCWSTR wzWebName,
+    __in_z LPCWSTR wzRootOfWeb,
+    SCA_MIMEMAP* psmmList
+    )
+{
+    HRESULT hr = S_OK;
+    SCA_MIMEMAP* psmm;
+
+    //create the mimemap list for this vdir application
+    //all go to same web/root location tag
+    hr = ScaWriteConfigID(IIS_MIMEMAP_BEGIN);
+    ExitOnFailure(hr, "Failed to write mimemap begin id");
+    hr = ScaWriteConfigString(wzWebName);                //site name key
+    ExitOnFailure(hr, "Failed to write mimemap web key");
+    hr = ScaWriteConfigString(wzRootOfWeb);               //app path key
+    ExitOnFailure(hr, "Failed to write mimemap app key");
+
+    psmm = psmmList;
+
+    while (psmm)
+    {
+        //create the Extension for this vdir application
+        hr = ScaWriteConfigID(IIS_MIMEMAP);
+        ExitOnFailure(hr, "Failed to write mimemap id");
+
+        if (*psmm->wzExtension)
+        {
+            hr = ScaWriteConfigString(psmm->wzExtension);
+        }
+        else   // blank means "*" (all)
+        {
+            hr = ScaWriteConfigString(L"*");
+        }
+        ExitOnFailure(hr, "Failed to write mimemap extension");
+
+        hr = ScaWriteConfigString(psmm->wzMimeType);
+        ExitOnFailure(hr, "Failed to write mimemap type");
+
+        psmm = psmm->psmmNext;
+    }
+
+    hr = ScaWriteConfigID(IIS_MIMEMAP_END);
+    ExitOnFailure(hr, "Failed to write mimemap end id");
+
+LExit:
+    return hr;
+}
+
+
+//static HRESULT AddMimeMapToList(SCA_MIMEMAP** ppsmmList)
+//{
+//    HRESULT hr = S_OK;
+//
+//    SCA_MIMEMAP* psmm = static_cast<SCA_MIMEMAP*>(MemAlloc(sizeof(SCA_MIMEMAP), TRUE));
+//    ExitOnNull(psmm, hr, E_OUTOFMEMORY, "failed to allocate memory for new mime map list element");
+//
+//    psmm->psmmNext = *ppsmmList;
+//    *ppsmmList = psmm;
+//
+//LExit:
+//    return hr;
+//}
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 @@
+#pragma once
+// 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.
+
+
+HRESULT ScaWriteMimeMap7(
+    __in_z LPCWSTR wzWebName,
+    __in_z LPCWSTR wzRootOfWeb,
+    SCA_MIMEMAP* psmmList
+    );
+
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 @@
+// 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.
+
+#include "precomp.h"
+
+/*------------------------------------------------------------------
+IIsProperty table:
+
+Property  Component_  Attributes  Value
+s72      s72         i4          s255
+------------------------------------------------------------------*/
+
+// sql queries
+enum ePropertyQuery { pqProperty = 1, pqComponent, pqAttributes, pqValue, pqInstalled, pqAction };
+
+
+// prototypes
+static HRESULT AddPropertyToList(
+    SCA_PROPERTY** ppspList
+    );
+
+
+// functions
+void ScaPropertyFreeList(
+    SCA_PROPERTY* pspList
+    )
+{
+    SCA_PROPERTY* pspDelete = pspList;
+    while (pspList)
+    {
+        pspDelete = pspList;
+        pspList = pspList->pspNext;
+
+        MemFree(pspDelete);
+    }
+}
+
+
+HRESULT ScaPropertyRead(
+    SCA_PROPERTY** ppspList,
+    __inout LPWSTR *ppwzCustomActionData
+    )
+{
+    HRESULT hr = S_OK;
+    MSIHANDLE hRec;
+
+    LPWSTR pwzData = NULL;
+    SCA_PROPERTY* pss;
+
+    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
+
+    ExitOnNull(ppspList, hr, E_INVALIDARG, "Failed to read property, because no property to read was provided");
+
+    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead");
+
+    if (0 == WcaGetQueryRecords(hWrapQuery))
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ScaInstallProperty() - required table not present");
+        ExitFunction1(hr = S_FALSE);
+    }
+
+    // loop through all the Settings
+    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
+    {
+        hr = AddPropertyToList(ppspList);
+        ExitOnFailure(hr, "failed to add property to list");
+
+        pss = *ppspList;
+
+        hr = WcaGetRecordString(hRec, pqProperty, &pwzData);
+        ExitOnFailure(hr, "failed to get IIsProperty.Property");
+        hr = ::StringCchCopyW(pss->wzProperty, countof(pss->wzProperty), pwzData);
+        ExitOnFailure(hr, "failed to copy Property name: %ls", pwzData);
+
+        hr = WcaGetRecordString(hRec, pqValue, &pwzData);
+        ExitOnFailure(hr, "failed to get IIsProperty.Value");
+        hr = ::StringCchCopyW(pss->wzValue, countof(pss->wzValue), pwzData);
+        ExitOnFailure(hr, "failed to copy Property value: %ls", pwzData);
+
+        hr = WcaGetRecordInteger(hRec, pqAttributes, &pss->iAttributes);
+        ExitOnFailure(hr, "failed to get IIsProperty.Attributes");
+
+        hr = WcaGetRecordString(hRec, pqComponent, &pwzData);
+        ExitOnFailure(hr, "failed to get IIsProperty.Component");
+        hr = ::StringCchCopyW(pss->wzComponent, countof(pss->wzComponent), pwzData);
+        ExitOnFailure(hr, "failed to copy component name: %ls", pwzData);
+
+        hr = WcaGetRecordInteger(hRec, pqInstalled, (int *)&pss->isInstalled);
+        ExitOnFailure(hr, "Failed to get Component installed state for filter");
+
+        hr = WcaGetRecordInteger(hRec, pqAction, (int *)&pss->isAction);
+        ExitOnFailure(hr, "Failed to get Component action state for filter");
+    }
+
+    if (E_NOMOREITEMS == hr)
+    {
+        hr = S_OK;
+    }
+    ExitOnFailure(hr, "failure while processing IIsProperty table");
+
+LExit:
+    WcaFinishUnwrapQuery(hWrapQuery);
+
+    ReleaseStr(pwzData);
+
+    return hr;
+}
+
+
+HRESULT ScaPropertyInstall(
+    IMSAdminBase* piMetabase, 
+    SCA_PROPERTY* pspList
+    )
+{
+    Assert(piMetabase);
+
+    HRESULT hr = S_OK;
+
+    for (SCA_PROPERTY* psp = pspList; psp; psp = psp->pspNext)
+    {
+        // if we are installing the web site
+        if (WcaIsInstalling(psp->isInstalled, psp->isAction))
+        {
+            hr = ScaWriteProperty(piMetabase, psp);
+            ExitOnFailure(hr, "failed to write Property '%ls' to metabase", psp->wzProperty);
+        }
+    }
+
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaPropertyUninstall(
+    IMSAdminBase* piMetabase, 
+    SCA_PROPERTY* pspList
+    )
+{
+    Assert(piMetabase);
+
+    HRESULT hr = S_OK;
+
+    for (SCA_PROPERTY* psp = pspList; psp; psp = psp->pspNext)
+    {
+        // if we are uninstalling the web site
+        if (WcaIsUninstalling(psp->isInstalled, psp->isAction))
+        {
+            hr = ScaRemoveProperty(piMetabase, psp);
+            ExitOnFailure(hr, "Failed to remove Property '%ls' from metabase", psp->wzProperty);
+        }
+    }
+
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaWriteProperty(
+    IMSAdminBase* piMetabase, 
+    SCA_PROPERTY* psp
+    )
+{
+    Assert(piMetabase);
+
+    HRESULT hr = S_OK;
+    DWORD dwValue;
+    LPWSTR wz = NULL;
+
+    ExitOnNull(psp, hr, E_INVALIDARG, "Failed to write property because no property to write was given");
+
+    //
+    // Figure out what setting we're writing and write it
+    //
+    if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_IIS5_ISOLATION_MODE))
+    {
+        dwValue = 1;
+        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));
+        ExitOnFailure(hr, "failed to set IIs5IsolationMode");
+    }
+    else if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_MAX_GLOBAL_BANDWIDTH))
+    {
+        dwValue = wcstoul(psp->wzValue, &wz, 10) * 1024; // remember, the value shown is in kilobytes, the value saved is in bytes
+        hr = ScaWriteMetabaseValue(piMetabase, L"/LM/W3SVC", NULL, MD_MAX_GLOBAL_BANDWIDTH, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwValue));
+        ExitOnFailure(hr, "failed to set MaxGlobalBandwidth");
+    }
+    else if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_LOG_IN_UTF8))
+    {
+        dwValue = 1;
+        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));
+        ExitOnFailure(hr, "failed to set LogInUTF8");
+    }
+    else if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_ETAG_CHANGENUMBER))
+    {
+        dwValue = wcstoul(psp->wzValue, &wz, 10);
+        hr = ScaWriteMetabaseValue(piMetabase, L"/LM/W3SVC", NULL, /*MD_ETAG_CHANGENUMBER*/ 2039, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwValue));
+        ExitOnFailure(hr, "failed to set EtagChangenumber");
+    }
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaRemoveProperty(
+    IMSAdminBase* piMetabase, 
+    SCA_PROPERTY* psp
+    )
+{
+    Assert(piMetabase);
+
+    HRESULT hr = S_OK;
+    DWORD dwValue;
+
+    ExitOnNull(psp, hr, E_INVALIDARG, "Failed to remove property because no property to remove was given");
+
+    if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_IIS5_ISOLATION_MODE))
+    {
+        dwValue = 0;
+        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));
+        ExitOnFailure(hr, "failed to clear IIs5IsolationMode");
+    }
+    else if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_MAX_GLOBAL_BANDWIDTH))
+    {
+        dwValue = 0xFFFFFFFF; // This unchecks the box
+        hr = ScaWriteMetabaseValue(piMetabase, L"/LM/W3SVC", NULL, MD_MAX_GLOBAL_BANDWIDTH, METADATA_NO_ATTRIBUTES , IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwValue));
+        ExitOnFailure(hr, "failed to clear MaxGlobalBandwidth");
+    }
+    else if (0 == lstrcmpW(psp->wzProperty, wzIISPROPERTY_LOG_IN_UTF8))
+    {
+        dwValue = 0;
+        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));
+        ExitOnFailure(hr, "failed to clear LogInUTF8");
+    }
+
+LExit:
+    return hr;
+}
+
+
+static HRESULT AddPropertyToList(
+    SCA_PROPERTY** ppspList
+    )
+{
+    HRESULT hr = S_OK;
+    SCA_PROPERTY* psp = static_cast<SCA_PROPERTY*>(MemAlloc(sizeof(SCA_PROPERTY), TRUE));
+    ExitOnNull(psp, hr, E_OUTOFMEMORY, "failed to allocate memory for new property list element");
+    
+    psp->pspNext = *ppspList;
+    *ppspList = psp;
+    
+LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+#define wzIISPROPERTY_IIS5_ISOLATION_MODE L"IIs5IsolationMode"
+#define wzIISPROPERTY_MAX_GLOBAL_BANDWIDTH L"MaxGlobalBandwidth"
+#define wzIISPROPERTY_LOG_IN_UTF8 L"LogInUTF8"
+#define wzIISPROPERTY_ETAG_CHANGENUMBER L"ETagChangeNumber"
+
+struct SCA_PROPERTY
+{
+	// iis configuation information
+	WCHAR wzProperty[MAX_DARWIN_KEY + 1];
+	WCHAR wzComponent[MAX_DARWIN_KEY + 1];
+	INSTALLSTATE isInstalled;
+	INSTALLSTATE isAction;
+	INT iAttributes;
+	WCHAR wzValue[MAX_DARWIN_COLUMN + 1];
+
+	SCA_PROPERTY *pspNext;
+};
+
+
+// prototypes
+
+HRESULT ScaPropertyRead(
+	SCA_PROPERTY** ppspList,
+    __inout LPWSTR *ppwzCustomActionData
+	);
+
+void ScaPropertyFreeList(
+	SCA_PROPERTY* pspList
+	);
+
+HRESULT ScaPropertyInstall(
+	IMSAdminBase* piMetabase, 
+	SCA_PROPERTY* pspList
+	);
+
+HRESULT ScaPropertyUninstall(
+	IMSAdminBase* piMetabase, 
+	SCA_PROPERTY* pspList
+	);
+
+HRESULT ScaWriteProperty(
+	IMSAdminBase* piMetabase, 
+	SCA_PROPERTY* psp
+	);
+
+HRESULT ScaRemoveProperty(
+	IMSAdminBase* piMetabase, 
+	SCA_PROPERTY* psp
+	);
+
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 @@
+// 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.
+
+#include "precomp.h"
+
+HRESULT ScaPropertyInstall7(
+    SCA_PROPERTY* pspList
+    )
+{
+    HRESULT hr = S_OK;
+
+    for (SCA_PROPERTY* psp = pspList; psp; psp = psp->pspNext)
+    {
+        // if we are installing the web site
+        if (WcaIsInstalling(psp->isInstalled, psp->isAction))
+        {
+            hr = ScaWriteProperty7(psp);
+            ExitOnFailure(hr, "failed to write Property '%ls' ", psp->wzProperty);
+        }
+    }
+
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaPropertyUninstall7(
+    SCA_PROPERTY* pspList
+    )
+{
+    HRESULT hr = S_OK;
+
+    for (SCA_PROPERTY* psp = pspList; psp; psp = psp->pspNext)
+    {
+        // if we are uninstalling the web site
+        if (WcaIsUninstalling(psp->isInstalled, psp->isAction))
+        {
+            hr = ScaRemoveProperty7(psp);
+            ExitOnFailure(hr, "Failed to remove Property '%ls'", psp->wzProperty);
+        }
+    }
+
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaWriteProperty7(
+    const SCA_PROPERTY* psp
+    )
+{
+    HRESULT hr = S_OK;
+    DWORD dwValue;
+    LPWSTR wz = NULL;
+
+    ExitOnNull(psp, hr, E_INVALIDARG, "Failed to write property because no property to write was given");
+    //
+    // Figure out what setting we're writing and write it
+    //
+    if (0 == wcscmp(psp->wzProperty, wzIISPROPERTY_IIS5_ISOLATION_MODE))
+    {
+        // IIs5IsolationMode not supported
+        WcaLog(LOGMSG_VERBOSE, "Not supported by IIS7: IIs5IsolationMode, ignoring");
+    }
+    else if (0 == wcscmp(psp->wzProperty, wzIISPROPERTY_MAX_GLOBAL_BANDWIDTH))
+    {
+        dwValue = wcstoul(psp->wzValue, &wz, 10) * 1024; // remember, the value shown is in kilobytes, the value saved is in bytes
+        hr = ScaWriteConfigID(IIS_PROPERTY);
+        ExitOnFailure(hr, "failed to set Property ID");
+        hr = ScaWriteConfigID(IIS_PROPERTY_MAXBAND);
+        ExitOnFailure(hr, "failed to set Property MSXBAND ID");
+        hr = ScaWriteConfigInteger(dwValue);
+        ExitOnFailure(hr, "failed to set Property MSXBAND value");
+    }
+    else if (0 == wcscmp(psp->wzProperty, wzIISPROPERTY_LOG_IN_UTF8))
+    {
+        dwValue = 1;
+        hr = ScaWriteConfigID(IIS_PROPERTY);
+        ExitOnFailure(hr, "failed to set Property ID");
+        hr = ScaWriteConfigID(IIS_PROPERTY_LOGUTF8);
+        ExitOnFailure(hr, "failed to set Property LOG ID");
+        hr = ScaWriteConfigInteger(dwValue);
+        ExitOnFailure(hr, "failed to set Property Log value");
+    }
+    else if (0 == wcscmp(psp->wzProperty, wzIISPROPERTY_ETAG_CHANGENUMBER))
+    {
+        //EtagChangenumber not supported
+        WcaLog(LOGMSG_VERBOSE, "Not supported by IIS7: EtagChangenumber, ignoring");
+    }
+
+LExit:
+    return hr;
+}
+
+HRESULT ScaRemoveProperty7(
+    __in SCA_PROPERTY* /*psp*/
+    )
+{
+
+    // NOP function for now
+    //The two global values being set by WebProperty:
+    //    <iis:WebProperty Id="MaxGlobalBandwidth" Value="1024" />
+    //    <iis:WebProperty Id ="LogInUTF8" />
+    // should should not be removed on uninstall.
+
+    HRESULT hr = S_OK;
+
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+#define wzIISPROPERTY_IIS5_ISOLATION_MODE L"IIs5IsolationMode"
+#define wzIISPROPERTY_MAX_GLOBAL_BANDWIDTH L"MaxGlobalBandwidth"
+#define wzIISPROPERTY_LOG_IN_UTF8 L"LogInUTF8"
+#define wzIISPROPERTY_ETAG_CHANGENUMBER L"ETagChangeNumber"
+
+// prototypes
+HRESULT ScaPropertyInstall7(
+    SCA_PROPERTY* pspList
+    );
+
+HRESULT ScaPropertyUninstall7(
+    SCA_PROPERTY* pspList
+    );
+
+HRESULT ScaWriteProperty7(
+    const SCA_PROPERTY* psp
+    );
+
+HRESULT ScaRemoveProperty7(
+    SCA_PROPERTY* psp
+    );
+
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 @@
+// 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.
+
+#include "precomp.h"
+
+const int ConfigureIIsCost = 8;
+const int WriteMetabaseChangesCost = 20;
+const int WriteIIS7ConfigChangesCost = 20;
+
+// sql queries
+LPCWSTR vcsUserDeferredQuery = L"SELECT `User`, `Component_`, `Name`, `Domain`, `Password` FROM `User`";
+
+LPCWSTR vcsWebSvcExtQuery = L"SELECT `Component_`, `File`, `Description`, `Group`, `Attributes` FROM `IIsWebServiceExtension`";
+
+LPCWSTR vcsAppPoolQuery = L"SELECT `AppPool`, `Name`, `Component_`, `Attributes`, `User_`, `RecycleMinutes`, `RecycleRequests`, `RecycleTimes`, `VirtualMemory`, `PrivateMemory`, `IdleTimeout`, `QueueLimit`, `CPUMon`, `MaxProc`, `ManagedRuntimeVersion`, `ManagedPipelineMode` FROM `IIsAppPool`";
+
+LPCWSTR vcsComponentAttrQuery = L"SELECT `Component`,`Attributes` FROM `Component`";
+
+LPCWSTR vcsMimeMapQuery = L"SELECT `MimeMap`, `ParentType`, `ParentValue`, `MimeType`, `Extension` FROM `IIsMimeMap`";
+
+LPCWSTR vcsHttpHeaderQuery = L"SELECT `Name`, `ParentType`, `ParentValue`, `Value`, `Attributes` FROM `IIsHttpHeader` ORDER BY `Sequence`";
+
+LPCWSTR vcsWebErrorQuery =
+    L"SELECT `ErrorCode`, `SubCode`, `ParentType`, `ParentValue`, `File`, `URL` "
+    L"FROM `IIsWebError` ORDER BY `ErrorCode`, `SubCode`";
+
+LPCWSTR vcsWebDirPropertiesQuery = L"SELECT `DirProperties`, `Access`, `Authorization`, `AnonymousUser_`, `IIsControlledPassword`, `LogVisits`, `Index`, `DefaultDoc`, `AspDetailedError`, `HttpExpires`, `CacheControlMaxAge`, `CacheControlCustom`, `NoCustomError`, `AccessSSLFlags`, `AuthenticationProviders` "
+    L"FROM `IIsWebDirProperties`";
+
+LPCWSTR vcsSslCertificateQuery = L"SELECT `Certificate`.`StoreName`, `CertificateHash`.`Hash`, `IIsWebSiteCertificates`.`Web_` FROM `Certificate`, `CertificateHash`, `IIsWebSiteCertificates` WHERE `Certificate`.`Certificate`=`CertificateHash`.`Certificate_` AND `CertificateHash`.`Certificate_`=`IIsWebSiteCertificates`.`Certificate_`";
+
+LPCWSTR vcsWebLogQuery = L"SELECT `Log`, `Format` "
+    L"FROM `IIsWebLog`";
+
+LPCWSTR vcsWebApplicationQuery = L"SELECT `Name`, `Isolation`, `AllowSessions`, `SessionTimeout`, "
+    L"`Buffer`, `ParentPaths`, `DefaultScript`, `ScriptTimeout`, "
+    L"`ServerDebugging`, `ClientDebugging`, `AppPool_`, `Application` "
+    L"FROM `IIsWebApplication`";
+
+LPCWSTR vcsWebAppExtensionQuery = L"SELECT `Extension`, `Verbs`, `Executable`, `Attributes`, `Application_` FROM `IIsWebApplicationExtension`";
+
+LPCWSTR vcsWebQuery = L"SELECT `Web`, `Component_`, `Id`, `Description`, `ConnectionTimeout`, `Directory_`, `State`, `Attributes`, `DirProperties_`, `Application_`, "
+    L"`Address`, `IP`, `Port`, `Header`, `Secure`, `Log_` FROM `IIsWebSite`, `IIsWebAddress` "
+    L"WHERE `KeyAddress_`=`Address` ORDER BY `Sequence`";
+
+LPCWSTR vcsWebAddressQuery = L"SELECT `Address`, `Web_`, `IP`, `Port`, `Header`, `Secure` "
+    L"FROM `IIsWebAddress`";
+
+LPCWSTR vcsWebBaseQuery = L"SELECT `Web`, `Id`, `IP`, `Port`, `Header`, `Secure`, `Description` "
+    L"FROM `IIsWebSite`, `IIsWebAddress` "
+    L"WHERE `KeyAddress_`=`Address`";
+
+LPCWSTR vcsWebDirQuery = L"SELECT `Web_`, `WebDir`, `Component_`, `Path`, `DirProperties_`, `Application_` "
+    L"FROM `IIsWebDir`";
+
+LPCWSTR vcsVDirQuery = L"SELECT `Web_`, `VirtualDir`, `Component_`, `Alias`, `Directory_`, `DirProperties_`, `Application_` "
+    L"FROM `IIsWebVirtualDir`";
+
+LPCWSTR vcsFilterQuery = L"SELECT `Web_`, `Name`, `Component_`, `Path`, `Description`, `Flags`, `LoadOrder` FROM `IIsFilter` ORDER BY `Web_`";
+
+LPCWSTR vcsPropertyQuery = L"SELECT `Property`, `Component_`, `Attributes`, `Value` "
+    L"FROM `IIsProperty`";
+
+#define IIS7CONDITION L"VersionNT >= 600"
+#define USEIIS7CONDITION IIS7CONDITION L"AND NOT UseIis6Compatibility"
+
+/********************************************************************
+ConfigureIIs - CUSTOM ACTION ENTRY POINT for installing IIs settings
+
+********************************************************************/
+extern "C" UINT __stdcall ConfigureIIs(
+    __in MSIHANDLE hInstall
+    )
+{
+    //AssertSz(FALSE, "debug ConfigureIIs here");
+    HRESULT hr = S_OK;
+    UINT er = ERROR_SUCCESS;
+    LPWSTR pwzScriptKey = NULL;
+    LPWSTR pwzBackupId = NULL;
+    LPWSTR pwzCustomActionData = NULL; // CustomActionData for ConfigureIIs custom action
+
+    // initialize
+    hr = WcaInitialize(hInstall, "ConfigureIIs");
+    ExitOnFailure(hr, "Failed to initialize");
+
+    // check for the prerequsite tables
+    if (S_OK != WcaTableExists(L"IIsWebSite") && S_OK != WcaTableExists(L"IIsFilter") && S_OK != WcaTableExists(L"IIsProperty") && 
+        S_OK != WcaTableExists(L"IIsWebServiceExtension") && S_OK != WcaTableExists(L"IIsAppPool"))
+    {
+        WcaLog(LOGMSG_VERBOSE, "skipping IIs CustomAction, no IIsWebSite table, no IIsFilter table, no IIsProperty table, no IIsWebServiceExtension, and no IIsAppPool table");
+        ExitFunction1(hr = S_FALSE);
+    }
+
+    // Get a CaScript key
+    hr = WcaCaScriptCreateKey(&pwzScriptKey);
+    ExitOnFailure(hr, "Failed to get encoding key.");
+
+    // Generate a unique string to be used for this product's transaction
+    // This prevents a name collision when doing a major upgrade
+    hr = WcaGetProperty(L"ProductCode", &pwzBackupId);
+    ExitOnFailure(hr, "failed to get ProductCode");
+
+    hr = StrAllocConcat(&pwzBackupId, L"ScaConfigureIIs", 0);
+    ExitOnFailure(hr, "failed to concat ScaConfigureIIs");
+
+    // make sure the operations below are wrapped in a "transaction"
+    // use IIS7 transaction logic even if using Iis6 compat because Backup/Restore don't work with metabase compatibility
+    if (MSICONDITION_TRUE == ::MsiEvaluateConditionW(hInstall, IIS7CONDITION))
+    {
+        hr = ScaIIS7ConfigTransaction(pwzBackupId);
+        MessageExitOnFailure(hr, msierrIISFailedSchedTransaction, "failed to start IIS7 transaction");
+    }
+    else
+    {
+        hr = ScaMetabaseTransaction(pwzBackupId);
+        MessageExitOnFailure(hr, msierrIISFailedSchedTransaction, "failed to start IIS transaction");
+    }
+
+    // Write the CaScript key to the ConfigureIIS custom action data
+    hr = WcaWriteStringToCaData(pwzScriptKey, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to add encoding key to CustomActionData.");
+
+    // Wrap vcsUserDeferredQuery to send to deferred CA
+    if (S_OK == WcaTableExists(L"User"))
+    {
+        hr = WcaWrapQuery(vcsUserDeferredQuery, &pwzCustomActionData, efmcColumn3 | efmcColumn4 | efmcColumn5, 0xFFFFFFFF, 0xFFFFFFFF);
+        ExitOnFailure(hr, "Failed to wrap User query");
+    }
+    else
+    {
+        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to wrap User empty query");
+    }
+
+    // Wrap vcsWebSvcExtQuery to send to deferred CA
+    if (S_OK == WcaTableExists(L"IIsWebServiceExtension"))
+    {
+        hr = WcaWrapQuery(vcsWebSvcExtQuery, &pwzCustomActionData, efmcColumn2 | efmcColumn3 | efmcColumn4, 1, 0xFFFFFFFF);
+        ExitOnFailure(hr, "Failed to wrap IIsWebServiceExtension query");
+    }
+    else
+    {
+        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to wrap IIsWebServiceExtension empty query");
+    }
+
+    // Wrap vcsAppPoolQuery to send to deferred CA
+    if (S_OK == WcaTableExists(L"IIsAppPool"))
+    {
+        hr = WcaWrapQuery(vcsAppPoolQuery, &pwzCustomActionData, efmcColumn2 | efmcColumn15 | efmcColumn16, 3, 0xFFFFFFFF);
+        ExitOnFailure(hr, "Failed to wrap IIsAppPool query");
+
+        hr = WcaWrapQuery(vcsComponentAttrQuery, &pwzCustomActionData, 0, 0xFFFFFFFF, 0xFFFFFFFF);
+        ExitOnFailure(hr, "Failed to wrap Component query");
+    }
+    else
+    {
+        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to wrap IIsAppPool empty query");
+    }
+
+    // Wrap vcsMimeMapQuery to send to deferred CA
+    if (S_OK == WcaTableExists(L"IIsMimeMap"))
+    {
+        hr = WcaWrapQuery(vcsMimeMapQuery, &pwzCustomActionData, efmcColumn4 | efmcColumn5, 0xFFFFFFFF, 0xFFFFFFFF);
+        ExitOnFailure(hr, "Failed to wrap IIsMimeMap query");
+    }
+    else
+    {
+        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to wrap IIsMimeMap empty query");
+    }
+
+    // Wrap vcsHttpHeaderQuery to send to deferred CA
+    if (S_OK == WcaTableExists(L"IIsHttpHeader"))
+    {
+        hr = WcaWrapQuery(vcsHttpHeaderQuery, &pwzCustomActionData, efmcColumn1 | efmcColumn4, 0xFFFFFFFF, 0xFFFFFFFF);
+        ExitOnFailure(hr, "Failed to wrap IIsHttpHeader query");
+    }
+    else
+    {
+        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to wrap IIsHttpHeader empty query");
+    }
+
+    // Wrap vcsWebErrorQuery to send to deferred CA
+    if (S_OK == WcaTableExists(L"IIsWebError"))
+    {
+        hr = WcaWrapQuery(vcsWebErrorQuery, &pwzCustomActionData, efmcColumn5 | efmcColumn6, 0xFFFFFFFF, 0xFFFFFFFF);
+        ExitOnFailure(hr, "Failed to wrap IIsWebError query");
+    }
+    else
+    {
+        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to wrap IIsWebError empty query");
+    }
+
+    // Wrap vcsWebDirPropertiesQuery to send to deferred CA
+    if (S_OK == WcaTableExists(L"IIsWebDirProperties"))
+    {
+        hr = WcaWrapQuery(vcsWebDirPropertiesQuery, &pwzCustomActionData, efmcColumn8 | efmcColumn10 | efmcColumn12 | efmcColumn15, 0xFFFFFFFF, 0xFFFFFFFF);
+        ExitOnFailure(hr, "Failed to wrap IIsWebDirProperties query");
+    }
+    else
+    {
+        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to wrap IIsWebDirProperties empty query");
+    }
+
+    // Wrap vcsSslCertificateQuery to send to deferred CA
+    if (S_OK == WcaTableExists(L"Certificate") && S_OK == WcaTableExists(L"CertificateHash") && S_OK == WcaTableExists(L"IIsWebSiteCertificates"))
+    {
+        hr = WcaWrapQuery(vcsSslCertificateQuery, &pwzCustomActionData, 0, 0xFFFFFFFF, 0xFFFFFFFF);
+        ExitOnFailure(hr, "Failed to wrap SslCertificate query");
+    }
+    else
+    {
+        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to wrap SslCertificate empty query");
+    }
+
+    // Wrap vcsWebLogQuery to send to deferred CA
+    if (S_OK == WcaTableExists(L"IIsWebLog"))
+    {
+        hr = WcaWrapQuery(vcsWebLogQuery, &pwzCustomActionData, efmcColumn2, 0xFFFFFFFF, 0xFFFFFFFF);
+        ExitOnFailure(hr, "Failed to wrap IIsWebLog query");
+    }
+    else
+    {
+        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to wrap IIsWebLog empty query");
+    }
+
+    // Wrap vcsWebApplicationQuery to send to deferred CA
+    if (S_OK == WcaTableExists(L"IIsWebApplication"))
+    {
+        hr = WcaWrapQuery(vcsWebApplicationQuery, &pwzCustomActionData, efmcColumn1, 0xFFFFFFFF, 0xFFFFFFFF);
+        ExitOnFailure(hr, "Failed to wrap IIsWebApplication query");
+    }
+    else
+    {
+        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to wrap IIsWebApplication empty query");
+    }
+
+    // Wrap vcsWebAppExtensionQuery to send to deferred CA
+    if (S_OK == WcaTableExists(L"IIsWebApplicationExtension"))
+    {
+        hr = WcaWrapQuery(vcsWebAppExtensionQuery, &pwzCustomActionData, efmcColumn2 | efmcColumn3, 0xFFFFFFFF, 0xFFFFFFFF);
+        ExitOnFailure(hr, "Failed to wrap IIsWebApplicationExtension query");
+    }
+    else
+    {
+        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to wrap IIsWebApplicationExtension empty query");
+    }
+
+    // Wrap vcsWebQuery, vcsWebAddressQuery, and vcsWebBaseQuery to send to deferred CA
+    if (S_OK == WcaTableExists(L"IIsWebAddress") && S_OK == WcaTableExists(L"IIsWebSite"))
+    {
+        hr = WcaWrapQuery(vcsWebQuery, &pwzCustomActionData, efmcColumn3 | efmcColumn4 | efmcColumn12 | efmcColumn13 | efmcColumn14, 2, 6);
+        ExitOnFailure(hr, "Failed to wrap IIsWebSite query");
+
+        hr = WcaWrapQuery(vcsWebAddressQuery, &pwzCustomActionData, efmcColumn3 | efmcColumn4 | efmcColumn5, 0xFFFFFFFF, 0xFFFFFFFF);
+        ExitOnFailure(hr, "Failed to wrap IIsWebAddress query");
+
+        hr = WcaWrapQuery(vcsWebBaseQuery, &pwzCustomActionData, efmcColumn2 | efmcColumn3 | efmcColumn4 | efmcColumn5 | efmcColumn7, 0xFFFFFFFF, 0xFFFFFFFF);
+        ExitOnFailure(hr, "Failed to wrap IIsWebBase query");
+    }
+    else
+    {
+        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to wrap IIsWebSite empty query");
+
+        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to wrap IIsWebAddress empty query");
+
+        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to wrap IIsWebBase empty query");
+    }
+
+    // Wrap vcsWebDirQuery to send to deferred CA
+    if (S_OK == WcaTableExists(L"IIsWebDir"))
+    {
+        hr = WcaWrapQuery(vcsWebDirQuery, &pwzCustomActionData, efmcColumn4, 3, 0xFFFFFFFF);
+        ExitOnFailure(hr, "Failed to wrap IIsWebDir query");
+    }
+    else
+    {
+        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to wrap IIsWebDir empty query");
+    }
+
+    // Wrap vcsVDirQuery to send to deferred CA
+    if (S_OK == WcaTableExists(L"IIsWebVirtualDir"))
+    {
+        hr = WcaWrapQuery(vcsVDirQuery, &pwzCustomActionData, efmcColumn4, 3, 5);
+        ExitOnFailure(hr, "Failed to wrap IIsWebVirtualDir query");
+    }
+    else
+    {
+        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to wrap IIsWebVirtualDir empty query");
+    }
+
+    // Wrap vcsFilterQuery to send to deferred CA
+    if (S_OK == WcaTableExists(L"IIsFilter"))
+    {
+        hr = WcaWrapQuery(vcsFilterQuery, &pwzCustomActionData, efmcColumn4 | efmcColumn5, 3, 0xFFFFFFFF);
+        ExitOnFailure(hr, "Failed to wrap IIsFilter query");
+    }
+    else
+    {
+        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to wrap IIsFilter empty query");
+    }
+
+    // Wrap vcsPropertyQuery to send to deferred CA
+    if (S_OK == WcaTableExists(L"IIsProperty"))
+    {
+        hr = WcaWrapQuery(vcsPropertyQuery, &pwzCustomActionData, efmcColumn4, 2, 0xFFFFFFFF);
+        ExitOnFailure(hr, "Failed to wrap IIsProperty query");
+    }
+    else
+    {
+        hr = WcaWrapEmptyQuery(&pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to wrap IIsProperty empty query");
+    }
+
+    if (MSICONDITION_TRUE == ::MsiEvaluateConditionW(hInstall, USEIIS7CONDITION))
+    {
+        // This must remain trace only, CA data may contain password
+        WcaLog(LOGMSG_TRACEONLY, "Custom Action Data for ConfigureIIS7Exec will be: %ls", pwzCustomActionData);
+
+        hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ConfigureIIs7Exec"), pwzCustomActionData, ConfigureIIsCost);
+        ExitOnFailure(hr, "Failed to schedule ConfigureIIs7Exec custom action");
+
+        ReleaseNullStr(pwzCustomActionData);
+
+        // Write the CaScript key to the ConfigureIIS custom action data
+        hr = WcaWriteStringToCaData(pwzScriptKey, &pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to add script key to CustomActionData.");
+
+        hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"WriteIIS7ConfigChanges"), pwzCustomActionData, WriteIIS7ConfigChangesCost);
+        ExitOnFailure(hr, "Failed to schedule WriteMetabaseChanges custom action");
+    }
+    else
+    {
+        // This must remain trace only, CA data may contain password
+        WcaLog(LOGMSG_TRACEONLY, "Custom Action Data for ConfigureIISExec will be: %ls", pwzCustomActionData);
+
+        hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ConfigureIIsExec"), pwzCustomActionData, ConfigureIIsCost);
+        ExitOnFailure(hr, "Failed to schedule ConfigureIISExec custom action");
+
+        ReleaseNullStr(pwzCustomActionData);
+
+        // Write the CaScript key to the ConfigureIIS custom action data
+        hr = WcaWriteStringToCaData(pwzScriptKey, &pwzCustomActionData);
+        ExitOnFailure(hr, "Failed to add script key to CustomActionData.");
+
+        hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"WriteMetabaseChanges"), pwzCustomActionData, WriteMetabaseChangesCost);
+        ExitOnFailure(hr, "Failed to schedule WriteMetabaseChanges custom action");
+    }
+
+LExit:
+    ReleaseStr(pwzScriptKey);
+    ReleaseStr(pwzBackupId);
+    ReleaseStr(pwzCustomActionData);
+
+    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
+    return WcaFinalize(er);
+}
+
+/********************************************************************
+ConfigureIIsExec - custom action for installing IIs settings - table
+data will be wrapped and passed in from immediate CA
+ReadIIsTables
+
+********************************************************************/
+extern "C" UINT __stdcall ConfigureIIsExec(
+    __in MSIHANDLE hInstall
+    )
+{
+    //AssertSz(FALSE, "debug ConfigureIIsExec here");
+    HRESULT hr = S_OK;
+    UINT er = ERROR_SUCCESS;
+
+    BOOL fInitializedCom = FALSE;
+    IMSAdminBase* piMetabase = NULL;
+
+    SCA_WEB* pswList = NULL;
+    SCA_WEBDIR* pswdList = NULL;
+    SCA_VDIR* psvdList = NULL;
+    SCA_FILTER* psfList = NULL;
+    SCA_APPPOOL *psapList = NULL;
+    SCA_MIMEMAP* psmmList = NULL;
+    SCA_HTTP_HEADER* pshhList = NULL;
+    SCA_PROPERTY *pspList = NULL;
+    SCA_WEBSVCEXT* psWseList = NULL;
+    SCA_WEB_ERROR* psweList = NULL;
+
+    LPWSTR pwzScriptKey = NULL;
+    LPWSTR pwzCustomActionData = NULL;
+
+    WCA_WRAPQUERY_HANDLE hUserQuery = NULL;
+    WCA_WRAPQUERY_HANDLE hWebBaseQuery = NULL;
+    WCA_WRAPQUERY_HANDLE hWebDirPropQuery = NULL;
+    WCA_WRAPQUERY_HANDLE hSslCertQuery = NULL;
+    WCA_WRAPQUERY_HANDLE hWebLogQuery = NULL;
+    WCA_WRAPQUERY_HANDLE hWebAppQuery = NULL;
+    WCA_WRAPQUERY_HANDLE hWebAppExtQuery = NULL;
+
+    // initialize
+    hr = WcaInitialize(hInstall, "ConfigureIIsExec");
+    ExitOnFailure(hr, "Failed to initialize");
+
+    hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
+    ExitOnFailure(hr, "failed to get CustomActionData");
+
+    // Get the CaScript key
+    hr = WcaReadStringFromCaData(&pwzCustomActionData, &pwzScriptKey);
+    ExitOnFailure(hr, "Failed to get CaScript key from custom action data");
+
+    hr = ::CoInitialize(NULL);
+    ExitOnFailure(hr, "failed to initialize COM");
+    fInitializedCom = TRUE;
+
+    // if IIS was uninstalled (thus no IID_IMSAdminBase) allow the
+    // user to still uninstall this package by clicking "Ignore"
+    do
+    {
+        hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, (void**)&piMetabase);
+        if (FAILED(hr))
+        {
+            WcaLog(LOGMSG_STANDARD, "failed to get IID_IMSAdminBase Object");
+            er = WcaErrorMessage(msierrIISCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
+            switch (er)
+            {
+            case IDABORT:
+                ExitFunction();   // bail with the error result from the CoCreate to kick off a rollback
+            case IDRETRY:
+                hr = S_FALSE;   // hit me, baby, one more time
+                break;
+            case IDIGNORE:
+                __fallthrough;
+            default:
+                WcaLog(LOGMSG_STANDARD, "ignoring absent IIS");
+                // We need to write the empty script to communicate to other deferred CA that there is noting to do.
+                hr = ScaWriteConfigurationScript(pwzScriptKey);
+                ExitOnFailure(hr, "failed to schedule metabase configuration");
+
+                ExitFunction1(hr = S_OK);  // pretend everything is okay
+                break;
+            }
+        }
+    } while (S_FALSE == hr);
+
+    // read the msi tables
+    hr = WcaBeginUnwrapQuery(&hUserQuery, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap user query");
+
+    hr = ScaWebSvcExtRead(&psWseList, &pwzCustomActionData);
+    MessageExitOnFailure(hr, msierrIISFailedReadWebSvcExt, "failed while processing WebServiceExtensions");
+
+    hr = ScaAppPoolRead(&psapList, hUserQuery, &pwzCustomActionData);
+    MessageExitOnFailure(hr, msierrIISFailedReadAppPool, "failed while processing WebAppPools");
+
+    // MimeMap, Error and HttpHeader need to be read before the virtual directory and web read
+    hr = ScaMimeMapRead(&psmmList, &pwzCustomActionData);
+    MessageExitOnFailure(hr, msierrIISFailedReadMimeMap, "failed while processing MimeMaps");
+
+    hr = ScaHttpHeaderRead(&pshhList, &pwzCustomActionData);
+    MessageExitOnFailure(hr, msierrIISFailedReadHttpHeader, "failed while processing HttpHeaders");
+
+    hr = ScaWebErrorRead(&psweList, &pwzCustomActionData);
+    MessageExitOnFailure(hr, msierrIISFailedReadWebError, "failed while processing WebErrors");
+
+    hr = WcaBeginUnwrapQuery(&hWebDirPropQuery, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap web dir properties query");
+
+    hr = WcaBeginUnwrapQuery(&hSslCertQuery, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap ssl certificate query");
+
+    hr = WcaBeginUnwrapQuery(&hWebLogQuery, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap web log query");
+
+    hr = WcaBeginUnwrapQuery(&hWebAppQuery, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap web application query");
+
+    hr = WcaBeginUnwrapQuery(&hWebAppExtQuery, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap web application extension query");
+
+    hr = ScaWebsRead(piMetabase, &psmmList, &pswList, &pshhList, &psweList, hUserQuery, hWebDirPropQuery, hSslCertQuery, hWebLogQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData);
+    MessageExitOnFailure(hr, msierrIISFailedReadWebSite, "failed while processing WebSites");
+
+    hr = WcaBeginUnwrapQuery(&hWebBaseQuery, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap web base query");
+
+    hr = ScaWebDirsRead(piMetabase, pswList, hUserQuery, hWebBaseQuery, hWebDirPropQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData, &pswdList);
+    MessageExitOnFailure(hr, msierrIISFailedReadWebDirs, "failed while processing WebDirs");
+
+    hr = ScaVirtualDirsRead(piMetabase, pswList, &psvdList, &psmmList, &pshhList, &psweList, hUserQuery, hWebBaseQuery, hWebDirPropQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData);
+    MessageExitOnFailure(hr, msierrIISFailedReadVDirs, "failed while processing WebVirtualDirs");
+
+    hr = ScaFiltersRead(piMetabase, pswList, hWebBaseQuery, &psfList, &pwzCustomActionData);
+    MessageExitOnFailure(hr, msierrIISFailedReadFilters, "failed while processing WebFilters");
+
+    hr = ScaPropertyRead(&pspList, &pwzCustomActionData);
+    MessageExitOnFailure(hr, msierrIISFailedReadProp, "failed while processing WebProperties");
+
+    // do uninstall actions (order is important!)
+    hr = ScaPropertyUninstall(piMetabase, pspList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallProp, "failed to uninstall IIS properties");
+
+    hr = ScaFiltersUninstall(piMetabase, psfList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallFilters, "failed to schedule uninstall of filters");
+
+    hr = ScaVirtualDirsUninstall(piMetabase, psvdList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallVDirs, "failed to schedule uninstall of virtual directories");
+
+    hr = ScaWebDirsUninstall(piMetabase, pswdList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallWebDirs, "failed to schedule uninstall of web directories");
+
+    hr = ScaWebsUninstall(piMetabase, pswList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallWebs, "failed to schedule uninstall of webs");
+
+    hr = ScaAppPoolUninstall(piMetabase, psapList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallAppPool, "failed to schedule uninstall of AppPools");
+
+
+    // do install actions (order is important!)
+    // ScaWebSvcExtCommit contains both uninstall and install actions.
+    hr = ScaWebSvcExtCommit(piMetabase, psWseList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebSvcExt, "failed to schedule install/uninstall of WebSvcExt");
+
+    hr = ScaAppPoolInstall(piMetabase, psapList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedInstallAppPool, "failed to schedule install of AppPools");
+
+    hr = ScaWebsInstall(piMetabase, pswList, psapList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebs, "failed to schedule install of webs");
+
+    hr = ScaWebDirsInstall(piMetabase, pswdList, psapList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebDirs, "failed to schedule install of web directories");
+
+    hr = ScaVirtualDirsInstall(piMetabase, psvdList, psapList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedInstallVDirs, "failed to schedule install of virtual directories");
+
+    hr = ScaFiltersInstall(piMetabase, psfList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedInstallFilters, "failed to schedule install of filters");
+
+    hr = ScaPropertyInstall(piMetabase, pspList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedInstallProp, "failed to schedule install of properties");
+
+    hr = ScaWriteConfigurationScript(pwzScriptKey);
+    ExitOnFailure(hr, "failed to schedule metabase configuration");
+
+LExit:
+    ReleaseStr(pwzScriptKey);
+    ReleaseStr(pwzCustomActionData);
+
+    WcaFinishUnwrapQuery(hUserQuery);
+    WcaFinishUnwrapQuery(hWebBaseQuery);
+    WcaFinishUnwrapQuery(hWebDirPropQuery);
+    WcaFinishUnwrapQuery(hSslCertQuery);
+    WcaFinishUnwrapQuery(hWebLogQuery);
+    WcaFinishUnwrapQuery(hWebAppQuery);
+    WcaFinishUnwrapQuery(hWebAppExtQuery);
+
+    if (psWseList)
+    {
+        ScaWebSvcExtFreeList(psWseList);
+    }
+
+    if (psfList)
+    {
+        ScaFiltersFreeList(psfList);
+    }
+
+    if (psvdList)
+    {
+        ScaVirtualDirsFreeList(psvdList);
+    }
+
+    if (pswdList)
+    {
+        ScaWebDirsFreeList(pswdList);
+    }
+
+    if (pswList)
+    {
+        ScaWebsFreeList(pswList);
+    }
+
+    if (psmmList)
+    {
+        ScaMimeMapCheckList(psmmList);
+        ScaMimeMapFreeList(psmmList);
+    }
+
+    if (pshhList)
+    {
+        ScaHttpHeaderCheckList(pshhList);
+        ScaHttpHeaderFreeList(pshhList);
+    }
+
+    if (psweList)
+    {
+        ScaWebErrorCheckList(psweList);
+        ScaWebErrorFreeList(psweList);
+    }
+
+    ReleaseObject(piMetabase);
+
+    if (fInitializedCom)
+    {
+        ::CoUninitialize();
+    }
+
+    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
+    return WcaFinalize(er);
+}
+
+
+/********************************************************************
+ConfigureIIs - CUSTOM ACTION ENTRY POINT for installing IIs settings
+
+********************************************************************/
+extern "C" UINT __stdcall ConfigureIIs7Exec(
+    __in MSIHANDLE hInstall
+    )
+{
+    //AssertSz(FALSE, "debug ConfigureIIs7Exec here");
+    HRESULT hr = S_OK;
+    UINT er = ERROR_SUCCESS;
+
+    LPWSTR pwzScriptKey = NULL;
+    LPWSTR pwzCustomActionData = NULL;
+
+    SCA_WEB7* pswList = NULL;
+    SCA_WEBDIR7* pswdList = NULL;
+    SCA_VDIR7* psvdList = NULL;
+    SCA_FILTER* psfList = NULL;
+    SCA_APPPOOL *psapList = NULL;
+    SCA_MIMEMAP* psmmList = NULL;
+    SCA_HTTP_HEADER* pshhList = NULL;
+    SCA_PROPERTY *pspList = NULL;
+    SCA_WEBSVCEXT* psWseList = NULL;
+    SCA_WEB_ERROR* psweList = NULL;
+
+    WCA_WRAPQUERY_HANDLE hUserQuery = NULL;
+    WCA_WRAPQUERY_HANDLE hWebBaseQuery = NULL;
+    WCA_WRAPQUERY_HANDLE hWebDirPropQuery = NULL;
+    WCA_WRAPQUERY_HANDLE hSslCertQuery = NULL;
+    WCA_WRAPQUERY_HANDLE hWebLogQuery = NULL;
+    WCA_WRAPQUERY_HANDLE hWebAppQuery = NULL;
+    WCA_WRAPQUERY_HANDLE hWebAppExtQuery = NULL;
+
+    // initialize
+    hr = WcaInitialize(hInstall, "ConfigureIIs7Exec");
+    ExitOnFailure(hr, "Failed to initialize");
+
+    hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
+    ExitOnFailure(hr, "failed to get CustomActionData");
+
+    // Get the CaScript key
+    hr = WcaReadStringFromCaData(&pwzCustomActionData, &pwzScriptKey);
+    ExitOnFailure(hr, "Failed to get CaScript key from custom action data");
+
+    // read the msi tables
+    hr = WcaBeginUnwrapQuery(&hUserQuery, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap user query");
+
+    hr = ScaWebSvcExtRead(&psWseList, &pwzCustomActionData);
+    MessageExitOnFailure(hr, msierrIISFailedReadWebSvcExt, "failed while processing WebServiceExtensions");
+
+    hr = ScaAppPoolRead(&psapList, hUserQuery, &pwzCustomActionData);
+    MessageExitOnFailure(hr, msierrIISFailedReadAppPool, "failed while processing WebAppPools");
+
+    // MimeMap, Error and HttpHeader need to be read before the virtual directory and web read
+    hr = ScaMimeMapRead(&psmmList, &pwzCustomActionData);
+    MessageExitOnFailure(hr, msierrIISFailedReadMimeMap, "failed while processing MimeMaps");
+
+    hr = ScaHttpHeaderRead(&pshhList, &pwzCustomActionData);
+    MessageExitOnFailure(hr, msierrIISFailedReadHttpHeader, "failed while processing HttpHeaders");
+
+    hr = ScaWebErrorRead(&psweList, &pwzCustomActionData);
+    MessageExitOnFailure(hr, msierrIISFailedReadWebError, "failed while processing WebErrors");
+
+    hr = WcaBeginUnwrapQuery(&hWebDirPropQuery, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap web dir properties query");
+
+    hr = WcaBeginUnwrapQuery(&hSslCertQuery, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap ssl certificate query");
+
+    hr = WcaBeginUnwrapQuery(&hWebLogQuery, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap web log query");
+
+    hr = WcaBeginUnwrapQuery(&hWebAppQuery, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap web application query");
+
+    hr = WcaBeginUnwrapQuery(&hWebAppExtQuery, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap web application extension query");
+
+    hr = ScaWebsRead7(&pswList, &pshhList, &psweList, hUserQuery, hWebDirPropQuery, hSslCertQuery, hWebLogQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData);
+    MessageExitOnFailure(hr, msierrIISFailedReadWebSite, "failed while processing WebSites");
+
+    hr = WcaBeginUnwrapQuery(&hWebBaseQuery, &pwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap web base query");
+
+    hr = ScaWebDirsRead7(pswList, hUserQuery, hWebBaseQuery, hWebDirPropQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData, &pswdList);
+    MessageExitOnFailure(hr, msierrIISFailedReadWebDirs, "failed while processing WebDirs");
+
+    hr = ScaVirtualDirsRead7(pswList, &psvdList, &psmmList, &pshhList, &psweList, hUserQuery, hWebBaseQuery, hWebDirPropQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData);
+    MessageExitOnFailure(hr, msierrIISFailedReadVDirs, "failed while processing WebVirtualDirs");
+
+    hr = ScaFiltersRead7(pswList, hWebBaseQuery, &psfList, &pwzCustomActionData);
+    MessageExitOnFailure(hr, msierrIISFailedReadFilters, "failed while processing WebFilters");
+
+    hr = ScaPropertyRead(&pspList, &pwzCustomActionData);
+    MessageExitOnFailure(hr, msierrIISFailedReadProp, "failed while processing WebProperties");
+
+    // do uninstall actions (order is important!)
+    hr = ScaPropertyUninstall7(pspList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallProp, "failed to uninstall IIS properties");
+
+    hr = ScaFiltersUninstall7(psfList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallFilters, "failed to schedule uninstall of filters");
+
+    hr = ScaVirtualDirsUninstall7(psvdList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallVDirs, "failed to schedule uninstall of virtual directories");
+
+    hr = ScaWebDirsUninstall7(pswdList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallWebDirs, "failed to schedule uninstall of web directories");
+
+    hr = ScaWebsUninstall7(pswList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallWebs, "failed to schedule uninstall of webs");
+
+    hr = ScaAppPoolUninstall7(psapList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallAppPool, "failed to schedule uninstall of AppPools");
+
+
+    // do install actions (order is important!)
+    // ScaWebSvcExtCommit contains both uninstall and install actions.
+    hr = ScaWebSvcExtCommit7(psWseList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebSvcExt, "failed to schedule install/uninstall of WebSvcExt");
+
+    hr = ScaAppPoolInstall7(psapList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedInstallAppPool, "failed to schedule install of AppPools");
+
+    hr = ScaWebsInstall7(pswList, psapList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebs, "failed to schedule install of webs");
+
+    hr = ScaWebDirsInstall7(pswdList, psapList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebDirs, "failed to schedule install of web directories");
+
+    hr = ScaVirtualDirsInstall7(psvdList, psapList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedInstallVDirs, "failed to schedule install of virtual directories");
+
+    hr = ScaFiltersInstall7(psfList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedInstallFilters, "failed to schedule install of filters");
+
+    hr = ScaPropertyInstall7(pspList);
+    MessageExitOnFailure(hr, msierrIISFailedSchedInstallProp, "failed to schedule install of properties");
+
+    hr = ScaWriteConfigurationScript(pwzScriptKey);
+    ExitOnFailure(hr, "failed to schedule metabase configuration");
+
+LExit:
+    ReleaseNullStr(pwzScriptKey);
+    ReleaseNullStr(pwzCustomActionData);
+
+    WcaFinishUnwrapQuery(hUserQuery);
+    WcaFinishUnwrapQuery(hWebBaseQuery);
+    WcaFinishUnwrapQuery(hWebDirPropQuery);
+    WcaFinishUnwrapQuery(hSslCertQuery);
+    WcaFinishUnwrapQuery(hWebLogQuery);
+    WcaFinishUnwrapQuery(hWebAppQuery);
+    WcaFinishUnwrapQuery(hWebAppExtQuery);
+
+    if (psWseList)
+    {
+        ScaWebSvcExtFreeList(psWseList);
+    }
+
+    if (psfList)
+    {
+        ScaFiltersFreeList(psfList);
+    }
+
+    if (psvdList)
+    {
+        ScaVirtualDirsFreeList7(psvdList);
+    }
+
+    if (pswdList)
+    {
+        ScaWebDirsFreeList7(pswdList);
+    }
+
+    if (pswList)
+    {
+        ScaWebsFreeList7(pswList);
+    }
+
+    if (psmmList)
+    {
+        ScaMimeMapFreeList(psmmList);
+    }
+
+    if (pshhList)
+    {
+        ScaHttpHeaderCheckList(pshhList);
+        ScaHttpHeaderFreeList(pshhList);
+    }
+
+    if (psweList)
+    {
+        ScaWebErrorCheckList(psweList);
+        ScaWebErrorFreeList(psweList);
+    }
+
+    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
+    return WcaFinalize(er);
+}
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 @@
+// 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.
+
+#include "precomp.h"
+
+enum eSslCertificateQuery { scqStoreName = 1, scqHash, scqWeb };
+
+static HRESULT AddSslCertificateToList(
+    __in SCA_WEB_SSL_CERTIFICATE** ppswscList
+    );
+
+
+HRESULT ScaSslCertificateRead(
+    __in LPCWSTR wzWebId,
+    __in WCA_WRAPQUERY_HANDLE hSslCertQuery,
+    __inout SCA_WEB_SSL_CERTIFICATE** ppswscList
+    )
+{
+    HRESULT hr = S_OK;
+
+    MSIHANDLE hRec;
+    SCA_WEB_SSL_CERTIFICATE* pswsc = NULL;
+    LPWSTR pwzData = NULL;
+
+    WcaFetchWrappedReset(hSslCertQuery);
+
+    // Get the certificate information.
+    while (S_OK == (hr = WcaFetchWrappedRecordWhereString(hSslCertQuery, scqWeb, wzWebId, &hRec)))
+    {
+        hr = AddSslCertificateToList(ppswscList);
+        ExitOnFailure(hr, "failed to add ssl certificate to list");
+
+        pswsc = *ppswscList;
+
+        hr = WcaGetRecordString(hRec, scqStoreName, &pwzData);
+        ExitOnFailure(hr, "Failed to get web ssl certificate store name.");
+
+        hr = ::StringCchCopyW(pswsc->wzStoreName, countof(pswsc->wzStoreName), pwzData);
+        ExitOnFailure(hr, "Failed to copy web ssl certificate store name.");
+
+        hr = WcaGetRecordString(hRec, scqHash, &pwzData);
+        ExitOnFailure(hr, "Failed to get hash for web ssl certificate.");
+
+        hr = StrHexDecode(pwzData, pswsc->rgbSHA1Hash, countof(pswsc->rgbSHA1Hash));
+        ExitOnFailure(hr, "Failed to decode certificate hash for web: %ls, data: %ls", wzWebId, pwzData);
+    }
+
+    if (E_NOMOREITEMS == hr)
+    {
+        hr = S_OK;
+    }
+    ExitOnFailure(hr, "Failed to read IIsWebSiteCertificates table.");
+
+LExit:
+    ReleaseStr(pwzData);
+    return hr;
+}
+
+
+HRESULT ScaSslCertificateWriteMetabase(
+    __in IMSAdminBase* piMetabase,
+    __in LPCWSTR wzWebBase,
+    __in SCA_WEB_SSL_CERTIFICATE* pswscList
+    )
+{
+    HRESULT hr = S_OK;
+    BLOB blob;
+
+    for (SCA_WEB_SSL_CERTIFICATE* pswsc = pswscList; pswsc; pswsc = pswsc->pNext)
+    {
+        // Write: /W3SVC/1:SslCertStoreName = "MY", "CA", "Root", etc.
+        hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_SSL_CERT_STORE_NAME, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, static_cast<LPVOID>(pswsc->wzStoreName));
+        ExitOnFailure(hr, "Failed to write SslCertStoreName");
+
+        // Write: /W3SVC/1:SslCertHash = <blob>
+        blob.pBlobData = pswsc->rgbSHA1Hash;
+        blob.cbSize = countof(pswsc->rgbSHA1Hash);
+        hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_SSL_CERT_HASH, METADATA_INHERIT, IIS_MD_UT_SERVER, BINARY_METADATA, static_cast<LPVOID>(&blob));
+        ExitOnFailure(hr, "Failed to write SslCertHash");
+    }
+
+LExit:
+    return hr;
+}
+
+
+void ScaSslCertificateFreeList(
+    __in SCA_WEB_SSL_CERTIFICATE* pswscList
+    )
+{
+    SCA_WEB_SSL_CERTIFICATE* pswscDelete = pswscList;
+    while (pswscList)
+    {
+        pswscDelete = pswscList;
+        pswscList = pswscList->pNext;
+
+        MemFree(pswscDelete);
+    }
+}
+
+
+static HRESULT AddSslCertificateToList(
+    __in SCA_WEB_SSL_CERTIFICATE** ppswscList
+    )
+{
+    HRESULT hr = S_OK;
+
+    SCA_WEB_SSL_CERTIFICATE* pswsc = static_cast<SCA_WEB_SSL_CERTIFICATE*>(MemAlloc(sizeof(SCA_WEB_SSL_CERTIFICATE), TRUE));
+    ExitOnNull(pswsc, hr, E_OUTOFMEMORY, "failed to allocate memory for new SSL certificate list element");
+
+    pswsc->pNext = *ppswscList;
+    *ppswscList = pswsc;
+
+LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+#define MD_SSL_CERT_HASH                ( IIS_MD_SSL_BASE+6 )
+#define MD_SSL_CERT_STORE_NAME          ( IIS_MD_SSL_BASE+11 )
+//#define WIDE(x)		WIDE2(x)
+//#define WIDE2(x)	L ## x
+
+
+// structs
+struct SCA_WEB_SSL_CERTIFICATE
+{
+    WCHAR wzStoreName[65];
+    BYTE rgbSHA1Hash[CB_CERTIFICATE_HASH];
+
+    SCA_WEB_SSL_CERTIFICATE* pNext;
+};
+
+
+// prototypes
+HRESULT ScaSslCertificateRead(
+    __in LPCWSTR wzWebId,
+    __in WCA_WRAPQUERY_HANDLE hSslCertQuery,
+    __inout SCA_WEB_SSL_CERTIFICATE** ppswscList
+    );
+
+HRESULT ScaSslCertificateWriteMetabase(
+    __in IMSAdminBase* piMetabase,
+    __in LPCWSTR wzWebBase,
+    __in SCA_WEB_SSL_CERTIFICATE* pswscList
+    );
+
+void ScaSslCertificateFreeList(
+    __in SCA_WEB_SSL_CERTIFICATE* pswscList
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+HRESULT ScaSslCertificateWrite7(
+    __in_z LPCWSTR wzWebBase,
+    __in SCA_WEB_SSL_CERTIFICATE* pswscList
+    )
+{
+    HRESULT hr = S_OK;
+    WCHAR wzEncodedCertificateHash[CB_CERTIFICATE_HASH * 2 + 1] = { 0 };
+
+    for (SCA_WEB_SSL_CERTIFICATE* pswsc = pswscList; pswsc; pswsc = pswsc->pNext)
+    {
+        hr = ScaWriteConfigID(IIS_SSL_BINDING);
+        ExitOnFailure(hr, "Failed write SSL binding ID");
+        hr = ScaWriteConfigID(IIS_CREATE);                      // Need to determine site action
+        ExitOnFailure(hr, "Failed write binding action");
+
+        hr = ScaWriteConfigString(wzWebBase);                   //site name key
+        ExitOnFailure(hr, "Failed to write SSL website");
+        hr = ScaWriteConfigString(pswsc->wzStoreName);          //ssl store name
+        ExitOnFailure(hr, "Failed to write SSL store name");
+
+        hr = StrHexEncode(pswsc->rgbSHA1Hash, countof(pswsc->rgbSHA1Hash), wzEncodedCertificateHash, countof(wzEncodedCertificateHash));
+        ExitOnFailure(hr, "Failed to encode SSL hash");
+
+        hr = ScaWriteConfigString(wzEncodedCertificateHash);    //ssl hash
+        ExitOnFailure(hr, "Failed to write SSL hash");
+    }
+LExit:
+
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+HRESULT ScaSslCertificateWrite7(
+    __in_z LPCWSTR wzWebBase,
+    __in SCA_WEB_SSL_CERTIFICATE* pswscList
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+LPCWSTR vcsUserQuery = L"SELECT `User`, `Component_`, `Name`, `Domain`, `Password` FROM `User` WHERE `User`=?";
+enum eUserQuery { vuqUser = 1, vuqComponent, vuqName, vuqDomain, vuqPassword };
+
+LPCWSTR vcsGroupQuery = L"SELECT `Group`, `Component_`, `Name`, `Domain` FROM `Group` WHERE `Group`=?";
+enum eGroupQuery { vgqGroup = 1, vgqComponent, vgqName, vgqDomain };
+
+LPCWSTR vcsUserGroupQuery = L"SELECT `User_`, `Group_` FROM `UserGroup` WHERE `User_`=?";
+enum eUserGroupQuery { vugqUser = 1, vugqGroup };
+
+LPCWSTR vActionableQuery = L"SELECT `User`,`Component_`,`Name`,`Domain`,`Password`,`Attributes` FROM `User` WHERE `Component_` IS NOT NULL";
+enum eActionableQuery { vaqUser = 1, vaqComponent, vaqName, vaqDomain, vaqPassword, vaqAttributes };
+
+HRESULT __stdcall ScaGetUserDeferred(
+    __in LPCWSTR wzUser,
+    __in WCA_WRAPQUERY_HANDLE hUserQuery,
+    __out SCA_USER* pscau
+    )
+{
+    if (!wzUser || !pscau)
+    {
+        return E_INVALIDARG;
+    }
+
+    HRESULT hr = S_OK;
+    MSIHANDLE hRec, hRecTest;
+
+    LPWSTR pwzData = NULL;
+
+    // clear struct and bail right away if no user key was passed to search for
+    ::ZeroMemory(pscau, sizeof(*pscau));
+    if (!*wzUser)
+    {
+        ExitFunction1(hr = S_OK);
+    }
+
+    // Reset back to the first record
+    WcaFetchWrappedReset(hUserQuery);
+
+    hr = WcaFetchWrappedRecordWhereString(hUserQuery, vuqUser, wzUser, &hRec);
+    if (S_OK == hr)
+    {
+        hr = WcaFetchWrappedRecordWhereString(hUserQuery, vuqUser, wzUser, &hRecTest);
+        if (S_OK == hr)
+        {
+            AssertSz(FALSE, "Found multiple matching User rows");
+        }
+
+        hr = WcaGetRecordString(hRec, vuqUser, &pwzData);
+        ExitOnFailure(hr, "Failed to get User.User");
+        hr = ::StringCchCopyW(pscau->wzKey, countof(pscau->wzKey), pwzData);
+        ExitOnFailure(hr, "Failed to copy key string to user object (in deferred CA)");
+
+        hr = WcaGetRecordString(hRec, vuqComponent, &pwzData);
+        ExitOnFailure(hr, "Failed to get User.Component_");
+        hr = ::StringCchCopyW(pscau->wzComponent, countof(pscau->wzComponent), pwzData);
+        ExitOnFailure(hr, "Failed to copy component string to user object (in deferred CA)");
+
+        hr = WcaGetRecordString(hRec, vuqName, &pwzData);
+        ExitOnFailure(hr, "Failed to get User.Name");
+        hr = ::StringCchCopyW(pscau->wzName, countof(pscau->wzName), pwzData);
+        ExitOnFailure(hr, "Failed to copy name string to user object (in deferred CA)");
+
+        hr = WcaGetRecordString(hRec, vuqDomain, &pwzData);
+        ExitOnFailure(hr, "Failed to get User.Domain");
+        hr = ::StringCchCopyW(pscau->wzDomain, countof(pscau->wzDomain), pwzData);
+        ExitOnFailure(hr, "Failed to copy domain string to user object (in deferred CA)");
+
+        hr = WcaGetRecordString(hRec, vuqPassword, &pwzData);
+        ExitOnFailure(hr, "Failed to get User.Password");
+        hr = ::StringCchCopyW(pscau->wzPassword, countof(pscau->wzPassword), pwzData);
+        ExitOnFailure(hr, "Failed to copy password string to user object (in deferred CA)");
+    }
+    else if (E_NOMOREITEMS == hr)
+    {
+        WcaLog(LOGMSG_STANDARD, "Error: Cannot locate User.User='%ls'", wzUser);
+        hr = E_FAIL;
+    }
+    else
+    {
+        ExitOnFailure(hr, "Error fetching single User row");
+    }
+
+LExit:
+    ReleaseStr(pwzData);
+
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+// structs
+struct SCA_GROUP
+{
+    WCHAR wzKey[MAX_DARWIN_KEY + 1];
+    WCHAR wzComponent[MAX_DARWIN_KEY + 1];
+
+    WCHAR wzDomain[MAX_DARWIN_COLUMN + 1];
+    WCHAR wzName[MAX_DARWIN_COLUMN + 1];
+
+    SCA_GROUP *psgNext;
+};
+
+struct SCA_USER
+{
+    WCHAR wzKey[MAX_DARWIN_KEY + 1];
+    WCHAR wzComponent[MAX_DARWIN_KEY + 1];
+    INSTALLSTATE isInstalled;
+    INSTALLSTATE isAction;
+
+    WCHAR wzDomain[MAX_DARWIN_COLUMN + 1];
+    WCHAR wzName[MAX_DARWIN_COLUMN + 1];
+    WCHAR wzPassword[MAX_DARWIN_COLUMN + 1];
+    INT iAttributes;
+
+    SCA_GROUP *psgGroups;
+
+    SCA_USER *psuNext;
+};
+
+
+// prototypes
+HRESULT __stdcall ScaGetUserDeferred(
+    __in LPCWSTR wzUser, 
+    __in WCA_WRAPQUERY_HANDLE hUserQuery,
+    __out SCA_USER* pscau
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+// prototypes
+static HRESULT AddVirtualDirToList(
+    __in SCA_VDIR** psvdList
+    );
+
+
+HRESULT __stdcall ScaVirtualDirsRead(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_WEB* pswList,
+    __in SCA_VDIR** ppsvdList,
+    __in SCA_MIMEMAP** ppsmmList,
+    __in SCA_HTTP_HEADER** ppshhList,
+    __in SCA_WEB_ERROR** ppsweList,
+    __in WCA_WRAPQUERY_HANDLE hUserQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebBaseQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
+    __inout LPWSTR *ppwzCustomActionData
+    )
+{
+    Assert(piMetabase && ppsvdList);
+
+    HRESULT hr = S_OK;
+    MSIHANDLE hRec;
+    INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN;
+    INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN;
+
+    SCA_VDIR* pvdir = NULL;
+    LPWSTR pwzData = NULL;
+
+    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
+
+    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead");
+
+    if (0 == WcaGetQueryRecords(hWrapQuery))
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ScaVirtualDirsRead() because IIsWebVirtualDir table not present");
+        ExitFunction1(hr = S_FALSE);
+    }
+
+    // loop through all the vdirs
+    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
+    {
+        // Get the Component first.  If there is a Component and it is not being modified during
+        // this transaction, skip processing this whole record.
+        hr = WcaGetRecordString(hRec, vdqComponent, &pwzData);
+        ExitOnFailure(hr, "failed to get IIsWebVirtualDir.Component");
+
+        hr = WcaGetRecordInteger(hRec, vdqInstalled, (int *)&isInstalled);
+        ExitOnFailure(hr, "Failed to get Component installed state for virtual dir");
+
+        hr = WcaGetRecordInteger(hRec, vdqAction, (int *)&isAction);
+        ExitOnFailure(hr, "Failed to get Component action state for virtual dir");
+
+        if (!WcaIsInstalling(isInstalled, isAction) &&
+            !WcaIsReInstalling(isInstalled, isAction) &&
+            !WcaIsUninstalling(isInstalled, isAction))
+        {
+            continue; // skip this record.
+        }
+
+        hr = AddVirtualDirToList(ppsvdList);
+        ExitOnFailure(hr, "failed to add virtual dir to list");
+
+        pvdir = *ppsvdList;
+
+        hr = ::StringCchCopyW(pvdir->wzComponent, countof(pvdir->wzComponent), pwzData);
+        ExitOnFailure(hr, "failed to copy component name: %ls", pwzData);
+
+        pvdir->isInstalled = isInstalled;
+        pvdir->isAction = isAction;
+
+        // get the web key
+        hr = WcaGetRecordString(hRec, vdqWeb, &pwzData);
+        ExitOnFailure(hr, "Failed to get Web for VirtualDir");
+
+        hr = ScaWebsGetBase(piMetabase, pswList, pwzData, pvdir->wzWebBase, countof(pvdir->wzWebBase), hWebBaseQuery);
+        if (WcaIsUninstalling(isInstalled, isAction))
+        {
+            // If we're uninstalling, ignore any failure to find the existing web
+            hr = S_OK;
+        }
+        ExitOnFailure(hr, "Failed to get base of web: %ls for VirtualDir", pwzData);
+
+        hr = WcaGetRecordString(hRec, vdqAlias, &pwzData);
+        ExitOnFailure(hr, "Failed to get Alias for VirtualDir");
+
+        if (0 != lstrlenW(pvdir->wzWebBase))
+        {
+            hr = ::StringCchPrintfW(pvdir->wzVDirRoot, countof(pvdir->wzVDirRoot), L"%s/Root/%s", pvdir->wzWebBase, pwzData);
+            ExitOnFailure(hr, "Failed to set VDirRoot for VirtualDir");
+        }
+
+        // get the vdir's directory
+        hr = WcaGetRecordString(hRec, vdqDirectory, &pwzData);
+        ExitOnFailure(hr, "Failed to get Directory for VirtualDir");
+
+        // get the web's directory
+        if (INSTALLSTATE_SOURCE == pvdir->isAction)
+        {
+            hr = WcaGetRecordString(hRec, vdqSourcePath, &pwzData);
+        }
+        else
+        {
+            hr = WcaGetRecordString(hRec, vdqTargetPath, &pwzData);
+        }
+        ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory");
+
+        // remove trailing backslash(es)
+        while (lstrlenW(pwzData) > 0 && pwzData[lstrlenW(pwzData)-1] == L'\\')
+        {
+            pwzData[lstrlenW(pwzData)-1] = 0;
+        }
+        hr = ::StringCchCopyW(pvdir->wzDirectory, countof(pvdir->wzDirectory), pwzData);
+        ExitOnFailure(hr, "Failed to copy directory string to vdir object");
+
+        // get the security information for this web
+        hr = WcaGetRecordString(hRec, vdqProperties, &pwzData);
+        ExitOnFailure(hr, "Failed to get web directory identifier for VirtualDir");
+        if (*pwzData)
+        {
+            hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &pvdir->swp);
+            ExitOnFailure(hr, "Failed to get web directory for VirtualDir");
+
+            pvdir->fHasProperties = TRUE;
+        }
+
+        // get the application information for this web
+        hr = WcaGetRecordString(hRec, vdqApplication, &pwzData);
+        ExitOnFailure(hr, "Failed to get application identifier for VirtualDir");
+        if (*pwzData)
+        {
+            hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &pvdir->swapp);
+            ExitOnFailure(hr, "Failed to get application for VirtualDir");
+
+            pvdir->fHasApplication = TRUE;
+        }
+
+        hr = WcaGetRecordString(hRec, vdqVDir, &pwzData);
+        ExitOnFailure(hr, "Failed to get VDir for VirtualDir");
+
+        if (*pwzData && *ppsmmList)
+        {
+            hr = ScaGetMimeMap(mmptVDir, pwzData, ppsmmList, &pvdir->psmm);
+            ExitOnFailure(hr, "Failed to get mimemap for VirtualDir");
+        }
+
+        if (*pwzData && *ppshhList)
+        {
+            hr = ScaGetHttpHeader(hhptVDir, pwzData, ppshhList, &pvdir->pshh);
+            ExitOnFailure(hr, "Failed to get custom HTTP headers for VirtualDir: %ls", pwzData);
+        }
+
+        if (*pwzData && *ppsweList)
+        {
+            hr = ScaGetWebError(weptVDir, pwzData, ppsweList, &pvdir->pswe);
+            ExitOnFailure(hr, "Failed to get custom web errors for VirtualDir: %ls", pwzData);
+        }
+    }
+
+    if (E_NOMOREITEMS == hr)
+    {
+        hr = S_OK;
+    }
+    ExitOnFailure(hr, "Failure while processing VirtualDirs");
+
+LExit:
+    WcaFinishUnwrapQuery(hWrapQuery);
+
+    ReleaseStr(pwzData);
+    return hr;
+}
+
+
+HRESULT ScaVirtualDirsInstall(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_VDIR* psvdList,
+    __in SCA_APPPOOL * psapList
+    )
+{
+    Assert(piMetabase);
+
+    HRESULT hr = S_OK;
+    SCA_VDIR* psvd = psvdList;
+    int i;
+
+    while (psvd)
+    {
+        // On reinstall, we have to uninstall the old application, otherwise a duplicate will be created
+        if (WcaIsReInstalling(psvd->isInstalled, psvd->isAction))
+        {
+            if (psvd->fHasApplication)
+            {
+                hr = ScaDeleteApp(piMetabase, psvd->wzVDirRoot);
+                ExitOnFailure(hr, "Failed to remove application for WebVDir as part of a reinstall");
+            }
+        }
+
+        if (WcaIsInstalling(psvd->isInstalled, psvd->isAction))
+        {
+            hr = ScaCreateMetabaseKey(piMetabase, psvd->wzVDirRoot, L"");
+            ExitOnFailure(hr, "Failed to create key for VirtualDir");
+            hr = ScaWriteMetabaseValue(piMetabase, psvd->wzVDirRoot, L"", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsWebVirtualDir");
+            ExitOnFailure(hr, "Failed to write key type for for VirtualDir");
+            i = 0x4000003e; // 1073741886;	// default directory browsing rights
+            hr = ScaWriteMetabaseValue(piMetabase, psvd->wzVDirRoot, L"", MD_DIRECTORY_BROWSING, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)i));
+            ExitOnFailure(hr, "Failed to set directory browsing for VirtualDir");
+
+            hr = ScaWriteMetabaseValue(piMetabase, psvd->wzVDirRoot, L"", MD_VR_PATH, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)psvd->wzDirectory);
+            ExitOnFailure(hr, "Failed to write Directory for VirtualDir");
+
+            if (psvd->fHasProperties)
+            {
+                ScaWriteWebDirProperties(piMetabase, psvd->wzVDirRoot, &psvd->swp);
+                ExitOnFailure(hr, "Failed to write directory properties for VirtualDir");
+            }
+
+            if (psvd->fHasApplication)
+            {
+                hr = ScaWriteWebApplication(piMetabase, psvd->wzVDirRoot, &psvd->swapp, psapList);
+                ExitOnFailure(hr, "Failed to write application for VirtualDir");
+            }
+
+            if (psvd->psmm)
+            {
+                hr = ScaWriteMimeMap(piMetabase, psvd->wzVDirRoot, psvd->psmm);
+                ExitOnFailure(hr, "Failed to write mimemap for VirtualDir");
+            }
+
+            if (psvd->pshh)
+            {
+                hr = ScaWriteHttpHeader(piMetabase, psvd->wzVDirRoot, psvd->pshh);
+                ExitOnFailure(hr, "Failed to write custom HTTP headers for VirtualDir");
+            }
+
+            if (psvd->pswe)
+            {
+                hr = ScaWriteWebError(piMetabase, weptVDir, psvd->wzVDirRoot, psvd->pswe);
+                ExitOnFailure(hr, "Failed to write custom web errors for VirtualDir");
+            }
+        }
+
+        psvd = psvd->psvdNext;
+    }
+
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaVirtualDirsUninstall(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_VDIR* psvdList
+    )
+{
+    Assert(piMetabase);
+
+    HRESULT hr = S_OK;
+    SCA_VDIR* psvd = psvdList;
+
+    while (psvd)
+    {
+        if (WcaIsUninstalling(psvd->isInstalled, psvd->isAction))
+        {
+            // delete the application for this virtual directory
+            if (psvd->fHasApplication)
+            {
+                hr = ScaDeleteApp(piMetabase, psvd->wzVDirRoot);
+                ExitOnFailure(hr, "Failed to remove application for WebVDir");
+            }
+
+            if (0 != lstrlenW(psvd->wzVDirRoot))
+            {
+                hr = ScaDeleteMetabaseKey(piMetabase, psvd->wzVDirRoot, L"");
+                ExitOnFailure(hr, "Failed to remove VirtualDir '%ls' from metabase", psvd->wzKey);
+            }
+        }
+
+        psvd = psvd->psvdNext;
+    }
+
+LExit:
+    return hr;
+}
+
+
+void ScaVirtualDirsFreeList(
+    __in SCA_VDIR* psvdList
+    )
+{
+    SCA_VDIR* psvdDelete = psvdList;
+    while (psvdList)
+    {
+        psvdDelete = psvdList;
+        psvdList = psvdList->psvdNext;
+
+        if (psvdDelete->psmm)
+        {
+            ScaMimeMapFreeList(psvdDelete->psmm);
+        }
+
+        if (psvdDelete->pswe)
+        {
+            ScaWebErrorFreeList(psvdDelete->pswe);
+        }
+
+        MemFree(psvdDelete);
+    }
+}
+
+
+static HRESULT AddVirtualDirToList(
+    __in SCA_VDIR** ppsvdList
+    )
+{
+    HRESULT hr = S_OK;
+    SCA_VDIR* psvd = static_cast<SCA_VDIR*>(MemAlloc(sizeof(SCA_VDIR), TRUE));
+    ExitOnNull(psvd, hr, E_OUTOFMEMORY, "failed to allocate memory for new vdir list element");
+
+    psvd->psvdNext= *ppsvdList;
+    *ppsvdList = psvd;
+
+LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+#include "scawebprop.h"
+#include "scawebapp.h"
+#include "scamimemap.h"
+#include "scaapppool.h"
+
+enum eVDirQuery { vdqWeb = 1, vdqVDir, vdqComponent , vdqAlias, vdqDirectory, vdqProperties, vdqApplication, vdqInstalled, vdqAction, vdqSourcePath, vdqTargetPath };
+
+struct SCA_VDIR
+{
+    // darwin information
+    WCHAR wzKey[MAX_DARWIN_KEY + 1];
+    WCHAR wzComponent[MAX_DARWIN_KEY + 1];
+    INSTALLSTATE isInstalled;
+    INSTALLSTATE isAction;
+
+    // metabase information
+    WCHAR wzWebKey[MAX_DARWIN_KEY + 1];
+    WCHAR wzWebBase[METADATA_MAX_NAME_LEN + 1];
+    WCHAR wzVDirRoot[METADATA_MAX_NAME_LEN + 1];
+
+    // iis configuation information
+    WCHAR wzDirectory[MAX_PATH];
+
+    BOOL fHasProperties;
+    SCA_WEB_PROPERTIES swp;
+
+    BOOL fHasApplication;
+    SCA_WEB_APPLICATION swapp;
+
+    SCA_MIMEMAP* psmm; // mime mappings
+    SCA_HTTP_HEADER* pshh; // custom web errors
+    SCA_WEB_ERROR* pswe; // custom web errors
+
+    SCA_VDIR* psvdNext;
+};
+
+
+// prototypes
+HRESULT __stdcall ScaVirtualDirsRead(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_WEB* pswList,
+    __in SCA_VDIR** ppsvdList,
+    __in SCA_MIMEMAP** ppsmmList,
+    __in SCA_HTTP_HEADER** ppshhList,
+    __in SCA_WEB_ERROR** ppsweList,
+    __in WCA_WRAPQUERY_HANDLE hUserQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebBaseQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
+    __inout LPWSTR *ppwzCustomActionData
+    );
+
+HRESULT ScaVirtualDirsInstall(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_VDIR* psvdList,
+    __in SCA_APPPOOL * psapList
+    );
+
+HRESULT ScaVirtualDirsUninstall(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_VDIR* psvdList
+    );
+
+void ScaVirtualDirsFreeList(
+    __in SCA_VDIR* psvdList
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+// prototypes
+static HRESULT AddVirtualDirToList7(
+    __in SCA_VDIR7** psvdList
+    );
+
+
+HRESULT __stdcall ScaVirtualDirsRead7(
+    __in SCA_WEB7* pswList,
+    __in SCA_VDIR7** ppsvdList,
+    __in SCA_MIMEMAP** ppsmmList,
+    __in SCA_HTTP_HEADER** ppshhList,
+    __in SCA_WEB_ERROR** ppsweList,
+    __in WCA_WRAPQUERY_HANDLE hUserQuery,
+    __in WCA_WRAPQUERY_HANDLE /*hWebBaseQuery*/,
+    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
+    __inout LPWSTR *ppwzCustomActionData
+    )
+{
+    Assert(ppsvdList);
+
+    HRESULT hr = S_OK;
+    MSIHANDLE hRec;
+
+    SCA_VDIR7* pvdir = NULL;
+    LPWSTR pwzData = NULL;
+    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
+
+    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead");
+
+    if (0 == WcaGetQueryRecords(hWrapQuery))
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ScaVirtualDirsRead() because IIsWebVirtualDir table not present");
+        ExitFunction1(hr = S_FALSE);
+    }
+
+    // loop through all the vdirs
+    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
+    {
+        // Add this record's information into the list of things to process.
+        hr = AddVirtualDirToList7(ppsvdList);
+        ExitOnFailure(hr, "failed to add vdir to vdir list");
+
+        pvdir = *ppsvdList;
+
+        // get the darwin information
+        hr = WcaGetRecordString(hRec, vdqComponent, &pwzData);
+        ExitOnFailure(hr, "failed to get IIsWebVirtualDir.Component");
+
+        hr = WcaGetRecordInteger(hRec, vdqInstalled, (int *)&pvdir->isInstalled);
+        ExitOnFailure(hr, "Failed to get Component installed state for virtual dir");
+
+        hr = WcaGetRecordInteger(hRec, vdqAction, (int *)&pvdir->isAction);
+        ExitOnFailure(hr, "Failed to get Component action state for virtual dir");
+
+        // get vdir properties
+        hr = ::StringCchCopyW(pvdir->wzComponent, countof(pvdir->wzComponent), pwzData);
+        ExitOnFailure(hr, "failed to copy vdir component name: %ls", pwzData);
+
+        hr = WcaGetRecordString(hRec, vdqWeb, &pwzData);
+        ExitOnFailure(hr, "Failed to get Web for VirtualDir");
+
+        hr = ScaWebsGetBase7(pswList, pwzData, pvdir->wzWebName , countof(pvdir->wzWebName));
+        if (S_FALSE == hr)
+        {
+            hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
+            ExitOnFailure(hr, "Failed to get Web Base for VirtualDir");
+        }
+        if (WcaIsUninstalling(pvdir->isInstalled, pvdir->isAction))
+        {
+            // If we're uninstalling, ignore any failure to find the existing web
+            hr = S_OK;
+        }
+
+        hr = WcaGetRecordString(hRec, vdqAlias, &pwzData);
+        ExitOnFailure(hr, "Failed to get Alias for VirtualDir");
+
+        hr = ::StringCchCopyW(pvdir->wzVDirRoot, countof(pvdir->wzVDirRoot), pwzData);
+        ExitOnFailure(hr, "Failed to set VDirRoot for VirtualDir");
+
+        // get the vdir's directory
+        hr = WcaGetRecordString(hRec, vdqDirectory, &pwzData);
+        ExitOnFailure(hr, "Failed to get Directory for VirtualDir");
+
+        // get the web's directory
+        if (INSTALLSTATE_SOURCE == pvdir->isAction)
+        {
+            hr = WcaGetRecordString(hRec, vdqSourcePath, &pwzData);
+        }
+        else
+        {
+            hr = WcaGetRecordString(hRec, vdqTargetPath, &pwzData);
+        }
+        ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory");
+
+        // remove trailing backslash(es)
+        while (lstrlenW(pwzData) > 0 && pwzData[lstrlenW(pwzData)-1] == L'\\')
+        {
+            pwzData[lstrlenW(pwzData)-1] = 0;
+        }
+        hr = ::StringCchCopyW(pvdir->wzDirectory, countof(pvdir->wzDirectory), pwzData);
+        ExitOnFailure(hr, "Failed to copy directory string to vdir object");
+
+        // get the security information for this web
+        hr = WcaGetRecordString(hRec, vdqProperties, &pwzData);
+        ExitOnFailure(hr, "Failed to get web directory identifier for VirtualDir");
+        if (*pwzData)
+        {
+            hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &pvdir->swp);
+            ExitOnFailure(hr, "Failed to get web directory for VirtualDir");
+
+            pvdir->fHasProperties = TRUE;
+        }
+
+        // get the application information for this web
+        hr = WcaGetRecordString(hRec, vdqApplication, &pwzData);
+        ExitOnFailure(hr, "Failed to get application identifier for VirtualDir");
+        if (*pwzData)
+        {
+            hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &pvdir->swapp);
+            ExitOnFailure(hr, "Failed to get application for VirtualDir");
+
+            pvdir->fHasApplication = TRUE;
+        }
+
+        hr = WcaGetRecordString(hRec, vdqVDir, &pwzData);
+        ExitOnFailure(hr, "Failed to get VDir for VirtualDir");
+
+        if (*pwzData && *ppsmmList)
+        {
+            hr = ScaGetMimeMap(mmptVDir, pwzData, ppsmmList, &pvdir->psmm);
+            ExitOnFailure(hr, "Failed to get mimemap for VirtualDir");
+        }
+
+        if (*pwzData && *ppshhList)
+        {
+            hr = ScaGetHttpHeader(hhptVDir, pwzData, ppshhList, &pvdir->pshh);
+            ExitOnFailure(hr, "Failed to get custom HTTP headers for VirtualDir: %ls", pwzData);
+        }
+
+        if (*pwzData && *ppsweList)
+        {
+            hr = ScaGetWebError(weptVDir, pwzData, ppsweList, &pvdir->pswe);
+            ExitOnFailure(hr, "Failed to get custom web errors for VirtualDir: %ls", pwzData);
+        }
+    }
+
+    if (E_NOMOREITEMS == hr)
+    {
+        hr = S_OK;
+    }
+    ExitOnFailure(hr, "Failure while processing VirtualDirs");
+
+LExit:
+    WcaFinishUnwrapQuery(hWrapQuery);
+
+    ReleaseStr(pwzData);
+
+    return hr;
+}
+
+
+HRESULT ScaVirtualDirsInstall7(
+    __in SCA_VDIR7* psvdList,
+    __in SCA_APPPOOL * psapList
+    )
+{
+    HRESULT hr = S_OK;
+    SCA_VDIR7* psvd = psvdList;
+    LPWSTR wzPath = NULL;
+    WCHAR wzAppPoolName[MAX_PATH];
+    while (psvd)
+    {
+        if (WcaIsInstalling(psvd->isInstalled, psvd->isAction))
+        {
+            // First write all applications, this is necessary since vdirs must be nested under the applications.
+            if (psvd->fHasApplication)
+            {
+                //create the application for this vdir application
+                hr = ScaWriteConfigID(IIS_APPLICATION);
+                ExitOnFailure(hr, "Failed to write app ID");
+                hr = ScaWriteConfigID(IIS_CREATE);
+                ExitOnFailure(hr, "Failed to write app action");
+#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
+                hr = ScaWriteConfigString(psvd->wzWebName);           //site name key
+                ExitOnFailure(hr, "Failed to write app web key");
+                hr = StrAllocFormatted(&wzPath, L"/%s", psvd->wzVDirRoot);
+                ExitOnFailure(hr, "Failed to create app path");
+                hr = ScaWriteConfigString(wzPath);                    //  App Path
+                ExitOnFailure(hr, "Failed to write app path root ");
+
+                if (!*psvd->swapp.wzAppPool)
+                {
+                    //This Application goes in default appPool
+                    hr = ScaWriteConfigString(L"");                   //  App Pool
+                }
+                else
+                {
+                    //get apppool from WebApplication
+#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
+                    hr = ScaFindAppPool7(psvd->swapp.wzAppPool, wzAppPoolName, countof(wzAppPoolName), psapList);
+                    ExitOnFailure(hr, "Failed to read app pool from application");
+                    hr = ScaWriteConfigString(wzAppPoolName);           //  App Pool
+                    ExitOnFailure(hr, "Failed to write appPool for vdir");
+
+                }
+            }
+        }
+
+        psvd = psvd->psvdNext;
+    }
+
+    // Reset our linked list and write all the VDirs
+    psvd = psvdList;
+    while (psvd)
+    {
+        if (WcaIsInstalling(psvd->isInstalled, psvd->isAction))
+        {
+            //create the Vdir
+            hr = ScaWriteConfigID(IIS_VDIR);
+            ExitOnFailure(hr, "Failed write VirDir ID")
+            hr = ScaWriteConfigID(IIS_CREATE);
+            ExitOnFailure(hr, "Failed write VirDir action")
+#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
+            hr = ScaWriteConfigString(psvd->wzWebName);         //site name key
+            ExitOnFailure(hr, "Failed write VirDir web name");
+            hr = StrAllocFormatted(&wzPath, L"/%s", psvd->wzVDirRoot);
+            ExitOnFailure(hr, "Failed to create vdir path");
+            hr = ScaWriteConfigString(wzPath);                  //vdir path
+            ExitOnFailure(hr, "Failed write VirDir path")
+#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
+            hr = ScaWriteConfigString(psvd->wzDirectory);       //physical dir
+            ExitOnFailure(hr, "Failed write VirDir dir");
+
+            if (psvd->fHasProperties)
+            {
+                ScaWriteWebDirProperties7(psvd->wzWebName, psvd->wzVDirRoot, &psvd->swp);
+                ExitOnFailure(hr, "Failed to write directory properties for VirtualDir");
+            }
+
+            if (psvd->fHasApplication)
+            {
+                hr = ScaWriteWebApplication7(psvd->wzWebName, psvd->wzVDirRoot, &psvd->swapp, psapList);
+                ExitOnFailure(hr, "Failed to write application for VirtualDir");
+            }
+
+            if (psvd->psmm)
+            {
+                hr = ScaWriteMimeMap7(psvd->wzWebName, psvd->wzVDirRoot, psvd->psmm);
+                ExitOnFailure(hr, "Failed to write mimemap for VirtualDir");
+            }
+
+            if (psvd->pshh)
+            {
+                hr = ScaWriteHttpHeader7(psvd->wzWebName, psvd->wzVDirRoot, psvd->pshh);
+                ExitOnFailure(hr, "Failed to write custom HTTP headers for VirtualDir");
+            }
+
+            if (psvd->pswe)
+            {
+                hr = ScaWriteWebError7(psvd->wzWebName, psvd->wzVDirRoot, psvd->pswe);
+                ExitOnFailure(hr, "Failed to write custom web errors for VirtualDir");
+            }
+        }
+
+        psvd = psvd->psvdNext;
+    }
+
+LExit:
+    ReleaseStr(wzPath);
+    return hr;
+}
+
+
+HRESULT ScaVirtualDirsUninstall7(
+                                 __in SCA_VDIR7* psvdList
+                                 )
+{
+
+    HRESULT hr = S_OK;
+    SCA_VDIR7* psvd = psvdList;
+    LPWSTR wzPath = NULL;
+
+    while (psvd)
+    {
+        if (WcaIsUninstalling(psvd->isInstalled, psvd->isAction))
+        {
+            //init path
+            hr = StrAllocFormatted(&wzPath, L"/%s", psvd->wzVDirRoot);
+            ExitOnFailure(hr, "Failed to create vdir path");
+
+            if (psvd->fHasApplication)
+            {
+                //delete Application
+                hr = ScaWriteConfigID(IIS_APPLICATION);
+                ExitOnFailure(hr, "Failed to write app ID ");
+                hr = ScaWriteConfigID(IIS_DELETE);
+                ExitOnFailure(hr, "Failed to write delete app ID ");
+#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
+                hr = ScaWriteConfigString(psvd->wzWebName);        //site name key
+                ExitOnFailure(hr, "Failed to write App site Name");
+#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
+                hr = ScaWriteConfigString(wzPath);                 //  App Path
+                ExitOnFailure(hr, "Failed to write app path root ");
+                hr = ScaWriteConfigString(L"NOP");                 //  App pool
+                ExitOnFailure(hr, "Failed to write app path app pool ");
+            }
+            else
+            {
+                //delete VDir
+                hr = ScaWriteConfigID(IIS_VDIR);
+                ExitOnFailure(hr, "Failed to write vDir ID ");
+                hr = ScaWriteConfigID(IIS_DELETE);
+#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
+                hr = ScaWriteConfigString(psvd->wzWebName);        //site name key
+                ExitOnFailure(hr, "Failed to write App site Name");
+                hr = ScaWriteConfigString(wzPath);                 //  Vdir Path
+                ExitOnFailure(hr, "Failed to write app vdir ");
+                hr = ScaWriteConfigString(L"NOP");                 //  Phy Path
+                ExitOnFailure(hr, "Failed to write vdir path");
+            }
+
+            ExitOnFailure(hr, "Failed to remove VirtualDir '%ls' from config", psvd->wzKey);
+        }
+
+        psvd = psvd->psvdNext;
+    }
+
+LExit:
+    ReleaseStr(wzPath);
+    return hr;
+}
+
+
+void ScaVirtualDirsFreeList7(
+    __in SCA_VDIR7* psvdList
+    )
+{
+    SCA_VDIR7* psvdDelete = psvdList;
+    while (psvdList)
+    {
+        psvdDelete = psvdList;
+        psvdList = psvdList->psvdNext;
+
+        if (psvdDelete->psmm)
+        {
+            ScaMimeMapFreeList(psvdDelete->psmm);
+        }
+
+        if (psvdDelete->pswe)
+        {
+            ScaWebErrorFreeList(psvdDelete->pswe);
+        }
+
+        MemFree(psvdDelete);
+    }
+}
+
+
+static HRESULT AddVirtualDirToList7(
+    __in SCA_VDIR7** ppsvdList
+    )
+{
+    HRESULT hr = S_OK;
+
+    SCA_VDIR7* psvd = static_cast<SCA_VDIR7*>(MemAlloc(sizeof(SCA_VDIR7), TRUE));
+    ExitOnNull(psvd, hr, E_OUTOFMEMORY, "failed to allocate memory for new vdir list element");
+
+    psvd->psvdNext= *ppsvdList;
+    *ppsvdList = psvd;
+
+LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+#include "scawebprop.h"
+#include "scawebapp.h"
+#include "scamimemap.h"
+#include "scaapppool.h"
+
+struct SCA_VDIR7
+{
+    // darwin information
+    WCHAR wzKey[MAX_DARWIN_KEY + 1];
+    WCHAR wzComponent[MAX_DARWIN_KEY + 1];
+    INSTALLSTATE isInstalled;
+    INSTALLSTATE isAction;
+
+    // metabase information
+    WCHAR wzWebKey[MAX_DARWIN_KEY + 1];
+    WCHAR wzWebName[METADATA_MAX_NAME_LEN + 1];
+    WCHAR wzVDirRoot[METADATA_MAX_NAME_LEN + 1];
+
+    // iis configuation information
+    WCHAR wzDirectory[MAX_PATH];
+
+    BOOL fHasProperties;
+    SCA_WEB_PROPERTIES swp;
+
+    BOOL fHasApplication;
+    SCA_WEB_APPLICATION swapp;
+
+    SCA_MIMEMAP* psmm; // mime mappings
+    SCA_HTTP_HEADER* pshh; // custom web errors
+    SCA_WEB_ERROR* pswe; // custom web errors
+
+    SCA_VDIR7* psvdNext;
+};
+
+
+// prototypes
+HRESULT __stdcall ScaVirtualDirsRead7(
+    __in SCA_WEB7* pswList,
+    __in SCA_VDIR7** ppsvdList,
+    __in SCA_MIMEMAP** ppsmmList,
+    __in SCA_HTTP_HEADER** ppshhList,
+    __in SCA_WEB_ERROR** ppsweList,
+    __in WCA_WRAPQUERY_HANDLE hUserQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebBaseQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
+    __inout LPWSTR *ppwzCustomActionData
+    );
+
+HRESULT ScaVirtualDirsInstall7(
+    __in SCA_VDIR7* psvdList,
+    __in SCA_APPPOOL * psapList
+    );
+
+HRESULT ScaVirtualDirsUninstall7(
+    __in SCA_VDIR7* psvdList
+    );
+
+void ScaVirtualDirsFreeList7(
+    __in SCA_VDIR7* psvdList
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+//Adding this because delivery doesn't have the updated specstrings.h that windows build does
+#ifndef __in_xcount
+#define __in_xcount(size)
+#endif
+
+// sql queries
+
+enum eWebBaseQuery { wbqWeb = 1, wbqId, wbqIP, wbqPort, wbqHeader, wbqSecure, wbqDescription };
+
+
+// prototypes for private helper functions
+static SCA_WEB* NewWeb();
+static void FreeWeb(SCA_WEB *pswDelete);
+static SCA_WEB* AddWebToList(
+    __in SCA_WEB* pswList,
+    __in SCA_WEB* psw
+    );
+static HRESULT ScaWebFindBase(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_WEB* pswList,
+    __in_z LPCWSTR wzWeb,
+    __in int iSiteId,
+    __in_z LPCWSTR wzIP,
+    __in int iPort,
+    __in_z LPCWSTR wzHeader,
+    __in BOOL fSecure,
+    __in_z LPCWSTR wzDescription,
+    __out_ecount(cchWebBase) LPWSTR wzWebBase,
+    __in DWORD cchWebBase
+    );
+static HRESULT ScaWebFindFreeBase(
+    __in IMSAdminBase* piMetabase,
+    __in_xcount(unknown) SCA_WEB* pswList,
+    __in int iSiteId,
+    __in_z LPCWSTR wzDescription,
+    __out_ecount(cchWebBase) LPWSTR wzWebBase,
+    __in DWORD cchWebBase
+    );
+static HRESULT ScaWebWrite(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_WEB* psw,
+    __in SCA_APPPOOL * psapList
+    );
+static HRESULT ScaWebRemove(
+    __in IMSAdminBase* piMetabase,
+    __in const SCA_WEB* psw);
+static DWORD SiteIdFromDescription(
+    __in_z LPCWSTR wzDescription
+    );
+static void Sort(
+    __in_ecount(cArray) DWORD dwArray[],
+    __in int cArray
+    );
+
+
+HRESULT ScaWebsRead(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_MIMEMAP** ppsmmList,
+    __in SCA_WEB** ppswList,
+    __in SCA_HTTP_HEADER** ppshhList,
+    __in SCA_WEB_ERROR** ppsweList,
+    __in WCA_WRAPQUERY_HANDLE hUserQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
+    __in WCA_WRAPQUERY_HANDLE hSslCertQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebLogQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
+    __inout LPWSTR *ppwzCustomActionData
+    )
+{
+    Assert(piMetabase && ppswList);
+
+    HRESULT hr = S_OK;
+
+    MSIHANDLE hRec;
+    MSIHANDLE hRecAddresses;
+
+    SCA_WEB* psw = NULL;
+    LPWSTR pwzData = NULL;
+    int iSiteId;
+
+    DWORD dwLen = 0;
+    WCA_WRAPQUERY_HANDLE hQueryWebSite = NULL;
+    WCA_WRAPQUERY_HANDLE hQueryWebAddress = NULL;
+
+    hr = WcaBeginUnwrapQuery(&hQueryWebSite, ppwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap query for ScaWebsRead");
+
+    hr = WcaBeginUnwrapQuery(&hQueryWebAddress, ppwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap query for ScaWebsRead");
+
+    if (0 == WcaGetQueryRecords(hQueryWebSite))
+    {
+        WcaLog(LOGMSG_VERBOSE, "Required tables not present");
+        ExitFunction1(hr = S_FALSE);
+    }
+
+    // loop through all the webs
+    while (S_OK == (hr = WcaFetchWrappedRecord(hQueryWebSite, &hRec)))
+    {
+        psw = NewWeb();
+        ExitOnNull(psw, hr, E_OUTOFMEMORY, "Failed to allocate memory for web object in memory");
+
+        // get the darwin information
+        hr = WcaGetRecordString(hRec, wqWeb, &pwzData);
+        ExitOnFailure(hr, "Failed to get Web");
+        hr = ::StringCchCopyW(psw->wzKey, countof(psw->wzKey), pwzData);
+        ExitOnFailure(hr, "Failed to copy key string to web object");
+
+        if (*pwzData && *ppsmmList)
+        {
+            hr = ScaGetMimeMap(mmptWeb, pwzData, ppsmmList, &psw->psmm);
+            ExitOnFailure(hr, "Failed to get mimemap for VirtualDir");
+        }
+
+        // get component install state
+        hr = WcaGetRecordString(hRec, wqComponent, &pwzData);
+        ExitOnFailure(hr, "Failed to get Component for Web");
+        hr = ::StringCchCopyW(psw->wzComponent, countof(psw->wzComponent), pwzData);
+        ExitOnFailure(hr, "Failed to copy component string to web object");
+        if (*(psw->wzComponent))
+        {
+            psw->fHasComponent = TRUE;
+
+            hr = WcaGetRecordInteger(hRec, wqInstalled, (int *)&psw->isInstalled);
+            ExitOnFailure(hr, "Failed to get web Component's installed state");
+
+            WcaGetRecordInteger(hRec, wqAction, (int *)&psw->isAction);
+            ExitOnFailure(hr, "Failed to get web Component's action state");
+
+            if (!WcaIsInstalling(psw->isInstalled, psw->isAction) && !WcaIsUninstalling(psw->isInstalled, psw->isAction)
+                && !WcaIsReInstalling(psw->isInstalled, psw->isAction))
+            {
+                FreeWeb(psw);
+                psw = NULL;
+
+                continue; // If we aren't acting on this component, skip it
+            }
+        }
+
+        hr = WcaGetRecordInteger(hRec, wqId, &iSiteId);
+        ExitOnFailure(hr, "Failed to get SiteId for Web");
+
+        // Get the web's key address.
+        hr = WcaGetRecordString(hRec, wqAddress, &pwzData);
+        ExitOnFailure(hr, "Failed to get Address for Web");
+        hr = ::StringCchCopyW(psw->swaKey.wzKey, countof(psw->swaKey.wzKey), pwzData);
+        ExitOnFailure(hr, "Failed to copy key string to web object");
+
+        hr = WcaGetRecordString(hRec, wqIP, &pwzData);
+        ExitOnFailure(hr, "Failed to get IP for Web");
+        hr = ::StringCchCopyW(psw->swaKey.wzIP, countof(psw->swaKey.wzIP), pwzData);
+        ExitOnFailure(hr, "Failed to copy IP string to web object");
+
+        hr = WcaGetRecordString(hRec, wqPort, &pwzData);
+        ExitOnFailure(hr, "Failed to get Web Address port");
+        psw->swaKey.iPort = wcstol(pwzData, NULL, 10);
+
+        hr = WcaGetRecordString(hRec, wqHeader, &pwzData);
+        ExitOnFailure(hr, "Failed to get Header for Web");
+        hr = ::StringCchCopyW(psw->swaKey.wzHeader, countof(psw->swaKey.wzHeader), pwzData);
+        ExitOnFailure(hr, "Failed to copy header string to web object");
+
+        hr = WcaGetRecordInteger(hRec, wqSecure, &psw->swaKey.fSecure);
+        ExitOnFailure(hr, "Failed to get if Web is secure");
+        if (S_FALSE == hr)
+        {
+            psw->swaKey.fSecure = FALSE;
+        }
+
+        // Get the web's description.
+        hr = WcaGetRecordString(hRec, wqDescription, &pwzData);
+        ExitOnFailure(hr, "Failed to get Description for Web");
+        hr = ::StringCchCopyW(psw->wzDescription, countof(psw->wzDescription), pwzData);
+        ExitOnFailure(hr, "Failed to copy description string to web object");
+
+        // Try to find the web root in case it already exists.
+        dwLen = METADATA_MAX_NAME_LEN;
+        hr = ScaWebFindBase(piMetabase, *ppswList,
+                            psw->wzKey,
+                            iSiteId,
+                            psw->swaKey.wzIP,
+                            psw->swaKey.iPort,
+                            psw->swaKey.wzHeader,
+                            psw->swaKey.fSecure,
+                            psw->wzDescription,
+                            psw->wzWebBase, dwLen);
+        if (S_OK == hr)
+        {
+            psw->fBaseExists = TRUE;
+        }
+        else if (S_FALSE == hr) // didn't find the web site.
+        {
+            psw->fBaseExists = FALSE;
+
+            // If we're actually configuring the web site.
+            if (psw->fHasComponent)
+            {
+                if (WcaIsInstalling(psw->isInstalled, psw->isAction))
+                {
+                    hr = ScaWebFindFreeBase(piMetabase, *ppswList, iSiteId, psw->wzDescription, psw->wzWebBase, countof(psw->wzWebBase));
+                    ExitOnFailure(hr, "Failed to find free web root.");
+                }
+                else if (WcaIsUninstalling(psw->isInstalled, psw->isAction))
+                {
+                    WcaLog(LOGMSG_VERBOSE, "Web site: '%ls' was already removed, skipping.", psw->wzKey);
+
+                    hr = S_OK;
+                    continue;
+                }
+            }
+        }
+        ExitOnFailure(hr, "Failed to find web root");
+
+        // get any extra web addresses
+        WcaFetchWrappedReset(hQueryWebAddress);
+        while (S_OK == (hr = WcaFetchWrappedRecordWhereString(hQueryWebAddress, 2, psw->wzKey, &hRecAddresses)))
+        {
+            if (MAX_ADDRESSES_PER_WEB <= psw->cExtraAddresses)
+            {
+                hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+                ExitOnFailure(hr, "Failure to get more extra web addresses, max exceeded.");
+            }
+
+            hr = WcaGetRecordString(hRecAddresses, waqAddress, &pwzData);
+            ExitOnFailure(hr, "Failed to get extra web Address");
+
+            // if this isn't the key address add it
+            if (0 != lstrcmpW(pwzData, psw->swaKey.wzKey))
+            {
+                hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey), pwzData);
+                ExitOnFailure(hr, "Failed to copy extra addresses key string to web object");
+
+                hr = WcaGetRecordString(hRecAddresses, waqIP, &pwzData);
+                ExitOnFailure(hr, "Failed to get extra web IP");
+                hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP), pwzData);
+                ExitOnFailure(hr, "Failed to copy extra addresses IP string to web object");
+
+                hr = WcaGetRecordString(hRecAddresses, waqPort, &pwzData);
+                ExitOnFailure(hr, "Failed to get port for extra web IP");
+                psw->swaExtraAddresses[psw->cExtraAddresses].iPort= wcstol(pwzData, NULL, 10);
+
+                hr = WcaGetRecordString(hRecAddresses, waqHeader, &pwzData);
+                ExitOnFailure(hr, "Failed to get header for extra web IP");
+                hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader), pwzData);
+                ExitOnFailure(hr, "Failed to copy extra addresses header string to web object");
+
+                hr = WcaGetRecordInteger(hRecAddresses, waqSecure, &psw->swaExtraAddresses[psw->cExtraAddresses].fSecure);
+                ExitOnFailure(hr, "Failed to get if secure extra web IP");
+                if (S_FALSE == hr)
+                    psw->swaExtraAddresses[psw->cExtraAddresses].fSecure = FALSE;
+
+                ++psw->cExtraAddresses;
+            }
+        }
+
+        if (E_NOMOREITEMS == hr)
+            hr = S_OK;
+        ExitOnFailure(hr, "Failure occured while getting extra web addresses");
+
+        hr = WcaGetRecordInteger(hRec, wqConnectionTimeout, &psw->iConnectionTimeout);
+        ExitOnFailure(hr, "Failed to get connection timeout for Web");
+
+        if (psw->fHasComponent) // If we're installing it, it needs a dir
+        {
+            // get the web's directory
+            if (INSTALLSTATE_SOURCE == psw->isAction)
+            {
+                hr = WcaGetRecordString(hRec, wqSourcePath, &pwzData);
+            }
+            else
+            {
+                hr = WcaGetRecordString(hRec, wqTargetPath, &pwzData);
+            }
+            ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory");
+
+            // remove trailing backslashes
+            while (lstrlenW(pwzData) > 0 && pwzData[lstrlenW(pwzData)-1] == L'\\')
+            {
+                pwzData[lstrlenW(pwzData)-1] = 0;
+            }
+            hr = ::StringCchCopyW(psw->wzDirectory, countof(psw->wzDirectory), pwzData);
+            ExitOnFailure(hr, "Failed to copy directory string to web object");
+        }
+
+        hr = WcaGetRecordInteger(hRec, wqState, &psw->iState);
+        ExitOnFailure(hr, "Failed to get state for Web");
+
+        hr = WcaGetRecordInteger(hRec, wqAttributes, &psw->iAttributes);
+        ExitOnFailure(hr, "Failed to get attributes for Web");
+
+        // get the dir properties for this web
+        hr = WcaGetRecordString(hRec, wqProperties, &pwzData);
+        ExitOnFailure(hr, "Failed to get directory property record for Web");
+        if (*pwzData)
+        {
+            hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &psw->swp);
+            ExitOnFailure(hr, "Failed to get directory properties for Web");
+
+            psw->fHasProperties = TRUE;
+        }
+
+        // get the application information for this web
+        hr = WcaGetRecordString(hRec, wqApplication, &pwzData);
+        ExitOnFailure(hr, "Failed to get application identifier for Web");
+        if (*pwzData)
+        {
+            hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &psw->swapp);
+            ExitOnFailure(hr, "Failed to get application for Web");
+
+            psw->fHasApplication = TRUE;
+        }
+
+        // get the SSL certificates
+        hr = ScaSslCertificateRead(psw->wzKey, hSslCertQuery, &(psw->pswscList));
+        ExitOnFailure(hr, "Failed to get SSL Certificates.");
+
+        // get the custom headers
+        if (*ppshhList)
+        {
+            hr = ScaGetHttpHeader(hhptWeb, psw->wzKey, ppshhList, &(psw->pshhList));
+            ExitOnFailure(hr, "Failed to get Custom HTTP Headers");
+        }
+
+        // get the errors
+        if (*ppsweList)
+        {
+            hr = ScaGetWebError(weptWeb, psw->wzKey, ppsweList, &(psw->psweList));
+            ExitOnFailure(hr, "Failed to get Custom Errors");
+        }
+
+        // get the log information for this web
+        hr = WcaGetRecordString(hRec, wqLog, &pwzData);
+        ExitOnFailure(hr, "Failed to get log identifier for Web");
+        if (*pwzData)
+        {
+            hr = ScaGetWebLog(piMetabase, pwzData, hWebLogQuery, &psw->swl);
+            ExitOnFailure(hr, "Failed to get Log for Web.");
+
+            psw->fHasLog = TRUE;
+        }
+
+        *ppswList = AddWebToList(*ppswList, psw);
+        psw = NULL; // set the web NULL so it doesn't accidentally get freed below
+    }
+
+    if (E_NOMOREITEMS == hr)
+    {
+        hr = S_OK;
+    }
+
+LExit:
+    // if anything was left over after an error clean it all up
+    WcaFinishUnwrapQuery(hQueryWebSite);
+    WcaFinishUnwrapQuery(hQueryWebAddress);
+
+    if (psw)
+    {
+        ScaWebsFreeList(psw);
+    }
+
+    ReleaseStr(pwzData);
+
+    return hr;
+}
+
+
+HRESULT ScaWebsGetBase(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_WEB* pswList,
+    __in LPCWSTR wzWeb,
+    __out_ecount(cchWebBase) LPWSTR wzWebBase,
+    __in DWORD cchWebBase,
+    __in WCA_WRAPQUERY_HANDLE hWrapQuery
+    )
+{
+    HRESULT hr = S_OK;
+    MSIHANDLE hRec;
+
+    int iSiteId;
+    WCHAR wzIP[MAX_PATH];
+    int iPort = -1;
+    WCHAR wzHeader[MAX_PATH];
+    BOOL fSecure = FALSE;
+
+    LPWSTR pwzData = NULL;
+
+    // get the web information
+    WcaFetchWrappedReset(hWrapQuery);
+
+    hr = WcaFetchWrappedRecordWhereString(hWrapQuery, 1, wzWeb, &hRec);
+    if (S_OK == hr)
+    {
+        // get the data to search for
+        hr = WcaGetRecordInteger(hRec, wbqId, &iSiteId);
+        ExitOnFailure(hr, "Failed to get SiteId for Web for VirtualDir");
+
+        hr = WcaGetRecordString(hRec, wbqIP, &pwzData);
+        ExitOnFailure(hr, "Failed to get IP for Web for VirtualDir");
+        hr = ::StringCchCopyW(wzIP, countof(wzIP), pwzData);
+        ExitOnFailure(hr, "Failed to copy IP for Web for VirtualDir");
+
+        hr = WcaGetRecordString(hRec, wbqPort, &pwzData);
+        ExitOnFailure(hr, "Failed to get port for extra web IP");
+        iPort = wcstol(pwzData, NULL, 10);
+
+        hr = WcaGetRecordString(hRec, wbqHeader, &pwzData);
+        ExitOnFailure(hr, "Failed to get Header for Web for VirtualDir");
+        hr = ::StringCchCopyW(wzHeader, countof(wzHeader), pwzData);
+        ExitOnFailure(hr, "Failed to copy Header for Web for VirtualDir");
+
+        hr = WcaGetRecordInteger(hRec, wbqSecure, &fSecure);
+        if (S_FALSE == hr)
+            fSecure = FALSE;
+
+        hr = WcaGetRecordString(hRec, wbqDescription, &pwzData);
+        ExitOnFailure(hr, "Failed to get Description for Web");
+
+        // find the web or find the next free web location
+        hr = ScaWebFindBase(piMetabase, pswList, wzWeb, iSiteId, wzIP, iPort, wzHeader, fSecure, pwzData, wzWebBase, cchWebBase);
+        if (S_FALSE == hr)
+            hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+        ExitOnFailure(hr, "Failed to find Web base");
+    }
+    else if (S_FALSE == hr)
+        hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
+
+    // Let's check that there isn't more than one record found - if there is, throw an assert like WcaFetchSingleRecord() would
+    HRESULT hrTemp = WcaFetchWrappedRecordWhereString(hWrapQuery, 1, wzWeb, &hRec);
+    if (SUCCEEDED(hrTemp))
+    {
+        AssertSz(E_NOMOREITEMS == hrTemp, "ScaWebsGetBase found more than one record");
+    }
+
+LExit:
+    ReleaseStr(pwzData);
+
+    return hr;
+}
+
+
+HRESULT ScaWebsInstall(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_WEB* pswList,
+    __in SCA_APPPOOL * psapList
+    )
+{
+    HRESULT hr = S_OK;
+    SCA_WEB* psw = pswList;
+
+    while (psw)
+    {
+        // if we are installing the web site
+        if (psw->fHasComponent && WcaIsInstalling(psw->isInstalled, psw->isAction))
+        {
+            hr = ScaWebWrite(piMetabase, psw, psapList);
+            ExitOnFailure(hr, "failed to write web '%ls' to metabase", psw->wzKey);
+        }
+
+        psw = psw->pswNext;
+    }
+
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaWebsUninstall(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_WEB* pswList
+    )
+{
+    HRESULT hr = S_OK;
+    SCA_WEB* psw = pswList;
+
+    while (psw)
+    {
+        // if we are uninstalling the web site
+        if (psw->fHasComponent && WcaIsUninstalling(psw->isInstalled, psw->isAction))
+        {
+            hr = ScaWebRemove(piMetabase, psw);
+            ExitOnFailure(hr, "Failed to remove web '%ls' from metabase", psw->wzKey);
+        }
+
+        psw = psw->pswNext;
+    }
+
+LExit:
+    return hr;
+}
+
+
+void ScaWebsFreeList(
+    __in SCA_WEB* pswList
+    )
+{
+    SCA_WEB* pswDelete = pswList;
+    while (pswList)
+    {
+        pswDelete = pswList;
+        pswList = pswList->pswNext;
+
+        // Free the SSL, headers and errors list first
+        FreeWeb(pswDelete);
+    }
+}
+
+
+// private helper functions
+
+static void FreeWeb(SCA_WEB *pswDelete)
+{
+    ScaSslCertificateFreeList(pswDelete->pswscList);
+    ScaHttpHeaderFreeList(pswDelete->pshhList);
+    ScaWebErrorFreeList(pswDelete->psweList);
+    MemFree(pswDelete);
+}
+
+static SCA_WEB* NewWeb()
+{
+    SCA_WEB* psw = static_cast<SCA_WEB*>(MemAlloc(sizeof(SCA_WEB), TRUE));
+    Assert(psw);
+    return psw;
+}
+
+
+static SCA_WEB* AddWebToList(
+    __in SCA_WEB* pswList,
+    __in SCA_WEB* psw
+    )
+{
+    if (pswList)
+    {
+        SCA_WEB* pswTemp = pswList;
+        while (pswTemp->pswNext)
+        {
+            pswTemp = pswTemp->pswNext;
+        }
+
+        pswTemp->pswNext = psw;
+    }
+    else
+    {
+        pswList = psw;
+    }
+
+    return pswList;
+}
+
+
+static HRESULT ScaWebFindBase(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_WEB* pswList,
+    __in_z LPCWSTR wzWeb,
+    __in int iSiteId,
+    __in_z LPCWSTR wzIP,
+    __in int iPort,
+    __in_z LPCWSTR wzHeader,
+    __in BOOL fSecure,
+    __in_z LPCWSTR wzDescription,
+    __out_ecount(cchWebBase) LPWSTR wzWebBase,
+    __in DWORD cchWebBase
+    )
+{
+    Assert(piMetabase);
+
+    HRESULT hr = S_OK;
+
+    WCHAR wzKey[METADATA_MAX_NAME_LEN];
+    WCHAR wzSubkey[METADATA_MAX_NAME_LEN];
+    LPWSTR wzFoundKey = NULL;
+
+    METADATA_RECORD mr;
+    ::ZeroMemory(&mr, sizeof(mr));
+
+    METADATA_RECORD mrCompare;
+    ::ZeroMemory(&mrCompare, sizeof(mrCompare));
+
+    // try to find the web in memory first
+    for (SCA_WEB* psw = pswList; psw; psw = psw->pswNext)
+    {
+        if (0 == lstrcmpW(wzWeb, psw->wzKey))
+        {
+            if ((0 == lstrcmpW(wzIP, psw->swaKey.wzIP) || 0 == lstrcmpW(wzIP, L"*") || 0 == lstrcmpW(psw->swaKey.wzIP, L"*")) &&
+                iPort == psw->swaKey.iPort &&
+                0 == lstrcmpW(wzHeader, psw->swaKey.wzHeader) &&
+                fSecure == psw->swaKey.fSecure)
+            {
+                if (0 == lstrlenW(psw->wzWebBase))
+                {
+                    WcaLog(LOGMSG_STANDARD, "A matching web object in memory was found, but the web object in memory has no associated base");
+                    ExitFunction1(hr = S_FALSE);
+                }
+
+                hr = ::StringCchCopyW(wzKey, countof(wzKey), psw->wzWebBase);
+                ExitOnFailure(hr, "Failed to copy web base into key.");
+
+                wzFoundKey = wzKey;
+                break;
+            }
+            else
+            {
+                WcaLog(LOGMSG_STANDARD, "Found web `%ls` but data did not match.", wzWeb);
+                hr = E_UNEXPECTED;
+                break;
+            }
+        }
+    }
+    ExitOnFailure(hr, "Failure occured while searching for web in memory");
+
+    // If we didn't find a web in memory matching look in the metabase.
+    if (!wzFoundKey)
+    {
+        mr.dwMDIdentifier = MD_KEY_TYPE;
+        mr.dwMDAttributes = METADATA_INHERIT;
+        mr.dwMDUserType = IIS_MD_UT_SERVER;
+        mr.dwMDDataType = ALL_METADATA;
+        mr.dwMDDataLen = 0;
+        mr.pbMDData = NULL;
+
+        // If we're looking based on the old WebAddress detection (NULL) or the new
+        // Web description detection (-1)
+        if (MSI_NULL_INTEGER == iSiteId || -1 == iSiteId)
+        {
+            if (MSI_NULL_INTEGER == iSiteId)
+            {
+                mrCompare.dwMDIdentifier = (fSecure) ? MD_SECURE_BINDINGS : MD_SERVER_BINDINGS;
+            }
+            else
+            {
+                mrCompare.dwMDIdentifier = MD_SERVER_COMMENT;
+            }
+            mrCompare.dwMDAttributes = METADATA_INHERIT;
+            mrCompare.dwMDUserType = IIS_MD_UT_SERVER;
+            mrCompare.dwMDDataType = ALL_METADATA;
+            mrCompare.dwMDDataLen = 0;
+            mrCompare.pbMDData = NULL;
+
+            // Loop through the "web keys" looking for the "IIsWebServer" key that matches our search criteria.
+            for (DWORD dwIndex = 0; SUCCEEDED(hr); ++dwIndex)
+            {
+                hr = piMetabase->EnumKeys(METADATA_MASTER_ROOT_HANDLE, L"/LM/W3SVC", wzSubkey, dwIndex);
+                if (SUCCEEDED(hr))
+                {
+                    hr = ::StringCchPrintfW(wzKey, countof(wzKey), L"/LM/W3SVC/%s", wzSubkey);
+                    ExitOnFailure(hr, "Failed to copy web subkey.");
+
+                    hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzKey, &mr);
+                    if (MD_ERROR_DATA_NOT_FOUND == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
+                    {
+                        hr = S_FALSE;  // didn't find anything, try next one
+                        continue;
+                    }
+                    ExitOnFailure(hr, "Failed to get key from metabase while searching for web servers");
+
+                    // If we have an IIsWebServer check to see if this is the site we are searching for.
+                    if (0 == lstrcmpW(L"IIsWebServer", (LPCWSTR)mr.pbMDData))
+                    {
+                        hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzKey, &mrCompare);
+                        if (MD_ERROR_DATA_NOT_FOUND == hr || NULL == mrCompare.pbMDData)
+                        {
+                            hr = S_FALSE;
+                            continue;
+                        }
+                        ExitOnFailure(hr, "Failed to get address/description from metabase while searching for web servers");
+
+                        LPWSTR pwzExists = (LPWSTR)mrCompare.pbMDData;
+                        if (MSI_NULL_INTEGER == iSiteId)
+                        {
+                            // Break down the address into its constituent parts (IP:Port:Header).
+                            while (S_OK == hr && *pwzExists)
+                            {
+                                LPCWSTR pwzIPExists = pwzExists;
+                                pwzExists = const_cast<LPWSTR>(wcsstr(pwzIPExists, L":"));
+                                ExitOnNull(pwzExists, hr, E_INVALIDARG, "Invalid web address. IP was not separated by a colon.");
+                                *pwzExists = L'\0';
+
+                                LPCWSTR pwzPortExists = pwzExists + 1;
+                                pwzExists = const_cast<LPWSTR>(wcsstr(pwzPortExists, L":"));
+                                ExitOnNull(pwzExists, hr, E_INVALIDARG, "Invalid web address. Port was not separated by a colon.");
+                                *pwzExists = L'\0';
+                                int iPortExists = wcstol(pwzPortExists, NULL, 10);
+
+                                LPCWSTR pwzHeaderExists = pwzExists + 1;
+
+                                // compare the passed in address with the address listed for this web
+                                if ((0 == lstrcmpW(wzIP, pwzIPExists) || 0 == lstrcmpW(wzIP, L"*")) &&
+                                    iPort == iPortExists &&
+                                    0 == lstrcmpW(wzHeader, pwzHeaderExists))
+                                {
+                                    wzFoundKey = wzKey;
+                                    break;
+                                }
+
+                                // move to the next block of data, this may move beyond the available
+                                // data and exit the while loop above.
+                                pwzExists = const_cast<LPWSTR>(pwzHeaderExists + lstrlenW(pwzHeaderExists) + 1);
+                            }
+                        }
+                        else
+                        {
+                            if (0 == lstrcmpW(wzDescription, pwzExists))
+                            {
+                                wzFoundKey = wzKey;
+                            }
+                        }
+
+                        // If we found the key we were looking for, no point in continuing to search.
+                        if (wzFoundKey)
+                        {
+                            break;
+                        }
+                    }
+                }
+            }
+
+            if (E_NOMOREITEMS == hr)
+            {
+                Assert(!wzFoundKey);
+                hr = S_FALSE;
+            }
+        }
+        else // we're looking a specific SiteId
+        {
+            hr = ::StringCchPrintfW(wzKey, countof(wzKey), L"/LM/W3SVC/%d", iSiteId);
+            ExitOnFailure(hr, "Failed to allocate metabase key string.");
+
+            // if we have an IIsWebServer store the key
+            hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzKey, &mr);
+
+            if (SUCCEEDED(hr) && NULL != mr.pbMDData && 0 == lstrcmpW(L"IIsWebServer", (LPCWSTR)mr.pbMDData))
+            {
+                wzFoundKey = wzKey;
+            }
+            else if (MD_ERROR_DATA_NOT_FOUND == hr || NULL == mrCompare.pbMDData || NULL == mr.pbMDData)
+            {
+                hr = S_FALSE;
+            }
+        }
+    }
+
+    if (wzFoundKey)
+    {
+        Assert(S_OK == hr);
+
+        hr = ::StringCchCopyW(wzWebBase, cchWebBase, wzFoundKey);
+        ExitOnFailure(hr, "Buffer not larger enough for found base key.");
+    }
+
+LExit:
+    MetaFreeValue(&mr);
+    MetaFreeValue(&mrCompare);
+
+    if (!wzFoundKey && SUCCEEDED(hr))
+    {
+        hr = S_FALSE;
+    }
+
+    return hr;
+}
+
+
+static HRESULT ScaWebFindFreeBase(
+    __in IMSAdminBase* piMetabase,
+    __in_xcount(unknown) SCA_WEB* pswList,
+    __in int iSiteId,
+    __in_z LPCWSTR wzDescription,
+    __out_ecount(cchWebBase) LPWSTR wzWebBase,
+    __in DWORD cchWebBase
+    )
+{
+    Assert(piMetabase);
+
+    HRESULT hr = S_OK;
+
+    WCHAR wzKey[METADATA_MAX_NAME_LEN];
+    WCHAR wzSubkey[METADATA_MAX_NAME_LEN];
+    DWORD* prgdwSubKeys = NULL;
+    DWORD cSubKeys = 128;
+    DWORD cSubKeysFilled = 0;
+
+    DWORD dwKey;
+
+    METADATA_RECORD mr;
+    ::ZeroMemory(&mr, sizeof(METADATA_RECORD));
+    mr.dwMDIdentifier = MD_KEY_TYPE;
+    mr.dwMDAttributes = 0;
+    mr.dwMDUserType = IIS_MD_UT_SERVER;
+    mr.dwMDDataType = STRING_METADATA;
+    mr.dwMDDataLen = 0;
+    mr.pbMDData = NULL;
+
+    if (MSI_NULL_INTEGER == iSiteId || -1 == iSiteId)
+    {
+        prgdwSubKeys = static_cast<DWORD*>(MemAlloc(cSubKeys * sizeof(DWORD), TRUE));
+        ExitOnNull(prgdwSubKeys, hr, E_OUTOFMEMORY, "failed to allocate space for web site keys");
+
+        // loop through the "web keys" looking for the "IIsWebServer" key that matches wzWeb
+        for (DWORD dwIndex = 0; SUCCEEDED(hr); ++dwIndex)
+        {
+            hr = piMetabase->EnumKeys(METADATA_MASTER_ROOT_HANDLE, L"/LM/W3SVC", wzSubkey, dwIndex);
+            if (SUCCEEDED(hr))
+            {
+                hr = ::StringCchPrintfW(wzKey, countof(wzKey), L"/LM/W3SVC/%s", wzSubkey);
+                ExitOnFailure(hr, "Failed remember key.");
+
+                hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzKey, &mr);
+                if (MD_ERROR_DATA_NOT_FOUND == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
+                {
+                    hr = S_FALSE;  // didn't find anything, try next one
+                    continue;
+                }
+                ExitOnFailure(hr, "Failed to get key from metabase while searching for free web root");
+
+                // if we have a IIsWebServer get the address information
+                if (0 == lstrcmpW(L"IIsWebServer", (LPCWSTR)mr.pbMDData))
+                {
+                    if (cSubKeysFilled >= cSubKeys)
+                    {
+                        cSubKeys = cSubKeys * 2;
+                        prgdwSubKeys = static_cast<DWORD*>(MemReAlloc(prgdwSubKeys, cSubKeys * sizeof(DWORD), FALSE));
+                        ExitOnNull(prgdwSubKeys, hr, E_OUTOFMEMORY, "failed to allocate space for web site keys");
+                    }
+
+                    prgdwSubKeys[cSubKeysFilled] = wcstol(wzSubkey, NULL, 10);
+                    ++cSubKeysFilled;
+                    Sort(prgdwSubKeys, cSubKeysFilled);
+                }
+            }
+        }
+
+        if (E_NOMOREITEMS == hr)
+        {
+            hr = S_OK;
+        }
+        ExitOnFailure(hr, "Failed to find free web root");
+
+        // Add all the webs created in memory.
+        CONST WCHAR *pcchSlash;
+        for (SCA_WEB* psw = pswList; psw; psw = psw->pswNext)
+        {
+            // Don't process webs that don't have a base
+            if (!*psw->wzWebBase)
+            {
+                continue;
+            }
+
+            // find the last slash in the web root because the root # is after it
+            pcchSlash = NULL;
+            for (CONST WCHAR *pcch = psw->wzWebBase; pcch && *pcch; ++pcch)
+            {
+                if (L'/' == *pcch)
+                {
+                    pcchSlash = pcch;
+                }
+            }
+            // In case we don't find a slash, error out
+            ExitOnNull(pcchSlash, hr, E_INVALIDARG, "Failed to find a slash in the web root: %ls", psw->wzWebBase);
+
+            prgdwSubKeys[cSubKeysFilled] = wcstol(pcchSlash + 1, NULL, 10);
+            ++cSubKeysFilled;
+            Sort(prgdwSubKeys, cSubKeysFilled);
+
+            if (cSubKeysFilled >= cSubKeys)
+            {
+                cSubKeys = cSubKeys * 2;
+                prgdwSubKeys = static_cast<DWORD*>(MemReAlloc(prgdwSubKeys, cSubKeys * sizeof(DWORD), FALSE));
+                ExitOnNull(prgdwSubKeys, hr, E_OUTOFMEMORY, "failed to allocate space for web site keys");
+            }
+        }
+
+        // Find the lowest free web root.
+        dwKey = (-1 == iSiteId) ? SiteIdFromDescription(wzDescription) : 1;
+        for (DWORD i = 0; i < cSubKeysFilled; ++i)
+        {
+            if (dwKey == prgdwSubKeys[i])
+            {
+                ++dwKey;
+            }
+            else if (dwKey < prgdwSubKeys[i])
+            {
+                break;
+            }
+        }
+    }
+    else
+    {
+        dwKey = iSiteId;
+    }
+
+    hr = ::StringCchPrintfW(wzWebBase, cchWebBase, L"/LM/W3SVC/%u", dwKey);
+    ExitOnFailure(hr, "failed to format web base with key: %u", dwKey);
+
+LExit:
+    MetaFreeValue(&mr);
+
+    if (prgdwSubKeys)
+    {
+        MemFree(prgdwSubKeys);
+    }
+
+    return hr;
+}
+
+
+static HRESULT ScaWebWrite(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_WEB* psw,
+    __in SCA_APPPOOL * psapList)
+{
+    HRESULT hr = S_OK;
+
+    UINT ui = 0;
+    WCHAR wzIP[64];
+    WCHAR wzBindings[1024];
+    WCHAR wzSecureBindings[1024];
+    WCHAR* pcchNext;        // used to properly create the MULTI_SZ
+    DWORD cchPcchNext;
+    WCHAR* pcchSecureNext ; // used to properly create the MULTI_SZ
+    DWORD cchPcchSecureNext;
+
+    // if the web root doesn't exist create it
+    if (!psw->fBaseExists)
+    {
+        hr = ScaCreateWeb(piMetabase, psw->wzKey, psw->wzWebBase);
+        ExitOnFailure(hr, "Failed to create web");
+    }
+    else if (psw->iAttributes & SWATTRIB_NOCONFIGUREIFEXISTS) // if we're not supposed to configure existing webs, bail
+    {
+        Assert(psw->fBaseExists);
+
+        hr = S_FALSE;
+        WcaLog(LOGMSG_VERBOSE, "Skipping configuration of existing web: %ls", psw->wzKey);
+        ExitFunction();
+    }
+
+    // put the secure and non-secure bindings together as MULTI_SZs
+    ::ZeroMemory(wzBindings, sizeof(wzBindings));
+    pcchNext = wzBindings;
+    cchPcchNext = countof(wzBindings);
+    ::ZeroMemory(wzSecureBindings, sizeof(wzSecureBindings));
+    pcchSecureNext = wzSecureBindings;
+    cchPcchSecureNext = countof(wzSecureBindings);
+
+    // set the IP address appropriately
+    if (0 == lstrcmpW(psw->swaKey.wzIP, L"*"))
+    {
+        ::ZeroMemory(wzIP, sizeof(wzIP));
+    }
+    else
+    {
+        hr = ::StringCchCopyW(wzIP, countof(wzIP), psw->swaKey.wzIP);
+        ExitOnFailure(hr, "Failed to copy IP string");
+    }
+
+    WCHAR wzBinding[256];
+    hr = ::StringCchPrintfW(wzBinding, countof(wzBinding), L"%s:%d:%s", wzIP, psw->swaKey.iPort, psw->swaKey.wzHeader);
+    ExitOnFailure(hr, "Failed to format IP:Port:Header binding string");
+    if (psw->swaKey.fSecure)
+    {
+        hr = ::StringCchCopyW(pcchSecureNext, cchPcchSecureNext, wzBinding);
+        ExitOnFailure(hr, "Failed to copy binding string to securenext string");
+        pcchSecureNext += lstrlenW(wzBinding) + 1;
+        cchPcchSecureNext -= lstrlenW(wzBinding) + 1;
+    }
+    else
+    {
+        hr = ::StringCchCopyW(pcchNext, cchPcchNext, wzBinding);
+        ExitOnFailure(hr, "Failed to copy binding string to next string");
+        pcchNext += lstrlenW(wzBinding) + 1;
+        cchPcchNext -= lstrlenW(wzBinding) + 1;
+    }
+
+    for (ui = 0; ui < psw->cExtraAddresses; ++ui)
+    {
+        // set the IP address appropriately
+        if (0 == lstrcmpW(psw->swaExtraAddresses[ui].wzIP, L"*"))
+        {
+            ::ZeroMemory(wzIP, sizeof(wzIP));
+        }
+        else
+        {
+            hr = ::StringCchCopyW(wzIP, countof(wzIP), psw->swaExtraAddresses[ui].wzIP);
+            ExitOnFailure(hr, "Failed to copy extra addresses IP to IP string");
+        }
+
+        hr = ::StringCchPrintfW(wzBinding, countof(wzBinding), L"%s:%d:%s", wzIP, psw->swaExtraAddresses[ui].iPort, psw->swaExtraAddresses[ui].wzHeader);
+        ExitOnFailure(hr, "Failed to format IP:Port:Header binding string for extra address");
+        if (psw->swaExtraAddresses[ui].fSecure)
+        {
+            hr = ::StringCchCopyW(pcchSecureNext, cchPcchSecureNext, wzBinding);
+            ExitOnFailure(hr, "Failed to copy binding string to securenext string for extra address");
+            pcchSecureNext += lstrlenW(wzBinding) + 1;
+            cchPcchSecureNext -= lstrlenW(wzBinding) + 1;
+        }
+        else
+        {
+            hr = ::StringCchCopyW(pcchNext, cchPcchNext, wzBinding);
+            ExitOnFailure(hr, "Failed to copy binding string to next string for extra address");
+            pcchNext += lstrlenW(wzBinding) + 1;
+            cchPcchNext -= lstrlenW(wzBinding) + 1;
+        }
+    }
+
+    // Delete the existing secure bindings metabase value, as having one while SSLCertHash and SSLStoreName aren't both set correctly can result in
+    // 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
+    // allows the two aforementioned properties to exist in an intermediate state without errors
+    hr = ScaDeleteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SECURE_BINDINGS, MULTISZ_METADATA);
+    ExitOnFailure(hr, "Failed to temporarily delete secure bindings for Web");
+
+    // now write the bindings to the metabase
+    hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SERVER_BINDINGS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, MULTISZ_METADATA, wzBindings);
+    ExitOnFailure(hr, "Failed to write server bindings for Web");
+
+    // write the target path for the web's directory to the metabase
+    hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"/Root", MD_VR_PATH, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, psw->wzDirectory);
+    ExitOnFailure(hr, "Failed to write virtual root path for Web");
+
+    // write the description for the web to the metabase
+    hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SERVER_COMMENT, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, psw->wzDescription);
+    ExitOnFailure(hr, "Failed to write description for Web");
+
+    ui = psw->iConnectionTimeout;
+    if (MSI_NULL_INTEGER != ui)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_CONNECTION_TIMEOUT, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)ui));
+        ExitOnFailure(hr, "Failed to write connection timeout for Web");
+    }
+
+    ui = psw->iState;
+    if (MSI_NULL_INTEGER != ui)
+    {
+        if (2 == ui)
+        {
+            ui = 1;
+            hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SERVER_AUTOSTART, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)ui));
+            ExitOnFailure(hr, "Failed to write auto start flag for Web");
+            ui = 2;
+        }
+
+        if (1 == ui || 2 == ui)
+        {
+            ui = 1; // start command
+            hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SERVER_COMMAND, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)ui));
+            ExitOnFailure(hr, "Failed to start Web");
+        }
+        else if (0 == ui)
+        {
+            ui = 2; // stop command
+            hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SERVER_COMMAND, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)ui));
+            ExitOnFailure(hr, "Failed to stop Web");
+        }
+        else
+        {
+            hr = E_UNEXPECTED;
+            ExitOnFailure(hr, "Unexpected value for Web State");
+        }
+    }
+
+    WCHAR wzRootOfWeb[METADATA_MAX_NAME_LEN];
+    hr = ::StringCchPrintfW(wzRootOfWeb, countof(wzRootOfWeb), L"%s/Root", psw->wzWebBase);
+    ExitOnFailure(hr, "Failed to allocate WebBase/Root string for root of web");
+
+    // write the web dirproperties information
+    if (psw->fHasProperties)
+    {
+        hr = ScaWriteWebDirProperties(piMetabase, wzRootOfWeb, &psw->swp);
+        ExitOnFailure(hr, "Failed to write web security information to metabase");
+    }
+
+    // write the application information
+    if (psw->fHasApplication)
+    {
+        // On reinstall, we have to uninstall the old application, otherwise a duplicate will be created
+        if (WcaIsReInstalling(psw->isInstalled, psw->isAction))
+        {
+            hr = ScaDeleteApp(piMetabase, wzRootOfWeb);
+            ExitOnFailure(hr, "Failed to remove application for WebDir as part of a reinstall");
+        }
+
+        hr = ScaWriteWebApplication(piMetabase, wzRootOfWeb, &psw->swapp, psapList);
+        ExitOnFailure(hr, "Failed to write web application information to metabase");
+    }
+
+    // write the SSL certificate information
+    if (psw->pswscList)
+    {
+        hr = ScaSslCertificateWriteMetabase(piMetabase, psw->wzWebBase, psw->pswscList);
+        ExitOnFailure(hr, "Failed to write SSL certificates for Web site: %ls", psw->wzKey);
+    }
+
+    hr = ScaWriteMetabaseValue(piMetabase, psw->wzWebBase, L"", MD_SECURE_BINDINGS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, MULTISZ_METADATA, wzSecureBindings);
+    ExitOnFailure(hr, "Failed to write secure bindings for Web");
+
+    // write the headers
+    if (psw->pshhList)
+    {
+        hr = ScaWriteHttpHeader(piMetabase, wzRootOfWeb, psw->pshhList);
+        ExitOnFailure(hr, "Failed to write custom HTTP headers for Web site: %ls", psw->wzKey);
+    }
+
+    // write the errors
+    if (psw->psweList)
+    {
+        hr = ScaWriteWebError(piMetabase, weptWeb, psw->wzWebBase, psw->psweList);
+        ExitOnFailure(hr, "Failed to write custom web errors for Web site: %ls", psw->wzKey);
+    }
+
+    // write the mimetypes
+    if (psw->psmm)
+    {
+        hr = ScaWriteMimeMap(piMetabase, wzRootOfWeb, psw->psmm);
+        ExitOnFailure(hr, "Failed to write mimemap for Web site: %ls", psw->wzKey);
+    }
+
+    // write the log information to the metabase
+    if (psw->fHasLog)
+    {
+        hr = ScaWriteWebLog(piMetabase, psw->wzWebBase, &psw->swl);
+        ExitOnFailure(hr, "Failed to write web log information to metabase");
+    }
+
+LExit:
+    return hr;
+}
+
+
+static HRESULT ScaWebRemove(
+    __in IMSAdminBase* piMetabase,
+    __in const SCA_WEB* psw
+    )
+{
+    HRESULT hr = S_OK;
+
+    // simply remove the root key and everything else is pulled at the same time
+    hr = ScaDeleteMetabaseKey(piMetabase, psw->wzWebBase, L"");
+    ExitOnFailure(hr, "Failed to remove web '%ls' from metabase", psw->wzKey);
+
+LExit:
+    return hr;
+}
+
+
+static DWORD SiteIdFromDescription(
+    __in_z LPCWSTR wzDescription
+    )
+{
+    LPCWSTR pwz = wzDescription;
+    DWORD dwSiteId = 0;
+    while (pwz && *pwz)
+    {
+        WCHAR ch = *pwz & 0xdf;
+        dwSiteId = (dwSiteId * 101) + ch;
+        ++pwz;
+    }
+
+    return (dwSiteId % INT_MAX) + 1;
+}
+
+
+// insertion sort
+static void Sort(
+    __in_ecount(cArray) DWORD dwArray[],
+    __in int cArray
+    )
+{
+    int i, j;
+    DWORD dwData;
+
+    for (i = 1; i < cArray; ++i)
+    {
+        dwData = dwArray[i];
+
+        j = i - 1;
+        while (0 <= j && dwArray[j] > dwData)
+        {
+            dwArray[j + 1] = dwArray[j];
+            j--;
+        }
+
+        dwArray[j + 1] = dwData;
+    }
+}
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 @@
+#pragma once
+// 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.
+
+
+#include "scawebapp.h"
+#include "scawebprop.h"
+#include "scahttpheader.h"
+#include "scaweberr.h"
+#include "scassl.h"
+#include "scaapppool.h"
+#include "scaweblog.h"
+#include "scamimemap.h"
+
+// globals
+#define MAX_ADDRESSES_PER_WEB 10
+
+enum eWebQuery { wqWeb = 1, wqComponent, wqId, wqDescription, wqConnectionTimeout, wqDirectory,
+                 wqState, wqAttributes, wqProperties, wqApplication, wqAddress, wqIP, wqPort, wqHeader, wqSecure, wqLog, wqInstalled, wqAction, wqSourcePath, wqTargetPath};
+
+enum eWebAddressQuery { waqAddress = 1, waqWeb, waqIP, waqPort, waqHeader, waqSecure };
+
+enum SCA_WEB_ATTRIBUTES
+{
+    SWATTRIB_NOCONFIGUREIFEXISTS = 2
+};
+
+// structs
+struct SCA_WEB_ADDRESS
+{
+    WCHAR wzKey [MAX_DARWIN_KEY + 1];
+
+    WCHAR wzIP[MAX_DARWIN_COLUMN + 1];
+    int iPort;
+    WCHAR wzHeader[MAX_DARWIN_COLUMN + 1];
+    BOOL fSecure;
+};
+
+struct SCA_WEB
+{
+    // darwin information
+    WCHAR wzKey[MAX_DARWIN_KEY + 1];
+    WCHAR wzComponent[MAX_DARWIN_KEY + 1];
+    BOOL fHasComponent;
+    INSTALLSTATE isInstalled;
+    INSTALLSTATE isAction;
+
+    // metabase information
+    WCHAR wzWebBase[METADATA_MAX_NAME_LEN + 1];
+    BOOL fBaseExists;
+
+    // iis configuation information
+    SCA_WEB_ADDRESS swaKey;
+
+    SCA_WEB_ADDRESS swaExtraAddresses[MAX_ADDRESSES_PER_WEB + 1];
+    DWORD cExtraAddresses;
+
+    WCHAR wzDirectory[MAX_PATH];
+    WCHAR wzDescription[MAX_DARWIN_COLUMN + 1];
+
+    int iState;
+    int iAttributes;
+
+    BOOL fHasProperties;
+    SCA_WEB_PROPERTIES swp;
+
+    BOOL fHasApplication;
+    SCA_WEB_APPLICATION swapp;
+
+    BOOL fHasSecurity;
+    int dwAccessPermissions;
+    int iConnectionTimeout;
+
+    SCA_MIMEMAP* psmm; // mime mappings
+    SCA_WEB_SSL_CERTIFICATE* pswscList;
+    SCA_HTTP_HEADER* pshhList;
+    SCA_WEB_ERROR* psweList;
+
+    BOOL fHasLog;
+    SCA_WEB_LOG swl;
+
+    SCA_WEB* pswNext;
+};
+
+
+// prototypes
+HRESULT ScaWebsRead(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_MIMEMAP** ppsmmList,
+    __in SCA_WEB** ppswList,
+    __in SCA_HTTP_HEADER** pshhList,
+    __in SCA_WEB_ERROR** psweList,
+    __in WCA_WRAPQUERY_HANDLE hUserQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
+    __in WCA_WRAPQUERY_HANDLE hSslCertQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebLogQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
+    __inout LPWSTR *ppwzCustomActionData
+    );
+
+HRESULT ScaWebsGetBase(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_WEB* pswList,
+    __in LPCWSTR wzWeb,
+    __out_ecount(cchWebBase) LPWSTR wzWebBase,
+    __in DWORD cchWebBase,
+    __in WCA_WRAPQUERY_HANDLE hWrapQuery
+    );
+
+HRESULT ScaWebsInstall(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_WEB* pswList,
+    __in SCA_APPPOOL * psapList
+    );
+
+HRESULT ScaWebsUninstall(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_WEB* pswList
+    );
+
+void ScaWebsFreeList(
+    __in SCA_WEB* pswHead
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+//Adding this because delivery doesn't have the updated specstrings.h that windows build does
+#ifndef __in_xcount
+#define __in_xcount(size)
+#endif
+
+// prototypes for private helper functions
+static SCA_WEB7* NewWeb7();
+static SCA_WEB7* AddWebToList7(
+    __in SCA_WEB7* pswList,
+    __in SCA_WEB7* psw
+    );
+
+static HRESULT ScaWebFindBase7(
+    __in SCA_WEB7* pswList,
+    LPCWSTR wzDescription
+    );
+
+static HRESULT ScaWebWrite7(
+    __in SCA_WEB7* psw,
+    __in SCA_APPPOOL * psapList
+    );
+
+static HRESULT ScaWebRemove7(__in const SCA_WEB7* psw);
+
+
+HRESULT ScaWebsRead7(
+    __in SCA_WEB7** ppswList,
+    __in SCA_HTTP_HEADER** ppshhList,
+    __in SCA_WEB_ERROR** ppsweList,
+    __in WCA_WRAPQUERY_HANDLE hUserQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
+    __in WCA_WRAPQUERY_HANDLE hSslCertQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebLogQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
+    __inout LPWSTR *ppwzCustomActionData
+    )
+{
+    Assert(ppswList);
+    WcaLog(LOGMSG_VERBOSE, "Entering ScaWebsRead7()");
+
+    HRESULT hr = S_OK;
+
+    MSIHANDLE hRec;
+    MSIHANDLE hRecAddresses;
+
+    WCA_WRAPQUERY_HANDLE hQueryWebSite = NULL;
+    WCA_WRAPQUERY_HANDLE hQueryWebAddress = NULL;
+
+    SCA_WEB7* psw = NULL;
+    LPWSTR pwzData = NULL;
+
+    DWORD dwLen = 0;
+    errno_t error = EINVAL;
+
+    // check to see what tables are available
+    hr = WcaBeginUnwrapQuery(&hQueryWebSite, ppwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap query for ScaWebsRead");
+
+    hr = WcaBeginUnwrapQuery(&hQueryWebAddress, ppwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap query for ScaWebsRead");
+
+
+    if (0 == WcaGetQueryRecords(hQueryWebSite) || 0 == WcaGetQueryRecords(hQueryWebAddress))
+    {
+        WcaLog(LOGMSG_VERBOSE, "Required tables not present");
+        ExitFunction1(hr = S_FALSE);
+    }
+
+    // loop through all the webs
+    while (S_OK == (hr = WcaFetchWrappedRecord(hQueryWebSite, &hRec)))
+    {
+        psw = NewWeb7();
+        if (!psw)
+        {
+            hr = E_OUTOFMEMORY;
+            break;
+        }
+
+        // get the darwin information
+        hr = WcaGetRecordString(hRec, wqWeb, &pwzData);
+        ExitOnFailure(hr, "Failed to get Web");
+        hr = ::StringCchCopyW(psw->wzKey, countof(psw->wzKey), pwzData);
+        ExitOnFailure(hr, "Failed to copy key string to web object");
+
+        // get component install state
+        hr = WcaGetRecordString(hRec, wqComponent, &pwzData);
+        ExitOnFailure(hr, "Failed to get Component for Web");
+        hr = ::StringCchCopyW(psw->wzComponent, countof(psw->wzComponent), pwzData);
+        ExitOnFailure(hr, "Failed to copy component string to web object");
+        if (*(psw->wzComponent))
+        {
+            psw->fHasComponent = TRUE;
+
+            hr = WcaGetRecordInteger(hRec, wqInstalled, (int *)&psw->isInstalled);
+            ExitOnFailure(hr, "Failed to get web Component's installed state");
+
+            WcaGetRecordInteger(hRec, wqAction, (int *)&psw->isAction);
+            ExitOnFailure(hr, "Failed to get web Component's action state");
+        }
+
+        // Get the web's description.
+        hr = WcaGetRecordString(hRec, wqDescription, &pwzData);
+        ExitOnFailure(hr, "Failed to get Description for Web");
+        hr = ::StringCchCopyW(psw->wzDescription, countof(psw->wzDescription), pwzData);
+        ExitOnFailure(hr, "Failed to copy description string to web object");
+
+        //get web's site Id
+        hr = WcaGetRecordInteger(hRec, wqId, &psw->iSiteId);
+        ExitOnFailure(hr, "Failed to get SiteId for Web");
+
+        // get the web's key address (Bindings)
+        hr = WcaGetRecordString(hRec, wqAddress, &pwzData);
+        ExitOnFailure(hr, "Failed to get Address for Web");
+        hr = ::StringCchCopyW(psw->swaBinding.wzKey, countof(psw->swaBinding.wzKey), pwzData);
+        ExitOnFailure(hr, "Failed to copy web binding key");
+
+        hr = WcaGetRecordString(hRec, wqIP, &pwzData);
+        ExitOnFailure(hr, "Failed to get IP for Web");
+        hr = ::StringCchCopyW(psw->swaBinding.wzIP, countof(psw->swaBinding.wzIP), pwzData);
+        ExitOnFailure(hr, "Failed to copy web IP");
+
+        hr = WcaGetRecordString(hRec, wqPort, &pwzData);
+        ExitOnFailure(hr, "Failed to get Web Address port");
+        psw->swaBinding.iPort = wcstol(pwzData, NULL, 10);
+
+        hr = WcaGetRecordString(hRec, wqHeader, &pwzData);
+        ExitOnFailure(hr, "Failed to get Header for Web");
+        hr = ::StringCchCopyW(psw->swaBinding.wzHeader, countof(psw->swaBinding.wzHeader), pwzData);
+        ExitOnFailure(hr, "Failed to copy web header");
+
+        hr = WcaGetRecordInteger(hRec, wqSecure, &psw->swaBinding.fSecure);
+        ExitOnFailure(hr, "Failed to get if Web is secure");
+        if (S_FALSE == hr)
+        {
+            psw->swaBinding.fSecure = FALSE;
+        }
+
+        // look to see if site exists
+        dwLen = METADATA_MAX_NAME_LEN;
+        hr = ScaWebFindBase7(*ppswList, psw->wzDescription);
+
+        // If we didn't find a web in memory, ignore it - during execute CA
+        // if the site truly does not exist then there will be an error.
+        if (S_OK == hr)
+        {
+            // site exists in config
+            psw->fBaseExists = TRUE;
+        }
+        else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
+        {
+            hr = S_OK;
+
+            // site does not exists in config
+            psw->fBaseExists = FALSE;
+        }
+        ExitOnFailure(hr, "Failed to find web site");
+
+        // get any extra web addresses
+        WcaFetchWrappedReset(hQueryWebAddress);
+
+        while (S_OK == (hr = WcaFetchWrappedRecordWhereString(hQueryWebAddress, 2, psw->wzKey, &hRecAddresses)))
+        {
+            if (MAX_ADDRESSES_PER_WEB <= psw->cExtraAddresses)
+            {
+                hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+                ExitOnFailure(hr, "Failure to get more extra web addresses, max exceeded.");
+            }
+
+            hr = WcaGetRecordString(hRecAddresses, waqAddress, &pwzData);
+            ExitOnFailure(hr, "Failed to get extra web Address");
+
+            // if this isn't the key address add it
+            if (0 != lstrcmpW(pwzData, psw->swaBinding.wzKey))
+            {
+                hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey,
+                    countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey), pwzData);
+                ExitOnFailure(hr, "Failed to copy web binding key");
+
+                hr = WcaGetRecordString(hRecAddresses, waqIP, &pwzData);
+                ExitOnFailure(hr, "Failed to get extra web IP");
+                hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP), pwzData);
+                ExitOnFailure(hr, "Failed to copy web binding IP");
+
+                hr = WcaGetRecordString(hRecAddresses, waqPort, &pwzData);
+                ExitOnFailure(hr, "Failed to get port for extra web IP");
+                psw->swaExtraAddresses[psw->cExtraAddresses].iPort= wcstol(pwzData, NULL, 10);
+
+                // errno is set to ERANGE if overflow or underflow occurs
+                _get_errno(&error);
+
+                if (ERANGE == error)
+                {
+                    hr = E_INVALIDARG;
+                    ExitOnFailure(hr, "Failed to convert web Port address");
+                }
+
+                hr = WcaGetRecordString(hRecAddresses, waqHeader, &pwzData);
+                ExitOnFailure(hr, "Failed to get header for extra web IP");
+                hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader), pwzData);
+                ExitOnFailure(hr, "Failed to copy web binding header");
+
+                hr = WcaGetRecordInteger(hRecAddresses, waqSecure, &psw->swaExtraAddresses[psw->cExtraAddresses].fSecure);
+                ExitOnFailure(hr, "Failed to get if secure extra web IP");
+                if (S_FALSE == hr)
+                {
+                    psw->swaExtraAddresses[psw->cExtraAddresses].fSecure = FALSE;
+                }
+
+                ++psw->cExtraAddresses;
+            }
+        }
+
+        if (E_NOMOREITEMS == hr)
+        {
+            hr = S_OK;
+        }
+        ExitOnFailure(hr, "Failure occured while getting extra web addresses");
+
+        //
+        // Connection time out
+        //
+        hr = WcaGetRecordInteger(hRec, wqConnectionTimeout, &psw->iConnectionTimeout);
+        ExitOnFailure(hr, "Failed to get connection timeout for Web");
+
+        if (psw->fHasComponent) // If we're installing it, it needs a dir
+        {
+            // get the web's directory
+            if (INSTALLSTATE_SOURCE == psw->isAction)
+            {
+                hr = WcaGetRecordString(hRec, wqSourcePath, &pwzData);
+            }
+            else
+            {
+                hr = WcaGetRecordString(hRec, wqTargetPath, &pwzData);
+            }
+            ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory");
+
+            dwLen = lstrlenW(pwzData);
+            // remove trailing backslash
+            if (dwLen > 0 && pwzData[dwLen-1] == L'\\')
+            {
+                pwzData[dwLen-1] = 0;
+            }
+            hr = ::StringCchCopyW(psw->wzDirectory, countof(psw->wzDirectory), pwzData);
+            ExitOnFailure(hr, "Failed to copy web dir: '%ls'", pwzData);
+
+        }
+
+        hr = WcaGetRecordInteger(hRec, wqState, &psw->iState);
+        ExitOnFailure(hr, "Failed to get state for Web");
+
+        hr = WcaGetRecordInteger(hRec, wqAttributes, &psw->iAttributes);
+        ExitOnFailure(hr, "Failed to get attributes for Web");
+
+        // get the dir properties for this web
+        hr = WcaGetRecordString(hRec, wqProperties, &pwzData);
+        ExitOnFailure(hr, "Failed to get directory properties for Web");
+        if (*pwzData)
+        {
+            hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &psw->swp);
+            ExitOnFailure(hr, "Failed to get directory properties for Web");
+
+            psw->fHasProperties = TRUE;
+        }
+
+        // get the application information for this web
+        hr = WcaGetRecordString(hRec, wqApplication, &pwzData);
+        ExitOnFailure(hr, "Failed to get application identifier for Web");
+        if (*pwzData)
+        {
+            hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &psw->swapp);
+            ExitOnFailure(hr, "Failed to get application for Web");
+
+            psw->fHasApplication = TRUE;
+        }
+
+        // get the SSL certificates
+        hr = ScaSslCertificateRead(psw->wzKey, hSslCertQuery, &(psw->pswscList));
+        ExitOnFailure(hr, "Failed to get SSL Certificates.");
+
+        // get the custom headers
+        if (*ppshhList)
+        {
+            hr = ScaGetHttpHeader(hhptWeb, psw->wzKey, ppshhList, &(psw->pshhList));
+            ExitOnFailure(hr, "Failed to get Custom HTTP Headers");
+        }
+
+        // get the errors
+        if (*ppsweList)
+        {
+            hr = ScaGetWebError(weptWeb, psw->wzKey, ppsweList, &(psw->psweList));
+            ExitOnFailure(hr, "Failed to get Custom Errors");
+        }
+
+        // get the log information for this web
+        hr = WcaGetRecordString(hRec, wqLog, &pwzData);
+        ExitOnFailure(hr, "Failed to get log identifier for Web");
+        if (*pwzData)
+        {
+            hr = ScaGetWebLog7(pwzData, hWebLogQuery, &psw->swl);
+            ExitOnFailure(hr, "Failed to get Log for Web.");
+            psw->fHasLog = TRUE;
+        }
+
+        *ppswList = AddWebToList7(*ppswList, psw);
+        psw = NULL; // set the web NULL so it doesn't accidentally get freed below
+    }
+
+    if (E_NOMOREITEMS == hr)
+    {
+        hr = S_OK;
+    }
+
+LExit:
+    // if anything was left over after an error clean it all up
+    WcaFinishUnwrapQuery(hQueryWebSite);
+    WcaFinishUnwrapQuery(hQueryWebAddress);
+
+    ScaWebsFreeList7(psw);
+
+    ReleaseStr(pwzData);
+    WcaLog(LOGMSG_VERBOSE, "Exiting ScaWebsRead7()");
+
+    return hr;
+}
+
+BOOL CompareBinding(
+    __in IAppHostElement* pBinding,
+    __in LPVOID pContext
+    )
+{
+    BOOL fFound = FALSE;
+    HRESULT hr = S_OK;
+    LPWSTR pwzBindingInfo = NULL;
+    SCA_WEB7* psw = (SCA_WEB7*)pContext;
+
+    hr = Iis7GetPropertyString(pBinding, IIS_CONFIG_BINDINGINFO, &pwzBindingInfo);
+    ExitOnFailure(hr, "Failed to get bindinginfo for binding element");
+
+    LPWSTR pwzExists = pwzBindingInfo;
+    // Break down the address into its constituent parts (IP:Port:Header).
+    // Taken from IIS6 CA code for compatibility
+    while (S_OK == hr && *pwzExists)
+    {
+        LPCWSTR pwzIPExists = pwzExists;
+        pwzExists = const_cast<LPWSTR>(wcsstr(pwzIPExists, L":"));
+        if (NULL == pwzExists)
+        {
+            ExitFunction();
+        }
+        *pwzExists = L'\0';
+
+        LPCWSTR pwzPortExists = pwzExists + 1;
+        pwzExists = const_cast<LPWSTR>(wcsstr(pwzPortExists, L":"));
+        if (NULL == pwzExists)
+        {
+            ExitFunction();
+        }
+        *pwzExists = L'\0';
+        int iPortExists = wcstol(pwzPortExists, NULL, 10);
+
+        LPCWSTR pwzHeaderExists = pwzExists + 1;
+
+        BOOL fIpMatches = (0 == lstrcmpW(psw->swaBinding.wzIP, pwzIPExists));   // Explicit IP match
+        fIpMatches |= (0 == lstrcmpW(psw->swaBinding.wzIP, L"*"));              // Authored * matches any IP
+        fIpMatches |= ('\0' != psw->swaBinding.wzIP) &&                         // Unauthored IP
+                      (0 == lstrcmpW(pwzIPExists, L"*"));                       // matches the All Unassigned IP : '*'
+
+        // compare the passed in address with the address listed for this web
+        if (fIpMatches && psw->swaBinding.iPort == iPortExists &&
+            0 == lstrcmpW(psw->swaBinding.wzHeader, pwzHeaderExists))
+        {
+            fFound = TRUE;
+            break;
+        }
+
+        // move to the next block of data, this may move beyond the available
+        // data and exit the while loop above.
+        pwzExists = const_cast<LPWSTR>(pwzHeaderExists + lstrlenW(pwzHeaderExists));
+    }
+
+LExit:
+    WcaLog(LOGMSG_VERBOSE, "Site with binding %ls %s a match", pwzBindingInfo, fFound ? "is" : "is not");
+    ReleaseNullStr(pwzBindingInfo);
+    return fFound;
+}
+
+BOOL EnumSiteCompareBinding(
+    __in IAppHostElement* pSite,
+    __in LPVOID pContext
+    )
+{
+    BOOL fFound = FALSE;
+    HRESULT hr = S_OK;
+    SCA_WEB7* psw = (SCA_WEB7*)pContext;
+    IAppHostChildElementCollection *pSiteChildren = NULL;
+    IAppHostElement *pBindings = NULL;
+    IAppHostElementCollection *pBindingsCollection = NULL;
+    IAppHostElement *pBinding = NULL;
+    VARIANT vtProp;
+    VariantInit(&vtProp);
+
+    hr = pSite->get_ChildElements(&pSiteChildren);
+    ExitOnFailure(hr, "Failed get site child elements collection");
+
+    vtProp.vt = VT_BSTR;
+    vtProp.bstrVal = ::SysAllocString(IIS_CONFIG_BINDINGS);
+    hr = pSiteChildren->get_Item(vtProp, &pBindings);
+    ExitOnFailure(hr, "Failed get bindings element");
+
+    hr = pBindings->get_Collection(&pBindingsCollection);
+    ExitOnFailure(hr, "Failed get bindings collection");
+
+    WcaLog(LOGMSG_VERBOSE, "Searching for site with binding %ls:%d:%ls", psw->swaBinding.wzIP, psw->swaBinding.iPort, psw->swaBinding.wzHeader);
+
+    hr = Iis7EnumAppHostElements(pBindingsCollection, CompareBinding, psw, &pBinding, NULL);
+    ExitOnFailure(hr, "Failed search bindings collection");
+
+    fFound = NULL != pBinding;
+LExit:
+    VariantClear(&vtProp);
+    ReleaseNullObject(pSiteChildren);
+    ReleaseNullObject(pBindings);
+    ReleaseNullObject(pBindingsCollection);
+    ReleaseNullObject(pBinding);
+    return fFound;
+}
+
+HRESULT ScaWebSearch7(
+    __in SCA_WEB7* psw,
+    __deref_out_z_opt LPWSTR* pswWeb,
+    __out_opt BOOL* pfFound
+    )
+{
+    HRESULT hr = S_OK;
+    BOOL fInitializedCom = FALSE;
+    BSTR bstrSites = NULL;
+    BSTR bstrAppHostRoot = NULL;
+    IAppHostAdminManager *pAdminMgr = NULL;
+    IAppHostElement *pSites = NULL;
+    IAppHostElementCollection *pCollection = NULL;
+    IAppHostElement *pSite = NULL;
+
+    if (NULL != pswWeb)
+    {
+        ReleaseNullStr(*pswWeb);
+    }
+
+    if (NULL != pfFound)
+    {
+        *pfFound = FALSE;
+    }
+
+    hr = ::CoInitialize(NULL);
+    ExitOnFailure(hr, "Failed to initialize COM");
+    fInitializedCom = TRUE;
+
+    hr = CoCreateInstance(__uuidof(AppHostAdminManager), NULL, CLSCTX_INPROC_SERVER, __uuidof(IAppHostAdminManager), reinterpret_cast<void**> (&pAdminMgr));
+    if (REGDB_E_CLASSNOTREG == hr)
+    {
+        WcaLog(LOGMSG_VERBOSE, "AppHostAdminManager was not registered, cannot find site.");
+        hr = S_OK;
+        ExitFunction();
+    }
+    ExitOnFailure(hr, "Failed to CoCreate IAppHostAdminManager");
+
+    bstrSites = ::SysAllocString(IIS_CONFIG_SITES_SECTION);
+    ExitOnNull(bstrSites, hr, E_OUTOFMEMORY, "Failed to allocate sites string.");
+
+    bstrAppHostRoot = ::SysAllocString(IIS_CONFIG_APPHOST_ROOT);
+    ExitOnNull(bstrAppHostRoot, hr, E_OUTOFMEMORY, "Failed to allocate host root string.");
+
+    hr = pAdminMgr->GetAdminSection(bstrSites, bstrAppHostRoot, &pSites);
+    ExitOnFailure(hr, "Failed get sites section");
+    ExitOnNull(pSites, hr, ERROR_FILE_NOT_FOUND, "Failed get sites section object");
+
+    hr = pSites->get_Collection(&pCollection);
+    ExitOnFailure(hr, "Failed get sites collection");
+
+    // not explicitly doing a Description search
+    if (-1 != psw->iSiteId)
+    {
+        if (MSI_NULL_INTEGER == psw->iSiteId)
+        {
+            // Enumerate sites & determine if the binding matches
+            hr = Iis7EnumAppHostElements(pCollection, EnumSiteCompareBinding, psw, &pSite, NULL);
+            ExitOnFailure(hr, "Failed locate site by ID");
+        }
+        else
+        {
+            // Find a site with ID matches
+            hr = Iis7FindAppHostElementInteger(pCollection, IIS_CONFIG_SITE, IIS_CONFIG_ID, psw->iSiteId, &pSite, NULL);
+            ExitOnFailure(hr, "Failed locate site by ID");
+        }
+    }
+
+    if (NULL == pSite)
+    {
+        // Find a site with Name that matches
+        hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_SITE, IIS_CONFIG_NAME, psw->wzDescription, &pSite, NULL);
+        ExitOnFailure(hr, "Failed locate site by ID");
+    }
+
+    if (NULL != pSite)
+    {
+        if (NULL != pfFound)
+        {
+            *pfFound = TRUE;
+        }
+
+        if (NULL != pswWeb)
+        {
+            // We found a site, return its description
+            hr = Iis7GetPropertyString(pSite, IIS_CONFIG_NAME, pswWeb);
+            ExitOnFailure(hr, "Failed get site name");
+        }
+    }
+LExit:
+    ReleaseNullObject(pAdminMgr);
+    ReleaseNullObject(pSites);
+    ReleaseNullObject(pCollection);
+    ReleaseNullObject(pSite);
+    ReleaseBSTR(bstrAppHostRoot);
+    ReleaseBSTR(bstrSites);
+
+    if (fInitializedCom)
+    {
+        ::CoUninitialize();
+    }
+    return hr;
+}
+
+
+HRESULT ScaWebsGetBase7(
+    __in SCA_WEB7* pswList,
+    __in LPCWSTR pswWebKey,
+    __out_ecount(cchDest) LPWSTR pswWeb,
+    __in DWORD_PTR cchDest
+    )
+{
+    HRESULT hr = S_OK;
+    BOOL fFound = FALSE;
+    SCA_WEB7* psw = pswList;
+    LPWSTR wzSiteName = NULL;
+
+    *pswWeb = '/0';
+
+    //looking for psw->wzKey == pswWebKey
+    while(psw)
+    {
+        if (0 == wcscmp(pswWebKey, psw->wzKey))
+        {
+            fFound = TRUE;
+            break;
+        }
+        psw = psw->pswNext;
+    }
+
+    if (!fFound)
+    {
+        ExitFunction1(hr = S_FALSE);
+    }
+
+    // Search if we're not installing the site
+    if (!psw->fHasComponent || (psw->iAttributes & SWATTRIB_NOCONFIGUREIFEXISTS))
+    {
+        // We are not installing this website.  Search for it in IIS config
+        hr = ScaWebSearch7(psw, &wzSiteName, NULL);
+        ExitOnFailure(hr, "Failed to search for Website");
+
+        if (NULL != wzSiteName)
+        {
+            hr = ::StringCchCopyW(pswWeb, cchDest, wzSiteName);
+            ExitOnFailure(hr, "Failed to set Website description for located Website");
+        }
+    }
+
+    if ('/0' == *pswWeb)
+    {
+        WcaLog(LOGMSG_VERBOSE, "Could not find Web: %ls, defaulting to %ls", psw->wzKey, psw->wzDescription);
+        // Default to the provided description, the Exec CA will locate by description
+        hr = ::StringCchCopyW(pswWeb, cchDest, psw->wzDescription);
+        ExitOnFailure(hr, "Failed to set Website description to default");
+    }
+LExit:
+    ReleaseNullStr(wzSiteName);
+    return hr;
+}
+
+HRESULT ScaWebsInstall7(
+    __in SCA_WEB7* pswList,
+    __in SCA_APPPOOL * psapList
+    )
+{
+    HRESULT hr = S_OK;
+    SCA_WEB7* psw = pswList;
+
+    while (psw)
+    {
+        // if we are installing the web site
+        if (psw->fHasComponent && WcaIsInstalling(psw->isInstalled, psw->isAction))
+        {
+            hr = ScaWebWrite7(psw, psapList);
+            ExitOnFailure(hr, "failed to write web '%ls' to metabase", psw->wzKey);
+        }
+
+        psw = psw->pswNext;
+    }
+
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaWebsUninstall7(
+    __in SCA_WEB7* pswList
+    )
+{
+    HRESULT hr = S_OK;
+    SCA_WEB7* psw = pswList;
+
+    while (psw)
+    {
+        if (psw->fHasComponent && WcaIsUninstalling(psw->isInstalled, psw->isAction))
+        {
+            // If someone
+            hr = ScaWebRemove7(psw);
+            ExitOnFailure(hr, "Failed to remove web '%ls' ", psw->wzKey);
+        }
+
+        psw = psw->pswNext;
+    }
+
+LExit:
+    return hr;
+}
+
+
+void ScaWebsFreeList7(__in SCA_WEB7* pswList)
+{
+    SCA_WEB7* pswDelete = pswList;
+    while (pswList)
+    {
+        pswDelete = pswList;
+        pswList = pswList->pswNext;
+
+        // Free the SSL, headers and errors list first
+        ScaSslCertificateFreeList(pswDelete->pswscList);
+        ScaHttpHeaderFreeList(pswDelete->pshhList);
+        ScaWebErrorFreeList(pswDelete->psweList);
+
+        MemFree(pswDelete);
+    }
+}
+
+
+// private helper functions
+
+static SCA_WEB7* NewWeb7()
+{
+    SCA_WEB7* psw = (SCA_WEB7*)MemAlloc(sizeof(SCA_WEB7), TRUE);
+    Assert(psw);
+    return psw;
+}
+
+
+static SCA_WEB7* AddWebToList7(
+    __in SCA_WEB7* pswList,
+    __in SCA_WEB7* psw
+    )
+{
+    if (pswList)
+    {
+        SCA_WEB7* pswTemp = pswList;
+        while (pswTemp->pswNext)
+        {
+            pswTemp = pswTemp->pswNext;
+        }
+
+        pswTemp->pswNext = psw;
+    }
+    else
+    {
+        pswList = psw;
+    }
+
+    return pswList;
+}
+
+
+static HRESULT ScaWebFindBase7(
+    __in SCA_WEB7* pswList,
+    __in_z LPCWSTR wzDescription
+    )
+{
+    HRESULT hr = S_OK;
+    BOOL fFound = FALSE;
+
+    // try to find the web in memory first
+    for (SCA_WEB7* psw = pswList; psw; psw = psw->pswNext)
+    {
+        if (0 == wcscmp(wzDescription, psw->wzDescription))
+        {
+            fFound = TRUE;
+            break;
+        }
+    }
+
+    if (!fFound)
+    {
+        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+    }
+
+    return hr;
+}
+
+
+static HRESULT ScaWebWrite7(
+    __in SCA_WEB7* psw,
+    __in SCA_APPPOOL * psapList
+    )
+{
+    HRESULT hr = S_OK;
+
+    BOOL fExists = FALSE;
+    UINT ui = 0;
+    WCHAR wzIP[64];
+    WCHAR wzBinding[1024];
+    WCHAR wzAppPoolName[MAX_PATH];
+
+    //
+    // determine if site must be new
+    //
+    if (psw->iAttributes & SWATTRIB_NOCONFIGUREIFEXISTS)
+    {
+        // Check if site already exists.
+        hr = ScaWebSearch7(psw, NULL, &fExists);
+        ExitOnFailure(hr, "Failed to search for web: %ls", psw->wzKey);
+
+        if (fExists)
+        {
+            hr = S_FALSE;
+            WcaLog(LOGMSG_VERBOSE, "Skipping configuration of existing web: %ls", psw->wzKey);
+            ExitFunction();
+        }
+    }
+
+    //create a site
+    hr = ScaWriteConfigID(IIS_SITE);
+    ExitOnFailure(hr, "Failed write site ID");
+
+    hr = ScaWriteConfigID(IIS_CREATE);
+    ExitOnFailure(hr, "Failed write site ID create action");
+
+    //Site Name
+    hr = ScaWriteConfigString(psw->wzDescription);                  //Site Name
+    ExitOnFailure(hr, "Failed write site desc");
+
+    //Site Id -- value is MSI_NULL_INTEGER if not set in WIX
+    hr = ScaWriteConfigInteger(psw->iSiteId);                        //SiteID
+    ExitOnFailure(hr, "Failed write site id value");
+
+    //Site Auto Start -- value is MSI_NULL_INTEGER if not set in WIX
+    hr = ScaWriteConfigInteger(psw->iState);                        // serverAutoStart
+    ExitOnFailure(hr, "Failed write site autostart");
+
+    hr = ScaWriteConfigInteger(psw->iConnectionTimeout);            //limits/connectionTimeout
+    ExitOnFailure(hr, "Failed write site timeout");
+
+    //create default application
+    hr = ScaWriteConfigID(IIS_APPLICATION);
+    ExitOnFailure(hr, "Failed write app ID");
+    hr = ScaWriteConfigID(IIS_CREATE);
+    ExitOnFailure(hr, "Failed write app action ID");
+    hr = ScaWriteConfigString(psw->wzDescription);      //site name key
+    ExitOnFailure(hr, "Failed write app desc");
+    hr = ScaWriteConfigString(L"/");                    //  App Path (default)
+    ExitOnFailure(hr, "Failed write app def path /");
+
+    if (psw->fHasApplication && *psw->swapp.wzAppPool)
+    {
+        hr = ScaFindAppPool7(psw->swapp.wzAppPool, wzAppPoolName, countof(wzAppPoolName), psapList);
+        ExitOnFailure(hr, "Failed to read app pool from application");
+
+        hr = ScaWriteConfigString(wzAppPoolName);
+        ExitOnFailure(hr, "Failed write app appPool");
+    }
+    else
+    {
+        hr = ScaWriteConfigString(L"");
+        ExitOnFailure(hr, "Failed write app appPool");
+    }
+
+    //create vdir for default application
+    hr = ScaWriteConfigID(IIS_VDIR);
+    ExitOnFailure(hr, "Failed write vdir ID");
+    hr = ScaWriteConfigID(IIS_CREATE);
+    ExitOnFailure(hr, "Failed write vdir action");
+    hr = ScaWriteConfigString(psw->wzDescription);      //site name key
+    ExitOnFailure(hr, "Failed write vdir desc");
+    hr = ScaWriteConfigString(L"/");                    //vdir path (default)
+    ExitOnFailure(hr, "Failed write vdir app");
+    hr = ScaWriteConfigString(psw->wzDirectory);         //physical dir
+    ExitOnFailure(hr, "Failed write vdir dir");
+
+    //create bindings for site
+    hr = ScaWriteConfigID(IIS_BINDING);
+    ExitOnFailure(hr, "Failed write binding ID");
+    hr = ScaWriteConfigID(IIS_CREATE);
+    ExitOnFailure(hr, "Failed write binding action ID");
+    hr = ScaWriteConfigString(psw->wzDescription);      //site name key
+    ExitOnFailure(hr, "Failed write binding site key");
+
+    if (psw->swaBinding.fSecure)
+    {
+        hr = ScaWriteConfigString(L"https");            // binding protocol
+        ExitOnFailure(hr, "Failed write binding https");
+    }
+    else
+    {
+        hr = ScaWriteConfigString(L"http");             // binding protocol
+        ExitOnFailure(hr, "Failed write binding http");
+    }
+
+    // set the IP address appropriately
+    if (0 == wcscmp(psw->swaBinding.wzIP, L""))
+    {
+        hr = ::StringCchCopyW(wzIP, countof(wzIP), L"*"); // if no IP specified = add *
+    }
+    else
+    {
+#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
+        hr = ::StringCchCopyW(wzIP, countof(wzIP), psw->swaBinding.wzIP); // else leave untouched
+    }
+    ExitOnFailure(hr, "Failed to copy IP string");
+
+    hr = ::StringCchPrintfW(wzBinding, countof(wzBinding), L"%s:%d:%s", wzIP, psw->swaBinding.iPort, psw->swaBinding.wzHeader);
+    ExitOnFailure(hr, "Failed to format IP:Port:Header binding string");
+
+    // write bindings CAData
+    hr = ScaWriteConfigString(wzBinding) ;            //binding info
+    ExitOnFailure(hr, "Failed to create web bindings");
+
+    for (ui = 0; (ui < MAX_ADDRESSES_PER_WEB) && (ui < psw->cExtraAddresses); ++ui)
+    {
+        // set the IP address appropriately
+        if (0 == wcscmp(psw->swaExtraAddresses[ui].wzIP, L""))
+        {
+            hr = ::StringCchCopyW(wzIP, countof(wzIP), L"*"); // if no IP specified = add *
+        }
+        else
+        {
+#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
+            hr = ::StringCchCopyW(wzIP, countof(wzIP), psw->swaExtraAddresses[ui].wzIP); //else leave untouched
+        }
+        ExitOnFailure(hr, "Failed to copy web IP string");
+
+        hr = ::StringCchPrintfW(wzBinding, countof(wzBinding), L"%s:%d:%s", wzIP, psw->swaExtraAddresses[ui].iPort, psw->swaExtraAddresses[ui].wzHeader);
+        ExitOnFailure(hr, "Failed to copy web IP");
+
+        //create bindings for site
+        hr = ScaWriteConfigID(IIS_BINDING);
+        ExitOnFailure(hr, "Failed write binding ID");
+        hr = ScaWriteConfigID(IIS_CREATE);
+        ExitOnFailure(hr, "Failed write binding action");
+        hr = ScaWriteConfigString(psw->wzDescription);      //site name key
+        ExitOnFailure(hr, "Failed write binding web name");
+
+        if (psw->swaExtraAddresses[ui].fSecure)
+        {
+            hr = ScaWriteConfigString(L"https");            // binding protocol
+        }
+        else
+        {
+            hr = ScaWriteConfigString(L"http");             // binding protocol
+        }
+        ExitOnFailure(hr, "Failed write binding http(s)");
+
+        // write bindings CAData
+        hr = ScaWriteConfigString(wzBinding) ;              //binding info
+        ExitOnFailure(hr, "Failed write binding info");
+    }
+
+    // write the web dirproperties information
+    if (psw->fHasProperties)
+    {
+        // dir properties are for the default application of the web
+        // with location '/'
+        hr = ScaWriteWebDirProperties7(psw->wzDescription, L"/", &psw->swp);
+        ExitOnFailure(hr, "Failed to write web security information to metabase");
+    }
+
+    //// write the application information
+    if (psw->fHasApplication)
+    {
+        hr = ScaWriteWebApplication7(psw->wzDescription, L"/", &psw->swapp, psapList);
+        ExitOnFailure(hr, "Failed to write web application information to metabase");
+    }
+
+    // write the SSL certificate information
+    if (psw->pswscList)
+    {
+        hr = ScaSslCertificateWrite7(psw->wzDescription, psw->pswscList);
+        ExitOnFailure(hr, "Failed to write SSL certificates for Web site: %ls", psw->wzKey);
+    }
+
+    // write the headers
+    if (psw->pshhList)
+    {
+        hr = ScaWriteHttpHeader7(psw->wzDescription, L"/", psw->pshhList);
+        ExitOnFailure(hr, "Failed to write custom HTTP headers for Web site: %ls", psw->wzKey);
+    }
+
+    // write the errors
+    if (psw->psweList)
+    {
+        hr = ScaWriteWebError7(psw->wzDescription, L"/", psw->psweList);
+        ExitOnFailure(hr, "Failed to write custom web errors for Web site: %ls", psw->wzKey);
+    }
+
+    // write the log information to the metabase
+    if (psw->fHasLog)
+    {
+        hr = ScaWriteWebLog7(psw->wzDescription, &psw->swl);
+        ExitOnFailure(hr, "Failed to write web log information to metabase");
+    }
+
+LExit:
+    return hr;
+}
+
+
+static HRESULT ScaWebRemove7(
+    __in const SCA_WEB7* psw
+    )
+{
+    HRESULT hr = S_OK;
+
+    hr = ScaWriteConfigID(IIS_SITE);
+    ExitOnFailure(hr, "Failed write site ID");
+    hr = ScaWriteConfigID(IIS_DELETE);
+    ExitOnFailure(hr, "Failed write site action");
+    hr = ScaWriteConfigString(psw->wzDescription);  //Site Name
+    ExitOnFailure(hr, "Failed write site name");
+
+LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+#include "scawebapp.h"
+#include "scawebprop.h"
+#include "scahttpheader.h"
+#include "scaweberr.h"
+#include "scassl.h"
+#include "scaapppool.h"
+#include "scaweblog.h"
+
+// globals
+#define MAX_ADDRESSES_PER_WEB 10
+
+// structs
+struct SCA_WEB7
+{
+    // darwin information
+    WCHAR wzKey[MAX_DARWIN_KEY + 1];
+    WCHAR wzComponent[MAX_DARWIN_KEY + 1];
+    BOOL fHasComponent;
+    INSTALLSTATE isInstalled;
+    INSTALLSTATE isAction;
+
+    int iSiteId;
+
+    // metabase information
+    WCHAR wzWebBase[METADATA_MAX_NAME_LEN + 1];
+    BOOL fBaseExists;
+
+    // iis configuation information
+    SCA_WEB_ADDRESS swaBinding;
+
+    SCA_WEB_ADDRESS swaExtraAddresses[MAX_ADDRESSES_PER_WEB + 1];
+    DWORD cExtraAddresses;
+
+    WCHAR wzDirectory[MAX_PATH];
+    WCHAR wzDescription[MAX_DARWIN_COLUMN + 1];
+
+    int iState;
+    int iAttributes;
+
+    BOOL fHasProperties;
+    SCA_WEB_PROPERTIES swp;
+
+    BOOL fHasApplication;
+    SCA_WEB_APPLICATION swapp;
+
+    BOOL fHasSecurity;
+    int dwAccessPermissions;
+    int iConnectionTimeout;
+
+    SCA_WEB_SSL_CERTIFICATE* pswscList;
+    SCA_HTTP_HEADER* pshhList;
+    SCA_WEB_ERROR* psweList;
+
+    BOOL fHasLog;
+    SCA_WEB_LOG swl;
+
+    SCA_WEB7* pswNext;
+};
+
+
+// prototypes
+HRESULT ScaWebsRead7(
+    __in SCA_WEB7** ppswList,
+    __in SCA_HTTP_HEADER** ppshhList,
+    __in SCA_WEB_ERROR** ppsweList,
+    __in WCA_WRAPQUERY_HANDLE hUserQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
+    __in WCA_WRAPQUERY_HANDLE hSslCertQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebLogQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
+    __inout LPWSTR *ppwzCustomActionData
+    );
+
+HRESULT ScaWebsGetBase7(
+    __in SCA_WEB7* pswList,
+    __in LPCWSTR pswWebKey,
+    __out_ecount(cchDest) LPWSTR pswWeb,
+    __in DWORD_PTR cchDest
+    );
+
+HRESULT ScaWebsInstall7(
+    __in SCA_WEB7* pswList,
+    __in SCA_APPPOOL * psapList
+    );
+
+HRESULT ScaWebsUninstall7(
+    __in SCA_WEB7* pswList
+    );
+
+void ScaWebsFreeList7(
+    __in SCA_WEB7* pswHead
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+// sql queries
+enum eWebApplicationQuery { wappqName = 1, wappqIsolation, wappqAllowSession,
+                            wappqSessionTimeout, wappqBuffer, wappqParentPaths,
+                            wappqDefaultScript, wappqScriptTimeout,
+                            wappqServerDebugging, wappqClientDebugging, wappqAppPool, wappqApplication};
+
+
+HRESULT ScaGetWebApplication(MSIHANDLE /*hViewApplications*/, 
+                             LPCWSTR pwzApplication,
+                             __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
+                             __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
+                             SCA_WEB_APPLICATION* pswapp)
+{
+    HRESULT hr = S_OK;
+
+    MSIHANDLE hRec;
+    LPWSTR pwzData = NULL;
+
+    // Reset back to the first record
+    WcaFetchWrappedReset(hWebAppQuery);
+
+    // get the application information
+    hr = WcaFetchWrappedRecordWhereString(hWebAppQuery, wappqApplication, pwzApplication, &hRec);
+    if (S_OK == hr)
+    {
+        // application name
+        hr = WcaGetRecordString(hRec, wappqName, &pwzData);
+        ExitOnFailure(hr, "Failed to get Name of App");
+        hr = ::StringCchCopyW(pswapp->wzName, countof(pswapp->wzName), pwzData);
+        if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr)
+        {
+            // The application name is sometimes truncated to IIS's supported length, so ignore insufficient buffer errors here
+            WcaLog(LOGMSG_VERBOSE, "Application name \"%ls\" truncated to fit IIS's supported %d-character length", pwzData, MAX_APP_NAME);
+            hr = S_OK;
+        }
+        ExitOnFailure(hr, "Failed to copy name string to webapp object");
+
+        hr = WcaGetRecordInteger(hRec, wappqIsolation, &pswapp->iIsolation);
+        ExitOnFailure(hr, "Failed to get App isolation: '%ls'", pswapp->wzName);
+
+        hr = WcaGetRecordInteger(hRec, wappqAllowSession, &pswapp->fAllowSessionState);
+
+        hr = WcaGetRecordInteger(hRec, wappqSessionTimeout, &pswapp->iSessionTimeout);
+
+        hr = WcaGetRecordInteger(hRec, wappqBuffer, &pswapp->fBuffer);
+
+        hr = WcaGetRecordInteger(hRec, wappqParentPaths, &pswapp->fParentPaths);
+
+        hr = WcaGetRecordString(hRec, wappqDefaultScript, &pwzData);
+        ExitOnFailure(hr, "Failed to get default scripting language for App: '%ls'", pswapp->wzName);
+        hr = ::StringCchCopyW(pswapp->wzDefaultScript, countof(pswapp->wzDefaultScript), pwzData);
+        ExitOnFailure(hr, "Failed to copy default script string to webapp object");
+
+        // asp script timeout
+        hr = WcaGetRecordInteger(hRec, wappqScriptTimeout, &pswapp->iScriptTimeout);
+        ExitOnFailure(hr, "Failed to get scripting timeout for App: '%ls'", pswapp->wzName);
+
+        // asp server-side script debugging
+        hr = WcaGetRecordInteger(hRec, wappqServerDebugging, &pswapp->fServerDebugging);
+
+        // asp client-side script debugging
+        hr = WcaGetRecordInteger(hRec, wappqClientDebugging, &pswapp->fClientDebugging);
+
+        hr = WcaGetRecordString(hRec, wappqAppPool, &pwzData);
+        ExitOnFailure(hr, "Failed to get AppPool for App: '%ls'", pswapp->wzName);
+        hr = ::StringCchCopyW(pswapp->wzAppPool, countof(pswapp->wzAppPool), pwzData);
+        ExitOnFailure(hr, "failed to copy AppPool: '%ls' for App: '%ls'", pwzData, pswapp->wzName);
+
+        // app extensions
+         hr = ScaWebAppExtensionsRead(pwzApplication, hWebAppExtQuery, &pswapp->pswappextList);
+        ExitOnFailure(hr, "Failed to read AppExtensions for App: '%ls'", pswapp->wzName);
+
+        hr = S_OK;
+    }
+    else if (E_NOMOREITEMS == hr)
+    {
+        WcaLog(LOGMSG_STANDARD, "Error: Cannot locate IIsWebApplication.Application='%ls'", pwzApplication);
+        hr = E_FAIL;
+    }
+    else
+        ExitOnFailure(hr, "Error matching Application rows");
+
+    // Let's check that there isn't more than one record found - if there is, throw an assert like WcaFetchSingleRecord() would
+    HRESULT hrTemp = WcaFetchWrappedRecordWhereString(hWebAppQuery, wappqApplication, pwzApplication, &hRec);
+    if (SUCCEEDED(hrTemp))
+    {
+        AssertSz(E_NOMOREITEMS == hrTemp, "ScaGetWebApplication found more than one record");
+    }
+
+LExit:
+    ReleaseStr(pwzData);
+
+    return hr;
+}
+
+
+HRESULT ScaWriteWebApplication(IMSAdminBase* piMetabase, LPCWSTR wzRootOfWeb, 
+                               SCA_WEB_APPLICATION* pswapp, SCA_APPPOOL * psapList)
+{
+    HRESULT hr = S_OK;
+    WCHAR wzAppPoolName[MAX_PATH];
+
+    hr = ScaCreateApp(piMetabase, wzRootOfWeb, pswapp->iIsolation);
+    ExitOnFailure(hr, "Failed to create ASP App");
+
+    // Medium Isolation seems to have to be set through the metabase
+    if (2 == pswapp->iIsolation)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_APP_ISOLATED, METADATA_INHERIT, IIS_MD_UT_WAM, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->iIsolation));
+        ExitOnFailure(hr, "Failed to write isolation value for App: '%ls'", pswapp->wzName);
+    }
+
+    // application name
+    hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_APP_FRIENDLY_NAME, METADATA_INHERIT, IIS_MD_UT_WAM, STRING_METADATA, pswapp->wzName);
+    ExitOnFailure(hr, "Failed to write Name of App: '%ls'", pswapp->wzName);
+
+    // allow session state
+    if (MSI_NULL_INTEGER != pswapp->fAllowSessionState)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_ALLOWSESSIONSTATE, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->fAllowSessionState));
+        ExitOnFailure(hr, "Failed to write allow session information for App: '%ls'", pswapp->wzName);
+    }
+
+    // session timeout
+    if (MSI_NULL_INTEGER != pswapp->iSessionTimeout)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_SESSIONTIMEOUT, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->iSessionTimeout));
+        ExitOnFailure(hr, "Failed to write session timeout for App: '%ls'", pswapp->wzName);
+    }
+
+    // asp buffering
+    if (MSI_NULL_INTEGER != pswapp->fBuffer)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_BUFFERINGON, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->fBuffer));
+        ExitOnFailure(hr, "Failed to write buffering flag for App: '%ls'", pswapp->wzName);
+    }
+
+    // asp parent paths
+    if (MSI_NULL_INTEGER != pswapp->fParentPaths)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_ENABLEPARENTPATHS, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->fParentPaths));
+        ExitOnFailure(hr, "Failed to write parent paths flag for App: '%ls'", pswapp->wzName);
+    }
+
+    // default scripting language
+    if (*pswapp->wzDefaultScript)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_SCRIPTLANGUAGE, METADATA_INHERIT, ASP_MD_UT_APP, STRING_METADATA, pswapp->wzDefaultScript);
+        ExitOnFailure(hr, "Failed to write default scripting language for App: '%ls'", pswapp->wzName);
+    }
+
+    // asp script timeout
+    if (MSI_NULL_INTEGER != pswapp->iScriptTimeout)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_SCRIPTTIMEOUT, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->iScriptTimeout));
+        ExitOnFailure(hr, "Failed to write script timeout for App: '%ls'", pswapp->wzName);
+    }
+
+    // asp server-side script debugging
+    if (MSI_NULL_INTEGER != pswapp->fServerDebugging)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_ENABLESERVERDEBUG, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->fServerDebugging));
+        ExitOnFailure(hr, "Failed to write ASP server-side script debugging flag for App: '%ls'", pswapp->wzName);
+    }
+
+    // asp server-side script debugging
+    if (MSI_NULL_INTEGER != pswapp->fClientDebugging)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_ENABLECLIENTDEBUG, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswapp->fClientDebugging));
+        ExitOnFailure(hr, "Failed to write ASP client-side script debugging flag for App: '%ls'", pswapp->wzName);
+    }
+
+    // AppPool
+    if (*pswapp->wzAppPool && NULL != psapList)
+    {
+        hr = ScaFindAppPool(piMetabase, pswapp->wzAppPool, wzAppPoolName, countof(wzAppPoolName), psapList);
+        ExitOnFailure(hr, "failed to find app pool: %ls", pswapp->wzAppPool);
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_APP_APPPOOL_ID, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, wzAppPoolName);
+        ExitOnFailure(hr, "Failed to write default AppPool for App: '%ls'", pswapp->wzName);
+    }
+
+    if (pswapp->pswappextList)
+    {
+        hr = ScaWebAppExtensionsWrite(piMetabase, wzRootOfWeb, pswapp->pswappextList);
+        ExitOnFailure(hr, "Failed to write AppExtensions for App: '%ls'", pswapp->wzName);
+    }
+
+LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+#include "scaapppool.h"
+#include "scawebappext.h"
+
+// global sql queries provided for optimization
+extern LPCWSTR vcsWebApplicationQuery;
+const int MAX_APP_NAME = 255;
+
+// structs
+struct SCA_WEB_APPLICATION
+{
+	WCHAR wzName[MAX_APP_NAME + 1];
+
+	int iIsolation;
+	BOOL fAllowSessionState;
+	int iSessionTimeout;
+	BOOL fBuffer;
+	BOOL fParentPaths;
+
+	WCHAR wzDefaultScript[MAX_DARWIN_COLUMN + 1];
+	int iScriptTimeout;
+	BOOL fServerDebugging;
+	BOOL fClientDebugging;
+	WCHAR wzAppPool[MAX_DARWIN_COLUMN + 1];
+
+	SCA_WEB_APPLICATION_EXTENSION* pswappextList;
+};
+
+
+// prototypes
+HRESULT ScaGetWebApplication(MSIHANDLE hViewApplications, 
+                             LPCWSTR pwzApplication,
+                             __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
+                             __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
+                             SCA_WEB_APPLICATION* pswapp);
+
+HRESULT ScaWriteWebApplication(IMSAdminBase* piMetabase, LPCWSTR wzRootOfWeb, 
+                               SCA_WEB_APPLICATION* pswapp, SCA_APPPOOL * psapList);
+
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 @@
+// 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.
+
+#include "precomp.h"
+HRESULT ScaWriteWebApplication7(
+    __in_z LPCWSTR wzWebName,
+    __in_z LPCWSTR wzRootOfWeb,
+    SCA_WEB_APPLICATION* pswapp,
+    SCA_APPPOOL * /*psapList*/
+    )
+{
+    HRESULT hr = S_OK;
+
+    //all go to same web/root location tag
+    hr = ScaWriteConfigID(IIS_ASP_BEGIN);
+    ExitOnFailure(hr, "Failed to write WebApp ASP begin id");
+    hr = ScaWriteConfigString(wzWebName);                //site name key
+    ExitOnFailure(hr, "Failed to write app web key");
+    hr = ScaWriteConfigString(wzRootOfWeb);               //app path key
+    ExitOnFailure(hr, "Failed to write app web root");
+
+    // IIS7 Not Supported: Isolation
+    if (MSI_NULL_INTEGER != pswapp->iIsolation)
+    {
+        WcaLog(LOGMSG_TRACEONLY, "Not supported by IIS7: Isolation Mode, ignoring");
+    }
+
+    // allow session state
+    if (MSI_NULL_INTEGER != pswapp->fAllowSessionState)
+    {
+        //system.webServer/asp /session | allowSessionState
+        hr = ScaWriteConfigID(IIS_ASP_SESSIONSTATE);
+        ExitOnFailure(hr, "Failed to write WebApp ASP sessionstate id");
+        hr = ScaWriteConfigInteger(pswapp->fAllowSessionState);
+        ExitOnFailure(hr, "Failed to write allow session information for App: '%ls'", pswapp->wzName);
+    }
+
+    // session timeout
+    if (MSI_NULL_INTEGER != pswapp->iSessionTimeout)
+    {
+        //system.webServer/asp /session | timeout
+        hr = ScaWriteConfigID(IIS_ASP_SESSIONTIMEOUT);
+        ExitOnFailure(hr, "Failed to write WebApp ASP sessiontimepot id");
+        hr = ScaWriteConfigInteger(pswapp->iSessionTimeout);
+        ExitOnFailure(hr, "Failed to write session timeout for App: '%ls'", pswapp->wzName);
+    }
+
+    // asp buffering
+    if (MSI_NULL_INTEGER != pswapp->fBuffer)
+    {
+        //system.webServer/asp | bufferingOn
+        hr = ScaWriteConfigID(IIS_ASP_BUFFER);
+        ExitOnFailure(hr, "Failed to write WebApp ASP buffer id");
+        hr = ScaWriteConfigInteger(pswapp->fBuffer);
+        ExitOnFailure(hr, "Failed to write buffering flag for App: '%ls'", pswapp->wzName);
+    }
+
+    // asp parent paths
+    if (MSI_NULL_INTEGER != pswapp->fParentPaths)
+    {
+        //system.webServer/asp | enableParentPaths
+        hr = ScaWriteConfigID(IIS_ASP_PARENTPATHS);
+        ExitOnFailure(hr, "Failed to write WebApp ASP parentpaths id");
+        hr = ScaWriteConfigInteger(pswapp->fParentPaths);
+        ExitOnFailure(hr, "Failed to write parent paths flag for App: '%ls'", pswapp->wzName);
+    }
+
+    // default scripting language
+    if (*pswapp->wzDefaultScript)
+    {
+        //system.webServer/asp | scriptLanguage
+        hr = ScaWriteConfigID(IIS_ASP_SCRIPTLANG);
+        ExitOnFailure(hr, "Failed to write WebApp ASP script lang id");
+        hr = ScaWriteConfigString(pswapp->wzDefaultScript);
+        ExitOnFailure(hr, "Failed to write default scripting language for App: '%ls'", pswapp->wzName);
+    }
+
+    // asp script timeout
+    if (MSI_NULL_INTEGER != pswapp->iScriptTimeout)
+    {
+        //system.webServer/asp /limits | scriptTimeout
+        hr = ScaWriteConfigID(IIS_ASP_SCRIPTTIMEOUT);
+        ExitOnFailure(hr, "Failed to write WebApp ASP script timeout id");
+        hr = ScaWriteConfigInteger(pswapp->iScriptTimeout);
+        ExitOnFailure(hr, "Failed to write script timeout for App: '%ls'", pswapp->wzName);
+    }
+
+    // asp server-side script debugging
+    if (MSI_NULL_INTEGER != pswapp->fServerDebugging)
+    {
+        //system.webServer/asp | appAllowDebugging
+        hr = ScaWriteConfigID(IIS_ASP_SCRIPTSERVERDEBUG);
+        ExitOnFailure(hr, "Failed to write WebApp ASP script debug id");
+        hr = ScaWriteConfigInteger(pswapp->fServerDebugging);
+        ExitOnFailure(hr, "Failed to write ASP server-side script debugging flag for App: '%ls'", pswapp->wzName);
+    }
+
+    // asp client-side script debugging
+    if (MSI_NULL_INTEGER != pswapp->fClientDebugging)
+    {
+        //system.webServer/asp | appAllowClientDebug
+        hr = ScaWriteConfigID(IIS_ASP_SCRIPTCLIENTDEBUG);
+        ExitOnFailure(hr, "Failed to write WebApp ASP script debug id");
+        hr = ScaWriteConfigInteger(pswapp->fClientDebugging);
+        ExitOnFailure(hr, "Failed to write ASP client-side script debugging flag for App: '%ls'", pswapp->wzName);
+    }
+
+    //done with ASP application properties
+    hr = ScaWriteConfigID(IIS_ASP_END);
+    ExitOnFailure(hr, "Failed to write WebApp ASP begin id");
+
+    //write out app estensions
+    if (pswapp->pswappextList)
+    {
+        hr = ScaWebAppExtensionsWrite7(wzWebName, wzRootOfWeb, pswapp->pswappextList);
+        ExitOnFailure(hr, "Failed to write AppExtensions for App: '%ls'", pswapp->wzName);
+    }
+
+LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+HRESULT ScaWriteWebApplication7(
+    __in_z LPCWSTR wzWebName,
+    __in_z LPCWSTR wzRootOfWeb,
+    SCA_WEB_APPLICATION* pswapp,
+    SCA_APPPOOL * psapList
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+enum eWebAppExtensionQuery { wappextqExtension = 1, wappextqVerbs, wappextqExecutable, wappextqAttributes, wappextqApplication };
+
+// prototypes for private helper functions
+static HRESULT NewAppExt(
+    __out SCA_WEB_APPLICATION_EXTENSION** ppswappext
+    );
+static SCA_WEB_APPLICATION_EXTENSION* AddAppExtToList(
+    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList,
+    __in SCA_WEB_APPLICATION_EXTENSION* pswappext
+    );
+
+
+
+HRESULT ScaWebAppExtensionsRead(
+    __in LPCWSTR wzApplication,
+    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
+    __inout SCA_WEB_APPLICATION_EXTENSION** ppswappextList
+    )
+{
+    HRESULT hr = S_OK;
+    MSIHANDLE hRec;
+
+    SCA_WEB_APPLICATION_EXTENSION* pswappext = NULL;
+    LPWSTR pwzData = NULL;
+
+    // Reset back to the first record
+    WcaFetchWrappedReset(hWebAppExtQuery);
+
+    // get the application extension information
+    while (S_OK == (hr = WcaFetchWrappedRecordWhereString(hWebAppExtQuery, wappextqApplication, wzApplication, &hRec)))
+    {
+        hr = NewAppExt(&pswappext);
+        ExitOnFailure(hr, "failed to create new web app extension");
+
+        // get the extension
+        hr = WcaGetRecordString(hRec, wappextqExtension, &pwzData);
+        ExitOnFailure(hr, "Failed to get Web Application Extension");
+        hr = ::StringCchCopyW(pswappext->wzExtension, countof(pswappext->wzExtension), pwzData);
+        ExitOnFailure(hr, "Failed to copy extension string to webappext object");
+
+        // application extension verbs
+        hr = WcaGetRecordString(hRec, wappextqVerbs, &pwzData);
+        ExitOnFailure(hr, "Failed to get Verbs for Application: '%ls'", wzApplication);
+        hr = ::StringCchCopyW(pswappext->wzVerbs, countof(pswappext->wzVerbs), pwzData);
+        ExitOnFailure(hr, "Failed to copy verbs string to webappext object");
+
+        // extension executeable
+        hr = WcaGetRecordString(hRec, wappextqExecutable, &pwzData);
+        ExitOnFailure(hr, "Failed to get Executable for Application: '%ls'", wzApplication);
+        hr = ::StringCchCopyW(pswappext->wzExecutable, countof(pswappext->wzExecutable), pwzData);
+        ExitOnFailure(hr, "Failed to copy executable string to webappext object");
+
+        hr = WcaGetRecordInteger(hRec, wappextqAttributes, &pswappext->iAttributes);
+        if (S_FALSE == hr)
+        {
+            pswappext->iAttributes = 0;
+            hr = S_OK;
+        }
+        ExitOnFailure(hr, "Failed to get App isolation");
+
+        *ppswappextList = AddAppExtToList(*ppswappextList, pswappext);
+        pswappext = NULL; // set the appext NULL so it doesn't accidentally get freed below
+    }
+
+    if (E_NOMOREITEMS == hr)
+    {
+        hr = S_OK;
+    }
+
+LExit:
+    // if anything was left over after an error clean it all up
+    if (pswappext)
+    {
+        ScaWebAppExtensionsFreeList(pswappext);
+    }
+
+    ReleaseStr(pwzData);
+
+    return hr;
+}
+
+
+
+HRESULT ScaWebAppExtensionsWrite(
+    __in IMSAdminBase* piMetabase,
+    __in LPCWSTR wzRootOfWeb,
+    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList
+    )
+{
+    HRESULT hr = S_OK;
+
+    LPWSTR wzAppExt = NULL;
+    DWORD cchAppExt;
+    WCHAR wzAppExtension[1024];
+    WCHAR wzAppExtensions[65536];
+    SCA_WEB_APPLICATION_EXTENSION* pswappext = NULL;
+
+    if (!pswappextList)
+    {
+        ExitFunction();
+    }
+
+    ::ZeroMemory(wzAppExtensions, sizeof(wzAppExtensions));
+    wzAppExt = wzAppExtensions;
+    cchAppExt = countof(wzAppExtensions);
+    pswappext = pswappextList;
+
+    while (pswappext)
+    {
+        // if all (represented by "*" or blank)
+        if (0 == lstrcmpW(pswappext->wzExtension, L"*") || 0 == lstrlenW(pswappext->wzExtension))
+        {
+            hr = ::StringCchPrintfW(wzAppExtension, countof(wzAppExtension), L"*,%s,%d", pswappext->wzExecutable, pswappext->iAttributes);
+            ExitOnFailure(hr, "Failed to format *,executable,attributes string");
+        }
+        else
+        {
+            hr = ::StringCchPrintfW(wzAppExtension, countof(wzAppExtension), L".%s,%s,%d", pswappext->wzExtension, pswappext->wzExecutable, pswappext->iAttributes);
+            ExitOnFailure(hr, "Failed to format extension,executable,attributes string");
+        }
+
+        // if verbs were specified and not the keyword "all"
+        if (pswappext->wzVerbs[0] && CSTR_EQUAL != CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pswappext->wzVerbs, -1, L"all", -1))
+        {
+            hr = ::StringCchCatW(wzAppExtension, countof(wzAppExtension), L",");
+            ExitOnFailure(hr, "Failed to concatenate comma to app extension string");
+            hr = ::StringCchCatW(wzAppExtension, countof(wzAppExtension), pswappext->wzVerbs);
+            ExitOnFailure(hr, "Failed to concatenate verb to app extension string");
+        }
+
+        hr = ::StringCchCopyW(wzAppExt, cchAppExt, wzAppExtension);
+        ExitOnFailure(hr, "Failed to copy app extension string");
+        wzAppExt += lstrlenW(wzAppExtension) + 1;
+        cchAppExt -= lstrlenW(wzAppExtension) + 1;
+        pswappext = pswappext->pswappextNext;
+    }
+
+    if (*wzAppExtensions)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_SCRIPT_MAPS, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, wzAppExtensions);
+        ExitOnFailure(hr, "Failed to write AppExtension: '%ls'", wzAppExtension);
+    }
+
+LExit:
+    return hr;
+}
+
+
+void ScaWebAppExtensionsFreeList(
+    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList
+    )
+{
+    SCA_WEB_APPLICATION_EXTENSION* pswappextDelete = pswappextList;
+    while (pswappextList)
+    {
+        pswappextDelete = pswappextList;
+        pswappextList = pswappextList->pswappextNext;
+
+        MemFree(pswappextDelete);
+    }
+}
+
+
+
+// private helper functions
+
+static HRESULT NewAppExt(
+    __out SCA_WEB_APPLICATION_EXTENSION** ppswappext
+    )
+{
+    HRESULT hr = S_OK;
+    SCA_WEB_APPLICATION_EXTENSION* pswappext = static_cast<SCA_WEB_APPLICATION_EXTENSION*>(MemAlloc(sizeof(SCA_WEB_APPLICATION_EXTENSION), TRUE));
+    ExitOnNull(pswappext, hr, E_OUTOFMEMORY, "failed to allocate memory for new web app ext element");
+
+    *ppswappext = pswappext;
+
+LExit:
+    return hr;
+}
+
+
+static SCA_WEB_APPLICATION_EXTENSION* AddAppExtToList(
+    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList,
+    __in SCA_WEB_APPLICATION_EXTENSION* pswappext
+    )
+{
+    if (pswappextList)
+    {
+        SCA_WEB_APPLICATION_EXTENSION* pswappextT = pswappextList;
+        while (pswappextT->pswappextNext)
+        {
+            pswappextT = pswappextT->pswappextNext;
+        }
+
+        pswappextT->pswappextNext = pswappext;
+    }
+    else
+    {
+        pswappextList = pswappext;
+    }
+
+    return pswappextList;
+}
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 @@
+#pragma once
+// 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.
+
+
+struct SCA_WEB_APPLICATION_EXTENSION
+{
+    WCHAR wzExtension[MAX_DARWIN_COLUMN + 1];
+
+    WCHAR wzVerbs[MAX_DARWIN_COLUMN + 1];
+    WCHAR wzExecutable[MAX_DARWIN_COLUMN + 1];
+    int iAttributes;
+
+    SCA_WEB_APPLICATION_EXTENSION* pswappextNext;
+};
+
+
+// prototypes
+HRESULT ScaWebAppExtensionsRead(
+    __in LPCWSTR wzApplication,
+    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
+    __inout SCA_WEB_APPLICATION_EXTENSION** ppswappextList
+    );
+
+HRESULT ScaWebAppExtensionsWrite(
+    __in IMSAdminBase* piMetabase,
+    __in LPCWSTR wzRootOfWeb,
+    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList
+    );
+
+void ScaWebAppExtensionsFreeList(
+    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+HRESULT ScaWebAppExtensionsWrite7(
+    __in_z LPCWSTR wzWebName,
+    __in_z LPCWSTR wzRootOfWeb,
+    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList
+    )
+{
+    HRESULT hr = S_OK;
+    SCA_WEB_APPLICATION_EXTENSION* pswappext = NULL;
+
+    if (!pswappextList)
+    {
+        ExitFunction1(hr = S_OK);
+    }
+
+    //create the Extension for this vdir application
+    //all go to same web/root location tag
+    hr = ScaWriteConfigID(IIS_APPEXT_BEGIN);
+    ExitOnFailure(hr, "Failed to write webappext begin id");
+    hr = ScaWriteConfigString(wzWebName);                //site name key
+    ExitOnFailure(hr, "Failed to write app web key");
+    hr = ScaWriteConfigString(wzRootOfWeb);               //app path key
+    ExitOnFailure(hr, "Failed to write app web key");
+
+    pswappext = pswappextList;
+
+    while (pswappext)
+    {
+        //create the Extension for this vdir application
+        hr = ScaWriteConfigID(IIS_APPEXT);
+        ExitOnFailure(hr, "Failed to write webappext begin id");
+
+        if (*pswappext->wzExtension)
+        {
+            hr = ScaWriteConfigString(pswappext->wzExtension);
+        }
+        else   // blank means "*" (all)
+        {
+            hr = ScaWriteConfigString(L"*");
+        }
+        ExitOnFailure(hr, "Failed to write extension");
+
+        hr = ScaWriteConfigString(pswappext->wzExecutable);
+        ExitOnFailure(hr, "Failed to write extension executable");
+
+        hr = ScaWriteConfigString(pswappext->wzVerbs);
+        ExitOnFailure(hr, "Failed to write extension verbs");
+
+        pswappext = pswappext->pswappextNext;
+    }
+
+    hr = ScaWriteConfigID(IIS_APPEXT_END);
+    ExitOnFailure(hr, "Failed to write webappext begin id");
+
+LExit:
+    return hr;
+}
+
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 @@
+#pragma once
+// 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.
+
+
+HRESULT ScaWebAppExtensionsWrite7(
+    __in_z LPCWSTR wzWebName,
+    __in_z LPCWSTR wzRootOfWeb,
+    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+// sql queries
+enum eWebDirQuery { wdqWeb = 1, wdqWebDir, wdqComponent , wdqPath, wdqProperties, wdqApplication, wdqInstalled, wdqAction };
+
+// prototypes
+static void AddWebDirToList(SCA_WEBDIR** ppswdList, SCA_WEBDIR *pswd);
+
+static SCA_WEBDIR* NewWebDir();
+static void FreeWebDir(SCA_WEBDIR *pswd);
+
+
+UINT __stdcall ScaWebDirsRead(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_WEB* pswList,
+    __in WCA_WRAPQUERY_HANDLE hUserQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebBaseQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
+    __inout LPWSTR *ppwzCustomActionData,
+    __out SCA_WEBDIR** ppswdList
+    )
+{
+    Assert(piMetabase && ppswdList);
+
+    HRESULT hr = S_OK;
+    MSIHANDLE hRec;
+
+    LPWSTR pwzData = NULL;
+    SCA_WEBDIR* pswd;
+    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
+
+    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap query for ScaWebDirsRead");
+
+    if (0 == WcaGetQueryRecords(hWrapQuery))
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ScaInstallWebDirs() because IIsWebDir table not present");
+        ExitFunction1(hr = S_FALSE);
+    }
+
+    // loop through all the web directories
+    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
+    {
+        pswd = NewWebDir();
+        ExitOnNull(pswd, hr, E_OUTOFMEMORY, "Failed to allocate memory for web dir object in memory");
+
+        // get component install state
+        hr = WcaGetRecordString(hRec, wdqComponent, &pwzData);
+        ExitOnFailure(hr, "Failed to get Component for WebDirs");
+        hr = ::StringCchCopyW(pswd->wzComponent, countof(pswd->wzComponent), pwzData);
+        ExitOnFailure(hr, "Failed to copy component string to webdir object");
+
+        hr = WcaGetRecordInteger(hRec, wdqInstalled, (int *)&pswd->isInstalled);
+        ExitOnFailure(hr, "Failed to get Component installed state for webdir");
+
+        hr = WcaGetRecordInteger(hRec, wdqAction, (int *)&pswd->isAction);
+        ExitOnFailure(hr, "Failed to get Component action state for webdir");
+
+        // If this record has a component and no action is being taken for it, skip processing it entirely
+        if (0 < lstrlenW(pswd->wzComponent) && !WcaIsInstalling(pswd->isInstalled, pswd->isAction)
+            && !WcaIsUninstalling(pswd->isInstalled, pswd->isAction) && !WcaIsReInstalling(pswd->isInstalled, pswd->isAction))
+        {
+            FreeWebDir(pswd);
+            pswd = NULL;
+            continue;
+        }
+
+        hr = WcaGetRecordString(hRec, wdqWeb, &pwzData);
+        ExitOnFailure(hr, "Failed to get Web for WebDir");
+
+        hr = ScaWebsGetBase(piMetabase, pswList, pwzData, pswd->wzWebBase, countof(pswd->wzWebBase), hWebBaseQuery);
+        if (WcaIsUninstalling(pswd->isInstalled, pswd->isAction))
+        {
+            // If we're uninstalling, ignore any failure to find the existing web
+            hr = S_OK;
+        }
+
+        ExitOnFailure(hr, "Failed to get base of web for WebDir");
+
+        hr = WcaGetRecordString(hRec, wdqPath, &pwzData);
+        ExitOnFailure(hr, "Failed to get Path for WebDir");
+
+        hr = ::StringCchPrintfW(pswd->wzWebDirRoot, countof(pswd->wzWebDirRoot), L"%s/Root/%s", pswd->wzWebBase, pwzData);
+        ExitOnFailure(hr, "Failed to format webdir root string");
+
+        // get the directory properties for this web
+        hr = WcaGetRecordString(hRec, wdqProperties, &pwzData);
+        ExitOnFailure(hr, "Failed to get security identifier for WebDir");
+        if (*pwzData)
+        {
+            hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &pswd->swp);
+            ExitOnFailure(hr, "Failed to get properties for WebDir");
+
+            pswd->fHasProperties = TRUE;
+        }
+
+        // get the application information for this web directory
+        hr = WcaGetRecordString(hRec, wdqApplication, &pwzData);
+        ExitOnFailure(hr, "Failed to get application identifier for WebDir");
+        if (*pwzData)
+        {
+            hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &pswd->swapp);
+            ExitOnFailure(hr, "Failed to get application for WebDir");
+
+            pswd->fHasApplication = TRUE;
+        }
+
+        AddWebDirToList(ppswdList, pswd);
+    }
+
+    if (E_NOMOREITEMS == hr)
+    {
+        hr = S_OK;
+    }
+    ExitOnFailure(hr, "Failure while processing WebDirs");
+
+LExit:
+    WcaFinishUnwrapQuery(hWrapQuery);
+
+    ReleaseStr(pwzData);
+
+    return hr;
+}
+
+
+HRESULT ScaWebDirsInstall(IMSAdminBase* piMetabase, SCA_WEBDIR* pswdList, SCA_APPPOOL * psapList)
+{
+    HRESULT hr = S_OK;
+    SCA_WEBDIR* pswd = pswdList;
+    int i;
+
+    while (pswd)
+    {
+        // On reinstall, we have to uninstall the old application, otherwise a duplicate will be created
+        if (WcaIsReInstalling(pswd->isInstalled, pswd->isAction))
+        {
+            if (pswd->fHasApplication)
+            {
+                hr = ScaDeleteApp(piMetabase, pswd->wzWebDirRoot);
+                ExitOnFailure(hr, "Failed to remove application for WebDir as part of a reinstall");
+            }
+        }
+
+        // if we are installing the web site
+        if (WcaIsInstalling(pswd->isInstalled, pswd->isAction))
+        {
+            hr = ScaCreateMetabaseKey(piMetabase, pswd->wzWebDirRoot, L"");
+            ExitOnFailure(hr, "Failed to create key for WebDir");
+            hr = ScaWriteMetabaseValue(piMetabase, pswd->wzWebDirRoot, L"", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsWebDirectory");
+            ExitOnFailure(hr, "Failed to write key type for for WebDir");
+            i = 0x4000003e; // 1073741886: default directory browsing rights
+            hr = ScaWriteMetabaseValue(piMetabase, pswd->wzWebDirRoot, L"", MD_DIRECTORY_BROWSING, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)i));
+            ExitOnFailure(hr, "Failed to set directory browsing for WebDir");
+
+            // get the security information for this web
+            if (pswd->fHasProperties)
+            {
+                ScaWriteWebDirProperties(piMetabase, pswd->wzWebDirRoot, &pswd->swp);
+                ExitOnFailure(hr, "Failed to write properties for WebDir");
+            }
+
+            // get the application information for this web directory
+            if (pswd->fHasApplication)
+            {
+                hr = ScaWriteWebApplication(piMetabase, pswd->wzWebDirRoot, &pswd->swapp, psapList);
+                ExitOnFailure(hr, "Failed to write application for WebDir");
+            }
+        }
+
+        pswd = pswd->pswdNext;
+    }
+
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaWebDirsUninstall(IMSAdminBase* piMetabase, SCA_WEBDIR* pswdList)
+{
+    Assert(piMetabase);
+
+    HRESULT hr = S_OK;
+    SCA_WEBDIR* pswd = pswdList;
+
+    while (pswd)
+    {
+        if (WcaIsUninstalling(pswd->isInstalled, pswd->isAction))
+        {
+            // remove the application from this web directory
+            if (pswd->fHasApplication)
+            {
+                hr = ScaDeleteApp(piMetabase, pswd->wzWebDirRoot);
+                ExitOnFailure(hr, "Failed to remove application for WebDir");
+            }
+
+            hr = ScaDeleteMetabaseKey(piMetabase, pswd->wzWebDirRoot, L"");
+            ExitOnFailure(hr, "Failed to remove WebDir '%ls' from metabase", pswd->wzKey);
+        }
+
+        pswd = pswd->pswdNext;
+    }
+
+LExit:
+    return hr;
+}
+
+
+static SCA_WEBDIR* NewWebDir()
+{
+    SCA_WEBDIR* pswd = static_cast<SCA_WEBDIR*>(MemAlloc(sizeof(SCA_WEBDIR), TRUE));
+    Assert(pswd);
+    return pswd;
+}
+
+static void FreeWebDir(SCA_WEBDIR *pswd)
+{
+    MemFree(pswd);
+}
+
+void ScaWebDirsFreeList(SCA_WEBDIR* pswdList)
+{
+    SCA_WEBDIR* pswdDelete = pswdList;
+    while (pswdList)
+    {
+        pswdDelete = pswdList;
+        pswdList = pswdList->pswdNext;
+
+        FreeWebDir(pswdDelete);
+    }
+}
+
+
+static void AddWebDirToList(SCA_WEBDIR** ppswdList, SCA_WEBDIR *pswd)
+{
+    pswd->pswdNext = *ppswdList;
+    *ppswdList = pswd;
+}
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 @@
+#pragma once
+// 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.
+
+
+struct SCA_WEBDIR
+{
+    // darwin information
+    WCHAR wzKey[MAX_DARWIN_KEY + 1];
+    WCHAR wzComponent[MAX_DARWIN_KEY + 1];
+    INSTALLSTATE isInstalled;
+    INSTALLSTATE isAction;
+
+    // metabase information
+    WCHAR wzWebKey[MAX_DARWIN_KEY + 1];
+    WCHAR wzWebBase[METADATA_MAX_NAME_LEN + 1];
+    WCHAR wzWebDirRoot[METADATA_MAX_NAME_LEN + 1];
+
+    // iis configuation information
+    WCHAR wzDirectory[MAX_PATH];
+
+    BOOL fHasProperties;
+    SCA_WEB_PROPERTIES swp;
+
+    BOOL fHasApplication;
+    SCA_WEB_APPLICATION swapp;
+
+    SCA_WEBDIR* pswdNext;
+};
+
+
+// prototypes
+UINT __stdcall ScaWebDirsRead(
+    __in IMSAdminBase* piMetabase, 
+    __in SCA_WEB* pswList,
+    __in WCA_WRAPQUERY_HANDLE hUserQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebBaseQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
+    __inout LPWSTR *ppwzCustomActionData,
+    __out SCA_WEBDIR** ppswdList
+    );
+
+HRESULT ScaWebDirsInstall(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_WEBDIR* pswdList,
+    __in SCA_APPPOOL* psapList
+    );
+
+HRESULT ScaWebDirsUninstall(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_WEBDIR* pswdList
+    );
+
+void ScaWebDirsFreeList(
+    __in SCA_WEBDIR* pswdList
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+// sql queries
+static LPCWSTR vcsWebDirQuery7 = L"SELECT `Web_`, `WebDir`, `Component_`, `Path`, `DirProperties_`, `Application_`"
+                                       L"FROM `IIsWebDir`";
+
+enum eWebDirQuery { wdqWeb = 1, wdqWebDir, wdqComponent , wdqPath, wdqProperties, wdqApplication, wdqInstalled, wdqAction };
+
+// prototypes
+static HRESULT AddWebDirToList(SCA_WEBDIR7** ppswdList);
+
+
+UINT __stdcall ScaWebDirsRead7(
+    __in SCA_WEB7* pswList,
+    __in WCA_WRAPQUERY_HANDLE hUserQuery,
+    __in WCA_WRAPQUERY_HANDLE /*hWebBaseQuery*/,
+    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
+    __inout LPWSTR *ppwzCustomActionData,
+    __out SCA_WEBDIR7** ppswdList
+    )
+{
+    HRESULT hr = S_OK;
+    MSIHANDLE hRec;
+
+    LPWSTR pwzData = NULL;
+    SCA_WEBDIR7* pswd;
+    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
+
+    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap query for ScaWebDirsRead7");
+
+    if (0 == WcaGetQueryRecords(hWrapQuery))
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ScaInstallWebDirs7() because IIsWebDir table not present");
+        ExitFunction1(hr = S_FALSE);
+    }
+
+    // loop through all the web directories
+    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
+    {
+        hr = AddWebDirToList(ppswdList);
+        ExitOnFailure(hr, "failed to add web dir to list");
+
+        pswd = *ppswdList;
+        ExitOnNull(pswd, hr, E_INVALIDARG, "No web dir provided");
+
+        // get component install state
+        hr = WcaGetRecordString(hRec, wdqComponent, &pwzData);
+        ExitOnFailure(hr, "Failed to get Component for WebDirs");
+        hr = ::StringCchCopyW(pswd->wzComponent, countof(pswd->wzComponent), pwzData);
+        ExitOnFailure(hr, "Failed to copy component string to webdir object");
+
+        hr = WcaGetRecordInteger(hRec, wdqInstalled, (int *)&pswd->isInstalled);
+        ExitOnFailure(hr, "Failed to get Component installed state for webdir");
+
+        hr = WcaGetRecordInteger(hRec, wdqAction, (int *)&pswd->isAction);
+        ExitOnFailure(hr, "Failed to get Component action state for webdir");
+
+        hr = WcaGetRecordString(hRec, wdqWeb, &pwzData);
+        ExitOnFailure(hr, "Failed to get Web for WebDir");
+
+        // get the web key
+        hr = ScaWebsGetBase7(pswList, pwzData, pswd->wzWebSite, countof(pswd->wzWebSite));
+        if (S_FALSE == hr)
+        {
+            hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
+            ExitOnFailure(hr, "Failed to get base of web for WebDir");
+        }
+        ExitOnFailure(hr, "Failed to format webdir root string");
+
+        hr = WcaGetRecordString(hRec, wdqPath, &pwzData);
+        ExitOnFailure(hr, "Failed to get Path for WebDir");
+
+        hr = ::StringCchCopyW(pswd->wzPath, countof(pswd->wzPath), pwzData);
+        ExitOnFailure(hr, "Failed to copy path for WebDir");
+
+        // get the directory properties for this web
+        hr = WcaGetRecordString(hRec, wdqProperties, &pwzData);
+        ExitOnFailure(hr, "Failed to get security identifier for WebDir");
+        if (*pwzData)
+        {
+            hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &pswd->swp);
+            ExitOnFailure(hr, "Failed to get properties for WebDir");
+
+            pswd->fHasProperties = TRUE;
+        }
+
+        // get the application information for this web directory
+        hr = WcaGetRecordString(hRec, wdqApplication, &pwzData);
+        ExitOnFailure(hr, "Failed to get application identifier for WebDir");
+        if (*pwzData)
+        {
+            hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &pswd->swapp);
+            ExitOnFailure(hr, "Failed to get application for WebDir");
+
+            pswd->fHasApplication = TRUE;
+        }
+    }
+
+    if (E_NOMOREITEMS == hr)
+    {
+        hr = S_OK;
+    }
+    ExitOnFailure(hr, "Failure while processing WebDirs");
+
+LExit:
+    WcaFinishUnwrapQuery(hWrapQuery);
+
+    ReleaseStr(pwzData);
+
+    return hr;
+}
+
+
+HRESULT ScaWebDirsInstall7(SCA_WEBDIR7* pswdList, SCA_APPPOOL * psapList)
+{
+    HRESULT hr = S_OK;
+    SCA_WEBDIR7* pswd = pswdList;
+
+    while (pswd)
+    {
+        // if we are installing the web site
+        if (WcaIsInstalling(pswd->isInstalled, pswd->isAction))
+        {
+            hr = ScaWriteConfigID(IIS_WEBDIR);
+            ExitOnFailure(hr, "Failed to write WebDir ID");
+
+            hr = ScaWriteConfigID(IIS_CREATE);
+            ExitOnFailure(hr, "Failed to write WebDir action ID");
+
+            hr = ScaWriteConfigString(pswd->wzWebSite);
+            ExitOnFailure(hr, "Failed to write WebDir site");
+
+            hr = ScaWriteConfigString(pswd->wzPath);
+            ExitOnFailure(hr, "Failed to write WebDir path");
+
+            // get the security information for this web
+            if (pswd->fHasProperties)
+            {
+                ScaWriteWebDirProperties7(pswd->wzWebSite, pswd->wzPath, &pswd->swp);
+                ExitOnFailure(hr, "Failed to write properties for WebDir");
+            }
+
+            // get the application information for this web directory
+            if (pswd->fHasApplication)
+            {
+                hr = ScaWriteWebApplication7(pswd->wzWebSite, pswd->wzPath, &pswd->swapp, psapList);
+                ExitOnFailure(hr, "Failed to write application for WebDir");
+            }
+        }
+
+        pswd = pswd->pswdNext;
+    }
+
+LExit:
+    return hr;
+}
+
+
+HRESULT ScaWebDirsUninstall7(SCA_WEBDIR7* pswdList)
+{
+    HRESULT hr = S_OK;
+    SCA_WEBDIR7* pswd = pswdList;
+
+    while (pswd)
+    {
+        if (WcaIsUninstalling(pswd->isInstalled, pswd->isAction))
+        {
+            hr = ScaWriteConfigID(IIS_WEBDIR);
+            ExitOnFailure(hr, "Failed to write WebDir ID");
+
+            hr = ScaWriteConfigID(IIS_DELETE);
+            ExitOnFailure(hr, "Failed to write WebDir action ID");
+
+            hr = ScaWriteConfigString(pswd->wzWebSite);
+            ExitOnFailure(hr, "Failed to write WebDir site");
+
+            hr = ScaWriteConfigString(pswd->wzPath);
+            ExitOnFailure(hr, "Failed to write WebDir path");
+        }
+
+        pswd = pswd->pswdNext;
+    }
+
+LExit:
+    return hr;
+}
+
+
+void ScaWebDirsFreeList7(SCA_WEBDIR7* pswdList)
+{
+    SCA_WEBDIR7* pswdDelete = pswdList;
+    while (pswdList)
+    {
+        pswdDelete = pswdList;
+        pswdList = pswdList->pswdNext;
+
+        MemFree(pswdDelete);
+    }
+}
+
+
+static HRESULT AddWebDirToList(SCA_WEBDIR7** ppswdList)
+{
+    HRESULT hr = S_OK;
+
+    SCA_WEBDIR7* pswd = static_cast<SCA_WEBDIR7*>(MemAlloc(sizeof(SCA_WEBDIR7), TRUE));
+    ExitOnNull(pswd, hr, E_OUTOFMEMORY, "failed to allocate element for web dir list");
+
+    pswd->pswdNext = *ppswdList;
+    *ppswdList = pswd;
+
+LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+struct SCA_WEBDIR7
+{
+    // darwin information
+    WCHAR wzKey[MAX_DARWIN_KEY + 1];
+    WCHAR wzComponent[MAX_DARWIN_KEY + 1];
+    INSTALLSTATE isInstalled;
+    INSTALLSTATE isAction;
+
+
+    // iis configuation information
+    WCHAR wzPath[MAX_PATH];
+    WCHAR wzWebSite[MAX_PATH];
+
+    BOOL fHasProperties;
+    SCA_WEB_PROPERTIES swp;
+
+    BOOL fHasApplication;
+    SCA_WEB_APPLICATION swapp;
+
+    SCA_WEBDIR7* pswdNext;
+};
+
+
+// prototypes
+UINT __stdcall ScaWebDirsRead7(
+    __in SCA_WEB7* pswList,
+    __in WCA_WRAPQUERY_HANDLE hUserQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebBaseQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
+    __inout LPWSTR *ppwzCustomActionData,
+    __out SCA_WEBDIR7** ppswdList
+    );
+
+HRESULT ScaWebDirsInstall7(
+    __in SCA_WEBDIR7* pswdList,
+    __in SCA_APPPOOL* psapList
+    );
+
+HRESULT ScaWebDirsUninstall7(
+    __in SCA_WEBDIR7* pswdList
+    );
+
+void ScaWebDirsFreeList7(
+    __in SCA_WEBDIR7* pswdList
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+enum eWebErrorQuery { weqErrorCode = 1, weqSubCode, weqParentType, weqParentValue, weqFile, weqURL };
+
+static HRESULT AddWebErrorToList(SCA_WEB_ERROR** ppsweList);
+
+void ScaWebErrorFreeList(SCA_WEB_ERROR *psweList)
+{
+    SCA_WEB_ERROR *psweDelete = psweList;
+    while (psweList)
+    {
+        psweDelete = psweList;
+        psweList = psweList->psweNext;
+
+        MemFree(psweDelete);
+    }
+}
+
+HRESULT ScaWebErrorRead(
+                        SCA_WEB_ERROR **ppsweList,
+                        __inout LPWSTR *ppwzCustomActionData
+                        )
+{
+//    AssertSz(0, "Debug ScaWebErrorRead here");
+    HRESULT hr = S_OK;
+    MSIHANDLE hRec;
+    LPWSTR pwzData = NULL;
+    SCA_WEB_ERROR* pswe;
+    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
+
+    ExitOnNull(ppsweList, hr, E_INVALIDARG, "Failed to read web error, because no web error was provided to read");
+
+    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead");
+
+    if (0 == WcaGetQueryRecords(hWrapQuery))
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ScaWebErrorRead() - required tables not present.");
+        ExitFunction1(hr = S_FALSE);
+    }
+
+    // loop through all the web errors
+    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
+    {
+        hr = AddWebErrorToList(ppsweList);
+        ExitOnFailure(hr, "failed to add web error to list");
+
+        pswe = *ppsweList;
+
+        hr = WcaGetRecordInteger(hRec, weqErrorCode, &(pswe->iErrorCode));
+        ExitOnFailure(hr, "failed to get IIsWebError.ErrorCode");
+
+        hr = WcaGetRecordInteger(hRec, weqSubCode, &(pswe->iSubCode));
+        ExitOnFailure(hr, "failed to get IIsWebError.SubCode");
+
+        hr = WcaGetRecordInteger(hRec, weqParentType, &(pswe->iParentType));
+        ExitOnFailure(hr, "failed to get IIsWebError.ParentType");
+
+        hr = WcaGetRecordString(hRec, weqParentValue, &pwzData);
+        ExitOnFailure(hr, "Failed to get IIsWebError.ParentValue");
+        hr = ::StringCchCopyW(pswe->wzParentValue, countof(pswe->wzParentValue), pwzData);
+        ExitOnFailure(hr, "Failed to copy IIsWebError.ParentValue");
+
+        hr = WcaGetRecordString(hRec, weqFile, &pwzData);
+        ExitOnFailure(hr, "Failed to get IIsWebError.File");
+        hr = ::StringCchCopyW(pswe->wzFile, countof(pswe->wzFile), pwzData);
+        ExitOnFailure(hr, "Failed to copy IIsWebError.File");
+
+        hr = WcaGetRecordString(hRec, weqURL, &pwzData);
+        ExitOnFailure(hr, "Failed to get IIsWebError.URL");
+        hr = ::StringCchCopyW(pswe->wzURL, countof(pswe->wzURL), pwzData);
+        ExitOnFailure(hr, "Failed to copy IIsWebError.URL");
+
+        // If they've specified both a file and a URL, that's invalid
+        if (*(pswe->wzFile) && *(pswe->wzURL))
+            ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA), "Both File and URL specified for web error.  File: %ls, URL: %ls", pswe->wzFile, pswe->wzURL);
+    }
+
+    if (E_NOMOREITEMS == hr)
+    {
+        hr = S_OK;
+    }
+    ExitOnFailure(hr, "Failure while processing web errors");
+
+LExit:
+    WcaFinishUnwrapQuery(hWrapQuery);
+
+    ReleaseStr(pwzData);
+
+    return hr;
+}
+
+HRESULT ScaGetWebError(int iParentType, LPCWSTR wzParentValue, SCA_WEB_ERROR **ppsweList, SCA_WEB_ERROR **ppsweOut)
+{
+    HRESULT hr = S_OK;
+    SCA_WEB_ERROR* psweAdd = NULL;
+    SCA_WEB_ERROR* psweLast = NULL;
+
+    *ppsweOut = NULL;
+    
+    if (!*ppsweList)
+        return hr;
+
+    SCA_WEB_ERROR* pswe = *ppsweList;
+    while (pswe)
+    {
+        if (iParentType == pswe->iParentType && 0 == lstrcmpW(wzParentValue, pswe->wzParentValue))
+        {
+            // Found a match, take this one out of the list and add it to the matched out list
+            psweAdd = pswe;
+
+            if (psweLast)
+            {
+                // 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)
+                psweLast->psweNext = psweAdd->psweNext;
+            }
+            else
+            {
+                // If we are at the beginning (no psweLast) update the beginning (since we're taking it)
+                *ppsweList = pswe->psweNext;
+            }
+            pswe = pswe->psweNext; // move on
+
+            // Add the one we've removed to the beginning of the out list
+            psweAdd->psweNext = *ppsweOut;
+            *ppsweOut = psweAdd;
+        }
+        else
+        {
+            psweLast = pswe; // remember the last we that didn't match
+            pswe = pswe->psweNext; // move on
+        }
+    }
+
+    return hr;
+}
+
+HRESULT ScaWriteWebError(IMSAdminBase* piMetabase, int iParentType, LPCWSTR wzRoot, SCA_WEB_ERROR* psweList)
+{
+//    AssertSz(0, "Debug ScaWriteWebError here");
+    Assert(*wzRoot && psweList);
+
+    HRESULT hr = S_OK;
+
+    DWORD cchData = 0;
+    LPWSTR pwzSearchKey = NULL;
+    LPWSTR pwz = NULL;
+    LPWSTR pwzErrors = NULL;
+
+    LPWSTR pwzCodeSubCode = NULL;
+    LPWSTR pwzAcceptableCodeSubCode = NULL;
+    LPCWSTR wzFoundCodeSubCode = NULL;
+    DWORD_PTR dwFoundCodeSubCodeIndex = 0xFFFFFFFF;
+    BOOL fOldValueFound = FALSE;
+    LPWSTR pwzAcceptableErrors = NULL;
+
+    LPWSTR pwzNewError = NULL;
+
+    METADATA_RECORD mr;
+    ::ZeroMemory(&mr, sizeof(mr));
+
+    ExitOnNull(piMetabase, hr, E_INVALIDARG, "Failed to write web error, because no metabase was provided");
+    ExitOnNull(wzRoot, hr, E_INVALIDARG, "Failed to write web error, because no root was provided");
+
+    // get the set of all valid custom errors from the metabase
+    mr.dwMDIdentifier = MD_CUSTOM_ERROR_DESC;
+    mr.dwMDAttributes = METADATA_INHERIT;
+    mr.dwMDUserType = IIS_MD_UT_SERVER;
+    mr.dwMDDataType = ALL_METADATA;
+    mr.dwMDDataLen = cchData = 0;
+    mr.pbMDData = NULL;
+
+    hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, L"/LM/W3SVC/Info", &mr);
+    ExitOnFailure(hr, "Unable to get set of acceptable error codes for this server.");
+
+    pwzAcceptableErrors = reinterpret_cast<LPWSTR>(mr.pbMDData);
+
+    // Check if web errors already exist here
+    mr.dwMDIdentifier = MD_CUSTOM_ERROR;
+    mr.dwMDAttributes = METADATA_INHERIT;
+    mr.dwMDUserType = IIS_MD_UT_SERVER;
+    mr.dwMDDataType = ALL_METADATA;
+    mr.dwMDDataLen = cchData = 0;
+    mr.pbMDData = NULL;
+
+    hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzRoot, &mr);
+    if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || MD_ERROR_DATA_NOT_FOUND == hr)
+    {
+        //
+        // If we don't have one already, find an appropriate one to start with
+        //
+
+        // we can walk up key by key and look for custom errors to inherit
+
+        hr = StrAllocConcat(&pwzSearchKey, wzRoot, 0);
+        ExitOnFailure(hr, "Failed to copy root string: %ls", wzRoot);
+
+        pwz = pwzSearchKey + lstrlenW(pwzSearchKey);
+
+        while (NULL == pwzErrors)
+        {
+            // find the last slash
+            while (*pwz != '/' && pwz != pwzSearchKey)
+                pwz --;
+
+            if (pwz == pwzSearchKey)
+                break;
+
+            *pwz = L'\0';
+
+            // Try here.  If it's not found, keep walking up the path
+            hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, pwzSearchKey, &mr);
+            if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || MD_ERROR_DATA_NOT_FOUND == hr)
+                hr = S_FALSE;
+            ExitOnFailure(hr, "failed to discover default error values to start with for web root: %ls while walking up the tree", wzRoot);
+
+            if (S_OK == hr)
+            {
+                pwzErrors = reinterpret_cast<LPWSTR>(mr.pbMDData);
+                break;
+            }
+
+            // Don't keep going if we're at the root
+            if (0 == lstrcmpW(pwz + 1, L"W3SVC"))
+                break;
+        }
+    }
+    else
+    {
+        pwzErrors = reinterpret_cast<LPWSTR>(mr.pbMDData);
+    }
+    ExitOnFailure(hr, "failed to discover default error values to start with for web root: %ls", wzRoot);
+
+    // The above code should have come up with some value to start pwzErrors off with.  Make sure it did.
+    if (NULL == pwzErrors)
+    {
+        ExitOnFailure(hr = E_UNEXPECTED, "failed to discover default error values to start with for web root: %ls", wzRoot);
+    }
+
+    // Loop through the web errors
+    for (SCA_WEB_ERROR* pswe = psweList; pswe; pswe = pswe->psweNext)
+    {
+        // Assume that we will have to replace 
+        fOldValueFound = TRUE;
+
+        // If the subcode is 0, that means "*" in MD_CUSTOM_ERROR (thus the special formatting logic)
+        if (0 == pswe->iSubCode)
+        {
+            hr = StrAllocFormatted(&pwzCodeSubCode, L"%d,*", pswe->iErrorCode);
+            ExitOnFailure(hr, "failed to create error code string while installing web error");
+        }
+        else
+        {
+            hr = StrAllocFormatted(&pwzCodeSubCode, L"%d,%d", pswe->iErrorCode, pswe->iSubCode);
+            ExitOnFailure(hr, "failed to create error code,subcode string while installing web error");
+        }
+
+        hr = MultiSzFindSubstring(pwzErrors, pwzCodeSubCode, &dwFoundCodeSubCodeIndex, &wzFoundCodeSubCode);
+        ExitOnFailure(hr, "failed to find existing error code,subcode: %ls", pwzCodeSubCode);
+
+        // If we didn't find this error code/sub code pair in the list already, make sure it's acceptable to add
+        if (S_FALSE == hr)
+        {
+            //
+            // Make sure this error code/sub code pair is in the "acceptable" list
+            //
+
+            // If the subcode is 0, that means "0" in MD_CUSTOM_ERROR_DESC (no special formatting logic needed)
+            hr = StrAllocFormatted(&pwzAcceptableCodeSubCode, L"%d,%d", pswe->iErrorCode, pswe->iSubCode);
+            ExitOnFailure(hr, "failed to create error code,subcode string while installing web error");
+
+            // We don't care where it is, just whether it's there or not
+            hr = MultiSzFindSubstring(pwzAcceptableErrors, pwzAcceptableCodeSubCode, NULL, NULL);
+            ExitOnFailure(hr, "failed to find whether or not error code, subcode: %ls is supported", pwzCodeSubCode);
+
+            if (S_FALSE == hr)
+            {
+                WcaLog(LOGMSG_VERBOSE, "Skipping error code, subcode: %ls because it is not supported by the server.", pwzCodeSubCode);
+                continue;
+            }
+
+            // If we didn't find it (and its an acceptable error) then we have nothing to replace
+            fOldValueFound = FALSE;
+        }
+
+        // Set up the new error string if needed
+        if (*(pswe->wzFile))
+        {
+            hr = StrAllocFormatted(&pwzNewError, L"%s,FILE,%s", pwzCodeSubCode, pswe->wzFile);
+            ExitOnFailure(hr, "failed to create new error code string with code,subcode: %ls, file: %ls", pwzCodeSubCode, pswe->wzFile);
+        }
+        else if (*(pswe->wzURL))
+        {
+            hr = StrAllocFormatted(&pwzNewError, L"%s,URL,%s", pwzCodeSubCode, pswe->wzURL);
+            ExitOnFailure(hr, "failed to create new error code string with code,subcode: %ls, file: %ls", pwzCodeSubCode, pswe->wzFile);
+        }
+        else if (fOldValueFound)
+        {
+            // If no File or URL was specified, they want a default error so remove the old value from the MULTISZ and move on
+            hr = MultiSzRemoveString(&pwzErrors, dwFoundCodeSubCodeIndex);
+            ExitOnFailure(hr, "failed to remove string for error code sub code: %ls in order to make it 'default'", pwzCodeSubCode);
+            continue;
+        }
+
+        // If we have something to replace, replace it, otherwise, put it at the beginning (order shouldn't matter)
+        if (fOldValueFound)
+        {
+            hr = MultiSzReplaceString(&pwzErrors, dwFoundCodeSubCodeIndex, pwzNewError);
+            ExitOnFailure(hr, "failed to replace old error string with new error string for error code,subcode: %ls", pwzCodeSubCode);
+        }
+        else
+        {
+            hr = MultiSzPrepend(&pwzErrors, NULL, pwzNewError);
+            ExitOnFailure(hr, "failed to prepend new error string for error code,subcode: %ls", pwzCodeSubCode);
+        }
+    }
+
+    // now write the CustomErrors to the metabase
+    if (weptWeb == iParentType)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRoot, L"/Root", MD_CUSTOM_ERROR, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, pwzErrors);
+        ExitOnFailure(hr, "Failed to write Web Error to /Root");
+    }
+    else
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRoot, NULL, MD_CUSTOM_ERROR, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, pwzErrors);
+        ExitOnFailure(hr, "Failed to write Web Error");
+    }
+
+LExit:
+    ReleaseStr(pwzErrors);
+    ReleaseStr(pwzSearchKey);
+    ReleaseStr(pwzCodeSubCode);
+    ReleaseStr(pwzAcceptableCodeSubCode);
+    ReleaseStr(pwzAcceptableErrors);
+
+    return hr;
+}
+
+static HRESULT AddWebErrorToList(SCA_WEB_ERROR** ppsweList)
+{
+    HRESULT hr = S_OK;
+
+    SCA_WEB_ERROR* pswe = static_cast<SCA_WEB_ERROR*>(MemAlloc(sizeof(SCA_WEB_ERROR), TRUE));
+    ExitOnNull(pswe, hr, E_OUTOFMEMORY, "failed to allocate memory for new web error list element");
+
+    pswe->psweNext = *ppsweList;
+    *ppsweList = pswe;
+
+LExit:
+    return hr;
+}
+
+HRESULT ScaWebErrorCheckList(SCA_WEB_ERROR* psweList)
+{
+    if (!psweList)
+    {
+        return S_OK;
+    }
+    
+    while (psweList)
+    {
+        WcaLog(LOGMSG_STANDARD, "WebError code: %d subcode: %d for parent: %ls not used!", psweList->iErrorCode, psweList->iSubCode, psweList->wzParentValue);
+        psweList = psweList->psweNext;
+    }
+
+    return E_FAIL;
+}
+
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 @@
+#pragma once
+// 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.
+
+
+enum eWebErrorParentType { weptVDir = 1, weptWeb };
+
+struct SCA_WEB_ERROR
+{
+	int iErrorCode;
+	int iSubCode;
+
+	int iParentType;
+	WCHAR wzParentValue[MAX_DARWIN_KEY + 1];
+
+	WCHAR wzFile[MAX_PATH];
+	WCHAR wzURL[MAX_PATH]; // TODO: this needs to be bigger than MAX_PATH
+	
+	SCA_WEB_ERROR *psweNext;
+};
+
+// prototypes
+HRESULT ScaWebErrorRead(
+                        SCA_WEB_ERROR **ppsweList,
+                        __inout LPWSTR *ppwzCustomActionData
+                        );
+void ScaWebErrorFreeList(SCA_WEB_ERROR *psweList);
+HRESULT ScaWebErrorCheckList(SCA_WEB_ERROR* psweList);
+HRESULT ScaGetWebError(int iParentType, LPCWSTR wzParentValue, SCA_WEB_ERROR **ppsweList, SCA_WEB_ERROR **ppsweOut);
+HRESULT ScaWriteWebError(IMSAdminBase* piMetabase, int iParentType, LPCWSTR wzRoot, SCA_WEB_ERROR* psweList);
+
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 @@
+// 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.
+
+#include "precomp.h"
+
+HRESULT ScaWriteWebError7(
+    __in_z LPCWSTR wzWebName,
+    __in_z LPCWSTR wzRoot,
+    SCA_WEB_ERROR* psweList
+    )
+{
+    HRESULT hr = S_OK;
+
+    hr = ScaWriteConfigID(IIS_WEBERROR_BEGIN);
+    ExitOnFailure(hr, "Fail to write webError begin ID");
+
+    hr = ScaWriteConfigString(wzWebName);
+    ExitOnFailure(hr, "Fail to write webError Web Key");
+
+    hr = ScaWriteConfigString(wzRoot);
+    ExitOnFailure(hr, "Fail to write webError Vdir key");
+
+    // Loop through the HTTP headers
+    for (SCA_WEB_ERROR* pswe = psweList; pswe; pswe = pswe->psweNext)
+    {
+        hr = ScaWriteConfigID(IIS_WEBERROR);
+        ExitOnFailure(hr, "Fail to write webError ID");
+
+        hr = ScaWriteConfigInteger(pswe->iErrorCode);
+        ExitOnFailure(hr, "Fail to write webError code");
+
+        hr = ScaWriteConfigInteger(pswe->iSubCode);
+        ExitOnFailure(hr, "Fail to write webError subcode");
+
+        //just write one
+        if (*(pswe->wzFile))
+        {
+            hr = ScaWriteConfigString(pswe->wzFile);
+            ExitOnFailure(hr, "Fail to write webError file");
+            hr = ScaWriteConfigInteger(0);
+            ExitOnFailure(hr, "Fail to write webError file code");
+        }
+        else if (*(pswe->wzURL))
+        {
+            hr = ScaWriteConfigString(pswe->wzURL);
+            ExitOnFailure(hr, "Fail to write webError URL");
+            hr = ScaWriteConfigInteger(1);
+            ExitOnFailure(hr, "Fail to write webError URL code");
+        }
+    }
+
+    hr = ScaWriteConfigID(IIS_WEBERROR_END);
+    ExitOnFailure(hr, "Fail to write httpHeader end ID");
+
+LExit:
+    return hr;
+
+}
+
+//static HRESULT AddWebErrorToList(SCA_WEB_ERROR** ppsweList)
+//{
+//    HRESULT hr = S_OK;
+//
+//    SCA_WEB_ERROR* pswe = static_cast<SCA_WEB_ERROR*>(MemAlloc(sizeof(SCA_WEB_ERROR), TRUE));
+//    ExitOnNull(pswe, hr, E_OUTOFMEMORY, "failed to allocate memory for new web error list element");
+//
+//    pswe->psweNext = *ppsweList;
+//    *ppsweList = pswe;
+//
+//LExit:
+//    return hr;
+//}
+
+HRESULT ScaWebErrorCheckList7(SCA_WEB_ERROR* psweList)
+{
+    if (!psweList)
+    {
+        return S_OK;
+    }
+
+    while (psweList)
+    {
+        WcaLog(LOGMSG_STANDARD, "WebError code: %d subcode: %d for parent: %ls not used!", psweList->iErrorCode, psweList->iSubCode, psweList->wzParentValue);
+        psweList = psweList->psweNext;
+    }
+
+    return E_FAIL;
+}
+
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 @@
+#pragma once
+// 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.
+
+
+HRESULT ScaWriteWebError7(
+    __in_z LPCWSTR wzWebName,
+    __in_z LPCWSTR wzRoot,
+    SCA_WEB_ERROR* psweList
+    );
+
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 @@
+// 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.
+
+#include "precomp.h"
+
+enum eWebLogQuery { wlqLog = 1, wlqFormat };
+
+/* ****************************************************************
+ * LookupLogFormatGUID -Looks up a given IIS Log format type in 
+ * the metabase and returns the GUID for it.
+ * ****************************************************************/
+static HRESULT LookupLogFormatGUID(
+    __in IMSAdminBase* piMetabase,
+    __in LPCWSTR wzLogFormat,
+    __out_ecount(cchGUID) LPWSTR wzGUID,
+    __in int cchGUID
+    )
+{
+    WCHAR wzKey[METADATA_MAX_NAME_LEN];
+    HRESULT hr = S_OK;
+
+    METADATA_RECORD mrKeyType;
+    ::ZeroMemory(&mrKeyType, sizeof(mrKeyType));
+
+    mrKeyType.dwMDIdentifier = MD_KEY_TYPE;
+    mrKeyType.dwMDAttributes = METADATA_NO_ATTRIBUTES;
+    mrKeyType.dwMDUserType = IIS_MD_UT_SERVER;
+    mrKeyType.dwMDDataType = ALL_METADATA;
+    mrKeyType.dwMDDataLen = 0;
+    mrKeyType.pbMDData = NULL;
+
+    METADATA_RECORD mrPluginId;
+    ::ZeroMemory(&mrPluginId, sizeof(mrPluginId));
+
+    mrPluginId.dwMDIdentifier = MD_LOG_PLUGIN_MOD_ID;
+    mrPluginId.dwMDAttributes = METADATA_INHERIT;
+    mrPluginId.dwMDUserType = IIS_MD_UT_SERVER;
+    mrPluginId.dwMDDataType = ALL_METADATA;
+    mrPluginId.dwMDDataLen = 0;
+    mrPluginId.pbMDData = NULL;
+    
+    hr = ::StringCchPrintfW(wzKey, countof(wzKey), L"/LM/Logging/%s", wzLogFormat);
+    ExitOnFailure(hr, "failed to format logging metabase key name");
+
+    // verify that we have this log format available in IIS
+    hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzKey, &mrKeyType);
+    ExitOnFailure(hr, "Failed to find specified Log format key in IIS for log format: %ls", wzLogFormat);
+    ExitOnNull(mrKeyType.pbMDData, hr, E_POINTER, "Request for Log format key in IIS for log format returned success, but value was NULL");
+
+    if (0 != lstrcmpW(L"IIsLogModule", (LPCWSTR)mrKeyType.pbMDData))
+    {
+        ExitOnFailure(hr = E_UNEXPECTED, "Found invalid log format in IIS: %ls", (LPCWSTR)mrKeyType.pbMDData);
+    }
+
+    // find the GUID for that log format
+    hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzKey, &mrPluginId);
+    ExitOnFailure(hr, "Failed to retrieve IISLog format GUID. Key: %ls", wzKey);
+    ExitOnNull(mrPluginId.pbMDData, hr, E_POINTER, "Retrieval of IISLog format GUID returned success, but value was NULL");
+
+    hr = ::StringCchCopyW(wzGUID, cchGUID, (LPCWSTR)mrPluginId.pbMDData);
+    ExitOnFailure(hr, "failed to copy metabase value: %ls", (LPCWSTR)mrPluginId.pbMDData);
+
+LExit:
+
+    if (mrKeyType.pbMDData)
+    {
+        MetaFreeValue(&mrKeyType);
+    }
+
+    if (mrPluginId.pbMDData)
+    {
+        MetaFreeValue(&mrPluginId);
+    }
+
+    return hr;
+}
+
+
+/* ****************************************************************
+ * ScaGetWebLog -Retrieves Log table data for the specified Log key
+ *
+ * ****************************************************************/
+HRESULT ScaGetWebLog(
+    IMSAdminBase* piMetabase,
+    LPCWSTR wzLog,
+    __in WCA_WRAPQUERY_HANDLE hWebLogQuery,
+    SCA_WEB_LOG* pswl
+    )
+{
+    HRESULT hr = S_OK;
+    LPWSTR pwzData = NULL;
+    MSIHANDLE hRec;
+
+    if (0 == WcaGetQueryRecords(hWebLogQuery))
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ScaGetWebLog() - no records to process");
+        ExitFunction1(hr = S_FALSE);
+    }
+
+    WcaFetchWrappedReset(hWebLogQuery);
+
+    hr = WcaFetchWrappedRecordWhereString(hWebLogQuery, wlqLog, wzLog, &hRec);
+    if (E_NOMOREITEMS == hr)
+    {
+        ExitOnFailure(hr, "cannot locate IIsWebLog.Log='%ls'", wzLog);
+    }
+    HRESULT hrTemp = WcaFetchWrappedRecordWhereString(hWebLogQuery, wlqLog, wzLog, &hRec);
+
+    if (SUCCEEDED(hrTemp))
+    {
+        ExitOnFailure(hr, "error - found multiple matching IIsWebLog rows");
+    }
+
+    ::ZeroMemory(pswl, sizeof(SCA_WEB_LOG));
+
+    // check that log key matches
+    hr = WcaGetRecordString(hRec, wlqLog, &pwzData);
+    ExitOnFailure(hr, "failed to get IIsWebLog.Log for Log: %ls", wzLog);
+    hr = ::StringCchCopyW(pswl->wzLog, countof(pswl->wzLog), pwzData);
+    ExitOnFailure(hr, "failed to copy log name: %ls", pwzData);
+
+    hr = WcaGetRecordString(hRec, wlqFormat, &pwzData);
+    ExitOnFailure(hr, "failed to get IIsWebLog.Format for Log:", wzLog);
+    hr = ::StringCchCopyW(pswl->wzFormat, countof(pswl->wzFormat), pwzData);
+    ExitOnFailure(hr, "failed to copy log format: %ls", pwzData);
+
+    // if they specified a log format, look up its GUID in the metabase
+    if (*pswl->wzFormat && 0 != lstrcmpW(pswl->wzFormat, L"none"))
+    {
+        hr = LookupLogFormatGUID(piMetabase, pswl->wzFormat, pswl->wzFormatGUID, countof(pswl->wzFormatGUID));
+        ExitOnFailure(hr, "Failed to get Log Format GUID for Log: %ls", wzLog);
+    }
+
+LExit:
+    ReleaseStr(pwzData);
+
+    return hr;
+}
+
+
+/* ****************************************************************
+ * ScaWriteWebLog -Writes the IIS log values to the metabase.
+ *
+ * ****************************************************************/
+HRESULT ScaWriteWebLog(
+    IMSAdminBase* piMetabase,
+    LPCWSTR wzWebBase,
+    SCA_WEB_LOG *pswl
+    )
+{
+    HRESULT hr = S_OK;
+
+    if (*pswl->wzFormat)
+    {
+        if (0 == lstrcmpW(pswl->wzFormat, L"none"))
+        {
+            // user wishes for Logging to be turned 'off'
+            hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_LOG_TYPE, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)0));
+            ExitOnFailure(hr, "Failed to write Log Type for Web: %ls", wzWebBase);
+        }
+        else
+        {
+            Assert(*pswl->wzFormatGUID);
+            
+            // write the GUID for the log format for the web to the metabase
+            hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_LOG_PLUGIN_ORDER, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, pswl->wzFormatGUID);
+            ExitOnFailure(hr, "Failed to write Log GUID for Web: %ls", wzWebBase);
+
+            hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_LOG_TYPE, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)1));
+            ExitOnFailure(hr, "Failed to write Log Type for Web: %ls", wzWebBase);
+        }
+    }
+
+LExit:
+    return hr;
+}
+
+
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 @@
+#pragma once
+// 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.
+
+
+struct SCA_WEB_LOG
+{
+	// iis configuation information
+	WCHAR wzLog[MAX_DARWIN_KEY + 1];
+
+	// for specifying the log format
+	WCHAR wzFormat[MAX_DARWIN_KEY + 1];
+	WCHAR wzFormatGUID[MAX_DARWIN_KEY + 1];
+};
+
+
+// prototypes
+HRESULT ScaGetWebLog(
+	IMSAdminBase* piMetabase,
+	LPCWSTR wzLog,
+    __in WCA_WRAPQUERY_HANDLE hWebLogQuery,
+	SCA_WEB_LOG* pswl
+	);
+HRESULT ScaWriteWebLog(
+	IMSAdminBase* piMetabase,
+	LPCWSTR wzRootOfWeb,
+	SCA_WEB_LOG *pswl
+	);
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 @@
+// 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.
+
+#include "precomp.h"
+// sql queries
+LPCWSTR vcsWebLogQuery7 = L"SELECT `Log`, `Format` "
+                         L"FROM `IIsWebLog`  WHERE `Log`=?";
+
+enum eWebLogQuery { wlqLog = 1, wlqFormat };
+
+/* ****************************************************************
+ * ScaGetWebLog7 -Retrieves Log table data for the specified Log key
+ *
+ * ****************************************************************/
+HRESULT ScaGetWebLog7(
+    __in_z LPCWSTR wzLog,
+    __in WCA_WRAPQUERY_HANDLE hWebLogQuery,
+    __out SCA_WEB_LOG* pswl
+    )
+{
+    HRESULT hr = S_OK;
+    LPWSTR pwzData = NULL;
+    MSIHANDLE hRec;
+
+    if (0 == WcaGetQueryRecords(hWebLogQuery))
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ScaGetWebLog() - no records to process");
+        ExitFunction1(hr = S_FALSE);
+    }
+
+    WcaFetchWrappedReset(hWebLogQuery);
+
+    hr = WcaFetchWrappedRecordWhereString(hWebLogQuery, wlqLog, wzLog, &hRec);
+    if (E_NOMOREITEMS == hr)
+    {
+        ExitOnFailure(hr, "cannot locate IIsWebLog.Log='%ls'", wzLog);
+    }
+    HRESULT hrTemp = WcaFetchWrappedRecordWhereString(hWebLogQuery, wlqLog, wzLog, &hRec);
+
+    if (SUCCEEDED(hrTemp))
+    {
+        ExitOnFailure(hr, "error - found multiple matching IIsWebLog rows");
+    }
+
+    ::ZeroMemory(pswl, sizeof(SCA_WEB_LOG));
+
+    // check that log key matches
+    hr = WcaGetRecordString(hRec, wlqLog, &pwzData);
+    ExitOnFailure(hr, "failed to get IIsWebLog.Log for Log: %ls", wzLog);
+    hr = ::StringCchCopyW(pswl->wzLog, countof(pswl->wzLog), pwzData);
+    ExitOnFailure(hr, "failed to copy log name: %ls", pwzData);
+
+    hr = WcaGetRecordString(hRec, wlqFormat, &pwzData);
+    ExitOnFailure(hr, "failed to get IIsWebLog.Format for Log:", wzLog);
+
+    //translate WIX log format name strings to IIS7
+    if (0 == lstrcmpW(pwzData, L"Microsoft IIS Log File Format"))
+    {
+        hr = ::StringCchCopyW(pswl->wzFormat, countof(pswl->wzFormat), L"IIS");
+        ExitOnFailure(hr, "failed to copy log format: %ls", pwzData);
+    }
+    else if (0 == lstrcmpW(pwzData, L"NCSA Common Log File Format"))
+    {
+        hr = ::StringCchCopyW(pswl->wzFormat, countof(pswl->wzFormat), L"NCSA");
+        ExitOnFailure(hr, "failed to copy log format: %ls", pwzData);
+    }
+    else if (0 == lstrcmpW(pwzData, L"none"))
+    {
+        hr = ::StringCchCopyW(pswl->wzFormat, countof(pswl->wzFormat), L"none");
+        ExitOnFailure(hr, "failed to copy log format: %ls", pwzData);
+    }
+    else if (0 == lstrcmpW(pwzData, L"ODBC Logging"))
+    {
+        hr = ::StringCchCopyW(pswl->wzFormat, countof(pswl->wzFormat), L"W3C");
+        ExitOnFailure(hr, "failed to copy log format: %ls", pwzData);
+    }
+    else if (0 == lstrcmpW(pwzData, L"W3C Extended Log File Format"))
+    {
+        hr = ::StringCchCopyW(pswl->wzFormat, countof(pswl->wzFormat), L"W3C");
+        ExitOnFailure(hr, "failed to copy log format: %ls", pwzData);
+    }
+    else
+    {
+        hr = HRESULT_FROM_WIN32(ERROR_INVALID_INDEX);
+        ExitOnFailure(hr, "Invalid log file format: %ls", pwzData);
+    }
+
+LExit:
+    ReleaseStr(pwzData);
+
+    return hr;
+}
+
+
+/* ****************************************************************
+ * ScaWriteWebLog -Writes the IIS log values to the metabase.
+ *
+ * ****************************************************************/
+HRESULT ScaWriteWebLog7(
+    LPCWSTR wzWebBase,
+    const SCA_WEB_LOG *pswl
+    )
+{
+    HRESULT hr = S_OK;
+
+    if (*pswl->wzFormat)
+    {
+        //write pswl->wzFormat
+        hr = ScaWriteConfigID(IIS_WEBLOG);
+        ExitOnFailure(hr, "Failed to write log format id");
+        hr = ScaWriteConfigString(wzWebBase);
+        ExitOnFailure(hr, "Failed to write log web key");
+        hr = ScaWriteConfigString(pswl->wzFormat);
+        ExitOnFailure(hr, "Failed to write log format string");
+    }
+
+LExit:
+    return hr;
+}
+
+
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 @@
+#pragma once
+// 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.
+
+
+HRESULT ScaGetWebLog7(
+    __in_z LPCWSTR wzLog,
+    __in WCA_WRAPQUERY_HANDLE hWebLogQuery,
+    __out SCA_WEB_LOG* pswl
+    );
+
+HRESULT ScaWriteWebLog7(
+    __in_z LPCWSTR wzRootOfWeb,
+    const SCA_WEB_LOG *pswl
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+// sql queries
+enum eWebDirPropertiesQuery { wpqProperties = 1, wpqAccess, wpqAuthorization, wpqUser, wpqControlledPassword, wpqLogVisits, wpqIndex, wpqDefaultDoc,  wpqAspDetailedError, wpqHttpExp, wpqCCMaxAge, wpqCCCustom, wpqNoCustomError, wpqAccessSSLFlags, wpqAuthenticationProviders };
+
+HRESULT ScaGetWebDirProperties(
+    __in LPCWSTR wzProperties,
+    __in WCA_WRAPQUERY_HANDLE hUserQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
+    __inout SCA_WEB_PROPERTIES* pswp
+    )
+{
+    Assert(*wzProperties && pswp);
+
+    HRESULT hr = S_OK;
+    MSIHANDLE hRec;
+    LPWSTR pwzData = NULL;
+
+    ExitOnNull(wzProperties, hr, E_INVALIDARG, "Failed to get web directory properties because no properties were provided to get");
+
+    WcaFetchWrappedReset(hWebDirPropQuery);
+
+    hr = WcaFetchWrappedRecordWhereString(hWebDirPropQuery, 1, wzProperties, &hRec);
+    if (S_OK == hr)
+    {
+        hr = WcaGetRecordString(hRec, wpqProperties, &pwzData);
+        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.DirProperties");
+        hr = ::StringCchCopyW(pswp->wzKey, countof(pswp->wzKey), pwzData);
+        ExitOnFailure(hr, "Failed to copy key string to webdirproperties object");
+
+        Assert(0 == lstrcmpW(pswp->wzKey, wzProperties));
+
+        hr = WcaGetRecordInteger(hRec, wpqAccess, &pswp->iAccess);
+        ExitOnFailure(hr, "Failed to get access value");
+
+        hr = WcaGetRecordInteger(hRec, wpqAuthorization, &pswp->iAuthorization);
+        ExitOnFailure(hr, "Failed to get authorization value");
+
+        // if allow anonymous users
+        if (S_OK == hr && pswp->iAuthorization & 1)
+        {
+            // if there is an anonymous user specified
+            hr = WcaGetRecordString(hRec, wpqUser, &pwzData);
+            ExitOnFailure(hr, "Failed to get AnonymousUser_");
+            if (pwzData && *pwzData)
+            {
+                hr = WcaGetRecordInteger(hRec, wpqControlledPassword, &pswp->fIIsControlledPassword);
+                ExitOnFailure(hr, "Failed to get IIsControlledPassword");
+                if (S_FALSE == hr)
+                {
+                    pswp->fIIsControlledPassword = FALSE;
+                    hr = S_OK;
+                }
+
+                hr = ScaGetUserDeferred(pwzData, hUserQuery, &pswp->scau);
+                ExitOnFailure(hr, "Failed to get User information for Web");
+
+                pswp->fHasUser = TRUE;
+            }
+            else
+                pswp->fHasUser = FALSE;
+        }
+
+        hr = WcaGetRecordInteger(hRec, wpqLogVisits, &pswp->fLogVisits);
+        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.LogVisits");
+
+        hr = WcaGetRecordInteger(hRec, wpqIndex, &pswp->fIndex);
+        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.Index");
+
+        hr = WcaGetRecordString(hRec, wpqDefaultDoc, &pwzData);
+        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.DefaultDoc");
+        if (pwzData && *pwzData)
+        {
+            pswp->fHasDefaultDoc = TRUE;
+            if (0 == lstrcmpW(L"-", pwzData))   // remove any existing default documents by setting them blank
+            {
+                pswp->wzDefaultDoc[0] = L'\0';
+            }
+            else   // set the default documents
+            {
+                hr = ::StringCchCopyW(pswp->wzDefaultDoc, countof(pswp->wzDefaultDoc), pwzData);
+                ExitOnFailure(hr, "Failed to copy default document string to webdirproperties object");
+            }
+        }
+        else
+        {
+            pswp->fHasDefaultDoc = FALSE;
+        }
+
+        hr = WcaGetRecordInteger(hRec, wpqAspDetailedError, &pswp->fAspDetailedError);
+        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.AspDetailedError");
+
+        hr = WcaGetRecordString(hRec, wpqHttpExp, &pwzData);
+        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.HttpExp");
+        if (pwzData && *pwzData)
+        {
+            pswp->fHasHttpExp = TRUE;
+            if (0 == lstrcmpW(L"-", pwzData))   // remove any existing default expiration settings by setting them blank
+            {
+                pswp->wzHttpExp[0] = L'\0';
+            }
+            else   // set the expiration setting
+            {
+                hr = ::StringCchCopyW(pswp->wzHttpExp, countof(pswp->wzHttpExp), pwzData);
+                ExitOnFailure(hr, "Failed to copy http expiration string to webdirproperties object");
+            }
+        }
+        else
+        {
+            pswp->fHasHttpExp = FALSE;
+        }
+
+        hr = WcaGetRecordInteger(hRec, wpqCCMaxAge, &pswp->iCacheControlMaxAge);
+        ExitOnFailure(hr, "failed to get IIsWebDirProperties.CacheControlMaxAge");
+
+        hr = WcaGetRecordString(hRec, wpqCCCustom, &pwzData);
+        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.CacheControlCustom");
+        if (pwzData && *pwzData)
+        {
+            pswp->fHasCacheControlCustom = TRUE;
+            if (0 == lstrcmpW(L"-", pwzData))   // remove any existing default cache control custom settings by setting them blank
+            {
+                pswp->wzCacheControlCustom[0] = L'\0';
+            }
+            else   // set the custom cache control setting
+            {
+                hr = ::StringCchCopyW(pswp->wzCacheControlCustom, countof(pswp->wzCacheControlCustom), pwzData);
+                ExitOnFailure(hr, "Failed to copy cache control custom settings to webdirproperites object");
+            }
+        }
+        else
+        {
+            pswp->fHasCacheControlCustom = FALSE;
+        }
+
+        hr = WcaGetRecordInteger(hRec, wpqNoCustomError, &pswp->fNoCustomError);
+        ExitOnFailure(hr, "failed to get IIsWebDirProperties.NoCustomError");
+        if (MSI_NULL_INTEGER == pswp->fNoCustomError)
+            pswp->fNoCustomError = FALSE;
+
+        hr = WcaGetRecordInteger(hRec, wpqAccessSSLFlags, &pswp->iAccessSSLFlags);
+        ExitOnFailure(hr, "failed to get IIsWebDirProperties.AccessSSLFlags");
+
+        hr = WcaGetRecordString(hRec, wpqAuthenticationProviders, &pwzData);
+        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.AuthenticationProviders");
+        if (pwzData && *pwzData)
+        {
+            hr = ::StringCchCopyW(pswp->wzAuthenticationProviders, countof(pswp->wzAuthenticationProviders), pwzData);
+            ExitOnFailure(hr, "Failed to copy authentication providers string to webdirproperties object");
+        }
+        else
+        {
+            pswp->wzAuthenticationProviders[0] = L'\0';
+        }
+    }
+    else if (E_NOMOREITEMS == hr)
+    {
+        WcaLog(LOGMSG_STANDARD, "Error: Cannot locate IIsWebDirProperties.DirProperties='%ls'", wzProperties);
+        hr = E_FAIL;
+    }
+    else
+    {
+        ExitOnFailure(hr, "Error getting appropriate webdirproperty");
+    }
+
+    // Let's check that there isn't more than one record found - if there is, throw an assert like WcaFetchSingleRecord() would
+    HRESULT hrTemp = WcaFetchWrappedRecordWhereString(hWebDirPropQuery, 1, wzProperties, &hRec);
+    if (SUCCEEDED(hrTemp))
+    {
+        AssertSz(E_NOMOREITEMS == hrTemp, "ScaGetWebDirProperties found more than one record");
+    }
+
+LExit:
+    ReleaseStr(pwzData);
+
+    return hr;
+}
+
+
+HRESULT ScaWriteWebDirProperties(
+    __in IMSAdminBase* piMetabase,
+    __in LPCWSTR wzRootOfWeb,
+    __inout SCA_WEB_PROPERTIES* pswp
+    )
+{
+    HRESULT hr = S_OK;
+    DWORD dw = 0;
+    WCHAR wz[METADATA_MAX_NAME_LEN + 1];
+
+    // write the access permissions to the metabase
+    if (MSI_NULL_INTEGER != pswp->iAccess)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ACCESS_PERM, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswp->iAccess));
+        ExitOnFailure(hr, "Failed to write access permissions for Web");
+    }
+
+    if (MSI_NULL_INTEGER != pswp->iAuthorization)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_AUTHORIZATION, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswp->iAuthorization));
+        ExitOnFailure(hr, "Failed to write authorization for Web");
+    }
+
+    if (pswp->fHasUser)
+    {
+        Assert(pswp->scau.wzName);
+        // write the user name
+        if (*pswp->scau.wzDomain)
+        {
+            hr = ::StringCchPrintfW(wz, countof(wz), L"%s\\%s", pswp->scau.wzDomain, pswp->scau.wzName);
+            ExitOnFailure(hr, "Failed to format domain\\username string");
+        }
+        else
+        {
+            hr = ::StringCchCopyW(wz, countof(wz), pswp->scau.wzName);
+            ExitOnFailure(hr, "Failed to copy user name");
+        }
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ANONYMOUS_USER_NAME, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)wz);
+        ExitOnFailure(hr, "Failed to write anonymous user name for Web");
+
+        // write the password
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ANONYMOUS_PWD, METADATA_INHERIT | METADATA_SECURE, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pswp->scau.wzPassword);
+        ExitOnFailure(hr, "Failed to write anonymous user password for Web");
+
+        // store whether IIs controls password
+        dw = (pswp->fIIsControlledPassword) ? TRUE : FALSE;
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ANONYMOUS_USE_SUBAUTH, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)dw));
+        ExitOnFailure(hr, "Failed to write if IIs controls user password for Web");
+    }
+
+    if (MSI_NULL_INTEGER != pswp->fLogVisits)
+    {
+        // The sense of this boolean value is reversed - it is "don't log", not "log visits."
+        dw = (pswp->fLogVisits) ? FALSE : TRUE;
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_DONT_LOG, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)dw));
+        ExitOnFailure(hr, "Failed to write authorization for Web");
+    }
+
+    if (MSI_NULL_INTEGER != pswp->fIndex)
+    {
+        dw = (pswp->fIndex) ? TRUE : FALSE;
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_IS_CONTENT_INDEXED, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)dw));
+        ExitOnFailure(hr, "Failed to write authorization for Web");
+    }
+
+    if (pswp->fHasDefaultDoc)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_DEFAULT_LOAD_FILE, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pswp->wzDefaultDoc);
+        ExitOnFailure(hr, "Failed to write default documents for Web");
+    }
+
+    if (MSI_NULL_INTEGER != pswp->fAspDetailedError)
+    {
+        dw = (pswp->fAspDetailedError) ? TRUE : FALSE;
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_SCRIPTERRORSSENTTOBROWSER, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)dw));
+        ExitOnFailure(hr, "Failed to write ASP script error for Web");
+    }
+
+    if (pswp->fHasHttpExp)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_HTTP_EXPIRES, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pswp->wzHttpExp);
+        ExitOnFailure(hr, "Failed to write HTTP Expiration for Web");
+    }
+
+    if (MSI_NULL_INTEGER != pswp->iCacheControlMaxAge)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_CC_MAX_AGE, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswp->iCacheControlMaxAge));
+        ExitOnFailure(hr, "Failed to write Cache Control Max Age for Web");
+    }
+
+    if (pswp->fHasCacheControlCustom)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_CC_OTHER, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pswp->wzCacheControlCustom);
+        ExitOnFailure(hr, "Failed to write Cache Control Custom for Web");
+    }
+
+    if (pswp->fNoCustomError)
+    {
+        memset(wz, 0, sizeof(wz));
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_CUSTOM_ERROR, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, wz);
+        ExitOnFailure(hr, "Failed to write Custom Error for Web");
+    }
+
+    if (MSI_NULL_INTEGER != pswp->iAccessSSLFlags)
+    {
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_SSL_ACCESS_PERM, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswp->iAccessSSLFlags));
+        ExitOnFailure(hr, "Failed to write AccessSSLFlags for Web");
+    }
+
+    if (*pswp->wzAuthenticationProviders)
+    {
+        hr = ::StringCchCopyW(wz, countof(wz), pswp->wzAuthenticationProviders);
+        ExitOnFailure(hr, "Failed to copy authentication providers string");
+        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_NTAUTHENTICATION_PROVIDERS, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)wz);
+        ExitOnFailure(hr, "Failed to write AuthenticationProviders for Web");
+    }
+
+LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+#include "scauser.h"
+ 
+// global sql queries provided for optimization
+extern LPCWSTR vcsWebDirPropertiesQuery;
+
+
+// structs
+struct SCA_WEB_PROPERTIES
+{
+	WCHAR wzKey[MAX_DARWIN_KEY + 1];
+
+	int iAccess;
+
+	int iAuthorization;
+	BOOL fHasUser;
+	SCA_USER scau;
+	BOOL fIIsControlledPassword;
+
+	BOOL fLogVisits;
+	BOOL fIndex;
+
+	BOOL fHasDefaultDoc;
+	WCHAR wzDefaultDoc[MAX_DARWIN_COLUMN + 1];
+
+	BOOL fHasHttpExp;
+	WCHAR wzHttpExp[MAX_DARWIN_COLUMN + 1];
+
+	BOOL fAspDetailedError;
+
+	int iCacheControlMaxAge;
+
+	BOOL fHasCacheControlCustom;
+	WCHAR wzCacheControlCustom[MAX_DARWIN_COLUMN + 1];
+
+	BOOL fNoCustomError;
+
+	int iAccessSSLFlags;
+
+	WCHAR wzAuthenticationProviders[MAX_DARWIN_COLUMN + 1];
+};
+ 
+
+// prototypes
+HRESULT ScaGetWebDirProperties(
+    __in LPCWSTR pwzProperties,
+    __in WCA_WRAPQUERY_HANDLE hUserQuery,
+    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
+    __inout SCA_WEB_PROPERTIES* pswp
+    );
+
+HRESULT ScaWriteWebDirProperties(
+    __in IMSAdminBase* piMetabase,
+    __in LPCWSTR wzRootOfWeb, 
+    __inout SCA_WEB_PROPERTIES* pswp
+    );
+
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 @@
+// 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.
+
+#include "precomp.h"
+
+HRESULT ScaWriteWebDirProperties7(
+    __in_z LPCWSTR wzWebName,
+    __in_z LPCWSTR wzRootOfWeb,
+    __in const SCA_WEB_PROPERTIES* pswp
+    )
+{
+    HRESULT hr = S_OK;
+    WCHAR wz[METADATA_MAX_NAME_LEN + 1];
+
+    //all go to same web/root location tag
+    hr = ScaWriteConfigID(IIS_DIRPROP_BEGIN);
+    ExitOnFailure(hr, "Failed to write DirProp begin id");
+    hr = ScaWriteConfigString(wzWebName);                //site name key
+    ExitOnFailure(hr, "Failed to write DirProp web key");
+    hr = ScaWriteConfigString(wzRootOfWeb);               //app path key
+    ExitOnFailure(hr, "Failed to write DirProp app key");
+
+    // write the access permissions to the metabase
+    if (MSI_NULL_INTEGER != pswp->iAccess)
+    {
+        hr = ScaWriteConfigID(IIS_DIRPROP_ACCESS);
+        ExitOnFailure(hr, "Failed to write DirProp access id");
+        hr = ScaWriteConfigInteger(pswp->iAccess);
+        ExitOnFailure(hr, "Failed to write access permissions for Web");
+    }
+
+    if (MSI_NULL_INTEGER != pswp->iAuthorization)
+    {
+        hr = ScaWriteConfigID(IIS_DIRPROP_AUTH);
+        ExitOnFailure(hr, "Failed to write DirProp auth id");
+        hr = ScaWriteConfigInteger(pswp->iAuthorization);
+        ExitOnFailure(hr, "Failed to write authorization for Web");
+    }
+
+    if (pswp->fHasUser)
+    {
+        Assert(pswp->scau.wzName);
+        // write the user name
+        if (*pswp->scau.wzDomain)
+        {
+            hr = ::StringCchPrintfW(wz, countof(wz), L"%s\\%s", pswp->scau.wzDomain, pswp->scau.wzName);
+            ExitOnFailure(hr, "Failed to format domain\\username string");
+        }
+        else
+        {
+#pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW")
+            hr = ::StringCchCopyW(wz, countof(wz), pswp->scau.wzName);
+            ExitOnFailure(hr, "Failed to copy user name");
+        }
+        hr = ScaWriteConfigID(IIS_DIRPROP_USER);
+        ExitOnFailure(hr, "Failed to write DirProp user id");
+        hr = ScaWriteConfigString(wz);
+        ExitOnFailure(hr, "Failed to write anonymous user name for Web");
+
+        // write the password
+        hr = ScaWriteConfigID(IIS_DIRPROP_PWD);
+        ExitOnFailure(hr, "Failed to write DirProp pwd id");
+        hr = ScaWriteConfigString(pswp->scau.wzPassword);
+        ExitOnFailure(hr, "Failed to write anonymous user password for Web");
+
+        if (pswp->fIIsControlledPassword)
+        {
+            //Not Supported by IIS7 : pswp->fIIsControlledPassword
+            WcaLog(LOGMSG_VERBOSE, "Not supported by IIS7: WebDirProperties.IIsControlledPassword, ignoring");
+        }
+    }
+
+    if (MSI_NULL_INTEGER != pswp->fLogVisits)
+    {
+        hr = ScaWriteConfigID(IIS_DIRPROP_LOGVISITS);
+        ExitOnFailure(hr, "Failed to write DirProp logVisits id");
+        hr = ScaWriteConfigInteger(pswp->fLogVisits ? FALSE : TRUE); // we capture "should log" but IIS7 wants "should not log"
+        ExitOnFailure(hr, "Failed to write DirProp logVisits");
+    }
+
+    if (MSI_NULL_INTEGER != pswp->fIndex)
+    {
+        //Not Supported by IIS7 : pswp->fIndex
+        WcaLog(LOGMSG_VERBOSE, "Not supported by IIS7: WebDirProperties.Index, ignoring");
+    }
+
+    if (pswp->fHasDefaultDoc)
+    {
+        hr = ScaWriteConfigID(IIS_DIRPROP_DEFDOCS);
+        ExitOnFailure(hr, "Failed to write DirProp defdocs id");
+        hr = ScaWriteConfigString(pswp->wzDefaultDoc);
+        ExitOnFailure(hr, "Failed to write default documents for Web");
+    }
+
+    if (MSI_NULL_INTEGER != pswp->fAspDetailedError)
+    {
+        hr = ScaWriteConfigID(IIS_DIRPROP_ASPERROR);
+        ExitOnFailure(hr, "Failed to write ASP script error id");
+        hr = ScaWriteConfigInteger(pswp->fAspDetailedError);
+        ExitOnFailure(hr, "Failed to write ASP script error for Web");
+    }
+
+    if (pswp->fHasHttpExp)
+    {
+        hr = ScaWriteConfigID(IIS_DIRPROP_HTTPEXPIRES);
+        ExitOnFailure(hr, "Failed to write DirProp HttpExpires id");
+        hr = ScaWriteConfigString(pswp->wzHttpExp);
+        ExitOnFailure(hr, "Failed to write DirProp HttpExpires value");
+    }
+
+    if (MSI_NULL_INTEGER != pswp->iCacheControlMaxAge)
+    {
+        hr = ScaWriteConfigID(IIS_DIRPROP_MAXAGE);
+        ExitOnFailure(hr, "Failed to write DirProp MaxAge id");
+        hr = ScaWriteConfigInteger(pswp->iCacheControlMaxAge);
+        ExitOnFailure(hr, "Failed to write DirProp MaxAge value");
+    }
+
+    if (pswp->fHasCacheControlCustom)
+    {
+        hr = ScaWriteConfigID(IIS_DIRPROP_CACHECUST);
+        ExitOnFailure(hr, "Failed to write DirProp Cache Control Custom id");
+        hr = ScaWriteConfigString(pswp->wzCacheControlCustom);
+        ExitOnFailure(hr, "Failed to write Cache Control Custom for Web");
+    }
+
+    if (pswp->fNoCustomError)
+    {
+        hr = ScaWriteConfigID(IIS_DIRPROP_NOCUSTERROR);
+        ExitOnFailure(hr, "Failed to write DirProp clear Cust Errors id");
+    }
+
+    if (MSI_NULL_INTEGER != pswp->iAccessSSLFlags)
+    {
+        hr = ScaWriteConfigID(IIS_DIRPROP_SSLFLAGS);
+        ExitOnFailure(hr, "Failed to write DirProp sslFlags id");
+        hr = ScaWriteConfigInteger(pswp->iAccessSSLFlags);
+        ExitOnFailure(hr, "Failed to write AccessSSLFlags for Web");
+    }
+
+    if (*pswp->wzAuthenticationProviders)
+    {
+        hr = ::StringCchCopyW(wz, countof(wz), pswp->wzAuthenticationProviders);
+        ExitOnFailure(hr, "Failed to copy authentication providers string");
+        hr = ScaWriteConfigID(IIS_DIRPROP_AUTHPROVID);
+        ExitOnFailure(hr, "Failed to write DirProp AuthProvid id");
+        hr = ScaWriteConfigString(wz);
+        ExitOnFailure(hr, "Failed to write AuthenticationProviders for Web");
+    }
+    //End of Dir Properties
+    hr = ScaWriteConfigID(IIS_DIRPROP_END);
+    ExitOnFailure(hr, "Failed to write DirProp end id");
+
+LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+#include "scauser.h"
+
+HRESULT ScaWriteWebDirProperties7(
+    __in_z LPCWSTR wzwWebName,
+    __in_z LPCWSTR wzRootOfWeb,
+    const SCA_WEB_PROPERTIES* pswp
+    );
+
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 @@
+// 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.
+
+#include "precomp.h"
+
+// sql queries
+enum eWebSvcExtQuery { ldqComponent=1 , ldqFile, ldqDescription, ldqGroup, ldqAttributes, ldqInstalled, ldqAction };
+
+
+LPCWSTR vcsWebSvcExtRoot = L"/LM/W3SVC";
+
+// prototypes for private helper functions
+static HRESULT AddWebSvcExtToList(
+    __in SCA_WEBSVCEXT** ppsWseList
+    );
+
+//static HRESULT ScaCheckWebSvcExtValue(
+//    __in IMSAdminBase* piMetabase,
+//    __in DWORD dwMDIdentifier
+//    );
+
+static HRESULT ScaWebSvcExtInstall(
+    __in LPWSTR *pwzWebSvcExtList,
+    __in DWORD_PTR *pcchWebSvcExtList,
+    __in SCA_WEBSVCEXT* psWseList
+    );
+
+static HRESULT ScaWebSvcExtUninstall(
+    __in LPWSTR *pwzWebSvcExtList,
+    __in const DWORD *pcchWebSvcExtList,
+    __in SCA_WEBSVCEXT* psWseList
+    );
+
+// functions
+
+HRESULT __stdcall ScaWebSvcExtRead(
+    __in SCA_WEBSVCEXT** ppsWseList,
+    __inout LPWSTR *ppwzCustomActionData
+    )
+{
+    Assert(ppsWseList);
+
+    HRESULT hr = S_OK;
+    MSIHANDLE hRec;
+    LPWSTR pwzData = NULL;
+    INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN;
+    INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN;
+    SCA_WEBSVCEXT* psWebSvcExt = NULL;
+    WCA_WRAPQUERY_HANDLE hWrapQuery = NULL;
+
+    hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData);
+    ExitOnFailure(hr, "Failed to unwrap query for ScaWebSvcExtRead");
+
+    if (0 == WcaGetQueryRecords(hWrapQuery))
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ScaWebSvcExtRead() because IIsWebServiceExtension data not present");
+        ExitFunction1(hr = S_FALSE);
+    }
+
+    // loop through all the web service extensions
+    while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec)))
+    {
+        // Get the Component first.  If the Component is not being modified during
+        // this transaction, skip processing this whole record.
+        hr = WcaGetRecordString(hRec, ldqComponent, &pwzData);
+        ExitOnFailure(hr, "Failed to get Component for WebSvcExt");
+
+        hr = WcaGetRecordInteger(hRec, ldqInstalled, (int *)&isInstalled);
+        ExitOnFailure(hr, "Failed to get Component installed state for WebSvcExt");
+
+        hr = WcaGetRecordInteger(hRec, ldqAction, (int *)&isAction);
+        ExitOnFailure(hr, "Failed to get Component action state for WebSvcExt");
+
+        if (!WcaIsInstalling(isInstalled, isAction) &&
+            !WcaIsReInstalling(isInstalled, isAction) &&
+            !WcaIsUninstalling(isInstalled, isAction))
+        {
+            continue; // skip this record.
+        }
+
+        hr = AddWebSvcExtToList(ppsWseList);
+        ExitOnFailure(hr, "failed to add element to web svc ext list");
+
+        psWebSvcExt = *ppsWseList;
+        Assert(psWebSvcExt);
+
+        psWebSvcExt->isInstalled = isInstalled;
+        psWebSvcExt->isAction = isAction;
+
+        hr = WcaGetRecordString(hRec, ldqFile, &pwzData);
+        ExitOnFailure(hr, "Failed to get File for WebSvcExt");
+        hr = ::StringCchCopyW(psWebSvcExt->wzFile, countof(psWebSvcExt->wzFile), pwzData);
+        ExitOnFailure(hr, "Failed to copy File for WebSvcExt");
+
+        hr = WcaGetRecordString(hRec, ldqDescription, &pwzData);
+        ExitOnFailure(hr, "Failed to get Description for WebSvcExt");
+        hr = ::StringCchCopyW(psWebSvcExt->wzDescription, countof(psWebSvcExt->wzDescription), pwzData);
+        ExitOnFailure(hr, "Failed to copy Description for WebSvcExt");
+
+        hr = WcaGetRecordString(hRec, ldqGroup, &pwzData);
+        ExitOnFailure(hr, "Failed to get Group for WebSvcExt");
+        hr = ::StringCchCopyW(psWebSvcExt->wzGroup, countof(psWebSvcExt->wzGroup), pwzData);
+        ExitOnFailure(hr, "Failed to copy Group for WebSvcExt");
+
+        hr = WcaGetRecordInteger(hRec, ldqAttributes, &psWebSvcExt->iAttributes);
+        ExitOnFailure(hr, "Failed to get Attributes for WebSvcExt");
+    }
+
+    if (E_NOMOREITEMS == hr)
+        hr = S_OK;
+    ExitOnFailure(hr, "Failure while processing WebSvcExt");
+
+LExit:
+    WcaFinishUnwrapQuery(hWrapQuery);
+
+    ReleaseStr(pwzData);
+
+    return hr;
+}
+
+
+// Commit does both install and uninstall
+HRESULT __stdcall ScaWebSvcExtCommit(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_WEBSVCEXT* psWseList
+    )
+{
+    Assert(piMetabase);
+
+    HRESULT hr = S_OK;
+    METADATA_RECORD mr;
+
+    LPWSTR wzWebSvcExtList = NULL;
+    DWORD cbWebSvcExtList = 0;
+    DWORD_PTR cchWebSvcExtList = 0;
+
+    if (!psWseList)
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ScaWebSvcExtCommit() because there are no web service extensions in the list");
+        ExitFunction();
+    }
+
+    // Get current set of web service extensions.
+    ::ZeroMemory(&mr, sizeof(mr));
+    mr.dwMDIdentifier = MD_WEB_SVC_EXT_RESTRICTION_LIST;
+    mr.dwMDAttributes = 0;
+    mr.dwMDUserType  = IIS_MD_UT_SERVER;
+    mr.dwMDDataType = ALL_METADATA;
+    mr.pbMDData = NULL;
+    mr.dwMDDataLen = 0;
+
+    hr = piMetabase->GetData(METADATA_MASTER_ROOT_HANDLE, vcsWebSvcExtRoot, &mr, &cbWebSvcExtList);
+    if (MD_ERROR_DATA_NOT_FOUND == hr)
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ScaWebSvcExtCommit() because WebSvcExtRestrictionList value is not present");
+        ExitFunction1(hr = S_FALSE);
+    }
+    else if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr)
+    {
+        // cchWebSvcExtList is returned in bytes. Convert to WCHAR size to call StrAlloc
+        cchWebSvcExtList = cbWebSvcExtList / sizeof(WCHAR);
+        hr = StrAlloc(&wzWebSvcExtList, cchWebSvcExtList);
+        ExitOnFailure(hr, "Failed allocating space for web service extensions");
+    }
+    else
+    {
+        ExitOnFailure(hr, "Failed retrieving web service extensions");
+    }
+
+    mr.pbMDData = (unsigned char*)wzWebSvcExtList;
+    mr.dwMDDataLen = cbWebSvcExtList;
+
+    hr = piMetabase->GetData(METADATA_MASTER_ROOT_HANDLE, vcsWebSvcExtRoot, &mr, &cbWebSvcExtList);
+    ExitOnFailure(hr, "Failed retrieving web service extensions");
+
+    // Make changes to local copy of metabase
+    while (psWseList)
+    {
+        if (WcaIsInstalling(psWseList->isInstalled, psWseList->isAction))
+        {
+            hr = ScaWebSvcExtInstall(&wzWebSvcExtList, &cchWebSvcExtList, psWseList);
+            ExitOnFailure(hr, "Failed to install Web Service extension");
+        }
+        else if (WcaIsUninstalling(psWseList->isInstalled, psWseList->isAction))
+        {
+            hr = ScaWebSvcExtUninstall(&wzWebSvcExtList, (DWORD *)&cchWebSvcExtList, psWseList);
+            ExitOnFailure(hr, "Failed to uninstall Web Service extension");
+        }
+
+        psWseList = psWseList->psWseNext;
+    }
+
+    // Write Metabase
+    hr = ScaWriteMetabaseValue(piMetabase, vcsWebSvcExtRoot, NULL, MD_WEB_SVC_EXT_RESTRICTION_LIST, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, wzWebSvcExtList);
+    ExitOnFailure(hr, "Failed to write WebServiceExtensions: '%ls'", wzWebSvcExtList);
+
+LExit:
+    ReleaseStr(wzWebSvcExtList);
+
+    return hr;
+}
+
+
+static HRESULT ScaWebSvcExtInstall(
+    __in LPWSTR *ppwzWebSvcExtList,
+    __in DWORD_PTR *pcchWebSvcExtList,
+    __in SCA_WEBSVCEXT* psWseList
+    )
+{
+    Assert( ppwzWebSvcExtList && pcchWebSvcExtList && psWseList);
+    Assert(*ppwzWebSvcExtList);
+
+    HRESULT hr = S_OK;
+
+    LPWSTR pwzWebSvcExt = NULL;
+    int iAllow;
+    int iUiDeletable;
+
+    BOOL fAlreadyExists = FALSE;
+    DWORD_PTR dwIndex = 0xFFFFFFFF;
+    LPCWSTR wzFoundString = NULL;
+
+    // Check if it's already in there
+    hr = MultiSzFindSubstring(*ppwzWebSvcExtList, psWseList->wzFile, &dwIndex, &wzFoundString);
+    ExitOnFailure(hr, "failed to search for string:%ls in web service extension MULTISZ", psWseList->wzFile);
+
+    if (S_FALSE != hr && NULL != wcsstr(wzFoundString, psWseList->wzGroup) && NULL != wcsstr(wzFoundString, psWseList->wzDescription))
+    {
+        fAlreadyExists = TRUE;
+    }
+
+    // Construct the single string in the format required for the WebSvc Ext list in metabase
+    iAllow = (psWseList->iAttributes & 1);
+    iUiDeletable = ((psWseList->iAttributes >> 1) & 1);
+    hr = StrAllocFormatted(&pwzWebSvcExt, L"%d,%s,%d,%s,%s", iAllow, psWseList->wzFile, iUiDeletable, psWseList->wzGroup, psWseList->wzDescription);
+    ExitOnFailure(hr, "Failure allocating space for web service extensions");
+
+    if (fAlreadyExists)
+    {
+        hr = MultiSzReplaceString(ppwzWebSvcExtList, dwIndex, pwzWebSvcExt);
+        ExitOnFailure(hr, "failed to update web service extension string: %ls", pwzWebSvcExt);
+    }
+    else
+    {
+        hr = MultiSzPrepend(ppwzWebSvcExtList, pcchWebSvcExtList, pwzWebSvcExt);
+        ExitOnFailure(hr, "failed to prepend web service extension string: %ls", pwzWebSvcExt);
+    }
+
+LExit:
+    ReleaseStr(pwzWebSvcExt);
+
+    return hr;
+}
+
+
+static HRESULT ScaWebSvcExtUninstall(
+    __in LPWSTR *ppwzWebSvcExtList,
+    __in const DWORD* /*pcchWebSvcExtList*/,
+    __in SCA_WEBSVCEXT* psWseList
+    )
+{
+    Assert(ppwzWebSvcExtList && *ppwzWebSvcExtList && psWseList);
+    Assert(*ppwzWebSvcExtList);
+
+    HRESULT hr = S_OK;
+    DWORD_PTR dwIndex = 0xFFFFFFFF;
+    LPCWSTR wzFoundString = NULL;
+
+    // Find the string to remove
+    hr = MultiSzFindSubstring(*ppwzWebSvcExtList, psWseList->wzFile, &dwIndex, &wzFoundString);
+    ExitOnFailure(hr, "failed to search for string:%ls in web service extension MULTISZ", psWseList->wzFile);
+
+    // If we found a match (ignoring the Allow and Deletable flags)
+    if (S_FALSE != hr && NULL != wcsstr(wzFoundString, psWseList->wzGroup) && NULL != wcsstr(wzFoundString, psWseList->wzDescription))
+    {
+        hr = MultiSzRemoveString(ppwzWebSvcExtList, dwIndex);
+        ExitOnFailure(hr, "failed to remove string: %d from web service extension MULTISZ", dwIndex);
+    }
+
+LExit:
+    return hr;
+}
+
+
+//static HRESULT ScaCheckWebSvcExtValue(
+//    __in IMSAdminBase* piMetabase,
+//    __in DWORD dwMDIdentifier
+//    )
+//{
+//    if (!piMetabase)
+//    {
+//        return E_INVALIDARG;
+//    }
+//
+//    HRESULT hr = S_OK;
+//    METADATA_RECORD mr = { 0 };
+//    DWORD cch = 0;
+//
+//    mr.dwMDIdentifier = dwMDIdentifier;
+//    mr.dwMDUserType  = IIS_MD_UT_SERVER;
+//
+//    hr = piMetabase->GetData(METADATA_MASTER_ROOT_HANDLE, vcsWebSvcExtRoot, &mr, &cch);
+//    if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr)
+//    {
+//        hr = S_OK;
+//    }
+//    else if (MD_ERROR_DATA_NOT_FOUND == hr)
+//    {
+//        hr = S_FALSE;
+//    }
+//
+//    return hr;
+//}
+
+
+void ScaWebSvcExtFreeList(
+    __in SCA_WEBSVCEXT* psWseList
+    )
+{
+    SCA_WEBSVCEXT* psWseDelete = psWseList;
+    while (psWseList)
+    {
+        psWseDelete = psWseList;
+        psWseList = psWseList->psWseNext;
+        MemFree(psWseDelete);
+    }
+}
+
+
+static HRESULT AddWebSvcExtToList(
+    __in SCA_WEBSVCEXT** ppsWseList
+    )
+{
+    HRESULT hr = S_OK;
+
+    SCA_WEBSVCEXT* psWse = static_cast<SCA_WEBSVCEXT*>(MemAlloc(sizeof(SCA_WEBSVCEXT), TRUE));
+    ExitOnNull(psWse, hr, E_OUTOFMEMORY, "failed to allocate element for web svc ext list");
+
+    psWse->psWseNext = *ppsWseList;
+    *ppsWseList = psWse;
+
+LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+enum SCA_WEBSVCEXT_ATTRIBUTES { SWSEATTRIB_ALLOW = 1, SWSEATTRIB_UIDELETABLE = 2 };
+
+struct SCA_WEBSVCEXT
+{
+    // darwin information
+    INSTALLSTATE isInstalled;
+    INSTALLSTATE isAction;
+
+    // iis configuation information
+    WCHAR wzFile[MAX_PATH + 1];
+    WCHAR wzDescription[MAX_DARWIN_COLUMN + 1];
+    WCHAR wzGroup[MAX_DARWIN_COLUMN + 1];
+
+    int iAttributes;
+
+    SCA_WEBSVCEXT* psWseNext;
+};
+
+HRESULT __stdcall ScaWebSvcExtRead(
+    __in SCA_WEBSVCEXT** ppsWseList,
+    __inout LPWSTR *ppwzCustomActionData
+    );
+
+HRESULT ScaWebSvcExtCommit(
+    __in IMSAdminBase* piMetabase,
+    __in SCA_WEBSVCEXT* psWseList
+    );
+
+void ScaWebSvcExtFreeList(
+    __in SCA_WEBSVCEXT* psWseList
+    );
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 @@
+// 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.
+
+#include "precomp.h"
+
+static HRESULT ScaWebSvcExtInstall(
+    const SCA_WEBSVCEXT* psWseList
+    );
+
+static HRESULT ScaWebSvcExtUninstall(
+    const SCA_WEBSVCEXT* psWseList
+    );
+
+// functions
+// Commit does both install and uninstall
+HRESULT __stdcall ScaWebSvcExtCommit7(
+    __in SCA_WEBSVCEXT* psWseList
+    )
+{
+    HRESULT hr = S_OK;
+
+    if (!psWseList)
+    {
+        WcaLog(LOGMSG_VERBOSE, "Skipping ScaWebSvcExtCommit() because there are no web service extensions in the list");
+        ExitFunction();
+    }
+
+    // Make changes to local copy of metabase
+    while (psWseList)
+    {
+        if (WcaIsInstalling(psWseList->isInstalled, psWseList->isAction))
+        {
+            hr = ScaWebSvcExtInstall(psWseList);
+            ExitOnFailure(hr, "Failed to install Web Service extension");
+        }
+        else if (WcaIsUninstalling(psWseList->isInstalled, psWseList->isAction))
+        {
+            hr = ScaWebSvcExtUninstall(psWseList);
+            ExitOnFailure(hr, "Failed to uninstall Web Service extension");
+        }
+
+        psWseList = psWseList->psWseNext;
+    }
+
+
+LExit:
+
+    return hr;
+}
+
+
+static HRESULT ScaWebSvcExtInstall(
+    const SCA_WEBSVCEXT* psWseList
+    )
+{
+    HRESULT hr = S_OK;
+    int iAllow;
+
+    //Write CAData actions
+    hr = ScaWriteConfigID(IIS_WEB_SVC_EXT);
+    ExitOnFailure(hr, "failed add web svc ext ID");
+    hr = ScaWriteConfigID(IIS_CREATE);
+    ExitOnFailure(hr, "failed add web svc ext action");
+
+    // write File path
+    hr = ScaWriteConfigString(psWseList->wzFile);
+    ExitOnFailure(hr, "failed add web svc ext file path");
+
+    // write allowed
+    // unDeleatable n/a in IIS7
+    iAllow = (psWseList->iAttributes & 1);
+    hr = ScaWriteConfigInteger(iAllow);
+    ExitOnFailure(hr, "failed add web svc ext Allowed");
+
+    //write group
+    hr = ScaWriteConfigString(psWseList->wzGroup);
+    ExitOnFailure(hr, "failed add web svc ext group");
+
+    //write description
+    hr = ScaWriteConfigString(psWseList->wzDescription);
+    ExitOnFailure(hr, "failed add web svc ext description");
+
+LExit:
+
+    return hr;
+}
+
+
+static HRESULT ScaWebSvcExtUninstall(
+    const SCA_WEBSVCEXT* psWseList
+    )
+{
+    HRESULT hr = S_OK;
+
+    //Write CAData actions
+    hr = ScaWriteConfigID(IIS_WEB_SVC_EXT);
+    ExitOnFailure(hr, "failed add web svc ext ID");
+    hr = ScaWriteConfigID(IIS_DELETE);
+    ExitOnFailure(hr, "failed add web svc ext action");
+
+    // write File path (Key)
+    hr = ScaWriteConfigString(psWseList->wzFile);
+    ExitOnFailure(hr, "failed add web svc ext file path");
+
+LExit:
+    return hr;
+}
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 @@
+#pragma once
+// 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.
+
+
+HRESULT ScaWebSvcExtCommit7(
+    __in SCA_WEBSVCEXT* psWseList
+    );
+
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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <packageSources>
+    <clear />
+    <add key="wixtoolset-burn" value="https://ci.appveyor.com/nuget/wixtoolset-burn" />
+    <add key="wixtoolset-data" value="https://ci.appveyor.com/nuget/wixtoolset-data" />
+    <add key="wixtoolset-extensibility" value="https://ci.appveyor.com/nuget/wixtoolset-extensibility" />
+    <add key="wixtoolset-core" value="https://ci.appveyor.com/nuget/wixtoolset-core" />
+    <add key="wixtoolset-core-native" value="https://ci.appveyor.com/nuget/wixtoolset-core-native" />
+    <add key="wixtoolset-dtf" value="https://ci.appveyor.com/nuget/wixtoolset-dtf" />
+    <add key="wixtoolset-dutil" value="https://ci.appveyor.com/nuget/wixtoolset-dutil" />
+    <add key="wixtoolset-wcautil" value="https://ci.appveyor.com/nuget/wixtoolset-wcautil" />
+    <add key="wixtoolset-tools" value="https://ci.appveyor.com/nuget/wixtoolset-tools" />
+    <add key="wixbuildtools" value="https://ci.appveyor.com/nuget/wixbuildtools" />
+    <add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
+  </packageSources>
+</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 @@
+// 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.
+
+namespace WixToolsetTest.Iis
+{
+    using System.Linq;
+    using WixBuildTools.TestSupport;
+    using WixToolset.Core.TestPackage;
+    using WixToolset.Iis;
+    using Xunit;
+
+    public class IisExtensionFixture
+    {
+        [Fact]
+        public void CanBuildUsingIIsWebAddress()
+        {
+            var folder = TestData.Get(@"TestData\UsingIis");
+            var build = new Builder(folder, typeof(IisExtensionFactory), new[] { folder });
+
+            var results = build.BuildAndQuery(Build, "IIsWebAddress");
+            Assert.Equal(new[]
+            {
+                "IIsWebAddress:TestAddress\tTest\t\t[PORT]\t\t0",
+            }, results);
+        }
+
+        private static void Build(string[] args)
+        {
+            var result = WixRunner.Execute(args)
+                                  .AssertSuccess();
+        }
+    }
+}
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 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+This file contains the declaration of all the localizable strings.
+-->
+<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US">
+
+  <String Id="DowngradeError">A newer version of [ProductName] is already installed.</String>
+  <String Id="FeatureTitle">MsiPackage</String>
+
+</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 @@
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
+  <Package Name="MsiPackage" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a" InstallerVersion="200">
+    <MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" />
+
+    <Feature Id="ProductFeature" Title="!(loc.FeatureTitle)">
+      <ComponentGroupRef Id="ProductComponents" />
+    </Feature>
+  </Package>
+
+  <Fragment>
+    <StandardDirectory Id="ProgramFilesFolder">
+      <Directory Id="INSTALLFOLDER" Name="MsiPackage">
+        <Directory Id="TestWebSiteProductDirectory" />
+      </Directory>
+    </StandardDirectory>
+  </Fragment>
+</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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
+     xmlns:iis="http://wixtoolset.org/schemas/v4/wxs/iis">
+  <Fragment>
+    <Property Id="PORT" Value="3062" />
+    <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
+       <Component>
+         <File Source="example.txt" />
+         <iis:WebSite Id="Test" Description="Test web server" Directory="TestWebSiteProductDirectory" AutoStart="yes" DirProperties="ReadAndExecute" ConfigureIfExists="no" >
+            <iis:WebAddress Id="TestAddress" Port="[PORT]" Secure="no" />
+         </iis:WebSite>
+       </Component>
+    </ComponentGroup>
+    <iis:WebDirProperties Id="ReadAndExecute" />
+  </Fragment>
+</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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>netcoreapp3.1</TargetFramework>
+    <IsPackable>false</IsPackable>
+  </PropertyGroup>
+
+  <PropertyGroup>
+    <NoWarn>NU1701</NoWarn>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Content Include="TestData\UsingIis\example.txt" CopyToOutputDirectory="PreserveNewest" />
+    <Content Include="TestData\UsingIis\Package.en-us.wxl" CopyToOutputDirectory="PreserveNewest" />
+    <Content Include="TestData\UsingIis\Package.wxs" CopyToOutputDirectory="PreserveNewest" />
+    <Content Include="TestData\UsingIis\PackageComponents.wxs" CopyToOutputDirectory="PreserveNewest" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\wixext\WixToolset.Iis.wixext.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="WixToolset.Core" Version="4.0.*" />
+    <PackageReference Include="WixToolset.Core.Burn" Version="4.0.*" />
+    <PackageReference Include="WixToolset.Core.WindowsInstaller" Version="4.0.*" />
+    <PackageReference Include="WixToolset.Core.TestPackage" Version="4.0.*" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="WixBuildTools.TestSupport" Version="4.0.*" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
+    <PackageReference Include="xunit" Version="2.4.1" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" PrivateAssets="All" />
+  </ItemGroup>
+</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 @@
+<ProjectConfiguration>
+  <Settings>
+    <CopyReferencedAssembliesToWorkspace>True</CopyReferencedAssembliesToWorkspace>
+  </Settings>
+</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
Binary files /dev/null and b/src/ext/Iis/wix.snk 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Globalization;
+    using System.Xml.Linq;
+    using WixToolset.Data;
+    using WixToolset.Extensibility;
+    using WixToolset.Extensibility.Data;
+    using WixToolset.Iis.Symbols;
+
+    /// <summary>
+    /// The compiler for the WiX Toolset Internet Information Services Extension.
+    /// </summary>
+    public sealed class IIsCompiler : BaseCompilerExtension
+    {
+        public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/iis";
+
+        /// <summary>
+        /// Types of objects that custom HTTP Headers can be applied to.
+        /// </summary>
+        /// <remarks>Note that this must be kept in sync with the eHttpHeaderParentType in scahttpheader.h.</remarks>
+        private enum HttpHeaderParentType
+        {
+            /// <summary>Custom HTTP Header is to be applied to a Web Virtual Directory.</summary>
+            WebVirtualDir = 1,
+            /// <summary>Custom HTTP Header is to be applied to a Web Site.</summary>
+            WebSite = 2,
+        }
+
+        /// <summary>
+        /// Types of objects that MimeMaps can be applied to.
+        /// </summary>
+        /// <remarks>Note that this must be kept in sync with the eMimeMapParentType in scamimemap.h.</remarks>
+        private enum MimeMapParentType
+        {
+            /// <summary>MimeMap is to be applied to a Web Virtual Directory.</summary>
+            WebVirtualDir = 1,
+            WebSite = 2,
+        }
+
+        /// <summary>
+        /// Types of objects that custom WebErrors can be applied to.
+        /// </summary>
+        /// <remarks>Note that this must be kept in sync with the eWebErrorParentType in scaweberror.h.</remarks>
+        private enum WebErrorParentType
+        {
+            /// <summary>Custom WebError is to be applied to a Web Virtual Directory.</summary>
+            WebVirtualDir = 1,
+
+            /// <summary>Custom WebError is to be applied to a Web Site.</summary>
+            WebSite = 2,
+        }
+
+        /// <summary>
+        /// Processes an element for the Compiler.
+        /// </summary>
+        /// <param name="sourceLineNumbers">Source line number for the parent element.</param>
+        /// <param name="parentElement">Parent element of element to process.</param>
+        /// <param name="element">Element to process.</param>
+        /// <param name="contextValues">Extra information about the context in which this element is being parsed.</param>
+        public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary<string, string> context)
+        {
+            switch (parentElement.Name.LocalName)
+            {
+                case "Component":
+                    var componentId = context["ComponentId"];
+                    var directoryId = context["DirectoryId"];
+
+                    switch (element.Name.LocalName)
+                    {
+                        case "Certificate":
+                            this.ParseCertificateElement(intermediate, section, element, componentId);
+                            break;
+                        case "WebAppPool":
+                            this.ParseWebAppPoolElement(intermediate, section, element, componentId);
+                            break;
+                        case "WebDir":
+                            this.ParseWebDirElement(intermediate, section, element, componentId, null);
+                            break;
+                        case "WebFilter":
+                            this.ParseWebFilterElement(intermediate, section, element, componentId, null);
+                            break;
+                        case "WebProperty":
+                            this.ParseWebPropertyElement(intermediate, section, element, componentId);
+                            break;
+                        case "WebServiceExtension":
+                            this.ParseWebServiceExtensionElement(intermediate, section, element, componentId);
+                            break;
+                        case "WebSite":
+                            this.ParseWebSiteElement(intermediate, section, element, componentId);
+                            break;
+                        case "WebVirtualDir":
+                            this.ParseWebVirtualDirElement(intermediate, section, element, componentId, null, null);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedElement(parentElement, element);
+                            break;
+                    }
+                    break;
+                case "Fragment":
+                case "Module":
+                case "Package":
+                    switch (element.Name.LocalName)
+                    {
+                        case "WebApplication":
+                            this.ParseWebApplicationElement(intermediate, section, element);
+                            break;
+                        case "WebAppPool":
+                            this.ParseWebAppPoolElement(intermediate, section, element, null);
+                            break;
+                        case "WebDirProperties":
+                            this.ParseWebDirPropertiesElement(intermediate, section, element, null);
+                            break;
+                        case "WebLog":
+                            this.ParseWebLogElement(intermediate, section, element);
+                            break;
+                        case "WebSite":
+                            this.ParseWebSiteElement(intermediate, section, element, null);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedElement(parentElement, element);
+                            break;
+                    }
+                    break;
+                default:
+                    this.ParseHelper.UnexpectedElement(parentElement, element);
+                    break;
+            }
+        }
+
+        /// <summary>
+        /// Parses a certificate element.
+        /// </summary>
+        /// <param name="element">Element to parse.</param>
+        /// <param name="componentId">Identifier for parent component.</param>
+        private void ParseCertificateElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
+        {
+            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
+            Identifier id = null;
+            int attributes = 8; // SCA_CERT_ATTRIBUTE_VITAL
+            string binaryRef = null;
+            string certificatePath = null;
+            string name = null;
+            string pfxPassword = null;
+            int storeLocation = 0;
+            string storeName = null;
+
+            foreach (var attrib in element.Attributes())
+            {
+                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
+                {
+                    switch (attrib.Name.LocalName)
+                    {
+                        case "Id":
+                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
+                            break;
+                        case "BinaryRef":
+                            attributes |= 2; // SCA_CERT_ATTRIBUTE_BINARYDATA
+                            binaryRef = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
+                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Binary, binaryRef);
+                            break;
+                        case "CertificatePath":
+                            certificatePath = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "Name":
+                            name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "Overwrite":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                attributes |= 4; // SCA_CERT_ATTRIBUTE_OVERWRITE
+                            }
+                            else
+                            {
+                                attributes &= ~4; // SCA_CERT_ATTRIBUTE_OVERWRITE
+                            }
+                            break;
+                        case "PFXPassword":
+                            pfxPassword = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "Request":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                attributes |= 1; // SCA_CERT_ATTRIBUTE_REQUEST
+                            }
+                            else
+                            {
+                                attributes &= ~1; // SCA_CERT_ATTRIBUTE_REQUEST
+                            }
+                            break;
+                        case "StoreLocation":
+                            var storeLocationValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            if (0 < storeLocationValue.Length)
+                            {
+                                switch (storeLocationValue)
+                                {
+                                    case "currentUser":
+                                        storeLocation = 1; // SCA_CERTSYSTEMSTORE_CURRENTUSER
+                                        break;
+                                    case "localMachine":
+                                        storeLocation = 2; // SCA_CERTSYSTEMSTORE_LOCALMACHINE
+                                        break;
+                                    default:
+                                        storeLocation = -1;
+                                        this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "StoreLocation", storeLocationValue, "currentUser", "localMachine"));
+                                        break;
+                                }
+                            }
+                            break;
+                        case "StoreName":
+                            var storeNameValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            if (0 < storeNameValue.Length)
+                            {
+                                switch (storeNameValue)
+                                {
+                                    case "ca":
+                                        storeName = "CA";
+                                        break;
+                                    case "my":
+                                    case "personal":
+                                        storeName = "MY";
+                                        break;
+                                    case "request":
+                                        storeName = "REQUEST";
+                                        break;
+                                    case "root":
+                                        storeName = "Root";
+                                        break;
+                                    case "otherPeople":
+                                        storeName = "AddressBook";
+                                        break;
+                                    case "trustedPeople":
+                                        storeName = "TrustedPeople";
+                                        break;
+                                    case "trustedPublisher":
+                                        storeName = "TrustedPublisher";
+                                        break;
+                                    default:
+                                        this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "StoreName", storeNameValue, "ca", "my", "request", "root", "otherPeople", "trustedPeople", "trustedPublisher"));
+                                        break;
+                                }
+                            }
+                            break;
+                        case "Vital":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                attributes |= 8; // SCA_CERT_ATTRIBUTE_VITAL
+                            }
+                            else
+                            {
+                                attributes &= ~8; // SCA_CERT_ATTRIBUTE_VITAL
+                            }
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedAttribute(element, attrib);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
+                }
+            }
+
+
+            if (null == id)
+            {
+                id = this.ParseHelper.CreateIdentifier("crt", componentId, binaryRef, certificatePath);
+            }
+
+            if (null == name)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
+            }
+
+            if (0 == storeLocation)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "StoreLocation"));
+            }
+
+            if (null == storeName)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "StoreName"));
+            }
+
+            if (null != binaryRef && null != certificatePath)
+            {
+                this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "BinaryRef", "CertificatePath", certificatePath));
+            }
+            else if (null == binaryRef && null == certificatePath)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, element.Name.LocalName, "BinaryRef", "CertificatePath"));
+            }
+
+            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
+
+            // Reference InstallCertificates and UninstallCertificates since nothing will happen without them
+            this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4InstallCertificates", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
+            this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4UninstallCertificates", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
+            this.ParseHelper.EnsureTable(section, sourceLineNumbers, IisTableDefinitions.CertificateHash); // Certificate CustomActions require the CertificateHash table
+
+            if (!this.Messaging.EncounteredError)
+            {
+                section.AddSymbol(new CertificateSymbol(sourceLineNumbers, id)
+                {
+                    ComponentRef = componentId,
+                    Name = name,
+                    StoreLocation = storeLocation,
+                    StoreName = storeName,
+                    Attributes = attributes,
+                    BinaryRef = binaryRef,
+                    CertificatePath = certificatePath,
+                    PFXPassword = pfxPassword,
+                });
+            }
+        }
+
+        /// <summary>
+        /// Parses a CertificateRef extension element.
+        /// </summary>
+        /// <param name="element">Element to parse.</param>
+        /// <param name="webId">Identifier for parent web site.</param>
+        private void ParseCertificateRefElement(Intermediate intermediate, IntermediateSection section, XElement element, string webId)
+        {
+            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
+            Identifier id = null;
+
+            foreach (var attrib in element.Attributes())
+            {
+                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
+                {
+                    switch (attrib.Name.LocalName)
+                    {
+                        case "Id":
+                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
+                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.Certificate, id.Id);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedAttribute(element, attrib);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
+                }
+            }
+
+            if (null == id)
+            {
+                id = this.ParseHelper.CreateIdentifier("wsc", webId);
+            }
+
+            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
+
+            if (!this.Messaging.EncounteredError)
+            {
+                this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.Certificate, id.Id);
+
+                section.AddSymbol(new IIsWebSiteCertificatesSymbol(sourceLineNumbers)
+                {
+                    WebRef = webId,
+                    CertificateRef = id.Id,
+                });
+            }
+        }
+
+        /// <summary>
+        /// Parses a mime map element.
+        /// </summary>
+        /// <param name="element">Element to parse.</param>
+        /// <param name="parentId">Identifier for parent symbol.</param>
+        /// <param name="parentType">Type that parentId refers to.</param>
+        private void ParseMimeMapElement(Intermediate intermediate, IntermediateSection section, XElement element, string parentId, MimeMapParentType parentType)
+        {
+            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
+            Identifier id = null;
+            string extension = null;
+            string type = null;
+
+            foreach (var attrib in element.Attributes())
+            {
+                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
+                {
+                    switch (attrib.Name.LocalName)
+                    {
+                        case "Id":
+                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
+                            break;
+                        case "Extension":
+                            extension = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "Type":
+                            type = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedAttribute(element, attrib);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
+                }
+            }
+
+            if (null == id)
+            {
+                id = this.ParseHelper.CreateIdentifier("imm", parentId, type, extension);
+            }
+
+            if (null == extension)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Extension"));
+            }
+            else if (0 < extension.Length)
+            {
+                if (!extension.StartsWith(".", StringComparison.Ordinal))
+                {
+                    this.Messaging.Write(IIsErrors.MimeMapExtensionMissingPeriod(sourceLineNumbers, element.Name.LocalName, "Extension", extension));
+                }
+            }
+
+            if (null == type)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Type"));
+            }
+
+            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
+
+            if (!this.Messaging.EncounteredError)
+            {
+                section.AddSymbol(new IIsMimeMapSymbol(sourceLineNumbers, id)
+                {
+                    ParentType = (int)parentType,
+                    ParentValue = parentId,
+                    MimeType = type,
+                    Extension = extension,
+                });
+            }
+        }
+
+        /// <summary>
+        /// Parses a recycle time element.
+        /// </summary>
+        /// <param name="element">Element to parse.</param>
+        /// <returns>Recycle time value.</returns>
+        private string ParseRecycleTimeElement(Intermediate intermediate, IntermediateSection section, XElement element)
+        {
+            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
+            string value = null;
+
+            foreach (var attrib in element.Attributes())
+            {
+                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
+                {
+                    switch (attrib.Name.LocalName)
+                    {
+                        case "Value":
+                            value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedAttribute(element, attrib);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
+                }
+            }
+
+            if (null == value)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Value"));
+            }
+
+            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
+
+            return value;
+        }
+
+        /// <summary>
+        /// Parses a web address element.
+        /// </summary>
+        /// <param name="element">Element to parse.</param>
+        /// <param name="parentWeb">Identifier of parent web site.</param>
+        /// <returns>Identifier for web address.</returns>
+        private string ParseWebAddressElement(Intermediate intermediate, IntermediateSection section, XElement element, string parentWeb)
+        {
+            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
+            Identifier id = null;
+            string header = null;
+            string ip = null;
+            string port = null;
+            var secure = false;
+
+            foreach (var attrib in element.Attributes())
+            {
+                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
+                {
+                    switch (attrib.Name.LocalName)
+                    {
+                        case "Id":
+                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
+                            break;
+                        case "Header":
+                            header = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "IP":
+                            ip = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "Port":
+                            port = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "Secure":
+                            secure = YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedAttribute(element, attrib);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
+                }
+            }
+
+            if (null == id)
+            {
+                id = this.ParseHelper.CreateIdentifier("iwa", parentWeb, ip, port);
+            }
+
+            if (null == port)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Port"));
+            }
+
+            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
+
+            if (!this.Messaging.EncounteredError)
+            {
+                section.AddSymbol(new IIsWebAddressSymbol(sourceLineNumbers, id)
+                {
+                    WebRef = parentWeb,
+                    IP = ip,
+                    Port = port,
+                    Header = header,
+                    Secure = secure ? 1 : 0,
+                });
+            }
+
+            return id?.Id;
+        }
+
+        /// <summary>
+        /// Parses a web application element.
+        /// </summary>
+        /// <param name="element">Element to parse.</param>
+        /// <returns>Identifier for web application.</returns>
+        private string ParseWebApplicationElement(Intermediate intermediate, IntermediateSection section, XElement element)
+        {
+            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
+            Identifier id = null;
+            var allowSessions = YesNoDefaultType.Default;
+            string appPool = null;
+            var buffer = YesNoDefaultType.Default;
+            var clientDebugging = YesNoDefaultType.Default;
+            string defaultScript = null;
+            int isolation = 0;
+            string name = null;
+            var parentPaths = YesNoDefaultType.Default;
+            var scriptTimeout = CompilerConstants.IntegerNotSet;
+            var sessionTimeout = CompilerConstants.IntegerNotSet;
+            var serverDebugging = YesNoDefaultType.Default;
+
+            foreach (var attrib in element.Attributes())
+            {
+                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
+                {
+                    switch (attrib.Name.LocalName)
+                    {
+                        case "Id":
+                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
+                            break;
+                        case "AllowSessions":
+                            allowSessions = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
+                            break;
+                        case "Buffer":
+                            buffer = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
+                            break;
+                        case "ClientDebugging":
+                            clientDebugging = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
+                            break;
+                        case "DefaultScript":
+                            defaultScript = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            if (0 < defaultScript.Length)
+                            {
+                                switch (defaultScript)
+                                {
+                                    case "JScript":
+                                    case "VBScript":
+                                        // these are valid values
+                                        break;
+                                    default:
+                                        this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, defaultScript, "JScript", "VBScript"));
+                                        break;
+                                }
+                            }
+                            break;
+                        case "Isolation":
+                            string isolationValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            if (0 < isolationValue.Length)
+                            {
+                                switch (isolationValue)
+                                {
+                                    case "low":
+                                        isolation = 0;
+                                        break;
+                                    case "medium":
+                                        isolation = 2;
+                                        break;
+                                    case "high":
+                                        isolation = 1;
+                                        break;
+                                    default:
+                                        this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, isolationValue, "low", "medium", "high"));
+                                        break;
+                                }
+                            }
+                            break;
+                        case "Name":
+                            name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "ParentPaths":
+                            parentPaths = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
+                            break;
+                        case "ScriptTimeout":
+                            scriptTimeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
+                            break;
+                        case "ServerDebugging":
+                            serverDebugging = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
+                            break;
+                        case "SessionTimeout":
+                            sessionTimeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
+                            break;
+                        case "WebAppPool":
+                            appPool = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
+                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsAppPool, appPool);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedAttribute(element, attrib);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
+                }
+            }
+
+            if (null == id)
+            {
+                id = this.ParseHelper.CreateIdentifier("wap", name, appPool);
+            }
+
+            if (null == name)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
+            }
+            else if (-1 != name.IndexOf("\\", StringComparison.Ordinal))
+            {
+                this.Messaging.Write(IIsErrors.IllegalCharacterInAttributeValue(sourceLineNumbers, element.Name.LocalName, "Name", name, '\\'));
+            }
+
+            foreach (var child in element.Elements())
+            {
+                if (this.Namespace == child.Name.Namespace)
+                {
+                    switch (child.Name.LocalName)
+                    {
+                        case "WebApplicationExtension":
+                            this.ParseWebApplicationExtensionElement(intermediate, section, child, id?.Id);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedElement(element, child);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
+                }
+            }
+
+            if (!this.Messaging.EncounteredError)
+            {
+                var symbol = section.AddSymbol(new IIsWebApplicationSymbol(sourceLineNumbers, id)
+                {
+                    Name = name,
+                    Isolation = isolation,
+                    DefaultScript = defaultScript,
+                    AppPoolRef = appPool,
+                });
+
+                if (YesNoDefaultType.Default != allowSessions)
+                {
+                    symbol.AllowSessions = YesNoDefaultType.Yes == allowSessions ? 1 : 0;
+                }
+
+                if (CompilerConstants.IntegerNotSet != sessionTimeout)
+                {
+                    symbol.SessionTimeout = sessionTimeout;
+                }
+
+                if (YesNoDefaultType.Default != buffer)
+                {
+                    symbol.Buffer = YesNoDefaultType.Yes == buffer ? 1 : 0;
+                }
+
+                if (YesNoDefaultType.Default != parentPaths)
+                {
+                    symbol.ParentPaths = YesNoDefaultType.Yes == parentPaths ? 1 : 0;
+                }
+
+                if (CompilerConstants.IntegerNotSet != scriptTimeout)
+                {
+                    symbol.ScriptTimeout = scriptTimeout;
+                }
+
+                if (YesNoDefaultType.Default != serverDebugging)
+                {
+                    symbol.ServerDebugging = YesNoDefaultType.Yes == serverDebugging ? 1 : 0;
+                }
+
+                if (YesNoDefaultType.Default != clientDebugging)
+                {
+                    symbol.ClientDebugging = YesNoDefaultType.Yes == clientDebugging ? 1 : 0;
+                }
+            }
+
+            return id?.Id;
+        }
+
+        /// <summary>
+        /// Parses a web application extension element.
+        /// </summary>
+        /// <param name="element">Element to parse.</param>
+        /// <param name="application">Identifier for parent web application.</param>
+        private void ParseWebApplicationExtensionElement(Intermediate intermediate, IntermediateSection section, XElement element, string application)
+        {
+            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
+            int attributes = 0;
+            string executable = null;
+            string extension = null;
+            string verbs = null;
+
+            foreach (var attrib in element.Attributes())
+            {
+                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
+                {
+                    switch (attrib.Name.LocalName)
+                    {
+                        case "CheckPath":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                attributes |= 4;
+                            }
+                            else
+                            {
+                                attributes &= ~4;
+                            }
+                            break;
+                        case "Executable":
+                            executable = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "Extension":
+                            extension = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "Script":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                attributes |= 1;
+                            }
+                            else
+                            {
+                                attributes &= ~1;
+                            }
+                            break;
+                        case "Verbs":
+                            verbs = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedAttribute(element, attrib);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
+                }
+            }
+
+            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
+
+            if (!this.Messaging.EncounteredError)
+            {
+                var symbol = section.AddSymbol(new IIsWebApplicationExtensionSymbol(sourceLineNumbers)
+                {
+                    ApplicationRef = application,
+                    Extension = extension,
+                    Verbs = verbs,
+                    Executable = executable,
+                });
+
+                if (0 < attributes)
+                {
+                    symbol.Attributes = attributes;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Parses web application pool element.
+        /// </summary>
+        /// <param name="element">Element to parse.</param>
+        /// <param name="componentId">Optional identifier of parent component.</param>
+        private void ParseWebAppPoolElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
+        {
+            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
+            Identifier id = null;
+            int attributes = 0;
+            var cpuAction = CompilerConstants.IntegerNotSet;
+            string cpuMon = null;
+            var idleTimeout = CompilerConstants.IntegerNotSet;
+            int maxCpuUsage = 0;
+            var maxWorkerProcs = CompilerConstants.IntegerNotSet;
+            string managedRuntimeVersion = null;
+            string managedPipelineMode = null;
+            string name = null;
+            var privateMemory = CompilerConstants.IntegerNotSet;
+            var queueLimit = CompilerConstants.IntegerNotSet;
+            var recycleMinutes = CompilerConstants.IntegerNotSet;
+            var recycleRequests = CompilerConstants.IntegerNotSet;
+            string recycleTimes = null;
+            var refreshCpu = CompilerConstants.IntegerNotSet;
+            string user = null;
+            var virtualMemory = CompilerConstants.IntegerNotSet;
+
+            foreach (var attrib in element.Attributes())
+            {
+                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
+                {
+                    switch (attrib.Name.LocalName)
+                    {
+                        case "Id":
+                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
+                            break;
+                        case "CpuAction":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            var cpuActionValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            if (0 < cpuActionValue.Length)
+                            {
+                                switch (cpuActionValue)
+                                {
+                                    case "shutdown":
+                                        cpuAction = 1;
+                                        break;
+                                    case "none":
+                                        cpuAction = 0;
+                                        break;
+                                    default:
+                                        this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, cpuActionValue, "shutdown", "none"));
+                                        break;
+                                }
+                            }
+                            break;
+                        case "Identity":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            var identityValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            if (0 < identityValue.Length)
+                            {
+                                switch (identityValue)
+                                {
+                                    case "networkService":
+                                        attributes |= 1;
+                                        break;
+                                    case "localService":
+                                        attributes |= 2;
+                                        break;
+                                    case "localSystem":
+                                        attributes |= 4;
+                                        break;
+                                    case "other":
+                                        attributes |= 8;
+                                        break;
+                                    case "applicationPoolIdentity":
+                                        attributes |= 0x10;
+                                        break;
+                                    default:
+                                        this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, identityValue, "networkService", "localService", "localSystem", "other", "applicationPoolIdentity"));
+                                        break;
+                                }
+                            }
+                            break;
+                        case "IdleTimeout":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            idleTimeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
+                            break;
+                        case "ManagedPipelineMode":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            managedPipelineMode = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+
+
+                            if (!String.IsNullOrEmpty(managedPipelineMode))
+                            {
+                                switch (managedPipelineMode)
+                                {
+                                    // In 3.5 we allowed lower case values (per camel case enum style), we now use formatted fields,
+                                    // so the value needs to match exactly what we pass in to IIS which uses pascal case.
+                                    case "classic":
+                                        managedPipelineMode = "Classic";
+                                        break;
+                                    case "integrated":
+                                        managedPipelineMode = "Integrated";
+                                        break;
+                                    case "Classic":
+                                        break;
+                                    case "Integrated":
+                                        break;
+                                    default:
+                                        if (!this.ParseHelper.ContainsProperty(managedPipelineMode))
+                                        {
+                                            this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, managedPipelineMode, "Classic", "Integrated"));
+                                        }
+                                        break;
+                                }
+                            }
+
+                            break;
+                        case "ManagedRuntimeVersion":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            managedRuntimeVersion = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "MaxCpuUsage":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            maxCpuUsage = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 100);
+                            break;
+                        case "MaxWorkerProcesses":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            maxWorkerProcs = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
+                            break;
+                        case "Name":
+                            name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "PrivateMemory":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            privateMemory = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 4294967);
+                            break;
+                        case "QueueLimit":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            queueLimit = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
+                            break;
+                        case "RecycleMinutes":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            recycleMinutes = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
+                            break;
+                        case "RecycleRequests":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            recycleRequests = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
+                            break;
+                        case "RefreshCpu":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            refreshCpu = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue);
+                            break;
+                        case "User":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            user = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
+                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "User", user);
+                            break;
+                        case "VirtualMemory":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            virtualMemory = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 4294967);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedAttribute(element, attrib);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
+                }
+            }
+
+            if (null == id)
+            {
+                id = this.ParseHelper.CreateIdentifier("iap", name, componentId, user);
+            }
+
+            if (null == name)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
+            }
+
+            if (null == user && 8 == (attributes & 0x1F))
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "User", "Identity", "other"));
+            }
+
+            if (null != user && 8 != (attributes & 0x1F))
+            {
+                this.Messaging.Write(ErrorMessages.IllegalAttributeValueWithoutOtherAttribute(sourceLineNumbers, element.Name.LocalName, "User", user, "Identity", "other"));
+            }
+
+            cpuMon = maxCpuUsage.ToString(CultureInfo.InvariantCulture.NumberFormat);
+            if (CompilerConstants.IntegerNotSet != refreshCpu)
+            {
+                cpuMon = String.Concat(cpuMon, ",", refreshCpu.ToString(CultureInfo.InvariantCulture.NumberFormat));
+                if (CompilerConstants.IntegerNotSet != cpuAction)
+                {
+                    cpuMon = String.Concat(cpuMon, ",", cpuAction.ToString(CultureInfo.InvariantCulture.NumberFormat));
+                }
+            }
+
+            foreach (var child in element.Elements())
+            {
+                if (this.Namespace == child.Name.Namespace)
+                {
+                    switch (child.Name.LocalName)
+                    {
+                        case "RecycleTime":
+                            if (null == componentId)
+                            {
+                                var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child);
+                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, element.Name.LocalName));
+                            }
+
+                            if (null == recycleTimes)
+                            {
+                                recycleTimes = this.ParseRecycleTimeElement(intermediate, section, child);
+                            }
+                            else
+                            {
+                                recycleTimes = String.Concat(recycleTimes, ",", this.ParseRecycleTimeElement(intermediate, section, child));
+                            }
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedElement(element, child);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
+                }
+            }
+
+            if (null != componentId)
+            {
+                // Reference ConfigureIIs since nothing will happen without it
+                this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
+            }
+
+            if (!this.Messaging.EncounteredError)
+            {
+                var symbol = section.AddSymbol(new IIsAppPoolSymbol(sourceLineNumbers, id)
+                {
+                    Name = name,
+                    ComponentRef = componentId,
+                    Attributes = attributes,
+                    UserRef = user,
+                    RecycleTimes = recycleTimes,
+                    CPUMon = cpuMon,
+                    ManagedRuntimeVersion = managedRuntimeVersion,
+                    ManagedPipelineMode = managedPipelineMode,
+                });
+
+                if (CompilerConstants.IntegerNotSet != recycleMinutes)
+                {
+                    symbol.RecycleMinutes = recycleMinutes;
+                }
+
+                if (CompilerConstants.IntegerNotSet != recycleRequests)
+                {
+                    symbol.RecycleRequests = recycleRequests;
+                }
+
+                if (CompilerConstants.IntegerNotSet != idleTimeout)
+                {
+                    symbol.IdleTimeout = idleTimeout;
+                }
+
+                if (CompilerConstants.IntegerNotSet != queueLimit)
+                {
+                    symbol.QueueLimit = queueLimit;
+                }
+
+                if (CompilerConstants.IntegerNotSet != maxWorkerProcs)
+                {
+                    symbol.MaxProc = maxWorkerProcs;
+                }
+
+                if (CompilerConstants.IntegerNotSet != virtualMemory)
+                {
+                    symbol.VirtualMemory = virtualMemory;
+                }
+
+                if (CompilerConstants.IntegerNotSet != privateMemory)
+                {
+                    symbol.PrivateMemory = privateMemory;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Parses a web directory element.
+        /// </summary>
+        /// <param name="element">Element to parse.</param>
+        /// <param name="componentId">Identifier for parent component.</param>
+        /// <param name="parentWeb">Optional identifier for parent web site.</param>
+        private void ParseWebDirElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string parentWeb)
+        {
+            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
+            Identifier id = null;
+            string dirProperties = null;
+            string path = null;
+            string application = null;
+
+            foreach (var attrib in element.Attributes())
+            {
+                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
+                {
+                    switch (attrib.Name.LocalName)
+                    {
+                        case "Id":
+                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
+                            break;
+                        case "DirProperties":
+                            dirProperties = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
+                            break;
+                        case "Path":
+                            path = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "WebApplication":
+                            application = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "WebSite":
+                            if (null != parentWeb)
+                            {
+                                this.Messaging.Write(IIsErrors.WebSiteAttributeUnderWebSite(sourceLineNumbers, element.Name.LocalName));
+                            }
+
+                            parentWeb = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
+                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebSite, parentWeb);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedAttribute(element, attrib);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
+                }
+            }
+
+            if (null == id)
+            {
+                id = this.ParseHelper.CreateIdentifier("iwd", componentId, parentWeb, dirProperties, application);
+            }
+
+            if (null == path)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Path"));
+            }
+
+            if (null == parentWeb)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "WebSite"));
+            }
+
+            foreach (var child in element.Elements())
+            {
+                if (this.Namespace == child.Name.Namespace)
+                {
+                    var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child);
+                    switch (child.Name.LocalName)
+                    {
+                        case "WebApplication":
+                            if (null != application)
+                            {
+                                this.Messaging.Write(IIsErrors.WebApplicationAlreadySpecified(childSourceLineNumbers, element.Name.LocalName));
+                            }
+
+                            application = this.ParseWebApplicationElement(intermediate, section, child);
+                            break;
+                        case "WebDirProperties":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
+                            }
+
+                            string childWebDirProperties = this.ParseWebDirPropertiesElement(intermediate, section, child, componentId);
+                            if (null == dirProperties)
+                            {
+                                dirProperties = childWebDirProperties;
+                            }
+                            else
+                            {
+                                this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, child.Name.LocalName, "DirProperties", child.Name.LocalName));
+                            }
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedElement(element, child);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
+                }
+            }
+
+            if (null == dirProperties)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "DirProperties"));
+            }
+
+            if (null != application)
+            {
+                this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebApplication, application);
+            }
+
+            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebDirProperties, dirProperties);
+
+            // Reference ConfigureIIs since nothing will happen without it
+            this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
+
+            if (!this.Messaging.EncounteredError)
+            {
+                section.AddSymbol(new IIsWebDirSymbol(sourceLineNumbers, id)
+                {
+                    ComponentRef = componentId,
+                    WebRef = parentWeb,
+                    Path = path,
+                    DirPropertiesRef = dirProperties,
+                    ApplicationRef = application,
+                });
+            }
+        }
+
+        /// <summary>
+        /// Parses a web directory properties element.
+        /// </summary>
+        /// <param name="element">Element to parse.</param>
+        /// <returns>The identifier for this WebDirProperties.</returns>
+        private string ParseWebDirPropertiesElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
+        {
+            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
+            Identifier id = null;
+            int access = 0;
+            var accessSet = false;
+            int accessSSLFlags = 0;
+            var accessSSLFlagsSet = false;
+            string anonymousUser = null;
+            var aspDetailedError = YesNoType.NotSet;
+            string authenticationProviders = null;
+            int authorization = 0;
+            var authorizationSet = false;
+            string cacheControlCustom = null;
+            var cacheControlMaxAge = CompilerConstants.LongNotSet;
+            string defaultDocuments = null;
+            string httpExpires = null;
+            var iisControlledPassword = false;
+            var index = YesNoType.NotSet;
+            var logVisits = YesNoType.NotSet;
+            var notCustomError = YesNoType.NotSet;
+
+            foreach (var attrib in element.Attributes())
+            {
+                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
+                {
+                    switch (attrib.Name.LocalName)
+                    {
+                        case "Id":
+                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
+                            break;
+                        case "AnonymousUser":
+                            anonymousUser = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
+                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "User", anonymousUser);
+                            break;
+                        case "AspDetailedError":
+                            aspDetailedError = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
+                            break;
+                        case "AuthenticationProviders":
+                            authenticationProviders = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "CacheControlCustom":
+                            cacheControlCustom = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "CacheControlMaxAge":
+                            cacheControlMaxAge = this.ParseHelper.GetAttributeLongValue(sourceLineNumbers, attrib, 0, uint.MaxValue); // 4294967295 (uint.MaxValue) represents unlimited
+                            break;
+                        case "ClearCustomError":
+                            notCustomError = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
+                            break;
+                        case "DefaultDocuments":
+                            defaultDocuments = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "HttpExpires":
+                            httpExpires = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "IIsControlledPassword":
+                            iisControlledPassword = YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
+                            break;
+                        case "Index":
+                            index = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
+                            break;
+                        case "LogVisits":
+                            logVisits = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
+                            break;
+
+                        // Access attributes
+                        case "Execute":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                access |= 4;
+                            }
+                            else
+                            {
+                                access &= ~4;
+                            }
+                            accessSet = true;
+                            break;
+                        case "Read":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                access |= 1;
+                            }
+                            else
+                            {
+                                access &= ~1;
+                            }
+                            accessSet = true;
+                            break;
+                        case "Script":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                access |= 512;
+                            }
+                            else
+                            {
+                                access &= ~512;
+                            }
+                            accessSet = true;
+                            break;
+                        case "Write":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                access |= 2;
+                            }
+                            else
+                            {
+                                access &= ~2;
+                            }
+                            accessSet = true;
+                            break;
+
+                        // AccessSSL Attributes
+                        case "AccessSSL":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                accessSSLFlags |= 8;
+                            }
+                            else
+                            {
+                                accessSSLFlags &= ~8;
+                            }
+                            accessSSLFlagsSet = true;
+                            break;
+                        case "AccessSSL128":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                accessSSLFlags |= 256;
+                            }
+                            else
+                            {
+                                accessSSLFlags &= ~256;
+                            }
+                            accessSSLFlagsSet = true;
+                            break;
+                        case "AccessSSLMapCert":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                accessSSLFlags |= 128;
+                            }
+                            else
+                            {
+                                accessSSLFlags &= ~128;
+                            }
+                            accessSSLFlagsSet = true;
+                            break;
+                        case "AccessSSLNegotiateCert":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                accessSSLFlags |= 32;
+                            }
+                            else
+                            {
+                                accessSSLFlags &= ~32;
+                            }
+                            accessSSLFlagsSet = true;
+                            break;
+                        case "AccessSSLRequireCert":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                accessSSLFlags |= 64;
+                            }
+                            else
+                            {
+                                accessSSLFlags &= ~64;
+                            }
+                            accessSSLFlagsSet = true;
+                            break;
+
+                        // Authorization attributes
+                        case "AnonymousAccess":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                authorization |= 1;
+                            }
+                            else
+                            {
+                                authorization &= ~1;
+                            }
+                            authorizationSet = true;
+                            break;
+                        case "BasicAuthentication":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                authorization |= 2;
+                            }
+                            else
+                            {
+                                authorization &= ~2;
+                            }
+                            authorizationSet = true;
+                            break;
+                        case "DigestAuthentication":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                authorization |= 16;
+                            }
+                            else
+                            {
+                                authorization &= ~16;
+                            }
+                            authorizationSet = true;
+                            break;
+                        case "PassportAuthentication":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                authorization |= 64;
+                            }
+                            else
+                            {
+                                authorization &= ~64;
+                            }
+                            authorizationSet = true;
+                            break;
+                        case "WindowsAuthentication":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                authorization |= 4;
+                            }
+                            else
+                            {
+                                authorization &= ~4;
+                            }
+                            authorizationSet = true;
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedAttribute(element, attrib);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
+                }
+            }
+
+            if (null == id)
+            {
+                if (null == componentId)
+                {
+                    this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Id"));
+                    id = Identifier.Invalid;
+                }
+                else
+                {
+                    id = this.ParseHelper.CreateIdentifier("wdp", componentId);
+                }
+            }
+
+            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
+
+            if (!this.Messaging.EncounteredError)
+            {
+                var symbol = section.AddSymbol(new IIsWebDirPropertiesSymbol(sourceLineNumbers, id)
+                {
+                    AnonymousUserRef = anonymousUser,
+                    IIsControlledPassword = iisControlledPassword ? 1 : 0,
+                    DefaultDoc = defaultDocuments,
+                    HttpExpires = httpExpires,
+                    CacheControlCustom = cacheControlCustom,
+                });
+
+                if (accessSet)
+                {
+                    symbol.Access = access;
+                }
+
+                if (authorizationSet)
+                {
+                    symbol.Authorization = authorization;
+                }
+
+                if (YesNoType.NotSet != logVisits)
+                {
+                    symbol.LogVisits = YesNoType.Yes == logVisits ? 1 : 0;
+                }
+
+                if (YesNoType.NotSet != index)
+                {
+                    symbol.Index = YesNoType.Yes == index ? 1 : 0;
+                }
+
+                if (YesNoType.NotSet != aspDetailedError)
+                {
+                    symbol.AspDetailedError = YesNoType.Yes == aspDetailedError ? 1 : 0;
+                }
+
+                if (CompilerConstants.LongNotSet != cacheControlMaxAge)
+                {
+                    symbol.CacheControlMaxAge = unchecked((int)cacheControlMaxAge);
+                }
+
+                if (YesNoType.NotSet != notCustomError)
+                {
+                    symbol.NoCustomError = YesNoType.Yes == notCustomError ? 1 : 0;
+                }
+
+                if (accessSSLFlagsSet)
+                {
+                    symbol.AccessSSLFlags = accessSSLFlags;
+                }
+
+                if (null != authenticationProviders)
+                {
+                    symbol.AuthenticationProviders = authenticationProviders;
+                }
+            }
+
+            return id?.Id;
+        }
+
+        /// <summary>
+        /// Parses a web error element.
+        /// </summary>
+        /// <param name="element">Element to parse.</param>
+        /// <param name="parentType">Type of the parent.</param>
+        /// <param name="parent">Id of the parent.</param>
+        private void ParseWebErrorElement(Intermediate intermediate, IntermediateSection section, XElement element, WebErrorParentType parentType, string parent)
+        {
+            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
+            var errorCode = CompilerConstants.IntegerNotSet;
+            string file = null;
+            string url = null;
+            var subCode = CompilerConstants.IntegerNotSet;
+
+            foreach (var attrib in element.Attributes())
+            {
+                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
+                {
+                    switch (attrib.Name.LocalName)
+                    {
+                        case "ErrorCode":
+                            errorCode = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 400, 599);
+                            break;
+                        case "File":
+                            file = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "SubCode":
+                            subCode = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue);
+                            break;
+                        case "URL":
+                            url = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedAttribute(element, attrib);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
+                }
+            }
+
+            if (CompilerConstants.IntegerNotSet == errorCode)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "ErrorCode"));
+                errorCode = CompilerConstants.IllegalInteger;
+            }
+
+            if (CompilerConstants.IntegerNotSet == subCode)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "SubCode"));
+                subCode = CompilerConstants.IllegalInteger;
+            }
+
+            if (String.IsNullOrEmpty(file) && String.IsNullOrEmpty(url))
+            {
+                this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "File", "URL"));
+            }
+
+            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
+
+            // Reference ConfigureIIs since nothing will happen without it
+            this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
+
+            if (!this.Messaging.EncounteredError)
+            {
+                section.AddSymbol(new IIsWebErrorSymbol(sourceLineNumbers)
+                {
+                    ErrorCode = errorCode,
+                    SubCode = subCode,
+                    ParentType = (int)parentType,
+                    ParentValue = parent,
+                    File = file,
+                    URL = url,
+                });
+            }
+        }
+
+        /// <summary>
+        /// Parses a web filter element.
+        /// </summary>
+        /// <param name="element">Element to parse.</param>
+        /// <param name="componentId">Identifier of parent component.</param>
+        /// <param name="parentWeb">Optional identifier of parent web site.</param>
+        private void ParseWebFilterElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string parentWeb)
+        {
+            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
+            Identifier id = null;
+            string description = null;
+            int flags = 0;
+            var loadOrder = CompilerConstants.IntegerNotSet;
+            string name = null;
+            string path = null;
+
+            foreach (var attrib in element.Attributes())
+            {
+                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
+                {
+                    switch (attrib.Name.LocalName)
+                    {
+                        case "Id":
+                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
+                            break;
+                        case "Description":
+                            description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "Flags":
+                            flags = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue);
+                            break;
+                        case "LoadOrder":
+                            string loadOrderValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            if (0 < loadOrderValue.Length)
+                            {
+                                switch (loadOrderValue)
+                                {
+                                    case "first":
+                                        loadOrder = 0;
+                                        break;
+                                    case "last":
+                                        loadOrder = -1;
+                                        break;
+                                    default:
+                                        loadOrder = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, short.MaxValue);
+                                        break;
+                                }
+                            }
+                            break;
+                        case "Name":
+                            name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "Path":
+                            path = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "WebSite":
+                            if (null != parentWeb)
+                            {
+                                this.Messaging.Write(IIsErrors.WebSiteAttributeUnderWebSite(sourceLineNumbers, element.Name.LocalName));
+                            }
+
+                            parentWeb = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
+                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebSite, parentWeb);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedAttribute(element, attrib);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
+                }
+            }
+
+            if (null == id)
+            {
+                id = this.ParseHelper.CreateIdentifier("ifl", name, componentId, path, parentWeb);
+            }
+
+            if (null == name)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
+            }
+
+            if (null == path)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Path"));
+            }
+
+            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
+
+            // Reference ConfigureIIs since nothing will happen without it
+            this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
+
+            if (!this.Messaging.EncounteredError)
+            {
+                var symbol = section.AddSymbol(new IIsFilterSymbol(sourceLineNumbers, id)
+                {
+                    Name = name,
+                    ComponentRef = componentId,
+                    Path = path,
+                    WebRef = parentWeb,
+                    Description = description,
+                    Flags = flags,
+                });
+
+                if (CompilerConstants.IntegerNotSet != loadOrder)
+                {
+                    symbol.LoadOrder = loadOrder;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Parses web log element.
+        /// </summary>
+        /// <param name="element">Node to be parsed.</param>
+        private void ParseWebLogElement(Intermediate intermediate, IntermediateSection section, XElement element)
+        {
+            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
+            Identifier id = null;
+            string type = null;
+
+            foreach (var attrib in element.Attributes())
+            {
+                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
+                {
+                    switch (attrib.Name.LocalName)
+                    {
+                        case "Id":
+                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
+                            break;
+                        case "Type":
+                            var typeValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            if (0 < typeValue.Length)
+                            {
+                                switch (typeValue)
+                                {
+                                    case "IIS":
+                                        type = "Microsoft IIS Log File Format";
+                                        break;
+                                    case "NCSA":
+                                        type = "NCSA Common Log File Format";
+                                        break;
+                                    case "none":
+                                        type = "none";
+                                        break;
+                                    case "ODBC":
+                                        type = "ODBC Logging";
+                                        break;
+                                    case "W3C":
+                                        type = "W3C Extended Log File Format";
+                                        break;
+                                    default:
+                                        this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Type", typeValue, "IIS", "NCSA", "none", "ODBC", "W3C"));
+                                        break;
+                                }
+                            }
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedAttribute(element, attrib);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
+                }
+            }
+
+            if (null == id)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Id"));
+            }
+
+            if (null == type)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Type"));
+            }
+
+            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
+
+            if (!this.Messaging.EncounteredError)
+            {
+                section.AddSymbol(new IIsWebLogSymbol(sourceLineNumbers, id)
+                {
+                    Format = type,
+                });
+            }
+        }
+
+        /// <summary>
+        /// Parses a web property element.
+        /// </summary>
+        /// <param name="element">Element to parse.</param>
+        /// <param name="componentId">Identifier for parent component.</param>
+        private void ParseWebPropertyElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
+        {
+            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
+            Identifier id = null;
+            string value = null;
+
+            foreach (var attrib in element.Attributes())
+            {
+                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
+                {
+                    switch (attrib.Name.LocalName)
+                    {
+                        case "Id":
+                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
+                            break;
+                        case "Value":
+                            value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedAttribute(element, attrib);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
+                }
+            }
+
+            switch (id?.Id)
+            {
+                case "ETagChangeNumber":
+                case "MaxGlobalBandwidth":
+                    // Must specify a value for these
+                    if (null == value)
+                    {
+                        this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Value", "Id", id.Id));
+                    }
+                    break;
+                case "IIs5IsolationMode":
+                case "LogInUTF8":
+                    // Can't specify a value for these
+                    if (null != value)
+                    {
+                        this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "Value", "Id", id.Id));
+                    }
+                    break;
+                default:
+                    this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Id", id?.Id, "ETagChangeNumber", "IIs5IsolationMode", "LogInUTF8", "MaxGlobalBandwidth"));
+                    break;
+            }
+
+            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
+
+            // Reference ConfigureIIs since nothing will happen without it
+            this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
+
+            if (!this.Messaging.EncounteredError)
+            {
+                section.AddSymbol(new IIsPropertySymbol(sourceLineNumbers, id)
+                {
+                    ComponentRef = componentId,
+                    Attributes = 0,
+                    Value = value,
+                });
+            }
+        }
+
+        /// <summary>
+        /// Parses a web service extension element.
+        /// </summary>
+        /// <param name="element">Element to parse.</param>
+        /// <param name="componentId">Identifier for parent component.</param>
+        private void ParseWebServiceExtensionElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
+        {
+            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
+            Identifier id = null;
+            int attributes = 0;
+            string description = null;
+            string file = null;
+            string group = null;
+
+            foreach (XAttribute attrib in element.Attributes())
+            {
+                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
+                {
+                    switch (attrib.Name.LocalName)
+                    {
+                        case "Id":
+                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
+                            break;
+                        case "Allow":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                attributes |= 1;
+                            }
+                            else
+                            {
+                                attributes &= ~1;
+                            }
+                            break;
+                        case "Description":
+                            description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "File":
+                            file = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "Group":
+                            group = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "UIDeletable":
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                attributes |= 2;
+                            }
+                            else
+                            {
+                                attributes &= ~2;
+                            }
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedAttribute(element, attrib);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
+                }
+            }
+
+            if (null == id)
+            {
+                id = this.ParseHelper.CreateIdentifier("iwe", componentId, file);
+            }
+
+            if (null == file)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "File"));
+            }
+
+            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
+
+            // Reference ConfigureIIs since nothing will happen without it
+            this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
+
+            if (!this.Messaging.EncounteredError)
+            {
+                section.AddSymbol(new IIsWebServiceExtensionSymbol(sourceLineNumbers, id)
+                {
+                    ComponentRef = componentId,
+                    File = file,
+                    Description = description,
+                    Group = group,
+                    Attributes = attributes,
+                });
+            }
+        }
+
+        /// <summary>
+        /// Parses a web site element.
+        /// </summary>
+        /// <param name="element">Element to parse.</param>
+        /// <param name="componentId">Optional identifier of parent component.</param>
+        private void ParseWebSiteElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
+        {
+            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
+            Identifier id = null;
+            string application = null;
+            int attributes = 0;
+            var connectionTimeout = CompilerConstants.IntegerNotSet;
+            string description = null;
+            string directory = null;
+            string dirProperties = null;
+            string keyAddress = null;
+            string log = null;
+            string siteId = null;
+            var sequence = CompilerConstants.IntegerNotSet;
+            var state = CompilerConstants.IntegerNotSet;
+
+            foreach (var attrib in element.Attributes())
+            {
+                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
+                {
+                    switch (attrib.Name.LocalName)
+                    {
+                        case "Id":
+                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
+                            break;
+                        case "AutoStart":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                state = 2;
+                            }
+                            else if (state != 1)
+                            {
+                                state = 0;
+                            }
+                            break;
+                        case "ConfigureIfExists":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                attributes &= ~2;
+                            }
+                            else
+                            {
+                                attributes |= 2;
+                            }
+                            break;
+                        case "ConnectionTimeout":
+                            connectionTimeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
+                            break;
+                        case "Description":
+                            description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "Directory":
+                            directory = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
+                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Directory, directory);
+                            break;
+                        case "DirProperties":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            dirProperties = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "SiteId":
+                            siteId = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            if ("*" == siteId)
+                            {
+                                siteId = "-1";
+                            }
+                            break;
+                        case "Sequence":
+                            sequence = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, short.MaxValue);
+                            break;
+                        case "StartOnInstall":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            // when state is set to 2 it implies 1, so don't set it to 1
+                            if (2 != state && YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
+                            {
+                                state = 1;
+                            }
+                            else if (2 != state)
+                            {
+                                state = 0;
+                            }
+                            break;
+                        case "WebApplication":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            application = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "WebLog":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
+                            }
+
+                            log = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
+                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebLog, log);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedAttribute(element, attrib);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
+                }
+            }
+
+            if (null == id)
+            {
+                id = this.ParseHelper.CreateIdentifier("iws", description, componentId, siteId, application);
+            }
+
+            if (null == description)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Description"));
+            }
+
+            if (null == directory && null != componentId)
+            {
+                this.Messaging.Write(IIsErrors.RequiredAttributeUnderComponent(sourceLineNumbers, element.Name.LocalName, "Directory"));
+            }
+
+            foreach (var child in element.Elements())
+            {
+                if (this.Namespace == child.Name.Namespace)
+                {
+                    var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child);
+                    switch (child.Name.LocalName)
+                    {
+                        case "CertificateRef":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
+                            }
+
+                            this.ParseCertificateRefElement(intermediate, section, child, id?.Id);
+                            break;
+                        case "HttpHeader":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
+                            }
+
+                            this.ParseHttpHeaderElement(intermediate, section, child, HttpHeaderParentType.WebSite, id?.Id);
+                            break;
+                        case "WebAddress":
+                            string address = this.ParseWebAddressElement(intermediate, section, child, id?.Id);
+                            if (null == keyAddress)
+                            {
+                                keyAddress = address;
+                            }
+                            break;
+                        case "WebApplication":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
+                            }
+
+                            if (null != application)
+                            {
+                                this.Messaging.Write(IIsErrors.WebApplicationAlreadySpecified(childSourceLineNumbers, element.Name.LocalName));
+                            }
+
+                            application = this.ParseWebApplicationElement(intermediate, section, child);
+                            break;
+                        case "WebDir":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
+                            }
+
+                            this.ParseWebDirElement(intermediate, section, child, componentId, id?.Id);
+                            break;
+                        case "WebDirProperties":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
+                            }
+
+                            string childWebDirProperties = this.ParseWebDirPropertiesElement(intermediate, section, child, componentId);
+                            if (null == dirProperties)
+                            {
+                                dirProperties = childWebDirProperties;
+                            }
+                            else
+                            {
+                                this.Messaging.Write(ErrorMessages.IllegalParentAttributeWhenNested(sourceLineNumbers, "WebSite", "DirProperties", child.Name.LocalName));
+                            }
+                            break;
+                        case "WebError":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
+                            }
+
+                            this.ParseWebErrorElement(intermediate, section, child, WebErrorParentType.WebSite, id?.Id);
+                            break;
+                        case "WebFilter":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
+                            }
+
+                            this.ParseWebFilterElement(intermediate, section, child, componentId, id?.Id);
+                            break;
+                        case "WebVirtualDir":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
+                            }
+
+                            this.ParseWebVirtualDirElement(intermediate, section, child, componentId, id?.Id, null);
+                            break;
+                        case "MimeMap":
+                            this.ParseMimeMapElement(intermediate, section, child, id?.Id, MimeMapParentType.WebSite);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedElement(element, child);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
+                }
+            }
+
+
+            if (null == keyAddress)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedElement(sourceLineNumbers, element.Name.LocalName, "WebAddress"));
+            }
+
+            if (null != application)
+            {
+                this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebApplication, application);
+            }
+
+            if (null != dirProperties)
+            {
+                this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebDirProperties, dirProperties);
+            }
+
+            if (null != componentId)
+            {
+                // Reference ConfigureIIs since nothing will happen without it
+                this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
+            }
+
+            if (!this.Messaging.EncounteredError)
+            {
+                var symbol = section.AddSymbol(new IIsWebSiteSymbol(sourceLineNumbers, id)
+                {
+                    ComponentRef = componentId,
+                    Description = description,
+                    DirectoryRef = directory,
+                    KeyAddressRef = keyAddress,
+                    DirPropertiesRef = dirProperties,
+                    ApplicationRef = application,
+                    LogRef = log,
+                    WebsiteId = siteId,
+                });
+
+                if (CompilerConstants.IntegerNotSet != connectionTimeout)
+                {
+                    symbol.ConnectionTimeout = connectionTimeout;
+                }
+
+                if (CompilerConstants.IntegerNotSet != state)
+                {
+                    symbol.State = state;
+                }
+
+                if (0 != attributes)
+                {
+                    symbol.Attributes = attributes;
+                }
+
+                if (CompilerConstants.IntegerNotSet != sequence)
+                {
+                    symbol.Sequence = sequence;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Parses a HTTP Header element.
+        /// </summary>
+        /// <param name="element">Element to parse.</param>
+        /// <param name="parentType">Type of the parent.</param>
+        /// <param name="parent">Id of the parent.</param>
+        private void ParseHttpHeaderElement(Intermediate intermediate, IntermediateSection section, XElement element, HttpHeaderParentType parentType, string parent)
+        {
+            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
+            Identifier id = null;
+            string headerName = null;
+            string headerValue = null;
+
+            foreach (var attrib in element.Attributes())
+            {
+                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
+                {
+                    switch (attrib.Name.LocalName)
+                    {
+                        case "Id":
+                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
+                            break;
+                        case "Name":
+                            headerName = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "Value":
+                            headerValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedAttribute(element, attrib);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
+                }
+            }
+
+            if (null == headerName)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
+            }
+            else if (null == id)
+            {
+                id = this.ParseHelper.CreateIdentifierFromFilename(headerName);
+            }
+
+            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
+
+            // Reference ConfigureIIs since nothing will happen without it
+            this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
+
+            if (!this.Messaging.EncounteredError)
+            {
+                section.AddSymbol(new IIsHttpHeaderSymbol(sourceLineNumbers, id)
+                {
+                    HttpHeader = id.Id,
+                    ParentType = (int)parentType,
+                    ParentValue = parent,
+                    Name = headerName,
+                    Value = headerValue,
+                    Attributes = 0,
+                });
+            }
+        }
+
+        /// <summary>
+        /// Parses a virtual directory element.
+        /// </summary>
+        /// <param name="element">Element to parse.</param>
+        /// <param name="componentId">Identifier of parent component.</param>
+        /// <param name="parentWeb">Identifier of parent web site.</param>
+        /// <param name="parentAlias">Alias of the parent web site.</param>
+        private void ParseWebVirtualDirElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string parentWeb, string parentAlias)
+        {
+            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
+            Identifier id = null;
+            string alias = null;
+            string application = null;
+            string directory = null;
+            string dirProperties = null;
+
+            foreach (var attrib in element.Attributes())
+            {
+                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
+                {
+                    switch (attrib.Name.LocalName)
+                    {
+                        case "Id":
+                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
+                            break;
+                        case "Alias":
+                            alias = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "Directory":
+                            directory = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
+                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Directory, directory);
+                            break;
+                        case "DirProperties":
+                            dirProperties = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "WebApplication":
+                            application = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
+                            break;
+                        case "WebSite":
+                            if (null != parentWeb)
+                            {
+                                this.Messaging.Write(IIsErrors.WebSiteAttributeUnderWebSite(sourceLineNumbers, element.Name.LocalName));
+                            }
+
+                            parentWeb = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
+                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebSite, parentWeb);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedAttribute(element, attrib);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
+                }
+            }
+
+            if (null == id)
+            {
+                id = this.ParseHelper.CreateIdentifier("wvd", alias, directory, dirProperties, application, parentWeb);
+            }
+
+            if (null == alias)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Alias"));
+            }
+            else if (-1 != alias.IndexOf("\\", StringComparison.Ordinal))
+            {
+                this.Messaging.Write(IIsErrors.IllegalCharacterInAttributeValue(sourceLineNumbers, element.Name.LocalName, "Alias", alias, '\\'));
+            }
+
+            if (null == directory)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Directory"));
+            }
+
+            if (null == parentWeb)
+            {
+                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "WebSite"));
+            }
+
+            if (null == componentId)
+            {
+                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(sourceLineNumbers, element.Name.LocalName));
+            }
+
+            if (null != parentAlias)
+            {
+                alias = String.Concat(parentAlias, "/", alias);
+            }
+
+            foreach (var child in element.Elements())
+            {
+                if (this.Namespace == child.Name.Namespace)
+                {
+                    var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child);
+                    switch (child.Name.LocalName)
+                    {
+                        case "WebApplication":
+                            if (null != application)
+                            {
+                                this.Messaging.Write(IIsErrors.WebApplicationAlreadySpecified(childSourceLineNumbers, element.Name.LocalName));
+                            }
+
+                            application = this.ParseWebApplicationElement(intermediate, section, child);
+                            break;
+                        case "WebDirProperties":
+                            if (null == componentId)
+                            {
+                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
+                            }
+
+                            string childWebDirProperties = this.ParseWebDirPropertiesElement(intermediate, section, child, componentId);
+                            if (null == dirProperties)
+                            {
+                                dirProperties = childWebDirProperties;
+                            }
+                            else
+                            {
+                                this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, child.Name.LocalName, "DirProperties", child.Name.LocalName));
+                            }
+                            break;
+
+                        case "WebError":
+                            this.ParseWebErrorElement(intermediate, section, child, WebErrorParentType.WebVirtualDir, id?.Id);
+                            break;
+                        case "WebVirtualDir":
+                            this.ParseWebVirtualDirElement(intermediate, section, child, componentId, parentWeb, alias);
+                            break;
+                        case "HttpHeader":
+                            this.ParseHttpHeaderElement(intermediate, section, child, HttpHeaderParentType.WebVirtualDir, id?.Id);
+                            break;
+                        case "MimeMap":
+                            this.ParseMimeMapElement(intermediate, section, child, id?.Id, MimeMapParentType.WebVirtualDir);
+                            break;
+                        default:
+                            this.ParseHelper.UnexpectedElement(element, child);
+                            break;
+                    }
+                }
+                else
+                {
+                    this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
+                }
+            }
+
+            if (null != dirProperties)
+            {
+                this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebDirProperties, dirProperties);
+            }
+
+            if (null != application)
+            {
+                this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebApplication, application);
+            }
+
+            // Reference ConfigureIIs since nothing will happen without it
+            this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
+
+            if (!this.Messaging.EncounteredError)
+            {
+                section.AddSymbol(new IIsWebVirtualDirSymbol(sourceLineNumbers, id)
+                {
+                    ComponentRef = componentId,
+                    WebRef = parentWeb,
+                    Alias = alias,
+                    DirectoryRef = directory,
+                    DirPropertiesRef = dirProperties,
+                    ApplicationRef = application,
+                });
+            }
+        }
+
+        private void AddReferenceToConfigureIIs(IntermediateSection section, SourceLineNumber sourceLineNumbers)
+        {
+            this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureIIs", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
+        }
+    }
+}
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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+#if TODO_CONSIDER_DECOMPILER
+    using System;
+    using System.Collections;
+    using System.Globalization;
+    using WixToolset.Data;
+    using WixToolset.Extensibility;
+    using IIs = WixToolset.Extensions.Serialize.IIs;
+    using Wix = WixToolset.Data.Serialize;
+
+    /// <summary>
+    /// The decompiler for the WiX Toolset Internet Information Services Extension.
+    /// </summary>
+    public sealed class IIsDecompiler : DecompilerExtension
+    {
+        /// <summary>
+        /// Creates a decompiler for IIs Extension.
+        /// </summary>
+        public IIsDecompiler()
+        {
+            this.TableDefinitions = IIsExtensionData.GetExtensionTableDefinitions();
+        }
+
+        /// <summary>
+        /// Get the extensions library to be removed.
+        /// </summary>
+        /// <param name="tableDefinitions">Table definitions for library.</param>
+        /// <returns>Library to remove from decompiled output.</returns>
+        public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions)
+        {
+            return IIsExtensionData.GetExtensionLibrary(tableDefinitions);
+        }
+
+        /// <summary>
+        /// Decompiles an extension table.
+        /// </summary>
+        /// <param name="table">The table to decompile.</param>
+        public override void DecompileTable(Table table)
+        {
+            switch (table.Name)
+            {
+                case "Certificate":
+                    this.DecompileCertificateTable(table);
+                    break;
+                case "CertificateHash":
+                    // There is nothing to do for this table, it contains no authored data
+                    // to be decompiled.
+                    break;
+                case "IIsAppPool":
+                    this.DecompileIIsAppPoolTable(table);
+                    break;
+                case "IIsFilter":
+                    this.DecompileIIsFilterTable(table);
+                    break;
+                case "IIsProperty":
+                    this.DecompileIIsPropertyTable(table);
+                    break;
+                case "IIsHttpHeader":
+                    this.DecompileIIsHttpHeaderTable(table);
+                    break;
+                case "IIsMimeMap":
+                    this.DecompileIIsMimeMapTable(table);
+                    break;
+                case "IIsWebAddress":
+                    this.DecompileIIsWebAddressTable(table);
+                    break;
+                case "IIsWebApplication":
+                    this.DecompileIIsWebApplicationTable(table);
+                    break;
+                case "IIsWebDirProperties":
+                    this.DecompileIIsWebDirPropertiesTable(table);
+                    break;
+                case "IIsWebError":
+                    this.DecompileIIsWebErrorTable(table);
+                    break;
+                case "IIsWebLog":
+                    this.DecompileIIsWebLogTable(table);
+                    break;
+                case "IIsWebServiceExtension":
+                    this.DecompileIIsWebServiceExtensionTable(table);
+                    break;
+                case "IIsWebSite":
+                    this.DecompileIIsWebSiteTable(table);
+                    break;
+                case "IIsWebVirtualDir":
+                    this.DecompileIIsWebVirtualDirTable(table);
+                    break;
+                case "IIsWebSiteCertificates":
+                    this.DecompileIIsWebSiteCertificatesTable(table);
+                    break;
+                default:
+                    base.DecompileTable(table);
+                    break;
+            }
+        }
+
+        /// <summary>
+        /// Finalize decompilation.
+        /// </summary>
+        /// <param name="tables">The collection of all tables.</param>
+        public override void Finish(TableIndexedCollection tables)
+        {
+            this.FinalizeIIsMimeMapTable(tables);
+            this.FinalizeIIsHttpHeaderTable(tables);
+            this.FinalizeIIsWebApplicationTable(tables);
+            this.FinalizeIIsWebErrorTable(tables);
+            this.FinalizeIIsWebVirtualDirTable(tables);
+            this.FinalizeIIsWebSiteCertificatesTable(tables);
+            this.FinalizeWebAddressTable(tables);
+        }
+
+        /// <summary>
+        /// Decompile the Certificate table.
+        /// </summary>
+        /// <param name="table">The table to decompile.</param>
+        private void DecompileCertificateTable(Table table)
+        {
+            foreach (Row row in table.Rows)
+            {
+                IIs.Certificate certificate = new IIs.Certificate();
+
+                certificate.Id = (string)row[0];
+                certificate.Name = (string)row[2];
+
+                switch ((int)row[3])
+                {
+                    case 1:
+                        certificate.StoreLocation = IIs.Certificate.StoreLocationType.currentUser;
+                        break;
+                    case 2:
+                        certificate.StoreLocation = IIs.Certificate.StoreLocationType.localMachine;
+                        break;
+                    default:
+                        // TODO: warn
+                        break;
+                }
+
+                switch ((string)row[4])
+                {
+                    case "CA":
+                        certificate.StoreName = IIs.Certificate.StoreNameType.ca;
+                        break;
+                    case "MY":
+                        certificate.StoreName = IIs.Certificate.StoreNameType.my;
+                        break;
+                    case "REQUEST":
+                        certificate.StoreName = IIs.Certificate.StoreNameType.request;
+                        break;
+                    case "Root":
+                        certificate.StoreName = IIs.Certificate.StoreNameType.root;
+                        break;
+                    case "AddressBook":
+                        certificate.StoreName = IIs.Certificate.StoreNameType.otherPeople;
+                        break;
+                    case "TrustedPeople":
+                        certificate.StoreName = IIs.Certificate.StoreNameType.trustedPeople;
+                        break;
+                    case "TrustedPublisher":
+                        certificate.StoreName = IIs.Certificate.StoreNameType.trustedPublisher;
+                        break;
+                    default:
+                        // TODO: warn
+                        break;
+                }
+
+                int attribute = (int)row[5];
+
+                if (0x1 == (attribute & 0x1))
+                {
+                    certificate.Request = IIs.YesNoType.yes;
+                }
+
+                if (0x2 == (attribute & 0x2))
+                {
+                    if (null != row[6])
+                    {
+                        certificate.BinaryKey = (string)row[6];
+                    }
+                    else
+                    {
+                        // TODO: warn about expected value in row 5
+                    }
+                }
+                else if (null != row[7])
+                {
+                    certificate.CertificatePath = (string)row[7];
+                }
+
+                if (0x4 == (attribute & 0x4))
+                {
+                    certificate.Overwrite = IIs.YesNoType.yes;
+                }
+
+                if (null != row[8])
+                {
+                    certificate.PFXPassword = (string)row[8];
+                }
+
+                Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
+                if (null != component)
+                {
+                    component.AddChild(certificate);
+                }
+                else
+                {
+                    this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
+                }
+            }
+        }
+
+        /// <summary>
+        /// Decompile the IIsAppPool table.
+        /// </summary>
+        /// <param name="table">The table to decompile.</param>
+        private void DecompileIIsAppPoolTable(Table table)
+        {
+            foreach (Row row in table.Rows)
+            {
+                IIs.WebAppPool webAppPool = new IIs.WebAppPool();
+
+                webAppPool.Id = (string)row[0];
+
+                webAppPool.Name = (string)row[1];
+
+                switch ((int)row[3] & 0x1F)
+                {
+                    case 1:
+                        webAppPool.Identity = IIs.WebAppPool.IdentityType.networkService;
+                        break;
+                    case 2:
+                        webAppPool.Identity = IIs.WebAppPool.IdentityType.localService;
+                        break;
+                    case 4:
+                        webAppPool.Identity = IIs.WebAppPool.IdentityType.localSystem;
+                        break;
+                    case 8:
+                        webAppPool.Identity = IIs.WebAppPool.IdentityType.other;
+                        break;
+                    case 0x10:
+                        webAppPool.Identity = IIs.WebAppPool.IdentityType.applicationPoolIdentity;
+                        break;
+                    default:
+                        // TODO: warn
+                        break;
+                }
+
+                if (null != row[4])
+                {
+                    webAppPool.User = (string)row[4];
+                }
+
+                if (null != row[5])
+                {
+                    webAppPool.RecycleMinutes = (int)row[5];
+                }
+
+                if (null != row[6])
+                {
+                    webAppPool.RecycleRequests = (int)row[6];
+                }
+
+                if (null != row[7])
+                {
+                    string[] recycleTimeValues = ((string)row[7]).Split(',');
+
+                    foreach (string recycleTimeValue in recycleTimeValues)
+                    {
+                        IIs.RecycleTime recycleTime = new IIs.RecycleTime();
+
+                        recycleTime.Value = recycleTimeValue;
+
+                        webAppPool.AddChild(recycleTime);
+                    }
+                }
+
+                if (null != row[8])
+                {
+                    webAppPool.IdleTimeout = (int)row[8];
+                }
+
+                if (null != row[9])
+                {
+                    webAppPool.QueueLimit = (int)row[9];
+                }
+
+                if (null != row[10])
+                {
+                    string[] cpuMon = ((string)row[10]).Split(',');
+
+                    if (0 < cpuMon.Length && "0" != cpuMon[0])
+                    {
+                        webAppPool.MaxCpuUsage = Convert.ToInt32(cpuMon[0], CultureInfo.InvariantCulture);
+                    }
+
+                    if (1 < cpuMon.Length)
+                    {
+                        webAppPool.RefreshCpu = Convert.ToInt32(cpuMon[1], CultureInfo.InvariantCulture);
+                    }
+
+                    if (2 < cpuMon.Length)
+                    {
+                        switch (Convert.ToInt32(cpuMon[2], CultureInfo.InvariantCulture))
+                        {
+                            case 0:
+                                webAppPool.CpuAction = IIs.WebAppPool.CpuActionType.none;
+                                break;
+                            case 1:
+                                webAppPool.CpuAction = IIs.WebAppPool.CpuActionType.shutdown;
+                                break;
+                            default:
+                                // TODO: warn
+                                break;
+                        }
+                    }
+
+                    if (3 < cpuMon.Length)
+                    {
+                        // TODO: warn
+                    }
+                }
+
+                if (null != row[11])
+                {
+                    webAppPool.MaxWorkerProcesses = (int)row[11];
+                }
+
+                if (null != row[12])
+                {
+                    webAppPool.VirtualMemory = (int)row[12];
+                }
+
+                if (null != row[13])
+                {
+                    webAppPool.PrivateMemory = (int)row[13];
+                }
+
+                if (null != row[14])
+                {
+                    webAppPool.ManagedRuntimeVersion = (string)row[14];
+                }
+
+                if (null != row[15])
+                {
+                    webAppPool.ManagedPipelineMode = (string)row[15];
+                }
+
+                if (null != row[2])
+                {
+                    Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]);
+
+                    if (null != component)
+                    {
+                        component.AddChild(webAppPool);
+                    }
+                    else
+                    {
+                        this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
+                    }
+                }
+                else
+                {
+                    this.Core.RootElement.AddChild(webAppPool);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Decompile the IIsProperty table.
+        /// </summary>
+        /// <param name="table">The table to decompile.</param>
+        private void DecompileIIsPropertyTable(Table table)
+        {
+            foreach (Row row in table.Rows)
+            {
+                IIs.WebProperty webProperty = new IIs.WebProperty();
+
+                switch ((string)row[0])
+                {
+                    case "ETagChangeNumber":
+                        webProperty.Id = IIs.WebProperty.IdType.ETagChangeNumber;
+                        break;
+                    case "IIs5IsolationMode":
+                        webProperty.Id = IIs.WebProperty.IdType.IIs5IsolationMode;
+                        break;
+                    case "LogInUTF8":
+                        webProperty.Id = IIs.WebProperty.IdType.LogInUTF8;
+                        break;
+                    case "MaxGlobalBandwidth":
+                        webProperty.Id = IIs.WebProperty.IdType.MaxGlobalBandwidth;
+                        break;
+                }
+
+                if (0 != (int)row[2])
+                {
+                    // TODO: warn about value in unused column
+                }
+
+                if (null != row[3])
+                {
+                    webProperty.Value = (string)row[3];
+                }
+
+                Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
+                if (null != component)
+                {
+                    component.AddChild(webProperty);
+                }
+                else
+                {
+                    this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
+                }
+            }
+        }
+
+        /// <summary>
+        /// Decompile the IIsHttpHeader table.
+        /// </summary>
+        /// <param name="table">The table to decompile.</param>
+        private void DecompileIIsHttpHeaderTable(Table table)
+        {
+            foreach (Row row in table.Rows)
+            {
+                IIs.HttpHeader httpHeader = new IIs.HttpHeader();
+
+                httpHeader.Name = (string)row[3];
+
+                // the ParentType and Parent columns are handled in FinalizeIIsHttpHeaderTable
+
+                httpHeader.Value = (string)row[4];
+
+                this.Core.IndexElement(row, httpHeader);
+            }
+        }
+
+        /// <summary>
+        /// Decompile the IIsMimeMap table.
+        /// </summary>
+        /// <param name="table">The table to decompile.</param>
+        private void DecompileIIsMimeMapTable(Table table)
+        {
+            foreach (Row row in table.Rows)
+            {
+                IIs.MimeMap mimeMap = new IIs.MimeMap();
+
+                mimeMap.Id = (string)row[0];
+
+                // the ParentType and ParentValue columns are handled in FinalizeIIsMimeMapTable
+
+                mimeMap.Type = (string)row[3];
+
+                mimeMap.Extension = (string)row[4];
+
+                this.Core.IndexElement(row, mimeMap);
+            }
+        }
+
+        /// <summary>
+        /// Decompile the IIsWebAddress table.
+        /// </summary>
+        /// <param name="table">The table to decompile.</param>
+        private void DecompileIIsWebAddressTable(Table table)
+        {
+            foreach (Row row in table.Rows)
+            {
+                IIs.WebAddress webAddress = new IIs.WebAddress();
+
+                webAddress.Id = (string)row[0];
+
+                if (null != row[2])
+                {
+                    webAddress.IP = (string)row[2];
+                }
+
+                webAddress.Port = (string)row[3];
+
+                if (null != row[4])
+                {
+                    webAddress.Header = (string)row[4];
+                }
+
+                if (null != row[5] && 1 == (int)row[5])
+                {
+                    webAddress.Secure = IIs.YesNoType.yes;
+                }
+
+                this.Core.IndexElement(row, webAddress);
+            }
+        }
+
+        /// <summary>
+        /// Decompile the IIsWebApplication table.
+        /// </summary>
+        /// <param name="table">The table to decompile.</param>
+        private void DecompileIIsWebApplicationTable(Table table)
+        {
+            foreach (Row row in table.Rows)
+            {
+                IIs.WebApplication webApplication = new IIs.WebApplication();
+
+                webApplication.Id = (string)row[0];
+
+                webApplication.Name = (string)row[1];
+
+                // these are not listed incorrectly - the order is low, high, medium
+                switch ((int)row[2])
+                {
+                    case 0:
+                        webApplication.Isolation = IIs.WebApplication.IsolationType.low;
+                        break;
+                    case 1:
+                        webApplication.Isolation = IIs.WebApplication.IsolationType.high;
+                        break;
+                    case 2:
+                        webApplication.Isolation = IIs.WebApplication.IsolationType.medium;
+                        break;
+                    default:
+                        // TODO: warn
+                        break;
+                }
+
+                if (null != row[3])
+                {
+                    switch ((int)row[3])
+                    {
+                        case 0:
+                            webApplication.AllowSessions = IIs.YesNoDefaultType.no;
+                            break;
+                        case 1:
+                            webApplication.AllowSessions = IIs.YesNoDefaultType.yes;
+                            break;
+                        default:
+                            // TODO: warn
+                            break;
+                    }
+                }
+
+                if (null != row[4])
+                {
+                    webApplication.SessionTimeout = (int)row[4];
+                }
+
+                if (null != row[5])
+                {
+                    switch ((int)row[5])
+                    {
+                        case 0:
+                            webApplication.Buffer = IIs.YesNoDefaultType.no;
+                            break;
+                        case 1:
+                            webApplication.Buffer = IIs.YesNoDefaultType.yes;
+                            break;
+                        default:
+                            // TODO: warn
+                            break;
+                    }
+                }
+
+                if (null != row[6])
+                {
+                    switch ((int)row[6])
+                    {
+                        case 0:
+                            webApplication.ParentPaths = IIs.YesNoDefaultType.no;
+                            break;
+                        case 1:
+                            webApplication.ParentPaths = IIs.YesNoDefaultType.yes;
+                            break;
+                        default:
+                            // TODO: warn
+                            break;
+                    }
+                }
+
+                if (null != row[7])
+                {
+                    switch ((string)row[7])
+                    {
+                        case "JScript":
+                            webApplication.DefaultScript = IIs.WebApplication.DefaultScriptType.JScript;
+                            break;
+                        case "VBScript":
+                            webApplication.DefaultScript = IIs.WebApplication.DefaultScriptType.VBScript;
+                            break;
+                        default:
+                            // TODO: warn
+                            break;
+                    }
+                }
+
+                if (null != row[8])
+                {
+                    webApplication.ScriptTimeout = (int)row[8];
+                }
+
+                if (null != row[9])
+                {
+                    switch ((int)row[9])
+                    {
+                        case 0:
+                            webApplication.ServerDebugging = IIs.YesNoDefaultType.no;
+                            break;
+                        case 1:
+                            webApplication.ServerDebugging = IIs.YesNoDefaultType.yes;
+                            break;
+                        default:
+                            // TODO: warn
+                            break;
+                    }
+                }
+
+                if (null != row[10])
+                {
+                    switch ((int)row[10])
+                    {
+                        case 0:
+                            webApplication.ClientDebugging = IIs.YesNoDefaultType.no;
+                            break;
+                        case 1:
+                            webApplication.ClientDebugging = IIs.YesNoDefaultType.yes;
+                            break;
+                        default:
+                            // TODO: warn
+                            break;
+                    }
+                }
+
+                if (null != row[11])
+                {
+                    webApplication.WebAppPool = (string)row[11];
+                }
+
+                this.Core.IndexElement(row, webApplication);
+            }
+        }
+
+        /// <summary>
+        /// Decompile the IIsWebDirProperties table.
+        /// </summary>
+        /// <param name="table">The table to decompile.</param>
+        private void DecompileIIsWebDirPropertiesTable(Table table)
+        {
+            foreach (Row row in table.Rows)
+            {
+                IIs.WebDirProperties webDirProperties = new IIs.WebDirProperties();
+
+                webDirProperties.Id = (string)row[0];
+
+                if (null != row[1])
+                {
+                    int access = (int)row[1];
+
+                    if (0x1 == (access & 0x1))
+                    {
+                        webDirProperties.Read = IIs.YesNoType.yes;
+                    }
+
+                    if (0x2 == (access & 0x2))
+                    {
+                        webDirProperties.Write = IIs.YesNoType.yes;
+                    }
+
+                    if (0x4 == (access & 0x4))
+                    {
+                        webDirProperties.Execute = IIs.YesNoType.yes;
+                    }
+
+                    if (0x200 == (access & 0x200))
+                    {
+                        webDirProperties.Script = IIs.YesNoType.yes;
+                    }
+                }
+
+                if (null != row[2])
+                {
+                    int authorization = (int)row[2];
+
+                    if (0x1 == (authorization & 0x1))
+                    {
+                        webDirProperties.AnonymousAccess = IIs.YesNoType.yes;
+                    }
+                    else // set one of the properties to 'no' to force the output value to be '0' if not other attributes are set
+                    {
+                        webDirProperties.AnonymousAccess = IIs.YesNoType.no;
+                    }
+
+                    if (0x2 == (authorization & 0x2))
+                    {
+                        webDirProperties.BasicAuthentication = IIs.YesNoType.yes;
+                    }
+
+                    if (0x4 == (authorization & 0x4))
+                    {
+                        webDirProperties.WindowsAuthentication = IIs.YesNoType.yes;
+                    }
+
+                    if (0x10 == (authorization & 0x10))
+                    {
+                        webDirProperties.DigestAuthentication = IIs.YesNoType.yes;
+                    }
+
+                    if (0x40 == (authorization & 0x40))
+                    {
+                        webDirProperties.PassportAuthentication = IIs.YesNoType.yes;
+                    }
+                }
+
+                if (null != row[3])
+                {
+                    webDirProperties.AnonymousUser = (string)row[3];
+                }
+
+                if (null != row[4] && 1 == (int)row[4])
+                {
+                    webDirProperties.IIsControlledPassword = IIs.YesNoType.yes;
+                }
+
+                if (null != row[5])
+                {
+                    switch ((int)row[5])
+                    {
+                        case 0:
+                            webDirProperties.LogVisits = IIs.YesNoType.no;
+                            break;
+                        case 1:
+                            webDirProperties.LogVisits = IIs.YesNoType.yes;
+                            break;
+                        default:
+                            // TODO: warn
+                            break;
+                    }
+                }
+
+                if (null != row[6])
+                {
+                    switch ((int)row[6])
+                    {
+                        case 0:
+                            webDirProperties.Index = IIs.YesNoType.no;
+                            break;
+                        case 1:
+                            webDirProperties.Index = IIs.YesNoType.yes;
+                            break;
+                        default:
+                            // TODO: warn
+                            break;
+                    }
+                }
+
+                if (null != row[7])
+                {
+                    webDirProperties.DefaultDocuments = (string)row[7];
+                }
+
+                if (null != row[8])
+                {
+                    switch ((int)row[8])
+                    {
+                        case 0:
+                            webDirProperties.AspDetailedError = IIs.YesNoType.no;
+                            break;
+                        case 1:
+                            webDirProperties.AspDetailedError = IIs.YesNoType.yes;
+                            break;
+                        default:
+                            // TODO: warn
+                            break;
+                    }
+                }
+
+                if (null != row[9])
+                {
+                    webDirProperties.HttpExpires = (string)row[9];
+                }
+
+                if (null != row[10])
+                {
+                    // force the value to be a positive number
+                    webDirProperties.CacheControlMaxAge = unchecked((uint)(int)row[10]);
+                }
+
+                if (null != row[11])
+                {
+                    webDirProperties.CacheControlCustom = (string)row[11];
+                }
+
+                if (null != row[12])
+                {
+                    switch ((int)row[8])
+                    {
+                        case 0:
+                            webDirProperties.ClearCustomError = IIs.YesNoType.no;
+                            break;
+                        case 1:
+                            webDirProperties.ClearCustomError = IIs.YesNoType.yes;
+                            break;
+                        default:
+                            // TODO: warn
+                            break;
+                    }
+                }
+
+                if (null != row[13])
+                {
+                    int accessSSLFlags = (int)row[13];
+
+                    if (0x8 == (accessSSLFlags & 0x8))
+                    {
+                        webDirProperties.AccessSSL = IIs.YesNoType.yes;
+                    }
+
+                    if (0x20 == (accessSSLFlags & 0x20))
+                    {
+                        webDirProperties.AccessSSLNegotiateCert = IIs.YesNoType.yes;
+                    }
+
+                    if (0x40 == (accessSSLFlags & 0x40))
+                    {
+                        webDirProperties.AccessSSLRequireCert = IIs.YesNoType.yes;
+                    }
+
+                    if (0x80 == (accessSSLFlags & 0x80))
+                    {
+                        webDirProperties.AccessSSLMapCert = IIs.YesNoType.yes;
+                    }
+
+                    if (0x100 == (accessSSLFlags & 0x100))
+                    {
+                        webDirProperties.AccessSSL128 = IIs.YesNoType.yes;
+                    }
+                }
+
+                if (null != row[14])
+                {
+                    webDirProperties.AuthenticationProviders = (string)row[14];
+                }
+
+                this.Core.RootElement.AddChild(webDirProperties);
+            }
+        }
+
+        /// <summary>
+        /// Decompile the IIsWebError table.
+        /// </summary>
+        /// <param name="table">The table to decompile.</param>
+        private void DecompileIIsWebErrorTable(Table table)
+        {
+            foreach (Row row in table.Rows)
+            {
+                IIs.WebError webError = new IIs.WebError();
+
+                webError.ErrorCode = (int)row[0];
+
+                webError.SubCode = (int)row[1];
+
+                // the ParentType and ParentValue columns are handled in FinalizeIIsWebErrorTable
+
+                if (null != row[4])
+                {
+                    webError.File = (string)row[4];
+                }
+
+                if (null != row[5])
+                {
+                    webError.URL = (string)row[5];
+                }
+
+                this.Core.IndexElement(row, webError);
+            }
+        }
+
+        /// <summary>
+        /// Decompile the IIsFilter table.
+        /// </summary>
+        /// <param name="table">The table to decompile.</param>
+        private void DecompileIIsFilterTable(Table table)
+        {
+            foreach (Row row in table.Rows)
+            {
+                IIs.WebFilter webFilter = new IIs.WebFilter();
+
+                webFilter.Id = (string)row[0];
+
+                webFilter.Name = (string)row[1];
+
+                if (null != row[3])
+                {
+                    webFilter.Path = (string)row[3];
+                }
+
+                if (null != row[5])
+                {
+                    webFilter.Description = (string)row[5];
+                }
+
+                webFilter.Flags = (int)row[6];
+
+                if (null != row[7])
+                {
+                    switch ((int)row[7])
+                    {
+                        case (-1):
+                            webFilter.LoadOrder = "last";
+                            break;
+                        case 0:
+                            webFilter.LoadOrder = "first";
+                            break;
+                        default:
+                            webFilter.LoadOrder = Convert.ToString((int)row[7], CultureInfo.InvariantCulture);
+                            break;
+                    }
+                }
+
+                if (null != row[4])
+                {
+                    IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement("IIsWebSite", (string)row[4]);
+
+                    if (null != webSite)
+                    {
+                        webSite.AddChild(webFilter);
+                    }
+                    else
+                    {
+                        this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Web_", (string)row[4], "IIsWebSite"));
+                    }
+                }
+                else // Component parent
+                {
+                    Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]);
+
+                    if (null != component)
+                    {
+                        component.AddChild(webFilter);
+                    }
+                    else
+                    {
+                        this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Decompile the IIsWebLog table.
+        /// </summary>
+        /// <param name="table">The table to decompile.</param>
+        private void DecompileIIsWebLogTable(Table table)
+        {
+            foreach (Row row in table.Rows)
+            {
+                IIs.WebLog webLog = new IIs.WebLog();
+
+                webLog.Id = (string)row[0];
+
+                switch ((string)row[1])
+                {
+                    case "Microsoft IIS Log File Format":
+                        webLog.Type = IIs.WebLog.TypeType.IIS;
+                        break;
+                    case "NCSA Common Log File Format":
+                        webLog.Type = IIs.WebLog.TypeType.NCSA;
+                        break;
+                    case "none":
+                        webLog.Type = IIs.WebLog.TypeType.none;
+                        break;
+                    case "ODBC Logging":
+                        webLog.Type = IIs.WebLog.TypeType.ODBC;
+                        break;
+                    case "W3C Extended Log File Format":
+                        webLog.Type = IIs.WebLog.TypeType.W3C;
+                        break;
+                    default:
+                        // TODO: warn
+                        break;
+                }
+
+                this.Core.RootElement.AddChild(webLog);
+            }
+        }
+
+        /// <summary>
+        /// Decompile the IIsWebServiceExtension table.
+        /// </summary>
+        /// <param name="table">The table to decompile.</param>
+        private void DecompileIIsWebServiceExtensionTable(Table table)
+        {
+            foreach (Row row in table.Rows)
+            {
+                IIs.WebServiceExtension webServiceExtension = new IIs.WebServiceExtension();
+
+                webServiceExtension.Id = (string)row[0];
+
+                webServiceExtension.File = (string)row[2];
+
+                if (null != row[3])
+                {
+                    webServiceExtension.Description = (string)row[3];
+                }
+
+                if (null != row[4])
+                {
+                    webServiceExtension.Group = (string)row[4];
+                }
+
+                int attributes = (int)row[5];
+
+                if (0x1 == (attributes & 0x1))
+                {
+                    webServiceExtension.Allow = IIs.YesNoType.yes;
+                }
+                else
+                {
+                    webServiceExtension.Allow = IIs.YesNoType.no;
+                }
+
+                if (0x2 == (attributes & 0x2))
+                {
+                    webServiceExtension.UIDeletable = IIs.YesNoType.yes;
+                }
+
+                Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
+                if (null != component)
+                {
+                    component.AddChild(webServiceExtension);
+                }
+                else
+                {
+                    this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
+                }
+            }
+        }
+
+        /// <summary>
+        /// Decompile the IIsWebSite table.
+        /// </summary>
+        /// <param name="table">The table to decompile.</param>
+        private void DecompileIIsWebSiteTable(Table table)
+        {
+            foreach (Row row in table.Rows)
+            {
+                IIs.WebSite webSite = new IIs.WebSite();
+
+                webSite.Id = (string)row[0];
+
+                if (null != row[2])
+                {
+                    webSite.Description = (string)row[2];
+                }
+
+                if (null != row[3])
+                {
+                    webSite.ConnectionTimeout = (int)row[3];
+                }
+
+                if (null != row[4])
+                {
+                    webSite.Directory = (string)row[4];
+                }
+
+                if (null != row[5])
+                {
+                    switch ((int)row[5])
+                    {
+                        case 0:
+                            // this is the default
+                            break;
+                        case 1:
+                            webSite.StartOnInstall = IIs.YesNoType.yes;
+                            break;
+                        case 2:
+                            webSite.AutoStart = IIs.YesNoType.yes;
+                            break;
+                        default:
+                            // TODO: warn
+                            break;
+                    }
+                }
+
+                if (null != row[6])
+                {
+                    int attributes = (int)row[6];
+
+                    if (0x2 == (attributes & 0x2))
+                    {
+                        webSite.ConfigureIfExists = IIs.YesNoType.no;
+                    }
+                }
+
+                // the KeyAddress_ column is handled in FinalizeWebAddressTable
+
+                if (null != row[8])
+                {
+                    webSite.DirProperties = (string)row[8];
+                }
+
+                // the Application_ column is handled in FinalizeIIsWebApplicationTable
+
+                if (null != row[10])
+                {
+                    if (-1 != (int)row[10])
+                    {
+                        webSite.Sequence = (int)row[10];
+                    }
+                }
+
+                if (null != row[11])
+                {
+                    webSite.WebLog = (string)row[11];
+                }
+
+                if (null != row[12])
+                {
+                    webSite.SiteId = (string)row[12];
+                }
+
+                if (null != row[1])
+                {
+                    Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
+
+                    if (null != component)
+                    {
+                        component.AddChild(webSite);
+                    }
+                    else
+                    {
+                        this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
+                    }
+                }
+                else
+                {
+                    this.Core.RootElement.AddChild(webSite);
+                }
+                this.Core.IndexElement(row, webSite);
+            }
+        }
+
+        /// <summary>
+        /// Decompile the IIsWebVirtualDir table.
+        /// </summary>
+        /// <param name="table">The table to decompile.</param>
+        private void DecompileIIsWebVirtualDirTable(Table table)
+        {
+            foreach (Row row in table.Rows)
+            {
+                IIs.WebVirtualDir webVirtualDir = new IIs.WebVirtualDir();
+
+                webVirtualDir.Id = (string)row[0];
+
+                // the Component_ and Web_ columns are handled in FinalizeIIsWebVirtualDirTable
+
+                webVirtualDir.Alias = (string)row[3];
+
+                webVirtualDir.Directory = (string)row[4];
+
+                if (null != row[5])
+                {
+                    webVirtualDir.DirProperties = (string)row[5];
+                }
+
+                // the Application_ column is handled in FinalizeIIsWebApplicationTable
+
+                this.Core.IndexElement(row, webVirtualDir);
+            }
+        }
+
+        /// <summary>
+        /// Decompile the IIsWebSiteCertificates table.
+        /// </summary>
+        /// <param name="table">The table to decompile.</param>
+        private void DecompileIIsWebSiteCertificatesTable(Table table)
+        {
+            foreach (Row row in table.Rows)
+            {
+                IIs.CertificateRef certificateRef = new IIs.CertificateRef();
+
+                certificateRef.Id = (string)row[1];
+
+                this.Core.IndexElement(row, certificateRef);
+            }
+        }
+
+        /// <summary>
+        /// Finalize the IIsHttpHeader table.
+        /// </summary>
+        /// <param name="tables">The collection of all tables.</param>
+        /// <remarks>
+        /// The IIsHttpHeader table supports multiple parent types so no foreign key
+        /// is declared and thus nesting must be done late.
+        /// </remarks>
+        private void FinalizeIIsHttpHeaderTable(TableIndexedCollection tables)
+        {
+            Table iisHttpHeaderTable = tables["IIsHttpHeader"];
+
+            if (null != iisHttpHeaderTable)
+            {
+                foreach (Row row in iisHttpHeaderTable.Rows)
+                {
+                    IIs.HttpHeader httpHeader = (IIs.HttpHeader)this.Core.GetIndexedElement(row);
+
+                    if (1 == (int)row[1])
+                    {
+                        IIs.WebVirtualDir webVirtualDir = (IIs.WebVirtualDir)this.Core.GetIndexedElement("IIsWebVirtualDir", (string)row[2]);
+                        if (null != webVirtualDir)
+                        {
+                            webVirtualDir.AddChild(httpHeader);
+                        }
+                        else
+                        {
+                            this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisHttpHeaderTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ParentValue", (string)row[2], "IIsWebVirtualDir"));
+                        }
+                    }
+                    else if (2 == (int)row[1])
+                    {
+                        IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement("IIsWebSite", (string)row[2]);
+                        if (null != webSite)
+                        {
+                            webSite.AddChild(httpHeader);
+                        }
+                        else
+                        {
+                            this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisHttpHeaderTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ParentValue", (string)row[2], "IIsWebSite"));
+                        }
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Finalize the IIsMimeMap table.
+        /// </summary>
+        /// <param name="tables">The collection of all tables.</param>
+        /// <remarks>
+        /// The IIsMimeMap table supports multiple parent types so no foreign key
+        /// is declared and thus nesting must be done late.
+        /// </remarks>
+        private void FinalizeIIsMimeMapTable(TableIndexedCollection tables)
+        {
+            Table iisMimeMapTable = tables["IIsMimeMap"];
+
+            if (null != iisMimeMapTable)
+            {
+                foreach (Row row in iisMimeMapTable.Rows)
+                {
+                    IIs.MimeMap mimeMap = (IIs.MimeMap)this.Core.GetIndexedElement(row);
+
+                    if (2 < (int)row[1] || 0 >= (int)row[1])
+                    {
+                        // TODO: warn about unknown parent type
+                    }
+
+                    IIs.WebVirtualDir webVirtualDir = (IIs.WebVirtualDir)this.Core.GetIndexedElement("IIsWebVirtualDir", (string)row[2]);
+                    IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement("IIsWebSite", (string)row[2]);
+                    if (null != webVirtualDir)
+                    {
+                        webVirtualDir.AddChild(mimeMap);
+                    }
+                    else if (null != webSite)
+                    {
+                        webSite.AddChild(mimeMap);
+                    }
+                    else
+                    {
+                        this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisMimeMapTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ParentValue", (string)row[2], "IIsWebVirtualDir"));
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Finalize the IIsWebApplication table.
+        /// </summary>
+        /// <param name="tables">The collection of all tables.</param>
+        /// <remarks>
+        /// Since WebApplication elements may nest under a specific WebSite or
+        /// WebVirtualDir (or just the root element), the nesting must be done late.
+        /// </remarks>
+        private void FinalizeIIsWebApplicationTable(TableIndexedCollection tables)
+        {
+            Table iisWebApplicationTable = tables["IIsWebApplication"];
+            Table iisWebSiteTable = tables["IIsWebSite"];
+            Table iisWebVirtualDirTable = tables["IIsWebVirtualDir"];
+
+            Hashtable addedWebApplications = new Hashtable();
+
+            if (null != iisWebSiteTable)
+            {
+                foreach (Row row in iisWebSiteTable.Rows)
+                {
+                    if (null != row[9])
+                    {
+                        IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement(row);
+
+                        IIs.WebApplication webApplication = (IIs.WebApplication)this.Core.GetIndexedElement("IIsWebApplication", (string)row[9]);
+                        if (null != webApplication)
+                        {
+                            webSite.AddChild(webApplication);
+                            addedWebApplications[webApplication] = null;
+                        }
+                        else
+                        {
+                            this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebSiteTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Application_", (string)row[9], "IIsWebApplication"));
+                        }
+                    }
+                }
+            }
+
+            if (null != iisWebVirtualDirTable)
+            {
+                foreach (Row row in iisWebVirtualDirTable.Rows)
+                {
+                    if (null != row[6])
+                    {
+                        IIs.WebVirtualDir webVirtualDir = (IIs.WebVirtualDir)this.Core.GetIndexedElement(row);
+
+                        IIs.WebApplication webApplication = (IIs.WebApplication)this.Core.GetIndexedElement("IIsWebApplication", (string)row[6]);
+                        if (null != webApplication)
+                        {
+                            webVirtualDir.AddChild(webApplication);
+                            addedWebApplications[webApplication] = null;
+                        }
+                        else
+                        {
+                            this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebVirtualDirTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Application_", (string)row[6], "IIsWebApplication"));
+                        }
+                    }
+                }
+            }
+
+            if (null != iisWebApplicationTable)
+            {
+                foreach (Row row in iisWebApplicationTable.Rows)
+                {
+                    IIs.WebApplication webApplication = (IIs.WebApplication)this.Core.GetIndexedElement(row);
+
+                    if (!addedWebApplications.Contains(webApplication))
+                    {
+                        this.Core.RootElement.AddChild(webApplication);
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Finalize the IIsWebError table.
+        /// </summary>
+        /// <param name="tables">The collection of all tables.</param>
+        /// <remarks>
+        /// Since there is no foreign key relationship declared for this table
+        /// (because it takes various parent types), it must be nested late.
+        /// </remarks>
+        private void FinalizeIIsWebErrorTable(TableIndexedCollection tables)
+        {
+            Table iisWebErrorTable = tables["IIsWebError"];
+
+            if (null != iisWebErrorTable)
+            {
+                foreach (Row row in iisWebErrorTable.Rows)
+                {
+                    IIs.WebError webError = (IIs.WebError)this.Core.GetIndexedElement(row);
+
+                    if (1 == (int)row[2]) // WebVirtualDir parent
+                    {
+                        IIs.WebVirtualDir webVirtualDir = (IIs.WebVirtualDir)this.Core.GetIndexedElement("IIsWebVirtualDir", (string)row[3]);
+
+                        if (null != webVirtualDir)
+                        {
+                            webVirtualDir.AddChild(webError);
+                        }
+                        else
+                        {
+                            this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebErrorTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ParentValue", (string)row[3], "IIsWebVirtualDir"));
+                        }
+                    }
+                    else if (2 == (int)row[2]) // WebSite parent
+                    {
+                        IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement("IIsWebSite", (string)row[3]);
+
+                        if (null != webSite)
+                        {
+                            webSite.AddChild(webError);
+                        }
+                        else
+                        {
+                            this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebErrorTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ParentValue", (string)row[3], "IIsWebSite"));
+                        }
+                    }
+                    else
+                    {
+                        // TODO: warn unknown parent type
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Finalize the IIsWebVirtualDir table.
+        /// </summary>
+        /// <param name="tables">The collection of all tables.</param>
+        /// <remarks>
+        /// WebVirtualDir elements nest under either a WebSite or component
+        /// depending upon whether the component in the IIsWebVirtualDir row
+        /// is the same as the one in the parent IIsWebSite row.
+        /// </remarks>
+        private void FinalizeIIsWebVirtualDirTable(TableIndexedCollection tables)
+        {
+            Table iisWebSiteTable = tables["IIsWebSite"];
+            Table iisWebVirtualDirTable = tables["IIsWebVirtualDir"];
+
+            Hashtable iisWebSiteRows = new Hashtable();
+
+            // index the IIsWebSite rows by their primary keys
+            if (null != iisWebSiteTable)
+            {
+                foreach (Row row in iisWebSiteTable.Rows)
+                {
+                    iisWebSiteRows.Add(row[0], row);
+                }
+            }
+
+            if (null != iisWebVirtualDirTable)
+            {
+                foreach (Row row in iisWebVirtualDirTable.Rows)
+                {
+                    IIs.WebVirtualDir webVirtualDir = (IIs.WebVirtualDir)this.Core.GetIndexedElement(row);
+                    Row iisWebSiteRow = (Row)iisWebSiteRows[row[2]];
+
+                    if (null != iisWebSiteRow)
+                    {
+                        if ((string)iisWebSiteRow[1] == (string)row[1])
+                        {
+                            IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement(iisWebSiteRow);
+
+                            webSite.AddChild(webVirtualDir);
+                        }
+                        else
+                        {
+                            Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
+
+                            if (null != component)
+                            {
+                                webVirtualDir.WebSite = (string)row[2];
+                                component.AddChild(webVirtualDir);
+                            }
+                            else
+                            {
+                                this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebVirtualDirTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
+                            }
+                        }
+                    }
+                    else
+                    {
+                        this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebVirtualDirTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Web_", (string)row[2], "IIsWebSite"));
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Finalize the IIsWebSiteCertificates table.
+        /// </summary>
+        /// <param name="tables">The collection of all tables.</param>
+        /// <remarks>
+        /// This table creates CertificateRef elements which nest under WebSite
+        /// elements.
+        /// </remarks>
+        private void FinalizeIIsWebSiteCertificatesTable(TableIndexedCollection tables)
+        {
+            Table IIsWebSiteCertificatesTable = tables["IIsWebSiteCertificates"];
+
+            if (null != IIsWebSiteCertificatesTable)
+            {
+                foreach (Row row in IIsWebSiteCertificatesTable.Rows)
+                {
+                    IIs.CertificateRef certificateRef = (IIs.CertificateRef)this.Core.GetIndexedElement(row);
+                    IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement("IIsWebSite", (string)row[0]);
+
+                    if (null != webSite)
+                    {
+                        webSite.AddChild(certificateRef);
+                    }
+                    else
+                    {
+                        this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, IIsWebSiteCertificatesTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Web_", (string)row[0], "IIsWebSite"));
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Finalize the WebAddress table.
+        /// </summary>
+        /// <param name="tables">The collection of all tables.</param>
+        /// <remarks>
+        /// There is a circular dependency between the WebAddress and WebSite
+        /// tables, so nesting must be handled here.
+        /// </remarks>
+        private void FinalizeWebAddressTable(TableIndexedCollection tables)
+        {
+            Table iisWebAddressTable = tables["IIsWebAddress"];
+            Table iisWebSiteTable = tables["IIsWebSite"];
+
+            Hashtable addedWebAddresses = new Hashtable();
+
+            if (null != iisWebSiteTable)
+            {
+                foreach (Row row in iisWebSiteTable.Rows)
+                {
+                    IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement(row);
+
+                    IIs.WebAddress webAddress = (IIs.WebAddress)this.Core.GetIndexedElement("IIsWebAddress", (string)row[7]);
+                    if (null != webAddress)
+                    {
+                        webSite.AddChild(webAddress);
+                        addedWebAddresses[webAddress] = null;
+                    }
+                    else
+                    {
+                        this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebSiteTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "KeyAddress_", (string)row[7], "IIsWebAddress"));
+                    }
+                }
+            }
+
+            if (null != iisWebAddressTable)
+            {
+                foreach (Row row in iisWebAddressTable.Rows)
+                {
+                    IIs.WebAddress webAddress = (IIs.WebAddress)this.Core.GetIndexedElement(row);
+
+                    if (!addedWebAddresses.Contains(webAddress))
+                    {
+                        IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement("IIsWebSite", (string)row[1]);
+
+                        if (null != webSite)
+                        {
+                            webSite.AddChild(webAddress);
+                        }
+                        else
+                        {
+                            this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebAddressTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Web_", (string)row[1], "IIsWebSite"));
+                        }
+                    }
+                }
+            }
+        }
+    }
+#endif
+}
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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Extensibility;
+
+    /// <summary>
+    /// The WiX Toolset Internet Information Services Extension.
+    /// </summary>
+    public sealed class IIsExtensionData : BaseExtensionData
+    {
+        /// <summary>
+        /// Gets the default culture.
+        /// </summary>
+        /// <value>The default culture.</value>
+        public override string DefaultCulture => "en-US";
+
+        public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
+        {
+            symbolDefinition = IisSymbolDefinitions.ByName(name);
+            return symbolDefinition != null;
+        }
+
+        public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions)
+        {
+            return Intermediate.Load(typeof(IIsExtensionData).Assembly, "WixToolset.Iis.iis.wixlib", symbolDefinitions);
+        }
+    }
+}
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 @@
+// 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.
+
+namespace WixToolset.Data
+{
+    using System;
+    using System.Resources;
+
+    public static class IIsErrors
+    {
+        public static Message DeprecatedBinaryChildElement(SourceLineNumber sourceLineNumbers, string elementName)
+        {
+            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);
+        }
+
+        public static Message IllegalAttributeWithoutComponent(SourceLineNumber sourceLineNumbers, string elementName, string attributeName)
+        {
+            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);
+        }
+
+        public static Message IllegalCharacterInAttributeValue(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string value, Char illegalCharacter)
+        {
+            return Message(sourceLineNumbers, Ids.IllegalCharacterInAttributeValue, "The {0}/@{1} attribute's value, '{2}', is invalid.  It cannot contain the character '{3}'.", elementName, attributeName, value, illegalCharacter);
+        }
+
+        public static Message IllegalElementWithoutComponent(SourceLineNumber sourceLineNumbers, string elementName)
+        {
+            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);
+        }
+
+        public static Message MimeMapExtensionMissingPeriod(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string attributeValue)
+        {
+            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);
+        }
+
+        public static Message OneOfAttributesRequiredUnderComponent(SourceLineNumber sourceLineNumbers, string elementName, string attributeName1, string attributeName2, string attributeName3, string attributeName4)
+        {
+            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);
+        }
+
+        public static Message RequiredAttributeUnderComponent(SourceLineNumber sourceLineNumbers, string elementName, string attributeName)
+        {
+            return Message(sourceLineNumbers, Ids.RequiredAttributeUnderComponent, "The {0}/@{1} attribute must be specified when the element has a Component as an ancestor.", elementName, attributeName);
+        }
+
+        public static Message WebApplicationAlreadySpecified(SourceLineNumber sourceLineNumbers, string elementName)
+        {
+            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);
+        }
+
+        public static Message WebSiteAttributeUnderWebSite(SourceLineNumber sourceLineNumbers, string elementName)
+        {
+            return Message(sourceLineNumbers, Ids.WebSiteAttributeUnderWebSite, "The {0}/@WebSite attribute cannot be specified when the {0} element is nested under a WebSite element.", elementName);
+        }
+
+        private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args)
+        {
+            return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args);
+        }
+
+        private static Message Message(SourceLineNumber sourceLineNumber, Ids id, ResourceManager resourceManager, string resourceName, params object[] args)
+        {
+            return new Message(sourceLineNumber, MessageLevel.Error, (int)id, resourceManager, resourceName, args);
+        }
+
+        public enum Ids
+        {
+            MimeMapExtensionMissingPeriod = 5150,
+            IllegalAttributeWithoutComponent = 5151,
+            IllegalElementWithoutComponent = 5152,
+            OneOfAttributesRequiredUnderComponent = 5153,
+            WebSiteAttributeUnderWebSite = 5154,
+            WebApplicationAlreadySpecified = 5155,
+            IllegalCharacterInAttributeValue = 5156,
+            DeprecatedBinaryChildElement = 5157,
+            RequiredAttributeUnderComponent = 5161,
+        }
+    }
+}
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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using System;
+    using System.Collections.Generic;
+    using WixToolset.Extensibility;
+
+    public class IisExtensionFactory : BaseExtensionFactory
+    {
+        protected override IReadOnlyCollection<Type> ExtensionTypes => new[]
+        {
+            typeof(IIsCompiler),
+            typeof(IIsExtensionData),
+            typeof(IisWindowsInstallerBackendBinderExtension),
+        };
+    }
+}
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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data.WindowsInstaller;
+
+    public static class IisTableDefinitions
+    {
+        public static readonly TableDefinition Certificate = new TableDefinition(
+            "Certificate",
+            IisSymbolDefinitions.Certificate,
+            new[]
+            {
+                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),
+                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),
+                new ColumnDefinition("Name", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Name to be used for the Certificate."),
+                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)"),
+                new ColumnDefinition("StoreName", ColumnType.String, 64, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Name of the target certificate store"),
+                new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 2147483647, description: "Attributes of the certificate"),
+                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),
+                new ColumnDefinition("CertificatePath", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Property to path of certificate.", modularizeType: ColumnModularizeType.Property),
+                new ColumnDefinition("PFXPassword", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Hidden property to a pfx password", modularizeType: ColumnModularizeType.Property),
+            },
+            symbolIdIsPrimaryKey: true
+        );
+
+        public static readonly TableDefinition CertificateHash = new TableDefinition(
+            "CertificateHash",
+            IisSymbolDefinitions.CertificateHash,
+            new[]
+            {
+                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),
+                new ColumnDefinition("Hash", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Base64 encoded SHA1 hash of certificate populated at run-time."),
+            },
+            symbolIdIsPrimaryKey: false
+        );
+
+        public static readonly TableDefinition IIsWebSiteCertificates = new TableDefinition(
+            "IIsWebSiteCertificates",
+            IisSymbolDefinitions.IIsWebSiteCertificates,
+            new[]
+            {
+                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),
+                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),
+            },
+            symbolIdIsPrimaryKey: false
+        );
+
+        public static readonly TableDefinition IIsAppPool = new TableDefinition(
+            "IIsAppPool",
+            IisSymbolDefinitions.IIsAppPool,
+            new[]
+            {
+                new ColumnDefinition("AppPool", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token for apppool", modularizeType: ColumnModularizeType.Column),
+                new ColumnDefinition("Name", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Name to be used for the IIs AppPool.", modularizeType: ColumnModularizeType.Property),
+                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),
+                new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, description: "Attributes of the AppPool"),
+                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),
+                new ColumnDefinition("RecycleMinutes", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Number of minutes between recycling app pool"),
+                new ColumnDefinition("RecycleRequests", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Number of requests between recycling app pool"),
+                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)"),
+                new ColumnDefinition("IdleTimeout", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Amount of idle time before shutting down"),
+                new ColumnDefinition("QueueLimit", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Reject requests after queue gets how large"),
+                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)."),
+                new ColumnDefinition("MaxProc", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Maximum number of processes to use"),
+                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."),
+                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."),
+                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."),
+                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."),
+            },
+            symbolIdIsPrimaryKey: true
+        );
+
+        public static readonly TableDefinition IIsMimeMap = new TableDefinition(
+            "IIsMimeMap",
+            IisSymbolDefinitions.IIsMimeMap,
+            new[]
+            {
+                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),
+                new ColumnDefinition("ParentType", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, possibilities: "1;2", description: "Type of parent: 1=vdir 2=website"),
+                new ColumnDefinition("ParentValue", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, description: "Name of the parent value.", modularizeType: ColumnModularizeType.Column),
+                new ColumnDefinition("MimeType", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Mime-type covered by the MimeMap."),
+                new ColumnDefinition("Extension", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Extension covered by the MimeMap."),
+            },
+            symbolIdIsPrimaryKey: true
+        );
+
+        public static readonly TableDefinition IIsProperty = new TableDefinition(
+            "IIsProperty",
+            IisSymbolDefinitions.IIsProperty,
+            new[]
+            {
+                new ColumnDefinition("Property", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Unique name of the IIsProperty"),
+                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),
+                new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, description: "Attributes of the IIsProperty (unused)"),
+                new ColumnDefinition("Value", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Value of the IIsProperty"),
+            },
+            symbolIdIsPrimaryKey: true
+        );
+
+        public static readonly TableDefinition IIsWebDirProperties = new TableDefinition(
+            "IIsWebDirProperties",
+            IisSymbolDefinitions.IIsWebDirProperties,
+            new[]
+            {
+                new ColumnDefinition("DirProperties", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token for Web Properties", modularizeType: ColumnModularizeType.Column),
+                new ColumnDefinition("Access", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Access rights to the web server"),
+                new ColumnDefinition("Authorization", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Authorization policy to web server (anonymous access, NTLM, etc)"),
+                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),
+                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"),
+                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"),
+                new ColumnDefinition("Index", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "Specifies whether IIs searches the directory"),
+                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"),
+                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"),
+                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"),
+                new ColumnDefinition("CacheControlMaxAge", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Integer value specifying the cache control maximum age value."),
+                new ColumnDefinition("CacheControlCustom", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Custom HTTP 1.1 cache control directives."),
+                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."),
+                new ColumnDefinition("AccessSSLFlags", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Specifies AccessSSLFlags IIS metabase property."),
+                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."),
+            },
+            symbolIdIsPrimaryKey: true
+        );
+
+        public static readonly TableDefinition IIsWebAddress = new TableDefinition(
+            "IIsWebAddress",
+            IisSymbolDefinitions.IIsWebAddress,
+            new[]
+            {
+                new ColumnDefinition("Address", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
+                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),
+                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),
+                new ColumnDefinition("Port", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Port web site listens on", modularizeType: ColumnModularizeType.Property),
+                new ColumnDefinition("Header", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Special header information for the web site"),
+                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"),
+            },
+            symbolIdIsPrimaryKey: true
+        );
+
+        public static readonly TableDefinition IIsWebSite = new TableDefinition(
+            "IIsWebSite",
+            IisSymbolDefinitions.IIsWebSite,
+            new[]
+            {
+                new ColumnDefinition("Web", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
+                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),
+                new ColumnDefinition("Description", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Description displayed in IIS MMC applet"),
+                new ColumnDefinition("ConnectionTimeout", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Time connection is maintained without activity (in seconds)"),
+                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),
+                new ColumnDefinition("State", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1;2", description: "Sets intial state of web site"),
+                new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "2", description: "Control the install behavior of web site"),
+                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),
+                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),
+                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),
+                new ColumnDefinition("Sequence", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Allows ordering of web site install"),
+                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),
+                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."),
+            },
+            symbolIdIsPrimaryKey: true
+        );
+
+        public static readonly TableDefinition IIsWebApplication = new TableDefinition(
+            "IIsWebApplication",
+            IisSymbolDefinitions.IIsWebApplication,
+            new[]
+            {
+                new ColumnDefinition("Application", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token for ASP Application", modularizeType: ColumnModularizeType.Column),
+                new ColumnDefinition("Name", ColumnType.Localized, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Name of application in IIS MMC applet", modularizeType: ColumnModularizeType.Property),
+                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"),
+                new ColumnDefinition("AllowSessions", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "Specifies whether application may maintain session state"),
+                new ColumnDefinition("SessionTimeout", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Time session state is maintained without user interaction"),
+                new ColumnDefinition("Buffer", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "Specifies whether application buffers its output"),
+                new ColumnDefinition("ParentPaths", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "What is this for anyway?"),
+                new ColumnDefinition("DefaultScript", ColumnType.String, 26, primaryKey: false, nullable: true, ColumnCategory.Text, possibilities: "VBScript;JScript", description: "Default scripting language for ASP applications"),
+                new ColumnDefinition("ScriptTimeout", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Time ASP application page is permitted to process"),
+                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"),
+                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"),
+                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),
+            },
+            symbolIdIsPrimaryKey: true
+        );
+
+        public static readonly TableDefinition IIsWebApplicationExtension = new TableDefinition(
+            "IIsWebApplicationExtension",
+            IisSymbolDefinitions.IIsWebApplicationExtension,
+            new[]
+            {
+                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),
+                new ColumnDefinition("Extension", ColumnType.String, 255, primaryKey: true, nullable: true, ColumnCategory.Text, description: "Primary key, Extension that should be registered for this ASP application"),
+                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"),
+                new ColumnDefinition("Executable", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Path to extension (usually file property: [#file])", modularizeType: ColumnModularizeType.Property),
+                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"),
+            },
+            symbolIdIsPrimaryKey: false
+        );
+
+        public static readonly TableDefinition IIsFilter = new TableDefinition(
+            "IIsFilter",
+            IisSymbolDefinitions.IIsFilter,
+            new[]
+            {
+                new ColumnDefinition("Filter", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
+                new ColumnDefinition("Name", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Unknown, description: "Name of the ISAPI Filter in IIS"),
+                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),
+                new ColumnDefinition("Path", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Path to filter (usually file property: [#file])", modularizeType: ColumnModularizeType.Property),
+                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),
+                new ColumnDefinition("Description", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Description displayed in IIS MMC applet"),
+                new ColumnDefinition("Flags", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 2147483647, description: "What do all these numbers mean?"),
+                new ColumnDefinition("LoadOrder", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "-1 == last in order, 0 == first in order, # == place in order"),
+            },
+            symbolIdIsPrimaryKey: true
+        );
+
+        public static readonly TableDefinition IIsWebDir = new TableDefinition(
+            "IIsWebDir",
+            IisSymbolDefinitions.IIsWebDir,
+            new[]
+            {
+                new ColumnDefinition("WebDir", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
+                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),
+                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),
+                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),
+                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),
+                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),
+            },
+            symbolIdIsPrimaryKey: true
+        );
+
+        public static readonly TableDefinition IIsWebError = new TableDefinition(
+            "IIsWebError",
+            IisSymbolDefinitions.IIsWebError,
+            new[]
+            {
+                new ColumnDefinition("ErrorCode", ColumnType.Number, 2, primaryKey: true, nullable: false, ColumnCategory.Unknown, minValue: 400, maxValue: 599, description: "HTTP status code indicating error."),
+                new ColumnDefinition("SubCode", ColumnType.Number, 4, primaryKey: true, nullable: false, ColumnCategory.Unknown, description: "HTTP sub-status code indicating error."),
+                new ColumnDefinition("ParentType", ColumnType.Number, 2, primaryKey: true, nullable: false, ColumnCategory.Unknown, possibilities: "1;2", description: "Type of parent: 1=vdir, 2=web"),
+                new ColumnDefinition("ParentValue", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Name of the parent value.", modularizeType: ColumnModularizeType.Column),
+                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."),
+                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."),
+            },
+            symbolIdIsPrimaryKey: false
+        );
+
+        public static readonly TableDefinition IIsHttpHeader = new TableDefinition(
+            "IIsHttpHeader",
+            IisSymbolDefinitions.IIsHttpHeader,
+            new[]
+            {
+                new ColumnDefinition("HttpHeader", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
+                new ColumnDefinition("ParentType", ColumnType.Number, 2, primaryKey: true, nullable: false, ColumnCategory.Unknown, possibilities: "1;2", description: "Type of parent: 1=vdir, 2=web"),
+                new ColumnDefinition("ParentValue", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Name of the parent value.", modularizeType: ColumnModularizeType.Column),
+                new ColumnDefinition("Name", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Name of the HTTP Header"),
+                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."),
+                new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 0, description: "Attributes for HTTP Header: none"),
+                new ColumnDefinition("Sequence", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Order to add the HTTP Headers."),
+            },
+            symbolIdIsPrimaryKey: false
+        );
+
+        public static readonly TableDefinition IIsWebServiceExtension = new TableDefinition(
+            "IIsWebServiceExtension",
+            IisSymbolDefinitions.IIsWebServiceExtension,
+            new[]
+            {
+                new ColumnDefinition("WebServiceExtension", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
+                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),
+                new ColumnDefinition("File", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Path to handler (usually file property: [#file])", modularizeType: ColumnModularizeType.Property),
+                new ColumnDefinition("Description", ColumnType.Localized, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Description displayed in WebServiceExtension Wizard", modularizeType: ColumnModularizeType.Property),
+                new ColumnDefinition("Group", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "String used to identify groups of extensions.", modularizeType: ColumnModularizeType.Property),
+                new ColumnDefinition("Attributes", ColumnType.Number, 1, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 3, description: "Attributes for WebServiceExtension: 1 = Allow, 2 = UIDeletable"),
+            },
+            symbolIdIsPrimaryKey: true
+        );
+
+        public static readonly TableDefinition IIsWebVirtualDir = new TableDefinition(
+            "IIsWebVirtualDir",
+            IisSymbolDefinitions.IIsWebVirtualDir,
+            new[]
+            {
+                new ColumnDefinition("VirtualDir", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
+                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),
+                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),
+                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),
+                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),
+                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),
+                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),
+            },
+            symbolIdIsPrimaryKey: true
+        );
+
+        public static readonly TableDefinition IIsWebLog = new TableDefinition(
+            "IIsWebLog",
+            IisSymbolDefinitions.IIsWebLog,
+            new[]
+            {
+                new ColumnDefinition("Log", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
+                new ColumnDefinition("Format", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Type of log format"),
+            },
+            symbolIdIsPrimaryKey: true
+        );
+
+        public static readonly TableDefinition[] All = new[]
+        {
+            Certificate,
+            CertificateHash,
+            IIsWebSiteCertificates,
+            IIsAppPool,
+            IIsMimeMap,
+            IIsProperty,
+            IIsWebDirProperties,
+            IIsWebAddress,
+            IIsWebSite,
+            IIsWebApplication,
+            IIsWebApplicationExtension,
+            IIsFilter,
+            IIsWebDir,
+            IIsWebError,
+            IIsHttpHeader,
+            IIsWebServiceExtension,
+            IIsWebVirtualDir,
+            IIsWebLog,
+        };
+    }
+}
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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using System.Collections.Generic;
+    using WixToolset.Data.WindowsInstaller;
+    using WixToolset.Extensibility;
+
+    public class IisWindowsInstallerBackendBinderExtension : BaseWindowsInstallerBackendBinderExtension
+    {
+        public override IReadOnlyCollection<TableDefinition> TableDefinitions => IisTableDefinitions.All;
+    }
+}
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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Iis.Symbols;
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly IntermediateSymbolDefinition CertificateHash = new IntermediateSymbolDefinition(
+            IisSymbolDefinitionType.CertificateHash.ToString(),
+            new[]
+            {
+                new IntermediateFieldDefinition(nameof(CertificateHashSymbolFields.CertificateRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(CertificateHashSymbolFields.Hash), IntermediateFieldType.String),
+            },
+            typeof(CertificateHashSymbol));
+    }
+}
+
+namespace WixToolset.Iis.Symbols
+{
+    using WixToolset.Data;
+
+    public enum CertificateHashSymbolFields
+    {
+        CertificateRef,
+        Hash,
+    }
+
+    public class CertificateHashSymbol : IntermediateSymbol
+    {
+        public CertificateHashSymbol() : base(IisSymbolDefinitions.CertificateHash, null, null)
+        {
+        }
+
+        public CertificateHashSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.CertificateHash, sourceLineNumber, id)
+        {
+        }
+
+        public IntermediateField this[CertificateHashSymbolFields index] => this.Fields[(int)index];
+
+        public string CertificateRef
+        {
+            get => this.Fields[(int)CertificateHashSymbolFields.CertificateRef].AsString();
+            set => this.Set((int)CertificateHashSymbolFields.CertificateRef, value);
+        }
+
+        public string Hash
+        {
+            get => this.Fields[(int)CertificateHashSymbolFields.Hash].AsString();
+            set => this.Set((int)CertificateHashSymbolFields.Hash, value);
+        }
+    }
+}
\ 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Iis.Symbols;
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly IntermediateSymbolDefinition Certificate = new IntermediateSymbolDefinition(
+            IisSymbolDefinitionType.Certificate.ToString(),
+            new[]
+            {
+                new IntermediateFieldDefinition(nameof(CertificateSymbolFields.ComponentRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(CertificateSymbolFields.Name), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(CertificateSymbolFields.StoreLocation), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(CertificateSymbolFields.StoreName), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(CertificateSymbolFields.Attributes), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(CertificateSymbolFields.BinaryRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(CertificateSymbolFields.CertificatePath), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(CertificateSymbolFields.PFXPassword), IntermediateFieldType.String),
+            },
+            typeof(CertificateSymbol));
+    }
+}
+
+namespace WixToolset.Iis.Symbols
+{
+    using WixToolset.Data;
+
+    public enum CertificateSymbolFields
+    {
+        ComponentRef,
+        Name,
+        StoreLocation,
+        StoreName,
+        Attributes,
+        BinaryRef,
+        CertificatePath,
+        PFXPassword,
+    }
+
+    public class CertificateSymbol : IntermediateSymbol
+    {
+        public CertificateSymbol() : base(IisSymbolDefinitions.Certificate, null, null)
+        {
+        }
+
+        public CertificateSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.Certificate, sourceLineNumber, id)
+        {
+        }
+
+        public IntermediateField this[CertificateSymbolFields index] => this.Fields[(int)index];
+
+        public string ComponentRef
+        {
+            get => this.Fields[(int)CertificateSymbolFields.ComponentRef].AsString();
+            set => this.Set((int)CertificateSymbolFields.ComponentRef, value);
+        }
+
+        public string Name
+        {
+            get => this.Fields[(int)CertificateSymbolFields.Name].AsString();
+            set => this.Set((int)CertificateSymbolFields.Name, value);
+        }
+
+        public int StoreLocation
+        {
+            get => this.Fields[(int)CertificateSymbolFields.StoreLocation].AsNumber();
+            set => this.Set((int)CertificateSymbolFields.StoreLocation, value);
+        }
+
+        public string StoreName
+        {
+            get => this.Fields[(int)CertificateSymbolFields.StoreName].AsString();
+            set => this.Set((int)CertificateSymbolFields.StoreName, value);
+        }
+
+        public int Attributes
+        {
+            get => this.Fields[(int)CertificateSymbolFields.Attributes].AsNumber();
+            set => this.Set((int)CertificateSymbolFields.Attributes, value);
+        }
+
+        public string BinaryRef
+        {
+            get => this.Fields[(int)CertificateSymbolFields.BinaryRef].AsString();
+            set => this.Set((int)CertificateSymbolFields.BinaryRef, value);
+        }
+
+        public string CertificatePath
+        {
+            get => this.Fields[(int)CertificateSymbolFields.CertificatePath].AsString();
+            set => this.Set((int)CertificateSymbolFields.CertificatePath, value);
+        }
+
+        public string PFXPassword
+        {
+            get => this.Fields[(int)CertificateSymbolFields.PFXPassword].AsString();
+            set => this.Set((int)CertificateSymbolFields.PFXPassword, value);
+        }
+    }
+}
\ 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Iis.Symbols;
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly IntermediateSymbolDefinition IIsAppPool = new IntermediateSymbolDefinition(
+            IisSymbolDefinitionType.IIsAppPool.ToString(),
+            new[]
+            {
+                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.Name), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.ComponentRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.Attributes), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.UserRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.RecycleMinutes), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.RecycleRequests), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.RecycleTimes), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.IdleTimeout), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.QueueLimit), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.CPUMon), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.MaxProc), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.VirtualMemory), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.PrivateMemory), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.ManagedRuntimeVersion), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.ManagedPipelineMode), IntermediateFieldType.String),
+            },
+            typeof(IIsAppPoolSymbol));
+    }
+}
+
+namespace WixToolset.Iis.Symbols
+{
+    using WixToolset.Data;
+
+    public enum IIsAppPoolSymbolFields
+    {
+        Name,
+        ComponentRef,
+        Attributes,
+        UserRef,
+        RecycleMinutes,
+        RecycleRequests,
+        RecycleTimes,
+        IdleTimeout,
+        QueueLimit,
+        CPUMon,
+        MaxProc,
+        VirtualMemory,
+        PrivateMemory,
+        ManagedRuntimeVersion,
+        ManagedPipelineMode,
+    }
+
+    public class IIsAppPoolSymbol : IntermediateSymbol
+    {
+        public IIsAppPoolSymbol() : base(IisSymbolDefinitions.IIsAppPool, null, null)
+        {
+        }
+
+        public IIsAppPoolSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsAppPool, sourceLineNumber, id)
+        {
+        }
+
+        public IntermediateField this[IIsAppPoolSymbolFields index] => this.Fields[(int)index];
+
+        public string Name
+        {
+            get => this.Fields[(int)IIsAppPoolSymbolFields.Name].AsString();
+            set => this.Set((int)IIsAppPoolSymbolFields.Name, value);
+        }
+
+        public string ComponentRef
+        {
+            get => this.Fields[(int)IIsAppPoolSymbolFields.ComponentRef].AsString();
+            set => this.Set((int)IIsAppPoolSymbolFields.ComponentRef, value);
+        }
+
+        public int Attributes
+        {
+            get => this.Fields[(int)IIsAppPoolSymbolFields.Attributes].AsNumber();
+            set => this.Set((int)IIsAppPoolSymbolFields.Attributes, value);
+        }
+
+        public string UserRef
+        {
+            get => this.Fields[(int)IIsAppPoolSymbolFields.UserRef].AsString();
+            set => this.Set((int)IIsAppPoolSymbolFields.UserRef, value);
+        }
+
+        public int? RecycleMinutes
+        {
+            get => this.Fields[(int)IIsAppPoolSymbolFields.RecycleMinutes].AsNullableNumber();
+            set => this.Set((int)IIsAppPoolSymbolFields.RecycleMinutes, value);
+        }
+
+        public int? RecycleRequests
+        {
+            get => this.Fields[(int)IIsAppPoolSymbolFields.RecycleRequests].AsNullableNumber();
+            set => this.Set((int)IIsAppPoolSymbolFields.RecycleRequests, value);
+        }
+
+        public string RecycleTimes
+        {
+            get => this.Fields[(int)IIsAppPoolSymbolFields.RecycleTimes].AsString();
+            set => this.Set((int)IIsAppPoolSymbolFields.RecycleTimes, value);
+        }
+
+        public int? IdleTimeout
+        {
+            get => this.Fields[(int)IIsAppPoolSymbolFields.IdleTimeout].AsNullableNumber();
+            set => this.Set((int)IIsAppPoolSymbolFields.IdleTimeout, value);
+        }
+
+        public int? QueueLimit
+        {
+            get => this.Fields[(int)IIsAppPoolSymbolFields.QueueLimit].AsNullableNumber();
+            set => this.Set((int)IIsAppPoolSymbolFields.QueueLimit, value);
+        }
+
+        public string CPUMon
+        {
+            get => this.Fields[(int)IIsAppPoolSymbolFields.CPUMon].AsString();
+            set => this.Set((int)IIsAppPoolSymbolFields.CPUMon, value);
+        }
+
+        public int? MaxProc
+        {
+            get => this.Fields[(int)IIsAppPoolSymbolFields.MaxProc].AsNullableNumber();
+            set => this.Set((int)IIsAppPoolSymbolFields.MaxProc, value);
+        }
+
+        public int? VirtualMemory
+        {
+            get => this.Fields[(int)IIsAppPoolSymbolFields.VirtualMemory].AsNullableNumber();
+            set => this.Set((int)IIsAppPoolSymbolFields.VirtualMemory, value);
+        }
+
+        public int? PrivateMemory
+        {
+            get => this.Fields[(int)IIsAppPoolSymbolFields.PrivateMemory].AsNullableNumber();
+            set => this.Set((int)IIsAppPoolSymbolFields.PrivateMemory, value);
+        }
+
+        public string ManagedRuntimeVersion
+        {
+            get => this.Fields[(int)IIsAppPoolSymbolFields.ManagedRuntimeVersion].AsString();
+            set => this.Set((int)IIsAppPoolSymbolFields.ManagedRuntimeVersion, value);
+        }
+
+        public string ManagedPipelineMode
+        {
+            get => this.Fields[(int)IIsAppPoolSymbolFields.ManagedPipelineMode].AsString();
+            set => this.Set((int)IIsAppPoolSymbolFields.ManagedPipelineMode, value);
+        }
+    }
+}
\ 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Iis.Symbols;
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly IntermediateSymbolDefinition IIsFilter = new IntermediateSymbolDefinition(
+            IisSymbolDefinitionType.IIsFilter.ToString(),
+            new[]
+            {
+                new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.Name), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.ComponentRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.Path), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.WebRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.Description), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.Flags), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.LoadOrder), IntermediateFieldType.Number),
+            },
+            typeof(IIsFilterSymbol));
+    }
+}
+
+namespace WixToolset.Iis.Symbols
+{
+    using WixToolset.Data;
+
+    public enum IIsFilterSymbolFields
+    {
+        Name,
+        ComponentRef,
+        Path,
+        WebRef,
+        Description,
+        Flags,
+        LoadOrder,
+    }
+
+    public class IIsFilterSymbol : IntermediateSymbol
+    {
+        public IIsFilterSymbol() : base(IisSymbolDefinitions.IIsFilter, null, null)
+        {
+        }
+
+        public IIsFilterSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsFilter, sourceLineNumber, id)
+        {
+        }
+
+        public IntermediateField this[IIsFilterSymbolFields index] => this.Fields[(int)index];
+
+        public string Name
+        {
+            get => this.Fields[(int)IIsFilterSymbolFields.Name].AsString();
+            set => this.Set((int)IIsFilterSymbolFields.Name, value);
+        }
+
+        public string ComponentRef
+        {
+            get => this.Fields[(int)IIsFilterSymbolFields.ComponentRef].AsString();
+            set => this.Set((int)IIsFilterSymbolFields.ComponentRef, value);
+        }
+
+        public string Path
+        {
+            get => this.Fields[(int)IIsFilterSymbolFields.Path].AsString();
+            set => this.Set((int)IIsFilterSymbolFields.Path, value);
+        }
+
+        public string WebRef
+        {
+            get => this.Fields[(int)IIsFilterSymbolFields.WebRef].AsString();
+            set => this.Set((int)IIsFilterSymbolFields.WebRef, value);
+        }
+
+        public string Description
+        {
+            get => this.Fields[(int)IIsFilterSymbolFields.Description].AsString();
+            set => this.Set((int)IIsFilterSymbolFields.Description, value);
+        }
+
+        public int Flags
+        {
+            get => this.Fields[(int)IIsFilterSymbolFields.Flags].AsNumber();
+            set => this.Set((int)IIsFilterSymbolFields.Flags, value);
+        }
+
+        public int? LoadOrder
+        {
+            get => this.Fields[(int)IIsFilterSymbolFields.LoadOrder].AsNullableNumber();
+            set => this.Set((int)IIsFilterSymbolFields.LoadOrder, value);
+        }
+    }
+}
\ 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Iis.Symbols;
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly IntermediateSymbolDefinition IIsHttpHeader = new IntermediateSymbolDefinition(
+            IisSymbolDefinitionType.IIsHttpHeader.ToString(),
+            new[]
+            {
+                new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.HttpHeader), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.ParentType), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.ParentValue), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.Name), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.Value), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.Attributes), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.Sequence), IntermediateFieldType.Number),
+            },
+            typeof(IIsHttpHeaderSymbol));
+    }
+}
+
+namespace WixToolset.Iis.Symbols
+{
+    using WixToolset.Data;
+
+    public enum IIsHttpHeaderSymbolFields
+    {
+        HttpHeader,
+        ParentType,
+        ParentValue,
+        Name,
+        Value,
+        Attributes,
+        Sequence,
+    }
+
+    public class IIsHttpHeaderSymbol : IntermediateSymbol
+    {
+        public IIsHttpHeaderSymbol() : base(IisSymbolDefinitions.IIsHttpHeader, null, null)
+        {
+        }
+
+        public IIsHttpHeaderSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsHttpHeader, sourceLineNumber, id)
+        {
+        }
+
+        public IntermediateField this[IIsHttpHeaderSymbolFields index] => this.Fields[(int)index];
+
+        public string HttpHeader
+        {
+            get => this.Fields[(int)IIsHttpHeaderSymbolFields.HttpHeader].AsString();
+            set => this.Set((int)IIsHttpHeaderSymbolFields.HttpHeader, value);
+        }
+
+        public int ParentType
+        {
+            get => this.Fields[(int)IIsHttpHeaderSymbolFields.ParentType].AsNumber();
+            set => this.Set((int)IIsHttpHeaderSymbolFields.ParentType, value);
+        }
+
+        public string ParentValue
+        {
+            get => this.Fields[(int)IIsHttpHeaderSymbolFields.ParentValue].AsString();
+            set => this.Set((int)IIsHttpHeaderSymbolFields.ParentValue, value);
+        }
+
+        public string Name
+        {
+            get => this.Fields[(int)IIsHttpHeaderSymbolFields.Name].AsString();
+            set => this.Set((int)IIsHttpHeaderSymbolFields.Name, value);
+        }
+
+        public string Value
+        {
+            get => this.Fields[(int)IIsHttpHeaderSymbolFields.Value].AsString();
+            set => this.Set((int)IIsHttpHeaderSymbolFields.Value, value);
+        }
+
+        public int Attributes
+        {
+            get => this.Fields[(int)IIsHttpHeaderSymbolFields.Attributes].AsNumber();
+            set => this.Set((int)IIsHttpHeaderSymbolFields.Attributes, value);
+        }
+
+        public int? Sequence
+        {
+            get => this.Fields[(int)IIsHttpHeaderSymbolFields.Sequence].AsNullableNumber();
+            set => this.Set((int)IIsHttpHeaderSymbolFields.Sequence, value);
+        }
+    }
+}
\ 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Iis.Symbols;
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly IntermediateSymbolDefinition IIsMimeMap = new IntermediateSymbolDefinition(
+            IisSymbolDefinitionType.IIsMimeMap.ToString(),
+            new[]
+            {
+                new IntermediateFieldDefinition(nameof(IIsMimeMapSymbolFields.ParentType), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsMimeMapSymbolFields.ParentValue), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsMimeMapSymbolFields.MimeType), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsMimeMapSymbolFields.Extension), IntermediateFieldType.String),
+            },
+            typeof(IIsMimeMapSymbol));
+    }
+}
+
+namespace WixToolset.Iis.Symbols
+{
+    using WixToolset.Data;
+
+    public enum IIsMimeMapSymbolFields
+    {
+        ParentType,
+        ParentValue,
+        MimeType,
+        Extension,
+    }
+
+    public class IIsMimeMapSymbol : IntermediateSymbol
+    {
+        public IIsMimeMapSymbol() : base(IisSymbolDefinitions.IIsMimeMap, null, null)
+        {
+        }
+
+        public IIsMimeMapSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsMimeMap, sourceLineNumber, id)
+        {
+        }
+
+        public IntermediateField this[IIsMimeMapSymbolFields index] => this.Fields[(int)index];
+
+        public int ParentType
+        {
+            get => this.Fields[(int)IIsMimeMapSymbolFields.ParentType].AsNumber();
+            set => this.Set((int)IIsMimeMapSymbolFields.ParentType, value);
+        }
+
+        public string ParentValue
+        {
+            get => this.Fields[(int)IIsMimeMapSymbolFields.ParentValue].AsString();
+            set => this.Set((int)IIsMimeMapSymbolFields.ParentValue, value);
+        }
+
+        public string MimeType
+        {
+            get => this.Fields[(int)IIsMimeMapSymbolFields.MimeType].AsString();
+            set => this.Set((int)IIsMimeMapSymbolFields.MimeType, value);
+        }
+
+        public string Extension
+        {
+            get => this.Fields[(int)IIsMimeMapSymbolFields.Extension].AsString();
+            set => this.Set((int)IIsMimeMapSymbolFields.Extension, value);
+        }
+    }
+}
\ 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Iis.Symbols;
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly IntermediateSymbolDefinition IIsProperty = new IntermediateSymbolDefinition(
+            IisSymbolDefinitionType.IIsProperty.ToString(),
+            new[]
+            {
+                new IntermediateFieldDefinition(nameof(IIsPropertySymbolFields.ComponentRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsPropertySymbolFields.Attributes), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsPropertySymbolFields.Value), IntermediateFieldType.String),
+            },
+            typeof(IIsPropertySymbol));
+    }
+}
+
+namespace WixToolset.Iis.Symbols
+{
+    using WixToolset.Data;
+
+    public enum IIsPropertySymbolFields
+    {
+        ComponentRef,
+        Attributes,
+        Value,
+    }
+
+    public class IIsPropertySymbol : IntermediateSymbol
+    {
+        public IIsPropertySymbol() : base(IisSymbolDefinitions.IIsProperty, null, null)
+        {
+        }
+
+        public IIsPropertySymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsProperty, sourceLineNumber, id)
+        {
+        }
+
+        public IntermediateField this[IIsPropertySymbolFields index] => this.Fields[(int)index];
+
+        public string ComponentRef
+        {
+            get => this.Fields[(int)IIsPropertySymbolFields.ComponentRef].AsString();
+            set => this.Set((int)IIsPropertySymbolFields.ComponentRef, value);
+        }
+
+        public int Attributes
+        {
+            get => this.Fields[(int)IIsPropertySymbolFields.Attributes].AsNumber();
+            set => this.Set((int)IIsPropertySymbolFields.Attributes, value);
+        }
+
+        public string Value
+        {
+            get => this.Fields[(int)IIsPropertySymbolFields.Value].AsString();
+            set => this.Set((int)IIsPropertySymbolFields.Value, value);
+        }
+    }
+}
\ 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Iis.Symbols;
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly IntermediateSymbolDefinition IIsWebAddress = new IntermediateSymbolDefinition(
+            IisSymbolDefinitionType.IIsWebAddress.ToString(),
+            new[]
+            {
+                new IntermediateFieldDefinition(nameof(IIsWebAddressSymbolFields.WebRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebAddressSymbolFields.IP), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebAddressSymbolFields.Port), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebAddressSymbolFields.Header), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebAddressSymbolFields.Secure), IntermediateFieldType.Number),
+            },
+            typeof(IIsWebAddressSymbol));
+    }
+}
+
+namespace WixToolset.Iis.Symbols
+{
+    using WixToolset.Data;
+
+    public enum IIsWebAddressSymbolFields
+    {
+        WebRef,
+        IP,
+        Port,
+        Header,
+        Secure,
+    }
+
+    public class IIsWebAddressSymbol : IntermediateSymbol
+    {
+        public IIsWebAddressSymbol() : base(IisSymbolDefinitions.IIsWebAddress, null, null)
+        {
+        }
+
+        public IIsWebAddressSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebAddress, sourceLineNumber, id)
+        {
+        }
+
+        public IntermediateField this[IIsWebAddressSymbolFields index] => this.Fields[(int)index];
+
+        public string WebRef
+        {
+            get => this.Fields[(int)IIsWebAddressSymbolFields.WebRef].AsString();
+            set => this.Set((int)IIsWebAddressSymbolFields.WebRef, value);
+        }
+
+        public string IP
+        {
+            get => this.Fields[(int)IIsWebAddressSymbolFields.IP].AsString();
+            set => this.Set((int)IIsWebAddressSymbolFields.IP, value);
+        }
+
+        public string Port
+        {
+            get => this.Fields[(int)IIsWebAddressSymbolFields.Port].AsString();
+            set => this.Set((int)IIsWebAddressSymbolFields.Port, value);
+        }
+
+        public string Header
+        {
+            get => this.Fields[(int)IIsWebAddressSymbolFields.Header].AsString();
+            set => this.Set((int)IIsWebAddressSymbolFields.Header, value);
+        }
+
+        public int? Secure
+        {
+            get => this.Fields[(int)IIsWebAddressSymbolFields.Secure].AsNullableNumber();
+            set => this.Set((int)IIsWebAddressSymbolFields.Secure, value);
+        }
+    }
+}
\ 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Iis.Symbols;
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly IntermediateSymbolDefinition IIsWebApplicationExtension = new IntermediateSymbolDefinition(
+            IisSymbolDefinitionType.IIsWebApplicationExtension.ToString(),
+            new[]
+            {
+                new IntermediateFieldDefinition(nameof(IIsWebApplicationExtensionSymbolFields.ApplicationRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebApplicationExtensionSymbolFields.Extension), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebApplicationExtensionSymbolFields.Verbs), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebApplicationExtensionSymbolFields.Executable), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebApplicationExtensionSymbolFields.Attributes), IntermediateFieldType.Number),
+            },
+            typeof(IIsWebApplicationExtensionSymbol));
+    }
+}
+
+namespace WixToolset.Iis.Symbols
+{
+    using WixToolset.Data;
+
+    public enum IIsWebApplicationExtensionSymbolFields
+    {
+        ApplicationRef,
+        Extension,
+        Verbs,
+        Executable,
+        Attributes,
+    }
+
+    public class IIsWebApplicationExtensionSymbol : IntermediateSymbol
+    {
+        public IIsWebApplicationExtensionSymbol() : base(IisSymbolDefinitions.IIsWebApplicationExtension, null, null)
+        {
+        }
+
+        public IIsWebApplicationExtensionSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebApplicationExtension, sourceLineNumber, id)
+        {
+        }
+
+        public IntermediateField this[IIsWebApplicationExtensionSymbolFields index] => this.Fields[(int)index];
+
+        public string ApplicationRef
+        {
+            get => this.Fields[(int)IIsWebApplicationExtensionSymbolFields.ApplicationRef].AsString();
+            set => this.Set((int)IIsWebApplicationExtensionSymbolFields.ApplicationRef, value);
+        }
+
+        public string Extension
+        {
+            get => this.Fields[(int)IIsWebApplicationExtensionSymbolFields.Extension].AsString();
+            set => this.Set((int)IIsWebApplicationExtensionSymbolFields.Extension, value);
+        }
+
+        public string Verbs
+        {
+            get => this.Fields[(int)IIsWebApplicationExtensionSymbolFields.Verbs].AsString();
+            set => this.Set((int)IIsWebApplicationExtensionSymbolFields.Verbs, value);
+        }
+
+        public string Executable
+        {
+            get => this.Fields[(int)IIsWebApplicationExtensionSymbolFields.Executable].AsString();
+            set => this.Set((int)IIsWebApplicationExtensionSymbolFields.Executable, value);
+        }
+
+        public int Attributes
+        {
+            get => this.Fields[(int)IIsWebApplicationExtensionSymbolFields.Attributes].AsNumber();
+            set => this.Set((int)IIsWebApplicationExtensionSymbolFields.Attributes, value);
+        }
+    }
+}
\ 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Iis.Symbols;
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly IntermediateSymbolDefinition IIsWebApplication = new IntermediateSymbolDefinition(
+            IisSymbolDefinitionType.IIsWebApplication.ToString(),
+            new[]
+            {
+                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.Name), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.Isolation), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.AllowSessions), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.SessionTimeout), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.Buffer), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.ParentPaths), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.DefaultScript), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.ScriptTimeout), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.ServerDebugging), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.ClientDebugging), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.AppPoolRef), IntermediateFieldType.String),
+            },
+            typeof(IIsWebApplicationSymbol));
+    }
+}
+
+namespace WixToolset.Iis.Symbols
+{
+    using WixToolset.Data;
+
+    public enum IIsWebApplicationSymbolFields
+    {
+        Name,
+        Isolation,
+        AllowSessions,
+        SessionTimeout,
+        Buffer,
+        ParentPaths,
+        DefaultScript,
+        ScriptTimeout,
+        ServerDebugging,
+        ClientDebugging,
+        AppPoolRef,
+    }
+
+    public class IIsWebApplicationSymbol : IntermediateSymbol
+    {
+        public IIsWebApplicationSymbol() : base(IisSymbolDefinitions.IIsWebApplication, null, null)
+        {
+        }
+
+        public IIsWebApplicationSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebApplication, sourceLineNumber, id)
+        {
+        }
+
+        public IntermediateField this[IIsWebApplicationSymbolFields index] => this.Fields[(int)index];
+
+        public string Name
+        {
+            get => this.Fields[(int)IIsWebApplicationSymbolFields.Name].AsString();
+            set => this.Set((int)IIsWebApplicationSymbolFields.Name, value);
+        }
+
+        public int Isolation
+        {
+            get => this.Fields[(int)IIsWebApplicationSymbolFields.Isolation].AsNumber();
+            set => this.Set((int)IIsWebApplicationSymbolFields.Isolation, value);
+        }
+
+        public int? AllowSessions
+        {
+            get => this.Fields[(int)IIsWebApplicationSymbolFields.AllowSessions].AsNullableNumber();
+            set => this.Set((int)IIsWebApplicationSymbolFields.AllowSessions, value);
+        }
+
+        public int? SessionTimeout
+        {
+            get => this.Fields[(int)IIsWebApplicationSymbolFields.SessionTimeout].AsNullableNumber();
+            set => this.Set((int)IIsWebApplicationSymbolFields.SessionTimeout, value);
+        }
+
+        public int? Buffer
+        {
+            get => this.Fields[(int)IIsWebApplicationSymbolFields.Buffer].AsNullableNumber();
+            set => this.Set((int)IIsWebApplicationSymbolFields.Buffer, value);
+        }
+
+        public int? ParentPaths
+        {
+            get => this.Fields[(int)IIsWebApplicationSymbolFields.ParentPaths].AsNullableNumber();
+            set => this.Set((int)IIsWebApplicationSymbolFields.ParentPaths, value);
+        }
+
+        public string DefaultScript
+        {
+            get => this.Fields[(int)IIsWebApplicationSymbolFields.DefaultScript].AsString();
+            set => this.Set((int)IIsWebApplicationSymbolFields.DefaultScript, value);
+        }
+
+        public int? ScriptTimeout
+        {
+            get => this.Fields[(int)IIsWebApplicationSymbolFields.ScriptTimeout].AsNullableNumber();
+            set => this.Set((int)IIsWebApplicationSymbolFields.ScriptTimeout, value);
+        }
+
+        public int? ServerDebugging
+        {
+            get => this.Fields[(int)IIsWebApplicationSymbolFields.ServerDebugging].AsNullableNumber();
+            set => this.Set((int)IIsWebApplicationSymbolFields.ServerDebugging, value);
+        }
+
+        public int? ClientDebugging
+        {
+            get => this.Fields[(int)IIsWebApplicationSymbolFields.ClientDebugging].AsNullableNumber();
+            set => this.Set((int)IIsWebApplicationSymbolFields.ClientDebugging, value);
+        }
+
+        public string AppPoolRef
+        {
+            get => this.Fields[(int)IIsWebApplicationSymbolFields.AppPoolRef].AsString();
+            set => this.Set((int)IIsWebApplicationSymbolFields.AppPoolRef, value);
+        }
+    }
+}
\ 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Iis.Symbols;
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly IntermediateSymbolDefinition IIsWebDirProperties = new IntermediateSymbolDefinition(
+            IisSymbolDefinitionType.IIsWebDirProperties.ToString(),
+            new[]
+            {
+                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.Access), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.Authorization), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.AnonymousUserRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.IIsControlledPassword), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.LogVisits), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.Index), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.DefaultDoc), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.AspDetailedError), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.HttpExpires), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.CacheControlMaxAge), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.CacheControlCustom), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.NoCustomError), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.AccessSSLFlags), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.AuthenticationProviders), IntermediateFieldType.String),
+            },
+            typeof(IIsWebDirPropertiesSymbol));
+    }
+}
+
+namespace WixToolset.Iis.Symbols
+{
+    using WixToolset.Data;
+
+    public enum IIsWebDirPropertiesSymbolFields
+    {
+        Access,
+        Authorization,
+        AnonymousUserRef,
+        IIsControlledPassword,
+        LogVisits,
+        Index,
+        DefaultDoc,
+        AspDetailedError,
+        HttpExpires,
+        CacheControlMaxAge,
+        CacheControlCustom,
+        NoCustomError,
+        AccessSSLFlags,
+        AuthenticationProviders,
+    }
+
+    public class IIsWebDirPropertiesSymbol : IntermediateSymbol
+    {
+        public IIsWebDirPropertiesSymbol() : base(IisSymbolDefinitions.IIsWebDirProperties, null, null)
+        {
+        }
+
+        public IIsWebDirPropertiesSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebDirProperties, sourceLineNumber, id)
+        {
+        }
+
+        public IntermediateField this[IIsWebDirPropertiesSymbolFields index] => this.Fields[(int)index];
+
+        public int? Access
+        {
+            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.Access].AsNullableNumber();
+            set => this.Set((int)IIsWebDirPropertiesSymbolFields.Access, value);
+        }
+
+        public int? Authorization
+        {
+            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.Authorization].AsNullableNumber();
+            set => this.Set((int)IIsWebDirPropertiesSymbolFields.Authorization, value);
+        }
+
+        public string AnonymousUserRef
+        {
+            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.AnonymousUserRef].AsString();
+            set => this.Set((int)IIsWebDirPropertiesSymbolFields.AnonymousUserRef, value);
+        }
+
+        public int? IIsControlledPassword
+        {
+            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.IIsControlledPassword].AsNullableNumber();
+            set => this.Set((int)IIsWebDirPropertiesSymbolFields.IIsControlledPassword, value);
+        }
+
+        public int? LogVisits
+        {
+            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.LogVisits].AsNullableNumber();
+            set => this.Set((int)IIsWebDirPropertiesSymbolFields.LogVisits, value);
+        }
+
+        public int? Index
+        {
+            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.Index].AsNullableNumber();
+            set => this.Set((int)IIsWebDirPropertiesSymbolFields.Index, value);
+        }
+
+        public string DefaultDoc
+        {
+            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.DefaultDoc].AsString();
+            set => this.Set((int)IIsWebDirPropertiesSymbolFields.DefaultDoc, value);
+        }
+
+        public int? AspDetailedError
+        {
+            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.AspDetailedError].AsNullableNumber();
+            set => this.Set((int)IIsWebDirPropertiesSymbolFields.AspDetailedError, value);
+        }
+
+        public string HttpExpires
+        {
+            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.HttpExpires].AsString();
+            set => this.Set((int)IIsWebDirPropertiesSymbolFields.HttpExpires, value);
+        }
+
+        public int? CacheControlMaxAge
+        {
+            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.CacheControlMaxAge].AsNullableNumber();
+            set => this.Set((int)IIsWebDirPropertiesSymbolFields.CacheControlMaxAge, value);
+        }
+
+        public string CacheControlCustom
+        {
+            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.CacheControlCustom].AsString();
+            set => this.Set((int)IIsWebDirPropertiesSymbolFields.CacheControlCustom, value);
+        }
+
+        public int? NoCustomError
+        {
+            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.NoCustomError].AsNullableNumber();
+            set => this.Set((int)IIsWebDirPropertiesSymbolFields.NoCustomError, value);
+        }
+
+        public int? AccessSSLFlags
+        {
+            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.AccessSSLFlags].AsNullableNumber();
+            set => this.Set((int)IIsWebDirPropertiesSymbolFields.AccessSSLFlags, value);
+        }
+
+        public string AuthenticationProviders
+        {
+            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.AuthenticationProviders].AsString();
+            set => this.Set((int)IIsWebDirPropertiesSymbolFields.AuthenticationProviders, value);
+        }
+    }
+}
\ 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Iis.Symbols;
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly IntermediateSymbolDefinition IIsWebDir = new IntermediateSymbolDefinition(
+            IisSymbolDefinitionType.IIsWebDir.ToString(),
+            new[]
+            {
+                new IntermediateFieldDefinition(nameof(IIsWebDirSymbolFields.ComponentRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebDirSymbolFields.WebRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebDirSymbolFields.Path), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebDirSymbolFields.DirPropertiesRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebDirSymbolFields.ApplicationRef), IntermediateFieldType.String),
+            },
+            typeof(IIsWebDirSymbol));
+    }
+}
+
+namespace WixToolset.Iis.Symbols
+{
+    using WixToolset.Data;
+
+    public enum IIsWebDirSymbolFields
+    {
+        ComponentRef,
+        WebRef,
+        Path,
+        DirPropertiesRef,
+        ApplicationRef,
+    }
+
+    public class IIsWebDirSymbol : IntermediateSymbol
+    {
+        public IIsWebDirSymbol() : base(IisSymbolDefinitions.IIsWebDir, null, null)
+        {
+        }
+
+        public IIsWebDirSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebDir, sourceLineNumber, id)
+        {
+        }
+
+        public IntermediateField this[IIsWebDirSymbolFields index] => this.Fields[(int)index];
+
+        public string ComponentRef
+        {
+            get => this.Fields[(int)IIsWebDirSymbolFields.ComponentRef].AsString();
+            set => this.Set((int)IIsWebDirSymbolFields.ComponentRef, value);
+        }
+
+        public string WebRef
+        {
+            get => this.Fields[(int)IIsWebDirSymbolFields.WebRef].AsString();
+            set => this.Set((int)IIsWebDirSymbolFields.WebRef, value);
+        }
+
+        public string Path
+        {
+            get => this.Fields[(int)IIsWebDirSymbolFields.Path].AsString();
+            set => this.Set((int)IIsWebDirSymbolFields.Path, value);
+        }
+
+        public string DirPropertiesRef
+        {
+            get => this.Fields[(int)IIsWebDirSymbolFields.DirPropertiesRef].AsString();
+            set => this.Set((int)IIsWebDirSymbolFields.DirPropertiesRef, value);
+        }
+
+        public string ApplicationRef
+        {
+            get => this.Fields[(int)IIsWebDirSymbolFields.ApplicationRef].AsString();
+            set => this.Set((int)IIsWebDirSymbolFields.ApplicationRef, value);
+        }
+    }
+}
\ 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Iis.Symbols;
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly IntermediateSymbolDefinition IIsWebError = new IntermediateSymbolDefinition(
+            IisSymbolDefinitionType.IIsWebError.ToString(),
+            new[]
+            {
+                new IntermediateFieldDefinition(nameof(IIsWebErrorSymbolFields.ErrorCode), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebErrorSymbolFields.SubCode), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebErrorSymbolFields.ParentType), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebErrorSymbolFields.ParentValue), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebErrorSymbolFields.File), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebErrorSymbolFields.URL), IntermediateFieldType.String),
+            },
+            typeof(IIsWebErrorSymbol));
+    }
+}
+
+namespace WixToolset.Iis.Symbols
+{
+    using WixToolset.Data;
+
+    public enum IIsWebErrorSymbolFields
+    {
+        ErrorCode,
+        SubCode,
+        ParentType,
+        ParentValue,
+        File,
+        URL,
+    }
+
+    public class IIsWebErrorSymbol : IntermediateSymbol
+    {
+        public IIsWebErrorSymbol() : base(IisSymbolDefinitions.IIsWebError, null, null)
+        {
+        }
+
+        public IIsWebErrorSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebError, sourceLineNumber, id)
+        {
+        }
+
+        public IntermediateField this[IIsWebErrorSymbolFields index] => this.Fields[(int)index];
+
+        public int ErrorCode
+        {
+            get => this.Fields[(int)IIsWebErrorSymbolFields.ErrorCode].AsNumber();
+            set => this.Set((int)IIsWebErrorSymbolFields.ErrorCode, value);
+        }
+
+        public int SubCode
+        {
+            get => this.Fields[(int)IIsWebErrorSymbolFields.SubCode].AsNumber();
+            set => this.Set((int)IIsWebErrorSymbolFields.SubCode, value);
+        }
+
+        public int ParentType
+        {
+            get => this.Fields[(int)IIsWebErrorSymbolFields.ParentType].AsNumber();
+            set => this.Set((int)IIsWebErrorSymbolFields.ParentType, value);
+        }
+
+        public string ParentValue
+        {
+            get => this.Fields[(int)IIsWebErrorSymbolFields.ParentValue].AsString();
+            set => this.Set((int)IIsWebErrorSymbolFields.ParentValue, value);
+        }
+
+        public string File
+        {
+            get => this.Fields[(int)IIsWebErrorSymbolFields.File].AsString();
+            set => this.Set((int)IIsWebErrorSymbolFields.File, value);
+        }
+
+        public string URL
+        {
+            get => this.Fields[(int)IIsWebErrorSymbolFields.URL].AsString();
+            set => this.Set((int)IIsWebErrorSymbolFields.URL, value);
+        }
+    }
+}
\ 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Iis.Symbols;
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly IntermediateSymbolDefinition IIsWebLog = new IntermediateSymbolDefinition(
+            IisSymbolDefinitionType.IIsWebLog.ToString(),
+            new[]
+            {
+                new IntermediateFieldDefinition(nameof(IIsWebLogSymbolFields.Format), IntermediateFieldType.String),
+            },
+            typeof(IIsWebLogSymbol));
+    }
+}
+
+namespace WixToolset.Iis.Symbols
+{
+    using WixToolset.Data;
+
+    public enum IIsWebLogSymbolFields
+    {
+        Format,
+    }
+
+    public class IIsWebLogSymbol : IntermediateSymbol
+    {
+        public IIsWebLogSymbol() : base(IisSymbolDefinitions.IIsWebLog, null, null)
+        {
+        }
+
+        public IIsWebLogSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebLog, sourceLineNumber, id)
+        {
+        }
+
+        public IntermediateField this[IIsWebLogSymbolFields index] => this.Fields[(int)index];
+
+        public string Format
+        {
+            get => this.Fields[(int)IIsWebLogSymbolFields.Format].AsString();
+            set => this.Set((int)IIsWebLogSymbolFields.Format, value);
+        }
+    }
+}
\ 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Iis.Symbols;
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly IntermediateSymbolDefinition IIsWebServiceExtension = new IntermediateSymbolDefinition(
+            IisSymbolDefinitionType.IIsWebServiceExtension.ToString(),
+            new[]
+            {
+                new IntermediateFieldDefinition(nameof(IIsWebServiceExtensionSymbolFields.ComponentRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebServiceExtensionSymbolFields.File), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebServiceExtensionSymbolFields.Description), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebServiceExtensionSymbolFields.Group), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebServiceExtensionSymbolFields.Attributes), IntermediateFieldType.Number),
+            },
+            typeof(IIsWebServiceExtensionSymbol));
+    }
+}
+
+namespace WixToolset.Iis.Symbols
+{
+    using WixToolset.Data;
+
+    public enum IIsWebServiceExtensionSymbolFields
+    {
+        ComponentRef,
+        File,
+        Description,
+        Group,
+        Attributes,
+    }
+
+    public class IIsWebServiceExtensionSymbol : IntermediateSymbol
+    {
+        public IIsWebServiceExtensionSymbol() : base(IisSymbolDefinitions.IIsWebServiceExtension, null, null)
+        {
+        }
+
+        public IIsWebServiceExtensionSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebServiceExtension, sourceLineNumber, id)
+        {
+        }
+
+        public IntermediateField this[IIsWebServiceExtensionSymbolFields index] => this.Fields[(int)index];
+
+        public string ComponentRef
+        {
+            get => this.Fields[(int)IIsWebServiceExtensionSymbolFields.ComponentRef].AsString();
+            set => this.Set((int)IIsWebServiceExtensionSymbolFields.ComponentRef, value);
+        }
+
+        public string File
+        {
+            get => this.Fields[(int)IIsWebServiceExtensionSymbolFields.File].AsString();
+            set => this.Set((int)IIsWebServiceExtensionSymbolFields.File, value);
+        }
+
+        public string Description
+        {
+            get => this.Fields[(int)IIsWebServiceExtensionSymbolFields.Description].AsString();
+            set => this.Set((int)IIsWebServiceExtensionSymbolFields.Description, value);
+        }
+
+        public string Group
+        {
+            get => this.Fields[(int)IIsWebServiceExtensionSymbolFields.Group].AsString();
+            set => this.Set((int)IIsWebServiceExtensionSymbolFields.Group, value);
+        }
+
+        public int Attributes
+        {
+            get => this.Fields[(int)IIsWebServiceExtensionSymbolFields.Attributes].AsNumber();
+            set => this.Set((int)IIsWebServiceExtensionSymbolFields.Attributes, value);
+        }
+    }
+}
\ 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Iis.Symbols;
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly IntermediateSymbolDefinition IIsWebSiteCertificates = new IntermediateSymbolDefinition(
+            IisSymbolDefinitionType.IIsWebSiteCertificates.ToString(),
+            new[]
+            {
+                new IntermediateFieldDefinition(nameof(IIsWebSiteCertificatesSymbolFields.WebRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebSiteCertificatesSymbolFields.CertificateRef), IntermediateFieldType.String),
+            },
+            typeof(IIsWebSiteCertificatesSymbol));
+    }
+}
+
+namespace WixToolset.Iis.Symbols
+{
+    using WixToolset.Data;
+
+    public enum IIsWebSiteCertificatesSymbolFields
+    {
+        WebRef,
+        CertificateRef,
+    }
+
+    public class IIsWebSiteCertificatesSymbol : IntermediateSymbol
+    {
+        public IIsWebSiteCertificatesSymbol() : base(IisSymbolDefinitions.IIsWebSiteCertificates, null, null)
+        {
+        }
+
+        public IIsWebSiteCertificatesSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebSiteCertificates, sourceLineNumber, id)
+        {
+        }
+
+        public IntermediateField this[IIsWebSiteCertificatesSymbolFields index] => this.Fields[(int)index];
+
+        public string WebRef
+        {
+            get => this.Fields[(int)IIsWebSiteCertificatesSymbolFields.WebRef].AsString();
+            set => this.Set((int)IIsWebSiteCertificatesSymbolFields.WebRef, value);
+        }
+
+        public string CertificateRef
+        {
+            get => this.Fields[(int)IIsWebSiteCertificatesSymbolFields.CertificateRef].AsString();
+            set => this.Set((int)IIsWebSiteCertificatesSymbolFields.CertificateRef, value);
+        }
+    }
+}
\ 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Iis.Symbols;
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly IntermediateSymbolDefinition IIsWebSite = new IntermediateSymbolDefinition(
+            IisSymbolDefinitionType.IIsWebSite.ToString(),
+            new[]
+            {
+                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.ComponentRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.Description), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.ConnectionTimeout), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.DirectoryRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.State), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.Attributes), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.KeyAddressRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.DirPropertiesRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.ApplicationRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.Sequence), IntermediateFieldType.Number),
+                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.LogRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.WebsiteId), IntermediateFieldType.String),
+            },
+            typeof(IIsWebSiteSymbol));
+    }
+}
+
+namespace WixToolset.Iis.Symbols
+{
+    using WixToolset.Data;
+
+    public enum IIsWebSiteSymbolFields
+    {
+        ComponentRef,
+        Description,
+        ConnectionTimeout,
+        DirectoryRef,
+        State,
+        Attributes,
+        KeyAddressRef,
+        DirPropertiesRef,
+        ApplicationRef,
+        Sequence,
+        LogRef,
+        WebsiteId,
+    }
+
+    public class IIsWebSiteSymbol : IntermediateSymbol
+    {
+        public IIsWebSiteSymbol() : base(IisSymbolDefinitions.IIsWebSite, null, null)
+        {
+        }
+
+        public IIsWebSiteSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebSite, sourceLineNumber, id)
+        {
+        }
+
+        public IntermediateField this[IIsWebSiteSymbolFields index] => this.Fields[(int)index];
+
+        public string ComponentRef
+        {
+            get => this.Fields[(int)IIsWebSiteSymbolFields.ComponentRef].AsString();
+            set => this.Set((int)IIsWebSiteSymbolFields.ComponentRef, value);
+        }
+
+        public string Description
+        {
+            get => this.Fields[(int)IIsWebSiteSymbolFields.Description].AsString();
+            set => this.Set((int)IIsWebSiteSymbolFields.Description, value);
+        }
+
+        public int? ConnectionTimeout
+        {
+            get => this.Fields[(int)IIsWebSiteSymbolFields.ConnectionTimeout].AsNullableNumber();
+            set => this.Set((int)IIsWebSiteSymbolFields.ConnectionTimeout, value);
+        }
+
+        public string DirectoryRef
+        {
+            get => this.Fields[(int)IIsWebSiteSymbolFields.DirectoryRef].AsString();
+            set => this.Set((int)IIsWebSiteSymbolFields.DirectoryRef, value);
+        }
+
+        public int? State
+        {
+            get => this.Fields[(int)IIsWebSiteSymbolFields.State].AsNullableNumber();
+            set => this.Set((int)IIsWebSiteSymbolFields.State, value);
+        }
+
+        public int Attributes
+        {
+            get => this.Fields[(int)IIsWebSiteSymbolFields.Attributes].AsNumber();
+            set => this.Set((int)IIsWebSiteSymbolFields.Attributes, value);
+        }
+
+        public string KeyAddressRef
+        {
+            get => this.Fields[(int)IIsWebSiteSymbolFields.KeyAddressRef].AsString();
+            set => this.Set((int)IIsWebSiteSymbolFields.KeyAddressRef, value);
+        }
+
+        public string DirPropertiesRef
+        {
+            get => this.Fields[(int)IIsWebSiteSymbolFields.DirPropertiesRef].AsString();
+            set => this.Set((int)IIsWebSiteSymbolFields.DirPropertiesRef, value);
+        }
+
+        public string ApplicationRef
+        {
+            get => this.Fields[(int)IIsWebSiteSymbolFields.ApplicationRef].AsString();
+            set => this.Set((int)IIsWebSiteSymbolFields.ApplicationRef, value);
+        }
+
+        public int? Sequence
+        {
+            get => this.Fields[(int)IIsWebSiteSymbolFields.Sequence].AsNullableNumber();
+            set => this.Set((int)IIsWebSiteSymbolFields.Sequence, value);
+        }
+
+        public string LogRef
+        {
+            get => this.Fields[(int)IIsWebSiteSymbolFields.LogRef].AsString();
+            set => this.Set((int)IIsWebSiteSymbolFields.LogRef, value);
+        }
+
+        public string WebsiteId
+        {
+            get => this.Fields[(int)IIsWebSiteSymbolFields.WebsiteId].AsString();
+            set => this.Set((int)IIsWebSiteSymbolFields.WebsiteId, value);
+        }
+    }
+}
\ 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using WixToolset.Data;
+    using WixToolset.Iis.Symbols;
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly IntermediateSymbolDefinition IIsWebVirtualDir = new IntermediateSymbolDefinition(
+            IisSymbolDefinitionType.IIsWebVirtualDir.ToString(),
+            new[]
+            {
+                new IntermediateFieldDefinition(nameof(IIsWebVirtualDirSymbolFields.ComponentRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebVirtualDirSymbolFields.WebRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebVirtualDirSymbolFields.Alias), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebVirtualDirSymbolFields.DirectoryRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebVirtualDirSymbolFields.DirPropertiesRef), IntermediateFieldType.String),
+                new IntermediateFieldDefinition(nameof(IIsWebVirtualDirSymbolFields.ApplicationRef), IntermediateFieldType.String),
+            },
+            typeof(IIsWebVirtualDirSymbol));
+    }
+}
+
+namespace WixToolset.Iis.Symbols
+{
+    using WixToolset.Data;
+
+    public enum IIsWebVirtualDirSymbolFields
+    {
+        ComponentRef,
+        WebRef,
+        Alias,
+        DirectoryRef,
+        DirPropertiesRef,
+        ApplicationRef,
+    }
+
+    public class IIsWebVirtualDirSymbol : IntermediateSymbol
+    {
+        public IIsWebVirtualDirSymbol() : base(IisSymbolDefinitions.IIsWebVirtualDir, null, null)
+        {
+        }
+
+        public IIsWebVirtualDirSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebVirtualDir, sourceLineNumber, id)
+        {
+        }
+
+        public IntermediateField this[IIsWebVirtualDirSymbolFields index] => this.Fields[(int)index];
+
+        public string ComponentRef
+        {
+            get => this.Fields[(int)IIsWebVirtualDirSymbolFields.ComponentRef].AsString();
+            set => this.Set((int)IIsWebVirtualDirSymbolFields.ComponentRef, value);
+        }
+
+        public string WebRef
+        {
+            get => this.Fields[(int)IIsWebVirtualDirSymbolFields.WebRef].AsString();
+            set => this.Set((int)IIsWebVirtualDirSymbolFields.WebRef, value);
+        }
+
+        public string Alias
+        {
+            get => this.Fields[(int)IIsWebVirtualDirSymbolFields.Alias].AsString();
+            set => this.Set((int)IIsWebVirtualDirSymbolFields.Alias, value);
+        }
+
+        public string DirectoryRef
+        {
+            get => this.Fields[(int)IIsWebVirtualDirSymbolFields.DirectoryRef].AsString();
+            set => this.Set((int)IIsWebVirtualDirSymbolFields.DirectoryRef, value);
+        }
+
+        public string DirPropertiesRef
+        {
+            get => this.Fields[(int)IIsWebVirtualDirSymbolFields.DirPropertiesRef].AsString();
+            set => this.Set((int)IIsWebVirtualDirSymbolFields.DirPropertiesRef, value);
+        }
+
+        public string ApplicationRef
+        {
+            get => this.Fields[(int)IIsWebVirtualDirSymbolFields.ApplicationRef].AsString();
+            set => this.Set((int)IIsWebVirtualDirSymbolFields.ApplicationRef, value);
+        }
+    }
+}
\ 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 @@
+// 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.
+
+namespace WixToolset.Iis
+{
+    using System;
+    using WixToolset.Data;
+
+    public enum IisSymbolDefinitionType
+    {
+        Certificate,
+        CertificateHash,
+        IIsAppPool,
+        IIsFilter,
+        IIsHttpHeader,
+        IIsMimeMap,
+        IIsProperty,
+        IIsWebAddress,
+        IIsWebApplication,
+        IIsWebApplicationExtension,
+        IIsWebDir,
+        IIsWebDirProperties,
+        IIsWebError,
+        IIsWebLog,
+        IIsWebServiceExtension,
+        IIsWebSite,
+        IIsWebSiteCertificates,
+        IIsWebVirtualDir,
+    }
+
+    public static partial class IisSymbolDefinitions
+    {
+        public static readonly Version Version = new Version("4.0.0");
+
+        public static IntermediateSymbolDefinition ByName(string name)
+        {
+            if (!Enum.TryParse(name, out IisSymbolDefinitionType type))
+            {
+                return null;
+            }
+
+            return ByType(type);
+        }
+
+        public static IntermediateSymbolDefinition ByType(IisSymbolDefinitionType type)
+        {
+            switch (type)
+            {
+                case IisSymbolDefinitionType.Certificate:
+                    return IisSymbolDefinitions.Certificate;
+
+                case IisSymbolDefinitionType.CertificateHash:
+                    return IisSymbolDefinitions.CertificateHash;
+
+                case IisSymbolDefinitionType.IIsAppPool:
+                    return IisSymbolDefinitions.IIsAppPool;
+
+                case IisSymbolDefinitionType.IIsFilter:
+                    return IisSymbolDefinitions.IIsFilter;
+
+                case IisSymbolDefinitionType.IIsHttpHeader:
+                    return IisSymbolDefinitions.IIsHttpHeader;
+
+                case IisSymbolDefinitionType.IIsMimeMap:
+                    return IisSymbolDefinitions.IIsMimeMap;
+
+                case IisSymbolDefinitionType.IIsProperty:
+                    return IisSymbolDefinitions.IIsProperty;
+
+                case IisSymbolDefinitionType.IIsWebAddress:
+                    return IisSymbolDefinitions.IIsWebAddress;
+
+                case IisSymbolDefinitionType.IIsWebApplication:
+                    return IisSymbolDefinitions.IIsWebApplication;
+
+                case IisSymbolDefinitionType.IIsWebApplicationExtension:
+                    return IisSymbolDefinitions.IIsWebApplicationExtension;
+
+                case IisSymbolDefinitionType.IIsWebDir:
+                    return IisSymbolDefinitions.IIsWebDir;
+
+                case IisSymbolDefinitionType.IIsWebDirProperties:
+                    return IisSymbolDefinitions.IIsWebDirProperties;
+
+                case IisSymbolDefinitionType.IIsWebError:
+                    return IisSymbolDefinitions.IIsWebError;
+
+                case IisSymbolDefinitionType.IIsWebLog:
+                    return IisSymbolDefinitions.IIsWebLog;
+
+                case IisSymbolDefinitionType.IIsWebServiceExtension:
+                    return IisSymbolDefinitions.IIsWebServiceExtension;
+
+                case IisSymbolDefinitionType.IIsWebSite:
+                    return IisSymbolDefinitions.IIsWebSite;
+
+                case IisSymbolDefinitionType.IIsWebSiteCertificates:
+                    return IisSymbolDefinitions.IIsWebSiteCertificates;
+
+                case IisSymbolDefinitionType.IIsWebVirtualDir:
+                    return IisSymbolDefinitions.IIsWebVirtualDir;
+
+                default:
+                    throw new ArgumentOutOfRangeException(nameof(type));
+            }
+        }
+    }
+}
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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>netstandard2.0</TargetFramework>
+    <RootNamespace>WixToolset.Iis</RootNamespace>
+    <Description>WiX Toolset Iis Extension</Description>
+    <Title>WiX Toolset Iis Extension</Title>
+    <IsTool>true</IsTool>
+    <ContentTargetFolders>build</ContentTargetFolders>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Content Include="$(MSBuildThisFileName).targets" />
+    <EmbeddedResource Include="$(OutputPath)..\iis.wixlib" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="WixToolset.Data" Version="4.0.*" PrivateAssets="all" />
+    <PackageReference Include="WixToolset.Extensibility" Version="4.0.*" PrivateAssets="all" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\wixlib\iis.wixproj" ReferenceOutputAssembly="false" Condition=" '$(NCrunch)'=='' " />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Nerdbank.GitVersioning" Version="2.1.65" PrivateAssets="all" />
+  </ItemGroup>
+</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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+  <PropertyGroup>
+    <WixToolsetIisWixextPath Condition=" '$(WixToolsetIisWixextPath)' == '' ">$(MSBuildThisFileDirectory)..\tools\WixToolset.Iis.wixext.dll</WixToolsetIisWixextPath>
+  </PropertyGroup>
+  <ItemGroup>
+    <WixExtension Include="$(WixToolsetIisWixextPath)" />
+  </ItemGroup>
+</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 @@
+<!-- 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. -->
+
+
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
+    <?include caerr.wxi ?>
+
+    <Fragment>
+        <Property Id="IISMAJORVERSION">
+            <RegistrySearch Id="IIsMajorVersionSearch" Root="HKLM" Key="SOFTWARE\Microsoft\InetStp" Name="MajorVersion" Type="raw" />
+        </Property>
+
+        <Property Id="IISMINORVERSION">
+            <RegistrySearch Id="IIsMinorVersionSearch" Root="HKLM" Key="SOFTWARE\Microsoft\InetStp" Name="MinorVersion" Type="raw" />
+        </Property>
+    </Fragment>
+
+    <Fragment>
+      <UI Id="WixIIsErrors">
+        <Error Id="$(var.msierrIISCannotConnect)" Message="!(loc.msierrIISCannotConnect)" />
+        <Error Id="$(var.msierrIISFailedReadWebSite)" Message="!(loc.msierrIISFailedReadWebSite)" />
+        <Error Id="$(var.msierrIISFailedReadWebDirs)" Message="!(loc.msierrIISFailedReadWebDirs)" />
+        <Error Id="$(var.msierrIISFailedReadVDirs)" Message="!(loc.msierrIISFailedReadVDirs)" />
+        <Error Id="$(var.msierrIISFailedReadFilters)" Message="!(loc.msierrIISFailedReadFilters)" />
+        <Error Id="$(var.msierrIISFailedReadMimeMap)" Message="!(loc.msierrIISFailedReadMimeMap)" />
+        <Error Id="$(var.msierrIISFailedReadAppPool)" Message="!(loc.msierrIISFailedReadAppPool)" />
+        <Error Id="$(var.msierrIISFailedReadProp)" Message="!(loc.msierrIISFailedReadProp)" />
+        <Error Id="$(var.msierrIISFailedReadWebSvcExt)" Message="!(loc.msierrIISFailedReadWebSvcExt)" />
+        <Error Id="$(var.msierrIISFailedReadWebError)" Message="!(loc.msierrIISFailedReadWebError)" />
+        <Error Id="$(var.msierrIISFailedReadHttpHeader)" Message="!(loc.msierrIISFailedReadHttpHeader)" />
+
+        <Error Id="$(var.msierrIISFailedSchedTransaction)" Message="!(loc.msierrIISFailedSchedTransaction)" />
+        <Error Id="$(var.msierrIISFailedSchedInstallWebs)" Message="!(loc.msierrIISFailedSchedInstallWebs)" />
+        <Error Id="$(var.msierrIISFailedSchedInstallWebDirs)" Message="!(loc.msierrIISFailedSchedInstallWebDirs)" />
+        <Error Id="$(var.msierrIISFailedSchedInstallVDirs)" Message="!(loc.msierrIISFailedSchedInstallVDirs)" />
+        <Error Id="$(var.msierrIISFailedSchedInstallFilters)" Message="!(loc.msierrIISFailedSchedInstallFilters)" />
+        <Error Id="$(var.msierrIISFailedSchedInstallAppPool)" Message="!(loc.msierrIISFailedSchedInstallAppPool)" />
+        <Error Id="$(var.msierrIISFailedSchedInstallProp)" Message="!(loc.msierrIISFailedSchedInstallProp)" />
+        <Error Id="$(var.msierrIISFailedSchedInstallWebSvcExt)" Message="!(loc.msierrIISFailedSchedInstallWebSvcExt)" />
+
+        <Error Id="$(var.msierrIISFailedSchedUninstallWebs)" Message="!(loc.msierrIISFailedSchedUninstallWebs)" />
+        <Error Id="$(var.msierrIISFailedSchedUninstallWebDirs)" Message="!(loc.msierrIISFailedSchedUninstallWebDirs)" />
+        <Error Id="$(var.msierrIISFailedSchedUninstallVDirs)" Message="!(loc.msierrIISFailedSchedUninstallVDirs)" />
+        <Error Id="$(var.msierrIISFailedSchedUninstallFilters)" Message="!(loc.msierrIISFailedSchedUninstallFilters)" />
+        <Error Id="$(var.msierrIISFailedSchedUninstallAppPool)" Message="!(loc.msierrIISFailedSchedUninstallAppPool)" />
+        <Error Id="$(var.msierrIISFailedSchedUninstallProp)" Message="!(loc.msierrIISFailedSchedUninstallProp)" />
+        <Error Id="$(var.msierrIISFailedSchedUninstallWebSvcExt)" Message="!(loc.msierrIISFailedSchedUninstallWebSvcExt)" />
+
+        <Error Id="$(var.msierrIISFailedStartTransaction)" Message="!(loc.msierrIISFailedStartTransaction)" />
+        <Error Id="$(var.msierrIISFailedOpenKey)" Message="!(loc.msierrIISFailedOpenKey)" />
+        <Error Id="$(var.msierrIISFailedCreateKey)" Message="!(loc.msierrIISFailedCreateKey)" />
+        <Error Id="$(var.msierrIISFailedWriteData)" Message="!(loc.msierrIISFailedWriteData)" />
+        <Error Id="$(var.msierrIISFailedCreateApp)" Message="!(loc.msierrIISFailedCreateApp)" />
+        <Error Id="$(var.msierrIISFailedDeleteKey)" Message="!(loc.msierrIISFailedDeleteKey)" />
+        <Error Id="$(var.msierrIISFailedDeleteValue)" Message="!(loc.msierrIISFailedDeleteValue)" />
+        <Error Id="$(var.msierrIISFailedCommitInUse)" Message="!(loc.msierrIISFailedCommitInUse)" />
+      </UI>
+    </Fragment>
+</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 @@
+<!-- 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. -->
+
+
+<Include xmlns="http://wixtoolset.org/schemas/v4/wxs">
+  <?include caDecor.wxi ?>
+  
+  <Fragment>
+    <UIRef Id="WixIIsErrors" />
+    <UI>
+      <ProgressText Action="$(var.Prefix)ConfigureIIs$(var.Suffix)" Message="!(loc.ConfigureIIs)" />
+      <ProgressText Action="$(var.Prefix)ConfigureIIsExec$(var.Suffix)" Message="!(loc.ConfigureIIsExec)" />
+      <ProgressText Action="$(var.Prefix)StartMetabaseTransaction$(var.Suffix)" Message="!(loc.StartMetabaseTransaction)" />
+      <ProgressText Action="$(var.Prefix)RollbackMetabaseTransaction$(var.Suffix)" Message="!(loc.RollbackMetabaseTransaction)" />
+      <ProgressText Action="$(var.Prefix)CommitMetabaseTransaction$(var.Suffix)" Message="!(loc.CommitMetabaseTransaction)" />
+      <ProgressText Action="$(var.Prefix)WriteMetabaseChanges$(var.Suffix)" Message="!(loc.WriteMetabaseChanges)" />
+
+      <ProgressText Action="$(var.Prefix)ConfigureIIs7Exec$(var.Suffix)" Message="!(loc.ConfigureIIs7Exec)" />
+      <ProgressText Action="$(var.Prefix)StartIIS7ConfigTransaction$(var.Suffix)" Message="!(loc.StartIIS7ConfigTransaction)" />
+      <ProgressText Action="$(var.Prefix)RollbackIIS7ConfigTransaction$(var.Suffix)" Message="!(loc.RollbackIIS7ConfigTransaction)" />
+      <ProgressText Action="$(var.Prefix)CommitIIS7ConfigTransaction$(var.Suffix)" Message="!(loc.CommitIIS7ConfigTransaction)" />
+      <ProgressText Action="$(var.Prefix)WriteIIS7ConfigChanges$(var.Suffix)" Message="!(loc.WriteIIS7ConfigChanges)" />
+    </UI>
+
+    <CustomAction Id="$(var.Prefix)ConfigureIIs$(var.Suffix)" DllEntry="ConfigureIIs" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
+    <CustomAction Id="$(var.Prefix)ConfigureIIsExec$(var.Suffix)" DllEntry="ConfigureIIsExec" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
+    <CustomAction Id="$(var.Prefix)StartMetabaseTransaction$(var.Suffix)" DllEntry="StartMetabaseTransaction" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
+    <CustomAction Id="$(var.Prefix)RollbackMetabaseTransaction$(var.Suffix)" DllEntry="RollbackMetabaseTransaction" Impersonate="no" Execute="rollback" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
+    <CustomAction Id="$(var.Prefix)CommitMetabaseTransaction$(var.Suffix)" DllEntry="CommitMetabaseTransaction" Impersonate="no" Execute="commit" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
+    <CustomAction Id="$(var.Prefix)WriteMetabaseChanges$(var.Suffix)" DllEntry="WriteMetabaseChanges" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
+
+    <CustomAction Id="$(var.Prefix)ConfigureIIs7Exec$(var.Suffix)" DllEntry="ConfigureIIs7Exec" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
+    <CustomAction Id="$(var.Prefix)StartIIS7ConfigTransaction$(var.Suffix)" DllEntry="StartIIS7ConfigTransaction" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
+    <CustomAction Id="$(var.Prefix)RollbackIIS7ConfigTransaction$(var.Suffix)" DllEntry="RollbackIIS7ConfigTransaction" Impersonate="no" Execute="rollback" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
+    <CustomAction Id="$(var.Prefix)CommitIIS7ConfigTransaction$(var.Suffix)" DllEntry="CommitIIS7ConfigTransaction" Impersonate="no" Execute="commit" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
+    <CustomAction Id="$(var.Prefix)WriteIIS7ConfigChanges$(var.Suffix)" DllEntry="WriteIIS7ConfigChanges" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
+
+    <InstallExecuteSequence>
+      <Custom Action="$(var.Prefix)ConfigureIIs$(var.Suffix)" Before="RegisterUser" Overridable="yes" Condition="NOT SKIPCONFIGUREIIS AND VersionNT &gt; 400" />
+    </InstallExecuteSequence>
+  </Fragment>
+
+  <Fragment>
+    <Binary Id="IisCA$(var.Suffix)" SourceFile="!(bindpath.$(var.platform))iisca.dll" />
+  </Fragment>
+
+  <Fragment>
+    <CustomAction Id="$(var.Prefix)InstallCertificates$(var.Suffix)" DllEntry="InstallCertificates" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
+    <CustomAction Id="$(var.Prefix)UninstallCertificates$(var.Suffix)" DllEntry="UninstallCertificates" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
+
+    <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)" />
+    <CustomAction Id="$(var.Prefix)AddMachineCertificate$(var.Suffix)" DllEntry="AddMachineCertificate" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
+    <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)" />
+    <CustomAction Id="$(var.Prefix)DeleteMachineCertificate$(var.Suffix)" DllEntry="DeleteMachineCertificate" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
+
+    <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)" />
+    <CustomAction Id="$(var.Prefix)RollbackAddMachineCertificate$(var.Suffix)" DllEntry="DeleteMachineCertificate" Impersonate="no" Execute="rollback" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
+    <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)" />
+    <CustomAction Id="$(var.Prefix)RollbackDeleteMachineCertificate$(var.Suffix)" DllEntry="AddMachineCertificate" Impersonate="no" Execute="rollback" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
+
+    <InstallExecuteSequence>
+      <Custom Action="UninstallCertificates$(var.Suffix)" Before="RemoveFiles" Overridable="yes" Condition="VersionNT &gt; 400" />
+      <Custom Action="InstallCertificates$(var.Suffix)" After="InstallFiles" Overridable="yes" Condition="VersionNT &gt; 400" />
+    </InstallExecuteSequence>
+  </Fragment>
+
+</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 @@
+<!-- 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. -->
+
+
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
+    <?define platform=arm64 ?>
+    <?include IIsExtension_Platform.wxi ?>
+</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 @@
+<!-- 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. -->
+
+
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
+    <?define platform=x64 ?>
+    <?include IIsExtension_Platform.wxi ?>
+</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 @@
+<!-- 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. -->
+
+
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
+    <?define platform=x86 ?>
+    <?include IIsExtension_Platform.wxi ?>
+</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 @@
+<!-- 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. -->
+
+
+<Include xmlns="http://wixtoolset.org/schemas/v4/wxs">
+    <?ifdef Prefix ?>
+        <?undef Prefix ?>
+    <?endif?>
+
+    <?define Prefix="Wix4" ?>
+
+    <?ifndef platform ?>
+        <?define platform="x86" ?>
+    <?endif?>
+
+    <?if $(var.platform)="" ?>
+        <?undef platform ?>
+        <?define platform="x86" ?>
+    <?endif?>
+
+    <?ifdef Suffix ?>
+        <?undef Suffix ?>
+    <?endif?>
+
+    <?if $(var.platform)~="x86" ?>
+        <?define Suffix="_X86" ?>
+    <?endif?>
+
+    <?if $(var.platform)~="x64" ?>
+        <?define Suffix="_X64" ?>
+    <?endif?>
+
+    <?if $(var.platform)~="arm" ?>
+        <?define Suffix="_A32" ?>
+    <?endif?>
+
+    <?if $(var.platform)~="arm64" ?>
+        <?define Suffix="_A64" ?>
+    <?endif?>
+</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 @@
+<Include xmlns="http://wixtoolset.org/schemas/v4/wxs">
+  <?define msierrSecureObjectsFailedCreateSD = 25520?>
+  <?define msierrSecureObjectsFailedSet = 25521?>
+  <?define msierrSecureObjectsUnknownType = 25522?>
+  <?define msierrXmlFileFailedRead = 25530?>
+  <?define msierrXmlFileFailedOpen = 25531?>
+  <?define msierrXmlFileFailedSelect = 25532?>
+  <?define msierrXmlFileFailedSave = 25533?>
+  <?define msierrXmlConfigFailedRead = 25540?>
+  <?define msierrXmlConfigFailedOpen = 25541?>
+  <?define msierrXmlConfigFailedSelect = 25542?>
+  <?define msierrXmlConfigFailedSave = 25543?>
+  <?define msierrFirewallCannotConnect = 25580?>
+  <?define msierrIISCannotConnect = 26001?>
+  <?define msierrIISFailedReadWebSite = 26002?>
+  <?define msierrIISFailedReadWebDirs = 26003?>
+  <?define msierrIISFailedReadVDirs = 26004?>
+  <?define msierrIISFailedReadFilters = 26005?>
+  <?define msierrIISFailedReadAppPool = 26006?>
+  <?define msierrIISFailedReadMimeMap = 26007?>
+  <?define msierrIISFailedReadProp = 26008?>
+  <?define msierrIISFailedReadWebSvcExt = 26009?>
+  <?define msierrIISFailedReadWebError = 26010?>
+  <?define msierrIISFailedReadHttpHeader = 26011?>
+  <?define msierrIISFailedSchedTransaction = 26031?>
+  <?define msierrIISFailedSchedInstallWebs = 26032?>
+  <?define msierrIISFailedSchedInstallWebDirs = 26033?>
+  <?define msierrIISFailedSchedInstallVDirs = 26034?>
+  <?define msierrIISFailedSchedInstallFilters = 26035?>
+  <?define msierrIISFailedSchedInstallAppPool = 26036?>
+  <?define msierrIISFailedSchedInstallProp = 26037?>
+  <?define msierrIISFailedSchedInstallWebSvcExt = 26038?>
+  <?define msierrIISFailedSchedUninstallWebs = 26051?>
+  <?define msierrIISFailedSchedUninstallWebDirs = 26052?>
+  <?define msierrIISFailedSchedUninstallVDirs = 26053?>
+  <?define msierrIISFailedSchedUninstallFilters = 26054?>
+  <?define msierrIISFailedSchedUninstallAppPool = 26055?>
+  <?define msierrIISFailedSchedUninstallProp = 26056?>
+  <?define msierrIISFailedSchedUninstallWebSvcExt = 26057?>
+  <?define msierrIISFailedStartTransaction = 26101?>
+  <?define msierrIISFailedOpenKey = 26102?>
+  <?define msierrIISFailedCreateKey = 26103?>
+  <?define msierrIISFailedWriteData = 26104?>
+  <?define msierrIISFailedCreateApp = 26105?>
+  <?define msierrIISFailedDeleteKey = 26106?>
+  <?define msierrIISFailedDeleteApp = 26107?>
+  <?define msierrIISFailedDeleteValue = 26108?>
+  <?define msierrIISFailedCommitInUse = 26109?>
+  <?define msierrSQLFailedCreateDatabase = 26201?>
+  <?define msierrSQLFailedDropDatabase = 26202?>
+  <?define msierrSQLFailedConnectDatabase = 26203?>
+  <?define msierrSQLFailedExecString = 26204?>
+  <?define msierrSQLDatabaseAlreadyExists = 26205?>
+  <?define msierrPERFMONFailedRegisterDLL = 26251?>
+  <?define msierrPERFMONFailedUnregisterDLL = 26252?>
+  <?define msierrInstallPerfCounterData = 26253?>
+  <?define msierrUninstallPerfCounterData = 26254?>
+  <?define msierrSMBFailedCreate = 26301?>
+  <?define msierrSMBFailedDrop = 26302?>
+  <?define msierrCERTFailedOpen = 26351?>
+  <?define msierrCERTFailedAdd = 26352?>
+  <?define msierrUSRFailedUserCreate = 26401?>
+  <?define msierrUSRFailedUserCreatePswd = 26402?>
+  <?define msierrUSRFailedUserGroupAdd = 26403?>
+  <?define msierrUSRFailedUserCreateExists = 26404?>
+  <?define msierrUSRFailedGrantLogonAsService = 26405?>
+  <?define msierrDependencyMissingDependencies = 26451?>
+  <?define msierrDependencyHasDependents = 26452?>
+  <?define msierrDotNetRuntimeRequired = 27000?>
+  <?define msierrComPlusCannotConnect = 28001?>
+  <?define msierrComPlusPartitionReadFailed = 28002?>
+  <?define msierrComPlusPartitionRoleReadFailed = 28003?>
+  <?define msierrComPlusUserInPartitionRoleReadFailed = 28004?>
+  <?define msierrComPlusPartitionUserReadFailed = 28005?>
+  <?define msierrComPlusApplicationReadFailed = 28006?>
+  <?define msierrComPlusApplicationRoleReadFailed = 28007?>
+  <?define msierrComPlusUserInApplicationRoleReadFailed = 28008?>
+  <?define msierrComPlusAssembliesReadFailed = 28009?>
+  <?define msierrComPlusSubscriptionReadFailed = 28010?>
+  <?define msierrComPlusPartitionDependency = 28011?>
+  <?define msierrComPlusPartitionNotFound = 28012?>
+  <?define msierrComPlusPartitionIdConflict = 28013?>
+  <?define msierrComPlusPartitionNameConflict = 28014?>
+  <?define msierrComPlusApplicationDependency = 28015?>
+  <?define msierrComPlusApplicationNotFound = 28016?>
+  <?define msierrComPlusApplicationIdConflict = 28017?>
+  <?define msierrComPlusApplicationNameConflict = 28018?>
+  <?define msierrComPlusApplicationRoleDependency = 28019?>
+  <?define msierrComPlusApplicationRoleNotFound = 28020?>
+  <?define msierrComPlusApplicationRoleConflict = 28021?>
+  <?define msierrComPlusAssemblyDependency = 28022?>
+  <?define msierrComPlusSubscriptionIdConflict = 28023?>
+  <?define msierrComPlusSubscriptionNameConflict = 28024?>
+  <?define msierrComPlusFailedLookupNames = 28025?>
+  <?define msierrMsmqCannotConnect = 28101?>
+</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 @@
+<!-- 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. -->
+
+
+<WixLocalization Culture="de-de" xmlns="http://wixtoolset.org/schemas/v4/wxl">
+    <String Id="msierrIISCannotConnect" Overridable="yes">Konnte keine Verbindung mit dem Internet Information Server herstellen.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadWebSite" Overridable="yes">Fehler bei der Verarbeitung der WebSites.   ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadWebDirs" Overridable="yes">Fehler bei der Verarbeitung der WebDirs.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadVDirs" Overridable="yes">Fehler bei der Verarbeitung der WebVirtualDirs.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadFilters" Overridable="yes">Fehler bei der Verarbeitung der WebFilters.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadMimeMap" Overridable="yes">Fehler bei der Verarbeitung der MimeMaps. ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadAppPool" Overridable="yes">Fehler bei der Verarbeitung der WebAppPools. ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadProp" Overridable="yes">Fehler bei der Verarbeitung der WebProperties. ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadWebSvcExt" Overridable="yes">Fehler bei der Verarbeitung der WebServiceExtensions. ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadWebError" Overridable="yes">Fehler bei der Verarbeitung der WebErrors. ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadHttpHeader" Overridable="yes">Fehler bei der Verarbeitung der HttpHeader. ([2]   [3]   [4]   [5])</String>
+
+    <String Id="msierrIISFailedSchedTransaction" Overridable="yes">Die Transaktion für Änderungen am IIS konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallWebs" Overridable="yes">Die Installation von IIS-Websites konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallWebDirs" Overridable="yes">Die Installation von IIS Web Directories konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallVDirs" Overridable="yes">Die Installation von IIS Virtual Directories konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallFilters" Overridable="yes">Die Installation von IIS Filters konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallAppPool" Overridable="yes">Die Installation von IIS AppPools konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallProp" Overridable="yes">Die Installation von IIS Properties konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallWebSvcExt" Overridable="yes">Die Installation von IIS Web Service Extensions konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
+
+    <String Id="msierrIISFailedSchedUninstallWebs" Overridable="yes">Die Deinstallation von IIS Web Sites konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallWebDirs" Overridable="yes">Die Deinstallation von IIS Web Directories konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallVDirs" Overridable="yes">Die Deinstallation von IIS Virtual Directories konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallFilters" Overridable="yes">Die Deinstallation von IIS Filters konnte nicht geschedulded werden.   ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallAppPool" Overridable="yes">Die Deinstallation von IIS AppPools konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallProp" Overridable="yes">Die Deinstallation der IIS Properties konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallWebSvcExt" Overridable="yes">Die Deinstallation von IIS Web Service Extensions konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
+
+    <String Id="msierrIISFailedStartTransaction" Overridable="yes">Die IIS-Transaktion konnte nicht gestartet werden. ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedOpenKey" Overridable="yes">Der Metabase Key konnte nicht geöffnet werden.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedCreateKey" Overridable="yes">Der Metabase Key konnte nicht erstellt werden.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedWriteData" Overridable="yes">Daten konnten nicht in den Metabase Key geschrieben werden.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedCreateApp" Overridable="yes">Webanwendung konnte nicht erstellt werden.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedDeleteKey" Overridable="yes">Der Metabase Key konnte nicht gelöscht werden.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedDeleteValue" Overridable="yes">Der Metabase Value konnte nicht gelöscht werden.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedCommitInUse" Overridable="yes">Die IIS Transaktion konnte aufgrund einer Freigabeverletzung nicht committed werden. Möglicherweise konfiguriert eine andere Anwendung derzeit IIS.</String>
+
+    <String Id="ConfigureIIs" Overridable="yes">Konfiguriere IIS</String>
+    <String Id="ConfigureIIsExec" Overridable="yes">Führe IIS Konfiguration aus</String>
+    <String Id="StartMetabaseTransaction" Overridable="yes">Starte IIS Metabase Transaktion</String>
+    <String Id="RollbackMetabaseTransaction" Overridable="yes">Mache IIS Metabase Transaktion rückgängig</String>
+    <String Id="CommitMetabaseTransaction" Overridable="yes">Committe IIS Metabase Transaktion</String>
+    <String Id="WriteMetabaseChanges" Overridable="yes">Installiere Metabase Keys und Values</String>
+
+    <String Id="ConfigureIIs7Exec" Overridable="yes">Konfiguriere IIS</String>
+    <String Id="StartIIS7ConfigTransaction" Overridable="yes">Starte IIS Konfigurationstransaktion</String>
+    <String Id="RollbackIIS7ConfigTransaction" Overridable="yes">Mache IIS Konfigurationstransaktion rückgängig</String>
+    <String Id="CommitIIS7ConfigTransaction" Overridable="yes">Committe IIS Konfigurationstransaktion</String>
+    <String Id="WriteIIS7ConfigChanges" Overridable="yes">Installiere Konfigurationskeys and -values</String>
+</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 @@
+<!-- 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. -->
+
+
+<WixLocalization Culture="en-us" xmlns="http://wixtoolset.org/schemas/v4/wxl">
+    <String Id="msierrIISCannotConnect" Overridable="yes">Cannot connect to Internet Information Server.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadWebSite" Overridable="yes">Failed while processing WebSites.   ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadWebDirs" Overridable="yes">Failed while processing WebDirs.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadVDirs" Overridable="yes">Failed while processing WebVirtualDirs.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadFilters" Overridable="yes">Failed while processing WebFilters.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadMimeMap" Overridable="yes">Failed while processing MimeMaps. ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadAppPool" Overridable="yes">Failed while processing WebAppPools. ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadProp" Overridable="yes">Failed while processing WebProperties. ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadWebSvcExt" Overridable="yes">Failed while processing WebServiceExtensions. ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadWebError" Overridable="yes">Failed while processing WebErrors. ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadHttpHeader" Overridable="yes">Failed while processing HttpHeaders. ([2]   [3]   [4]   [5])</String>
+
+    <String Id="msierrIISFailedSchedTransaction" Overridable="yes">Failed to schedule transaction for changes to IIS.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallWebs" Overridable="yes">Failed to schedule install of IIS Web Sites.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallWebDirs" Overridable="yes">Failed to schedule install of IIS Web Directories.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallVDirs" Overridable="yes">Failed to schedule install of IIS Virtual Directories.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallFilters" Overridable="yes">Failed to schedule install of IIS Filters.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallAppPool" Overridable="yes">Failed to schedule install of IIS AppPools.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallProp" Overridable="yes">Failed to schedule install of IIS Properties.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallWebSvcExt" Overridable="yes">Failed to schedule install of IIS Web Service Extensions.  ([2]   [3]   [4]   [5])</String>
+
+    <String Id="msierrIISFailedSchedUninstallWebs" Overridable="yes">Failed to schedule uninstall of IIS Web Sites.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallWebDirs" Overridable="yes">Failed to schedule uninstall of IIS Web Directories.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallVDirs" Overridable="yes">Failed to schedule uninstall of IIS Virtual Directories.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallFilters" Overridable="yes">Failed to schedule uninstall of IIS Filters.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallAppPool" Overridable="yes">Failed to schedule uninstall of IIS AppPools.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallProp" Overridable="yes">Failed to schedule uninstall of IIS Properties.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallWebSvcExt" Overridable="yes">Failed to schedule uninstall of IIS Web Service Extensions.  ([2]   [3]   [4]   [5])</String>
+
+    <String Id="msierrIISFailedStartTransaction" Overridable="yes">Failed to start IIS transaction. ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedOpenKey" Overridable="yes">Failed to open metabase key.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedCreateKey" Overridable="yes">Failed to create metabase key.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedWriteData" Overridable="yes">Failed to write data to metabase key.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedCreateApp" Overridable="yes">Failed to create web application.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedDeleteKey" Overridable="yes">Failed to delete metabase key.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedDeleteValue" Overridable="yes">Failed to delete metabase value.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedCommitInUse" Overridable="yes">Failed to commit IIS transaction due to a sharing violation.  Some other application may be configuring IIS.</String>
+
+    <String Id="ConfigureIIs" Overridable="yes">Configuring IIS</String>
+    <String Id="ConfigureIIsExec" Overridable="yes">Executing IIS Configuration</String>
+    <String Id="StartMetabaseTransaction" Overridable="yes">Starting IIS Metabase Transaction</String>
+    <String Id="RollbackMetabaseTransaction" Overridable="yes">Rolling back IIS Metabase Transaction</String>
+    <String Id="CommitMetabaseTransaction" Overridable="yes">Committing IIS Metabase Transaction</String>
+    <String Id="WriteMetabaseChanges" Overridable="yes">Installing Metabase Keys and Values</String>
+
+    <String Id="ConfigureIIs7Exec" Overridable="yes">Configuring IIS</String>
+    <String Id="StartIIS7ConfigTransaction" Overridable="yes">Starting IIS Config Transaction</String>
+    <String Id="RollbackIIS7ConfigTransaction" Overridable="yes">Rolling back IIS Config Transaction</String>
+    <String Id="CommitIIS7ConfigTransaction" Overridable="yes">Committing IIS Config Transaction</String>
+    <String Id="WriteIIS7ConfigChanges" Overridable="yes">Installing Config Keys and Values</String>
+</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 @@
+<ProjectConfiguration>
+  <Settings>
+    <IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
+  </Settings>
+</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 @@
+<!-- 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. -->
+<Project Sdk="WixToolset.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Library</OutputType>
+    <BindFiles>true</BindFiles>
+    <Cultures>en-us</Cultures>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <BindInputPaths Include="$(OutputPath)x86" BindName='x86' />
+    <BindInputPaths Include="$(OutputPath)x64" BindName='x64' />
+    <BindInputPaths Include="$(OutputPath)arm64" BindName='arm64' />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\ca\iisca.vcxproj" Properties="Platform=ARM64" />
+    <ProjectReference Include="..\ca\iisca.vcxproj" Properties="Platform=x86" />
+    <ProjectReference Include="..\ca\iisca.vcxproj" Properties="Platform=x64" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Nerdbank.GitVersioning" Version="2.1.65" PrivateAssets="All" />
+  </ItemGroup>
+
+</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 @@
+<!-- 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. -->
+
+
+<WixLocalization Culture="ja-jp" xmlns="http://wixtoolset.org/schemas/v4/wxl">
+  <String Id="msierrIISCannotConnect" Overridable="yes">IISへ接続できません。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedReadWebSite" Overridable="yes">ウェブ サイト処理中に失敗しました。   ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedReadWebDirs" Overridable="yes">ウェブ ディレクトリ処理中に失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedReadVDirs" Overridable="yes">ウェブ仮想ディレクトリ処理中に失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedReadFilters" Overridable="yes">ウェブ フィルタ処理中に失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedReadMimeMap" Overridable="yes">MIME マップ処理中に失敗しました。 ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedReadAppPool" Overridable="yes">ウェブ アプリケーション プール処理中に失敗しました。 ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedReadProp" Overridable="yes">ウェブ プロパティ処理中に失敗しました。 ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedReadWebSvcExt" Overridable="yes">ウェブ サービス拡張処理中に失敗しました。 ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedReadWebError" Overridable="yes">ウェブ エラー処理中に失敗しました。 ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedReadHttpHeader" Overridable="yes">HTTP ヘッダ処理中に失敗しました。 ([2]   [3]   [4]   [5])</String>
+
+  <String Id="msierrIISFailedSchedTransaction" Overridable="yes">IIS 変更トランザクションのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedSchedInstallWebs" Overridable="yes">IIS ウェブ サイト インストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedSchedInstallWebDirs" Overridable="yes">IIS ウェブ ディレクトリ インストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedSchedInstallVDirs" Overridable="yes">IIS 仮想ディレクトリ インストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedSchedInstallFilters" Overridable="yes">IIS フィルタ インストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedSchedInstallAppPool" Overridable="yes">IIS アプリケーション プール インストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedSchedInstallProp" Overridable="yes">IIS プロパティ インストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedSchedInstallWebSvcExt" Overridable="yes">IIS ウェブ サービス拡張インストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
+
+  <String Id="msierrIISFailedSchedUninstallWebs" Overridable="yes">IISウェブ サイト アンインストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedSchedUninstallWebDirs" Overridable="yes">IIS ウェブ ディレクトリ アンインストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedSchedUninstallVDirs" Overridable="yes">IIS 仮想ディレクトリ アンインストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedSchedUninstallFilters" Overridable="yes">IIS フィルタ アンインストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedSchedUninstallAppPool" Overridable="yes">IIS アプリケーション プール アンインストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedSchedUninstallProp" Overridable="yes">IIS プロパティ アンインストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedSchedUninstallWebSvcExt" Overridable="yes">IIS ウェブ サービス拡張アンインストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
+
+  <String Id="msierrIISFailedStartTransaction" Overridable="yes">IIS トランザクション開始に失敗しました。 ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedOpenKey" Overridable="yes">メタベース キーのオープンに失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedCreateKey" Overridable="yes">メタベース キーの作成に失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedWriteData" Overridable="yes">メタベース キーの書き込みに失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedCreateApp" Overridable="yes">ウェブ アプリケーションの作成に失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedDeleteKey" Overridable="yes">メタベース キーの削除に失敗しました。  ([2]   [3]   [4]   [5])</String>
+  <String Id="msierrIISFailedDeleteValue" Overridable="yes">メタベース値の削除に失敗しました。  ([2]   [3]   [4]   [5])</String>
+
+  <String Id="ConfigureIIs" Overridable="yes">IIS を構成しています</String>
+  <String Id="StartMetabaseTransaction" Overridable="yes">IIS メタベース トランザクションを開始しています</String>
+  <String Id="RollbackMetabaseTransaction" Overridable="yes">IIS メタベース トランザクションをロールバックしています</String>
+  <String Id="CommitMetabaseTransaction" Overridable="yes">IIS メタベース トランザクションを確定しています</String>
+  <String Id="WriteMetabaseChanges" Overridable="yes">IIS メタベース キーと値をインストールしています</String>
+</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 @@
+<!-- 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. -->
+
+
+<WixLocalization Culture="pt-br" xmlns="http://wixtoolset.org/schemas/v4/wxl">
+    <String Id="msierrIISCannotConnect" Overridable="yes">Não foi possível conectar no Internet Information Server.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadWebSite" Overridable="yes">Erro ao processar WebSites.   ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadWebDirs" Overridable="yes">Erro ao processar WebDirs.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadVDirs" Overridable="yes">Erro ao processar WebVirtualDirs.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadFilters" Overridable="yes">Erro ao processar WebFilters.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadMimeMap" Overridable="yes">Erro ao processar MimeMaps. ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadAppPool" Overridable="yes">Erro ao processar WebAppPools. ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadProp" Overridable="yes">Erro ao processar WebProperties. ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadWebSvcExt" Overridable="yes">Erro ao processar WebServiceExtensions. ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadWebError" Overridable="yes">Erro ao processar WebErrors. ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedReadHttpHeader" Overridable="yes">Erro ao processar HttpHeaders. ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedTransaction" Overridable="yes">Erro ao agendar transação para alterações no IIS.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallWebs" Overridable="yes">Erro ao agendar instalação de IIS Web Sites.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallWebDirs" Overridable="yes">Erro ao agendar instalação de IIS Web Directories.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallVDirs" Overridable="yes">Erro ao agendar instalação de IIS Virtual Directories.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallFilters" Overridable="yes">Erro ao agendar instalação de IIS Filters.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallAppPool" Overridable="yes">Erro ao agendar instalação de IIS AppPools.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallProp" Overridable="yes">Erro ao agendar instalação de IIS Properties.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedInstallWebSvcExt" Overridable="yes">Erro ao agendar instalação de IIS Web Service Extensions.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallWebs" Overridable="yes">Erro ao agendar desinstalação de IIS Web Sites.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallWebDirs" Overridable="yes">Erro ao agendar desinstalação de IIS Web Directories.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallVDirs" Overridable="yes">Erro ao agendar desinstalação de IIS Virtual Directories.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallFilters" Overridable="yes">Erro ao agendar desinstalação de IIS Filters.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallAppPool" Overridable="yes">Erro ao agendar desinstalação de IIS AppPools.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallProp" Overridable="yes">Erro ao agendar desinstalação de IIS Properties.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedSchedUninstallWebSvcExt" Overridable="yes">Erro ao agendar desinstalação de IIS Web Service Extensions.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedStartTransaction" Overridable="yes">Erro ao iniciar transação do IIS . ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedOpenKey" Overridable="yes">Erro ao abrir metabase key.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedCreateKey" Overridable="yes">Erro ao criar metabase key.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedWriteData" Overridable="yes">Erro ao escrever dados na metabase key.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedCreateApp" Overridable="yes">Erro ao criar aplicação Web.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedDeleteKey" Overridable="yes">Erro ao excluir metabase key.  ([2]   [3]   [4]   [5])</String>
+    <String Id="msierrIISFailedDeleteValue" Overridable="yes">Erro ao excluir valor da metabase.  ([2]   [3]   [4]   [5])</String>
+    <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>
+    <String Id="ConfigureIIs" Overridable="yes">Configurando IIS</String>
+    <String Id="ConfigureIIsExec" Overridable="yes">Executando Configurações do IIS</String>
+    <String Id="StartMetabaseTransaction" Overridable="yes">Iniciando Transação de Metabase do IIS</String>
+    <String Id="RollbackMetabaseTransaction" Overridable="yes">Cancelando Transação de Metabase do IIS</String>
+    <String Id="CommitMetabaseTransaction" Overridable="yes">Efetivando Transação de Metabase do IIS</String>
+    <String Id="WriteMetabaseChanges" Overridable="yes">Instalando Chaves e Valores de Metabase do IIS</String>
+    <String Id="ConfigureIIs7Exec" Overridable="yes">Configurando IIS</String>
+    <String Id="StartIIS7ConfigTransaction" Overridable="yes">Iniciando Transação de Configuração do IIS</String>
+    <String Id="RollbackIIS7ConfigTransaction" Overridable="yes">Cancelando Transação de Configuração do IIS</String>
+    <String Id="CommitIIS7ConfigTransaction" Overridable="yes">Efetivando Transação de Configuração do IIS</String>
+    <String Id="WriteIIS7ConfigChanges" Overridable="yes">Instalando Chaves e Valores de Configurações do IIS</String>
+</WixLocalization>
diff --git a/src/ext/global.json b/src/ext/global.json
new file mode 100644
index 00000000..23dd3fa6
--- /dev/null
+++ b/src/ext/global.json
@@ -0,0 +1,5 @@
+{
+  "msbuild-sdks": {
+    "WixToolset.Sdk": "4.0.0-build-0211"
+  }
+}
diff --git a/src/test/WixToolsetTest.Iis/IisExtensionFixture.cs b/src/test/WixToolsetTest.Iis/IisExtensionFixture.cs
deleted file mode 100644
index 685e7126..00000000
--- a/src/test/WixToolsetTest.Iis/IisExtensionFixture.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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.
-
-namespace WixToolsetTest.Iis
-{
-    using System.Linq;
-    using WixBuildTools.TestSupport;
-    using WixToolset.Core.TestPackage;
-    using WixToolset.Iis;
-    using Xunit;
-
-    public class IisExtensionFixture
-    {
-        [Fact]
-        public void CanBuildUsingIIsWebAddress()
-        {
-            var folder = TestData.Get(@"TestData\UsingIis");
-            var build = new Builder(folder, typeof(IisExtensionFactory), new[] { folder });
-
-            var results = build.BuildAndQuery(Build, "IIsWebAddress");
-            Assert.Equal(new[]
-            {
-                "IIsWebAddress:TestAddress\tTest\t\t[PORT]\t\t0",
-            }, results);
-        }
-
-        private static void Build(string[] args)
-        {
-            var result = WixRunner.Execute(args)
-                                  .AssertSuccess();
-        }
-    }
-}
diff --git a/src/test/WixToolsetTest.Iis/TestData/UsingIis/Package.en-us.wxl b/src/test/WixToolsetTest.Iis/TestData/UsingIis/Package.en-us.wxl
deleted file mode 100644
index 38c12ac1..00000000
--- a/src/test/WixToolsetTest.Iis/TestData/UsingIis/Package.en-us.wxl
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-This file contains the declaration of all the localizable strings.
--->
-<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US">
-
-  <String Id="DowngradeError">A newer version of [ProductName] is already installed.</String>
-  <String Id="FeatureTitle">MsiPackage</String>
-
-</WixLocalization>
diff --git a/src/test/WixToolsetTest.Iis/TestData/UsingIis/Package.wxs b/src/test/WixToolsetTest.Iis/TestData/UsingIis/Package.wxs
deleted file mode 100644
index f36aafef..00000000
--- a/src/test/WixToolsetTest.Iis/TestData/UsingIis/Package.wxs
+++ /dev/null
@@ -1,17 +0,0 @@
-<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
-  <Package Name="MsiPackage" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a" InstallerVersion="200">
-    <MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" />
-
-    <Feature Id="ProductFeature" Title="!(loc.FeatureTitle)">
-      <ComponentGroupRef Id="ProductComponents" />
-    </Feature>
-  </Package>
-
-  <Fragment>
-    <StandardDirectory Id="ProgramFilesFolder">
-      <Directory Id="INSTALLFOLDER" Name="MsiPackage">
-        <Directory Id="TestWebSiteProductDirectory" />
-      </Directory>
-    </StandardDirectory>
-  </Fragment>
-</Wix>
diff --git a/src/test/WixToolsetTest.Iis/TestData/UsingIis/PackageComponents.wxs b/src/test/WixToolsetTest.Iis/TestData/UsingIis/PackageComponents.wxs
deleted file mode 100644
index 03203b50..00000000
--- a/src/test/WixToolsetTest.Iis/TestData/UsingIis/PackageComponents.wxs
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
-     xmlns:iis="http://wixtoolset.org/schemas/v4/wxs/iis">
-  <Fragment>
-    <Property Id="PORT" Value="3062" />
-    <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
-       <Component>
-         <File Source="example.txt" />
-         <iis:WebSite Id="Test" Description="Test web server" Directory="TestWebSiteProductDirectory" AutoStart="yes" DirProperties="ReadAndExecute" ConfigureIfExists="no" >
-            <iis:WebAddress Id="TestAddress" Port="[PORT]" Secure="no" />
-         </iis:WebSite>
-       </Component>
-    </ComponentGroup>
-    <iis:WebDirProperties Id="ReadAndExecute" />
-  </Fragment>
-</Wix>
diff --git a/src/test/WixToolsetTest.Iis/TestData/UsingIis/example.txt b/src/test/WixToolsetTest.Iis/TestData/UsingIis/example.txt
deleted file mode 100644
index 1b4ffe8a..00000000
--- a/src/test/WixToolsetTest.Iis/TestData/UsingIis/example.txt
+++ /dev/null
@@ -1 +0,0 @@
-This is example.txt.
\ No newline at end of file
diff --git a/src/test/WixToolsetTest.Iis/WixToolsetTest.Iis.csproj b/src/test/WixToolsetTest.Iis/WixToolsetTest.Iis.csproj
deleted file mode 100644
index 49ed89bc..00000000
--- a/src/test/WixToolsetTest.Iis/WixToolsetTest.Iis.csproj
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<Project Sdk="Microsoft.NET.Sdk">
-  <PropertyGroup>
-    <TargetFramework>netcoreapp3.1</TargetFramework>
-    <IsPackable>false</IsPackable>
-  </PropertyGroup>
-
-  <PropertyGroup>
-    <NoWarn>NU1701</NoWarn>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <Content Include="TestData\UsingIis\example.txt" CopyToOutputDirectory="PreserveNewest" />
-    <Content Include="TestData\UsingIis\Package.en-us.wxl" CopyToOutputDirectory="PreserveNewest" />
-    <Content Include="TestData\UsingIis\Package.wxs" CopyToOutputDirectory="PreserveNewest" />
-    <Content Include="TestData\UsingIis\PackageComponents.wxs" CopyToOutputDirectory="PreserveNewest" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <ProjectReference Include="..\..\wixext\WixToolset.Iis.wixext.csproj" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <PackageReference Include="WixToolset.Core" Version="4.0.*" />
-    <PackageReference Include="WixToolset.Core.Burn" Version="4.0.*" />
-    <PackageReference Include="WixToolset.Core.WindowsInstaller" Version="4.0.*" />
-    <PackageReference Include="WixToolset.Core.TestPackage" Version="4.0.*" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <PackageReference Include="WixBuildTools.TestSupport" Version="4.0.*" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
-    <PackageReference Include="xunit" Version="2.4.1" />
-    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" PrivateAssets="All" />
-  </ItemGroup>
-</Project>
diff --git a/src/test/WixToolsetTest.Iis/WixToolsetTest.Iis.v3.ncrunchproject b/src/test/WixToolsetTest.Iis/WixToolsetTest.Iis.v3.ncrunchproject
deleted file mode 100644
index 7b5b2139..00000000
--- a/src/test/WixToolsetTest.Iis/WixToolsetTest.Iis.v3.ncrunchproject
+++ /dev/null
@@ -1,5 +0,0 @@
-<ProjectConfiguration>
-  <Settings>
-    <CopyReferencedAssembliesToWorkspace>True</CopyReferencedAssembliesToWorkspace>
-  </Settings>
-</ProjectConfiguration>
\ No newline at end of file
diff --git a/src/version.json b/src/version.json
new file mode 100644
index 00000000..5f857771
--- /dev/null
+++ b/src/version.json
@@ -0,0 +1,11 @@
+{
+  "version": "4.0",
+  "publicReleaseRefSpec": [
+    "^refs/heads/master$"
+  ],
+  "cloudBuild": {
+    "buildNumber": {
+      "enabled": true
+    }
+  }
+}
diff --git a/src/wix.snk b/src/wix.snk
deleted file mode 100644
index 3908a66a..00000000
Binary files a/src/wix.snk and /dev/null differ
diff --git a/src/wixext/IIsCompiler.cs b/src/wixext/IIsCompiler.cs
deleted file mode 100644
index cb573ad1..00000000
--- a/src/wixext/IIsCompiler.cs
+++ /dev/null
@@ -1,2620 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using System;
-    using System.Collections.Generic;
-    using System.Globalization;
-    using System.Xml.Linq;
-    using WixToolset.Data;
-    using WixToolset.Extensibility;
-    using WixToolset.Extensibility.Data;
-    using WixToolset.Iis.Symbols;
-
-    /// <summary>
-    /// The compiler for the WiX Toolset Internet Information Services Extension.
-    /// </summary>
-    public sealed class IIsCompiler : BaseCompilerExtension
-    {
-        public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/iis";
-
-        /// <summary>
-        /// Types of objects that custom HTTP Headers can be applied to.
-        /// </summary>
-        /// <remarks>Note that this must be kept in sync with the eHttpHeaderParentType in scahttpheader.h.</remarks>
-        private enum HttpHeaderParentType
-        {
-            /// <summary>Custom HTTP Header is to be applied to a Web Virtual Directory.</summary>
-            WebVirtualDir = 1,
-            /// <summary>Custom HTTP Header is to be applied to a Web Site.</summary>
-            WebSite = 2,
-        }
-
-        /// <summary>
-        /// Types of objects that MimeMaps can be applied to.
-        /// </summary>
-        /// <remarks>Note that this must be kept in sync with the eMimeMapParentType in scamimemap.h.</remarks>
-        private enum MimeMapParentType
-        {
-            /// <summary>MimeMap is to be applied to a Web Virtual Directory.</summary>
-            WebVirtualDir = 1,
-            WebSite = 2,
-        }
-
-        /// <summary>
-        /// Types of objects that custom WebErrors can be applied to.
-        /// </summary>
-        /// <remarks>Note that this must be kept in sync with the eWebErrorParentType in scaweberror.h.</remarks>
-        private enum WebErrorParentType
-        {
-            /// <summary>Custom WebError is to be applied to a Web Virtual Directory.</summary>
-            WebVirtualDir = 1,
-
-            /// <summary>Custom WebError is to be applied to a Web Site.</summary>
-            WebSite = 2,
-        }
-
-        /// <summary>
-        /// Processes an element for the Compiler.
-        /// </summary>
-        /// <param name="sourceLineNumbers">Source line number for the parent element.</param>
-        /// <param name="parentElement">Parent element of element to process.</param>
-        /// <param name="element">Element to process.</param>
-        /// <param name="contextValues">Extra information about the context in which this element is being parsed.</param>
-        public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary<string, string> context)
-        {
-            switch (parentElement.Name.LocalName)
-            {
-                case "Component":
-                    var componentId = context["ComponentId"];
-                    var directoryId = context["DirectoryId"];
-
-                    switch (element.Name.LocalName)
-                    {
-                        case "Certificate":
-                            this.ParseCertificateElement(intermediate, section, element, componentId);
-                            break;
-                        case "WebAppPool":
-                            this.ParseWebAppPoolElement(intermediate, section, element, componentId);
-                            break;
-                        case "WebDir":
-                            this.ParseWebDirElement(intermediate, section, element, componentId, null);
-                            break;
-                        case "WebFilter":
-                            this.ParseWebFilterElement(intermediate, section, element, componentId, null);
-                            break;
-                        case "WebProperty":
-                            this.ParseWebPropertyElement(intermediate, section, element, componentId);
-                            break;
-                        case "WebServiceExtension":
-                            this.ParseWebServiceExtensionElement(intermediate, section, element, componentId);
-                            break;
-                        case "WebSite":
-                            this.ParseWebSiteElement(intermediate, section, element, componentId);
-                            break;
-                        case "WebVirtualDir":
-                            this.ParseWebVirtualDirElement(intermediate, section, element, componentId, null, null);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedElement(parentElement, element);
-                            break;
-                    }
-                    break;
-                case "Fragment":
-                case "Module":
-                case "Package":
-                    switch (element.Name.LocalName)
-                    {
-                        case "WebApplication":
-                            this.ParseWebApplicationElement(intermediate, section, element);
-                            break;
-                        case "WebAppPool":
-                            this.ParseWebAppPoolElement(intermediate, section, element, null);
-                            break;
-                        case "WebDirProperties":
-                            this.ParseWebDirPropertiesElement(intermediate, section, element, null);
-                            break;
-                        case "WebLog":
-                            this.ParseWebLogElement(intermediate, section, element);
-                            break;
-                        case "WebSite":
-                            this.ParseWebSiteElement(intermediate, section, element, null);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedElement(parentElement, element);
-                            break;
-                    }
-                    break;
-                default:
-                    this.ParseHelper.UnexpectedElement(parentElement, element);
-                    break;
-            }
-        }
-
-        /// <summary>
-        /// Parses a certificate element.
-        /// </summary>
-        /// <param name="element">Element to parse.</param>
-        /// <param name="componentId">Identifier for parent component.</param>
-        private void ParseCertificateElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
-        {
-            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
-            Identifier id = null;
-            int attributes = 8; // SCA_CERT_ATTRIBUTE_VITAL
-            string binaryRef = null;
-            string certificatePath = null;
-            string name = null;
-            string pfxPassword = null;
-            int storeLocation = 0;
-            string storeName = null;
-
-            foreach (var attrib in element.Attributes())
-            {
-                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
-                {
-                    switch (attrib.Name.LocalName)
-                    {
-                        case "Id":
-                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
-                            break;
-                        case "BinaryRef":
-                            attributes |= 2; // SCA_CERT_ATTRIBUTE_BINARYDATA
-                            binaryRef = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
-                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Binary, binaryRef);
-                            break;
-                        case "CertificatePath":
-                            certificatePath = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "Name":
-                            name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "Overwrite":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                attributes |= 4; // SCA_CERT_ATTRIBUTE_OVERWRITE
-                            }
-                            else
-                            {
-                                attributes &= ~4; // SCA_CERT_ATTRIBUTE_OVERWRITE
-                            }
-                            break;
-                        case "PFXPassword":
-                            pfxPassword = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "Request":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                attributes |= 1; // SCA_CERT_ATTRIBUTE_REQUEST
-                            }
-                            else
-                            {
-                                attributes &= ~1; // SCA_CERT_ATTRIBUTE_REQUEST
-                            }
-                            break;
-                        case "StoreLocation":
-                            var storeLocationValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            if (0 < storeLocationValue.Length)
-                            {
-                                switch (storeLocationValue)
-                                {
-                                    case "currentUser":
-                                        storeLocation = 1; // SCA_CERTSYSTEMSTORE_CURRENTUSER
-                                        break;
-                                    case "localMachine":
-                                        storeLocation = 2; // SCA_CERTSYSTEMSTORE_LOCALMACHINE
-                                        break;
-                                    default:
-                                        storeLocation = -1;
-                                        this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "StoreLocation", storeLocationValue, "currentUser", "localMachine"));
-                                        break;
-                                }
-                            }
-                            break;
-                        case "StoreName":
-                            var storeNameValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            if (0 < storeNameValue.Length)
-                            {
-                                switch (storeNameValue)
-                                {
-                                    case "ca":
-                                        storeName = "CA";
-                                        break;
-                                    case "my":
-                                    case "personal":
-                                        storeName = "MY";
-                                        break;
-                                    case "request":
-                                        storeName = "REQUEST";
-                                        break;
-                                    case "root":
-                                        storeName = "Root";
-                                        break;
-                                    case "otherPeople":
-                                        storeName = "AddressBook";
-                                        break;
-                                    case "trustedPeople":
-                                        storeName = "TrustedPeople";
-                                        break;
-                                    case "trustedPublisher":
-                                        storeName = "TrustedPublisher";
-                                        break;
-                                    default:
-                                        this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "StoreName", storeNameValue, "ca", "my", "request", "root", "otherPeople", "trustedPeople", "trustedPublisher"));
-                                        break;
-                                }
-                            }
-                            break;
-                        case "Vital":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                attributes |= 8; // SCA_CERT_ATTRIBUTE_VITAL
-                            }
-                            else
-                            {
-                                attributes &= ~8; // SCA_CERT_ATTRIBUTE_VITAL
-                            }
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedAttribute(element, attrib);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
-                }
-            }
-
-
-            if (null == id)
-            {
-                id = this.ParseHelper.CreateIdentifier("crt", componentId, binaryRef, certificatePath);
-            }
-
-            if (null == name)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
-            }
-
-            if (0 == storeLocation)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "StoreLocation"));
-            }
-
-            if (null == storeName)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "StoreName"));
-            }
-
-            if (null != binaryRef && null != certificatePath)
-            {
-                this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "BinaryRef", "CertificatePath", certificatePath));
-            }
-            else if (null == binaryRef && null == certificatePath)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, element.Name.LocalName, "BinaryRef", "CertificatePath"));
-            }
-
-            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
-
-            // Reference InstallCertificates and UninstallCertificates since nothing will happen without them
-            this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4InstallCertificates", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
-            this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4UninstallCertificates", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
-            this.ParseHelper.EnsureTable(section, sourceLineNumbers, IisTableDefinitions.CertificateHash); // Certificate CustomActions require the CertificateHash table
-
-            if (!this.Messaging.EncounteredError)
-            {
-                section.AddSymbol(new CertificateSymbol(sourceLineNumbers, id)
-                {
-                    ComponentRef = componentId,
-                    Name = name,
-                    StoreLocation = storeLocation,
-                    StoreName = storeName,
-                    Attributes = attributes,
-                    BinaryRef = binaryRef,
-                    CertificatePath = certificatePath,
-                    PFXPassword = pfxPassword,
-                });
-            }
-        }
-
-        /// <summary>
-        /// Parses a CertificateRef extension element.
-        /// </summary>
-        /// <param name="element">Element to parse.</param>
-        /// <param name="webId">Identifier for parent web site.</param>
-        private void ParseCertificateRefElement(Intermediate intermediate, IntermediateSection section, XElement element, string webId)
-        {
-            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
-            Identifier id = null;
-
-            foreach (var attrib in element.Attributes())
-            {
-                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
-                {
-                    switch (attrib.Name.LocalName)
-                    {
-                        case "Id":
-                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
-                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.Certificate, id.Id);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedAttribute(element, attrib);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
-                }
-            }
-
-            if (null == id)
-            {
-                id = this.ParseHelper.CreateIdentifier("wsc", webId);
-            }
-
-            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
-
-            if (!this.Messaging.EncounteredError)
-            {
-                this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.Certificate, id.Id);
-
-                section.AddSymbol(new IIsWebSiteCertificatesSymbol(sourceLineNumbers)
-                {
-                    WebRef = webId,
-                    CertificateRef = id.Id,
-                });
-            }
-        }
-
-        /// <summary>
-        /// Parses a mime map element.
-        /// </summary>
-        /// <param name="element">Element to parse.</param>
-        /// <param name="parentId">Identifier for parent symbol.</param>
-        /// <param name="parentType">Type that parentId refers to.</param>
-        private void ParseMimeMapElement(Intermediate intermediate, IntermediateSection section, XElement element, string parentId, MimeMapParentType parentType)
-        {
-            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
-            Identifier id = null;
-            string extension = null;
-            string type = null;
-
-            foreach (var attrib in element.Attributes())
-            {
-                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
-                {
-                    switch (attrib.Name.LocalName)
-                    {
-                        case "Id":
-                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
-                            break;
-                        case "Extension":
-                            extension = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "Type":
-                            type = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedAttribute(element, attrib);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
-                }
-            }
-
-            if (null == id)
-            {
-                id = this.ParseHelper.CreateIdentifier("imm", parentId, type, extension);
-            }
-
-            if (null == extension)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Extension"));
-            }
-            else if (0 < extension.Length)
-            {
-                if (!extension.StartsWith(".", StringComparison.Ordinal))
-                {
-                    this.Messaging.Write(IIsErrors.MimeMapExtensionMissingPeriod(sourceLineNumbers, element.Name.LocalName, "Extension", extension));
-                }
-            }
-
-            if (null == type)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Type"));
-            }
-
-            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
-
-            if (!this.Messaging.EncounteredError)
-            {
-                section.AddSymbol(new IIsMimeMapSymbol(sourceLineNumbers, id)
-                {
-                    ParentType = (int)parentType,
-                    ParentValue = parentId,
-                    MimeType = type,
-                    Extension = extension,
-                });
-            }
-        }
-
-        /// <summary>
-        /// Parses a recycle time element.
-        /// </summary>
-        /// <param name="element">Element to parse.</param>
-        /// <returns>Recycle time value.</returns>
-        private string ParseRecycleTimeElement(Intermediate intermediate, IntermediateSection section, XElement element)
-        {
-            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
-            string value = null;
-
-            foreach (var attrib in element.Attributes())
-            {
-                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
-                {
-                    switch (attrib.Name.LocalName)
-                    {
-                        case "Value":
-                            value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedAttribute(element, attrib);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
-                }
-            }
-
-            if (null == value)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Value"));
-            }
-
-            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
-
-            return value;
-        }
-
-        /// <summary>
-        /// Parses a web address element.
-        /// </summary>
-        /// <param name="element">Element to parse.</param>
-        /// <param name="parentWeb">Identifier of parent web site.</param>
-        /// <returns>Identifier for web address.</returns>
-        private string ParseWebAddressElement(Intermediate intermediate, IntermediateSection section, XElement element, string parentWeb)
-        {
-            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
-            Identifier id = null;
-            string header = null;
-            string ip = null;
-            string port = null;
-            var secure = false;
-
-            foreach (var attrib in element.Attributes())
-            {
-                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
-                {
-                    switch (attrib.Name.LocalName)
-                    {
-                        case "Id":
-                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
-                            break;
-                        case "Header":
-                            header = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "IP":
-                            ip = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "Port":
-                            port = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "Secure":
-                            secure = YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedAttribute(element, attrib);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
-                }
-            }
-
-            if (null == id)
-            {
-                id = this.ParseHelper.CreateIdentifier("iwa", parentWeb, ip, port);
-            }
-
-            if (null == port)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Port"));
-            }
-
-            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
-
-            if (!this.Messaging.EncounteredError)
-            {
-                section.AddSymbol(new IIsWebAddressSymbol(sourceLineNumbers, id)
-                {
-                    WebRef = parentWeb,
-                    IP = ip,
-                    Port = port,
-                    Header = header,
-                    Secure = secure ? 1 : 0,
-                });
-            }
-
-            return id?.Id;
-        }
-
-        /// <summary>
-        /// Parses a web application element.
-        /// </summary>
-        /// <param name="element">Element to parse.</param>
-        /// <returns>Identifier for web application.</returns>
-        private string ParseWebApplicationElement(Intermediate intermediate, IntermediateSection section, XElement element)
-        {
-            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
-            Identifier id = null;
-            var allowSessions = YesNoDefaultType.Default;
-            string appPool = null;
-            var buffer = YesNoDefaultType.Default;
-            var clientDebugging = YesNoDefaultType.Default;
-            string defaultScript = null;
-            int isolation = 0;
-            string name = null;
-            var parentPaths = YesNoDefaultType.Default;
-            var scriptTimeout = CompilerConstants.IntegerNotSet;
-            var sessionTimeout = CompilerConstants.IntegerNotSet;
-            var serverDebugging = YesNoDefaultType.Default;
-
-            foreach (var attrib in element.Attributes())
-            {
-                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
-                {
-                    switch (attrib.Name.LocalName)
-                    {
-                        case "Id":
-                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
-                            break;
-                        case "AllowSessions":
-                            allowSessions = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
-                            break;
-                        case "Buffer":
-                            buffer = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
-                            break;
-                        case "ClientDebugging":
-                            clientDebugging = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
-                            break;
-                        case "DefaultScript":
-                            defaultScript = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            if (0 < defaultScript.Length)
-                            {
-                                switch (defaultScript)
-                                {
-                                    case "JScript":
-                                    case "VBScript":
-                                        // these are valid values
-                                        break;
-                                    default:
-                                        this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, defaultScript, "JScript", "VBScript"));
-                                        break;
-                                }
-                            }
-                            break;
-                        case "Isolation":
-                            string isolationValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            if (0 < isolationValue.Length)
-                            {
-                                switch (isolationValue)
-                                {
-                                    case "low":
-                                        isolation = 0;
-                                        break;
-                                    case "medium":
-                                        isolation = 2;
-                                        break;
-                                    case "high":
-                                        isolation = 1;
-                                        break;
-                                    default:
-                                        this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, isolationValue, "low", "medium", "high"));
-                                        break;
-                                }
-                            }
-                            break;
-                        case "Name":
-                            name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "ParentPaths":
-                            parentPaths = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
-                            break;
-                        case "ScriptTimeout":
-                            scriptTimeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
-                            break;
-                        case "ServerDebugging":
-                            serverDebugging = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
-                            break;
-                        case "SessionTimeout":
-                            sessionTimeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
-                            break;
-                        case "WebAppPool":
-                            appPool = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
-                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsAppPool, appPool);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedAttribute(element, attrib);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
-                }
-            }
-
-            if (null == id)
-            {
-                id = this.ParseHelper.CreateIdentifier("wap", name, appPool);
-            }
-
-            if (null == name)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
-            }
-            else if (-1 != name.IndexOf("\\", StringComparison.Ordinal))
-            {
-                this.Messaging.Write(IIsErrors.IllegalCharacterInAttributeValue(sourceLineNumbers, element.Name.LocalName, "Name", name, '\\'));
-            }
-
-            foreach (var child in element.Elements())
-            {
-                if (this.Namespace == child.Name.Namespace)
-                {
-                    switch (child.Name.LocalName)
-                    {
-                        case "WebApplicationExtension":
-                            this.ParseWebApplicationExtensionElement(intermediate, section, child, id?.Id);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedElement(element, child);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
-                }
-            }
-
-            if (!this.Messaging.EncounteredError)
-            {
-                var symbol = section.AddSymbol(new IIsWebApplicationSymbol(sourceLineNumbers, id)
-                {
-                    Name = name,
-                    Isolation = isolation,
-                    DefaultScript = defaultScript,
-                    AppPoolRef = appPool,
-                });
-
-                if (YesNoDefaultType.Default != allowSessions)
-                {
-                    symbol.AllowSessions = YesNoDefaultType.Yes == allowSessions ? 1 : 0;
-                }
-
-                if (CompilerConstants.IntegerNotSet != sessionTimeout)
-                {
-                    symbol.SessionTimeout = sessionTimeout;
-                }
-
-                if (YesNoDefaultType.Default != buffer)
-                {
-                    symbol.Buffer = YesNoDefaultType.Yes == buffer ? 1 : 0;
-                }
-
-                if (YesNoDefaultType.Default != parentPaths)
-                {
-                    symbol.ParentPaths = YesNoDefaultType.Yes == parentPaths ? 1 : 0;
-                }
-
-                if (CompilerConstants.IntegerNotSet != scriptTimeout)
-                {
-                    symbol.ScriptTimeout = scriptTimeout;
-                }
-
-                if (YesNoDefaultType.Default != serverDebugging)
-                {
-                    symbol.ServerDebugging = YesNoDefaultType.Yes == serverDebugging ? 1 : 0;
-                }
-
-                if (YesNoDefaultType.Default != clientDebugging)
-                {
-                    symbol.ClientDebugging = YesNoDefaultType.Yes == clientDebugging ? 1 : 0;
-                }
-            }
-
-            return id?.Id;
-        }
-
-        /// <summary>
-        /// Parses a web application extension element.
-        /// </summary>
-        /// <param name="element">Element to parse.</param>
-        /// <param name="application">Identifier for parent web application.</param>
-        private void ParseWebApplicationExtensionElement(Intermediate intermediate, IntermediateSection section, XElement element, string application)
-        {
-            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
-            int attributes = 0;
-            string executable = null;
-            string extension = null;
-            string verbs = null;
-
-            foreach (var attrib in element.Attributes())
-            {
-                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
-                {
-                    switch (attrib.Name.LocalName)
-                    {
-                        case "CheckPath":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                attributes |= 4;
-                            }
-                            else
-                            {
-                                attributes &= ~4;
-                            }
-                            break;
-                        case "Executable":
-                            executable = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "Extension":
-                            extension = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "Script":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                attributes |= 1;
-                            }
-                            else
-                            {
-                                attributes &= ~1;
-                            }
-                            break;
-                        case "Verbs":
-                            verbs = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedAttribute(element, attrib);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
-                }
-            }
-
-            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
-
-            if (!this.Messaging.EncounteredError)
-            {
-                var symbol = section.AddSymbol(new IIsWebApplicationExtensionSymbol(sourceLineNumbers)
-                {
-                    ApplicationRef = application,
-                    Extension = extension,
-                    Verbs = verbs,
-                    Executable = executable,
-                });
-
-                if (0 < attributes)
-                {
-                    symbol.Attributes = attributes;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Parses web application pool element.
-        /// </summary>
-        /// <param name="element">Element to parse.</param>
-        /// <param name="componentId">Optional identifier of parent component.</param>
-        private void ParseWebAppPoolElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
-        {
-            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
-            Identifier id = null;
-            int attributes = 0;
-            var cpuAction = CompilerConstants.IntegerNotSet;
-            string cpuMon = null;
-            var idleTimeout = CompilerConstants.IntegerNotSet;
-            int maxCpuUsage = 0;
-            var maxWorkerProcs = CompilerConstants.IntegerNotSet;
-            string managedRuntimeVersion = null;
-            string managedPipelineMode = null;
-            string name = null;
-            var privateMemory = CompilerConstants.IntegerNotSet;
-            var queueLimit = CompilerConstants.IntegerNotSet;
-            var recycleMinutes = CompilerConstants.IntegerNotSet;
-            var recycleRequests = CompilerConstants.IntegerNotSet;
-            string recycleTimes = null;
-            var refreshCpu = CompilerConstants.IntegerNotSet;
-            string user = null;
-            var virtualMemory = CompilerConstants.IntegerNotSet;
-
-            foreach (var attrib in element.Attributes())
-            {
-                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
-                {
-                    switch (attrib.Name.LocalName)
-                    {
-                        case "Id":
-                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
-                            break;
-                        case "CpuAction":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            var cpuActionValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            if (0 < cpuActionValue.Length)
-                            {
-                                switch (cpuActionValue)
-                                {
-                                    case "shutdown":
-                                        cpuAction = 1;
-                                        break;
-                                    case "none":
-                                        cpuAction = 0;
-                                        break;
-                                    default:
-                                        this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, cpuActionValue, "shutdown", "none"));
-                                        break;
-                                }
-                            }
-                            break;
-                        case "Identity":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            var identityValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            if (0 < identityValue.Length)
-                            {
-                                switch (identityValue)
-                                {
-                                    case "networkService":
-                                        attributes |= 1;
-                                        break;
-                                    case "localService":
-                                        attributes |= 2;
-                                        break;
-                                    case "localSystem":
-                                        attributes |= 4;
-                                        break;
-                                    case "other":
-                                        attributes |= 8;
-                                        break;
-                                    case "applicationPoolIdentity":
-                                        attributes |= 0x10;
-                                        break;
-                                    default:
-                                        this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, identityValue, "networkService", "localService", "localSystem", "other", "applicationPoolIdentity"));
-                                        break;
-                                }
-                            }
-                            break;
-                        case "IdleTimeout":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            idleTimeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
-                            break;
-                        case "ManagedPipelineMode":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            managedPipelineMode = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-
-
-                            if (!String.IsNullOrEmpty(managedPipelineMode))
-                            {
-                                switch (managedPipelineMode)
-                                {
-                                    // In 3.5 we allowed lower case values (per camel case enum style), we now use formatted fields,
-                                    // so the value needs to match exactly what we pass in to IIS which uses pascal case.
-                                    case "classic":
-                                        managedPipelineMode = "Classic";
-                                        break;
-                                    case "integrated":
-                                        managedPipelineMode = "Integrated";
-                                        break;
-                                    case "Classic":
-                                        break;
-                                    case "Integrated":
-                                        break;
-                                    default:
-                                        if (!this.ParseHelper.ContainsProperty(managedPipelineMode))
-                                        {
-                                            this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, managedPipelineMode, "Classic", "Integrated"));
-                                        }
-                                        break;
-                                }
-                            }
-
-                            break;
-                        case "ManagedRuntimeVersion":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            managedRuntimeVersion = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "MaxCpuUsage":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            maxCpuUsage = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 100);
-                            break;
-                        case "MaxWorkerProcesses":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            maxWorkerProcs = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
-                            break;
-                        case "Name":
-                            name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "PrivateMemory":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            privateMemory = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 4294967);
-                            break;
-                        case "QueueLimit":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            queueLimit = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
-                            break;
-                        case "RecycleMinutes":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            recycleMinutes = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
-                            break;
-                        case "RecycleRequests":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            recycleRequests = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
-                            break;
-                        case "RefreshCpu":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            refreshCpu = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue);
-                            break;
-                        case "User":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            user = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
-                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "User", user);
-                            break;
-                        case "VirtualMemory":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            virtualMemory = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 4294967);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedAttribute(element, attrib);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
-                }
-            }
-
-            if (null == id)
-            {
-                id = this.ParseHelper.CreateIdentifier("iap", name, componentId, user);
-            }
-
-            if (null == name)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
-            }
-
-            if (null == user && 8 == (attributes & 0x1F))
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "User", "Identity", "other"));
-            }
-
-            if (null != user && 8 != (attributes & 0x1F))
-            {
-                this.Messaging.Write(ErrorMessages.IllegalAttributeValueWithoutOtherAttribute(sourceLineNumbers, element.Name.LocalName, "User", user, "Identity", "other"));
-            }
-
-            cpuMon = maxCpuUsage.ToString(CultureInfo.InvariantCulture.NumberFormat);
-            if (CompilerConstants.IntegerNotSet != refreshCpu)
-            {
-                cpuMon = String.Concat(cpuMon, ",", refreshCpu.ToString(CultureInfo.InvariantCulture.NumberFormat));
-                if (CompilerConstants.IntegerNotSet != cpuAction)
-                {
-                    cpuMon = String.Concat(cpuMon, ",", cpuAction.ToString(CultureInfo.InvariantCulture.NumberFormat));
-                }
-            }
-
-            foreach (var child in element.Elements())
-            {
-                if (this.Namespace == child.Name.Namespace)
-                {
-                    switch (child.Name.LocalName)
-                    {
-                        case "RecycleTime":
-                            if (null == componentId)
-                            {
-                                var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child);
-                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, element.Name.LocalName));
-                            }
-
-                            if (null == recycleTimes)
-                            {
-                                recycleTimes = this.ParseRecycleTimeElement(intermediate, section, child);
-                            }
-                            else
-                            {
-                                recycleTimes = String.Concat(recycleTimes, ",", this.ParseRecycleTimeElement(intermediate, section, child));
-                            }
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedElement(element, child);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
-                }
-            }
-
-            if (null != componentId)
-            {
-                // Reference ConfigureIIs since nothing will happen without it
-                this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
-            }
-
-            if (!this.Messaging.EncounteredError)
-            {
-                var symbol = section.AddSymbol(new IIsAppPoolSymbol(sourceLineNumbers, id)
-                {
-                    Name = name,
-                    ComponentRef = componentId,
-                    Attributes = attributes,
-                    UserRef = user,
-                    RecycleTimes = recycleTimes,
-                    CPUMon = cpuMon,
-                    ManagedRuntimeVersion = managedRuntimeVersion,
-                    ManagedPipelineMode = managedPipelineMode,
-                });
-
-                if (CompilerConstants.IntegerNotSet != recycleMinutes)
-                {
-                    symbol.RecycleMinutes = recycleMinutes;
-                }
-
-                if (CompilerConstants.IntegerNotSet != recycleRequests)
-                {
-                    symbol.RecycleRequests = recycleRequests;
-                }
-
-                if (CompilerConstants.IntegerNotSet != idleTimeout)
-                {
-                    symbol.IdleTimeout = idleTimeout;
-                }
-
-                if (CompilerConstants.IntegerNotSet != queueLimit)
-                {
-                    symbol.QueueLimit = queueLimit;
-                }
-
-                if (CompilerConstants.IntegerNotSet != maxWorkerProcs)
-                {
-                    symbol.MaxProc = maxWorkerProcs;
-                }
-
-                if (CompilerConstants.IntegerNotSet != virtualMemory)
-                {
-                    symbol.VirtualMemory = virtualMemory;
-                }
-
-                if (CompilerConstants.IntegerNotSet != privateMemory)
-                {
-                    symbol.PrivateMemory = privateMemory;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Parses a web directory element.
-        /// </summary>
-        /// <param name="element">Element to parse.</param>
-        /// <param name="componentId">Identifier for parent component.</param>
-        /// <param name="parentWeb">Optional identifier for parent web site.</param>
-        private void ParseWebDirElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string parentWeb)
-        {
-            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
-            Identifier id = null;
-            string dirProperties = null;
-            string path = null;
-            string application = null;
-
-            foreach (var attrib in element.Attributes())
-            {
-                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
-                {
-                    switch (attrib.Name.LocalName)
-                    {
-                        case "Id":
-                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
-                            break;
-                        case "DirProperties":
-                            dirProperties = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
-                            break;
-                        case "Path":
-                            path = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "WebApplication":
-                            application = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "WebSite":
-                            if (null != parentWeb)
-                            {
-                                this.Messaging.Write(IIsErrors.WebSiteAttributeUnderWebSite(sourceLineNumbers, element.Name.LocalName));
-                            }
-
-                            parentWeb = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
-                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebSite, parentWeb);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedAttribute(element, attrib);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
-                }
-            }
-
-            if (null == id)
-            {
-                id = this.ParseHelper.CreateIdentifier("iwd", componentId, parentWeb, dirProperties, application);
-            }
-
-            if (null == path)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Path"));
-            }
-
-            if (null == parentWeb)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "WebSite"));
-            }
-
-            foreach (var child in element.Elements())
-            {
-                if (this.Namespace == child.Name.Namespace)
-                {
-                    var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child);
-                    switch (child.Name.LocalName)
-                    {
-                        case "WebApplication":
-                            if (null != application)
-                            {
-                                this.Messaging.Write(IIsErrors.WebApplicationAlreadySpecified(childSourceLineNumbers, element.Name.LocalName));
-                            }
-
-                            application = this.ParseWebApplicationElement(intermediate, section, child);
-                            break;
-                        case "WebDirProperties":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
-                            }
-
-                            string childWebDirProperties = this.ParseWebDirPropertiesElement(intermediate, section, child, componentId);
-                            if (null == dirProperties)
-                            {
-                                dirProperties = childWebDirProperties;
-                            }
-                            else
-                            {
-                                this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, child.Name.LocalName, "DirProperties", child.Name.LocalName));
-                            }
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedElement(element, child);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
-                }
-            }
-
-            if (null == dirProperties)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "DirProperties"));
-            }
-
-            if (null != application)
-            {
-                this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebApplication, application);
-            }
-
-            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebDirProperties, dirProperties);
-
-            // Reference ConfigureIIs since nothing will happen without it
-            this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
-
-            if (!this.Messaging.EncounteredError)
-            {
-                section.AddSymbol(new IIsWebDirSymbol(sourceLineNumbers, id)
-                {
-                    ComponentRef = componentId,
-                    WebRef = parentWeb,
-                    Path = path,
-                    DirPropertiesRef = dirProperties,
-                    ApplicationRef = application,
-                });
-            }
-        }
-
-        /// <summary>
-        /// Parses a web directory properties element.
-        /// </summary>
-        /// <param name="element">Element to parse.</param>
-        /// <returns>The identifier for this WebDirProperties.</returns>
-        private string ParseWebDirPropertiesElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
-        {
-            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
-            Identifier id = null;
-            int access = 0;
-            var accessSet = false;
-            int accessSSLFlags = 0;
-            var accessSSLFlagsSet = false;
-            string anonymousUser = null;
-            var aspDetailedError = YesNoType.NotSet;
-            string authenticationProviders = null;
-            int authorization = 0;
-            var authorizationSet = false;
-            string cacheControlCustom = null;
-            var cacheControlMaxAge = CompilerConstants.LongNotSet;
-            string defaultDocuments = null;
-            string httpExpires = null;
-            var iisControlledPassword = false;
-            var index = YesNoType.NotSet;
-            var logVisits = YesNoType.NotSet;
-            var notCustomError = YesNoType.NotSet;
-
-            foreach (var attrib in element.Attributes())
-            {
-                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
-                {
-                    switch (attrib.Name.LocalName)
-                    {
-                        case "Id":
-                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
-                            break;
-                        case "AnonymousUser":
-                            anonymousUser = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
-                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "User", anonymousUser);
-                            break;
-                        case "AspDetailedError":
-                            aspDetailedError = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
-                            break;
-                        case "AuthenticationProviders":
-                            authenticationProviders = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "CacheControlCustom":
-                            cacheControlCustom = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "CacheControlMaxAge":
-                            cacheControlMaxAge = this.ParseHelper.GetAttributeLongValue(sourceLineNumbers, attrib, 0, uint.MaxValue); // 4294967295 (uint.MaxValue) represents unlimited
-                            break;
-                        case "ClearCustomError":
-                            notCustomError = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
-                            break;
-                        case "DefaultDocuments":
-                            defaultDocuments = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "HttpExpires":
-                            httpExpires = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "IIsControlledPassword":
-                            iisControlledPassword = YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
-                            break;
-                        case "Index":
-                            index = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
-                            break;
-                        case "LogVisits":
-                            logVisits = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
-                            break;
-
-                        // Access attributes
-                        case "Execute":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                access |= 4;
-                            }
-                            else
-                            {
-                                access &= ~4;
-                            }
-                            accessSet = true;
-                            break;
-                        case "Read":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                access |= 1;
-                            }
-                            else
-                            {
-                                access &= ~1;
-                            }
-                            accessSet = true;
-                            break;
-                        case "Script":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                access |= 512;
-                            }
-                            else
-                            {
-                                access &= ~512;
-                            }
-                            accessSet = true;
-                            break;
-                        case "Write":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                access |= 2;
-                            }
-                            else
-                            {
-                                access &= ~2;
-                            }
-                            accessSet = true;
-                            break;
-
-                        // AccessSSL Attributes
-                        case "AccessSSL":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                accessSSLFlags |= 8;
-                            }
-                            else
-                            {
-                                accessSSLFlags &= ~8;
-                            }
-                            accessSSLFlagsSet = true;
-                            break;
-                        case "AccessSSL128":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                accessSSLFlags |= 256;
-                            }
-                            else
-                            {
-                                accessSSLFlags &= ~256;
-                            }
-                            accessSSLFlagsSet = true;
-                            break;
-                        case "AccessSSLMapCert":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                accessSSLFlags |= 128;
-                            }
-                            else
-                            {
-                                accessSSLFlags &= ~128;
-                            }
-                            accessSSLFlagsSet = true;
-                            break;
-                        case "AccessSSLNegotiateCert":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                accessSSLFlags |= 32;
-                            }
-                            else
-                            {
-                                accessSSLFlags &= ~32;
-                            }
-                            accessSSLFlagsSet = true;
-                            break;
-                        case "AccessSSLRequireCert":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                accessSSLFlags |= 64;
-                            }
-                            else
-                            {
-                                accessSSLFlags &= ~64;
-                            }
-                            accessSSLFlagsSet = true;
-                            break;
-
-                        // Authorization attributes
-                        case "AnonymousAccess":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                authorization |= 1;
-                            }
-                            else
-                            {
-                                authorization &= ~1;
-                            }
-                            authorizationSet = true;
-                            break;
-                        case "BasicAuthentication":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                authorization |= 2;
-                            }
-                            else
-                            {
-                                authorization &= ~2;
-                            }
-                            authorizationSet = true;
-                            break;
-                        case "DigestAuthentication":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                authorization |= 16;
-                            }
-                            else
-                            {
-                                authorization &= ~16;
-                            }
-                            authorizationSet = true;
-                            break;
-                        case "PassportAuthentication":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                authorization |= 64;
-                            }
-                            else
-                            {
-                                authorization &= ~64;
-                            }
-                            authorizationSet = true;
-                            break;
-                        case "WindowsAuthentication":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                authorization |= 4;
-                            }
-                            else
-                            {
-                                authorization &= ~4;
-                            }
-                            authorizationSet = true;
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedAttribute(element, attrib);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
-                }
-            }
-
-            if (null == id)
-            {
-                if (null == componentId)
-                {
-                    this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Id"));
-                    id = Identifier.Invalid;
-                }
-                else
-                {
-                    id = this.ParseHelper.CreateIdentifier("wdp", componentId);
-                }
-            }
-
-            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
-
-            if (!this.Messaging.EncounteredError)
-            {
-                var symbol = section.AddSymbol(new IIsWebDirPropertiesSymbol(sourceLineNumbers, id)
-                {
-                    AnonymousUserRef = anonymousUser,
-                    IIsControlledPassword = iisControlledPassword ? 1 : 0,
-                    DefaultDoc = defaultDocuments,
-                    HttpExpires = httpExpires,
-                    CacheControlCustom = cacheControlCustom,
-                });
-
-                if (accessSet)
-                {
-                    symbol.Access = access;
-                }
-
-                if (authorizationSet)
-                {
-                    symbol.Authorization = authorization;
-                }
-
-                if (YesNoType.NotSet != logVisits)
-                {
-                    symbol.LogVisits = YesNoType.Yes == logVisits ? 1 : 0;
-                }
-
-                if (YesNoType.NotSet != index)
-                {
-                    symbol.Index = YesNoType.Yes == index ? 1 : 0;
-                }
-
-                if (YesNoType.NotSet != aspDetailedError)
-                {
-                    symbol.AspDetailedError = YesNoType.Yes == aspDetailedError ? 1 : 0;
-                }
-
-                if (CompilerConstants.LongNotSet != cacheControlMaxAge)
-                {
-                    symbol.CacheControlMaxAge = unchecked((int)cacheControlMaxAge);
-                }
-
-                if (YesNoType.NotSet != notCustomError)
-                {
-                    symbol.NoCustomError = YesNoType.Yes == notCustomError ? 1 : 0;
-                }
-
-                if (accessSSLFlagsSet)
-                {
-                    symbol.AccessSSLFlags = accessSSLFlags;
-                }
-
-                if (null != authenticationProviders)
-                {
-                    symbol.AuthenticationProviders = authenticationProviders;
-                }
-            }
-
-            return id?.Id;
-        }
-
-        /// <summary>
-        /// Parses a web error element.
-        /// </summary>
-        /// <param name="element">Element to parse.</param>
-        /// <param name="parentType">Type of the parent.</param>
-        /// <param name="parent">Id of the parent.</param>
-        private void ParseWebErrorElement(Intermediate intermediate, IntermediateSection section, XElement element, WebErrorParentType parentType, string parent)
-        {
-            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
-            var errorCode = CompilerConstants.IntegerNotSet;
-            string file = null;
-            string url = null;
-            var subCode = CompilerConstants.IntegerNotSet;
-
-            foreach (var attrib in element.Attributes())
-            {
-                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
-                {
-                    switch (attrib.Name.LocalName)
-                    {
-                        case "ErrorCode":
-                            errorCode = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 400, 599);
-                            break;
-                        case "File":
-                            file = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "SubCode":
-                            subCode = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue);
-                            break;
-                        case "URL":
-                            url = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedAttribute(element, attrib);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
-                }
-            }
-
-            if (CompilerConstants.IntegerNotSet == errorCode)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "ErrorCode"));
-                errorCode = CompilerConstants.IllegalInteger;
-            }
-
-            if (CompilerConstants.IntegerNotSet == subCode)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "SubCode"));
-                subCode = CompilerConstants.IllegalInteger;
-            }
-
-            if (String.IsNullOrEmpty(file) && String.IsNullOrEmpty(url))
-            {
-                this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "File", "URL"));
-            }
-
-            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
-
-            // Reference ConfigureIIs since nothing will happen without it
-            this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
-
-            if (!this.Messaging.EncounteredError)
-            {
-                section.AddSymbol(new IIsWebErrorSymbol(sourceLineNumbers)
-                {
-                    ErrorCode = errorCode,
-                    SubCode = subCode,
-                    ParentType = (int)parentType,
-                    ParentValue = parent,
-                    File = file,
-                    URL = url,
-                });
-            }
-        }
-
-        /// <summary>
-        /// Parses a web filter element.
-        /// </summary>
-        /// <param name="element">Element to parse.</param>
-        /// <param name="componentId">Identifier of parent component.</param>
-        /// <param name="parentWeb">Optional identifier of parent web site.</param>
-        private void ParseWebFilterElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string parentWeb)
-        {
-            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
-            Identifier id = null;
-            string description = null;
-            int flags = 0;
-            var loadOrder = CompilerConstants.IntegerNotSet;
-            string name = null;
-            string path = null;
-
-            foreach (var attrib in element.Attributes())
-            {
-                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
-                {
-                    switch (attrib.Name.LocalName)
-                    {
-                        case "Id":
-                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
-                            break;
-                        case "Description":
-                            description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "Flags":
-                            flags = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue);
-                            break;
-                        case "LoadOrder":
-                            string loadOrderValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            if (0 < loadOrderValue.Length)
-                            {
-                                switch (loadOrderValue)
-                                {
-                                    case "first":
-                                        loadOrder = 0;
-                                        break;
-                                    case "last":
-                                        loadOrder = -1;
-                                        break;
-                                    default:
-                                        loadOrder = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, short.MaxValue);
-                                        break;
-                                }
-                            }
-                            break;
-                        case "Name":
-                            name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "Path":
-                            path = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "WebSite":
-                            if (null != parentWeb)
-                            {
-                                this.Messaging.Write(IIsErrors.WebSiteAttributeUnderWebSite(sourceLineNumbers, element.Name.LocalName));
-                            }
-
-                            parentWeb = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
-                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebSite, parentWeb);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedAttribute(element, attrib);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
-                }
-            }
-
-            if (null == id)
-            {
-                id = this.ParseHelper.CreateIdentifier("ifl", name, componentId, path, parentWeb);
-            }
-
-            if (null == name)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
-            }
-
-            if (null == path)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Path"));
-            }
-
-            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
-
-            // Reference ConfigureIIs since nothing will happen without it
-            this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
-
-            if (!this.Messaging.EncounteredError)
-            {
-                var symbol = section.AddSymbol(new IIsFilterSymbol(sourceLineNumbers, id)
-                {
-                    Name = name,
-                    ComponentRef = componentId,
-                    Path = path,
-                    WebRef = parentWeb,
-                    Description = description,
-                    Flags = flags,
-                });
-
-                if (CompilerConstants.IntegerNotSet != loadOrder)
-                {
-                    symbol.LoadOrder = loadOrder;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Parses web log element.
-        /// </summary>
-        /// <param name="element">Node to be parsed.</param>
-        private void ParseWebLogElement(Intermediate intermediate, IntermediateSection section, XElement element)
-        {
-            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
-            Identifier id = null;
-            string type = null;
-
-            foreach (var attrib in element.Attributes())
-            {
-                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
-                {
-                    switch (attrib.Name.LocalName)
-                    {
-                        case "Id":
-                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
-                            break;
-                        case "Type":
-                            var typeValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            if (0 < typeValue.Length)
-                            {
-                                switch (typeValue)
-                                {
-                                    case "IIS":
-                                        type = "Microsoft IIS Log File Format";
-                                        break;
-                                    case "NCSA":
-                                        type = "NCSA Common Log File Format";
-                                        break;
-                                    case "none":
-                                        type = "none";
-                                        break;
-                                    case "ODBC":
-                                        type = "ODBC Logging";
-                                        break;
-                                    case "W3C":
-                                        type = "W3C Extended Log File Format";
-                                        break;
-                                    default:
-                                        this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Type", typeValue, "IIS", "NCSA", "none", "ODBC", "W3C"));
-                                        break;
-                                }
-                            }
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedAttribute(element, attrib);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
-                }
-            }
-
-            if (null == id)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Id"));
-            }
-
-            if (null == type)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Type"));
-            }
-
-            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
-
-            if (!this.Messaging.EncounteredError)
-            {
-                section.AddSymbol(new IIsWebLogSymbol(sourceLineNumbers, id)
-                {
-                    Format = type,
-                });
-            }
-        }
-
-        /// <summary>
-        /// Parses a web property element.
-        /// </summary>
-        /// <param name="element">Element to parse.</param>
-        /// <param name="componentId">Identifier for parent component.</param>
-        private void ParseWebPropertyElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
-        {
-            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
-            Identifier id = null;
-            string value = null;
-
-            foreach (var attrib in element.Attributes())
-            {
-                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
-                {
-                    switch (attrib.Name.LocalName)
-                    {
-                        case "Id":
-                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
-                            break;
-                        case "Value":
-                            value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedAttribute(element, attrib);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
-                }
-            }
-
-            switch (id?.Id)
-            {
-                case "ETagChangeNumber":
-                case "MaxGlobalBandwidth":
-                    // Must specify a value for these
-                    if (null == value)
-                    {
-                        this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Value", "Id", id.Id));
-                    }
-                    break;
-                case "IIs5IsolationMode":
-                case "LogInUTF8":
-                    // Can't specify a value for these
-                    if (null != value)
-                    {
-                        this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "Value", "Id", id.Id));
-                    }
-                    break;
-                default:
-                    this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Id", id?.Id, "ETagChangeNumber", "IIs5IsolationMode", "LogInUTF8", "MaxGlobalBandwidth"));
-                    break;
-            }
-
-            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
-
-            // Reference ConfigureIIs since nothing will happen without it
-            this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
-
-            if (!this.Messaging.EncounteredError)
-            {
-                section.AddSymbol(new IIsPropertySymbol(sourceLineNumbers, id)
-                {
-                    ComponentRef = componentId,
-                    Attributes = 0,
-                    Value = value,
-                });
-            }
-        }
-
-        /// <summary>
-        /// Parses a web service extension element.
-        /// </summary>
-        /// <param name="element">Element to parse.</param>
-        /// <param name="componentId">Identifier for parent component.</param>
-        private void ParseWebServiceExtensionElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
-        {
-            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
-            Identifier id = null;
-            int attributes = 0;
-            string description = null;
-            string file = null;
-            string group = null;
-
-            foreach (XAttribute attrib in element.Attributes())
-            {
-                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
-                {
-                    switch (attrib.Name.LocalName)
-                    {
-                        case "Id":
-                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
-                            break;
-                        case "Allow":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                attributes |= 1;
-                            }
-                            else
-                            {
-                                attributes &= ~1;
-                            }
-                            break;
-                        case "Description":
-                            description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "File":
-                            file = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "Group":
-                            group = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "UIDeletable":
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                attributes |= 2;
-                            }
-                            else
-                            {
-                                attributes &= ~2;
-                            }
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedAttribute(element, attrib);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
-                }
-            }
-
-            if (null == id)
-            {
-                id = this.ParseHelper.CreateIdentifier("iwe", componentId, file);
-            }
-
-            if (null == file)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "File"));
-            }
-
-            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
-
-            // Reference ConfigureIIs since nothing will happen without it
-            this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
-
-            if (!this.Messaging.EncounteredError)
-            {
-                section.AddSymbol(new IIsWebServiceExtensionSymbol(sourceLineNumbers, id)
-                {
-                    ComponentRef = componentId,
-                    File = file,
-                    Description = description,
-                    Group = group,
-                    Attributes = attributes,
-                });
-            }
-        }
-
-        /// <summary>
-        /// Parses a web site element.
-        /// </summary>
-        /// <param name="element">Element to parse.</param>
-        /// <param name="componentId">Optional identifier of parent component.</param>
-        private void ParseWebSiteElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
-        {
-            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
-            Identifier id = null;
-            string application = null;
-            int attributes = 0;
-            var connectionTimeout = CompilerConstants.IntegerNotSet;
-            string description = null;
-            string directory = null;
-            string dirProperties = null;
-            string keyAddress = null;
-            string log = null;
-            string siteId = null;
-            var sequence = CompilerConstants.IntegerNotSet;
-            var state = CompilerConstants.IntegerNotSet;
-
-            foreach (var attrib in element.Attributes())
-            {
-                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
-                {
-                    switch (attrib.Name.LocalName)
-                    {
-                        case "Id":
-                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
-                            break;
-                        case "AutoStart":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                state = 2;
-                            }
-                            else if (state != 1)
-                            {
-                                state = 0;
-                            }
-                            break;
-                        case "ConfigureIfExists":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                attributes &= ~2;
-                            }
-                            else
-                            {
-                                attributes |= 2;
-                            }
-                            break;
-                        case "ConnectionTimeout":
-                            connectionTimeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
-                            break;
-                        case "Description":
-                            description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "Directory":
-                            directory = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
-                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Directory, directory);
-                            break;
-                        case "DirProperties":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            dirProperties = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "SiteId":
-                            siteId = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            if ("*" == siteId)
-                            {
-                                siteId = "-1";
-                            }
-                            break;
-                        case "Sequence":
-                            sequence = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, short.MaxValue);
-                            break;
-                        case "StartOnInstall":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            // when state is set to 2 it implies 1, so don't set it to 1
-                            if (2 != state && YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
-                            {
-                                state = 1;
-                            }
-                            else if (2 != state)
-                            {
-                                state = 0;
-                            }
-                            break;
-                        case "WebApplication":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            application = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "WebLog":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
-                            }
-
-                            log = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
-                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebLog, log);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedAttribute(element, attrib);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
-                }
-            }
-
-            if (null == id)
-            {
-                id = this.ParseHelper.CreateIdentifier("iws", description, componentId, siteId, application);
-            }
-
-            if (null == description)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Description"));
-            }
-
-            if (null == directory && null != componentId)
-            {
-                this.Messaging.Write(IIsErrors.RequiredAttributeUnderComponent(sourceLineNumbers, element.Name.LocalName, "Directory"));
-            }
-
-            foreach (var child in element.Elements())
-            {
-                if (this.Namespace == child.Name.Namespace)
-                {
-                    var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child);
-                    switch (child.Name.LocalName)
-                    {
-                        case "CertificateRef":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
-                            }
-
-                            this.ParseCertificateRefElement(intermediate, section, child, id?.Id);
-                            break;
-                        case "HttpHeader":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
-                            }
-
-                            this.ParseHttpHeaderElement(intermediate, section, child, HttpHeaderParentType.WebSite, id?.Id);
-                            break;
-                        case "WebAddress":
-                            string address = this.ParseWebAddressElement(intermediate, section, child, id?.Id);
-                            if (null == keyAddress)
-                            {
-                                keyAddress = address;
-                            }
-                            break;
-                        case "WebApplication":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
-                            }
-
-                            if (null != application)
-                            {
-                                this.Messaging.Write(IIsErrors.WebApplicationAlreadySpecified(childSourceLineNumbers, element.Name.LocalName));
-                            }
-
-                            application = this.ParseWebApplicationElement(intermediate, section, child);
-                            break;
-                        case "WebDir":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
-                            }
-
-                            this.ParseWebDirElement(intermediate, section, child, componentId, id?.Id);
-                            break;
-                        case "WebDirProperties":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
-                            }
-
-                            string childWebDirProperties = this.ParseWebDirPropertiesElement(intermediate, section, child, componentId);
-                            if (null == dirProperties)
-                            {
-                                dirProperties = childWebDirProperties;
-                            }
-                            else
-                            {
-                                this.Messaging.Write(ErrorMessages.IllegalParentAttributeWhenNested(sourceLineNumbers, "WebSite", "DirProperties", child.Name.LocalName));
-                            }
-                            break;
-                        case "WebError":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
-                            }
-
-                            this.ParseWebErrorElement(intermediate, section, child, WebErrorParentType.WebSite, id?.Id);
-                            break;
-                        case "WebFilter":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
-                            }
-
-                            this.ParseWebFilterElement(intermediate, section, child, componentId, id?.Id);
-                            break;
-                        case "WebVirtualDir":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
-                            }
-
-                            this.ParseWebVirtualDirElement(intermediate, section, child, componentId, id?.Id, null);
-                            break;
-                        case "MimeMap":
-                            this.ParseMimeMapElement(intermediate, section, child, id?.Id, MimeMapParentType.WebSite);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedElement(element, child);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
-                }
-            }
-
-
-            if (null == keyAddress)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedElement(sourceLineNumbers, element.Name.LocalName, "WebAddress"));
-            }
-
-            if (null != application)
-            {
-                this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebApplication, application);
-            }
-
-            if (null != dirProperties)
-            {
-                this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebDirProperties, dirProperties);
-            }
-
-            if (null != componentId)
-            {
-                // Reference ConfigureIIs since nothing will happen without it
-                this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
-            }
-
-            if (!this.Messaging.EncounteredError)
-            {
-                var symbol = section.AddSymbol(new IIsWebSiteSymbol(sourceLineNumbers, id)
-                {
-                    ComponentRef = componentId,
-                    Description = description,
-                    DirectoryRef = directory,
-                    KeyAddressRef = keyAddress,
-                    DirPropertiesRef = dirProperties,
-                    ApplicationRef = application,
-                    LogRef = log,
-                    WebsiteId = siteId,
-                });
-
-                if (CompilerConstants.IntegerNotSet != connectionTimeout)
-                {
-                    symbol.ConnectionTimeout = connectionTimeout;
-                }
-
-                if (CompilerConstants.IntegerNotSet != state)
-                {
-                    symbol.State = state;
-                }
-
-                if (0 != attributes)
-                {
-                    symbol.Attributes = attributes;
-                }
-
-                if (CompilerConstants.IntegerNotSet != sequence)
-                {
-                    symbol.Sequence = sequence;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Parses a HTTP Header element.
-        /// </summary>
-        /// <param name="element">Element to parse.</param>
-        /// <param name="parentType">Type of the parent.</param>
-        /// <param name="parent">Id of the parent.</param>
-        private void ParseHttpHeaderElement(Intermediate intermediate, IntermediateSection section, XElement element, HttpHeaderParentType parentType, string parent)
-        {
-            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
-            Identifier id = null;
-            string headerName = null;
-            string headerValue = null;
-
-            foreach (var attrib in element.Attributes())
-            {
-                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
-                {
-                    switch (attrib.Name.LocalName)
-                    {
-                        case "Id":
-                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
-                            break;
-                        case "Name":
-                            headerName = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "Value":
-                            headerValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedAttribute(element, attrib);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
-                }
-            }
-
-            if (null == headerName)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
-            }
-            else if (null == id)
-            {
-                id = this.ParseHelper.CreateIdentifierFromFilename(headerName);
-            }
-
-            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
-
-            // Reference ConfigureIIs since nothing will happen without it
-            this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
-
-            if (!this.Messaging.EncounteredError)
-            {
-                section.AddSymbol(new IIsHttpHeaderSymbol(sourceLineNumbers, id)
-                {
-                    HttpHeader = id.Id,
-                    ParentType = (int)parentType,
-                    ParentValue = parent,
-                    Name = headerName,
-                    Value = headerValue,
-                    Attributes = 0,
-                });
-            }
-        }
-
-        /// <summary>
-        /// Parses a virtual directory element.
-        /// </summary>
-        /// <param name="element">Element to parse.</param>
-        /// <param name="componentId">Identifier of parent component.</param>
-        /// <param name="parentWeb">Identifier of parent web site.</param>
-        /// <param name="parentAlias">Alias of the parent web site.</param>
-        private void ParseWebVirtualDirElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string parentWeb, string parentAlias)
-        {
-            var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
-            Identifier id = null;
-            string alias = null;
-            string application = null;
-            string directory = null;
-            string dirProperties = null;
-
-            foreach (var attrib in element.Attributes())
-            {
-                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
-                {
-                    switch (attrib.Name.LocalName)
-                    {
-                        case "Id":
-                            id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
-                            break;
-                        case "Alias":
-                            alias = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "Directory":
-                            directory = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
-                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Directory, directory);
-                            break;
-                        case "DirProperties":
-                            dirProperties = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "WebApplication":
-                            application = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
-                            break;
-                        case "WebSite":
-                            if (null != parentWeb)
-                            {
-                                this.Messaging.Write(IIsErrors.WebSiteAttributeUnderWebSite(sourceLineNumbers, element.Name.LocalName));
-                            }
-
-                            parentWeb = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
-                            this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebSite, parentWeb);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedAttribute(element, attrib);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
-                }
-            }
-
-            if (null == id)
-            {
-                id = this.ParseHelper.CreateIdentifier("wvd", alias, directory, dirProperties, application, parentWeb);
-            }
-
-            if (null == alias)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Alias"));
-            }
-            else if (-1 != alias.IndexOf("\\", StringComparison.Ordinal))
-            {
-                this.Messaging.Write(IIsErrors.IllegalCharacterInAttributeValue(sourceLineNumbers, element.Name.LocalName, "Alias", alias, '\\'));
-            }
-
-            if (null == directory)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Directory"));
-            }
-
-            if (null == parentWeb)
-            {
-                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "WebSite"));
-            }
-
-            if (null == componentId)
-            {
-                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(sourceLineNumbers, element.Name.LocalName));
-            }
-
-            if (null != parentAlias)
-            {
-                alias = String.Concat(parentAlias, "/", alias);
-            }
-
-            foreach (var child in element.Elements())
-            {
-                if (this.Namespace == child.Name.Namespace)
-                {
-                    var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child);
-                    switch (child.Name.LocalName)
-                    {
-                        case "WebApplication":
-                            if (null != application)
-                            {
-                                this.Messaging.Write(IIsErrors.WebApplicationAlreadySpecified(childSourceLineNumbers, element.Name.LocalName));
-                            }
-
-                            application = this.ParseWebApplicationElement(intermediate, section, child);
-                            break;
-                        case "WebDirProperties":
-                            if (null == componentId)
-                            {
-                                this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
-                            }
-
-                            string childWebDirProperties = this.ParseWebDirPropertiesElement(intermediate, section, child, componentId);
-                            if (null == dirProperties)
-                            {
-                                dirProperties = childWebDirProperties;
-                            }
-                            else
-                            {
-                                this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, child.Name.LocalName, "DirProperties", child.Name.LocalName));
-                            }
-                            break;
-
-                        case "WebError":
-                            this.ParseWebErrorElement(intermediate, section, child, WebErrorParentType.WebVirtualDir, id?.Id);
-                            break;
-                        case "WebVirtualDir":
-                            this.ParseWebVirtualDirElement(intermediate, section, child, componentId, parentWeb, alias);
-                            break;
-                        case "HttpHeader":
-                            this.ParseHttpHeaderElement(intermediate, section, child, HttpHeaderParentType.WebVirtualDir, id?.Id);
-                            break;
-                        case "MimeMap":
-                            this.ParseMimeMapElement(intermediate, section, child, id?.Id, MimeMapParentType.WebVirtualDir);
-                            break;
-                        default:
-                            this.ParseHelper.UnexpectedElement(element, child);
-                            break;
-                    }
-                }
-                else
-                {
-                    this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
-                }
-            }
-
-            if (null != dirProperties)
-            {
-                this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebDirProperties, dirProperties);
-            }
-
-            if (null != application)
-            {
-                this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebApplication, application);
-            }
-
-            // Reference ConfigureIIs since nothing will happen without it
-            this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
-
-            if (!this.Messaging.EncounteredError)
-            {
-                section.AddSymbol(new IIsWebVirtualDirSymbol(sourceLineNumbers, id)
-                {
-                    ComponentRef = componentId,
-                    WebRef = parentWeb,
-                    Alias = alias,
-                    DirectoryRef = directory,
-                    DirPropertiesRef = dirProperties,
-                    ApplicationRef = application,
-                });
-            }
-        }
-
-        private void AddReferenceToConfigureIIs(IntermediateSection section, SourceLineNumber sourceLineNumbers)
-        {
-            this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureIIs", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
-        }
-    }
-}
diff --git a/src/wixext/IIsDecompiler.cs b/src/wixext/IIsDecompiler.cs
deleted file mode 100644
index 17e15348..00000000
--- a/src/wixext/IIsDecompiler.cs
+++ /dev/null
@@ -1,1549 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-#if TODO_CONSIDER_DECOMPILER
-    using System;
-    using System.Collections;
-    using System.Globalization;
-    using WixToolset.Data;
-    using WixToolset.Extensibility;
-    using IIs = WixToolset.Extensions.Serialize.IIs;
-    using Wix = WixToolset.Data.Serialize;
-
-    /// <summary>
-    /// The decompiler for the WiX Toolset Internet Information Services Extension.
-    /// </summary>
-    public sealed class IIsDecompiler : DecompilerExtension
-    {
-        /// <summary>
-        /// Creates a decompiler for IIs Extension.
-        /// </summary>
-        public IIsDecompiler()
-        {
-            this.TableDefinitions = IIsExtensionData.GetExtensionTableDefinitions();
-        }
-
-        /// <summary>
-        /// Get the extensions library to be removed.
-        /// </summary>
-        /// <param name="tableDefinitions">Table definitions for library.</param>
-        /// <returns>Library to remove from decompiled output.</returns>
-        public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions)
-        {
-            return IIsExtensionData.GetExtensionLibrary(tableDefinitions);
-        }
-
-        /// <summary>
-        /// Decompiles an extension table.
-        /// </summary>
-        /// <param name="table">The table to decompile.</param>
-        public override void DecompileTable(Table table)
-        {
-            switch (table.Name)
-            {
-                case "Certificate":
-                    this.DecompileCertificateTable(table);
-                    break;
-                case "CertificateHash":
-                    // There is nothing to do for this table, it contains no authored data
-                    // to be decompiled.
-                    break;
-                case "IIsAppPool":
-                    this.DecompileIIsAppPoolTable(table);
-                    break;
-                case "IIsFilter":
-                    this.DecompileIIsFilterTable(table);
-                    break;
-                case "IIsProperty":
-                    this.DecompileIIsPropertyTable(table);
-                    break;
-                case "IIsHttpHeader":
-                    this.DecompileIIsHttpHeaderTable(table);
-                    break;
-                case "IIsMimeMap":
-                    this.DecompileIIsMimeMapTable(table);
-                    break;
-                case "IIsWebAddress":
-                    this.DecompileIIsWebAddressTable(table);
-                    break;
-                case "IIsWebApplication":
-                    this.DecompileIIsWebApplicationTable(table);
-                    break;
-                case "IIsWebDirProperties":
-                    this.DecompileIIsWebDirPropertiesTable(table);
-                    break;
-                case "IIsWebError":
-                    this.DecompileIIsWebErrorTable(table);
-                    break;
-                case "IIsWebLog":
-                    this.DecompileIIsWebLogTable(table);
-                    break;
-                case "IIsWebServiceExtension":
-                    this.DecompileIIsWebServiceExtensionTable(table);
-                    break;
-                case "IIsWebSite":
-                    this.DecompileIIsWebSiteTable(table);
-                    break;
-                case "IIsWebVirtualDir":
-                    this.DecompileIIsWebVirtualDirTable(table);
-                    break;
-                case "IIsWebSiteCertificates":
-                    this.DecompileIIsWebSiteCertificatesTable(table);
-                    break;
-                default:
-                    base.DecompileTable(table);
-                    break;
-            }
-        }
-
-        /// <summary>
-        /// Finalize decompilation.
-        /// </summary>
-        /// <param name="tables">The collection of all tables.</param>
-        public override void Finish(TableIndexedCollection tables)
-        {
-            this.FinalizeIIsMimeMapTable(tables);
-            this.FinalizeIIsHttpHeaderTable(tables);
-            this.FinalizeIIsWebApplicationTable(tables);
-            this.FinalizeIIsWebErrorTable(tables);
-            this.FinalizeIIsWebVirtualDirTable(tables);
-            this.FinalizeIIsWebSiteCertificatesTable(tables);
-            this.FinalizeWebAddressTable(tables);
-        }
-
-        /// <summary>
-        /// Decompile the Certificate table.
-        /// </summary>
-        /// <param name="table">The table to decompile.</param>
-        private void DecompileCertificateTable(Table table)
-        {
-            foreach (Row row in table.Rows)
-            {
-                IIs.Certificate certificate = new IIs.Certificate();
-
-                certificate.Id = (string)row[0];
-                certificate.Name = (string)row[2];
-
-                switch ((int)row[3])
-                {
-                    case 1:
-                        certificate.StoreLocation = IIs.Certificate.StoreLocationType.currentUser;
-                        break;
-                    case 2:
-                        certificate.StoreLocation = IIs.Certificate.StoreLocationType.localMachine;
-                        break;
-                    default:
-                        // TODO: warn
-                        break;
-                }
-
-                switch ((string)row[4])
-                {
-                    case "CA":
-                        certificate.StoreName = IIs.Certificate.StoreNameType.ca;
-                        break;
-                    case "MY":
-                        certificate.StoreName = IIs.Certificate.StoreNameType.my;
-                        break;
-                    case "REQUEST":
-                        certificate.StoreName = IIs.Certificate.StoreNameType.request;
-                        break;
-                    case "Root":
-                        certificate.StoreName = IIs.Certificate.StoreNameType.root;
-                        break;
-                    case "AddressBook":
-                        certificate.StoreName = IIs.Certificate.StoreNameType.otherPeople;
-                        break;
-                    case "TrustedPeople":
-                        certificate.StoreName = IIs.Certificate.StoreNameType.trustedPeople;
-                        break;
-                    case "TrustedPublisher":
-                        certificate.StoreName = IIs.Certificate.StoreNameType.trustedPublisher;
-                        break;
-                    default:
-                        // TODO: warn
-                        break;
-                }
-
-                int attribute = (int)row[5];
-
-                if (0x1 == (attribute & 0x1))
-                {
-                    certificate.Request = IIs.YesNoType.yes;
-                }
-
-                if (0x2 == (attribute & 0x2))
-                {
-                    if (null != row[6])
-                    {
-                        certificate.BinaryKey = (string)row[6];
-                    }
-                    else
-                    {
-                        // TODO: warn about expected value in row 5
-                    }
-                }
-                else if (null != row[7])
-                {
-                    certificate.CertificatePath = (string)row[7];
-                }
-
-                if (0x4 == (attribute & 0x4))
-                {
-                    certificate.Overwrite = IIs.YesNoType.yes;
-                }
-
-                if (null != row[8])
-                {
-                    certificate.PFXPassword = (string)row[8];
-                }
-
-                Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
-                if (null != component)
-                {
-                    component.AddChild(certificate);
-                }
-                else
-                {
-                    this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
-                }
-            }
-        }
-
-        /// <summary>
-        /// Decompile the IIsAppPool table.
-        /// </summary>
-        /// <param name="table">The table to decompile.</param>
-        private void DecompileIIsAppPoolTable(Table table)
-        {
-            foreach (Row row in table.Rows)
-            {
-                IIs.WebAppPool webAppPool = new IIs.WebAppPool();
-
-                webAppPool.Id = (string)row[0];
-
-                webAppPool.Name = (string)row[1];
-
-                switch ((int)row[3] & 0x1F)
-                {
-                    case 1:
-                        webAppPool.Identity = IIs.WebAppPool.IdentityType.networkService;
-                        break;
-                    case 2:
-                        webAppPool.Identity = IIs.WebAppPool.IdentityType.localService;
-                        break;
-                    case 4:
-                        webAppPool.Identity = IIs.WebAppPool.IdentityType.localSystem;
-                        break;
-                    case 8:
-                        webAppPool.Identity = IIs.WebAppPool.IdentityType.other;
-                        break;
-                    case 0x10:
-                        webAppPool.Identity = IIs.WebAppPool.IdentityType.applicationPoolIdentity;
-                        break;
-                    default:
-                        // TODO: warn
-                        break;
-                }
-
-                if (null != row[4])
-                {
-                    webAppPool.User = (string)row[4];
-                }
-
-                if (null != row[5])
-                {
-                    webAppPool.RecycleMinutes = (int)row[5];
-                }
-
-                if (null != row[6])
-                {
-                    webAppPool.RecycleRequests = (int)row[6];
-                }
-
-                if (null != row[7])
-                {
-                    string[] recycleTimeValues = ((string)row[7]).Split(',');
-
-                    foreach (string recycleTimeValue in recycleTimeValues)
-                    {
-                        IIs.RecycleTime recycleTime = new IIs.RecycleTime();
-
-                        recycleTime.Value = recycleTimeValue;
-
-                        webAppPool.AddChild(recycleTime);
-                    }
-                }
-
-                if (null != row[8])
-                {
-                    webAppPool.IdleTimeout = (int)row[8];
-                }
-
-                if (null != row[9])
-                {
-                    webAppPool.QueueLimit = (int)row[9];
-                }
-
-                if (null != row[10])
-                {
-                    string[] cpuMon = ((string)row[10]).Split(',');
-
-                    if (0 < cpuMon.Length && "0" != cpuMon[0])
-                    {
-                        webAppPool.MaxCpuUsage = Convert.ToInt32(cpuMon[0], CultureInfo.InvariantCulture);
-                    }
-
-                    if (1 < cpuMon.Length)
-                    {
-                        webAppPool.RefreshCpu = Convert.ToInt32(cpuMon[1], CultureInfo.InvariantCulture);
-                    }
-
-                    if (2 < cpuMon.Length)
-                    {
-                        switch (Convert.ToInt32(cpuMon[2], CultureInfo.InvariantCulture))
-                        {
-                            case 0:
-                                webAppPool.CpuAction = IIs.WebAppPool.CpuActionType.none;
-                                break;
-                            case 1:
-                                webAppPool.CpuAction = IIs.WebAppPool.CpuActionType.shutdown;
-                                break;
-                            default:
-                                // TODO: warn
-                                break;
-                        }
-                    }
-
-                    if (3 < cpuMon.Length)
-                    {
-                        // TODO: warn
-                    }
-                }
-
-                if (null != row[11])
-                {
-                    webAppPool.MaxWorkerProcesses = (int)row[11];
-                }
-
-                if (null != row[12])
-                {
-                    webAppPool.VirtualMemory = (int)row[12];
-                }
-
-                if (null != row[13])
-                {
-                    webAppPool.PrivateMemory = (int)row[13];
-                }
-
-                if (null != row[14])
-                {
-                    webAppPool.ManagedRuntimeVersion = (string)row[14];
-                }
-
-                if (null != row[15])
-                {
-                    webAppPool.ManagedPipelineMode = (string)row[15];
-                }
-
-                if (null != row[2])
-                {
-                    Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]);
-
-                    if (null != component)
-                    {
-                        component.AddChild(webAppPool);
-                    }
-                    else
-                    {
-                        this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
-                    }
-                }
-                else
-                {
-                    this.Core.RootElement.AddChild(webAppPool);
-                }
-            }
-        }
-
-        /// <summary>
-        /// Decompile the IIsProperty table.
-        /// </summary>
-        /// <param name="table">The table to decompile.</param>
-        private void DecompileIIsPropertyTable(Table table)
-        {
-            foreach (Row row in table.Rows)
-            {
-                IIs.WebProperty webProperty = new IIs.WebProperty();
-
-                switch ((string)row[0])
-                {
-                    case "ETagChangeNumber":
-                        webProperty.Id = IIs.WebProperty.IdType.ETagChangeNumber;
-                        break;
-                    case "IIs5IsolationMode":
-                        webProperty.Id = IIs.WebProperty.IdType.IIs5IsolationMode;
-                        break;
-                    case "LogInUTF8":
-                        webProperty.Id = IIs.WebProperty.IdType.LogInUTF8;
-                        break;
-                    case "MaxGlobalBandwidth":
-                        webProperty.Id = IIs.WebProperty.IdType.MaxGlobalBandwidth;
-                        break;
-                }
-
-                if (0 != (int)row[2])
-                {
-                    // TODO: warn about value in unused column
-                }
-
-                if (null != row[3])
-                {
-                    webProperty.Value = (string)row[3];
-                }
-
-                Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
-                if (null != component)
-                {
-                    component.AddChild(webProperty);
-                }
-                else
-                {
-                    this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
-                }
-            }
-        }
-
-        /// <summary>
-        /// Decompile the IIsHttpHeader table.
-        /// </summary>
-        /// <param name="table">The table to decompile.</param>
-        private void DecompileIIsHttpHeaderTable(Table table)
-        {
-            foreach (Row row in table.Rows)
-            {
-                IIs.HttpHeader httpHeader = new IIs.HttpHeader();
-
-                httpHeader.Name = (string)row[3];
-
-                // the ParentType and Parent columns are handled in FinalizeIIsHttpHeaderTable
-
-                httpHeader.Value = (string)row[4];
-
-                this.Core.IndexElement(row, httpHeader);
-            }
-        }
-
-        /// <summary>
-        /// Decompile the IIsMimeMap table.
-        /// </summary>
-        /// <param name="table">The table to decompile.</param>
-        private void DecompileIIsMimeMapTable(Table table)
-        {
-            foreach (Row row in table.Rows)
-            {
-                IIs.MimeMap mimeMap = new IIs.MimeMap();
-
-                mimeMap.Id = (string)row[0];
-
-                // the ParentType and ParentValue columns are handled in FinalizeIIsMimeMapTable
-
-                mimeMap.Type = (string)row[3];
-
-                mimeMap.Extension = (string)row[4];
-
-                this.Core.IndexElement(row, mimeMap);
-            }
-        }
-
-        /// <summary>
-        /// Decompile the IIsWebAddress table.
-        /// </summary>
-        /// <param name="table">The table to decompile.</param>
-        private void DecompileIIsWebAddressTable(Table table)
-        {
-            foreach (Row row in table.Rows)
-            {
-                IIs.WebAddress webAddress = new IIs.WebAddress();
-
-                webAddress.Id = (string)row[0];
-
-                if (null != row[2])
-                {
-                    webAddress.IP = (string)row[2];
-                }
-
-                webAddress.Port = (string)row[3];
-
-                if (null != row[4])
-                {
-                    webAddress.Header = (string)row[4];
-                }
-
-                if (null != row[5] && 1 == (int)row[5])
-                {
-                    webAddress.Secure = IIs.YesNoType.yes;
-                }
-
-                this.Core.IndexElement(row, webAddress);
-            }
-        }
-
-        /// <summary>
-        /// Decompile the IIsWebApplication table.
-        /// </summary>
-        /// <param name="table">The table to decompile.</param>
-        private void DecompileIIsWebApplicationTable(Table table)
-        {
-            foreach (Row row in table.Rows)
-            {
-                IIs.WebApplication webApplication = new IIs.WebApplication();
-
-                webApplication.Id = (string)row[0];
-
-                webApplication.Name = (string)row[1];
-
-                // these are not listed incorrectly - the order is low, high, medium
-                switch ((int)row[2])
-                {
-                    case 0:
-                        webApplication.Isolation = IIs.WebApplication.IsolationType.low;
-                        break;
-                    case 1:
-                        webApplication.Isolation = IIs.WebApplication.IsolationType.high;
-                        break;
-                    case 2:
-                        webApplication.Isolation = IIs.WebApplication.IsolationType.medium;
-                        break;
-                    default:
-                        // TODO: warn
-                        break;
-                }
-
-                if (null != row[3])
-                {
-                    switch ((int)row[3])
-                    {
-                        case 0:
-                            webApplication.AllowSessions = IIs.YesNoDefaultType.no;
-                            break;
-                        case 1:
-                            webApplication.AllowSessions = IIs.YesNoDefaultType.yes;
-                            break;
-                        default:
-                            // TODO: warn
-                            break;
-                    }
-                }
-
-                if (null != row[4])
-                {
-                    webApplication.SessionTimeout = (int)row[4];
-                }
-
-                if (null != row[5])
-                {
-                    switch ((int)row[5])
-                    {
-                        case 0:
-                            webApplication.Buffer = IIs.YesNoDefaultType.no;
-                            break;
-                        case 1:
-                            webApplication.Buffer = IIs.YesNoDefaultType.yes;
-                            break;
-                        default:
-                            // TODO: warn
-                            break;
-                    }
-                }
-
-                if (null != row[6])
-                {
-                    switch ((int)row[6])
-                    {
-                        case 0:
-                            webApplication.ParentPaths = IIs.YesNoDefaultType.no;
-                            break;
-                        case 1:
-                            webApplication.ParentPaths = IIs.YesNoDefaultType.yes;
-                            break;
-                        default:
-                            // TODO: warn
-                            break;
-                    }
-                }
-
-                if (null != row[7])
-                {
-                    switch ((string)row[7])
-                    {
-                        case "JScript":
-                            webApplication.DefaultScript = IIs.WebApplication.DefaultScriptType.JScript;
-                            break;
-                        case "VBScript":
-                            webApplication.DefaultScript = IIs.WebApplication.DefaultScriptType.VBScript;
-                            break;
-                        default:
-                            // TODO: warn
-                            break;
-                    }
-                }
-
-                if (null != row[8])
-                {
-                    webApplication.ScriptTimeout = (int)row[8];
-                }
-
-                if (null != row[9])
-                {
-                    switch ((int)row[9])
-                    {
-                        case 0:
-                            webApplication.ServerDebugging = IIs.YesNoDefaultType.no;
-                            break;
-                        case 1:
-                            webApplication.ServerDebugging = IIs.YesNoDefaultType.yes;
-                            break;
-                        default:
-                            // TODO: warn
-                            break;
-                    }
-                }
-
-                if (null != row[10])
-                {
-                    switch ((int)row[10])
-                    {
-                        case 0:
-                            webApplication.ClientDebugging = IIs.YesNoDefaultType.no;
-                            break;
-                        case 1:
-                            webApplication.ClientDebugging = IIs.YesNoDefaultType.yes;
-                            break;
-                        default:
-                            // TODO: warn
-                            break;
-                    }
-                }
-
-                if (null != row[11])
-                {
-                    webApplication.WebAppPool = (string)row[11];
-                }
-
-                this.Core.IndexElement(row, webApplication);
-            }
-        }
-
-        /// <summary>
-        /// Decompile the IIsWebDirProperties table.
-        /// </summary>
-        /// <param name="table">The table to decompile.</param>
-        private void DecompileIIsWebDirPropertiesTable(Table table)
-        {
-            foreach (Row row in table.Rows)
-            {
-                IIs.WebDirProperties webDirProperties = new IIs.WebDirProperties();
-
-                webDirProperties.Id = (string)row[0];
-
-                if (null != row[1])
-                {
-                    int access = (int)row[1];
-
-                    if (0x1 == (access & 0x1))
-                    {
-                        webDirProperties.Read = IIs.YesNoType.yes;
-                    }
-
-                    if (0x2 == (access & 0x2))
-                    {
-                        webDirProperties.Write = IIs.YesNoType.yes;
-                    }
-
-                    if (0x4 == (access & 0x4))
-                    {
-                        webDirProperties.Execute = IIs.YesNoType.yes;
-                    }
-
-                    if (0x200 == (access & 0x200))
-                    {
-                        webDirProperties.Script = IIs.YesNoType.yes;
-                    }
-                }
-
-                if (null != row[2])
-                {
-                    int authorization = (int)row[2];
-
-                    if (0x1 == (authorization & 0x1))
-                    {
-                        webDirProperties.AnonymousAccess = IIs.YesNoType.yes;
-                    }
-                    else // set one of the properties to 'no' to force the output value to be '0' if not other attributes are set
-                    {
-                        webDirProperties.AnonymousAccess = IIs.YesNoType.no;
-                    }
-
-                    if (0x2 == (authorization & 0x2))
-                    {
-                        webDirProperties.BasicAuthentication = IIs.YesNoType.yes;
-                    }
-
-                    if (0x4 == (authorization & 0x4))
-                    {
-                        webDirProperties.WindowsAuthentication = IIs.YesNoType.yes;
-                    }
-
-                    if (0x10 == (authorization & 0x10))
-                    {
-                        webDirProperties.DigestAuthentication = IIs.YesNoType.yes;
-                    }
-
-                    if (0x40 == (authorization & 0x40))
-                    {
-                        webDirProperties.PassportAuthentication = IIs.YesNoType.yes;
-                    }
-                }
-
-                if (null != row[3])
-                {
-                    webDirProperties.AnonymousUser = (string)row[3];
-                }
-
-                if (null != row[4] && 1 == (int)row[4])
-                {
-                    webDirProperties.IIsControlledPassword = IIs.YesNoType.yes;
-                }
-
-                if (null != row[5])
-                {
-                    switch ((int)row[5])
-                    {
-                        case 0:
-                            webDirProperties.LogVisits = IIs.YesNoType.no;
-                            break;
-                        case 1:
-                            webDirProperties.LogVisits = IIs.YesNoType.yes;
-                            break;
-                        default:
-                            // TODO: warn
-                            break;
-                    }
-                }
-
-                if (null != row[6])
-                {
-                    switch ((int)row[6])
-                    {
-                        case 0:
-                            webDirProperties.Index = IIs.YesNoType.no;
-                            break;
-                        case 1:
-                            webDirProperties.Index = IIs.YesNoType.yes;
-                            break;
-                        default:
-                            // TODO: warn
-                            break;
-                    }
-                }
-
-                if (null != row[7])
-                {
-                    webDirProperties.DefaultDocuments = (string)row[7];
-                }
-
-                if (null != row[8])
-                {
-                    switch ((int)row[8])
-                    {
-                        case 0:
-                            webDirProperties.AspDetailedError = IIs.YesNoType.no;
-                            break;
-                        case 1:
-                            webDirProperties.AspDetailedError = IIs.YesNoType.yes;
-                            break;
-                        default:
-                            // TODO: warn
-                            break;
-                    }
-                }
-
-                if (null != row[9])
-                {
-                    webDirProperties.HttpExpires = (string)row[9];
-                }
-
-                if (null != row[10])
-                {
-                    // force the value to be a positive number
-                    webDirProperties.CacheControlMaxAge = unchecked((uint)(int)row[10]);
-                }
-
-                if (null != row[11])
-                {
-                    webDirProperties.CacheControlCustom = (string)row[11];
-                }
-
-                if (null != row[12])
-                {
-                    switch ((int)row[8])
-                    {
-                        case 0:
-                            webDirProperties.ClearCustomError = IIs.YesNoType.no;
-                            break;
-                        case 1:
-                            webDirProperties.ClearCustomError = IIs.YesNoType.yes;
-                            break;
-                        default:
-                            // TODO: warn
-                            break;
-                    }
-                }
-
-                if (null != row[13])
-                {
-                    int accessSSLFlags = (int)row[13];
-
-                    if (0x8 == (accessSSLFlags & 0x8))
-                    {
-                        webDirProperties.AccessSSL = IIs.YesNoType.yes;
-                    }
-
-                    if (0x20 == (accessSSLFlags & 0x20))
-                    {
-                        webDirProperties.AccessSSLNegotiateCert = IIs.YesNoType.yes;
-                    }
-
-                    if (0x40 == (accessSSLFlags & 0x40))
-                    {
-                        webDirProperties.AccessSSLRequireCert = IIs.YesNoType.yes;
-                    }
-
-                    if (0x80 == (accessSSLFlags & 0x80))
-                    {
-                        webDirProperties.AccessSSLMapCert = IIs.YesNoType.yes;
-                    }
-
-                    if (0x100 == (accessSSLFlags & 0x100))
-                    {
-                        webDirProperties.AccessSSL128 = IIs.YesNoType.yes;
-                    }
-                }
-
-                if (null != row[14])
-                {
-                    webDirProperties.AuthenticationProviders = (string)row[14];
-                }
-
-                this.Core.RootElement.AddChild(webDirProperties);
-            }
-        }
-
-        /// <summary>
-        /// Decompile the IIsWebError table.
-        /// </summary>
-        /// <param name="table">The table to decompile.</param>
-        private void DecompileIIsWebErrorTable(Table table)
-        {
-            foreach (Row row in table.Rows)
-            {
-                IIs.WebError webError = new IIs.WebError();
-
-                webError.ErrorCode = (int)row[0];
-
-                webError.SubCode = (int)row[1];
-
-                // the ParentType and ParentValue columns are handled in FinalizeIIsWebErrorTable
-
-                if (null != row[4])
-                {
-                    webError.File = (string)row[4];
-                }
-
-                if (null != row[5])
-                {
-                    webError.URL = (string)row[5];
-                }
-
-                this.Core.IndexElement(row, webError);
-            }
-        }
-
-        /// <summary>
-        /// Decompile the IIsFilter table.
-        /// </summary>
-        /// <param name="table">The table to decompile.</param>
-        private void DecompileIIsFilterTable(Table table)
-        {
-            foreach (Row row in table.Rows)
-            {
-                IIs.WebFilter webFilter = new IIs.WebFilter();
-
-                webFilter.Id = (string)row[0];
-
-                webFilter.Name = (string)row[1];
-
-                if (null != row[3])
-                {
-                    webFilter.Path = (string)row[3];
-                }
-
-                if (null != row[5])
-                {
-                    webFilter.Description = (string)row[5];
-                }
-
-                webFilter.Flags = (int)row[6];
-
-                if (null != row[7])
-                {
-                    switch ((int)row[7])
-                    {
-                        case (-1):
-                            webFilter.LoadOrder = "last";
-                            break;
-                        case 0:
-                            webFilter.LoadOrder = "first";
-                            break;
-                        default:
-                            webFilter.LoadOrder = Convert.ToString((int)row[7], CultureInfo.InvariantCulture);
-                            break;
-                    }
-                }
-
-                if (null != row[4])
-                {
-                    IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement("IIsWebSite", (string)row[4]);
-
-                    if (null != webSite)
-                    {
-                        webSite.AddChild(webFilter);
-                    }
-                    else
-                    {
-                        this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Web_", (string)row[4], "IIsWebSite"));
-                    }
-                }
-                else // Component parent
-                {
-                    Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]);
-
-                    if (null != component)
-                    {
-                        component.AddChild(webFilter);
-                    }
-                    else
-                    {
-                        this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
-                    }
-                }
-            }
-        }
-
-        /// <summary>
-        /// Decompile the IIsWebLog table.
-        /// </summary>
-        /// <param name="table">The table to decompile.</param>
-        private void DecompileIIsWebLogTable(Table table)
-        {
-            foreach (Row row in table.Rows)
-            {
-                IIs.WebLog webLog = new IIs.WebLog();
-
-                webLog.Id = (string)row[0];
-
-                switch ((string)row[1])
-                {
-                    case "Microsoft IIS Log File Format":
-                        webLog.Type = IIs.WebLog.TypeType.IIS;
-                        break;
-                    case "NCSA Common Log File Format":
-                        webLog.Type = IIs.WebLog.TypeType.NCSA;
-                        break;
-                    case "none":
-                        webLog.Type = IIs.WebLog.TypeType.none;
-                        break;
-                    case "ODBC Logging":
-                        webLog.Type = IIs.WebLog.TypeType.ODBC;
-                        break;
-                    case "W3C Extended Log File Format":
-                        webLog.Type = IIs.WebLog.TypeType.W3C;
-                        break;
-                    default:
-                        // TODO: warn
-                        break;
-                }
-
-                this.Core.RootElement.AddChild(webLog);
-            }
-        }
-
-        /// <summary>
-        /// Decompile the IIsWebServiceExtension table.
-        /// </summary>
-        /// <param name="table">The table to decompile.</param>
-        private void DecompileIIsWebServiceExtensionTable(Table table)
-        {
-            foreach (Row row in table.Rows)
-            {
-                IIs.WebServiceExtension webServiceExtension = new IIs.WebServiceExtension();
-
-                webServiceExtension.Id = (string)row[0];
-
-                webServiceExtension.File = (string)row[2];
-
-                if (null != row[3])
-                {
-                    webServiceExtension.Description = (string)row[3];
-                }
-
-                if (null != row[4])
-                {
-                    webServiceExtension.Group = (string)row[4];
-                }
-
-                int attributes = (int)row[5];
-
-                if (0x1 == (attributes & 0x1))
-                {
-                    webServiceExtension.Allow = IIs.YesNoType.yes;
-                }
-                else
-                {
-                    webServiceExtension.Allow = IIs.YesNoType.no;
-                }
-
-                if (0x2 == (attributes & 0x2))
-                {
-                    webServiceExtension.UIDeletable = IIs.YesNoType.yes;
-                }
-
-                Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
-                if (null != component)
-                {
-                    component.AddChild(webServiceExtension);
-                }
-                else
-                {
-                    this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
-                }
-            }
-        }
-
-        /// <summary>
-        /// Decompile the IIsWebSite table.
-        /// </summary>
-        /// <param name="table">The table to decompile.</param>
-        private void DecompileIIsWebSiteTable(Table table)
-        {
-            foreach (Row row in table.Rows)
-            {
-                IIs.WebSite webSite = new IIs.WebSite();
-
-                webSite.Id = (string)row[0];
-
-                if (null != row[2])
-                {
-                    webSite.Description = (string)row[2];
-                }
-
-                if (null != row[3])
-                {
-                    webSite.ConnectionTimeout = (int)row[3];
-                }
-
-                if (null != row[4])
-                {
-                    webSite.Directory = (string)row[4];
-                }
-
-                if (null != row[5])
-                {
-                    switch ((int)row[5])
-                    {
-                        case 0:
-                            // this is the default
-                            break;
-                        case 1:
-                            webSite.StartOnInstall = IIs.YesNoType.yes;
-                            break;
-                        case 2:
-                            webSite.AutoStart = IIs.YesNoType.yes;
-                            break;
-                        default:
-                            // TODO: warn
-                            break;
-                    }
-                }
-
-                if (null != row[6])
-                {
-                    int attributes = (int)row[6];
-
-                    if (0x2 == (attributes & 0x2))
-                    {
-                        webSite.ConfigureIfExists = IIs.YesNoType.no;
-                    }
-                }
-
-                // the KeyAddress_ column is handled in FinalizeWebAddressTable
-
-                if (null != row[8])
-                {
-                    webSite.DirProperties = (string)row[8];
-                }
-
-                // the Application_ column is handled in FinalizeIIsWebApplicationTable
-
-                if (null != row[10])
-                {
-                    if (-1 != (int)row[10])
-                    {
-                        webSite.Sequence = (int)row[10];
-                    }
-                }
-
-                if (null != row[11])
-                {
-                    webSite.WebLog = (string)row[11];
-                }
-
-                if (null != row[12])
-                {
-                    webSite.SiteId = (string)row[12];
-                }
-
-                if (null != row[1])
-                {
-                    Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
-
-                    if (null != component)
-                    {
-                        component.AddChild(webSite);
-                    }
-                    else
-                    {
-                        this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
-                    }
-                }
-                else
-                {
-                    this.Core.RootElement.AddChild(webSite);
-                }
-                this.Core.IndexElement(row, webSite);
-            }
-        }
-
-        /// <summary>
-        /// Decompile the IIsWebVirtualDir table.
-        /// </summary>
-        /// <param name="table">The table to decompile.</param>
-        private void DecompileIIsWebVirtualDirTable(Table table)
-        {
-            foreach (Row row in table.Rows)
-            {
-                IIs.WebVirtualDir webVirtualDir = new IIs.WebVirtualDir();
-
-                webVirtualDir.Id = (string)row[0];
-
-                // the Component_ and Web_ columns are handled in FinalizeIIsWebVirtualDirTable
-
-                webVirtualDir.Alias = (string)row[3];
-
-                webVirtualDir.Directory = (string)row[4];
-
-                if (null != row[5])
-                {
-                    webVirtualDir.DirProperties = (string)row[5];
-                }
-
-                // the Application_ column is handled in FinalizeIIsWebApplicationTable
-
-                this.Core.IndexElement(row, webVirtualDir);
-            }
-        }
-
-        /// <summary>
-        /// Decompile the IIsWebSiteCertificates table.
-        /// </summary>
-        /// <param name="table">The table to decompile.</param>
-        private void DecompileIIsWebSiteCertificatesTable(Table table)
-        {
-            foreach (Row row in table.Rows)
-            {
-                IIs.CertificateRef certificateRef = new IIs.CertificateRef();
-
-                certificateRef.Id = (string)row[1];
-
-                this.Core.IndexElement(row, certificateRef);
-            }
-        }
-
-        /// <summary>
-        /// Finalize the IIsHttpHeader table.
-        /// </summary>
-        /// <param name="tables">The collection of all tables.</param>
-        /// <remarks>
-        /// The IIsHttpHeader table supports multiple parent types so no foreign key
-        /// is declared and thus nesting must be done late.
-        /// </remarks>
-        private void FinalizeIIsHttpHeaderTable(TableIndexedCollection tables)
-        {
-            Table iisHttpHeaderTable = tables["IIsHttpHeader"];
-
-            if (null != iisHttpHeaderTable)
-            {
-                foreach (Row row in iisHttpHeaderTable.Rows)
-                {
-                    IIs.HttpHeader httpHeader = (IIs.HttpHeader)this.Core.GetIndexedElement(row);
-
-                    if (1 == (int)row[1])
-                    {
-                        IIs.WebVirtualDir webVirtualDir = (IIs.WebVirtualDir)this.Core.GetIndexedElement("IIsWebVirtualDir", (string)row[2]);
-                        if (null != webVirtualDir)
-                        {
-                            webVirtualDir.AddChild(httpHeader);
-                        }
-                        else
-                        {
-                            this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisHttpHeaderTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ParentValue", (string)row[2], "IIsWebVirtualDir"));
-                        }
-                    }
-                    else if (2 == (int)row[1])
-                    {
-                        IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement("IIsWebSite", (string)row[2]);
-                        if (null != webSite)
-                        {
-                            webSite.AddChild(httpHeader);
-                        }
-                        else
-                        {
-                            this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisHttpHeaderTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ParentValue", (string)row[2], "IIsWebSite"));
-                        }
-                    }
-                }
-            }
-        }
-
-        /// <summary>
-        /// Finalize the IIsMimeMap table.
-        /// </summary>
-        /// <param name="tables">The collection of all tables.</param>
-        /// <remarks>
-        /// The IIsMimeMap table supports multiple parent types so no foreign key
-        /// is declared and thus nesting must be done late.
-        /// </remarks>
-        private void FinalizeIIsMimeMapTable(TableIndexedCollection tables)
-        {
-            Table iisMimeMapTable = tables["IIsMimeMap"];
-
-            if (null != iisMimeMapTable)
-            {
-                foreach (Row row in iisMimeMapTable.Rows)
-                {
-                    IIs.MimeMap mimeMap = (IIs.MimeMap)this.Core.GetIndexedElement(row);
-
-                    if (2 < (int)row[1] || 0 >= (int)row[1])
-                    {
-                        // TODO: warn about unknown parent type
-                    }
-
-                    IIs.WebVirtualDir webVirtualDir = (IIs.WebVirtualDir)this.Core.GetIndexedElement("IIsWebVirtualDir", (string)row[2]);
-                    IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement("IIsWebSite", (string)row[2]);
-                    if (null != webVirtualDir)
-                    {
-                        webVirtualDir.AddChild(mimeMap);
-                    }
-                    else if (null != webSite)
-                    {
-                        webSite.AddChild(mimeMap);
-                    }
-                    else
-                    {
-                        this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisMimeMapTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ParentValue", (string)row[2], "IIsWebVirtualDir"));
-                    }
-                }
-            }
-        }
-
-        /// <summary>
-        /// Finalize the IIsWebApplication table.
-        /// </summary>
-        /// <param name="tables">The collection of all tables.</param>
-        /// <remarks>
-        /// Since WebApplication elements may nest under a specific WebSite or
-        /// WebVirtualDir (or just the root element), the nesting must be done late.
-        /// </remarks>
-        private void FinalizeIIsWebApplicationTable(TableIndexedCollection tables)
-        {
-            Table iisWebApplicationTable = tables["IIsWebApplication"];
-            Table iisWebSiteTable = tables["IIsWebSite"];
-            Table iisWebVirtualDirTable = tables["IIsWebVirtualDir"];
-
-            Hashtable addedWebApplications = new Hashtable();
-
-            if (null != iisWebSiteTable)
-            {
-                foreach (Row row in iisWebSiteTable.Rows)
-                {
-                    if (null != row[9])
-                    {
-                        IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement(row);
-
-                        IIs.WebApplication webApplication = (IIs.WebApplication)this.Core.GetIndexedElement("IIsWebApplication", (string)row[9]);
-                        if (null != webApplication)
-                        {
-                            webSite.AddChild(webApplication);
-                            addedWebApplications[webApplication] = null;
-                        }
-                        else
-                        {
-                            this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebSiteTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Application_", (string)row[9], "IIsWebApplication"));
-                        }
-                    }
-                }
-            }
-
-            if (null != iisWebVirtualDirTable)
-            {
-                foreach (Row row in iisWebVirtualDirTable.Rows)
-                {
-                    if (null != row[6])
-                    {
-                        IIs.WebVirtualDir webVirtualDir = (IIs.WebVirtualDir)this.Core.GetIndexedElement(row);
-
-                        IIs.WebApplication webApplication = (IIs.WebApplication)this.Core.GetIndexedElement("IIsWebApplication", (string)row[6]);
-                        if (null != webApplication)
-                        {
-                            webVirtualDir.AddChild(webApplication);
-                            addedWebApplications[webApplication] = null;
-                        }
-                        else
-                        {
-                            this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebVirtualDirTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Application_", (string)row[6], "IIsWebApplication"));
-                        }
-                    }
-                }
-            }
-
-            if (null != iisWebApplicationTable)
-            {
-                foreach (Row row in iisWebApplicationTable.Rows)
-                {
-                    IIs.WebApplication webApplication = (IIs.WebApplication)this.Core.GetIndexedElement(row);
-
-                    if (!addedWebApplications.Contains(webApplication))
-                    {
-                        this.Core.RootElement.AddChild(webApplication);
-                    }
-                }
-            }
-        }
-
-        /// <summary>
-        /// Finalize the IIsWebError table.
-        /// </summary>
-        /// <param name="tables">The collection of all tables.</param>
-        /// <remarks>
-        /// Since there is no foreign key relationship declared for this table
-        /// (because it takes various parent types), it must be nested late.
-        /// </remarks>
-        private void FinalizeIIsWebErrorTable(TableIndexedCollection tables)
-        {
-            Table iisWebErrorTable = tables["IIsWebError"];
-
-            if (null != iisWebErrorTable)
-            {
-                foreach (Row row in iisWebErrorTable.Rows)
-                {
-                    IIs.WebError webError = (IIs.WebError)this.Core.GetIndexedElement(row);
-
-                    if (1 == (int)row[2]) // WebVirtualDir parent
-                    {
-                        IIs.WebVirtualDir webVirtualDir = (IIs.WebVirtualDir)this.Core.GetIndexedElement("IIsWebVirtualDir", (string)row[3]);
-
-                        if (null != webVirtualDir)
-                        {
-                            webVirtualDir.AddChild(webError);
-                        }
-                        else
-                        {
-                            this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebErrorTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ParentValue", (string)row[3], "IIsWebVirtualDir"));
-                        }
-                    }
-                    else if (2 == (int)row[2]) // WebSite parent
-                    {
-                        IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement("IIsWebSite", (string)row[3]);
-
-                        if (null != webSite)
-                        {
-                            webSite.AddChild(webError);
-                        }
-                        else
-                        {
-                            this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebErrorTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ParentValue", (string)row[3], "IIsWebSite"));
-                        }
-                    }
-                    else
-                    {
-                        // TODO: warn unknown parent type
-                    }
-                }
-            }
-        }
-
-        /// <summary>
-        /// Finalize the IIsWebVirtualDir table.
-        /// </summary>
-        /// <param name="tables">The collection of all tables.</param>
-        /// <remarks>
-        /// WebVirtualDir elements nest under either a WebSite or component
-        /// depending upon whether the component in the IIsWebVirtualDir row
-        /// is the same as the one in the parent IIsWebSite row.
-        /// </remarks>
-        private void FinalizeIIsWebVirtualDirTable(TableIndexedCollection tables)
-        {
-            Table iisWebSiteTable = tables["IIsWebSite"];
-            Table iisWebVirtualDirTable = tables["IIsWebVirtualDir"];
-
-            Hashtable iisWebSiteRows = new Hashtable();
-
-            // index the IIsWebSite rows by their primary keys
-            if (null != iisWebSiteTable)
-            {
-                foreach (Row row in iisWebSiteTable.Rows)
-                {
-                    iisWebSiteRows.Add(row[0], row);
-                }
-            }
-
-            if (null != iisWebVirtualDirTable)
-            {
-                foreach (Row row in iisWebVirtualDirTable.Rows)
-                {
-                    IIs.WebVirtualDir webVirtualDir = (IIs.WebVirtualDir)this.Core.GetIndexedElement(row);
-                    Row iisWebSiteRow = (Row)iisWebSiteRows[row[2]];
-
-                    if (null != iisWebSiteRow)
-                    {
-                        if ((string)iisWebSiteRow[1] == (string)row[1])
-                        {
-                            IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement(iisWebSiteRow);
-
-                            webSite.AddChild(webVirtualDir);
-                        }
-                        else
-                        {
-                            Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
-
-                            if (null != component)
-                            {
-                                webVirtualDir.WebSite = (string)row[2];
-                                component.AddChild(webVirtualDir);
-                            }
-                            else
-                            {
-                                this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebVirtualDirTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
-                            }
-                        }
-                    }
-                    else
-                    {
-                        this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebVirtualDirTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Web_", (string)row[2], "IIsWebSite"));
-                    }
-                }
-            }
-        }
-
-        /// <summary>
-        /// Finalize the IIsWebSiteCertificates table.
-        /// </summary>
-        /// <param name="tables">The collection of all tables.</param>
-        /// <remarks>
-        /// This table creates CertificateRef elements which nest under WebSite
-        /// elements.
-        /// </remarks>
-        private void FinalizeIIsWebSiteCertificatesTable(TableIndexedCollection tables)
-        {
-            Table IIsWebSiteCertificatesTable = tables["IIsWebSiteCertificates"];
-
-            if (null != IIsWebSiteCertificatesTable)
-            {
-                foreach (Row row in IIsWebSiteCertificatesTable.Rows)
-                {
-                    IIs.CertificateRef certificateRef = (IIs.CertificateRef)this.Core.GetIndexedElement(row);
-                    IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement("IIsWebSite", (string)row[0]);
-
-                    if (null != webSite)
-                    {
-                        webSite.AddChild(certificateRef);
-                    }
-                    else
-                    {
-                        this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, IIsWebSiteCertificatesTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Web_", (string)row[0], "IIsWebSite"));
-                    }
-                }
-            }
-        }
-
-        /// <summary>
-        /// Finalize the WebAddress table.
-        /// </summary>
-        /// <param name="tables">The collection of all tables.</param>
-        /// <remarks>
-        /// There is a circular dependency between the WebAddress and WebSite
-        /// tables, so nesting must be handled here.
-        /// </remarks>
-        private void FinalizeWebAddressTable(TableIndexedCollection tables)
-        {
-            Table iisWebAddressTable = tables["IIsWebAddress"];
-            Table iisWebSiteTable = tables["IIsWebSite"];
-
-            Hashtable addedWebAddresses = new Hashtable();
-
-            if (null != iisWebSiteTable)
-            {
-                foreach (Row row in iisWebSiteTable.Rows)
-                {
-                    IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement(row);
-
-                    IIs.WebAddress webAddress = (IIs.WebAddress)this.Core.GetIndexedElement("IIsWebAddress", (string)row[7]);
-                    if (null != webAddress)
-                    {
-                        webSite.AddChild(webAddress);
-                        addedWebAddresses[webAddress] = null;
-                    }
-                    else
-                    {
-                        this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebSiteTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "KeyAddress_", (string)row[7], "IIsWebAddress"));
-                    }
-                }
-            }
-
-            if (null != iisWebAddressTable)
-            {
-                foreach (Row row in iisWebAddressTable.Rows)
-                {
-                    IIs.WebAddress webAddress = (IIs.WebAddress)this.Core.GetIndexedElement(row);
-
-                    if (!addedWebAddresses.Contains(webAddress))
-                    {
-                        IIs.WebSite webSite = (IIs.WebSite)this.Core.GetIndexedElement("IIsWebSite", (string)row[1]);
-
-                        if (null != webSite)
-                        {
-                            webSite.AddChild(webAddress);
-                        }
-                        else
-                        {
-                            this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, iisWebAddressTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Web_", (string)row[1], "IIsWebSite"));
-                        }
-                    }
-                }
-            }
-        }
-    }
-#endif
-}
diff --git a/src/wixext/IIsExtensionData.cs b/src/wixext/IIsExtensionData.cs
deleted file mode 100644
index 6a0e1f09..00000000
--- a/src/wixext/IIsExtensionData.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Extensibility;
-
-    /// <summary>
-    /// The WiX Toolset Internet Information Services Extension.
-    /// </summary>
-    public sealed class IIsExtensionData : BaseExtensionData
-    {
-        /// <summary>
-        /// Gets the default culture.
-        /// </summary>
-        /// <value>The default culture.</value>
-        public override string DefaultCulture => "en-US";
-
-        public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
-        {
-            symbolDefinition = IisSymbolDefinitions.ByName(name);
-            return symbolDefinition != null;
-        }
-
-        public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions)
-        {
-            return Intermediate.Load(typeof(IIsExtensionData).Assembly, "WixToolset.Iis.iis.wixlib", symbolDefinitions);
-        }
-    }
-}
diff --git a/src/wixext/IisErrors.cs b/src/wixext/IisErrors.cs
deleted file mode 100644
index 2f226217..00000000
--- a/src/wixext/IisErrors.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-// 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.
-
-namespace WixToolset.Data
-{
-    using System;
-    using System.Resources;
-
-    public static class IIsErrors
-    {
-        public static Message DeprecatedBinaryChildElement(SourceLineNumber sourceLineNumbers, string elementName)
-        {
-            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);
-        }
-
-        public static Message IllegalAttributeWithoutComponent(SourceLineNumber sourceLineNumbers, string elementName, string attributeName)
-        {
-            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);
-        }
-
-        public static Message IllegalCharacterInAttributeValue(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string value, Char illegalCharacter)
-        {
-            return Message(sourceLineNumbers, Ids.IllegalCharacterInAttributeValue, "The {0}/@{1} attribute's value, '{2}', is invalid.  It cannot contain the character '{3}'.", elementName, attributeName, value, illegalCharacter);
-        }
-
-        public static Message IllegalElementWithoutComponent(SourceLineNumber sourceLineNumbers, string elementName)
-        {
-            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);
-        }
-
-        public static Message MimeMapExtensionMissingPeriod(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string attributeValue)
-        {
-            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);
-        }
-
-        public static Message OneOfAttributesRequiredUnderComponent(SourceLineNumber sourceLineNumbers, string elementName, string attributeName1, string attributeName2, string attributeName3, string attributeName4)
-        {
-            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);
-        }
-
-        public static Message RequiredAttributeUnderComponent(SourceLineNumber sourceLineNumbers, string elementName, string attributeName)
-        {
-            return Message(sourceLineNumbers, Ids.RequiredAttributeUnderComponent, "The {0}/@{1} attribute must be specified when the element has a Component as an ancestor.", elementName, attributeName);
-        }
-
-        public static Message WebApplicationAlreadySpecified(SourceLineNumber sourceLineNumbers, string elementName)
-        {
-            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);
-        }
-
-        public static Message WebSiteAttributeUnderWebSite(SourceLineNumber sourceLineNumbers, string elementName)
-        {
-            return Message(sourceLineNumbers, Ids.WebSiteAttributeUnderWebSite, "The {0}/@WebSite attribute cannot be specified when the {0} element is nested under a WebSite element.", elementName);
-        }
-
-        private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args)
-        {
-            return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args);
-        }
-
-        private static Message Message(SourceLineNumber sourceLineNumber, Ids id, ResourceManager resourceManager, string resourceName, params object[] args)
-        {
-            return new Message(sourceLineNumber, MessageLevel.Error, (int)id, resourceManager, resourceName, args);
-        }
-
-        public enum Ids
-        {
-            MimeMapExtensionMissingPeriod = 5150,
-            IllegalAttributeWithoutComponent = 5151,
-            IllegalElementWithoutComponent = 5152,
-            OneOfAttributesRequiredUnderComponent = 5153,
-            WebSiteAttributeUnderWebSite = 5154,
-            WebApplicationAlreadySpecified = 5155,
-            IllegalCharacterInAttributeValue = 5156,
-            DeprecatedBinaryChildElement = 5157,
-            RequiredAttributeUnderComponent = 5161,
-        }
-    }
-}
diff --git a/src/wixext/IisExtensionFactory.cs b/src/wixext/IisExtensionFactory.cs
deleted file mode 100644
index 2fb7e682..00000000
--- a/src/wixext/IisExtensionFactory.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using System;
-    using System.Collections.Generic;
-    using WixToolset.Extensibility;
-
-    public class IisExtensionFactory : BaseExtensionFactory
-    {
-        protected override IReadOnlyCollection<Type> ExtensionTypes => new[]
-        {
-            typeof(IIsCompiler),
-            typeof(IIsExtensionData),
-            typeof(IisWindowsInstallerBackendBinderExtension),
-        };
-    }
-}
diff --git a/src/wixext/IisTableDefinitions.cs b/src/wixext/IisTableDefinitions.cs
deleted file mode 100644
index f513152e..00000000
--- a/src/wixext/IisTableDefinitions.cs
+++ /dev/null
@@ -1,324 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data.WindowsInstaller;
-
-    public static class IisTableDefinitions
-    {
-        public static readonly TableDefinition Certificate = new TableDefinition(
-            "Certificate",
-            IisSymbolDefinitions.Certificate,
-            new[]
-            {
-                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),
-                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),
-                new ColumnDefinition("Name", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Name to be used for the Certificate."),
-                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)"),
-                new ColumnDefinition("StoreName", ColumnType.String, 64, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Name of the target certificate store"),
-                new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 2147483647, description: "Attributes of the certificate"),
-                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),
-                new ColumnDefinition("CertificatePath", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Property to path of certificate.", modularizeType: ColumnModularizeType.Property),
-                new ColumnDefinition("PFXPassword", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Hidden property to a pfx password", modularizeType: ColumnModularizeType.Property),
-            },
-            symbolIdIsPrimaryKey: true
-        );
-
-        public static readonly TableDefinition CertificateHash = new TableDefinition(
-            "CertificateHash",
-            IisSymbolDefinitions.CertificateHash,
-            new[]
-            {
-                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),
-                new ColumnDefinition("Hash", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Base64 encoded SHA1 hash of certificate populated at run-time."),
-            },
-            symbolIdIsPrimaryKey: false
-        );
-
-        public static readonly TableDefinition IIsWebSiteCertificates = new TableDefinition(
-            "IIsWebSiteCertificates",
-            IisSymbolDefinitions.IIsWebSiteCertificates,
-            new[]
-            {
-                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),
-                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),
-            },
-            symbolIdIsPrimaryKey: false
-        );
-
-        public static readonly TableDefinition IIsAppPool = new TableDefinition(
-            "IIsAppPool",
-            IisSymbolDefinitions.IIsAppPool,
-            new[]
-            {
-                new ColumnDefinition("AppPool", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token for apppool", modularizeType: ColumnModularizeType.Column),
-                new ColumnDefinition("Name", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Name to be used for the IIs AppPool.", modularizeType: ColumnModularizeType.Property),
-                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),
-                new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, description: "Attributes of the AppPool"),
-                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),
-                new ColumnDefinition("RecycleMinutes", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Number of minutes between recycling app pool"),
-                new ColumnDefinition("RecycleRequests", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Number of requests between recycling app pool"),
-                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)"),
-                new ColumnDefinition("IdleTimeout", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Amount of idle time before shutting down"),
-                new ColumnDefinition("QueueLimit", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Reject requests after queue gets how large"),
-                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)."),
-                new ColumnDefinition("MaxProc", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Maximum number of processes to use"),
-                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."),
-                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."),
-                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."),
-                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."),
-            },
-            symbolIdIsPrimaryKey: true
-        );
-
-        public static readonly TableDefinition IIsMimeMap = new TableDefinition(
-            "IIsMimeMap",
-            IisSymbolDefinitions.IIsMimeMap,
-            new[]
-            {
-                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),
-                new ColumnDefinition("ParentType", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, possibilities: "1;2", description: "Type of parent: 1=vdir 2=website"),
-                new ColumnDefinition("ParentValue", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, description: "Name of the parent value.", modularizeType: ColumnModularizeType.Column),
-                new ColumnDefinition("MimeType", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Mime-type covered by the MimeMap."),
-                new ColumnDefinition("Extension", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Extension covered by the MimeMap."),
-            },
-            symbolIdIsPrimaryKey: true
-        );
-
-        public static readonly TableDefinition IIsProperty = new TableDefinition(
-            "IIsProperty",
-            IisSymbolDefinitions.IIsProperty,
-            new[]
-            {
-                new ColumnDefinition("Property", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Unique name of the IIsProperty"),
-                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),
-                new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, description: "Attributes of the IIsProperty (unused)"),
-                new ColumnDefinition("Value", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Value of the IIsProperty"),
-            },
-            symbolIdIsPrimaryKey: true
-        );
-
-        public static readonly TableDefinition IIsWebDirProperties = new TableDefinition(
-            "IIsWebDirProperties",
-            IisSymbolDefinitions.IIsWebDirProperties,
-            new[]
-            {
-                new ColumnDefinition("DirProperties", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token for Web Properties", modularizeType: ColumnModularizeType.Column),
-                new ColumnDefinition("Access", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Access rights to the web server"),
-                new ColumnDefinition("Authorization", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Authorization policy to web server (anonymous access, NTLM, etc)"),
-                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),
-                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"),
-                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"),
-                new ColumnDefinition("Index", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "Specifies whether IIs searches the directory"),
-                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"),
-                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"),
-                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"),
-                new ColumnDefinition("CacheControlMaxAge", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Integer value specifying the cache control maximum age value."),
-                new ColumnDefinition("CacheControlCustom", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Custom HTTP 1.1 cache control directives."),
-                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."),
-                new ColumnDefinition("AccessSSLFlags", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Specifies AccessSSLFlags IIS metabase property."),
-                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."),
-            },
-            symbolIdIsPrimaryKey: true
-        );
-
-        public static readonly TableDefinition IIsWebAddress = new TableDefinition(
-            "IIsWebAddress",
-            IisSymbolDefinitions.IIsWebAddress,
-            new[]
-            {
-                new ColumnDefinition("Address", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
-                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),
-                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),
-                new ColumnDefinition("Port", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Port web site listens on", modularizeType: ColumnModularizeType.Property),
-                new ColumnDefinition("Header", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Special header information for the web site"),
-                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"),
-            },
-            symbolIdIsPrimaryKey: true
-        );
-
-        public static readonly TableDefinition IIsWebSite = new TableDefinition(
-            "IIsWebSite",
-            IisSymbolDefinitions.IIsWebSite,
-            new[]
-            {
-                new ColumnDefinition("Web", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
-                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),
-                new ColumnDefinition("Description", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Description displayed in IIS MMC applet"),
-                new ColumnDefinition("ConnectionTimeout", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Time connection is maintained without activity (in seconds)"),
-                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),
-                new ColumnDefinition("State", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1;2", description: "Sets intial state of web site"),
-                new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "2", description: "Control the install behavior of web site"),
-                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),
-                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),
-                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),
-                new ColumnDefinition("Sequence", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Allows ordering of web site install"),
-                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),
-                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."),
-            },
-            symbolIdIsPrimaryKey: true
-        );
-
-        public static readonly TableDefinition IIsWebApplication = new TableDefinition(
-            "IIsWebApplication",
-            IisSymbolDefinitions.IIsWebApplication,
-            new[]
-            {
-                new ColumnDefinition("Application", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token for ASP Application", modularizeType: ColumnModularizeType.Column),
-                new ColumnDefinition("Name", ColumnType.Localized, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Name of application in IIS MMC applet", modularizeType: ColumnModularizeType.Property),
-                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"),
-                new ColumnDefinition("AllowSessions", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "Specifies whether application may maintain session state"),
-                new ColumnDefinition("SessionTimeout", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Time session state is maintained without user interaction"),
-                new ColumnDefinition("Buffer", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "Specifies whether application buffers its output"),
-                new ColumnDefinition("ParentPaths", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, possibilities: "0;1", description: "What is this for anyway?"),
-                new ColumnDefinition("DefaultScript", ColumnType.String, 26, primaryKey: false, nullable: true, ColumnCategory.Text, possibilities: "VBScript;JScript", description: "Default scripting language for ASP applications"),
-                new ColumnDefinition("ScriptTimeout", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Time ASP application page is permitted to process"),
-                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"),
-                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"),
-                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),
-            },
-            symbolIdIsPrimaryKey: true
-        );
-
-        public static readonly TableDefinition IIsWebApplicationExtension = new TableDefinition(
-            "IIsWebApplicationExtension",
-            IisSymbolDefinitions.IIsWebApplicationExtension,
-            new[]
-            {
-                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),
-                new ColumnDefinition("Extension", ColumnType.String, 255, primaryKey: true, nullable: true, ColumnCategory.Text, description: "Primary key, Extension that should be registered for this ASP application"),
-                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"),
-                new ColumnDefinition("Executable", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Path to extension (usually file property: [#file])", modularizeType: ColumnModularizeType.Property),
-                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"),
-            },
-            symbolIdIsPrimaryKey: false
-        );
-
-        public static readonly TableDefinition IIsFilter = new TableDefinition(
-            "IIsFilter",
-            IisSymbolDefinitions.IIsFilter,
-            new[]
-            {
-                new ColumnDefinition("Filter", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
-                new ColumnDefinition("Name", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Unknown, description: "Name of the ISAPI Filter in IIS"),
-                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),
-                new ColumnDefinition("Path", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Path to filter (usually file property: [#file])", modularizeType: ColumnModularizeType.Property),
-                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),
-                new ColumnDefinition("Description", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Description displayed in IIS MMC applet"),
-                new ColumnDefinition("Flags", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 2147483647, description: "What do all these numbers mean?"),
-                new ColumnDefinition("LoadOrder", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "-1 == last in order, 0 == first in order, # == place in order"),
-            },
-            symbolIdIsPrimaryKey: true
-        );
-
-        public static readonly TableDefinition IIsWebDir = new TableDefinition(
-            "IIsWebDir",
-            IisSymbolDefinitions.IIsWebDir,
-            new[]
-            {
-                new ColumnDefinition("WebDir", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
-                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),
-                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),
-                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),
-                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),
-                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),
-            },
-            symbolIdIsPrimaryKey: true
-        );
-
-        public static readonly TableDefinition IIsWebError = new TableDefinition(
-            "IIsWebError",
-            IisSymbolDefinitions.IIsWebError,
-            new[]
-            {
-                new ColumnDefinition("ErrorCode", ColumnType.Number, 2, primaryKey: true, nullable: false, ColumnCategory.Unknown, minValue: 400, maxValue: 599, description: "HTTP status code indicating error."),
-                new ColumnDefinition("SubCode", ColumnType.Number, 4, primaryKey: true, nullable: false, ColumnCategory.Unknown, description: "HTTP sub-status code indicating error."),
-                new ColumnDefinition("ParentType", ColumnType.Number, 2, primaryKey: true, nullable: false, ColumnCategory.Unknown, possibilities: "1;2", description: "Type of parent: 1=vdir, 2=web"),
-                new ColumnDefinition("ParentValue", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Name of the parent value.", modularizeType: ColumnModularizeType.Column),
-                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."),
-                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."),
-            },
-            symbolIdIsPrimaryKey: false
-        );
-
-        public static readonly TableDefinition IIsHttpHeader = new TableDefinition(
-            "IIsHttpHeader",
-            IisSymbolDefinitions.IIsHttpHeader,
-            new[]
-            {
-                new ColumnDefinition("HttpHeader", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
-                new ColumnDefinition("ParentType", ColumnType.Number, 2, primaryKey: true, nullable: false, ColumnCategory.Unknown, possibilities: "1;2", description: "Type of parent: 1=vdir, 2=web"),
-                new ColumnDefinition("ParentValue", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Name of the parent value.", modularizeType: ColumnModularizeType.Column),
-                new ColumnDefinition("Name", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Name of the HTTP Header"),
-                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."),
-                new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 0, description: "Attributes for HTTP Header: none"),
-                new ColumnDefinition("Sequence", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Order to add the HTTP Headers."),
-            },
-            symbolIdIsPrimaryKey: false
-        );
-
-        public static readonly TableDefinition IIsWebServiceExtension = new TableDefinition(
-            "IIsWebServiceExtension",
-            IisSymbolDefinitions.IIsWebServiceExtension,
-            new[]
-            {
-                new ColumnDefinition("WebServiceExtension", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
-                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),
-                new ColumnDefinition("File", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Path to handler (usually file property: [#file])", modularizeType: ColumnModularizeType.Property),
-                new ColumnDefinition("Description", ColumnType.Localized, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Description displayed in WebServiceExtension Wizard", modularizeType: ColumnModularizeType.Property),
-                new ColumnDefinition("Group", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "String used to identify groups of extensions.", modularizeType: ColumnModularizeType.Property),
-                new ColumnDefinition("Attributes", ColumnType.Number, 1, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 3, description: "Attributes for WebServiceExtension: 1 = Allow, 2 = UIDeletable"),
-            },
-            symbolIdIsPrimaryKey: true
-        );
-
-        public static readonly TableDefinition IIsWebVirtualDir = new TableDefinition(
-            "IIsWebVirtualDir",
-            IisSymbolDefinitions.IIsWebVirtualDir,
-            new[]
-            {
-                new ColumnDefinition("VirtualDir", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
-                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),
-                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),
-                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),
-                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),
-                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),
-                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),
-            },
-            symbolIdIsPrimaryKey: true
-        );
-
-        public static readonly TableDefinition IIsWebLog = new TableDefinition(
-            "IIsWebLog",
-            IisSymbolDefinitions.IIsWebLog,
-            new[]
-            {
-                new ColumnDefinition("Log", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
-                new ColumnDefinition("Format", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Type of log format"),
-            },
-            symbolIdIsPrimaryKey: true
-        );
-
-        public static readonly TableDefinition[] All = new[]
-        {
-            Certificate,
-            CertificateHash,
-            IIsWebSiteCertificates,
-            IIsAppPool,
-            IIsMimeMap,
-            IIsProperty,
-            IIsWebDirProperties,
-            IIsWebAddress,
-            IIsWebSite,
-            IIsWebApplication,
-            IIsWebApplicationExtension,
-            IIsFilter,
-            IIsWebDir,
-            IIsWebError,
-            IIsHttpHeader,
-            IIsWebServiceExtension,
-            IIsWebVirtualDir,
-            IIsWebLog,
-        };
-    }
-}
diff --git a/src/wixext/IisWindowsInstallerBackendBinderExtension.cs b/src/wixext/IisWindowsInstallerBackendBinderExtension.cs
deleted file mode 100644
index a61cbad6..00000000
--- a/src/wixext/IisWindowsInstallerBackendBinderExtension.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using System.Collections.Generic;
-    using WixToolset.Data.WindowsInstaller;
-    using WixToolset.Extensibility;
-
-    public class IisWindowsInstallerBackendBinderExtension : BaseWindowsInstallerBackendBinderExtension
-    {
-        public override IReadOnlyCollection<TableDefinition> TableDefinitions => IisTableDefinitions.All;
-    }
-}
diff --git a/src/wixext/Symbols/CertificateHashSymbol.cs b/src/wixext/Symbols/CertificateHashSymbol.cs
deleted file mode 100644
index 866d474c..00000000
--- a/src/wixext/Symbols/CertificateHashSymbol.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Iis.Symbols;
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly IntermediateSymbolDefinition CertificateHash = new IntermediateSymbolDefinition(
-            IisSymbolDefinitionType.CertificateHash.ToString(),
-            new[]
-            {
-                new IntermediateFieldDefinition(nameof(CertificateHashSymbolFields.CertificateRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(CertificateHashSymbolFields.Hash), IntermediateFieldType.String),
-            },
-            typeof(CertificateHashSymbol));
-    }
-}
-
-namespace WixToolset.Iis.Symbols
-{
-    using WixToolset.Data;
-
-    public enum CertificateHashSymbolFields
-    {
-        CertificateRef,
-        Hash,
-    }
-
-    public class CertificateHashSymbol : IntermediateSymbol
-    {
-        public CertificateHashSymbol() : base(IisSymbolDefinitions.CertificateHash, null, null)
-        {
-        }
-
-        public CertificateHashSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.CertificateHash, sourceLineNumber, id)
-        {
-        }
-
-        public IntermediateField this[CertificateHashSymbolFields index] => this.Fields[(int)index];
-
-        public string CertificateRef
-        {
-            get => this.Fields[(int)CertificateHashSymbolFields.CertificateRef].AsString();
-            set => this.Set((int)CertificateHashSymbolFields.CertificateRef, value);
-        }
-
-        public string Hash
-        {
-            get => this.Fields[(int)CertificateHashSymbolFields.Hash].AsString();
-            set => this.Set((int)CertificateHashSymbolFields.Hash, value);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/wixext/Symbols/CertificateSymbol.cs b/src/wixext/Symbols/CertificateSymbol.cs
deleted file mode 100644
index b80b6ba4..00000000
--- a/src/wixext/Symbols/CertificateSymbol.cs
+++ /dev/null
@@ -1,103 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Iis.Symbols;
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly IntermediateSymbolDefinition Certificate = new IntermediateSymbolDefinition(
-            IisSymbolDefinitionType.Certificate.ToString(),
-            new[]
-            {
-                new IntermediateFieldDefinition(nameof(CertificateSymbolFields.ComponentRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(CertificateSymbolFields.Name), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(CertificateSymbolFields.StoreLocation), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(CertificateSymbolFields.StoreName), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(CertificateSymbolFields.Attributes), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(CertificateSymbolFields.BinaryRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(CertificateSymbolFields.CertificatePath), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(CertificateSymbolFields.PFXPassword), IntermediateFieldType.String),
-            },
-            typeof(CertificateSymbol));
-    }
-}
-
-namespace WixToolset.Iis.Symbols
-{
-    using WixToolset.Data;
-
-    public enum CertificateSymbolFields
-    {
-        ComponentRef,
-        Name,
-        StoreLocation,
-        StoreName,
-        Attributes,
-        BinaryRef,
-        CertificatePath,
-        PFXPassword,
-    }
-
-    public class CertificateSymbol : IntermediateSymbol
-    {
-        public CertificateSymbol() : base(IisSymbolDefinitions.Certificate, null, null)
-        {
-        }
-
-        public CertificateSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.Certificate, sourceLineNumber, id)
-        {
-        }
-
-        public IntermediateField this[CertificateSymbolFields index] => this.Fields[(int)index];
-
-        public string ComponentRef
-        {
-            get => this.Fields[(int)CertificateSymbolFields.ComponentRef].AsString();
-            set => this.Set((int)CertificateSymbolFields.ComponentRef, value);
-        }
-
-        public string Name
-        {
-            get => this.Fields[(int)CertificateSymbolFields.Name].AsString();
-            set => this.Set((int)CertificateSymbolFields.Name, value);
-        }
-
-        public int StoreLocation
-        {
-            get => this.Fields[(int)CertificateSymbolFields.StoreLocation].AsNumber();
-            set => this.Set((int)CertificateSymbolFields.StoreLocation, value);
-        }
-
-        public string StoreName
-        {
-            get => this.Fields[(int)CertificateSymbolFields.StoreName].AsString();
-            set => this.Set((int)CertificateSymbolFields.StoreName, value);
-        }
-
-        public int Attributes
-        {
-            get => this.Fields[(int)CertificateSymbolFields.Attributes].AsNumber();
-            set => this.Set((int)CertificateSymbolFields.Attributes, value);
-        }
-
-        public string BinaryRef
-        {
-            get => this.Fields[(int)CertificateSymbolFields.BinaryRef].AsString();
-            set => this.Set((int)CertificateSymbolFields.BinaryRef, value);
-        }
-
-        public string CertificatePath
-        {
-            get => this.Fields[(int)CertificateSymbolFields.CertificatePath].AsString();
-            set => this.Set((int)CertificateSymbolFields.CertificatePath, value);
-        }
-
-        public string PFXPassword
-        {
-            get => this.Fields[(int)CertificateSymbolFields.PFXPassword].AsString();
-            set => this.Set((int)CertificateSymbolFields.PFXPassword, value);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/wixext/Symbols/IIsAppPoolSymbol.cs b/src/wixext/Symbols/IIsAppPoolSymbol.cs
deleted file mode 100644
index a6fab136..00000000
--- a/src/wixext/Symbols/IIsAppPoolSymbol.cs
+++ /dev/null
@@ -1,159 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Iis.Symbols;
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly IntermediateSymbolDefinition IIsAppPool = new IntermediateSymbolDefinition(
-            IisSymbolDefinitionType.IIsAppPool.ToString(),
-            new[]
-            {
-                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.Name), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.ComponentRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.Attributes), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.UserRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.RecycleMinutes), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.RecycleRequests), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.RecycleTimes), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.IdleTimeout), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.QueueLimit), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.CPUMon), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.MaxProc), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.VirtualMemory), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.PrivateMemory), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.ManagedRuntimeVersion), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsAppPoolSymbolFields.ManagedPipelineMode), IntermediateFieldType.String),
-            },
-            typeof(IIsAppPoolSymbol));
-    }
-}
-
-namespace WixToolset.Iis.Symbols
-{
-    using WixToolset.Data;
-
-    public enum IIsAppPoolSymbolFields
-    {
-        Name,
-        ComponentRef,
-        Attributes,
-        UserRef,
-        RecycleMinutes,
-        RecycleRequests,
-        RecycleTimes,
-        IdleTimeout,
-        QueueLimit,
-        CPUMon,
-        MaxProc,
-        VirtualMemory,
-        PrivateMemory,
-        ManagedRuntimeVersion,
-        ManagedPipelineMode,
-    }
-
-    public class IIsAppPoolSymbol : IntermediateSymbol
-    {
-        public IIsAppPoolSymbol() : base(IisSymbolDefinitions.IIsAppPool, null, null)
-        {
-        }
-
-        public IIsAppPoolSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsAppPool, sourceLineNumber, id)
-        {
-        }
-
-        public IntermediateField this[IIsAppPoolSymbolFields index] => this.Fields[(int)index];
-
-        public string Name
-        {
-            get => this.Fields[(int)IIsAppPoolSymbolFields.Name].AsString();
-            set => this.Set((int)IIsAppPoolSymbolFields.Name, value);
-        }
-
-        public string ComponentRef
-        {
-            get => this.Fields[(int)IIsAppPoolSymbolFields.ComponentRef].AsString();
-            set => this.Set((int)IIsAppPoolSymbolFields.ComponentRef, value);
-        }
-
-        public int Attributes
-        {
-            get => this.Fields[(int)IIsAppPoolSymbolFields.Attributes].AsNumber();
-            set => this.Set((int)IIsAppPoolSymbolFields.Attributes, value);
-        }
-
-        public string UserRef
-        {
-            get => this.Fields[(int)IIsAppPoolSymbolFields.UserRef].AsString();
-            set => this.Set((int)IIsAppPoolSymbolFields.UserRef, value);
-        }
-
-        public int? RecycleMinutes
-        {
-            get => this.Fields[(int)IIsAppPoolSymbolFields.RecycleMinutes].AsNullableNumber();
-            set => this.Set((int)IIsAppPoolSymbolFields.RecycleMinutes, value);
-        }
-
-        public int? RecycleRequests
-        {
-            get => this.Fields[(int)IIsAppPoolSymbolFields.RecycleRequests].AsNullableNumber();
-            set => this.Set((int)IIsAppPoolSymbolFields.RecycleRequests, value);
-        }
-
-        public string RecycleTimes
-        {
-            get => this.Fields[(int)IIsAppPoolSymbolFields.RecycleTimes].AsString();
-            set => this.Set((int)IIsAppPoolSymbolFields.RecycleTimes, value);
-        }
-
-        public int? IdleTimeout
-        {
-            get => this.Fields[(int)IIsAppPoolSymbolFields.IdleTimeout].AsNullableNumber();
-            set => this.Set((int)IIsAppPoolSymbolFields.IdleTimeout, value);
-        }
-
-        public int? QueueLimit
-        {
-            get => this.Fields[(int)IIsAppPoolSymbolFields.QueueLimit].AsNullableNumber();
-            set => this.Set((int)IIsAppPoolSymbolFields.QueueLimit, value);
-        }
-
-        public string CPUMon
-        {
-            get => this.Fields[(int)IIsAppPoolSymbolFields.CPUMon].AsString();
-            set => this.Set((int)IIsAppPoolSymbolFields.CPUMon, value);
-        }
-
-        public int? MaxProc
-        {
-            get => this.Fields[(int)IIsAppPoolSymbolFields.MaxProc].AsNullableNumber();
-            set => this.Set((int)IIsAppPoolSymbolFields.MaxProc, value);
-        }
-
-        public int? VirtualMemory
-        {
-            get => this.Fields[(int)IIsAppPoolSymbolFields.VirtualMemory].AsNullableNumber();
-            set => this.Set((int)IIsAppPoolSymbolFields.VirtualMemory, value);
-        }
-
-        public int? PrivateMemory
-        {
-            get => this.Fields[(int)IIsAppPoolSymbolFields.PrivateMemory].AsNullableNumber();
-            set => this.Set((int)IIsAppPoolSymbolFields.PrivateMemory, value);
-        }
-
-        public string ManagedRuntimeVersion
-        {
-            get => this.Fields[(int)IIsAppPoolSymbolFields.ManagedRuntimeVersion].AsString();
-            set => this.Set((int)IIsAppPoolSymbolFields.ManagedRuntimeVersion, value);
-        }
-
-        public string ManagedPipelineMode
-        {
-            get => this.Fields[(int)IIsAppPoolSymbolFields.ManagedPipelineMode].AsString();
-            set => this.Set((int)IIsAppPoolSymbolFields.ManagedPipelineMode, value);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/wixext/Symbols/IIsFilterSymbol.cs b/src/wixext/Symbols/IIsFilterSymbol.cs
deleted file mode 100644
index 618730bf..00000000
--- a/src/wixext/Symbols/IIsFilterSymbol.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Iis.Symbols;
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly IntermediateSymbolDefinition IIsFilter = new IntermediateSymbolDefinition(
-            IisSymbolDefinitionType.IIsFilter.ToString(),
-            new[]
-            {
-                new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.Name), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.ComponentRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.Path), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.WebRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.Description), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.Flags), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsFilterSymbolFields.LoadOrder), IntermediateFieldType.Number),
-            },
-            typeof(IIsFilterSymbol));
-    }
-}
-
-namespace WixToolset.Iis.Symbols
-{
-    using WixToolset.Data;
-
-    public enum IIsFilterSymbolFields
-    {
-        Name,
-        ComponentRef,
-        Path,
-        WebRef,
-        Description,
-        Flags,
-        LoadOrder,
-    }
-
-    public class IIsFilterSymbol : IntermediateSymbol
-    {
-        public IIsFilterSymbol() : base(IisSymbolDefinitions.IIsFilter, null, null)
-        {
-        }
-
-        public IIsFilterSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsFilter, sourceLineNumber, id)
-        {
-        }
-
-        public IntermediateField this[IIsFilterSymbolFields index] => this.Fields[(int)index];
-
-        public string Name
-        {
-            get => this.Fields[(int)IIsFilterSymbolFields.Name].AsString();
-            set => this.Set((int)IIsFilterSymbolFields.Name, value);
-        }
-
-        public string ComponentRef
-        {
-            get => this.Fields[(int)IIsFilterSymbolFields.ComponentRef].AsString();
-            set => this.Set((int)IIsFilterSymbolFields.ComponentRef, value);
-        }
-
-        public string Path
-        {
-            get => this.Fields[(int)IIsFilterSymbolFields.Path].AsString();
-            set => this.Set((int)IIsFilterSymbolFields.Path, value);
-        }
-
-        public string WebRef
-        {
-            get => this.Fields[(int)IIsFilterSymbolFields.WebRef].AsString();
-            set => this.Set((int)IIsFilterSymbolFields.WebRef, value);
-        }
-
-        public string Description
-        {
-            get => this.Fields[(int)IIsFilterSymbolFields.Description].AsString();
-            set => this.Set((int)IIsFilterSymbolFields.Description, value);
-        }
-
-        public int Flags
-        {
-            get => this.Fields[(int)IIsFilterSymbolFields.Flags].AsNumber();
-            set => this.Set((int)IIsFilterSymbolFields.Flags, value);
-        }
-
-        public int? LoadOrder
-        {
-            get => this.Fields[(int)IIsFilterSymbolFields.LoadOrder].AsNullableNumber();
-            set => this.Set((int)IIsFilterSymbolFields.LoadOrder, value);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/wixext/Symbols/IIsHttpHeaderSymbol.cs b/src/wixext/Symbols/IIsHttpHeaderSymbol.cs
deleted file mode 100644
index 3ab2bf59..00000000
--- a/src/wixext/Symbols/IIsHttpHeaderSymbol.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Iis.Symbols;
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly IntermediateSymbolDefinition IIsHttpHeader = new IntermediateSymbolDefinition(
-            IisSymbolDefinitionType.IIsHttpHeader.ToString(),
-            new[]
-            {
-                new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.HttpHeader), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.ParentType), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.ParentValue), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.Name), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.Value), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.Attributes), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsHttpHeaderSymbolFields.Sequence), IntermediateFieldType.Number),
-            },
-            typeof(IIsHttpHeaderSymbol));
-    }
-}
-
-namespace WixToolset.Iis.Symbols
-{
-    using WixToolset.Data;
-
-    public enum IIsHttpHeaderSymbolFields
-    {
-        HttpHeader,
-        ParentType,
-        ParentValue,
-        Name,
-        Value,
-        Attributes,
-        Sequence,
-    }
-
-    public class IIsHttpHeaderSymbol : IntermediateSymbol
-    {
-        public IIsHttpHeaderSymbol() : base(IisSymbolDefinitions.IIsHttpHeader, null, null)
-        {
-        }
-
-        public IIsHttpHeaderSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsHttpHeader, sourceLineNumber, id)
-        {
-        }
-
-        public IntermediateField this[IIsHttpHeaderSymbolFields index] => this.Fields[(int)index];
-
-        public string HttpHeader
-        {
-            get => this.Fields[(int)IIsHttpHeaderSymbolFields.HttpHeader].AsString();
-            set => this.Set((int)IIsHttpHeaderSymbolFields.HttpHeader, value);
-        }
-
-        public int ParentType
-        {
-            get => this.Fields[(int)IIsHttpHeaderSymbolFields.ParentType].AsNumber();
-            set => this.Set((int)IIsHttpHeaderSymbolFields.ParentType, value);
-        }
-
-        public string ParentValue
-        {
-            get => this.Fields[(int)IIsHttpHeaderSymbolFields.ParentValue].AsString();
-            set => this.Set((int)IIsHttpHeaderSymbolFields.ParentValue, value);
-        }
-
-        public string Name
-        {
-            get => this.Fields[(int)IIsHttpHeaderSymbolFields.Name].AsString();
-            set => this.Set((int)IIsHttpHeaderSymbolFields.Name, value);
-        }
-
-        public string Value
-        {
-            get => this.Fields[(int)IIsHttpHeaderSymbolFields.Value].AsString();
-            set => this.Set((int)IIsHttpHeaderSymbolFields.Value, value);
-        }
-
-        public int Attributes
-        {
-            get => this.Fields[(int)IIsHttpHeaderSymbolFields.Attributes].AsNumber();
-            set => this.Set((int)IIsHttpHeaderSymbolFields.Attributes, value);
-        }
-
-        public int? Sequence
-        {
-            get => this.Fields[(int)IIsHttpHeaderSymbolFields.Sequence].AsNullableNumber();
-            set => this.Set((int)IIsHttpHeaderSymbolFields.Sequence, value);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/wixext/Symbols/IIsMimeMapSymbol.cs b/src/wixext/Symbols/IIsMimeMapSymbol.cs
deleted file mode 100644
index 4af6f81c..00000000
--- a/src/wixext/Symbols/IIsMimeMapSymbol.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Iis.Symbols;
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly IntermediateSymbolDefinition IIsMimeMap = new IntermediateSymbolDefinition(
-            IisSymbolDefinitionType.IIsMimeMap.ToString(),
-            new[]
-            {
-                new IntermediateFieldDefinition(nameof(IIsMimeMapSymbolFields.ParentType), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsMimeMapSymbolFields.ParentValue), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsMimeMapSymbolFields.MimeType), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsMimeMapSymbolFields.Extension), IntermediateFieldType.String),
-            },
-            typeof(IIsMimeMapSymbol));
-    }
-}
-
-namespace WixToolset.Iis.Symbols
-{
-    using WixToolset.Data;
-
-    public enum IIsMimeMapSymbolFields
-    {
-        ParentType,
-        ParentValue,
-        MimeType,
-        Extension,
-    }
-
-    public class IIsMimeMapSymbol : IntermediateSymbol
-    {
-        public IIsMimeMapSymbol() : base(IisSymbolDefinitions.IIsMimeMap, null, null)
-        {
-        }
-
-        public IIsMimeMapSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsMimeMap, sourceLineNumber, id)
-        {
-        }
-
-        public IntermediateField this[IIsMimeMapSymbolFields index] => this.Fields[(int)index];
-
-        public int ParentType
-        {
-            get => this.Fields[(int)IIsMimeMapSymbolFields.ParentType].AsNumber();
-            set => this.Set((int)IIsMimeMapSymbolFields.ParentType, value);
-        }
-
-        public string ParentValue
-        {
-            get => this.Fields[(int)IIsMimeMapSymbolFields.ParentValue].AsString();
-            set => this.Set((int)IIsMimeMapSymbolFields.ParentValue, value);
-        }
-
-        public string MimeType
-        {
-            get => this.Fields[(int)IIsMimeMapSymbolFields.MimeType].AsString();
-            set => this.Set((int)IIsMimeMapSymbolFields.MimeType, value);
-        }
-
-        public string Extension
-        {
-            get => this.Fields[(int)IIsMimeMapSymbolFields.Extension].AsString();
-            set => this.Set((int)IIsMimeMapSymbolFields.Extension, value);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/wixext/Symbols/IIsPropertySymbol.cs b/src/wixext/Symbols/IIsPropertySymbol.cs
deleted file mode 100644
index 9cf67014..00000000
--- a/src/wixext/Symbols/IIsPropertySymbol.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Iis.Symbols;
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly IntermediateSymbolDefinition IIsProperty = new IntermediateSymbolDefinition(
-            IisSymbolDefinitionType.IIsProperty.ToString(),
-            new[]
-            {
-                new IntermediateFieldDefinition(nameof(IIsPropertySymbolFields.ComponentRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsPropertySymbolFields.Attributes), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsPropertySymbolFields.Value), IntermediateFieldType.String),
-            },
-            typeof(IIsPropertySymbol));
-    }
-}
-
-namespace WixToolset.Iis.Symbols
-{
-    using WixToolset.Data;
-
-    public enum IIsPropertySymbolFields
-    {
-        ComponentRef,
-        Attributes,
-        Value,
-    }
-
-    public class IIsPropertySymbol : IntermediateSymbol
-    {
-        public IIsPropertySymbol() : base(IisSymbolDefinitions.IIsProperty, null, null)
-        {
-        }
-
-        public IIsPropertySymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsProperty, sourceLineNumber, id)
-        {
-        }
-
-        public IntermediateField this[IIsPropertySymbolFields index] => this.Fields[(int)index];
-
-        public string ComponentRef
-        {
-            get => this.Fields[(int)IIsPropertySymbolFields.ComponentRef].AsString();
-            set => this.Set((int)IIsPropertySymbolFields.ComponentRef, value);
-        }
-
-        public int Attributes
-        {
-            get => this.Fields[(int)IIsPropertySymbolFields.Attributes].AsNumber();
-            set => this.Set((int)IIsPropertySymbolFields.Attributes, value);
-        }
-
-        public string Value
-        {
-            get => this.Fields[(int)IIsPropertySymbolFields.Value].AsString();
-            set => this.Set((int)IIsPropertySymbolFields.Value, value);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/wixext/Symbols/IIsWebAddressSymbol.cs b/src/wixext/Symbols/IIsWebAddressSymbol.cs
deleted file mode 100644
index 7111718a..00000000
--- a/src/wixext/Symbols/IIsWebAddressSymbol.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Iis.Symbols;
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly IntermediateSymbolDefinition IIsWebAddress = new IntermediateSymbolDefinition(
-            IisSymbolDefinitionType.IIsWebAddress.ToString(),
-            new[]
-            {
-                new IntermediateFieldDefinition(nameof(IIsWebAddressSymbolFields.WebRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebAddressSymbolFields.IP), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebAddressSymbolFields.Port), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebAddressSymbolFields.Header), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebAddressSymbolFields.Secure), IntermediateFieldType.Number),
-            },
-            typeof(IIsWebAddressSymbol));
-    }
-}
-
-namespace WixToolset.Iis.Symbols
-{
-    using WixToolset.Data;
-
-    public enum IIsWebAddressSymbolFields
-    {
-        WebRef,
-        IP,
-        Port,
-        Header,
-        Secure,
-    }
-
-    public class IIsWebAddressSymbol : IntermediateSymbol
-    {
-        public IIsWebAddressSymbol() : base(IisSymbolDefinitions.IIsWebAddress, null, null)
-        {
-        }
-
-        public IIsWebAddressSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebAddress, sourceLineNumber, id)
-        {
-        }
-
-        public IntermediateField this[IIsWebAddressSymbolFields index] => this.Fields[(int)index];
-
-        public string WebRef
-        {
-            get => this.Fields[(int)IIsWebAddressSymbolFields.WebRef].AsString();
-            set => this.Set((int)IIsWebAddressSymbolFields.WebRef, value);
-        }
-
-        public string IP
-        {
-            get => this.Fields[(int)IIsWebAddressSymbolFields.IP].AsString();
-            set => this.Set((int)IIsWebAddressSymbolFields.IP, value);
-        }
-
-        public string Port
-        {
-            get => this.Fields[(int)IIsWebAddressSymbolFields.Port].AsString();
-            set => this.Set((int)IIsWebAddressSymbolFields.Port, value);
-        }
-
-        public string Header
-        {
-            get => this.Fields[(int)IIsWebAddressSymbolFields.Header].AsString();
-            set => this.Set((int)IIsWebAddressSymbolFields.Header, value);
-        }
-
-        public int? Secure
-        {
-            get => this.Fields[(int)IIsWebAddressSymbolFields.Secure].AsNullableNumber();
-            set => this.Set((int)IIsWebAddressSymbolFields.Secure, value);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/wixext/Symbols/IIsWebApplicationExtensionSymbol.cs b/src/wixext/Symbols/IIsWebApplicationExtensionSymbol.cs
deleted file mode 100644
index 4283d702..00000000
--- a/src/wixext/Symbols/IIsWebApplicationExtensionSymbol.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Iis.Symbols;
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly IntermediateSymbolDefinition IIsWebApplicationExtension = new IntermediateSymbolDefinition(
-            IisSymbolDefinitionType.IIsWebApplicationExtension.ToString(),
-            new[]
-            {
-                new IntermediateFieldDefinition(nameof(IIsWebApplicationExtensionSymbolFields.ApplicationRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebApplicationExtensionSymbolFields.Extension), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebApplicationExtensionSymbolFields.Verbs), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebApplicationExtensionSymbolFields.Executable), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebApplicationExtensionSymbolFields.Attributes), IntermediateFieldType.Number),
-            },
-            typeof(IIsWebApplicationExtensionSymbol));
-    }
-}
-
-namespace WixToolset.Iis.Symbols
-{
-    using WixToolset.Data;
-
-    public enum IIsWebApplicationExtensionSymbolFields
-    {
-        ApplicationRef,
-        Extension,
-        Verbs,
-        Executable,
-        Attributes,
-    }
-
-    public class IIsWebApplicationExtensionSymbol : IntermediateSymbol
-    {
-        public IIsWebApplicationExtensionSymbol() : base(IisSymbolDefinitions.IIsWebApplicationExtension, null, null)
-        {
-        }
-
-        public IIsWebApplicationExtensionSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebApplicationExtension, sourceLineNumber, id)
-        {
-        }
-
-        public IntermediateField this[IIsWebApplicationExtensionSymbolFields index] => this.Fields[(int)index];
-
-        public string ApplicationRef
-        {
-            get => this.Fields[(int)IIsWebApplicationExtensionSymbolFields.ApplicationRef].AsString();
-            set => this.Set((int)IIsWebApplicationExtensionSymbolFields.ApplicationRef, value);
-        }
-
-        public string Extension
-        {
-            get => this.Fields[(int)IIsWebApplicationExtensionSymbolFields.Extension].AsString();
-            set => this.Set((int)IIsWebApplicationExtensionSymbolFields.Extension, value);
-        }
-
-        public string Verbs
-        {
-            get => this.Fields[(int)IIsWebApplicationExtensionSymbolFields.Verbs].AsString();
-            set => this.Set((int)IIsWebApplicationExtensionSymbolFields.Verbs, value);
-        }
-
-        public string Executable
-        {
-            get => this.Fields[(int)IIsWebApplicationExtensionSymbolFields.Executable].AsString();
-            set => this.Set((int)IIsWebApplicationExtensionSymbolFields.Executable, value);
-        }
-
-        public int Attributes
-        {
-            get => this.Fields[(int)IIsWebApplicationExtensionSymbolFields.Attributes].AsNumber();
-            set => this.Set((int)IIsWebApplicationExtensionSymbolFields.Attributes, value);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/wixext/Symbols/IIsWebApplicationSymbol.cs b/src/wixext/Symbols/IIsWebApplicationSymbol.cs
deleted file mode 100644
index 2f6f87de..00000000
--- a/src/wixext/Symbols/IIsWebApplicationSymbol.cs
+++ /dev/null
@@ -1,127 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Iis.Symbols;
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly IntermediateSymbolDefinition IIsWebApplication = new IntermediateSymbolDefinition(
-            IisSymbolDefinitionType.IIsWebApplication.ToString(),
-            new[]
-            {
-                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.Name), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.Isolation), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.AllowSessions), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.SessionTimeout), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.Buffer), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.ParentPaths), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.DefaultScript), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.ScriptTimeout), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.ServerDebugging), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.ClientDebugging), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebApplicationSymbolFields.AppPoolRef), IntermediateFieldType.String),
-            },
-            typeof(IIsWebApplicationSymbol));
-    }
-}
-
-namespace WixToolset.Iis.Symbols
-{
-    using WixToolset.Data;
-
-    public enum IIsWebApplicationSymbolFields
-    {
-        Name,
-        Isolation,
-        AllowSessions,
-        SessionTimeout,
-        Buffer,
-        ParentPaths,
-        DefaultScript,
-        ScriptTimeout,
-        ServerDebugging,
-        ClientDebugging,
-        AppPoolRef,
-    }
-
-    public class IIsWebApplicationSymbol : IntermediateSymbol
-    {
-        public IIsWebApplicationSymbol() : base(IisSymbolDefinitions.IIsWebApplication, null, null)
-        {
-        }
-
-        public IIsWebApplicationSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebApplication, sourceLineNumber, id)
-        {
-        }
-
-        public IntermediateField this[IIsWebApplicationSymbolFields index] => this.Fields[(int)index];
-
-        public string Name
-        {
-            get => this.Fields[(int)IIsWebApplicationSymbolFields.Name].AsString();
-            set => this.Set((int)IIsWebApplicationSymbolFields.Name, value);
-        }
-
-        public int Isolation
-        {
-            get => this.Fields[(int)IIsWebApplicationSymbolFields.Isolation].AsNumber();
-            set => this.Set((int)IIsWebApplicationSymbolFields.Isolation, value);
-        }
-
-        public int? AllowSessions
-        {
-            get => this.Fields[(int)IIsWebApplicationSymbolFields.AllowSessions].AsNullableNumber();
-            set => this.Set((int)IIsWebApplicationSymbolFields.AllowSessions, value);
-        }
-
-        public int? SessionTimeout
-        {
-            get => this.Fields[(int)IIsWebApplicationSymbolFields.SessionTimeout].AsNullableNumber();
-            set => this.Set((int)IIsWebApplicationSymbolFields.SessionTimeout, value);
-        }
-
-        public int? Buffer
-        {
-            get => this.Fields[(int)IIsWebApplicationSymbolFields.Buffer].AsNullableNumber();
-            set => this.Set((int)IIsWebApplicationSymbolFields.Buffer, value);
-        }
-
-        public int? ParentPaths
-        {
-            get => this.Fields[(int)IIsWebApplicationSymbolFields.ParentPaths].AsNullableNumber();
-            set => this.Set((int)IIsWebApplicationSymbolFields.ParentPaths, value);
-        }
-
-        public string DefaultScript
-        {
-            get => this.Fields[(int)IIsWebApplicationSymbolFields.DefaultScript].AsString();
-            set => this.Set((int)IIsWebApplicationSymbolFields.DefaultScript, value);
-        }
-
-        public int? ScriptTimeout
-        {
-            get => this.Fields[(int)IIsWebApplicationSymbolFields.ScriptTimeout].AsNullableNumber();
-            set => this.Set((int)IIsWebApplicationSymbolFields.ScriptTimeout, value);
-        }
-
-        public int? ServerDebugging
-        {
-            get => this.Fields[(int)IIsWebApplicationSymbolFields.ServerDebugging].AsNullableNumber();
-            set => this.Set((int)IIsWebApplicationSymbolFields.ServerDebugging, value);
-        }
-
-        public int? ClientDebugging
-        {
-            get => this.Fields[(int)IIsWebApplicationSymbolFields.ClientDebugging].AsNullableNumber();
-            set => this.Set((int)IIsWebApplicationSymbolFields.ClientDebugging, value);
-        }
-
-        public string AppPoolRef
-        {
-            get => this.Fields[(int)IIsWebApplicationSymbolFields.AppPoolRef].AsString();
-            set => this.Set((int)IIsWebApplicationSymbolFields.AppPoolRef, value);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/wixext/Symbols/IIsWebDirPropertiesSymbol.cs b/src/wixext/Symbols/IIsWebDirPropertiesSymbol.cs
deleted file mode 100644
index 42d2dead..00000000
--- a/src/wixext/Symbols/IIsWebDirPropertiesSymbol.cs
+++ /dev/null
@@ -1,151 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Iis.Symbols;
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly IntermediateSymbolDefinition IIsWebDirProperties = new IntermediateSymbolDefinition(
-            IisSymbolDefinitionType.IIsWebDirProperties.ToString(),
-            new[]
-            {
-                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.Access), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.Authorization), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.AnonymousUserRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.IIsControlledPassword), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.LogVisits), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.Index), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.DefaultDoc), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.AspDetailedError), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.HttpExpires), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.CacheControlMaxAge), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.CacheControlCustom), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.NoCustomError), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.AccessSSLFlags), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebDirPropertiesSymbolFields.AuthenticationProviders), IntermediateFieldType.String),
-            },
-            typeof(IIsWebDirPropertiesSymbol));
-    }
-}
-
-namespace WixToolset.Iis.Symbols
-{
-    using WixToolset.Data;
-
-    public enum IIsWebDirPropertiesSymbolFields
-    {
-        Access,
-        Authorization,
-        AnonymousUserRef,
-        IIsControlledPassword,
-        LogVisits,
-        Index,
-        DefaultDoc,
-        AspDetailedError,
-        HttpExpires,
-        CacheControlMaxAge,
-        CacheControlCustom,
-        NoCustomError,
-        AccessSSLFlags,
-        AuthenticationProviders,
-    }
-
-    public class IIsWebDirPropertiesSymbol : IntermediateSymbol
-    {
-        public IIsWebDirPropertiesSymbol() : base(IisSymbolDefinitions.IIsWebDirProperties, null, null)
-        {
-        }
-
-        public IIsWebDirPropertiesSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebDirProperties, sourceLineNumber, id)
-        {
-        }
-
-        public IntermediateField this[IIsWebDirPropertiesSymbolFields index] => this.Fields[(int)index];
-
-        public int? Access
-        {
-            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.Access].AsNullableNumber();
-            set => this.Set((int)IIsWebDirPropertiesSymbolFields.Access, value);
-        }
-
-        public int? Authorization
-        {
-            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.Authorization].AsNullableNumber();
-            set => this.Set((int)IIsWebDirPropertiesSymbolFields.Authorization, value);
-        }
-
-        public string AnonymousUserRef
-        {
-            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.AnonymousUserRef].AsString();
-            set => this.Set((int)IIsWebDirPropertiesSymbolFields.AnonymousUserRef, value);
-        }
-
-        public int? IIsControlledPassword
-        {
-            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.IIsControlledPassword].AsNullableNumber();
-            set => this.Set((int)IIsWebDirPropertiesSymbolFields.IIsControlledPassword, value);
-        }
-
-        public int? LogVisits
-        {
-            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.LogVisits].AsNullableNumber();
-            set => this.Set((int)IIsWebDirPropertiesSymbolFields.LogVisits, value);
-        }
-
-        public int? Index
-        {
-            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.Index].AsNullableNumber();
-            set => this.Set((int)IIsWebDirPropertiesSymbolFields.Index, value);
-        }
-
-        public string DefaultDoc
-        {
-            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.DefaultDoc].AsString();
-            set => this.Set((int)IIsWebDirPropertiesSymbolFields.DefaultDoc, value);
-        }
-
-        public int? AspDetailedError
-        {
-            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.AspDetailedError].AsNullableNumber();
-            set => this.Set((int)IIsWebDirPropertiesSymbolFields.AspDetailedError, value);
-        }
-
-        public string HttpExpires
-        {
-            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.HttpExpires].AsString();
-            set => this.Set((int)IIsWebDirPropertiesSymbolFields.HttpExpires, value);
-        }
-
-        public int? CacheControlMaxAge
-        {
-            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.CacheControlMaxAge].AsNullableNumber();
-            set => this.Set((int)IIsWebDirPropertiesSymbolFields.CacheControlMaxAge, value);
-        }
-
-        public string CacheControlCustom
-        {
-            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.CacheControlCustom].AsString();
-            set => this.Set((int)IIsWebDirPropertiesSymbolFields.CacheControlCustom, value);
-        }
-
-        public int? NoCustomError
-        {
-            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.NoCustomError].AsNullableNumber();
-            set => this.Set((int)IIsWebDirPropertiesSymbolFields.NoCustomError, value);
-        }
-
-        public int? AccessSSLFlags
-        {
-            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.AccessSSLFlags].AsNullableNumber();
-            set => this.Set((int)IIsWebDirPropertiesSymbolFields.AccessSSLFlags, value);
-        }
-
-        public string AuthenticationProviders
-        {
-            get => this.Fields[(int)IIsWebDirPropertiesSymbolFields.AuthenticationProviders].AsString();
-            set => this.Set((int)IIsWebDirPropertiesSymbolFields.AuthenticationProviders, value);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/wixext/Symbols/IIsWebDirSymbol.cs b/src/wixext/Symbols/IIsWebDirSymbol.cs
deleted file mode 100644
index 7f257f14..00000000
--- a/src/wixext/Symbols/IIsWebDirSymbol.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Iis.Symbols;
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly IntermediateSymbolDefinition IIsWebDir = new IntermediateSymbolDefinition(
-            IisSymbolDefinitionType.IIsWebDir.ToString(),
-            new[]
-            {
-                new IntermediateFieldDefinition(nameof(IIsWebDirSymbolFields.ComponentRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebDirSymbolFields.WebRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebDirSymbolFields.Path), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebDirSymbolFields.DirPropertiesRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebDirSymbolFields.ApplicationRef), IntermediateFieldType.String),
-            },
-            typeof(IIsWebDirSymbol));
-    }
-}
-
-namespace WixToolset.Iis.Symbols
-{
-    using WixToolset.Data;
-
-    public enum IIsWebDirSymbolFields
-    {
-        ComponentRef,
-        WebRef,
-        Path,
-        DirPropertiesRef,
-        ApplicationRef,
-    }
-
-    public class IIsWebDirSymbol : IntermediateSymbol
-    {
-        public IIsWebDirSymbol() : base(IisSymbolDefinitions.IIsWebDir, null, null)
-        {
-        }
-
-        public IIsWebDirSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebDir, sourceLineNumber, id)
-        {
-        }
-
-        public IntermediateField this[IIsWebDirSymbolFields index] => this.Fields[(int)index];
-
-        public string ComponentRef
-        {
-            get => this.Fields[(int)IIsWebDirSymbolFields.ComponentRef].AsString();
-            set => this.Set((int)IIsWebDirSymbolFields.ComponentRef, value);
-        }
-
-        public string WebRef
-        {
-            get => this.Fields[(int)IIsWebDirSymbolFields.WebRef].AsString();
-            set => this.Set((int)IIsWebDirSymbolFields.WebRef, value);
-        }
-
-        public string Path
-        {
-            get => this.Fields[(int)IIsWebDirSymbolFields.Path].AsString();
-            set => this.Set((int)IIsWebDirSymbolFields.Path, value);
-        }
-
-        public string DirPropertiesRef
-        {
-            get => this.Fields[(int)IIsWebDirSymbolFields.DirPropertiesRef].AsString();
-            set => this.Set((int)IIsWebDirSymbolFields.DirPropertiesRef, value);
-        }
-
-        public string ApplicationRef
-        {
-            get => this.Fields[(int)IIsWebDirSymbolFields.ApplicationRef].AsString();
-            set => this.Set((int)IIsWebDirSymbolFields.ApplicationRef, value);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/wixext/Symbols/IIsWebErrorSymbol.cs b/src/wixext/Symbols/IIsWebErrorSymbol.cs
deleted file mode 100644
index f8488fed..00000000
--- a/src/wixext/Symbols/IIsWebErrorSymbol.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Iis.Symbols;
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly IntermediateSymbolDefinition IIsWebError = new IntermediateSymbolDefinition(
-            IisSymbolDefinitionType.IIsWebError.ToString(),
-            new[]
-            {
-                new IntermediateFieldDefinition(nameof(IIsWebErrorSymbolFields.ErrorCode), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebErrorSymbolFields.SubCode), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebErrorSymbolFields.ParentType), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebErrorSymbolFields.ParentValue), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebErrorSymbolFields.File), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebErrorSymbolFields.URL), IntermediateFieldType.String),
-            },
-            typeof(IIsWebErrorSymbol));
-    }
-}
-
-namespace WixToolset.Iis.Symbols
-{
-    using WixToolset.Data;
-
-    public enum IIsWebErrorSymbolFields
-    {
-        ErrorCode,
-        SubCode,
-        ParentType,
-        ParentValue,
-        File,
-        URL,
-    }
-
-    public class IIsWebErrorSymbol : IntermediateSymbol
-    {
-        public IIsWebErrorSymbol() : base(IisSymbolDefinitions.IIsWebError, null, null)
-        {
-        }
-
-        public IIsWebErrorSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebError, sourceLineNumber, id)
-        {
-        }
-
-        public IntermediateField this[IIsWebErrorSymbolFields index] => this.Fields[(int)index];
-
-        public int ErrorCode
-        {
-            get => this.Fields[(int)IIsWebErrorSymbolFields.ErrorCode].AsNumber();
-            set => this.Set((int)IIsWebErrorSymbolFields.ErrorCode, value);
-        }
-
-        public int SubCode
-        {
-            get => this.Fields[(int)IIsWebErrorSymbolFields.SubCode].AsNumber();
-            set => this.Set((int)IIsWebErrorSymbolFields.SubCode, value);
-        }
-
-        public int ParentType
-        {
-            get => this.Fields[(int)IIsWebErrorSymbolFields.ParentType].AsNumber();
-            set => this.Set((int)IIsWebErrorSymbolFields.ParentType, value);
-        }
-
-        public string ParentValue
-        {
-            get => this.Fields[(int)IIsWebErrorSymbolFields.ParentValue].AsString();
-            set => this.Set((int)IIsWebErrorSymbolFields.ParentValue, value);
-        }
-
-        public string File
-        {
-            get => this.Fields[(int)IIsWebErrorSymbolFields.File].AsString();
-            set => this.Set((int)IIsWebErrorSymbolFields.File, value);
-        }
-
-        public string URL
-        {
-            get => this.Fields[(int)IIsWebErrorSymbolFields.URL].AsString();
-            set => this.Set((int)IIsWebErrorSymbolFields.URL, value);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/wixext/Symbols/IIsWebLogSymbol.cs b/src/wixext/Symbols/IIsWebLogSymbol.cs
deleted file mode 100644
index 409dc673..00000000
--- a/src/wixext/Symbols/IIsWebLogSymbol.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Iis.Symbols;
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly IntermediateSymbolDefinition IIsWebLog = new IntermediateSymbolDefinition(
-            IisSymbolDefinitionType.IIsWebLog.ToString(),
-            new[]
-            {
-                new IntermediateFieldDefinition(nameof(IIsWebLogSymbolFields.Format), IntermediateFieldType.String),
-            },
-            typeof(IIsWebLogSymbol));
-    }
-}
-
-namespace WixToolset.Iis.Symbols
-{
-    using WixToolset.Data;
-
-    public enum IIsWebLogSymbolFields
-    {
-        Format,
-    }
-
-    public class IIsWebLogSymbol : IntermediateSymbol
-    {
-        public IIsWebLogSymbol() : base(IisSymbolDefinitions.IIsWebLog, null, null)
-        {
-        }
-
-        public IIsWebLogSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebLog, sourceLineNumber, id)
-        {
-        }
-
-        public IntermediateField this[IIsWebLogSymbolFields index] => this.Fields[(int)index];
-
-        public string Format
-        {
-            get => this.Fields[(int)IIsWebLogSymbolFields.Format].AsString();
-            set => this.Set((int)IIsWebLogSymbolFields.Format, value);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/wixext/Symbols/IIsWebServiceExtensionSymbol.cs b/src/wixext/Symbols/IIsWebServiceExtensionSymbol.cs
deleted file mode 100644
index 44922357..00000000
--- a/src/wixext/Symbols/IIsWebServiceExtensionSymbol.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Iis.Symbols;
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly IntermediateSymbolDefinition IIsWebServiceExtension = new IntermediateSymbolDefinition(
-            IisSymbolDefinitionType.IIsWebServiceExtension.ToString(),
-            new[]
-            {
-                new IntermediateFieldDefinition(nameof(IIsWebServiceExtensionSymbolFields.ComponentRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebServiceExtensionSymbolFields.File), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebServiceExtensionSymbolFields.Description), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebServiceExtensionSymbolFields.Group), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebServiceExtensionSymbolFields.Attributes), IntermediateFieldType.Number),
-            },
-            typeof(IIsWebServiceExtensionSymbol));
-    }
-}
-
-namespace WixToolset.Iis.Symbols
-{
-    using WixToolset.Data;
-
-    public enum IIsWebServiceExtensionSymbolFields
-    {
-        ComponentRef,
-        File,
-        Description,
-        Group,
-        Attributes,
-    }
-
-    public class IIsWebServiceExtensionSymbol : IntermediateSymbol
-    {
-        public IIsWebServiceExtensionSymbol() : base(IisSymbolDefinitions.IIsWebServiceExtension, null, null)
-        {
-        }
-
-        public IIsWebServiceExtensionSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebServiceExtension, sourceLineNumber, id)
-        {
-        }
-
-        public IntermediateField this[IIsWebServiceExtensionSymbolFields index] => this.Fields[(int)index];
-
-        public string ComponentRef
-        {
-            get => this.Fields[(int)IIsWebServiceExtensionSymbolFields.ComponentRef].AsString();
-            set => this.Set((int)IIsWebServiceExtensionSymbolFields.ComponentRef, value);
-        }
-
-        public string File
-        {
-            get => this.Fields[(int)IIsWebServiceExtensionSymbolFields.File].AsString();
-            set => this.Set((int)IIsWebServiceExtensionSymbolFields.File, value);
-        }
-
-        public string Description
-        {
-            get => this.Fields[(int)IIsWebServiceExtensionSymbolFields.Description].AsString();
-            set => this.Set((int)IIsWebServiceExtensionSymbolFields.Description, value);
-        }
-
-        public string Group
-        {
-            get => this.Fields[(int)IIsWebServiceExtensionSymbolFields.Group].AsString();
-            set => this.Set((int)IIsWebServiceExtensionSymbolFields.Group, value);
-        }
-
-        public int Attributes
-        {
-            get => this.Fields[(int)IIsWebServiceExtensionSymbolFields.Attributes].AsNumber();
-            set => this.Set((int)IIsWebServiceExtensionSymbolFields.Attributes, value);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/wixext/Symbols/IIsWebSiteCertificatesSymbol.cs b/src/wixext/Symbols/IIsWebSiteCertificatesSymbol.cs
deleted file mode 100644
index 851ce556..00000000
--- a/src/wixext/Symbols/IIsWebSiteCertificatesSymbol.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Iis.Symbols;
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly IntermediateSymbolDefinition IIsWebSiteCertificates = new IntermediateSymbolDefinition(
-            IisSymbolDefinitionType.IIsWebSiteCertificates.ToString(),
-            new[]
-            {
-                new IntermediateFieldDefinition(nameof(IIsWebSiteCertificatesSymbolFields.WebRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebSiteCertificatesSymbolFields.CertificateRef), IntermediateFieldType.String),
-            },
-            typeof(IIsWebSiteCertificatesSymbol));
-    }
-}
-
-namespace WixToolset.Iis.Symbols
-{
-    using WixToolset.Data;
-
-    public enum IIsWebSiteCertificatesSymbolFields
-    {
-        WebRef,
-        CertificateRef,
-    }
-
-    public class IIsWebSiteCertificatesSymbol : IntermediateSymbol
-    {
-        public IIsWebSiteCertificatesSymbol() : base(IisSymbolDefinitions.IIsWebSiteCertificates, null, null)
-        {
-        }
-
-        public IIsWebSiteCertificatesSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebSiteCertificates, sourceLineNumber, id)
-        {
-        }
-
-        public IntermediateField this[IIsWebSiteCertificatesSymbolFields index] => this.Fields[(int)index];
-
-        public string WebRef
-        {
-            get => this.Fields[(int)IIsWebSiteCertificatesSymbolFields.WebRef].AsString();
-            set => this.Set((int)IIsWebSiteCertificatesSymbolFields.WebRef, value);
-        }
-
-        public string CertificateRef
-        {
-            get => this.Fields[(int)IIsWebSiteCertificatesSymbolFields.CertificateRef].AsString();
-            set => this.Set((int)IIsWebSiteCertificatesSymbolFields.CertificateRef, value);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/wixext/Symbols/IIsWebSiteSymbol.cs b/src/wixext/Symbols/IIsWebSiteSymbol.cs
deleted file mode 100644
index ceba2ea0..00000000
--- a/src/wixext/Symbols/IIsWebSiteSymbol.cs
+++ /dev/null
@@ -1,135 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Iis.Symbols;
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly IntermediateSymbolDefinition IIsWebSite = new IntermediateSymbolDefinition(
-            IisSymbolDefinitionType.IIsWebSite.ToString(),
-            new[]
-            {
-                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.ComponentRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.Description), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.ConnectionTimeout), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.DirectoryRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.State), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.Attributes), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.KeyAddressRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.DirPropertiesRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.ApplicationRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.Sequence), IntermediateFieldType.Number),
-                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.LogRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebSiteSymbolFields.WebsiteId), IntermediateFieldType.String),
-            },
-            typeof(IIsWebSiteSymbol));
-    }
-}
-
-namespace WixToolset.Iis.Symbols
-{
-    using WixToolset.Data;
-
-    public enum IIsWebSiteSymbolFields
-    {
-        ComponentRef,
-        Description,
-        ConnectionTimeout,
-        DirectoryRef,
-        State,
-        Attributes,
-        KeyAddressRef,
-        DirPropertiesRef,
-        ApplicationRef,
-        Sequence,
-        LogRef,
-        WebsiteId,
-    }
-
-    public class IIsWebSiteSymbol : IntermediateSymbol
-    {
-        public IIsWebSiteSymbol() : base(IisSymbolDefinitions.IIsWebSite, null, null)
-        {
-        }
-
-        public IIsWebSiteSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebSite, sourceLineNumber, id)
-        {
-        }
-
-        public IntermediateField this[IIsWebSiteSymbolFields index] => this.Fields[(int)index];
-
-        public string ComponentRef
-        {
-            get => this.Fields[(int)IIsWebSiteSymbolFields.ComponentRef].AsString();
-            set => this.Set((int)IIsWebSiteSymbolFields.ComponentRef, value);
-        }
-
-        public string Description
-        {
-            get => this.Fields[(int)IIsWebSiteSymbolFields.Description].AsString();
-            set => this.Set((int)IIsWebSiteSymbolFields.Description, value);
-        }
-
-        public int? ConnectionTimeout
-        {
-            get => this.Fields[(int)IIsWebSiteSymbolFields.ConnectionTimeout].AsNullableNumber();
-            set => this.Set((int)IIsWebSiteSymbolFields.ConnectionTimeout, value);
-        }
-
-        public string DirectoryRef
-        {
-            get => this.Fields[(int)IIsWebSiteSymbolFields.DirectoryRef].AsString();
-            set => this.Set((int)IIsWebSiteSymbolFields.DirectoryRef, value);
-        }
-
-        public int? State
-        {
-            get => this.Fields[(int)IIsWebSiteSymbolFields.State].AsNullableNumber();
-            set => this.Set((int)IIsWebSiteSymbolFields.State, value);
-        }
-
-        public int Attributes
-        {
-            get => this.Fields[(int)IIsWebSiteSymbolFields.Attributes].AsNumber();
-            set => this.Set((int)IIsWebSiteSymbolFields.Attributes, value);
-        }
-
-        public string KeyAddressRef
-        {
-            get => this.Fields[(int)IIsWebSiteSymbolFields.KeyAddressRef].AsString();
-            set => this.Set((int)IIsWebSiteSymbolFields.KeyAddressRef, value);
-        }
-
-        public string DirPropertiesRef
-        {
-            get => this.Fields[(int)IIsWebSiteSymbolFields.DirPropertiesRef].AsString();
-            set => this.Set((int)IIsWebSiteSymbolFields.DirPropertiesRef, value);
-        }
-
-        public string ApplicationRef
-        {
-            get => this.Fields[(int)IIsWebSiteSymbolFields.ApplicationRef].AsString();
-            set => this.Set((int)IIsWebSiteSymbolFields.ApplicationRef, value);
-        }
-
-        public int? Sequence
-        {
-            get => this.Fields[(int)IIsWebSiteSymbolFields.Sequence].AsNullableNumber();
-            set => this.Set((int)IIsWebSiteSymbolFields.Sequence, value);
-        }
-
-        public string LogRef
-        {
-            get => this.Fields[(int)IIsWebSiteSymbolFields.LogRef].AsString();
-            set => this.Set((int)IIsWebSiteSymbolFields.LogRef, value);
-        }
-
-        public string WebsiteId
-        {
-            get => this.Fields[(int)IIsWebSiteSymbolFields.WebsiteId].AsString();
-            set => this.Set((int)IIsWebSiteSymbolFields.WebsiteId, value);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/wixext/Symbols/IIsWebVirtualDirSymbol.cs b/src/wixext/Symbols/IIsWebVirtualDirSymbol.cs
deleted file mode 100644
index bfc29e84..00000000
--- a/src/wixext/Symbols/IIsWebVirtualDirSymbol.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using WixToolset.Data;
-    using WixToolset.Iis.Symbols;
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly IntermediateSymbolDefinition IIsWebVirtualDir = new IntermediateSymbolDefinition(
-            IisSymbolDefinitionType.IIsWebVirtualDir.ToString(),
-            new[]
-            {
-                new IntermediateFieldDefinition(nameof(IIsWebVirtualDirSymbolFields.ComponentRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebVirtualDirSymbolFields.WebRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebVirtualDirSymbolFields.Alias), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebVirtualDirSymbolFields.DirectoryRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebVirtualDirSymbolFields.DirPropertiesRef), IntermediateFieldType.String),
-                new IntermediateFieldDefinition(nameof(IIsWebVirtualDirSymbolFields.ApplicationRef), IntermediateFieldType.String),
-            },
-            typeof(IIsWebVirtualDirSymbol));
-    }
-}
-
-namespace WixToolset.Iis.Symbols
-{
-    using WixToolset.Data;
-
-    public enum IIsWebVirtualDirSymbolFields
-    {
-        ComponentRef,
-        WebRef,
-        Alias,
-        DirectoryRef,
-        DirPropertiesRef,
-        ApplicationRef,
-    }
-
-    public class IIsWebVirtualDirSymbol : IntermediateSymbol
-    {
-        public IIsWebVirtualDirSymbol() : base(IisSymbolDefinitions.IIsWebVirtualDir, null, null)
-        {
-        }
-
-        public IIsWebVirtualDirSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(IisSymbolDefinitions.IIsWebVirtualDir, sourceLineNumber, id)
-        {
-        }
-
-        public IntermediateField this[IIsWebVirtualDirSymbolFields index] => this.Fields[(int)index];
-
-        public string ComponentRef
-        {
-            get => this.Fields[(int)IIsWebVirtualDirSymbolFields.ComponentRef].AsString();
-            set => this.Set((int)IIsWebVirtualDirSymbolFields.ComponentRef, value);
-        }
-
-        public string WebRef
-        {
-            get => this.Fields[(int)IIsWebVirtualDirSymbolFields.WebRef].AsString();
-            set => this.Set((int)IIsWebVirtualDirSymbolFields.WebRef, value);
-        }
-
-        public string Alias
-        {
-            get => this.Fields[(int)IIsWebVirtualDirSymbolFields.Alias].AsString();
-            set => this.Set((int)IIsWebVirtualDirSymbolFields.Alias, value);
-        }
-
-        public string DirectoryRef
-        {
-            get => this.Fields[(int)IIsWebVirtualDirSymbolFields.DirectoryRef].AsString();
-            set => this.Set((int)IIsWebVirtualDirSymbolFields.DirectoryRef, value);
-        }
-
-        public string DirPropertiesRef
-        {
-            get => this.Fields[(int)IIsWebVirtualDirSymbolFields.DirPropertiesRef].AsString();
-            set => this.Set((int)IIsWebVirtualDirSymbolFields.DirPropertiesRef, value);
-        }
-
-        public string ApplicationRef
-        {
-            get => this.Fields[(int)IIsWebVirtualDirSymbolFields.ApplicationRef].AsString();
-            set => this.Set((int)IIsWebVirtualDirSymbolFields.ApplicationRef, value);
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/wixext/Symbols/IisSymbolDefinitions.cs b/src/wixext/Symbols/IisSymbolDefinitions.cs
deleted file mode 100644
index d6ed80a2..00000000
--- a/src/wixext/Symbols/IisSymbolDefinitions.cs
+++ /dev/null
@@ -1,107 +0,0 @@
-// 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.
-
-namespace WixToolset.Iis
-{
-    using System;
-    using WixToolset.Data;
-
-    public enum IisSymbolDefinitionType
-    {
-        Certificate,
-        CertificateHash,
-        IIsAppPool,
-        IIsFilter,
-        IIsHttpHeader,
-        IIsMimeMap,
-        IIsProperty,
-        IIsWebAddress,
-        IIsWebApplication,
-        IIsWebApplicationExtension,
-        IIsWebDir,
-        IIsWebDirProperties,
-        IIsWebError,
-        IIsWebLog,
-        IIsWebServiceExtension,
-        IIsWebSite,
-        IIsWebSiteCertificates,
-        IIsWebVirtualDir,
-    }
-
-    public static partial class IisSymbolDefinitions
-    {
-        public static readonly Version Version = new Version("4.0.0");
-
-        public static IntermediateSymbolDefinition ByName(string name)
-        {
-            if (!Enum.TryParse(name, out IisSymbolDefinitionType type))
-            {
-                return null;
-            }
-
-            return ByType(type);
-        }
-
-        public static IntermediateSymbolDefinition ByType(IisSymbolDefinitionType type)
-        {
-            switch (type)
-            {
-                case IisSymbolDefinitionType.Certificate:
-                    return IisSymbolDefinitions.Certificate;
-
-                case IisSymbolDefinitionType.CertificateHash:
-                    return IisSymbolDefinitions.CertificateHash;
-
-                case IisSymbolDefinitionType.IIsAppPool:
-                    return IisSymbolDefinitions.IIsAppPool;
-
-                case IisSymbolDefinitionType.IIsFilter:
-                    return IisSymbolDefinitions.IIsFilter;
-
-                case IisSymbolDefinitionType.IIsHttpHeader:
-                    return IisSymbolDefinitions.IIsHttpHeader;
-
-                case IisSymbolDefinitionType.IIsMimeMap:
-                    return IisSymbolDefinitions.IIsMimeMap;
-
-                case IisSymbolDefinitionType.IIsProperty:
-                    return IisSymbolDefinitions.IIsProperty;
-
-                case IisSymbolDefinitionType.IIsWebAddress:
-                    return IisSymbolDefinitions.IIsWebAddress;
-
-                case IisSymbolDefinitionType.IIsWebApplication:
-                    return IisSymbolDefinitions.IIsWebApplication;
-
-                case IisSymbolDefinitionType.IIsWebApplicationExtension:
-                    return IisSymbolDefinitions.IIsWebApplicationExtension;
-
-                case IisSymbolDefinitionType.IIsWebDir:
-                    return IisSymbolDefinitions.IIsWebDir;
-
-                case IisSymbolDefinitionType.IIsWebDirProperties:
-                    return IisSymbolDefinitions.IIsWebDirProperties;
-
-                case IisSymbolDefinitionType.IIsWebError:
-                    return IisSymbolDefinitions.IIsWebError;
-
-                case IisSymbolDefinitionType.IIsWebLog:
-                    return IisSymbolDefinitions.IIsWebLog;
-
-                case IisSymbolDefinitionType.IIsWebServiceExtension:
-                    return IisSymbolDefinitions.IIsWebServiceExtension;
-
-                case IisSymbolDefinitionType.IIsWebSite:
-                    return IisSymbolDefinitions.IIsWebSite;
-
-                case IisSymbolDefinitionType.IIsWebSiteCertificates:
-                    return IisSymbolDefinitions.IIsWebSiteCertificates;
-
-                case IisSymbolDefinitionType.IIsWebVirtualDir:
-                    return IisSymbolDefinitions.IIsWebVirtualDir;
-
-                default:
-                    throw new ArgumentOutOfRangeException(nameof(type));
-            }
-        }
-    }
-}
diff --git a/src/wixext/WixToolset.Iis.wixext.csproj b/src/wixext/WixToolset.Iis.wixext.csproj
deleted file mode 100644
index 81d41e77..00000000
--- a/src/wixext/WixToolset.Iis.wixext.csproj
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<Project Sdk="Microsoft.NET.Sdk">
-  <PropertyGroup>
-    <TargetFramework>netstandard2.0</TargetFramework>
-    <RootNamespace>WixToolset.Iis</RootNamespace>
-    <Description>WiX Toolset Iis Extension</Description>
-    <Title>WiX Toolset Iis Extension</Title>
-    <IsTool>true</IsTool>
-    <ContentTargetFolders>build</ContentTargetFolders>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <Content Include="$(MSBuildThisFileName).targets" />
-    <EmbeddedResource Include="$(OutputPath)..\iis.wixlib" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <PackageReference Include="WixToolset.Data" Version="4.0.*" PrivateAssets="all" />
-    <PackageReference Include="WixToolset.Extensibility" Version="4.0.*" PrivateAssets="all" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <ProjectReference Include="..\wixlib\iis.wixproj" ReferenceOutputAssembly="false" Condition=" '$(NCrunch)'=='' " />
-  </ItemGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Nerdbank.GitVersioning" Version="2.1.65" PrivateAssets="all" />
-  </ItemGroup>
-</Project>
diff --git a/src/wixext/WixToolset.Iis.wixext.targets b/src/wixext/WixToolset.Iis.wixext.targets
deleted file mode 100644
index 6398fce1..00000000
--- a/src/wixext/WixToolset.Iis.wixext.targets
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
-  <PropertyGroup>
-    <WixToolsetIisWixextPath Condition=" '$(WixToolsetIisWixextPath)' == '' ">$(MSBuildThisFileDirectory)..\tools\WixToolset.Iis.wixext.dll</WixToolsetIisWixextPath>
-  </PropertyGroup>
-  <ItemGroup>
-    <WixExtension Include="$(WixToolsetIisWixextPath)" />
-  </ItemGroup>
-</Project>
diff --git a/src/wixlib/IIsExtension.wxs b/src/wixlib/IIsExtension.wxs
deleted file mode 100644
index 18fc34ff..00000000
--- a/src/wixlib/IIsExtension.wxs
+++ /dev/null
@@ -1,58 +0,0 @@
-<!-- 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. -->
-
-
-<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
-    <?include caerr.wxi ?>
-
-    <Fragment>
-        <Property Id="IISMAJORVERSION">
-            <RegistrySearch Id="IIsMajorVersionSearch" Root="HKLM" Key="SOFTWARE\Microsoft\InetStp" Name="MajorVersion" Type="raw" />
-        </Property>
-
-        <Property Id="IISMINORVERSION">
-            <RegistrySearch Id="IIsMinorVersionSearch" Root="HKLM" Key="SOFTWARE\Microsoft\InetStp" Name="MinorVersion" Type="raw" />
-        </Property>
-    </Fragment>
-
-    <Fragment>
-      <UI Id="WixIIsErrors">
-        <Error Id="$(var.msierrIISCannotConnect)" Message="!(loc.msierrIISCannotConnect)" />
-        <Error Id="$(var.msierrIISFailedReadWebSite)" Message="!(loc.msierrIISFailedReadWebSite)" />
-        <Error Id="$(var.msierrIISFailedReadWebDirs)" Message="!(loc.msierrIISFailedReadWebDirs)" />
-        <Error Id="$(var.msierrIISFailedReadVDirs)" Message="!(loc.msierrIISFailedReadVDirs)" />
-        <Error Id="$(var.msierrIISFailedReadFilters)" Message="!(loc.msierrIISFailedReadFilters)" />
-        <Error Id="$(var.msierrIISFailedReadMimeMap)" Message="!(loc.msierrIISFailedReadMimeMap)" />
-        <Error Id="$(var.msierrIISFailedReadAppPool)" Message="!(loc.msierrIISFailedReadAppPool)" />
-        <Error Id="$(var.msierrIISFailedReadProp)" Message="!(loc.msierrIISFailedReadProp)" />
-        <Error Id="$(var.msierrIISFailedReadWebSvcExt)" Message="!(loc.msierrIISFailedReadWebSvcExt)" />
-        <Error Id="$(var.msierrIISFailedReadWebError)" Message="!(loc.msierrIISFailedReadWebError)" />
-        <Error Id="$(var.msierrIISFailedReadHttpHeader)" Message="!(loc.msierrIISFailedReadHttpHeader)" />
-
-        <Error Id="$(var.msierrIISFailedSchedTransaction)" Message="!(loc.msierrIISFailedSchedTransaction)" />
-        <Error Id="$(var.msierrIISFailedSchedInstallWebs)" Message="!(loc.msierrIISFailedSchedInstallWebs)" />
-        <Error Id="$(var.msierrIISFailedSchedInstallWebDirs)" Message="!(loc.msierrIISFailedSchedInstallWebDirs)" />
-        <Error Id="$(var.msierrIISFailedSchedInstallVDirs)" Message="!(loc.msierrIISFailedSchedInstallVDirs)" />
-        <Error Id="$(var.msierrIISFailedSchedInstallFilters)" Message="!(loc.msierrIISFailedSchedInstallFilters)" />
-        <Error Id="$(var.msierrIISFailedSchedInstallAppPool)" Message="!(loc.msierrIISFailedSchedInstallAppPool)" />
-        <Error Id="$(var.msierrIISFailedSchedInstallProp)" Message="!(loc.msierrIISFailedSchedInstallProp)" />
-        <Error Id="$(var.msierrIISFailedSchedInstallWebSvcExt)" Message="!(loc.msierrIISFailedSchedInstallWebSvcExt)" />
-
-        <Error Id="$(var.msierrIISFailedSchedUninstallWebs)" Message="!(loc.msierrIISFailedSchedUninstallWebs)" />
-        <Error Id="$(var.msierrIISFailedSchedUninstallWebDirs)" Message="!(loc.msierrIISFailedSchedUninstallWebDirs)" />
-        <Error Id="$(var.msierrIISFailedSchedUninstallVDirs)" Message="!(loc.msierrIISFailedSchedUninstallVDirs)" />
-        <Error Id="$(var.msierrIISFailedSchedUninstallFilters)" Message="!(loc.msierrIISFailedSchedUninstallFilters)" />
-        <Error Id="$(var.msierrIISFailedSchedUninstallAppPool)" Message="!(loc.msierrIISFailedSchedUninstallAppPool)" />
-        <Error Id="$(var.msierrIISFailedSchedUninstallProp)" Message="!(loc.msierrIISFailedSchedUninstallProp)" />
-        <Error Id="$(var.msierrIISFailedSchedUninstallWebSvcExt)" Message="!(loc.msierrIISFailedSchedUninstallWebSvcExt)" />
-
-        <Error Id="$(var.msierrIISFailedStartTransaction)" Message="!(loc.msierrIISFailedStartTransaction)" />
-        <Error Id="$(var.msierrIISFailedOpenKey)" Message="!(loc.msierrIISFailedOpenKey)" />
-        <Error Id="$(var.msierrIISFailedCreateKey)" Message="!(loc.msierrIISFailedCreateKey)" />
-        <Error Id="$(var.msierrIISFailedWriteData)" Message="!(loc.msierrIISFailedWriteData)" />
-        <Error Id="$(var.msierrIISFailedCreateApp)" Message="!(loc.msierrIISFailedCreateApp)" />
-        <Error Id="$(var.msierrIISFailedDeleteKey)" Message="!(loc.msierrIISFailedDeleteKey)" />
-        <Error Id="$(var.msierrIISFailedDeleteValue)" Message="!(loc.msierrIISFailedDeleteValue)" />
-        <Error Id="$(var.msierrIISFailedCommitInUse)" Message="!(loc.msierrIISFailedCommitInUse)" />
-      </UI>
-    </Fragment>
-</Wix>
diff --git a/src/wixlib/IIsExtension_Platform.wxi b/src/wixlib/IIsExtension_Platform.wxi
deleted file mode 100644
index 09562a69..00000000
--- a/src/wixlib/IIsExtension_Platform.wxi
+++ /dev/null
@@ -1,66 +0,0 @@
-<!-- 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. -->
-
-
-<Include xmlns="http://wixtoolset.org/schemas/v4/wxs">
-  <?include caDecor.wxi ?>
-  
-  <Fragment>
-    <UIRef Id="WixIIsErrors" />
-    <UI>
-      <ProgressText Action="$(var.Prefix)ConfigureIIs$(var.Suffix)" Message="!(loc.ConfigureIIs)" />
-      <ProgressText Action="$(var.Prefix)ConfigureIIsExec$(var.Suffix)" Message="!(loc.ConfigureIIsExec)" />
-      <ProgressText Action="$(var.Prefix)StartMetabaseTransaction$(var.Suffix)" Message="!(loc.StartMetabaseTransaction)" />
-      <ProgressText Action="$(var.Prefix)RollbackMetabaseTransaction$(var.Suffix)" Message="!(loc.RollbackMetabaseTransaction)" />
-      <ProgressText Action="$(var.Prefix)CommitMetabaseTransaction$(var.Suffix)" Message="!(loc.CommitMetabaseTransaction)" />
-      <ProgressText Action="$(var.Prefix)WriteMetabaseChanges$(var.Suffix)" Message="!(loc.WriteMetabaseChanges)" />
-
-      <ProgressText Action="$(var.Prefix)ConfigureIIs7Exec$(var.Suffix)" Message="!(loc.ConfigureIIs7Exec)" />
-      <ProgressText Action="$(var.Prefix)StartIIS7ConfigTransaction$(var.Suffix)" Message="!(loc.StartIIS7ConfigTransaction)" />
-      <ProgressText Action="$(var.Prefix)RollbackIIS7ConfigTransaction$(var.Suffix)" Message="!(loc.RollbackIIS7ConfigTransaction)" />
-      <ProgressText Action="$(var.Prefix)CommitIIS7ConfigTransaction$(var.Suffix)" Message="!(loc.CommitIIS7ConfigTransaction)" />
-      <ProgressText Action="$(var.Prefix)WriteIIS7ConfigChanges$(var.Suffix)" Message="!(loc.WriteIIS7ConfigChanges)" />
-    </UI>
-
-    <CustomAction Id="$(var.Prefix)ConfigureIIs$(var.Suffix)" DllEntry="ConfigureIIs" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
-    <CustomAction Id="$(var.Prefix)ConfigureIIsExec$(var.Suffix)" DllEntry="ConfigureIIsExec" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
-    <CustomAction Id="$(var.Prefix)StartMetabaseTransaction$(var.Suffix)" DllEntry="StartMetabaseTransaction" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
-    <CustomAction Id="$(var.Prefix)RollbackMetabaseTransaction$(var.Suffix)" DllEntry="RollbackMetabaseTransaction" Impersonate="no" Execute="rollback" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
-    <CustomAction Id="$(var.Prefix)CommitMetabaseTransaction$(var.Suffix)" DllEntry="CommitMetabaseTransaction" Impersonate="no" Execute="commit" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
-    <CustomAction Id="$(var.Prefix)WriteMetabaseChanges$(var.Suffix)" DllEntry="WriteMetabaseChanges" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
-
-    <CustomAction Id="$(var.Prefix)ConfigureIIs7Exec$(var.Suffix)" DllEntry="ConfigureIIs7Exec" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
-    <CustomAction Id="$(var.Prefix)StartIIS7ConfigTransaction$(var.Suffix)" DllEntry="StartIIS7ConfigTransaction" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
-    <CustomAction Id="$(var.Prefix)RollbackIIS7ConfigTransaction$(var.Suffix)" DllEntry="RollbackIIS7ConfigTransaction" Impersonate="no" Execute="rollback" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
-    <CustomAction Id="$(var.Prefix)CommitIIS7ConfigTransaction$(var.Suffix)" DllEntry="CommitIIS7ConfigTransaction" Impersonate="no" Execute="commit" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
-    <CustomAction Id="$(var.Prefix)WriteIIS7ConfigChanges$(var.Suffix)" DllEntry="WriteIIS7ConfigChanges" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
-
-    <InstallExecuteSequence>
-      <Custom Action="$(var.Prefix)ConfigureIIs$(var.Suffix)" Before="RegisterUser" Overridable="yes" Condition="NOT SKIPCONFIGUREIIS AND VersionNT &gt; 400" />
-    </InstallExecuteSequence>
-  </Fragment>
-
-  <Fragment>
-    <Binary Id="IisCA$(var.Suffix)" SourceFile="!(bindpath.$(var.platform))iisca.dll" />
-  </Fragment>
-
-  <Fragment>
-    <CustomAction Id="$(var.Prefix)InstallCertificates$(var.Suffix)" DllEntry="InstallCertificates" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
-    <CustomAction Id="$(var.Prefix)UninstallCertificates$(var.Suffix)" DllEntry="UninstallCertificates" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
-
-    <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)" />
-    <CustomAction Id="$(var.Prefix)AddMachineCertificate$(var.Suffix)" DllEntry="AddMachineCertificate" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
-    <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)" />
-    <CustomAction Id="$(var.Prefix)DeleteMachineCertificate$(var.Suffix)" DllEntry="DeleteMachineCertificate" Impersonate="no" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
-
-    <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)" />
-    <CustomAction Id="$(var.Prefix)RollbackAddMachineCertificate$(var.Suffix)" DllEntry="DeleteMachineCertificate" Impersonate="no" Execute="rollback" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
-    <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)" />
-    <CustomAction Id="$(var.Prefix)RollbackDeleteMachineCertificate$(var.Suffix)" DllEntry="AddMachineCertificate" Impersonate="no" Execute="rollback" Return="check" HideTarget="yes" SuppressModularization="yes" BinaryRef="IisCA$(var.Suffix)" />
-
-    <InstallExecuteSequence>
-      <Custom Action="UninstallCertificates$(var.Suffix)" Before="RemoveFiles" Overridable="yes" Condition="VersionNT &gt; 400" />
-      <Custom Action="InstallCertificates$(var.Suffix)" After="InstallFiles" Overridable="yes" Condition="VersionNT &gt; 400" />
-    </InstallExecuteSequence>
-  </Fragment>
-
-</Include>
diff --git a/src/wixlib/IIsExtension_arm64.wxs b/src/wixlib/IIsExtension_arm64.wxs
deleted file mode 100644
index 39ac048f..00000000
--- a/src/wixlib/IIsExtension_arm64.wxs
+++ /dev/null
@@ -1,7 +0,0 @@
-<!-- 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. -->
-
-
-<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
-    <?define platform=arm64 ?>
-    <?include IIsExtension_Platform.wxi ?>
-</Wix>
diff --git a/src/wixlib/IIsExtension_x64.wxs b/src/wixlib/IIsExtension_x64.wxs
deleted file mode 100644
index 553953b3..00000000
--- a/src/wixlib/IIsExtension_x64.wxs
+++ /dev/null
@@ -1,7 +0,0 @@
-<!-- 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. -->
-
-
-<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
-    <?define platform=x64 ?>
-    <?include IIsExtension_Platform.wxi ?>
-</Wix>
diff --git a/src/wixlib/IIsExtension_x86.wxs b/src/wixlib/IIsExtension_x86.wxs
deleted file mode 100644
index c99a243b..00000000
--- a/src/wixlib/IIsExtension_x86.wxs
+++ /dev/null
@@ -1,7 +0,0 @@
-<!-- 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. -->
-
-
-<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
-    <?define platform=x86 ?>
-    <?include IIsExtension_Platform.wxi ?>
-</Wix>
diff --git a/src/wixlib/caDecor.wxi b/src/wixlib/caDecor.wxi
deleted file mode 100644
index b1711518..00000000
--- a/src/wixlib/caDecor.wxi
+++ /dev/null
@@ -1,39 +0,0 @@
-<!-- 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. -->
-
-
-<Include xmlns="http://wixtoolset.org/schemas/v4/wxs">
-    <?ifdef Prefix ?>
-        <?undef Prefix ?>
-    <?endif?>
-
-    <?define Prefix="Wix4" ?>
-
-    <?ifndef platform ?>
-        <?define platform="x86" ?>
-    <?endif?>
-
-    <?if $(var.platform)="" ?>
-        <?undef platform ?>
-        <?define platform="x86" ?>
-    <?endif?>
-
-    <?ifdef Suffix ?>
-        <?undef Suffix ?>
-    <?endif?>
-
-    <?if $(var.platform)~="x86" ?>
-        <?define Suffix="_X86" ?>
-    <?endif?>
-
-    <?if $(var.platform)~="x64" ?>
-        <?define Suffix="_X64" ?>
-    <?endif?>
-
-    <?if $(var.platform)~="arm" ?>
-        <?define Suffix="_A32" ?>
-    <?endif?>
-
-    <?if $(var.platform)~="arm64" ?>
-        <?define Suffix="_A64" ?>
-    <?endif?>
-</Include>
diff --git a/src/wixlib/caerr.wxi b/src/wixlib/caerr.wxi
deleted file mode 100644
index ff7ec121..00000000
--- a/src/wixlib/caerr.wxi
+++ /dev/null
@@ -1,96 +0,0 @@
-<Include xmlns="http://wixtoolset.org/schemas/v4/wxs">
-  <?define msierrSecureObjectsFailedCreateSD = 25520?>
-  <?define msierrSecureObjectsFailedSet = 25521?>
-  <?define msierrSecureObjectsUnknownType = 25522?>
-  <?define msierrXmlFileFailedRead = 25530?>
-  <?define msierrXmlFileFailedOpen = 25531?>
-  <?define msierrXmlFileFailedSelect = 25532?>
-  <?define msierrXmlFileFailedSave = 25533?>
-  <?define msierrXmlConfigFailedRead = 25540?>
-  <?define msierrXmlConfigFailedOpen = 25541?>
-  <?define msierrXmlConfigFailedSelect = 25542?>
-  <?define msierrXmlConfigFailedSave = 25543?>
-  <?define msierrFirewallCannotConnect = 25580?>
-  <?define msierrIISCannotConnect = 26001?>
-  <?define msierrIISFailedReadWebSite = 26002?>
-  <?define msierrIISFailedReadWebDirs = 26003?>
-  <?define msierrIISFailedReadVDirs = 26004?>
-  <?define msierrIISFailedReadFilters = 26005?>
-  <?define msierrIISFailedReadAppPool = 26006?>
-  <?define msierrIISFailedReadMimeMap = 26007?>
-  <?define msierrIISFailedReadProp = 26008?>
-  <?define msierrIISFailedReadWebSvcExt = 26009?>
-  <?define msierrIISFailedReadWebError = 26010?>
-  <?define msierrIISFailedReadHttpHeader = 26011?>
-  <?define msierrIISFailedSchedTransaction = 26031?>
-  <?define msierrIISFailedSchedInstallWebs = 26032?>
-  <?define msierrIISFailedSchedInstallWebDirs = 26033?>
-  <?define msierrIISFailedSchedInstallVDirs = 26034?>
-  <?define msierrIISFailedSchedInstallFilters = 26035?>
-  <?define msierrIISFailedSchedInstallAppPool = 26036?>
-  <?define msierrIISFailedSchedInstallProp = 26037?>
-  <?define msierrIISFailedSchedInstallWebSvcExt = 26038?>
-  <?define msierrIISFailedSchedUninstallWebs = 26051?>
-  <?define msierrIISFailedSchedUninstallWebDirs = 26052?>
-  <?define msierrIISFailedSchedUninstallVDirs = 26053?>
-  <?define msierrIISFailedSchedUninstallFilters = 26054?>
-  <?define msierrIISFailedSchedUninstallAppPool = 26055?>
-  <?define msierrIISFailedSchedUninstallProp = 26056?>
-  <?define msierrIISFailedSchedUninstallWebSvcExt = 26057?>
-  <?define msierrIISFailedStartTransaction = 26101?>
-  <?define msierrIISFailedOpenKey = 26102?>
-  <?define msierrIISFailedCreateKey = 26103?>
-  <?define msierrIISFailedWriteData = 26104?>
-  <?define msierrIISFailedCreateApp = 26105?>
-  <?define msierrIISFailedDeleteKey = 26106?>
-  <?define msierrIISFailedDeleteApp = 26107?>
-  <?define msierrIISFailedDeleteValue = 26108?>
-  <?define msierrIISFailedCommitInUse = 26109?>
-  <?define msierrSQLFailedCreateDatabase = 26201?>
-  <?define msierrSQLFailedDropDatabase = 26202?>
-  <?define msierrSQLFailedConnectDatabase = 26203?>
-  <?define msierrSQLFailedExecString = 26204?>
-  <?define msierrSQLDatabaseAlreadyExists = 26205?>
-  <?define msierrPERFMONFailedRegisterDLL = 26251?>
-  <?define msierrPERFMONFailedUnregisterDLL = 26252?>
-  <?define msierrInstallPerfCounterData = 26253?>
-  <?define msierrUninstallPerfCounterData = 26254?>
-  <?define msierrSMBFailedCreate = 26301?>
-  <?define msierrSMBFailedDrop = 26302?>
-  <?define msierrCERTFailedOpen = 26351?>
-  <?define msierrCERTFailedAdd = 26352?>
-  <?define msierrUSRFailedUserCreate = 26401?>
-  <?define msierrUSRFailedUserCreatePswd = 26402?>
-  <?define msierrUSRFailedUserGroupAdd = 26403?>
-  <?define msierrUSRFailedUserCreateExists = 26404?>
-  <?define msierrUSRFailedGrantLogonAsService = 26405?>
-  <?define msierrDependencyMissingDependencies = 26451?>
-  <?define msierrDependencyHasDependents = 26452?>
-  <?define msierrDotNetRuntimeRequired = 27000?>
-  <?define msierrComPlusCannotConnect = 28001?>
-  <?define msierrComPlusPartitionReadFailed = 28002?>
-  <?define msierrComPlusPartitionRoleReadFailed = 28003?>
-  <?define msierrComPlusUserInPartitionRoleReadFailed = 28004?>
-  <?define msierrComPlusPartitionUserReadFailed = 28005?>
-  <?define msierrComPlusApplicationReadFailed = 28006?>
-  <?define msierrComPlusApplicationRoleReadFailed = 28007?>
-  <?define msierrComPlusUserInApplicationRoleReadFailed = 28008?>
-  <?define msierrComPlusAssembliesReadFailed = 28009?>
-  <?define msierrComPlusSubscriptionReadFailed = 28010?>
-  <?define msierrComPlusPartitionDependency = 28011?>
-  <?define msierrComPlusPartitionNotFound = 28012?>
-  <?define msierrComPlusPartitionIdConflict = 28013?>
-  <?define msierrComPlusPartitionNameConflict = 28014?>
-  <?define msierrComPlusApplicationDependency = 28015?>
-  <?define msierrComPlusApplicationNotFound = 28016?>
-  <?define msierrComPlusApplicationIdConflict = 28017?>
-  <?define msierrComPlusApplicationNameConflict = 28018?>
-  <?define msierrComPlusApplicationRoleDependency = 28019?>
-  <?define msierrComPlusApplicationRoleNotFound = 28020?>
-  <?define msierrComPlusApplicationRoleConflict = 28021?>
-  <?define msierrComPlusAssemblyDependency = 28022?>
-  <?define msierrComPlusSubscriptionIdConflict = 28023?>
-  <?define msierrComPlusSubscriptionNameConflict = 28024?>
-  <?define msierrComPlusFailedLookupNames = 28025?>
-  <?define msierrMsmqCannotConnect = 28101?>
-</Include>
\ No newline at end of file
diff --git a/src/wixlib/de-de.wxl b/src/wixlib/de-de.wxl
deleted file mode 100644
index 5929f258..00000000
--- a/src/wixlib/de-de.wxl
+++ /dev/null
@@ -1,55 +0,0 @@
-<!-- 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. -->
-
-
-<WixLocalization Culture="de-de" xmlns="http://wixtoolset.org/schemas/v4/wxl">
-    <String Id="msierrIISCannotConnect" Overridable="yes">Konnte keine Verbindung mit dem Internet Information Server herstellen.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadWebSite" Overridable="yes">Fehler bei der Verarbeitung der WebSites.   ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadWebDirs" Overridable="yes">Fehler bei der Verarbeitung der WebDirs.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadVDirs" Overridable="yes">Fehler bei der Verarbeitung der WebVirtualDirs.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadFilters" Overridable="yes">Fehler bei der Verarbeitung der WebFilters.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadMimeMap" Overridable="yes">Fehler bei der Verarbeitung der MimeMaps. ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadAppPool" Overridable="yes">Fehler bei der Verarbeitung der WebAppPools. ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadProp" Overridable="yes">Fehler bei der Verarbeitung der WebProperties. ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadWebSvcExt" Overridable="yes">Fehler bei der Verarbeitung der WebServiceExtensions. ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadWebError" Overridable="yes">Fehler bei der Verarbeitung der WebErrors. ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadHttpHeader" Overridable="yes">Fehler bei der Verarbeitung der HttpHeader. ([2]   [3]   [4]   [5])</String>
-
-    <String Id="msierrIISFailedSchedTransaction" Overridable="yes">Die Transaktion für Änderungen am IIS konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallWebs" Overridable="yes">Die Installation von IIS-Websites konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallWebDirs" Overridable="yes">Die Installation von IIS Web Directories konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallVDirs" Overridable="yes">Die Installation von IIS Virtual Directories konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallFilters" Overridable="yes">Die Installation von IIS Filters konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallAppPool" Overridable="yes">Die Installation von IIS AppPools konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallProp" Overridable="yes">Die Installation von IIS Properties konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallWebSvcExt" Overridable="yes">Die Installation von IIS Web Service Extensions konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
-
-    <String Id="msierrIISFailedSchedUninstallWebs" Overridable="yes">Die Deinstallation von IIS Web Sites konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallWebDirs" Overridable="yes">Die Deinstallation von IIS Web Directories konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallVDirs" Overridable="yes">Die Deinstallation von IIS Virtual Directories konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallFilters" Overridable="yes">Die Deinstallation von IIS Filters konnte nicht geschedulded werden.   ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallAppPool" Overridable="yes">Die Deinstallation von IIS AppPools konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallProp" Overridable="yes">Die Deinstallation der IIS Properties konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallWebSvcExt" Overridable="yes">Die Deinstallation von IIS Web Service Extensions konnte nicht geschedulded werden.  ([2]   [3]   [4]   [5])</String>
-
-    <String Id="msierrIISFailedStartTransaction" Overridable="yes">Die IIS-Transaktion konnte nicht gestartet werden. ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedOpenKey" Overridable="yes">Der Metabase Key konnte nicht geöffnet werden.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedCreateKey" Overridable="yes">Der Metabase Key konnte nicht erstellt werden.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedWriteData" Overridable="yes">Daten konnten nicht in den Metabase Key geschrieben werden.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedCreateApp" Overridable="yes">Webanwendung konnte nicht erstellt werden.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedDeleteKey" Overridable="yes">Der Metabase Key konnte nicht gelöscht werden.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedDeleteValue" Overridable="yes">Der Metabase Value konnte nicht gelöscht werden.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedCommitInUse" Overridable="yes">Die IIS Transaktion konnte aufgrund einer Freigabeverletzung nicht committed werden. Möglicherweise konfiguriert eine andere Anwendung derzeit IIS.</String>
-
-    <String Id="ConfigureIIs" Overridable="yes">Konfiguriere IIS</String>
-    <String Id="ConfigureIIsExec" Overridable="yes">Führe IIS Konfiguration aus</String>
-    <String Id="StartMetabaseTransaction" Overridable="yes">Starte IIS Metabase Transaktion</String>
-    <String Id="RollbackMetabaseTransaction" Overridable="yes">Mache IIS Metabase Transaktion rückgängig</String>
-    <String Id="CommitMetabaseTransaction" Overridable="yes">Committe IIS Metabase Transaktion</String>
-    <String Id="WriteMetabaseChanges" Overridable="yes">Installiere Metabase Keys und Values</String>
-
-    <String Id="ConfigureIIs7Exec" Overridable="yes">Konfiguriere IIS</String>
-    <String Id="StartIIS7ConfigTransaction" Overridable="yes">Starte IIS Konfigurationstransaktion</String>
-    <String Id="RollbackIIS7ConfigTransaction" Overridable="yes">Mache IIS Konfigurationstransaktion rückgängig</String>
-    <String Id="CommitIIS7ConfigTransaction" Overridable="yes">Committe IIS Konfigurationstransaktion</String>
-    <String Id="WriteIIS7ConfigChanges" Overridable="yes">Installiere Konfigurationskeys and -values</String>
-</WixLocalization>
diff --git a/src/wixlib/en-us.wxl b/src/wixlib/en-us.wxl
deleted file mode 100644
index 44949095..00000000
--- a/src/wixlib/en-us.wxl
+++ /dev/null
@@ -1,55 +0,0 @@
-<!-- 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. -->
-
-
-<WixLocalization Culture="en-us" xmlns="http://wixtoolset.org/schemas/v4/wxl">
-    <String Id="msierrIISCannotConnect" Overridable="yes">Cannot connect to Internet Information Server.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadWebSite" Overridable="yes">Failed while processing WebSites.   ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadWebDirs" Overridable="yes">Failed while processing WebDirs.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadVDirs" Overridable="yes">Failed while processing WebVirtualDirs.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadFilters" Overridable="yes">Failed while processing WebFilters.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadMimeMap" Overridable="yes">Failed while processing MimeMaps. ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadAppPool" Overridable="yes">Failed while processing WebAppPools. ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadProp" Overridable="yes">Failed while processing WebProperties. ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadWebSvcExt" Overridable="yes">Failed while processing WebServiceExtensions. ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadWebError" Overridable="yes">Failed while processing WebErrors. ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadHttpHeader" Overridable="yes">Failed while processing HttpHeaders. ([2]   [3]   [4]   [5])</String>
-
-    <String Id="msierrIISFailedSchedTransaction" Overridable="yes">Failed to schedule transaction for changes to IIS.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallWebs" Overridable="yes">Failed to schedule install of IIS Web Sites.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallWebDirs" Overridable="yes">Failed to schedule install of IIS Web Directories.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallVDirs" Overridable="yes">Failed to schedule install of IIS Virtual Directories.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallFilters" Overridable="yes">Failed to schedule install of IIS Filters.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallAppPool" Overridable="yes">Failed to schedule install of IIS AppPools.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallProp" Overridable="yes">Failed to schedule install of IIS Properties.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallWebSvcExt" Overridable="yes">Failed to schedule install of IIS Web Service Extensions.  ([2]   [3]   [4]   [5])</String>
-
-    <String Id="msierrIISFailedSchedUninstallWebs" Overridable="yes">Failed to schedule uninstall of IIS Web Sites.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallWebDirs" Overridable="yes">Failed to schedule uninstall of IIS Web Directories.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallVDirs" Overridable="yes">Failed to schedule uninstall of IIS Virtual Directories.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallFilters" Overridable="yes">Failed to schedule uninstall of IIS Filters.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallAppPool" Overridable="yes">Failed to schedule uninstall of IIS AppPools.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallProp" Overridable="yes">Failed to schedule uninstall of IIS Properties.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallWebSvcExt" Overridable="yes">Failed to schedule uninstall of IIS Web Service Extensions.  ([2]   [3]   [4]   [5])</String>
-
-    <String Id="msierrIISFailedStartTransaction" Overridable="yes">Failed to start IIS transaction. ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedOpenKey" Overridable="yes">Failed to open metabase key.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedCreateKey" Overridable="yes">Failed to create metabase key.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedWriteData" Overridable="yes">Failed to write data to metabase key.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedCreateApp" Overridable="yes">Failed to create web application.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedDeleteKey" Overridable="yes">Failed to delete metabase key.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedDeleteValue" Overridable="yes">Failed to delete metabase value.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedCommitInUse" Overridable="yes">Failed to commit IIS transaction due to a sharing violation.  Some other application may be configuring IIS.</String>
-
-    <String Id="ConfigureIIs" Overridable="yes">Configuring IIS</String>
-    <String Id="ConfigureIIsExec" Overridable="yes">Executing IIS Configuration</String>
-    <String Id="StartMetabaseTransaction" Overridable="yes">Starting IIS Metabase Transaction</String>
-    <String Id="RollbackMetabaseTransaction" Overridable="yes">Rolling back IIS Metabase Transaction</String>
-    <String Id="CommitMetabaseTransaction" Overridable="yes">Committing IIS Metabase Transaction</String>
-    <String Id="WriteMetabaseChanges" Overridable="yes">Installing Metabase Keys and Values</String>
-
-    <String Id="ConfigureIIs7Exec" Overridable="yes">Configuring IIS</String>
-    <String Id="StartIIS7ConfigTransaction" Overridable="yes">Starting IIS Config Transaction</String>
-    <String Id="RollbackIIS7ConfigTransaction" Overridable="yes">Rolling back IIS Config Transaction</String>
-    <String Id="CommitIIS7ConfigTransaction" Overridable="yes">Committing IIS Config Transaction</String>
-    <String Id="WriteIIS7ConfigChanges" Overridable="yes">Installing Config Keys and Values</String>
-</WixLocalization>
diff --git a/src/wixlib/iis.v3.ncrunchproject b/src/wixlib/iis.v3.ncrunchproject
deleted file mode 100644
index 319cd523..00000000
--- a/src/wixlib/iis.v3.ncrunchproject
+++ /dev/null
@@ -1,5 +0,0 @@
-<ProjectConfiguration>
-  <Settings>
-    <IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
-  </Settings>
-</ProjectConfiguration>
\ No newline at end of file
diff --git a/src/wixlib/iis.wixproj b/src/wixlib/iis.wixproj
deleted file mode 100644
index 89f9608f..00000000
--- a/src/wixlib/iis.wixproj
+++ /dev/null
@@ -1,26 +0,0 @@
-<!-- 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. -->
-<Project Sdk="WixToolset.Sdk">
-
-  <PropertyGroup>
-    <OutputType>Library</OutputType>
-    <BindFiles>true</BindFiles>
-    <Cultures>en-us</Cultures>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <BindInputPaths Include="$(OutputPath)x86" BindName='x86' />
-    <BindInputPaths Include="$(OutputPath)x64" BindName='x64' />
-    <BindInputPaths Include="$(OutputPath)arm64" BindName='arm64' />
-  </ItemGroup>
-
-  <ItemGroup>
-    <ProjectReference Include="..\ca\iisca.vcxproj" Properties="Platform=ARM64" />
-    <ProjectReference Include="..\ca\iisca.vcxproj" Properties="Platform=x86" />
-    <ProjectReference Include="..\ca\iisca.vcxproj" Properties="Platform=x64" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Nerdbank.GitVersioning" Version="2.1.65" PrivateAssets="All" />
-  </ItemGroup>
-
-</Project>
diff --git a/src/wixlib/ja-jp.wxl b/src/wixlib/ja-jp.wxl
deleted file mode 100644
index 7fd6978a..00000000
--- a/src/wixlib/ja-jp.wxl
+++ /dev/null
@@ -1,47 +0,0 @@
-<!-- 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. -->
-
-
-<WixLocalization Culture="ja-jp" xmlns="http://wixtoolset.org/schemas/v4/wxl">
-  <String Id="msierrIISCannotConnect" Overridable="yes">IISへ接続できません。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedReadWebSite" Overridable="yes">ウェブ サイト処理中に失敗しました。   ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedReadWebDirs" Overridable="yes">ウェブ ディレクトリ処理中に失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedReadVDirs" Overridable="yes">ウェブ仮想ディレクトリ処理中に失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedReadFilters" Overridable="yes">ウェブ フィルタ処理中に失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedReadMimeMap" Overridable="yes">MIME マップ処理中に失敗しました。 ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedReadAppPool" Overridable="yes">ウェブ アプリケーション プール処理中に失敗しました。 ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedReadProp" Overridable="yes">ウェブ プロパティ処理中に失敗しました。 ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedReadWebSvcExt" Overridable="yes">ウェブ サービス拡張処理中に失敗しました。 ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedReadWebError" Overridable="yes">ウェブ エラー処理中に失敗しました。 ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedReadHttpHeader" Overridable="yes">HTTP ヘッダ処理中に失敗しました。 ([2]   [3]   [4]   [5])</String>
-
-  <String Id="msierrIISFailedSchedTransaction" Overridable="yes">IIS 変更トランザクションのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedSchedInstallWebs" Overridable="yes">IIS ウェブ サイト インストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedSchedInstallWebDirs" Overridable="yes">IIS ウェブ ディレクトリ インストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedSchedInstallVDirs" Overridable="yes">IIS 仮想ディレクトリ インストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedSchedInstallFilters" Overridable="yes">IIS フィルタ インストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedSchedInstallAppPool" Overridable="yes">IIS アプリケーション プール インストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedSchedInstallProp" Overridable="yes">IIS プロパティ インストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedSchedInstallWebSvcExt" Overridable="yes">IIS ウェブ サービス拡張インストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
-
-  <String Id="msierrIISFailedSchedUninstallWebs" Overridable="yes">IISウェブ サイト アンインストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedSchedUninstallWebDirs" Overridable="yes">IIS ウェブ ディレクトリ アンインストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedSchedUninstallVDirs" Overridable="yes">IIS 仮想ディレクトリ アンインストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedSchedUninstallFilters" Overridable="yes">IIS フィルタ アンインストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedSchedUninstallAppPool" Overridable="yes">IIS アプリケーション プール アンインストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedSchedUninstallProp" Overridable="yes">IIS プロパティ アンインストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedSchedUninstallWebSvcExt" Overridable="yes">IIS ウェブ サービス拡張アンインストールのスケジューリングに失敗しました。  ([2]   [3]   [4]   [5])</String>
-
-  <String Id="msierrIISFailedStartTransaction" Overridable="yes">IIS トランザクション開始に失敗しました。 ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedOpenKey" Overridable="yes">メタベース キーのオープンに失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedCreateKey" Overridable="yes">メタベース キーの作成に失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedWriteData" Overridable="yes">メタベース キーの書き込みに失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedCreateApp" Overridable="yes">ウェブ アプリケーションの作成に失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedDeleteKey" Overridable="yes">メタベース キーの削除に失敗しました。  ([2]   [3]   [4]   [5])</String>
-  <String Id="msierrIISFailedDeleteValue" Overridable="yes">メタベース値の削除に失敗しました。  ([2]   [3]   [4]   [5])</String>
-
-  <String Id="ConfigureIIs" Overridable="yes">IIS を構成しています</String>
-  <String Id="StartMetabaseTransaction" Overridable="yes">IIS メタベース トランザクションを開始しています</String>
-  <String Id="RollbackMetabaseTransaction" Overridable="yes">IIS メタベース トランザクションをロールバックしています</String>
-  <String Id="CommitMetabaseTransaction" Overridable="yes">IIS メタベース トランザクションを確定しています</String>
-  <String Id="WriteMetabaseChanges" Overridable="yes">IIS メタベース キーと値をインストールしています</String>
-</WixLocalization>
diff --git a/src/wixlib/pt-br.wxl b/src/wixlib/pt-br.wxl
deleted file mode 100644
index 1fc0d768..00000000
--- a/src/wixlib/pt-br.wxl
+++ /dev/null
@@ -1,50 +0,0 @@
-<!-- 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. -->
-
-
-<WixLocalization Culture="pt-br" xmlns="http://wixtoolset.org/schemas/v4/wxl">
-    <String Id="msierrIISCannotConnect" Overridable="yes">Não foi possível conectar no Internet Information Server.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadWebSite" Overridable="yes">Erro ao processar WebSites.   ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadWebDirs" Overridable="yes">Erro ao processar WebDirs.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadVDirs" Overridable="yes">Erro ao processar WebVirtualDirs.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadFilters" Overridable="yes">Erro ao processar WebFilters.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadMimeMap" Overridable="yes">Erro ao processar MimeMaps. ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadAppPool" Overridable="yes">Erro ao processar WebAppPools. ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadProp" Overridable="yes">Erro ao processar WebProperties. ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadWebSvcExt" Overridable="yes">Erro ao processar WebServiceExtensions. ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadWebError" Overridable="yes">Erro ao processar WebErrors. ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedReadHttpHeader" Overridable="yes">Erro ao processar HttpHeaders. ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedTransaction" Overridable="yes">Erro ao agendar transação para alterações no IIS.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallWebs" Overridable="yes">Erro ao agendar instalação de IIS Web Sites.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallWebDirs" Overridable="yes">Erro ao agendar instalação de IIS Web Directories.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallVDirs" Overridable="yes">Erro ao agendar instalação de IIS Virtual Directories.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallFilters" Overridable="yes">Erro ao agendar instalação de IIS Filters.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallAppPool" Overridable="yes">Erro ao agendar instalação de IIS AppPools.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallProp" Overridable="yes">Erro ao agendar instalação de IIS Properties.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedInstallWebSvcExt" Overridable="yes">Erro ao agendar instalação de IIS Web Service Extensions.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallWebs" Overridable="yes">Erro ao agendar desinstalação de IIS Web Sites.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallWebDirs" Overridable="yes">Erro ao agendar desinstalação de IIS Web Directories.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallVDirs" Overridable="yes">Erro ao agendar desinstalação de IIS Virtual Directories.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallFilters" Overridable="yes">Erro ao agendar desinstalação de IIS Filters.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallAppPool" Overridable="yes">Erro ao agendar desinstalação de IIS AppPools.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallProp" Overridable="yes">Erro ao agendar desinstalação de IIS Properties.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedSchedUninstallWebSvcExt" Overridable="yes">Erro ao agendar desinstalação de IIS Web Service Extensions.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedStartTransaction" Overridable="yes">Erro ao iniciar transação do IIS . ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedOpenKey" Overridable="yes">Erro ao abrir metabase key.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedCreateKey" Overridable="yes">Erro ao criar metabase key.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedWriteData" Overridable="yes">Erro ao escrever dados na metabase key.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedCreateApp" Overridable="yes">Erro ao criar aplicação Web.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedDeleteKey" Overridable="yes">Erro ao excluir metabase key.  ([2]   [3]   [4]   [5])</String>
-    <String Id="msierrIISFailedDeleteValue" Overridable="yes">Erro ao excluir valor da metabase.  ([2]   [3]   [4]   [5])</String>
-    <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>
-    <String Id="ConfigureIIs" Overridable="yes">Configurando IIS</String>
-    <String Id="ConfigureIIsExec" Overridable="yes">Executando Configurações do IIS</String>
-    <String Id="StartMetabaseTransaction" Overridable="yes">Iniciando Transação de Metabase do IIS</String>
-    <String Id="RollbackMetabaseTransaction" Overridable="yes">Cancelando Transação de Metabase do IIS</String>
-    <String Id="CommitMetabaseTransaction" Overridable="yes">Efetivando Transação de Metabase do IIS</String>
-    <String Id="WriteMetabaseChanges" Overridable="yes">Instalando Chaves e Valores de Metabase do IIS</String>
-    <String Id="ConfigureIIs7Exec" Overridable="yes">Configurando IIS</String>
-    <String Id="StartIIS7ConfigTransaction" Overridable="yes">Iniciando Transação de Configuração do IIS</String>
-    <String Id="RollbackIIS7ConfigTransaction" Overridable="yes">Cancelando Transação de Configuração do IIS</String>
-    <String Id="CommitIIS7ConfigTransaction" Overridable="yes">Efetivando Transação de Configuração do IIS</String>
-    <String Id="WriteIIS7ConfigChanges" Overridable="yes">Instalando Chaves e Valores de Configurações do IIS</String>
-</WixLocalization>
-- 
cgit v1.2.3-55-g6feb