From ff659159e041bf6c083e6b7fcb9b726065a9dd73 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Mon, 3 May 2021 09:55:22 -0700 Subject: Move Util.wixext into ext --- .editorconfig | 37 - README.md | 3 - Util.wixext.sln | 87 - Util.wixext.v3.ncrunchsolution | 6 - appveyor.cmd | 19 - appveyor.yml | 40 - global.json | 8 - nuget.config | 18 - src/.editorconfig | 37 + src/CustomizedNativeRecommendedRules.ruleset | 8 - src/Directory.Build.props | 27 - src/Directory.Build.targets | 51 - src/Directory.csproj.props | 13 - src/Directory.csproj.targets | 26 - src/Directory.vcxproj.props | 97 - src/be/UtilBundleExtension.cpp | 87 - src/be/UtilBundleExtension.h | 16 - src/be/beDecor.h | 13 - src/be/detectsha2support.cpp | 58 - src/be/detectsha2support.h | 8 - src/be/precomp.cpp | 3 - src/be/precomp.h | 37 - src/be/utilbe.cpp | 41 - src/be/utilbe.def | 8 - src/be/utilbe.vcxproj | 80 - src/be/utilsearch.cpp | 160 - src/be/utilsearch.h | 65 - src/ca/BroadcastSettingChange.cpp | 45 - src/ca/CheckReboot.cpp | 36 - src/ca/CloseApps.cpp | 568 --- src/ca/CustomMsiErrors.h | 32 - src/ca/FormatFiles.cpp | 221 -- src/ca/OsInfo.cpp | 487 --- src/ca/RemoveFoldersEx.cpp | 243 -- src/ca/RemoveRegistryKeysEx.cpp | 114 - src/ca/RestartManager.cpp | 185 - src/ca/TouchFile.cpp | 308 -- src/ca/XmlConfig.cpp | 1130 ------ src/ca/XmlFile.cpp | 940 ----- src/ca/caDecor.h | 13 - src/ca/cost.h | 9 - src/ca/dllmain.cpp | 26 - src/ca/exitearlywithsuccess.cpp | 27 - src/ca/netshortcuts.cpp | 437 --- src/ca/precomp.h | 54 - src/ca/qtexecca.cpp | 316 -- src/ca/sca.h | 19 - src/ca/scacost.h | 18 - src/ca/scaexec.cpp | 1082 ------ src/ca/scamanifest.cpp | 377 -- src/ca/scaperf.cpp | 310 -- src/ca/scaperfexec.cpp | 423 --- src/ca/scasched.cpp | 127 - src/ca/scasmb.h | 46 - src/ca/scasmbexec.cpp | 316 -- src/ca/scasmbexec.h | 27 - src/ca/scasmbsched.cpp | 639 ---- src/ca/scauser.cpp | 709 ---- src/ca/scauser.h | 67 - src/ca/secureobj.cpp | 915 ----- src/ca/serviceconfig.cpp | 821 ----- src/ca/shellexecca.cpp | 271 -- src/ca/test.cpp | 269 -- src/ca/utilca.cpp | 3 - src/ca/utilca.def | 91 - src/ca/utilca.vcxproj | 106 - .../Util/CustomizedNativeRecommendedRules.ruleset | 8 + src/ext/Util/Directory.Build.props | 27 + src/ext/Util/Directory.Build.targets | 51 + src/ext/Util/Directory.csproj.props | 13 + src/ext/Util/Directory.csproj.targets | 26 + src/ext/Util/Directory.vcxproj.props | 97 + src/ext/Util/README.md | 3 + src/ext/Util/Util.wixext.sln | 87 + src/ext/Util/Util.wixext.v3.ncrunchsolution | 6 + src/ext/Util/appveyor.cmd | 19 + src/ext/Util/appveyor.yml | 40 + src/ext/Util/be/UtilBundleExtension.cpp | 87 + src/ext/Util/be/UtilBundleExtension.h | 16 + src/ext/Util/be/beDecor.h | 13 + src/ext/Util/be/detectsha2support.cpp | 58 + src/ext/Util/be/detectsha2support.h | 8 + src/ext/Util/be/precomp.cpp | 3 + src/ext/Util/be/precomp.h | 37 + src/ext/Util/be/utilbe.cpp | 41 + src/ext/Util/be/utilbe.def | 8 + src/ext/Util/be/utilbe.vcxproj | 80 + src/ext/Util/be/utilsearch.cpp | 160 + src/ext/Util/be/utilsearch.h | 65 + src/ext/Util/ca/BroadcastSettingChange.cpp | 45 + src/ext/Util/ca/CheckReboot.cpp | 36 + src/ext/Util/ca/CloseApps.cpp | 568 +++ src/ext/Util/ca/CustomMsiErrors.h | 32 + src/ext/Util/ca/FormatFiles.cpp | 221 ++ src/ext/Util/ca/OsInfo.cpp | 487 +++ src/ext/Util/ca/RemoveFoldersEx.cpp | 243 ++ src/ext/Util/ca/RemoveRegistryKeysEx.cpp | 114 + src/ext/Util/ca/RestartManager.cpp | 185 + src/ext/Util/ca/TouchFile.cpp | 308 ++ src/ext/Util/ca/XmlConfig.cpp | 1130 ++++++ src/ext/Util/ca/XmlFile.cpp | 940 +++++ src/ext/Util/ca/caDecor.h | 13 + src/ext/Util/ca/cost.h | 9 + src/ext/Util/ca/dllmain.cpp | 26 + src/ext/Util/ca/exitearlywithsuccess.cpp | 27 + src/ext/Util/ca/netshortcuts.cpp | 437 +++ src/ext/Util/ca/precomp.h | 54 + src/ext/Util/ca/qtexecca.cpp | 316 ++ src/ext/Util/ca/sca.h | 19 + src/ext/Util/ca/scacost.h | 18 + src/ext/Util/ca/scaexec.cpp | 1082 ++++++ src/ext/Util/ca/scamanifest.cpp | 377 ++ src/ext/Util/ca/scaperf.cpp | 310 ++ src/ext/Util/ca/scaperfexec.cpp | 423 +++ src/ext/Util/ca/scasched.cpp | 127 + src/ext/Util/ca/scasmb.h | 46 + src/ext/Util/ca/scasmbexec.cpp | 316 ++ src/ext/Util/ca/scasmbexec.h | 27 + src/ext/Util/ca/scasmbsched.cpp | 639 ++++ src/ext/Util/ca/scauser.cpp | 709 ++++ src/ext/Util/ca/scauser.h | 67 + src/ext/Util/ca/secureobj.cpp | 915 +++++ src/ext/Util/ca/serviceconfig.cpp | 821 +++++ src/ext/Util/ca/shellexecca.cpp | 271 ++ src/ext/Util/ca/test.cpp | 269 ++ src/ext/Util/ca/utilca.cpp | 3 + src/ext/Util/ca/utilca.def | 91 + src/ext/Util/ca/utilca.vcxproj | 106 + src/ext/Util/nuget.config | 18 + .../WixToolsetTest.Util/TestData/.Data/burn.exe | Bin 0 -> 463360 bytes .../TestData/BundleWithSearches/Bundle.en-us.wxl | 8 + .../TestData/BundleWithSearches/Bundle.wxs | 52 + .../BundleWithSearches/data/MsiPackage/Shared.dll | 1 + .../BundleWithSearches/data/MsiPackage/test.txt | 1 + .../TestData/BundleWithSearches/data/fakeba.dll | 1 + .../TestData/BundleWithSearches/data/test.msi | Bin 0 -> 32768 bytes .../TestData/CloseApplication/Package.en-us.wxl | 9 + .../TestData/CloseApplication/Package.wxs | 17 + .../CloseApplication/PackageComponents.wxs | 9 + .../TestData/CloseApplication/example.txt | 1 + .../TestData/EventManifest/Package.en-us.wxl | 9 + .../TestData/EventManifest/Package.wxs | 15 + .../TestData/EventManifest/PackageComponents.wxs | 11 + .../TestData/EventManifest/example.txt | 1 + .../TestData/InternetShortcut/Package.en-us.wxl | 9 + .../TestData/InternetShortcut/Package.ico | Bin 0 -> 83899 bytes .../TestData/InternetShortcut/Package.wxs | 15 + .../InternetShortcut/PackageComponents.wxs | 11 + .../TestData/InternetShortcut/example.txt | 1 + .../TestData/InternetShortcutModule/Module.wxs | 13 + .../InternetShortcutModule/ModuleComponents.wxs | 11 + .../TestData/InternetShortcutModule/Package.ico | Bin 0 -> 83899 bytes .../TestData/PermissionEx/Package.en-us.wxl | 9 + .../TestData/PermissionEx/Package.wxs | 15 + .../TestData/PermissionEx/PackageComponents.wxs | 23 + .../TestData/PermissionEx/example.txt | 1 + .../TestData/Queries/Package.en-us.wxl | 9 + .../TestData/Queries/Package.wxs | 23 + .../TestData/Queries/PackageComponents.wxs | 9 + .../TestData/Queries/example.txt | 1 + .../TestData/RemoveFolderEx/Module.wxs | 13 + .../TestData/RemoveFolderEx/ModuleComponents.wxs | 10 + .../TestData/RemoveRegistryKeyEx/Module.wxs | 13 + .../RemoveRegistryKeyEx/ModuleComponents.wxs | 10 + .../TestData/UsingFileShare/Package.en-us.wxl | 9 + .../TestData/UsingFileShare/Package.wxs | 15 + .../TestData/UsingFileShare/PackageComponents.wxs | 14 + .../TestData/UsingFileShare/example.txt | 1 + .../TestData/XmlConfig/Package.en-us.wxl | 9 + .../TestData/XmlConfig/Package.wxs | 17 + .../TestData/XmlConfigModule/Module.wxs | 19 + .../TestData/XmlConfigModule/my.xml | 1 + .../WixToolsetTest.Util/UtilExtensionFixture.cs | 317 ++ .../WixToolsetTest.Util/WixToolsetTest.Util.csproj | 38 + .../WixToolsetTest.Util.v3.ncrunchproject | 5 + src/ext/Util/wix.snk | Bin 0 -> 596 bytes src/ext/Util/wixext/PerformanceCounterType.cs | 192 + src/ext/Util/wixext/Symbols/EventManifestSymbol.cs | 55 + .../wixext/Symbols/FileSharePermissionsSymbol.cs | 63 + src/ext/Util/wixext/Symbols/FileShareSymbol.cs | 71 + src/ext/Util/wixext/Symbols/GroupSymbol.cs | 63 + .../Util/wixext/Symbols/PerfmonManifestSymbol.cs | 63 + src/ext/Util/wixext/Symbols/PerfmonSymbol.cs | 63 + .../wixext/Symbols/PerformanceCategorySymbol.cs | 71 + src/ext/Util/wixext/Symbols/SecureObjectsSymbol.cs | 103 + src/ext/Util/wixext/Symbols/ServiceConfigSymbol.cs | 119 + src/ext/Util/wixext/Symbols/UserGroupSymbol.cs | 55 + src/ext/Util/wixext/Symbols/UserSymbol.cs | 79 + .../Util/wixext/Symbols/UtilSymbolDefinitions.cs | 125 + .../wixext/Symbols/WixCloseApplicationSymbol.cs | 103 + .../Util/wixext/Symbols/WixFormatFilesSymbol.cs | 55 + .../wixext/Symbols/WixInternetShortcutSymbol.cs | 95 + .../Util/wixext/Symbols/WixRemoveFolderExSymbol.cs | 78 + .../wixext/Symbols/WixRemoveRegistryKeyExSymbol.cs | 86 + .../wixext/Symbols/WixRestartResourceSymbol.cs | 71 + src/ext/Util/wixext/Symbols/WixTouchFileSymbol.cs | 63 + .../Symbols/WixWindowsFeatureSearchSymbol.cs | 47 + src/ext/Util/wixext/Symbols/XmlConfigSymbol.cs | 111 + src/ext/Util/wixext/Symbols/XmlFileSymbol.cs | 95 + src/ext/Util/wixext/UtilCompiler.cs | 3889 ++++++++++++++++++++ src/ext/Util/wixext/UtilConstants.cs | 17 + src/ext/Util/wixext/UtilDecompiler.cs | 1543 ++++++++ src/ext/Util/wixext/UtilErrors.cs | 49 + src/ext/Util/wixext/UtilExtensionData.cs | 23 + src/ext/Util/wixext/UtilExtensionFactory.cs | 18 + src/ext/Util/wixext/UtilTableDefinitions.cs | 319 ++ src/ext/Util/wixext/UtilWarnings.cs | 37 + .../wixext/UtilWindowsInstallerBackendExtension.cs | 13 + src/ext/Util/wixext/WixToolset.Util.wixext.csproj | 31 + src/ext/Util/wixext/WixToolset.Util.wixext.nuspec | 25 + src/ext/Util/wixext/WixToolset.Util.wixext.targets | 11 + .../WixToolset.Util.wixext.v3.ncrunchproject | 7 + .../Util/wixlib/UtilBundleExtension_Platform.wxi | 10 + src/ext/Util/wixlib/UtilBundleExtension_arm64.wxs | 7 + src/ext/Util/wixlib/UtilBundleExtension_x64.wxs | 7 + src/ext/Util/wixlib/UtilBundleExtension_x86.wxs | 7 + src/ext/Util/wixlib/UtilExtension.wxs | 64 + src/ext/Util/wixlib/UtilExtension_Platform.wxi | 360 ++ src/ext/Util/wixlib/UtilExtension_arm64.wxs | 7 + src/ext/Util/wixlib/UtilExtension_x64.wxs | 7 + src/ext/Util/wixlib/UtilExtension_x86.wxs | 7 + src/ext/Util/wixlib/caDecor.wxi | 39 + src/ext/Util/wixlib/caerr.wxi | 96 + src/ext/Util/wixlib/de-de.wxl | 32 + src/ext/Util/wixlib/en-us.wxl | 32 + src/ext/Util/wixlib/es-es.wxl | 31 + src/ext/Util/wixlib/fr-fr.wxl | 31 + src/ext/Util/wixlib/it-it.wxl | 32 + src/ext/Util/wixlib/ja-jp.wxl | 32 + src/ext/Util/wixlib/pt-br.wxl | 26 + src/ext/Util/wixlib/util.v3.ncrunchproject | 5 + src/ext/Util/wixlib/util.wixproj | 27 + src/ext/global.json | 8 + .../WixToolsetTest.Util/TestData/.Data/burn.exe | Bin 463360 -> 0 bytes .../TestData/BundleWithSearches/Bundle.en-us.wxl | 8 - .../TestData/BundleWithSearches/Bundle.wxs | 52 - .../BundleWithSearches/data/MsiPackage/Shared.dll | 1 - .../BundleWithSearches/data/MsiPackage/test.txt | 1 - .../TestData/BundleWithSearches/data/fakeba.dll | 1 - .../TestData/BundleWithSearches/data/test.msi | Bin 32768 -> 0 bytes .../TestData/CloseApplication/Package.en-us.wxl | 9 - .../TestData/CloseApplication/Package.wxs | 17 - .../CloseApplication/PackageComponents.wxs | 9 - .../TestData/CloseApplication/example.txt | 1 - .../TestData/EventManifest/Package.en-us.wxl | 9 - .../TestData/EventManifest/Package.wxs | 15 - .../TestData/EventManifest/PackageComponents.wxs | 11 - .../TestData/EventManifest/example.txt | 1 - .../TestData/InternetShortcut/Package.en-us.wxl | 9 - .../TestData/InternetShortcut/Package.ico | Bin 83899 -> 0 bytes .../TestData/InternetShortcut/Package.wxs | 15 - .../InternetShortcut/PackageComponents.wxs | 11 - .../TestData/InternetShortcut/example.txt | 1 - .../TestData/InternetShortcutModule/Module.wxs | 13 - .../InternetShortcutModule/ModuleComponents.wxs | 11 - .../TestData/InternetShortcutModule/Package.ico | Bin 83899 -> 0 bytes .../TestData/PermissionEx/Package.en-us.wxl | 9 - .../TestData/PermissionEx/Package.wxs | 15 - .../TestData/PermissionEx/PackageComponents.wxs | 23 - .../TestData/PermissionEx/example.txt | 1 - .../TestData/Queries/Package.en-us.wxl | 9 - .../TestData/Queries/Package.wxs | 23 - .../TestData/Queries/PackageComponents.wxs | 9 - .../TestData/Queries/example.txt | 1 - .../TestData/RemoveFolderEx/Module.wxs | 13 - .../TestData/RemoveFolderEx/ModuleComponents.wxs | 10 - .../TestData/RemoveRegistryKeyEx/Module.wxs | 13 - .../RemoveRegistryKeyEx/ModuleComponents.wxs | 10 - .../TestData/UsingFileShare/Package.en-us.wxl | 9 - .../TestData/UsingFileShare/Package.wxs | 15 - .../TestData/UsingFileShare/PackageComponents.wxs | 14 - .../TestData/UsingFileShare/example.txt | 1 - .../TestData/XmlConfig/Package.en-us.wxl | 9 - .../TestData/XmlConfig/Package.wxs | 17 - .../TestData/XmlConfigModule/Module.wxs | 19 - .../TestData/XmlConfigModule/my.xml | 1 - .../WixToolsetTest.Util/UtilExtensionFixture.cs | 317 -- .../WixToolsetTest.Util/WixToolsetTest.Util.csproj | 38 - .../WixToolsetTest.Util.v3.ncrunchproject | 5 - src/version.json | 11 + src/wix.snk | Bin 596 -> 0 bytes src/wixext/PerformanceCounterType.cs | 192 - src/wixext/Symbols/EventManifestSymbol.cs | 55 - src/wixext/Symbols/FileSharePermissionsSymbol.cs | 63 - src/wixext/Symbols/FileShareSymbol.cs | 71 - src/wixext/Symbols/GroupSymbol.cs | 63 - src/wixext/Symbols/PerfmonManifestSymbol.cs | 63 - src/wixext/Symbols/PerfmonSymbol.cs | 63 - src/wixext/Symbols/PerformanceCategorySymbol.cs | 71 - src/wixext/Symbols/SecureObjectsSymbol.cs | 103 - src/wixext/Symbols/ServiceConfigSymbol.cs | 119 - src/wixext/Symbols/UserGroupSymbol.cs | 55 - src/wixext/Symbols/UserSymbol.cs | 79 - src/wixext/Symbols/UtilSymbolDefinitions.cs | 125 - src/wixext/Symbols/WixCloseApplicationSymbol.cs | 103 - src/wixext/Symbols/WixFormatFilesSymbol.cs | 55 - src/wixext/Symbols/WixInternetShortcutSymbol.cs | 95 - src/wixext/Symbols/WixRemoveFolderExSymbol.cs | 78 - src/wixext/Symbols/WixRemoveRegistryKeyExSymbol.cs | 86 - src/wixext/Symbols/WixRestartResourceSymbol.cs | 71 - src/wixext/Symbols/WixTouchFileSymbol.cs | 63 - .../Symbols/WixWindowsFeatureSearchSymbol.cs | 47 - src/wixext/Symbols/XmlConfigSymbol.cs | 111 - src/wixext/Symbols/XmlFileSymbol.cs | 95 - src/wixext/UtilCompiler.cs | 3889 -------------------- src/wixext/UtilConstants.cs | 17 - src/wixext/UtilDecompiler.cs | 1543 -------- src/wixext/UtilErrors.cs | 49 - src/wixext/UtilExtensionData.cs | 23 - src/wixext/UtilExtensionFactory.cs | 18 - src/wixext/UtilTableDefinitions.cs | 319 -- src/wixext/UtilWarnings.cs | 37 - src/wixext/UtilWindowsInstallerBackendExtension.cs | 13 - src/wixext/WixToolset.Util.wixext.csproj | 31 - src/wixext/WixToolset.Util.wixext.nuspec | 25 - src/wixext/WixToolset.Util.wixext.targets | 11 - .../WixToolset.Util.wixext.v3.ncrunchproject | 7 - src/wixlib/UtilBundleExtension_Platform.wxi | 10 - src/wixlib/UtilBundleExtension_arm64.wxs | 7 - src/wixlib/UtilBundleExtension_x64.wxs | 7 - src/wixlib/UtilBundleExtension_x86.wxs | 7 - src/wixlib/UtilExtension.wxs | 64 - src/wixlib/UtilExtension_Platform.wxi | 360 -- src/wixlib/UtilExtension_arm64.wxs | 7 - src/wixlib/UtilExtension_x64.wxs | 7 - src/wixlib/UtilExtension_x86.wxs | 7 - src/wixlib/caDecor.wxi | 39 - src/wixlib/caerr.wxi | 96 - src/wixlib/de-de.wxl | 32 - src/wixlib/en-us.wxl | 32 - src/wixlib/es-es.wxl | 31 - src/wixlib/fr-fr.wxl | 31 - src/wixlib/it-it.wxl | 32 - src/wixlib/ja-jp.wxl | 32 - src/wixlib/pt-br.wxl | 26 - src/wixlib/util.v3.ncrunchproject | 5 - src/wixlib/util.wixproj | 27 - version.json | 11 - 338 files changed, 22397 insertions(+), 22397 deletions(-) delete mode 100644 .editorconfig delete mode 100644 README.md delete mode 100644 Util.wixext.sln delete mode 100644 Util.wixext.v3.ncrunchsolution delete mode 100644 appveyor.cmd delete mode 100644 appveyor.yml delete mode 100644 global.json delete mode 100644 nuget.config create mode 100644 src/.editorconfig delete mode 100644 src/CustomizedNativeRecommendedRules.ruleset delete mode 100644 src/Directory.Build.props delete mode 100644 src/Directory.Build.targets delete mode 100644 src/Directory.csproj.props delete mode 100644 src/Directory.csproj.targets delete mode 100644 src/Directory.vcxproj.props delete mode 100644 src/be/UtilBundleExtension.cpp delete mode 100644 src/be/UtilBundleExtension.h delete mode 100644 src/be/beDecor.h delete mode 100644 src/be/detectsha2support.cpp delete mode 100644 src/be/detectsha2support.h delete mode 100644 src/be/precomp.cpp delete mode 100644 src/be/precomp.h delete mode 100644 src/be/utilbe.cpp delete mode 100644 src/be/utilbe.def delete mode 100644 src/be/utilbe.vcxproj delete mode 100644 src/be/utilsearch.cpp delete mode 100644 src/be/utilsearch.h delete mode 100644 src/ca/BroadcastSettingChange.cpp delete mode 100644 src/ca/CheckReboot.cpp delete mode 100644 src/ca/CloseApps.cpp delete mode 100644 src/ca/CustomMsiErrors.h delete mode 100644 src/ca/FormatFiles.cpp delete mode 100644 src/ca/OsInfo.cpp delete mode 100644 src/ca/RemoveFoldersEx.cpp delete mode 100644 src/ca/RemoveRegistryKeysEx.cpp delete mode 100644 src/ca/RestartManager.cpp delete mode 100644 src/ca/TouchFile.cpp delete mode 100644 src/ca/XmlConfig.cpp delete mode 100644 src/ca/XmlFile.cpp delete mode 100644 src/ca/caDecor.h delete mode 100644 src/ca/cost.h delete mode 100644 src/ca/dllmain.cpp delete mode 100644 src/ca/exitearlywithsuccess.cpp delete mode 100644 src/ca/netshortcuts.cpp delete mode 100644 src/ca/precomp.h delete mode 100644 src/ca/qtexecca.cpp delete mode 100644 src/ca/sca.h delete mode 100644 src/ca/scacost.h delete mode 100644 src/ca/scaexec.cpp delete mode 100644 src/ca/scamanifest.cpp delete mode 100644 src/ca/scaperf.cpp delete mode 100644 src/ca/scaperfexec.cpp delete mode 100644 src/ca/scasched.cpp delete mode 100644 src/ca/scasmb.h delete mode 100644 src/ca/scasmbexec.cpp delete mode 100644 src/ca/scasmbexec.h delete mode 100644 src/ca/scasmbsched.cpp delete mode 100644 src/ca/scauser.cpp delete mode 100644 src/ca/scauser.h delete mode 100644 src/ca/secureobj.cpp delete mode 100644 src/ca/serviceconfig.cpp delete mode 100644 src/ca/shellexecca.cpp delete mode 100644 src/ca/test.cpp delete mode 100644 src/ca/utilca.cpp delete mode 100644 src/ca/utilca.def delete mode 100644 src/ca/utilca.vcxproj create mode 100644 src/ext/Util/CustomizedNativeRecommendedRules.ruleset create mode 100644 src/ext/Util/Directory.Build.props create mode 100644 src/ext/Util/Directory.Build.targets create mode 100644 src/ext/Util/Directory.csproj.props create mode 100644 src/ext/Util/Directory.csproj.targets create mode 100644 src/ext/Util/Directory.vcxproj.props create mode 100644 src/ext/Util/README.md create mode 100644 src/ext/Util/Util.wixext.sln create mode 100644 src/ext/Util/Util.wixext.v3.ncrunchsolution create mode 100644 src/ext/Util/appveyor.cmd create mode 100644 src/ext/Util/appveyor.yml create mode 100644 src/ext/Util/be/UtilBundleExtension.cpp create mode 100644 src/ext/Util/be/UtilBundleExtension.h create mode 100644 src/ext/Util/be/beDecor.h create mode 100644 src/ext/Util/be/detectsha2support.cpp create mode 100644 src/ext/Util/be/detectsha2support.h create mode 100644 src/ext/Util/be/precomp.cpp create mode 100644 src/ext/Util/be/precomp.h create mode 100644 src/ext/Util/be/utilbe.cpp create mode 100644 src/ext/Util/be/utilbe.def create mode 100644 src/ext/Util/be/utilbe.vcxproj create mode 100644 src/ext/Util/be/utilsearch.cpp create mode 100644 src/ext/Util/be/utilsearch.h create mode 100644 src/ext/Util/ca/BroadcastSettingChange.cpp create mode 100644 src/ext/Util/ca/CheckReboot.cpp create mode 100644 src/ext/Util/ca/CloseApps.cpp create mode 100644 src/ext/Util/ca/CustomMsiErrors.h create mode 100644 src/ext/Util/ca/FormatFiles.cpp create mode 100644 src/ext/Util/ca/OsInfo.cpp create mode 100644 src/ext/Util/ca/RemoveFoldersEx.cpp create mode 100644 src/ext/Util/ca/RemoveRegistryKeysEx.cpp create mode 100644 src/ext/Util/ca/RestartManager.cpp create mode 100644 src/ext/Util/ca/TouchFile.cpp create mode 100644 src/ext/Util/ca/XmlConfig.cpp create mode 100644 src/ext/Util/ca/XmlFile.cpp create mode 100644 src/ext/Util/ca/caDecor.h create mode 100644 src/ext/Util/ca/cost.h create mode 100644 src/ext/Util/ca/dllmain.cpp create mode 100644 src/ext/Util/ca/exitearlywithsuccess.cpp create mode 100644 src/ext/Util/ca/netshortcuts.cpp create mode 100644 src/ext/Util/ca/precomp.h create mode 100644 src/ext/Util/ca/qtexecca.cpp create mode 100644 src/ext/Util/ca/sca.h create mode 100644 src/ext/Util/ca/scacost.h create mode 100644 src/ext/Util/ca/scaexec.cpp create mode 100644 src/ext/Util/ca/scamanifest.cpp create mode 100644 src/ext/Util/ca/scaperf.cpp create mode 100644 src/ext/Util/ca/scaperfexec.cpp create mode 100644 src/ext/Util/ca/scasched.cpp create mode 100644 src/ext/Util/ca/scasmb.h create mode 100644 src/ext/Util/ca/scasmbexec.cpp create mode 100644 src/ext/Util/ca/scasmbexec.h create mode 100644 src/ext/Util/ca/scasmbsched.cpp create mode 100644 src/ext/Util/ca/scauser.cpp create mode 100644 src/ext/Util/ca/scauser.h create mode 100644 src/ext/Util/ca/secureobj.cpp create mode 100644 src/ext/Util/ca/serviceconfig.cpp create mode 100644 src/ext/Util/ca/shellexecca.cpp create mode 100644 src/ext/Util/ca/test.cpp create mode 100644 src/ext/Util/ca/utilca.cpp create mode 100644 src/ext/Util/ca/utilca.def create mode 100644 src/ext/Util/ca/utilca.vcxproj create mode 100644 src/ext/Util/nuget.config create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/.Data/burn.exe create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.en-us.wxl create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/MsiPackage/Shared.dll create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/MsiPackage/test.txt create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/fakeba.dll create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/test.msi create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/CloseApplication/Package.en-us.wxl create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/CloseApplication/Package.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/CloseApplication/PackageComponents.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/CloseApplication/example.txt create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/EventManifest/Package.en-us.wxl create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/EventManifest/Package.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/EventManifest/PackageComponents.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/EventManifest/example.txt create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.en-us.wxl create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.ico create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/PackageComponents.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/example.txt create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcutModule/Module.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcutModule/ModuleComponents.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcutModule/Package.ico create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/Package.en-us.wxl create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/Package.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/PackageComponents.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/example.txt create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/Package.en-us.wxl create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/Package.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/PackageComponents.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/example.txt create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/RemoveFolderEx/Module.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/RemoveFolderEx/ModuleComponents.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/RemoveRegistryKeyEx/Module.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/RemoveRegistryKeyEx/ModuleComponents.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/UsingFileShare/Package.en-us.wxl create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/UsingFileShare/Package.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/UsingFileShare/PackageComponents.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/UsingFileShare/example.txt create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/XmlConfig/Package.en-us.wxl create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/XmlConfig/Package.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/XmlConfigModule/Module.wxs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/XmlConfigModule/my.xml create mode 100644 src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs create mode 100644 src/ext/Util/test/WixToolsetTest.Util/WixToolsetTest.Util.csproj create mode 100644 src/ext/Util/test/WixToolsetTest.Util/WixToolsetTest.Util.v3.ncrunchproject create mode 100644 src/ext/Util/wix.snk create mode 100644 src/ext/Util/wixext/PerformanceCounterType.cs create mode 100644 src/ext/Util/wixext/Symbols/EventManifestSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/FileSharePermissionsSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/FileShareSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/GroupSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/PerfmonManifestSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/PerfmonSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/PerformanceCategorySymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/SecureObjectsSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/ServiceConfigSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/UserGroupSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/UserSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/UtilSymbolDefinitions.cs create mode 100644 src/ext/Util/wixext/Symbols/WixCloseApplicationSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/WixFormatFilesSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/WixInternetShortcutSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/WixRemoveFolderExSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/WixRemoveRegistryKeyExSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/WixRestartResourceSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/WixTouchFileSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/WixWindowsFeatureSearchSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/XmlConfigSymbol.cs create mode 100644 src/ext/Util/wixext/Symbols/XmlFileSymbol.cs create mode 100644 src/ext/Util/wixext/UtilCompiler.cs create mode 100644 src/ext/Util/wixext/UtilConstants.cs create mode 100644 src/ext/Util/wixext/UtilDecompiler.cs create mode 100644 src/ext/Util/wixext/UtilErrors.cs create mode 100644 src/ext/Util/wixext/UtilExtensionData.cs create mode 100644 src/ext/Util/wixext/UtilExtensionFactory.cs create mode 100644 src/ext/Util/wixext/UtilTableDefinitions.cs create mode 100644 src/ext/Util/wixext/UtilWarnings.cs create mode 100644 src/ext/Util/wixext/UtilWindowsInstallerBackendExtension.cs create mode 100644 src/ext/Util/wixext/WixToolset.Util.wixext.csproj create mode 100644 src/ext/Util/wixext/WixToolset.Util.wixext.nuspec create mode 100644 src/ext/Util/wixext/WixToolset.Util.wixext.targets create mode 100644 src/ext/Util/wixext/WixToolset.Util.wixext.v3.ncrunchproject create mode 100644 src/ext/Util/wixlib/UtilBundleExtension_Platform.wxi create mode 100644 src/ext/Util/wixlib/UtilBundleExtension_arm64.wxs create mode 100644 src/ext/Util/wixlib/UtilBundleExtension_x64.wxs create mode 100644 src/ext/Util/wixlib/UtilBundleExtension_x86.wxs create mode 100644 src/ext/Util/wixlib/UtilExtension.wxs create mode 100644 src/ext/Util/wixlib/UtilExtension_Platform.wxi create mode 100644 src/ext/Util/wixlib/UtilExtension_arm64.wxs create mode 100644 src/ext/Util/wixlib/UtilExtension_x64.wxs create mode 100644 src/ext/Util/wixlib/UtilExtension_x86.wxs create mode 100644 src/ext/Util/wixlib/caDecor.wxi create mode 100644 src/ext/Util/wixlib/caerr.wxi create mode 100644 src/ext/Util/wixlib/de-de.wxl create mode 100644 src/ext/Util/wixlib/en-us.wxl create mode 100644 src/ext/Util/wixlib/es-es.wxl create mode 100644 src/ext/Util/wixlib/fr-fr.wxl create mode 100644 src/ext/Util/wixlib/it-it.wxl create mode 100644 src/ext/Util/wixlib/ja-jp.wxl create mode 100644 src/ext/Util/wixlib/pt-br.wxl create mode 100644 src/ext/Util/wixlib/util.v3.ncrunchproject create mode 100644 src/ext/Util/wixlib/util.wixproj create mode 100644 src/ext/global.json delete mode 100644 src/test/WixToolsetTest.Util/TestData/.Data/burn.exe delete mode 100644 src/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.en-us.wxl delete mode 100644 src/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/MsiPackage/Shared.dll delete mode 100644 src/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/MsiPackage/test.txt delete mode 100644 src/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/fakeba.dll delete mode 100644 src/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/test.msi delete mode 100644 src/test/WixToolsetTest.Util/TestData/CloseApplication/Package.en-us.wxl delete mode 100644 src/test/WixToolsetTest.Util/TestData/CloseApplication/Package.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/CloseApplication/PackageComponents.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/CloseApplication/example.txt delete mode 100644 src/test/WixToolsetTest.Util/TestData/EventManifest/Package.en-us.wxl delete mode 100644 src/test/WixToolsetTest.Util/TestData/EventManifest/Package.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/EventManifest/PackageComponents.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/EventManifest/example.txt delete mode 100644 src/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.en-us.wxl delete mode 100644 src/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.ico delete mode 100644 src/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/InternetShortcut/PackageComponents.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/InternetShortcut/example.txt delete mode 100644 src/test/WixToolsetTest.Util/TestData/InternetShortcutModule/Module.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/InternetShortcutModule/ModuleComponents.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/InternetShortcutModule/Package.ico delete mode 100644 src/test/WixToolsetTest.Util/TestData/PermissionEx/Package.en-us.wxl delete mode 100644 src/test/WixToolsetTest.Util/TestData/PermissionEx/Package.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/PermissionEx/PackageComponents.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/PermissionEx/example.txt delete mode 100644 src/test/WixToolsetTest.Util/TestData/Queries/Package.en-us.wxl delete mode 100644 src/test/WixToolsetTest.Util/TestData/Queries/Package.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/Queries/PackageComponents.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/Queries/example.txt delete mode 100644 src/test/WixToolsetTest.Util/TestData/RemoveFolderEx/Module.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/RemoveFolderEx/ModuleComponents.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/RemoveRegistryKeyEx/Module.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/RemoveRegistryKeyEx/ModuleComponents.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/UsingFileShare/Package.en-us.wxl delete mode 100644 src/test/WixToolsetTest.Util/TestData/UsingFileShare/Package.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/UsingFileShare/PackageComponents.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/UsingFileShare/example.txt delete mode 100644 src/test/WixToolsetTest.Util/TestData/XmlConfig/Package.en-us.wxl delete mode 100644 src/test/WixToolsetTest.Util/TestData/XmlConfig/Package.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/XmlConfigModule/Module.wxs delete mode 100644 src/test/WixToolsetTest.Util/TestData/XmlConfigModule/my.xml delete mode 100644 src/test/WixToolsetTest.Util/UtilExtensionFixture.cs delete mode 100644 src/test/WixToolsetTest.Util/WixToolsetTest.Util.csproj delete mode 100644 src/test/WixToolsetTest.Util/WixToolsetTest.Util.v3.ncrunchproject create mode 100644 src/version.json delete mode 100644 src/wix.snk delete mode 100644 src/wixext/PerformanceCounterType.cs delete mode 100644 src/wixext/Symbols/EventManifestSymbol.cs delete mode 100644 src/wixext/Symbols/FileSharePermissionsSymbol.cs delete mode 100644 src/wixext/Symbols/FileShareSymbol.cs delete mode 100644 src/wixext/Symbols/GroupSymbol.cs delete mode 100644 src/wixext/Symbols/PerfmonManifestSymbol.cs delete mode 100644 src/wixext/Symbols/PerfmonSymbol.cs delete mode 100644 src/wixext/Symbols/PerformanceCategorySymbol.cs delete mode 100644 src/wixext/Symbols/SecureObjectsSymbol.cs delete mode 100644 src/wixext/Symbols/ServiceConfigSymbol.cs delete mode 100644 src/wixext/Symbols/UserGroupSymbol.cs delete mode 100644 src/wixext/Symbols/UserSymbol.cs delete mode 100644 src/wixext/Symbols/UtilSymbolDefinitions.cs delete mode 100644 src/wixext/Symbols/WixCloseApplicationSymbol.cs delete mode 100644 src/wixext/Symbols/WixFormatFilesSymbol.cs delete mode 100644 src/wixext/Symbols/WixInternetShortcutSymbol.cs delete mode 100644 src/wixext/Symbols/WixRemoveFolderExSymbol.cs delete mode 100644 src/wixext/Symbols/WixRemoveRegistryKeyExSymbol.cs delete mode 100644 src/wixext/Symbols/WixRestartResourceSymbol.cs delete mode 100644 src/wixext/Symbols/WixTouchFileSymbol.cs delete mode 100644 src/wixext/Symbols/WixWindowsFeatureSearchSymbol.cs delete mode 100644 src/wixext/Symbols/XmlConfigSymbol.cs delete mode 100644 src/wixext/Symbols/XmlFileSymbol.cs delete mode 100644 src/wixext/UtilCompiler.cs delete mode 100644 src/wixext/UtilConstants.cs delete mode 100644 src/wixext/UtilDecompiler.cs delete mode 100644 src/wixext/UtilErrors.cs delete mode 100644 src/wixext/UtilExtensionData.cs delete mode 100644 src/wixext/UtilExtensionFactory.cs delete mode 100644 src/wixext/UtilTableDefinitions.cs delete mode 100644 src/wixext/UtilWarnings.cs delete mode 100644 src/wixext/UtilWindowsInstallerBackendExtension.cs delete mode 100644 src/wixext/WixToolset.Util.wixext.csproj delete mode 100644 src/wixext/WixToolset.Util.wixext.nuspec delete mode 100644 src/wixext/WixToolset.Util.wixext.targets delete mode 100644 src/wixext/WixToolset.Util.wixext.v3.ncrunchproject delete mode 100644 src/wixlib/UtilBundleExtension_Platform.wxi delete mode 100644 src/wixlib/UtilBundleExtension_arm64.wxs delete mode 100644 src/wixlib/UtilBundleExtension_x64.wxs delete mode 100644 src/wixlib/UtilBundleExtension_x86.wxs delete mode 100644 src/wixlib/UtilExtension.wxs delete mode 100644 src/wixlib/UtilExtension_Platform.wxi delete mode 100644 src/wixlib/UtilExtension_arm64.wxs delete mode 100644 src/wixlib/UtilExtension_x64.wxs delete mode 100644 src/wixlib/UtilExtension_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/es-es.wxl delete mode 100644 src/wixlib/fr-fr.wxl delete mode 100644 src/wixlib/it-it.wxl delete mode 100644 src/wixlib/ja-jp.wxl delete mode 100644 src/wixlib/pt-br.wxl delete mode 100644 src/wixlib/util.v3.ncrunchproject delete mode 100644 src/wixlib/util.wixproj delete mode 100644 version.json diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 1d72e683..00000000 --- a/.editorconfig +++ /dev/null @@ -1,37 +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\.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/README.md b/README.md deleted file mode 100644 index 540c539c..00000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Util.wixext -WixToolset.Util.wixext - Utility WiX Toolset Extension - diff --git a/Util.wixext.sln b/Util.wixext.sln deleted file mode 100644 index 050fd8b3..00000000 --- a/Util.wixext.sln +++ /dev/null @@ -1,87 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30204.135 -MinimumVisualStudioVersion = 15.0.26124.0 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utilbe", "src\be\utilbe.vcxproj", "{630C1EE7-2517-4A8C-83E3-DA1150308B58}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utilca", "src\ca\utilca.vcxproj", "{076018F7-19BD-423A-ABBF-229273DA08D8}" -EndProject -Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "util", "src\wixlib\util.wixproj", "{1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Util.wixext", "src\wixext\WixToolset.Util.wixext.csproj", "{6CF033EB-0A39-4AC6-9D41-9BD506352045}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.Util", "src\test\WixToolsetTest.Util\WixToolsetTest.Util.csproj", "{D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Debug|Any CPU.Build.0 = Debug|Win32 - {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Debug|x64.ActiveCfg = Debug|Win32 - {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Debug|x86.ActiveCfg = Debug|Win32 - {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Debug|x86.Build.0 = Debug|Win32 - {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Release|Any CPU.ActiveCfg = Release|Win32 - {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Release|Any CPU.Build.0 = Release|Win32 - {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Release|x64.ActiveCfg = Release|Win32 - {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Release|x86.ActiveCfg = Release|Win32 - {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Release|x86.Build.0 = Release|Win32 - {076018F7-19BD-423A-ABBF-229273DA08D8}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {076018F7-19BD-423A-ABBF-229273DA08D8}.Debug|Any CPU.Build.0 = Debug|Win32 - {076018F7-19BD-423A-ABBF-229273DA08D8}.Debug|x64.ActiveCfg = Debug|Win32 - {076018F7-19BD-423A-ABBF-229273DA08D8}.Debug|x86.ActiveCfg = Debug|Win32 - {076018F7-19BD-423A-ABBF-229273DA08D8}.Debug|x86.Build.0 = Debug|Win32 - {076018F7-19BD-423A-ABBF-229273DA08D8}.Release|Any CPU.ActiveCfg = Release|Win32 - {076018F7-19BD-423A-ABBF-229273DA08D8}.Release|Any CPU.Build.0 = Release|Win32 - {076018F7-19BD-423A-ABBF-229273DA08D8}.Release|x64.ActiveCfg = Release|Win32 - {076018F7-19BD-423A-ABBF-229273DA08D8}.Release|x86.ActiveCfg = Release|Win32 - {076018F7-19BD-423A-ABBF-229273DA08D8}.Release|x86.Build.0 = Release|Win32 - {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|Any CPU.ActiveCfg = Debug|x86 - {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|Any CPU.Build.0 = Debug|x86 - {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|x64.ActiveCfg = Debug|x86 - {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|x86.ActiveCfg = Debug|x86 - {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|x86.Build.0 = Debug|x86 - {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Release|Any CPU.ActiveCfg = Release|x86 - {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Release|Any CPU.Build.0 = Release|x86 - {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Release|x64.ActiveCfg = Release|x86 - {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Release|x86.ActiveCfg = Release|x86 - {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Release|x86.Build.0 = Release|x86 - {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|x64.ActiveCfg = Debug|Any CPU - {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|x64.Build.0 = Debug|Any CPU - {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|x86.ActiveCfg = Debug|Any CPU - {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|x86.Build.0 = Debug|Any CPU - {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|Any CPU.Build.0 = Release|Any CPU - {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|x64.ActiveCfg = Release|Any CPU - {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|x64.Build.0 = Release|Any CPU - {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|x86.ActiveCfg = Release|Any CPU - {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|x86.Build.0 = Release|Any CPU - {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|x64.ActiveCfg = Debug|Any CPU - {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|x64.Build.0 = Debug|Any CPU - {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|x86.ActiveCfg = Debug|Any CPU - {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|x86.Build.0 = Debug|Any CPU - {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|Any CPU.Build.0 = Release|Any CPU - {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|x64.ActiveCfg = Release|Any CPU - {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|x64.Build.0 = Release|Any CPU - {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|x86.ActiveCfg = Release|Any CPU - {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {E4566A6B-47D0-4EA0-989A-D763AC39105D} - EndGlobalSection -EndGlobal diff --git a/Util.wixext.v3.ncrunchsolution b/Util.wixext.v3.ncrunchsolution deleted file mode 100644 index 10420ac9..00000000 --- a/Util.wixext.v3.ncrunchsolution +++ /dev/null @@ -1,6 +0,0 @@ - - - True - True - - \ No newline at end of file diff --git a/appveyor.cmd b/appveyor.cmd deleted file mode 100644 index 8322ffae..00000000 --- a/appveyor.cmd +++ /dev/null @@ -1,19 +0,0 @@ -@setlocal -@pushd %~dp0 -@set _C=Release -@if /i "%1"=="debug" set _C=Debug - -:: Restore -msbuild -p:Configuration=%_C% -t:Restore || exit /b - -:: Build -msbuild -p:Configuration=%_C% src\test\WixToolsetTest.Util\WixToolsetTest.Util.csproj || exit /b - -:: Test -dotnet test -c %_C% --no-build src\test\WixToolsetTest.Util || exit /b - -:: Pack -msbuild -p:Configuration=%_C% -p:NoBuild=true -t:Pack src\wixext\WixToolset.Util.wixext.csproj || exit /b - -@popd -@endlocal diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 7c686b04..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,40 +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\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/global.json b/global.json deleted file mode 100644 index 697f5687..00000000 --- a/global.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "msbuild-sdks": { - "WixToolset.Sdk": "4.0.0-build-0213" - }, - "sdk": { - "allowPrerelease": false - } -} diff --git a/nuget.config b/nuget.config deleted file mode 100644 index 8d711148..00000000 --- a/nuget.config +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file 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/CustomizedNativeRecommendedRules.ruleset b/src/CustomizedNativeRecommendedRules.ruleset deleted file mode 100644 index 142b141c..00000000 --- a/src/CustomizedNativeRecommendedRules.ruleset +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props deleted file mode 100644 index b3c6287c..00000000 --- a/src/Directory.Build.props +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - Debug - false - MSB3246 - - $(MSBuildProjectName) - $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\build\)) - $(BaseOutputPath)obj\$(ProjectName)\ - $(BaseOutputPath)$(Configuration)\ - - WiX Toolset Team - WiX Toolset - Copyright (c) .NET Foundation and contributors. All rights reserved. - MS-RL - WiX Toolset - - - - - diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets deleted file mode 100644 index 2fcc765a..00000000 --- a/src/Directory.Build.targets +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - true - $(SolutionPath) - $(NCrunchOriginalSolutionPath) - - - - - - - $([System.IO.File]::ReadAllText($(TheSolutionPath))) - $([System.IO.Path]::GetDirectoryName( $(TheSolutionPath) )) - (?<="[PackageName]", ")(.*)(?=", ") - - - - - - %(Identity) - $(SolutionFileContent.Contains('\%(Identity).csproj')) - - - - - $(RegexPattern.Replace('[PackageName]','%(PackageName)') ) - $([System.Text.RegularExpressions.Regex]::Match('$(SolutionFileContent)', '%(Pattern)')) - - - - - - - - - - - - - - diff --git a/src/Directory.csproj.props b/src/Directory.csproj.props deleted file mode 100644 index 81d24ad1..00000000 --- a/src/Directory.csproj.props +++ /dev/null @@ -1,13 +0,0 @@ - - - - - true - true - $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)wix.snk)) - false - - diff --git a/src/Directory.csproj.targets b/src/Directory.csproj.targets deleted file mode 100644 index c3270426..00000000 --- a/src/Directory.csproj.targets +++ /dev/null @@ -1,26 +0,0 @@ - - - - - false - $(OutputPath)\$(AssemblyName).xml - - - - - $(PrivateRepositoryUrl.Replace('.git','')) - - $(MSBuildProjectName).nuspec - $(OutputPath)..\ - $(NuspecProperties);Id=$(PackageId);Authors=$(Authors);Copyright=$(Copyright);Description=$(Description);Title=$(Title) - $(NuspecProperties);Version=$(PackageVersion);RepositoryCommit=$(SourceRevisionId);RepositoryType=$(RepositoryType);RepositoryUrl=$(PrivateRepositoryUrl);ProjectFolder=$(MSBuildProjectDirectory)\;ProjectUrl=$(ProjectUrl) - true - snupkg - - - - diff --git a/src/Directory.vcxproj.props b/src/Directory.vcxproj.props deleted file mode 100644 index 11778f41..00000000 --- a/src/Directory.vcxproj.props +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - Win32 - $(BaseIntermediateOutputPath)$(Configuration)\$(Platform)\ - $(OutputPath)$(Platform)\ - - - $(Company) - $(Copyright) - - win-x86;win-x64;win-arm64 - native,Version=v0.0 - - - - $([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0')) - - - - $(MSBuildThisFileDirectory)CustomizedNativeRecommendedRules.ruleset - - - - - $(DisableSpecificCompilerWarnings) - Level4 - $(ProjectDir)inc;$(MSBuildProjectDirectory);$(IntDir);$(SqlCESdkIncludePath);$(ProjectAdditionalIncludeDirectories);%(AdditionalIncludeDirectories) - WIN32;_WINDOWS;_WIN32_MSI=500;_WIN32_WINNT=0x0501;$(ArmPreprocessorDefinitions);$(UnicodePreprocessorDefinitions);_CRT_STDIO_LEGACY_WIDE_SPECIFIERS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions) - Use - precomp.h - StdCall - true - false - -YlprecompDefine - /Zc:threadSafeInit- %(AdditionalOptions) - true - - - $(ArmPreprocessorDefinitions);%(PreprocessorDefinitions) - $(ProjectAdditionalResourceIncludeDirectories);%(AdditionalIncludeDirectories) - - - $(OutDir);$(AdditionalMultiTargetLibraryPath);$(ProjectAdditionalLibraryDirectories);%(AdditionalLibraryDirectories) - - - $(ProjectSubSystem) - $(ProjectModuleDefinitionFile) - $(ResourceOnlyDll) - true - $(ProjectAdditionalLinkLibraries);advapi32.lib;comdlg32.lib;user32.lib;oleaut32.lib;gdi32.lib;shell32.lib;ole32.lib;version.lib;%(AdditionalDependencies) - $(OutDir);$(AdditionalMultiTargetLibraryPath);$(ArmLibraryDirectories);$(ProjectAdditionalLinkLibraryDirectories);%(AdditionalLibraryDirectories) - /IGNORE:4099 %(AdditionalOptions) - - - - - - NoExtensions - - - - - CDecl - - - - - OldStyle - true - true - - - - - Disabled - EnableFastChecks - _DEBUG;DEBUG;%(PreprocessorDefinitions) - MultiThreadedDebug - - - - - MinSpace - NDEBUG;%(PreprocessorDefinitions) - true - true - MultiThreaded - - - true - true - - - diff --git a/src/be/UtilBundleExtension.cpp b/src/be/UtilBundleExtension.cpp deleted file mode 100644 index 2ac842a5..00000000 --- a/src/be/UtilBundleExtension.cpp +++ /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. - -#include "precomp.h" -#include "BextBaseBundleExtension.h" - -class CWixUtilBundleExtension : public CBextBaseBundleExtension -{ -public: // IBundleExtension - virtual STDMETHODIMP Search( - __in LPCWSTR wzId, - __in LPCWSTR wzVariable - ) - { - HRESULT hr = S_OK; - - hr = UtilSearchExecute(&m_searches, wzId, wzVariable, m_pEngine); - - return hr; - } - -public: //CBextBaseBundleExtension - virtual STDMETHODIMP Initialize( - __in const BUNDLE_EXTENSION_CREATE_ARGS* pCreateArgs - ) - { - HRESULT hr = S_OK; - IXMLDOMDocument* pixdManifest = NULL; - IXMLDOMNode* pixnBundleExtension = NULL; - - hr = CBextBaseBundleExtension::Initialize(pCreateArgs); - ExitOnFailure(hr, "CBextBaseBundleExtension initialization failed."); - - hr = XmlLoadDocumentFromFile(m_sczBundleExtensionDataPath, &pixdManifest); - ExitOnFailure(hr, "Failed to load bundle extension manifest from path: %ls", m_sczBundleExtensionDataPath); - - hr = BextGetBundleExtensionDataNode(pixdManifest, UTIL_BUNDLE_EXTENSION_ID, &pixnBundleExtension); - ExitOnFailure(hr, "Failed to get BundleExtension '%ls'", UTIL_BUNDLE_EXTENSION_ID); - - hr = UtilSearchParseFromXml(&m_searches, pixnBundleExtension); - ExitOnFailure(hr, "Failed to parse searches from bundle extension manifest."); - - LExit: - ReleaseObject(pixnBundleExtension); - ReleaseObject(pixdManifest); - - return hr; - } - -public: - CWixUtilBundleExtension( - __in IBundleExtensionEngine* pEngine - ) : CBextBaseBundleExtension(pEngine) - { - m_searches = { }; - } - - ~CWixUtilBundleExtension() - { - UtilSearchUninitialize(&m_searches); - } - -private: - UTIL_SEARCHES m_searches; -}; - -HRESULT UtilBundleExtensionCreate( - __in IBundleExtensionEngine* pEngine, - __in const BUNDLE_EXTENSION_CREATE_ARGS* pArgs, - __out IBundleExtension** ppBundleExtension - ) -{ - HRESULT hr = S_OK; - CWixUtilBundleExtension* pExtension = NULL; - - pExtension = new CWixUtilBundleExtension(pEngine); - ExitOnNull(pExtension, hr, E_OUTOFMEMORY, "Failed to create new CWixUtilBundleExtension."); - - hr = pExtension->Initialize(pArgs); - ExitOnFailure(hr, "CWixUtilBundleExtension initialization failed"); - - *ppBundleExtension = pExtension; - pExtension = NULL; - -LExit: - ReleaseObject(pExtension); - return hr; -} diff --git a/src/be/UtilBundleExtension.h b/src/be/UtilBundleExtension.h deleted file mode 100644 index c55d6b85..00000000 --- a/src/be/UtilBundleExtension.h +++ /dev/null @@ -1,16 +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. - - -// constants - -#define UTIL_BUNDLE_EXTENSION_ID BUNDLE_EXTENSION_DECORATION(L"UtilBundleExtension") - - -// function declarations - -HRESULT UtilBundleExtensionCreate( - __in IBundleExtensionEngine* pEngine, - __in const BUNDLE_EXTENSION_CREATE_ARGS* pArgs, - __out IBundleExtension** ppBundleExtension - ); diff --git a/src/be/beDecor.h b/src/be/beDecor.h deleted file mode 100644 index 2c6a8818..00000000 --- a/src/be/beDecor.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 BUNDLE_EXTENSION_DECORATION(f) L"Wix4" f L"_A64" -#elif defined(_M_AMD64) -#define BUNDLE_EXTENSION_DECORATION(f) L"Wix4" f L"_X64" -#elif defined(_M_ARM) -#define BUNDLE_EXTENSION_DECORATION(f) L"Wix4" f L"_ARM" -#else -#define BUNDLE_EXTENSION_DECORATION(f) L"Wix4" f L"_X86" -#endif diff --git a/src/be/detectsha2support.cpp b/src/be/detectsha2support.cpp deleted file mode 100644 index 90e349cd..00000000 --- a/src/be/detectsha2support.cpp +++ /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. - -#include "precomp.h" - -// https://gist.github.com/navossoc/7572c7d82243e9f818989e2765e7793a -HRESULT DetectSHA2CodeSigning( - __out BOOL* pfSupported - ) -{ - HRESULT hr = S_OK; - HMODULE hModule = NULL; - FARPROC pfn = NULL; - DWORD er = ERROR_SUCCESS; - - hr = LoadSystemLibrary(L"wintrust.dll", &hModule); - ExitOnFailure(hr, "Failed to load wintrust.dll"); - - pfn = ::GetProcAddress(hModule, "CryptCATAdminAcquireContext2"); - if (pfn) - { - *pfSupported = TRUE; - ExitFunction1(hr = S_OK); - } - - er = ::GetLastError(); - if (er == ERROR_PROC_NOT_FOUND) - { - *pfSupported = FALSE; - ExitFunction1(hr = S_OK); - } - - hr = HRESULT_FROM_WIN32(er); - ExitOnFailure(hr, "Failed to probe for CryptCATAdminAcquireContext2 in wintrust.dll"); - -LExit: - ::FreeLibrary(hModule); - - return hr; -} - -HRESULT UtilPerformDetectSHA2CodeSigning( - __in LPCWSTR wzVariable, - __in UTIL_SEARCH* /*pSearch*/, - __in IBundleExtensionEngine* pEngine - ) -{ - HRESULT hr = S_OK; - BOOL fSupported = FALSE; - - hr = DetectSHA2CodeSigning(&fSupported); - ExitOnFailure(hr, "DetectSHA2CodeSigning failed."); - - hr = pEngine->SetVariableNumeric(wzVariable, fSupported ? 1 : 0); - ExitOnFailure(hr, "Failed to set variable '%ls'", wzVariable); - -LExit: - return hr; -} diff --git a/src/be/detectsha2support.h b/src/be/detectsha2support.h deleted file mode 100644 index c38a3d59..00000000 --- a/src/be/detectsha2support.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 UtilPerformDetectSHA2CodeSigning( - __in LPCWSTR wzVariable, - __in UTIL_SEARCH* pSearch, - __in IBundleExtensionEngine* pEngine - ); \ No newline at end of file diff --git a/src/be/precomp.cpp b/src/be/precomp.cpp deleted file mode 100644 index 37664a1c..00000000 --- a/src/be/precomp.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/be/precomp.h b/src/be/precomp.h deleted file mode 100644 index 76d24c7b..00000000 --- a/src/be/precomp.h +++ /dev/null @@ -1,37 +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 -#include -#include -#include - -#include - -#include - -#define MAXUINT USHRT_MAX - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include "beDecor.h" -#include "utilsearch.h" -#include "detectsha2support.h" -#include "UtilBundleExtension.h" diff --git a/src/be/utilbe.cpp b/src/be/utilbe.cpp deleted file mode 100644 index d9816dc7..00000000 --- a/src/be/utilbe.cpp +++ /dev/null @@ -1,41 +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" -#include "BextBaseBundleExtensionProc.h" - -static IBundleExtension* vpBundleExtension = NULL; - -// function definitions - -extern "C" HRESULT WINAPI BundleExtensionCreate( - __in const BUNDLE_EXTENSION_CREATE_ARGS* pArgs, - __inout BUNDLE_EXTENSION_CREATE_RESULTS* pResults - ) -{ - HRESULT hr = S_OK; - IBundleExtensionEngine* pEngine = NULL; - - hr = XmlInitialize(); - ExitOnFailure(hr, "Failed to initialize XML."); - - hr = BextInitializeFromCreateArgs(pArgs, &pEngine); - ExitOnFailure(hr, "Failed to initialize bext"); - - hr = UtilBundleExtensionCreate(pEngine, pArgs, &vpBundleExtension); - BextExitOnFailure(hr, "Failed to create WixUtilBundleExtension"); - - pResults->pfnBundleExtensionProc = BextBaseBundleExtensionProc; - pResults->pvBundleExtensionProcContext = vpBundleExtension; - -LExit: - ReleaseObject(pEngine); - - return hr; -} - -extern "C" void WINAPI BundleExtensionDestroy() -{ - BextUninitialize(); - ReleaseNullObject(vpBundleExtension); - XmlUninitialize(); -} \ No newline at end of file diff --git a/src/be/utilbe.def b/src/be/utilbe.def deleted file mode 100644 index 711b1a5c..00000000 --- a/src/be/utilbe.def +++ /dev/null @@ -1,8 +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 "utilbe" - -EXPORTS - BundleExtensionCreate - BundleExtensionDestroy diff --git a/src/be/utilbe.vcxproj b/src/be/utilbe.vcxproj deleted file mode 100644 index 683b376a..00000000 --- a/src/be/utilbe.vcxproj +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - Debug - ARM64 - - - Release - ARM64 - - - Debug - X64 - - - Release - X64 - - - Debug - Win32 - - - Release - Win32 - - - - - {630C1EE7-2517-4A8C-83E3-DA1150308B58} - DynamicLibrary - utilbe - v142 - Unicode - utilbe.def - WiX Toolset Util BundleExtension - - - - - - - msi.lib - - - - - - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/be/utilsearch.cpp b/src/be/utilsearch.cpp deleted file mode 100644 index 7cd2ea09..00000000 --- a/src/be/utilsearch.cpp +++ /dev/null @@ -1,160 +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" - - -STDMETHODIMP UtilSearchParseFromXml( - __in UTIL_SEARCHES* pSearches, - __in IXMLDOMNode* pixnBundleExtension - ) -{ - HRESULT hr = S_OK; - IXMLDOMNodeList* pixnNodes = NULL; - IXMLDOMNode* pixnNode = NULL; - DWORD cNodes = 0; - BSTR bstrNodeName = NULL; - LPWSTR scz = NULL; - - // Select Util search nodes. - hr = XmlSelectNodes(pixnBundleExtension, L"WixWindowsFeatureSearch", &pixnNodes); - ExitOnFailure(hr, "Failed to select Util search nodes."); - - // Get Util search node count. - hr = pixnNodes->get_length((long*)&cNodes); - ExitOnFailure(hr, "Failed to get Util search node count."); - - if (!cNodes) - { - ExitFunction(); - } - - // Allocate memory for searches. - pSearches->rgSearches = (UTIL_SEARCH*)MemAlloc(sizeof(UTIL_SEARCH) * cNodes, TRUE); - ExitOnNull(pSearches->rgSearches, hr, E_OUTOFMEMORY, "Failed to allocate memory for search structs."); - - pSearches->cSearches = cNodes; - - // Parse search elements. - for (DWORD i = 0; i < cNodes; ++i) - { - UTIL_SEARCH* pSearch = &pSearches->rgSearches[i]; - - hr = XmlNextElement(pixnNodes, &pixnNode, &bstrNodeName); - ExitOnFailure(hr, "Failed to get next node."); - - // @Id - hr = XmlGetAttributeEx(pixnNode, L"Id", &pSearch->sczId); - ExitOnFailure(hr, "Failed to get @Id."); - - // Read type specific attributes. - if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"WixWindowsFeatureSearch", -1)) - { - pSearch->Type = UTIL_SEARCH_TYPE_WINDOWS_FEATURE_SEARCH; - - // @Type - hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); - ExitOnFailure(hr, "Failed to get @Type."); - - if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"sha2CodeSigning", -1)) - { - pSearch->WindowsFeatureSearch.type = UTIL_WINDOWS_FEATURE_SEARCH_TYPE_SHA2_CODE_SIGNING; - } - else - { - hr = E_INVALIDARG; - ExitOnFailure(hr, "Invalid value for @Type: %ls", scz); - } - } - else - { - hr = E_UNEXPECTED; - ExitOnFailure(hr, "Unexpected element name: %ls", bstrNodeName); - } - - // prepare next iteration - ReleaseNullObject(pixnNode); - ReleaseNullBSTR(bstrNodeName); - } - -LExit: - ReleaseStr(scz); - ReleaseBSTR(bstrNodeName); - ReleaseObject(pixnNode); - ReleaseObject(pixnNodes); - - return hr; -} - -void UtilSearchUninitialize( - __in UTIL_SEARCHES* pSearches - ) -{ - if (pSearches->rgSearches) - { - for (DWORD i = 0; i < pSearches->cSearches; ++i) - { - UTIL_SEARCH* pSearch = &pSearches->rgSearches[i]; - - ReleaseStr(pSearch->sczId); - } - MemFree(pSearches->rgSearches); - } -} - -STDMETHODIMP UtilSearchExecute( - __in UTIL_SEARCHES* pSearches, - __in LPCWSTR wzSearchId, - __in LPCWSTR wzVariable, - __in IBundleExtensionEngine* pEngine - ) -{ - HRESULT hr = S_OK; - UTIL_SEARCH* pSearch = NULL; - - hr = UtilSearchFindById(pSearches, wzSearchId, &pSearch); - ExitOnFailure(hr, "Search id '%ls' is unknown to the util extension."); - - switch (pSearch->Type) - { - case UTIL_SEARCH_TYPE_WINDOWS_FEATURE_SEARCH: - switch (pSearch->WindowsFeatureSearch.type) - { - case UTIL_WINDOWS_FEATURE_SEARCH_TYPE_SHA2_CODE_SIGNING: - hr = UtilPerformDetectSHA2CodeSigning(wzVariable, pSearch, pEngine); - break; - default: - hr = E_UNEXPECTED; - } - break; - default: - hr = E_UNEXPECTED; - } - -LExit: - return hr; -} - -STDMETHODIMP UtilSearchFindById( - __in UTIL_SEARCHES* pSearches, - __in LPCWSTR wzId, - __out UTIL_SEARCH** ppSearch - ) -{ - HRESULT hr = S_OK; - - for (DWORD i = 0; i < pSearches->cSearches; ++i) - { - UTIL_SEARCH* pSearch = &pSearches->rgSearches[i]; - - if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pSearch->sczId, -1, wzId, -1)) - { - *ppSearch = pSearch; - ExitFunction1(hr = S_OK); - } - } - - hr = E_NOTFOUND; - -LExit: - return hr; -} diff --git a/src/be/utilsearch.h b/src/be/utilsearch.h deleted file mode 100644 index deeab1f7..00000000 --- a/src/be/utilsearch.h +++ /dev/null @@ -1,65 +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. - - -// constants - -enum UTIL_SEARCH_TYPE -{ - UTIL_SEARCH_TYPE_NONE, - UTIL_SEARCH_TYPE_WINDOWS_FEATURE_SEARCH, -}; - -enum UTIL_WINDOWS_FEATURE_SEARCH_TYPE -{ - UTIL_WINDOWS_FEATURE_SEARCH_TYPE_NONE, - UTIL_WINDOWS_FEATURE_SEARCH_TYPE_SHA2_CODE_SIGNING, -}; - - -// structs - -typedef struct _UTIL_SEARCH -{ - LPWSTR sczId; - - UTIL_SEARCH_TYPE Type; - union - { - struct - { - UTIL_WINDOWS_FEATURE_SEARCH_TYPE type; - } WindowsFeatureSearch; - }; -} UTIL_SEARCH; - -typedef struct _UTIL_SEARCHES -{ - UTIL_SEARCH* rgSearches; - DWORD cSearches; -} UTIL_SEARCHES; - - -// function declarations - -STDMETHODIMP UtilSearchParseFromXml( - __in UTIL_SEARCHES* pSearches, - __in IXMLDOMNode* pixnBundleExtension - ); - -void UtilSearchUninitialize( - __in UTIL_SEARCHES* pSearches - ); - -STDMETHODIMP UtilSearchExecute( - __in UTIL_SEARCHES* pSearches, - __in LPCWSTR wzSearchId, - __in LPCWSTR wzVariable, - __in IBundleExtensionEngine* pEngine - ); - -STDMETHODIMP UtilSearchFindById( - __in UTIL_SEARCHES* pSearches, - __in LPCWSTR wzId, - __out UTIL_SEARCH** ppSearch - ); diff --git a/src/ca/BroadcastSettingChange.cpp b/src/ca/BroadcastSettingChange.cpp deleted file mode 100644 index 2e153ad3..00000000 --- a/src/ca/BroadcastSettingChange.cpp +++ /dev/null @@ -1,45 +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" - - -/******************************************************************** -WixBroadcastSettingChange - - Send WM_SETTINGCHANGE message to all top-level windows indicating - that unspecified settings have changed. -********************************************************************/ -extern "C" UINT __stdcall WixBroadcastSettingChange( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr = WcaInitialize(hInstall, "WixBroadcastSettingChange"); - ExitOnFailure(hr, "failed to initialize WixBroadcastSettingChange"); - - // best effort; ignore failures - ::SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE, NULL, NULL, SMTO_ABORTIFHUNG, 1000, NULL); - -LExit: - return WcaFinalize(ERROR_SUCCESS); -} - - -/******************************************************************** -WixBroadcastEnvironmentChange - - Send WM_SETTINGCHANGE message to all top-level windows indicating - that environment variables have changed. -********************************************************************/ -extern "C" UINT __stdcall WixBroadcastEnvironmentChange( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr = WcaInitialize(hInstall, "WixBroadcastEnvironmentChange"); - ExitOnFailure(hr, "failed to initialize WixBroadcastEnvironmentChange"); - - // best effort; ignore failures - ::SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE, NULL, reinterpret_cast(L"Environment"), SMTO_ABORTIFHUNG, 1000, NULL); - -LExit: - return WcaFinalize(ERROR_SUCCESS); -} diff --git a/src/ca/CheckReboot.cpp b/src/ca/CheckReboot.cpp deleted file mode 100644 index ce056411..00000000 --- a/src/ca/CheckReboot.cpp +++ /dev/null @@ -1,36 +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" - - -/******************************************************************** -WixCheckRebootRequired - entry point for WixCheckRebootRequired Custom Action - - called as Type 1 CustomAction (binary DLL) from Windows Installer - in InstallExecuteSequence after InstallFinalize -********************************************************************/ -extern "C" UINT __stdcall WixCheckRebootRequired( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr = S_OK; - DWORD er = ERROR_SUCCESS; - - hr = WcaInitialize(hInstall, "WixCheckRebootRequired"); - ExitOnFailure(hr, "failed to initialize"); - - if (WcaDidDeferredActionRequireReboot()) - { - WcaLog(LOGMSG_STANDARD, "Reboot required by deferred CustomAction."); - - er = ::MsiSetMode(hInstall, MSIRUNMODE_REBOOTATEND, TRUE); - hr = HRESULT_FROM_WIN32(er); - ExitOnFailure(hr, "Failed to schedule reboot."); - } - -LExit: - - if (FAILED(hr)) - er = ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} diff --git a/src/ca/CloseApps.cpp b/src/ca/CloseApps.cpp deleted file mode 100644 index d4256c43..00000000 --- a/src/ca/CloseApps.cpp +++ /dev/null @@ -1,568 +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 DEFAULT_PROCESS_EXIT_WAIT_TIME 5000 - -// structs -LPCWSTR wzQUERY_CLOSEAPPS = L"SELECT `Wix4CloseApplication`, `Target`, `Description`, `Condition`, `Attributes`, `Property`, `TerminateExitCode`, `Timeout` FROM `Wix4CloseApplication` ORDER BY `Sequence`"; -enum eQUERY_CLOSEAPPS { QCA_ID = 1, QCA_TARGET, QCA_DESCRIPTION, QCA_CONDITION, QCA_ATTRIBUTES, QCA_PROPERTY, QCA_TERMINATEEXITCODE, QCA_TIMEOUT }; - -// CloseApplication.Attributes -enum CLOSEAPP_ATTRIBUTES -{ - CLOSEAPP_ATTRIBUTE_NONE = 0x0, - CLOSEAPP_ATTRIBUTE_CLOSEMESSAGE = 0x1, - CLOSEAPP_ATTRIBUTE_REBOOTPROMPT = 0x2, - CLOSEAPP_ATTRIBUTE_ELEVATEDCLOSEMESSAGE = 0x4, - CLOSEAPP_ATTRIBUTE_ENDSESSIONMESSAGE = 0x8, - CLOSEAPP_ATTRIBUTE_ELEVATEDENDSESSIONMESSAGE = 0x10, - CLOSEAPP_ATTRIBUTE_TERMINATEPROCESS = 0x20, - CLOSEAPP_ATTRIBUTE_PROMPTTOCONTINUE = 0x40, -}; - -struct PROCESS_AND_MESSAGE -{ - DWORD dwProcessId; - DWORD dwMessageId; - DWORD dwTimeout; -}; - - -/****************************************************************** - EnumWindowsProc - callback function which sends message if the - current window matches the passed in process ID - -******************************************************************/ -BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) -{ - PROCESS_AND_MESSAGE* pPM = reinterpret_cast(lParam); - DWORD dwProcessId = 0; - DWORD_PTR dwResult = 0; - BOOL fQueryEndSession = WM_QUERYENDSESSION == pPM->dwMessageId; - BOOL fContinueWindowsInProcess = TRUE; // assume we will send message to all top-level windows in a process. - - ::GetWindowThreadProcessId(hwnd, &dwProcessId); - - // check if the process Id is the one we're looking for - if (dwProcessId != pPM->dwProcessId) - { - return TRUE; - } - - WcaLog(LOGMSG_VERBOSE, "Sending message to process id 0x%x", dwProcessId); - - if (::SendMessageTimeoutW(hwnd, pPM->dwMessageId, 0, fQueryEndSession ? ENDSESSION_CLOSEAPP : 0, SMTO_BLOCK, pPM->dwTimeout, &dwResult)) - { - WcaLog(LOGMSG_VERBOSE, "Result 0x%x", dwResult); - - if (fQueryEndSession) - { - // If application said it was okay to close, do that. - if (dwResult) - { - ::SendMessageTimeoutW(hwnd, WM_ENDSESSION, TRUE, ENDSESSION_CLOSEAPP, SMTO_BLOCK, pPM->dwTimeout, &dwResult); - } - else // application said don't try to close it, so don't bother sending messages to any other top-level windows. - { - fContinueWindowsInProcess = FALSE; - } - } - } - else // log result message. - { - WcaLog(LOGMSG_VERBOSE, "Failed to send message id: %u, error: 0x%x", pPM->dwMessageId, ::GetLastError()); - } - - // so we know we succeeded - ::SetLastError(ERROR_SUCCESS); - - return fContinueWindowsInProcess; -} - -/****************************************************************** - PromptToContinue - displays the prompt if the application is still - running. - -******************************************************************/ -static HRESULT PromptToContinue( - __in_z LPCWSTR wzApplication, - __in_z LPCWSTR wzPrompt - ) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - PMSIHANDLE hRecMessage = NULL; - DWORD *prgProcessIds = NULL; - DWORD cProcessIds = 0; - - hRecMessage = ::MsiCreateRecord(1); - ExitOnNull(hRecMessage, hr, E_OUTOFMEMORY, "Failed to create record for prompt."); - - er = ::MsiRecordSetStringW(hRecMessage, 0, wzPrompt); - ExitOnWin32Error(er, hr, "Failed to set prompt record field string"); - - do - { - hr = ProcFindAllIdsFromExeName(wzApplication, &prgProcessIds, &cProcessIds); - if (SUCCEEDED(hr) && 0 < cProcessIds) - { - er = WcaProcessMessage(static_cast(INSTALLMESSAGE_WARNING | MB_ABORTRETRYIGNORE | MB_DEFBUTTON3 | MB_ICONWARNING), hRecMessage); - if (IDABORT == er) - { - hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); - } - else if (IDRETRY == er) - { - hr = S_FALSE; - } - else if (IDIGNORE == er) - { - hr = S_OK; - } - else - { - ExitOnWin32Error(er, hr, "Unexpected return value from prompt to continue."); - } - } - - ReleaseNullMem(prgProcessIds); - cProcessIds = 0; - } while (S_FALSE == hr); - -LExit: - ReleaseMem(prgProcessIds); - return hr; -} - -/****************************************************************** - SendProcessMessage - helper function to enumerate the top-level - windows and send to all matching a process ID. - -******************************************************************/ -void SendProcessMessage( - __in DWORD dwProcessId, - __in DWORD dwMessageId, - __in DWORD dwTimeout - ) -{ - WcaLog(LOGMSG_VERBOSE, "Attempting to send process id 0x%x message id: %u", dwProcessId, dwMessageId); - - PROCESS_AND_MESSAGE pm = { }; - pm.dwProcessId = dwProcessId; - pm.dwMessageId = dwMessageId; - pm.dwTimeout = dwTimeout; - - if (!::EnumWindows(EnumWindowsProc, reinterpret_cast(&pm))) - { - DWORD dwLastError = ::GetLastError(); - if (ERROR_SUCCESS != dwLastError) - { - WcaLog(LOGMSG_VERBOSE, "CloseApp enumeration error: 0x%x", dwLastError); - } - } -} - -/****************************************************************** - SendApplicationMessage - helper function to iterate through the - processes for the specified application and send all - applicable process Ids a message and give them time to process - the message. - -******************************************************************/ -void SendApplicationMessage( - __in LPCWSTR wzApplication, - __in DWORD dwMessageId, - __in DWORD dwTimeout - ) -{ - DWORD *prgProcessIds = NULL; - DWORD cProcessIds = 0, iProcessId; - HRESULT hr = S_OK; - - WcaLog(LOGMSG_VERBOSE, "Checking App: %ls ", wzApplication); - - hr = ProcFindAllIdsFromExeName(wzApplication, &prgProcessIds, &cProcessIds); - - if (SUCCEEDED(hr) && 0 < cProcessIds) - { - WcaLog(LOGMSG_VERBOSE, "App: %ls found running, %d processes, attempting to send message.", wzApplication, cProcessIds); - - for (iProcessId = 0; iProcessId < cProcessIds; ++iProcessId) - { - SendProcessMessage(prgProcessIds[iProcessId], dwMessageId, dwTimeout); - } - - ProcWaitForIds(prgProcessIds, cProcessIds, dwTimeout); - } - - ReleaseMem(prgProcessIds); -} - -/****************************************************************** - SetRunningProcessProperty - helper function that sets the specified - property if there are any instances of the specified executable - running. Useful to show custom UI to ask for shutdown. -******************************************************************/ -void SetRunningProcessProperty( - __in LPCWSTR wzApplication, - __in LPCWSTR wzProperty - ) -{ - DWORD *prgProcessIds = NULL; - DWORD cProcessIds = 0; - HRESULT hr = S_OK; - - WcaLog(LOGMSG_VERBOSE, "Checking App: %ls ", wzApplication); - - hr = ProcFindAllIdsFromExeName(wzApplication, &prgProcessIds, &cProcessIds); - - if (SUCCEEDED(hr) && 0 < cProcessIds) - { - WcaLog(LOGMSG_VERBOSE, "App: %ls found running, %d processes, setting '%ls' property.", wzApplication, cProcessIds, wzProperty); - WcaSetIntProperty(wzProperty, cProcessIds); - } - - ReleaseMem(prgProcessIds); -} - -/****************************************************************** - TerminateProcesses - helper function that kills the provided set of - process ids such that they return a particular exit code. -******************************************************************/ -void TerminateProcesses( - __in_ecount(cProcessIds) DWORD rgdwProcessIds[], - __in DWORD cProcessIds, - __in DWORD dwExitCode - ) -{ - for (DWORD i = 0; i < cProcessIds; ++i) - { - HANDLE hProcess = ::OpenProcess(PROCESS_TERMINATE, FALSE, rgdwProcessIds[i]); - if (hProcess) - { - ::TerminateProcess(hProcess, dwExitCode); - ::CloseHandle(hProcess); - } - } -} - -/****************************************************************** - WixCloseApplications - entry point for WixCloseApplications Custom Action - - called as Type 1 CustomAction (binary DLL) from Windows Installer - in InstallExecuteSequence before InstallFiles -******************************************************************/ -extern "C" UINT __stdcall WixCloseApplications( - __in MSIHANDLE hInstall - ) -{ - //AssertSz(FALSE, "debug WixCloseApplications"); - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - LPWSTR pwzData = NULL; - LPWSTR pwzId = NULL; - LPWSTR pwzTarget = NULL; - LPWSTR pwzDescription = NULL; - LPWSTR pwzCondition = NULL; - LPWSTR pwzProperty = NULL; - DWORD dwAttributes = 0; - DWORD dwTimeout = 0; - DWORD dwTerminateExitCode = 0; - MSICONDITION condition = MSICONDITION_NONE; - - DWORD cCloseApps = 0; - - PMSIHANDLE hView = NULL; - PMSIHANDLE hRec = NULL; - MSIHANDLE hListboxTable = NULL; - MSIHANDLE hListboxColumns = NULL; - - LPWSTR pwzCustomActionData = NULL; - //DWORD cchCustomActionData = 0; - - // - // initialize - // - hr = WcaInitialize(hInstall, "WixCloseApplications"); - ExitOnFailure(hr, "failed to initialize"); - - // - // loop through all the objects to be secured - // - hr = WcaOpenExecuteView(wzQUERY_CLOSEAPPS, &hView); - ExitOnFailure(hr, "failed to open view on Wix4CloseApplication table"); - while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) - { - hr = WcaGetRecordString(hRec, QCA_ID, &pwzId); - ExitOnFailure(hr, "failed to get id from Wix4CloseApplication table"); - - hr = WcaGetRecordString(hRec, QCA_CONDITION, &pwzCondition); - ExitOnFailure(hr, "failed to get condition from Wix4CloseApplication table"); - - if (pwzCondition && *pwzCondition) - { - condition = ::MsiEvaluateConditionW(hInstall, pwzCondition); - if (MSICONDITION_ERROR == condition) - { - hr = E_INVALIDARG; - ExitOnFailure(hr, "failed to process condition for Wix4CloseApplication '%ls'", pwzId); - } - else if (MSICONDITION_FALSE == condition) - { - continue; // skip processing this target - } - } - - hr = WcaGetRecordFormattedString(hRec, QCA_TARGET, &pwzTarget); - ExitOnFailure(hr, "failed to get target from Wix4CloseApplication table"); - - hr = WcaGetRecordFormattedString(hRec, QCA_DESCRIPTION, &pwzDescription); - ExitOnFailure(hr, "failed to get description from Wix4CloseApplication table"); - - hr = WcaGetRecordInteger(hRec, QCA_ATTRIBUTES, reinterpret_cast(&dwAttributes)); - ExitOnFailure(hr, "failed to get attributes from Wix4CloseApplication table"); - - hr = WcaGetRecordFormattedString(hRec, QCA_PROPERTY, &pwzProperty); - ExitOnFailure(hr, "failed to get property from Wix4CloseApplication table"); - - hr = WcaGetRecordInteger(hRec, QCA_TERMINATEEXITCODE, reinterpret_cast(&dwTerminateExitCode)); - if (S_FALSE == hr) - { - dwTerminateExitCode = 0; - hr = S_OK; - } - ExitOnFailure(hr, "failed to get terminate exit-code from Wix4CloseApplication table"); - - hr = WcaGetRecordInteger(hRec, QCA_TIMEOUT, reinterpret_cast(&dwTimeout)); - if (S_FALSE == hr) - { - dwTimeout = DEFAULT_PROCESS_EXIT_WAIT_TIME; - hr = S_OK; - } - ExitOnFailure(hr, "failed to get timeout from Wix4CloseApplication table"); - - // Before trying any changes to the machine, prompt if requested. - if (dwAttributes & CLOSEAPP_ATTRIBUTE_PROMPTTOCONTINUE) - { - hr = PromptToContinue(pwzTarget, pwzDescription ? pwzDescription : L""); - if (HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) == hr) - { - // Skip error message if user canceled. - ExitFunction(); - } - ExitOnFailure(hr, "Failure while prompting user to continue to close application."); - } - - // - // send WM_CLOSE or WM_QUERYENDSESSION to currently running applications - // - if (dwAttributes & CLOSEAPP_ATTRIBUTE_CLOSEMESSAGE) - { - SendApplicationMessage(pwzTarget, WM_CLOSE, dwTimeout); - } - - if (dwAttributes & CLOSEAPP_ATTRIBUTE_ENDSESSIONMESSAGE) - { - SendApplicationMessage(pwzTarget, WM_QUERYENDSESSION, dwTimeout); - } - - // - // Pass the targets to the deferred action in case the app comes back - // even if we close it now. - // - if (dwAttributes & (CLOSEAPP_ATTRIBUTE_ELEVATEDCLOSEMESSAGE | CLOSEAPP_ATTRIBUTE_ELEVATEDENDSESSIONMESSAGE | CLOSEAPP_ATTRIBUTE_REBOOTPROMPT | CLOSEAPP_ATTRIBUTE_TERMINATEPROCESS)) - { - hr = WcaWriteStringToCaData(pwzTarget, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add target data to CustomActionData"); - - hr = WcaWriteIntegerToCaData(dwAttributes, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add attribute data to CustomActionData"); - - hr = WcaWriteIntegerToCaData(dwTimeout, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add timeout data to CustomActionData"); - - hr = WcaWriteIntegerToCaData(dwTerminateExitCode, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add timeout data to CustomActionData"); - } - - if (pwzProperty && *pwzProperty) - { - SetRunningProcessProperty(pwzTarget, pwzProperty); - } - - ++cCloseApps; - } - - // if we looped through all records all is well - if (E_NOMOREITEMS == hr) - { - hr = S_OK; - } - ExitOnFailure(hr, "failed while looping through all apps to close"); - - // - // Do the UI dance now. - // - /* - - TODO: Do this eventually - - if (cCloseApps) - { - while (TRUE) - { - for (DWORD i = 0; i < cCloseApps; ++i) - { - hr = WcaAddTempRecord(&hListboxTable, &hListboxColumns, L"ListBox", NULL, 0, 4, L"FileInUseProcess", i, target, description); - if (FAILED(hr)) - { - } - } - } - } - */ - - // - // schedule the custom action and add to progress bar - // - if (pwzCustomActionData && *pwzCustomActionData) - { - Assert(0 < cCloseApps); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CloseApplicationsDeferred"), pwzCustomActionData, cCloseApps * COST_CLOSEAPP); - ExitOnFailure(hr, "failed to schedule CloseApplicationsDeferred action"); - } - -LExit: - if (hListboxColumns) - { - ::MsiCloseHandle(hListboxColumns); - } - if (hListboxTable) - { - ::MsiCloseHandle(hListboxTable); - } - - ReleaseStr(pwzCustomActionData); - ReleaseStr(pwzData); - ReleaseStr(pwzProperty); - ReleaseStr(pwzCondition); - ReleaseStr(pwzDescription); - ReleaseStr(pwzTarget); - ReleaseStr(pwzId); - - if (FAILED(hr)) - { - er = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) == hr ? ERROR_INSTALL_USEREXIT : ERROR_INSTALL_FAILURE; - } - return WcaFinalize(er); -} - - -/****************************************************************** - WixCloseApplicationsDeferred - entry point for - WixCloseApplicationsDeferred Custom Action - called as Type 1025 CustomAction - (deferred binary DLL) - - NOTE: deferred CustomAction since it modifies the machine - NOTE: CustomActionData == wzTarget\tdwAttributes\tdwTimeout\tdwTerminateExitCode\t... -******************************************************************/ -extern "C" UINT __stdcall WixCloseApplicationsDeferred( - __in MSIHANDLE hInstall - ) -{ - //AssertSz(FALSE, "debug WixCloseApplicationsDeferred"); - HRESULT hr = S_OK; - DWORD er = ERROR_SUCCESS; - - LPWSTR pwz = NULL; - LPWSTR pwzData = NULL; - LPWSTR pwzTarget = NULL; - DWORD dwAttributes = 0; - DWORD dwTimeout = 0; - DWORD dwTerminateExitCode = 0; - - DWORD *prgProcessIds = NULL; - DWORD cProcessIds = 0; - - // - // initialize - // - hr = WcaInitialize(hInstall, "WixCloseApplicationsDeferred"); - ExitOnFailure(hr, "failed to initialize"); - - hr = WcaGetProperty(L"CustomActionData", &pwzData); - ExitOnFailure(hr, "failed to get CustomActionData"); - - WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); - - pwz = pwzData; - - // - // loop through all the passed in data - // - while (pwz && *pwz) - { - hr = WcaReadStringFromCaData(&pwz, &pwzTarget); - ExitOnFailure(hr, "failed to process target from CustomActionData"); - - hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwAttributes)); - ExitOnFailure(hr, "failed to process attributes from CustomActionData"); - - hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwTimeout)); - ExitOnFailure(hr, "failed to process timeout from CustomActionData"); - - hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwTerminateExitCode)); - ExitOnFailure(hr, "failed to process terminate exit code from CustomActionData"); - - WcaLog(LOGMSG_VERBOSE, "Checking for App: %ls Attributes: %d", pwzTarget, dwAttributes); - - // - // send WM_CLOSE or WM_QUERYENDSESSION to currently running applications - // - if (dwAttributes & CLOSEAPP_ATTRIBUTE_ELEVATEDCLOSEMESSAGE) - { - SendApplicationMessage(pwzTarget, WM_CLOSE, dwTimeout); - } - - if (dwAttributes & CLOSEAPP_ATTRIBUTE_ELEVATEDENDSESSIONMESSAGE) - { - SendApplicationMessage(pwzTarget, WM_QUERYENDSESSION, dwTimeout); - } - - // If we find that an app that we need closed is still runing, require a - // restart or kill the process as directed. - ProcFindAllIdsFromExeName(pwzTarget, &prgProcessIds, &cProcessIds); - if (0 < cProcessIds) - { - if (dwAttributes & CLOSEAPP_ATTRIBUTE_REBOOTPROMPT) - { - WcaLog(LOGMSG_VERBOSE, "App: %ls found running, requiring a reboot.", pwzTarget); - - WcaDeferredActionRequiresReboot(); - } - else if (dwAttributes & CLOSEAPP_ATTRIBUTE_TERMINATEPROCESS) - { - TerminateProcesses(prgProcessIds, cProcessIds, dwTerminateExitCode); - } - } - - hr = WcaProgressMessage(COST_CLOSEAPP, FALSE); - ExitOnFailure(hr, "failed to send progress message"); - } - -LExit: - ReleaseMem(prgProcessIds); - - ReleaseStr(pwzTarget); - ReleaseStr(pwzData); - - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - return WcaFinalize(er); -} diff --git a/src/ca/CustomMsiErrors.h b/src/ca/CustomMsiErrors.h deleted file mode 100644 index 3218b61b..00000000 --- a/src/ca/CustomMsiErrors.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. - - -#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 msierrPERFMONFailedRegisterDLL 26251 -#define msierrPERFMONFailedUnregisterDLL 26252 -#define msierrInstallPerfCounterData 26253 -#define msierrUninstallPerfCounterData 26254 - -#define msierrSMBFailedCreate 26301 -#define msierrSMBFailedDrop 26302 -#define msierrUSRFailedUserCreate 26401 -#define msierrUSRFailedUserCreatePswd 26402 -#define msierrUSRFailedUserGroupAdd 26403 -#define msierrUSRFailedUserCreateExists 26404 -#define msierrUSRFailedGrantLogonAsService 26405 - -//Last available is 26450 \ No newline at end of file diff --git a/src/ca/FormatFiles.cpp b/src/ca/FormatFiles.cpp deleted file mode 100644 index d1533999..00000000 --- a/src/ca/FormatFiles.cpp +++ /dev/null @@ -1,221 +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 UINT COST_FILEFORMATTING = 2000; - - -// -// WixSchedFormatFiles - immediate CA to schedule format files CAs -// -extern "C" UINT __stdcall WixSchedFormatFiles( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - PSCZ sczBinaryKey; - PSCZ sczFileKey; - PSCZ sczComponentKey; - PSCZ sczFormattedFile; - PSCZ sczFilePath; - PMSIHANDLE hView; - PMSIHANDLE hRec; - PSCZ sczFileContent; - PSCZ sczFormattedContent; - PSCZ sczExecCustomActionData; - PSCZ sczRollbackCustomActionData; - - LPCWSTR wzQuery = - L"SELECT `Wix4FormatFile`.`Binary_`, `Wix4FormatFile`.`File_`, `File`.`Component_` " - L"FROM `Wix4FormatFile`, `File` " - L"WHERE `Wix4FormatFile`.`File_` = `File`.`File`"; - enum eQuery { eqBinaryKey = 1, eqFileKey, eqComponentKey }; - - // initialize - hr = WcaInitialize(hInstall, "WixSchedFormatFiles"); - ExitOnFailure(hr, "Failed to initialize for WixSchedFormatFiles."); - - // query and loop through all the files - hr = WcaOpenExecuteView(wzQuery, &hView); - ExitOnFailure(hr, "Failed to open view on Wix4FormatFile table"); - - DWORD cFiles = 0; - while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) - { - ++cFiles; - - hr = WcaGetRecordString(hRec, eqBinaryKey, &sczBinaryKey); - ExitOnFailure(hr, "Failed to get Binary table key."); - - hr = WcaGetRecordString(hRec, eqFileKey, &sczFileKey); - ExitOnFailure(hr, "Failed to get File table key."); - - hr = WcaGetRecordString(hRec, eqComponentKey, &sczComponentKey); - ExitOnFailure(hr, "Failed to get Component table key."); - - // we need to know if the component's being installed, uninstalled, or reinstalled - WCA_TODO todo = WcaGetComponentToDo(sczComponentKey); - if (WCA_TODO_INSTALL == todo || WCA_TODO_REINSTALL == todo) - { - // turn the file key into the path to the target file - hr = StrAllocFormatted(&sczFormattedFile, L"[#%ls]", sczFileKey); - ExitOnFailure(hr, "Failed to format file string for file: %ls", sczFileKey); - hr = WcaGetFormattedString(sczFormattedFile, &sczFilePath); - ExitOnFailure(hr, "Failed to get path for file: %ls", sczFileKey); - - // extract binary to string - WCA_ENCODING encoding = WCA_ENCODING_UNKNOWN; - hr = WcaExtractBinaryToString(sczBinaryKey, &sczFileContent, &encoding); - ExitOnFailure(hr, "Failed to extract binary: %ls", sczBinaryKey); - - // format string - hr = WcaGetFormattedString(sczFileContent, &sczFormattedContent); - ExitOnFailure(hr, "Failed to format file content: %ls", sczFileContent); - - // write to deferred custom action data - hr = WcaWriteStringToCaData(sczFilePath, &sczExecCustomActionData); - ExitOnFailure(hr, "Failed to write deferred custom action data for file: %ls", sczFilePath); - - hr = WcaWriteIntegerToCaData(encoding, &sczExecCustomActionData); - ExitOnFailure(hr, "Failed to write deferred custom action data for encoding: %d", encoding); - - hr = WcaWriteStringToCaData(sczFormattedContent, &sczExecCustomActionData); - ExitOnFailure(hr, "Failed to write deferred custom action data for file content: %ls", sczFilePath); - - // write to rollback custom action data - hr = WcaWriteStringToCaData(sczFilePath, &sczRollbackCustomActionData); - ExitOnFailure(hr, "Failed to write rollback custom action data for file: %ls", sczFilePath); - - hr = WcaWriteIntegerToCaData(encoding, &sczRollbackCustomActionData); - ExitOnFailure(hr, "Failed to write deferred custom action data for encoding: %d", encoding); - - hr = WcaWriteStringToCaData(sczFileContent, &sczRollbackCustomActionData); - ExitOnFailure(hr, "Failed to write rollback custom action data for file content: %ls", sczFilePath); - } - } - - // reaching the end of the list is actually a good thing, not an error - if (E_NOMOREITEMS == hr) - { - hr = S_OK; - } - ExitOnFailure(hr, "Failure occurred while processing Wix4FormatFile table"); - - // schedule deferred CAs if there's anything to do - if (sczRollbackCustomActionData && *sczRollbackCustomActionData) - { - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackFormatFiles"), sczRollbackCustomActionData, cFiles * COST_FILEFORMATTING); - ExitOnFailure(hr, "Failed to schedule RollbackFormatFiles"); - } - - if (sczExecCustomActionData && *sczExecCustomActionData) - { - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecFormatFiles"), sczExecCustomActionData, cFiles * COST_FILEFORMATTING); - ExitOnFailure(hr, "Failed to schedule ExecFormatFiles"); - } - -LExit: - return WcaFinalize(er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er); -} - - -// -// WixExecFormatFiles - deferred and rollback CAs to write formatted files -// -extern "C" UINT __stdcall WixExecFormatFiles( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - PSCZ sczCustomActionData; - LPWSTR pwz = NULL; - PSCZ sczFilePath; - PSCZ sczFileContent; - LPSTR psz = NULL; - - // initialize - hr = WcaInitialize(hInstall, "WixExecFormatFiles"); - ExitOnFailure(hr, "Failed to initialize for WixExecFormatFiles."); - - hr = WcaGetProperty(L"CustomActionData", &sczCustomActionData); - ExitOnFailure(hr, "Failed to get CustomActionData."); -#ifdef _DEBUG - WcaLog(LOGMSG_STANDARD, "CustomActionData: %ls", sczCustomActionData); -#endif - - // loop through all the passed in data - pwz = sczCustomActionData; - while (pwz && *pwz) - { - // extract the custom action data - hr = WcaReadStringFromCaData(&pwz, &sczFilePath); - ExitOnFailure(hr, "Failed to read file path from custom action data"); - - WCA_ENCODING encoding = WCA_ENCODING_UNKNOWN; - hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&encoding)); - ExitOnFailure(hr, "Failed to read encoding from custom action data"); - - hr = WcaReadStringFromCaData(&pwz, &sczFileContent); - ExitOnFailure(hr, "Failed to read file content from custom action data"); - - // re-encode content - LPCBYTE pbData = NULL; - size_t cbData = 0; - switch (encoding) - { - case WCA_ENCODING_UTF_16: - pbData = reinterpret_cast(LPCWSTR(sczFileContent)); - cbData = lstrlenW(sczFileContent) * sizeof(WCHAR); - break; - - case WCA_ENCODING_UTF_8: - hr = StrAnsiAllocString(&psz, sczFileContent, 0, CP_UTF8); - ExitOnFailure(hr, "Failed to convert Unicode to UTF-8."); - pbData = reinterpret_cast(psz); - - hr = ::StringCbLengthA(psz, STRSAFE_MAX_CCH, &cbData); - ExitOnFailure(hr, "Failed to count UTF-8 bytes."); - break; - - case WCA_ENCODING_ANSI: - hr = StrAnsiAllocString(&psz, sczFileContent, 0, CP_ACP); - ExitOnFailure(hr, "Failed to convert Unicode to ANSI."); - pbData = reinterpret_cast(psz); - - hr = ::StringCbLengthA(psz, STRSAFE_MAX_CCH, &cbData); - ExitOnFailure(hr, "Failed to count UTF-8 bytes."); - break; - - default: - break; - } - -#ifdef _DEBUG - WcaLog(LOGMSG_STANDARD, "File: %ls", sczCustomActionData); - WcaLog(LOGMSG_STANDARD, "Content: %ls", sczFileContent); -#endif - - // write file and preserve modified time - FILETIME filetime; - - hr = FileGetTime(sczFilePath, NULL, NULL, &filetime); - ExitOnFailure(hr, "Failed to get modified time of file : %ls", sczFilePath); - - hr = FileWrite(sczFilePath, FILE_ATTRIBUTE_NORMAL, pbData, cbData, NULL); - ExitOnFailure(hr, "Failed to write file content: %ls", sczFilePath); - - hr = FileSetTime(sczFilePath, NULL, NULL, &filetime); - ExitOnFailure(hr, "Failed to set modified time of file : %ls", sczFilePath); - - // Tick the progress bar - hr = WcaProgressMessage(COST_FILEFORMATTING, FALSE); - ExitOnFailure(hr, "Failed to tick progress bar for file: %ls", sczFilePath); - } - -LExit: - ReleaseStr(psz); - - return WcaFinalize(er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er); -} diff --git a/src/ca/OsInfo.cpp b/src/ca/OsInfo.cpp deleted file mode 100644 index 4783673e..00000000 --- a/src/ca/OsInfo.cpp +++ /dev/null @@ -1,487 +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" - -// constants we'll pick up from later SDKs -#define SM_TABLETPC 86 -#define SM_MEDIACENTER 87 -#define SM_STARTER 88 -#define SM_SERVERR2 89 -#define VER_SUITE_WH_SERVER 0x00008000 - -/******************************************************************** -WixQueryOsInfo - entry point for WixQueryOsInfo custom action - - Called as Type 1 custom action (DLL from the Binary table) from - Windows Installer to set properties that identify OS information - and predefined directories -********************************************************************/ -extern "C" UINT __stdcall WixQueryOsInfo( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr = S_OK; - DWORD er = ERROR_SUCCESS; - OSVERSIONINFOEXW ovix = {0}; - - hr = WcaInitialize(hInstall, "WixQueryOsInfo"); - ExitOnFailure(hr, "WixQueryOsInfo failed to initialize"); - - // identify product suites - ovix.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); - #pragma warning(suppress: 4996) //TODO: use osutil - ::GetVersionExW(reinterpret_cast(&ovix)); - - if (VER_SUITE_SMALLBUSINESS == (ovix.wSuiteMask & VER_SUITE_SMALLBUSINESS)) - { - WcaSetIntProperty(L"WIX_SUITE_SMALLBUSINESS", 1); - } - - if (VER_SUITE_ENTERPRISE == (ovix.wSuiteMask & VER_SUITE_ENTERPRISE)) - { - WcaSetIntProperty(L"WIX_SUITE_ENTERPRISE", 1); - } - - if (VER_SUITE_BACKOFFICE == (ovix.wSuiteMask & VER_SUITE_BACKOFFICE)) - { - WcaSetIntProperty(L"WIX_SUITE_BACKOFFICE", 1); - } - - if (VER_SUITE_COMMUNICATIONS == (ovix.wSuiteMask & VER_SUITE_COMMUNICATIONS)) - { - WcaSetIntProperty(L"WIX_SUITE_COMMUNICATIONS", 1); - } - - if (VER_SUITE_TERMINAL == (ovix.wSuiteMask & VER_SUITE_TERMINAL)) - { - WcaSetIntProperty(L"WIX_SUITE_TERMINAL", 1); - } - - if (VER_SUITE_SMALLBUSINESS_RESTRICTED == (ovix.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED)) - { - WcaSetIntProperty(L"WIX_SUITE_SMALLBUSINESS_RESTRICTED", 1); - } - - if (VER_SUITE_EMBEDDEDNT == (ovix.wSuiteMask & VER_SUITE_EMBEDDEDNT)) - { - WcaSetIntProperty(L"WIX_SUITE_EMBEDDEDNT", 1); - } - - if (VER_SUITE_DATACENTER == (ovix.wSuiteMask & VER_SUITE_DATACENTER)) - { - WcaSetIntProperty(L"WIX_SUITE_DATACENTER", 1); - } - - if (VER_SUITE_SINGLEUSERTS == (ovix.wSuiteMask & VER_SUITE_SINGLEUSERTS)) - { - WcaSetIntProperty(L"WIX_SUITE_SINGLEUSERTS", 1); - } - - if (VER_SUITE_PERSONAL == (ovix.wSuiteMask & VER_SUITE_PERSONAL)) - { - WcaSetIntProperty(L"WIX_SUITE_PERSONAL", 1); - } - - if (VER_SUITE_BLADE == (ovix.wSuiteMask & VER_SUITE_BLADE)) - { - WcaSetIntProperty(L"WIX_SUITE_BLADE", 1); - } - - if (VER_SUITE_EMBEDDED_RESTRICTED == (ovix.wSuiteMask & VER_SUITE_EMBEDDED_RESTRICTED)) - { - WcaSetIntProperty(L"WIX_SUITE_EMBEDDED_RESTRICTED", 1); - } - - if (VER_SUITE_SECURITY_APPLIANCE == (ovix.wSuiteMask & VER_SUITE_SECURITY_APPLIANCE)) - { - WcaSetIntProperty(L"WIX_SUITE_SECURITY_APPLIANCE", 1); - } - - if (VER_SUITE_STORAGE_SERVER == (ovix.wSuiteMask & VER_SUITE_STORAGE_SERVER)) - { - WcaSetIntProperty(L"WIX_SUITE_STORAGE_SERVER", 1); - } - - if (VER_SUITE_COMPUTE_SERVER == (ovix.wSuiteMask & VER_SUITE_COMPUTE_SERVER)) - { - WcaSetIntProperty(L"WIX_SUITE_COMPUTE_SERVER", 1); - } - - if (VER_SUITE_WH_SERVER == (ovix.wSuiteMask & VER_SUITE_WH_SERVER)) - { - WcaSetIntProperty(L"WIX_SUITE_WH_SERVER", 1); - } - - // only for XP and later - if (5 < ovix.dwMajorVersion || (5 == ovix.dwMajorVersion && 0 < ovix.dwMinorVersion)) - { - if (::GetSystemMetrics(SM_SERVERR2)) - { - WcaSetIntProperty(L"WIX_SUITE_SERVERR2", 1); - } - - if (::GetSystemMetrics(SM_MEDIACENTER)) - { - WcaSetIntProperty(L"WIX_SUITE_MEDIACENTER", 1); - } - - if (::GetSystemMetrics(SM_STARTER)) - { - WcaSetIntProperty(L"WIX_SUITE_STARTER", 1); - } - - if (::GetSystemMetrics(SM_TABLETPC)) - { - WcaSetIntProperty(L"WIX_SUITE_TABLETPC", 1); - } - } - -LExit: - if (FAILED(hr)) - er = ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - -/******************************************************************** -WixQueryOsDirs - entry point for WixQueryOsDirs custom action - - Called as Type 1 custom action (DLL from the Binary table) from - Windows Installer to set properties that identify predefined directories -********************************************************************/ -extern "C" UINT __stdcall WixQueryOsDirs( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr = S_OK; - DWORD er = ERROR_SUCCESS; - - hr = WcaInitialize(hInstall, "WixQueryOsDirs"); - ExitOnFailure(hr, "WixQueryOsDirs failed to initialize"); - - // get the paths of the CSIDLs that represent real paths and for which MSI - // doesn't yet have standard folder properties - WCHAR path[MAX_PATH]; - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_ADMINTOOLS", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_ALTSTARTUP, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_ALTSTARTUP", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_CDBURN_AREA, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_CDBURN_AREA", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_COMMON_ADMINTOOLS, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_COMMON_ADMINTOOLS", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_COMMON_ALTSTARTUP, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_COMMON_ALTSTARTUP", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_COMMON_DOCUMENTS, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_COMMON_DOCUMENTS", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_COMMON_FAVORITES, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_COMMON_FAVORITES", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_COMMON_MUSIC, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_COMMON_MUSIC", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_COMMON_PICTURES, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_COMMON_PICTURES", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_COMMON_VIDEO, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_COMMON_VIDEO", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_COOKIES, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_COOKIES", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_DESKTOP", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_HISTORY, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_HISTORY", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_INTERNET_CACHE, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_INTERNET_CACHE", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_MYMUSIC, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_MYMUSIC", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_MYPICTURES", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_MYVIDEO, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_MYVIDEO", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_NETHOOD", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_PERSONAL", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_PRINTHOOD", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_PROFILE", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_RECENT", path); - } - - if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_RESOURCES, NULL, SHGFP_TYPE_CURRENT, path)) - { - WcaSetProperty(L"WIX_DIR_RESOURCES", path); - } - -LExit: - if (FAILED(hr)) - er = ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - -/******************************************************************** -SetPropertyWellKnownSID - - Set a property with the localized name of a well known windows SID -********************************************************************/ -static HRESULT SetPropertyWellKnownSID( - __in WELL_KNOWN_SID_TYPE sidType, - __in LPCWSTR wzPropertyName, - __in BOOL fIncludeDomainName - ) -{ - HRESULT hr = S_OK; - PSID psid = NULL; - WCHAR wzRefDomain[MAX_PATH] = {0}; - SID_NAME_USE nameUse; - DWORD refSize = MAX_PATH; - WCHAR wzName[MAX_PATH] = {0}; - LPWSTR pwzPropertyValue = NULL; - DWORD size = MAX_PATH; - - hr = AclGetWellKnownSid(sidType, &psid); - ExitOnFailure(hr, "Failed to get SID; skipping account %ls", wzPropertyName); - - if (!::LookupAccountSidW(NULL, psid, wzName, &size, wzRefDomain, &refSize, &nameUse)) - { - ExitWithLastError(hr, "Failed to look up account for SID; skipping account %ls.", wzPropertyName); - } - - if (fIncludeDomainName) - { - hr = StrAllocFormatted(&pwzPropertyValue, L"%s\\%s", wzRefDomain, wzName); - ExitOnFailure(hr, "Failed to format property value"); - - hr = WcaSetProperty(wzPropertyName, pwzPropertyValue); - ExitOnFailure(hr, "Failed write domain\\name property"); - } - else - { - hr = WcaSetProperty(wzPropertyName, wzName); - ExitOnFailure(hr, "Failed write to name-only property"); - } - -LExit: - if (NULL != psid) - { - ::LocalFree(psid); - } - ReleaseStr(pwzPropertyValue); - return hr; -} - -/******************************************************************** -WixQueryOsWellKnownSID - entry point for WixQueryOsWellKnownSID custom action - - Called as Type 1 custom action (DLL from the Binary table) from - Windows Installer to set properties with the localized names of built-in - Windows Security IDs -********************************************************************/ -extern "C" UINT __stdcall WixQueryOsWellKnownSID( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr = S_OK; - DWORD er = ERROR_SUCCESS; - - hr = WcaInitialize(hInstall, "WixQueryOsWellKnownSID"); - ExitOnFailure(hr, "WixQueryOsWellKnownSID failed to initialize"); - - SetPropertyWellKnownSID(WinLocalSystemSid, L"WIX_ACCOUNT_LOCALSYSTEM", TRUE); - SetPropertyWellKnownSID(WinLocalServiceSid, L"WIX_ACCOUNT_LOCALSERVICE", TRUE); - SetPropertyWellKnownSID(WinNetworkServiceSid, L"WIX_ACCOUNT_NETWORKSERVICE", TRUE); - SetPropertyWellKnownSID(WinBuiltinAdministratorsSid, L"WIX_ACCOUNT_ADMINISTRATORS", TRUE); - SetPropertyWellKnownSID(WinBuiltinUsersSid, L"WIX_ACCOUNT_USERS", TRUE); - SetPropertyWellKnownSID(WinBuiltinGuestsSid, L"WIX_ACCOUNT_GUESTS", TRUE); - SetPropertyWellKnownSID(WinBuiltinPerfLoggingUsersSid, L"WIX_ACCOUNT_PERFLOGUSERS", TRUE); - SetPropertyWellKnownSID(WinBuiltinPerfLoggingUsersSid, L"WIX_ACCOUNT_PERFLOGUSERS_NODOMAIN", FALSE); - -LExit: - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - return WcaFinalize(er); -} - - -/******************************************************************** -DetectWDDMDriver - - Set a property if the driver on the machine is a WDDM driver. One - reliable way to detect the presence of a WDDM driver is to try and - use the Direct3DCreate9Ex() function. This method attempts that - then sets the property appropriately. -********************************************************************/ -static HRESULT DetectWDDMDriver() -{ - HRESULT hr = S_OK; - HMODULE hModule = NULL; - - // Manually load the d3d9.dll library. If the library couldn't be loaded then we obviously won't be able - // to try calling the function so just return. - hr = LoadSystemLibrary(L"d3d9.dll", &hModule); - if (E_MODNOTFOUND == hr) - { - TraceError(hr, "Unable to load DirectX APIs, skipping WDDM driver check."); - ExitFunction1(hr = S_OK); - } - ExitOnFailure(hr, "Failed to the load the existing DirectX APIs."); - - // Obtain the address of the Direct3DCreate9Ex function. If this fails we know it isn't a WDDM - // driver so just exit. - const void* Direct3DCreate9ExPtr = ::GetProcAddress(hModule, "Direct3DCreate9Ex"); - ExitOnNull(Direct3DCreate9ExPtr, hr, S_OK, "Unable to load Direct3DCreateEx function, so the driver is not a WDDM driver."); - - // At this point we know it's a WDDM driver so set the property. - hr = WcaSetIntProperty(L"WIX_WDDM_DRIVER_PRESENT", 1); - ExitOnFailure(hr, "Failed write property"); - -LExit: - if (NULL != hModule) - { - FreeLibrary(hModule); - } - - return hr; -} - -/******************************************************************** -DetectIsCompositionEnabled - - Set a property based on the return value of DwmIsCompositionEnabled(). -********************************************************************/ -static HRESULT DetectIsCompositionEnabled() -{ - HRESULT hr = S_OK; - HMODULE hModule = NULL; - BOOL compositionState = false; - - // Manually load the d3d9.dll library. If the library can't load it's likely because we are not on a Vista - // OS. Just return ok, and the property won't get set. - hr = LoadSystemLibrary(L"dwmapi.dll", &hModule); - if (E_MODNOTFOUND == hr) - { - TraceError(hr, "Unable to load Vista desktop window manager APIs, skipping Composition Enabled check."); - ExitFunction1(hr = S_OK); - } - ExitOnFailure(hr, "Failed to load the existing window manager APIs."); - - // If for some reason we can't get the function pointer that's ok, just return. - typedef HRESULT (WINAPI *DWMISCOMPOSITIONENABLEDPTR)(BOOL*); - DWMISCOMPOSITIONENABLEDPTR DwmIsCompositionEnabledPtr = (DWMISCOMPOSITIONENABLEDPTR)::GetProcAddress(hModule, "DwmIsCompositionEnabled"); - ExitOnNull(hModule, hr, S_OK, "Unable to obtain function information, skipping Composition Enabled check."); - - hr = DwmIsCompositionEnabledPtr(&compositionState); - ExitOnFailure(hr, "Failed to retrieve Composition state"); - - if (compositionState) - { - hr = WcaSetIntProperty(L"WIX_DWM_COMPOSITION_ENABLED", 1); - ExitOnFailure(hr, "Failed write property"); - } - -LExit: - if (NULL != hModule) - { - FreeLibrary(hModule); - } - return hr; -} - -/******************************************************************** -WixQueryOsDriverInfo - entry point for WixQueryOsDriverInfo custom action - - Called as Type 1 custom action (DLL from the Binary table) from - Windows Installer to set properties about drivers installed on - the target machine -********************************************************************/ -extern "C" UINT __stdcall WixQueryOsDriverInfo( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr = S_OK; - DWORD er = ERROR_SUCCESS; - - hr = WcaInitialize(hInstall, "WixQueryOsDriverInfo"); - ExitOnFailure(hr, "WixQueryOsDriverInfo failed to initialize"); - - // Detect the WDDM driver status - hr = DetectWDDMDriver(); - ExitOnFailure(hr, "Failed to detect WIX_WDDM_DRIVER_PRESENT"); - - // Detect whether composition is enabled - hr = DetectIsCompositionEnabled(); - ExitOnFailure(hr, "Failed to detect WIX_DWM_COMPOSITION_ENABLED"); - -LExit: - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - return WcaFinalize(er); -} diff --git a/src/ca/RemoveFoldersEx.cpp b/src/ca/RemoveFoldersEx.cpp deleted file mode 100644 index cbc7f4bb..00000000 --- a/src/ca/RemoveFoldersEx.cpp +++ /dev/null @@ -1,243 +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 vcsRemoveFolderExQuery = - L"SELECT `Wix4RemoveFolderEx`, `Component_`, `Property`, `InstallMode`, `WixRemoveFolderEx`.`Condition`, `Component`.`Attributes`" - L"FROM `Wix4RemoveFolderEx``,`Component` " - L"WHERE `Wix4RemoveFolderEx`.`Component_`=`Component`.`Component`"; -enum eRemoveFolderExQuery { rfqId = 1, rfqComponent, rfqProperty, rfqMode, rfqCondition, rfqComponentAttributes }; - -static HRESULT RecursePath( - __in_z LPCWSTR wzPath, - __in_z LPCWSTR wzId, - __in_z LPCWSTR wzComponent, - __in_z LPCWSTR wzProperty, - __in int iMode, - __in BOOL fDisableWow64Redirection, - __inout DWORD* pdwCounter, - __inout MSIHANDLE* phTable, - __inout MSIHANDLE* phColumns - ) -{ - HRESULT hr = S_OK; - DWORD er; - LPWSTR sczSearch = NULL; - LPWSTR sczProperty = NULL; - HANDLE hFind = INVALID_HANDLE_VALUE; - WIN32_FIND_DATAW wfd; - LPWSTR sczNext = NULL; - - if (fDisableWow64Redirection) - { - hr = WcaDisableWow64FSRedirection(); - ExitOnFailure(hr, "Custom action was told to act on a 64-bit component, but was unable to disable filesystem redirection through the Wow64 API."); - } - - // First recurse down to all the child directories. - hr = StrAllocFormatted(&sczSearch, L"%s*", wzPath); - ExitOnFailure(hr, "Failed to allocate file search string in path: %S", wzPath); - - hFind = ::FindFirstFileW(sczSearch, &wfd); - if (INVALID_HANDLE_VALUE == hFind) - { - er = ::GetLastError(); - if (ERROR_PATH_NOT_FOUND == er) - { - WcaLog(LOGMSG_STANDARD, "Search path not found: %ls; skipping", sczSearch); - ExitFunction1(hr = S_FALSE); - } - else - { - hr = HRESULT_FROM_WIN32(er); - } - ExitOnFailure(hr, "Failed to find all files in path: %S", wzPath); - } - - do - { - // Skip files and the dot directories. - if (FILE_ATTRIBUTE_DIRECTORY != (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || L'.' == wfd.cFileName[0] && (L'\0' == wfd.cFileName[1] || (L'.' == wfd.cFileName[1] && L'\0' == wfd.cFileName[2]))) - { - continue; - } - - hr = StrAllocFormatted(&sczNext, L"%s%s\\", wzPath, wfd.cFileName); - ExitOnFailure(hr, "Failed to concat filename '%S' to string: %S", wfd.cFileName, wzPath); - - // Don't re-disable redirection; if it was necessary, we've already done it. - hr = RecursePath(sczNext, wzId, wzComponent, wzProperty, iMode, FALSE, pdwCounter, phTable, phColumns); - ExitOnFailure(hr, "Failed to recurse path: %S", sczNext); - } while (::FindNextFileW(hFind, &wfd)); - - er = ::GetLastError(); - if (ERROR_NO_MORE_FILES == er) - { - hr = S_OK; - } - else - { - hr = HRESULT_FROM_WIN32(er); - ExitOnFailure(hr, "Failed while looping through files in directory: %S", wzPath); - } - - // Finally, set a property that points at our path. - hr = StrAllocFormatted(&sczProperty, L"_%s_%u", wzProperty, *pdwCounter); - ExitOnFailure(hr, "Failed to allocate Property for RemoveFile table with property: %S.", wzProperty); - - ++(*pdwCounter); - - hr = WcaSetProperty(sczProperty, wzPath); - ExitOnFailure(hr, "Failed to set Property: %S with path: %S", sczProperty, wzPath); - - // Add the row to remove any files and another row to remove the folder. - hr = WcaAddTempRecord(phTable, phColumns, L"RemoveFile", NULL, 1, 5, L"RfxFiles", wzComponent, L"*.*", sczProperty, iMode); - ExitOnFailure(hr, "Failed to add row to remove all files for Wix4RemoveFolderEx row: %ls under path: %ls", wzId, wzPath); - - hr = WcaAddTempRecord(phTable, phColumns, L"RemoveFile", NULL, 1, 5, L"RfxFolder", wzComponent, NULL, sczProperty, iMode); - ExitOnFailure(hr, "Failed to add row to remove folder for Wix4RemoveFolderEx row: %ls under path: %ls", wzId, wzPath); - -LExit: - if (INVALID_HANDLE_VALUE != hFind) - { - ::FindClose(hFind); - } - - if (fDisableWow64Redirection) - { - WcaRevertWow64FSRedirection(); - } - - ReleaseStr(sczNext); - ReleaseStr(sczProperty); - ReleaseStr(sczSearch); - return hr; -} - -extern "C" UINT WINAPI WixRemoveFoldersEx( - __in MSIHANDLE hInstall - ) -{ - //AssertSz(FALSE, "debug WixRemoveFoldersEx"); - - HRESULT hr = S_OK; - PMSIHANDLE hView; - PMSIHANDLE hRec; - LPWSTR sczId = NULL; - LPWSTR sczComponent = NULL; - LPWSTR sczProperty = NULL; - LPWSTR sczCondition = NULL; - LPWSTR sczPath = NULL; - LPWSTR sczExpandedPath = NULL; - int iMode = 0; - int iComponentAttributes; - BOOL f64BitComponent = FALSE; - DWORD dwCounter = 0; - DWORD_PTR cchLen = 0; - MSIHANDLE hTable = NULL; - MSIHANDLE hColumns = NULL; - - hr = WcaInitialize(hInstall, "WixRemoveFoldersEx"); - ExitOnFailure(hr, "Failed to initialize WixRemoveFoldersEx."); - - WcaInitializeWow64(); - - // anything to do? - if (S_OK != WcaTableExists(L"Wix4RemoveFolderEx")) - { - WcaLog(LOGMSG_STANDARD, "Wix4RemoveFolderEx table doesn't exist, so there are no folders to remove."); - ExitFunction(); - } - - // query and loop through all the remove folders exceptions - hr = WcaOpenExecuteView(vcsRemoveFolderExQuery, &hView); - ExitOnFailure(hr, "Failed to open view on Wix4RemoveFolderEx table"); - - while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) - { - hr = WcaGetRecordString(hRec, rfqId, &sczId); - ExitOnFailure(hr, "Failed to get remove folder identity."); - - hr = WcaGetRecordString(hRec, rfqCondition, &sczCondition); - ExitOnFailure(hr, "Failed to get remove folder condition."); - - if (sczCondition && *sczCondition) - { - MSICONDITION condition = ::MsiEvaluateConditionW(hInstall, sczCondition); - if (MSICONDITION_TRUE == condition) - { - WcaLog(LOGMSG_STANDARD, "True condition for row %S: %S; processing.", sczId, sczCondition); - } - else - { - WcaLog(LOGMSG_STANDARD, "False or invalid condition for row %S: %S; skipping.", sczId, sczCondition); - continue; - } - } - - hr = WcaGetRecordString(hRec, rfqComponent, &sczComponent); - ExitOnFailure(hr, "Failed to get remove folder component."); - - hr = WcaGetRecordString(hRec, rfqProperty, &sczProperty); - ExitOnFailure(hr, "Failed to get remove folder property."); - - hr = WcaGetRecordInteger(hRec, rfqMode, &iMode); - ExitOnFailure(hr, "Failed to get remove folder mode"); - - hr = WcaGetProperty(sczProperty, &sczPath); - ExitOnFailure(hr, "Failed to resolve remove folder property: %S for row: %S", sczProperty, sczId); - - hr = WcaGetRecordInteger(hRec, rfqComponentAttributes, &iComponentAttributes); - ExitOnFailure(hr, "failed to get component attributes for row: %ls", sczId); - - f64BitComponent = iComponentAttributes & msidbComponentAttributes64bit; - - // fail early if the property isn't set as you probably don't want your installers trying to delete SystemFolder - // StringCchLengthW succeeds only if the string is zero characters plus 1 for the terminating null - hr = ::StringCchLengthW(sczPath, 1, reinterpret_cast(&cchLen)); - if (SUCCEEDED(hr)) - { - ExitOnFailure(hr = E_INVALIDARG, "Missing folder property: %S for row: %S", sczProperty, sczId); - } - - hr = PathExpand(&sczExpandedPath, sczPath, PATH_EXPAND_ENVIRONMENT); - ExitOnFailure(hr, "Failed to expand path: %S for row: %S", sczPath, sczId); - - hr = PathBackslashTerminate(&sczExpandedPath); - ExitOnFailure(hr, "Failed to backslash-terminate path: %S", sczExpandedPath); - - WcaLog(LOGMSG_STANDARD, "Recursing path: %S for row: %S.", sczExpandedPath, sczId); - hr = RecursePath(sczExpandedPath, sczId, sczComponent, sczProperty, iMode, f64BitComponent, &dwCounter, &hTable, &hColumns); - ExitOnFailure(hr, "Failed while navigating path: %S for row: %S", sczPath, sczId); - } - - // reaching the end of the list is actually a good thing, not an error - if (E_NOMOREITEMS == hr) - { - hr = S_OK; - } - ExitOnFailure(hr, "Failure occured while processing Wix4RemoveFolderEx table"); - -LExit: - WcaFinalizeWow64(); - - if (hColumns) - { - ::MsiCloseHandle(hColumns); - } - - if (hTable) - { - ::MsiCloseHandle(hTable); - } - - ReleaseStr(sczExpandedPath); - ReleaseStr(sczPath); - ReleaseStr(sczProperty); - ReleaseStr(sczComponent); - ReleaseStr(sczCondition); - ReleaseStr(sczId); - - DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} diff --git a/src/ca/RemoveRegistryKeysEx.cpp b/src/ca/RemoveRegistryKeysEx.cpp deleted file mode 100644 index 478c0779..00000000 --- a/src/ca/RemoveRegistryKeysEx.cpp +++ /dev/null @@ -1,114 +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 vcsRemoveRegistryKeyExQuery = - L"SELECT `Wix4RemoveRegistryKeyEx`, `Component_`, `Root`, `Key`, `InstallMode`, `Condition` FROM `Wix4RemoveRegistryKeyEx`"; -enum eRemoveRegistryKeyExQuery { rrxqId = 1, rrxqComponent, rrxqRoot, rrxqKey, rrxqMode, rrxqCondition }; - -extern "C" UINT WINAPI WixRemoveRegistryKeysEx( - __in MSIHANDLE hInstall -) -{ - //AssertSz(FALSE, "debug WixRemoveRegistryKeyEx"); - - HRESULT hr = S_OK; - PMSIHANDLE hView; - PMSIHANDLE hRec; - LPWSTR sczId = NULL; - LPWSTR sczComponent = NULL; - LPWSTR sczCondition = NULL; - LPWSTR sczKey = NULL; - int iRoot = 0; - int iMode = 0; - MSIHANDLE hTable = NULL; - MSIHANDLE hColumns = NULL; - - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize " __FUNCTION__); - - // anything to do? - if (S_OK != WcaTableExists(L"Wix4RemoveRegistryKeyEx")) - { - WcaLog(LOGMSG_STANDARD, "Wix4RemoveRegistryKeyEx table doesn't exist, so there are no registry keys to remove."); - ExitFunction(); - } - - hr = WcaOpenExecuteView(vcsRemoveRegistryKeyExQuery, &hView); - ExitOnFailure(hr, "Failed to open view on Wix4RemoveRegistryKeyEx table"); - - while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) - { - hr = WcaGetRecordString(hRec, rrxqId, &sczId); - ExitOnFailure(hr, "Failed to get Wix4RemoveRegistryKeyEx identity."); - - hr = WcaGetRecordString(hRec, rrxqCondition, &sczCondition); - ExitOnFailure(hr, "Failed to get Wix4RemoveRegistryKeyEx condition."); - - if (sczCondition && *sczCondition) - { - MSICONDITION condition = ::MsiEvaluateConditionW(hInstall, sczCondition); - if (MSICONDITION_TRUE == condition) - { - WcaLog(LOGMSG_STANDARD, "True condition for row %S: %S; processing.", sczId, sczCondition); - } - else - { - WcaLog(LOGMSG_STANDARD, "False or invalid condition for row %S: %S; skipping.", sczId, sczCondition); - continue; - } - } - - hr = WcaGetRecordString(hRec, rrxqComponent, &sczComponent); - ExitOnFailure(hr, "Failed to get Wix4RemoveRegistryKeyEx component."); - - hr = WcaGetRecordInteger(hRec, rrxqRoot, &iRoot); - ExitOnFailure(hr, "Failed to get Wix4RemoveRegistryKeyEx root."); - - hr = WcaGetRecordString(hRec, rrxqKey, &sczKey); - ExitOnFailure(hr, "Failed to get Wix4RemoveRegistryKeyEx key."); - - hr = WcaGetRecordInteger(hRec, rrxqMode, &iMode); - ExitOnFailure(hr, "Failed to get Wix4RemoveRegistryKeyEx mode."); - - switch (iMode) - { - case 1: // remove on install - WcaLog(LOGMSG_STANDARD, "Adding RemoveRegistry row: %ls/%d/%ls/-/%ls", sczId, iRoot, sczKey, sczComponent); - hr = WcaAddTempRecord(&hTable, &hColumns, L"RemoveRegistry", NULL, 0, 5, sczId, iRoot, sczKey, L"-", sczComponent); - ExitOnFailure(hr, "Failed to add RemoveRegistry row for remove-on-install Wix4RemoveRegistryKeyEx row: %ls:", sczId); - break; - case 2: // remove on uninstall - WcaLog(LOGMSG_STANDARD, "Adding Registry row: %ls/%d/%ls/-/null/%ls", sczId, iRoot, sczKey, sczComponent); - hr = WcaAddTempRecord(&hTable, &hColumns, L"Registry", NULL, 0, 6, sczId, iRoot, sczKey, L"-", NULL, sczComponent); - ExitOnFailure(hr, "Failed to add Registry row for remove-on-uninstall Wix4RemoveRegistryKeyEx row: %ls:", sczId); - break; - } - } - - // reaching the end of the list is actually a good thing, not an error - if (E_NOMOREITEMS == hr) - { - hr = S_OK; - } - ExitOnFailure(hr, "Failure occured while processing Wix4RemoveRegistryKeyEx table."); - -LExit: - if (hColumns) - { - ::MsiCloseHandle(hColumns); - } - - if (hTable) - { - ::MsiCloseHandle(hTable); - } - - ReleaseStr(sczKey); - ReleaseStr(sczComponent); - ReleaseStr(sczCondition); - ReleaseStr(sczId); - - DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} diff --git a/src/ca/RestartManager.cpp b/src/ca/RestartManager.cpp deleted file mode 100644 index c31819c1..00000000 --- a/src/ca/RestartManager.cpp +++ /dev/null @@ -1,185 +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" -#include - -// Include space for the terminating null. -#define CCH_SESSION_KEY CCH_RM_SESSION_KEY + 1 - -enum eRmuResourceType -{ - etInvalid, - etFilename, - etApplication, - etServiceName, - - // Mask types from Attributes. - etTypeMask = 0xf, -}; - -LPCWSTR vcsRestartResourceQuery = - L"SELECT `Wix4RestartResource`.`Wix4RestartResource`, `Wix4RestartResource`.`Component_`, `Wix4RestartResource`.`Resource`, `Wix4RestartResource`.`Attributes` " - L"FROM `Wix4RestartResource`"; -enum eRestartResourceQuery { rrqRestartResource = 1, rrqComponent, rrqResource, rrqAttributes }; - -/******************************************************************** -WixRegisterRestartResources - Immediate CA to register resources with RM. - -Enumerates components before InstallValidate and registers resources -to be restarted by Restart Manager if the component action -is anything other than None. - -Do not disable file system redirection. - -********************************************************************/ -extern "C" UINT __stdcall WixRegisterRestartResources( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - PMSIHANDLE hView = NULL; - PMSIHANDLE hRec = NULL; - - LPWSTR wzSessionKey = NULL; - size_t cchSessionKey = 0; - PRMU_SESSION pSession = NULL; - - LPWSTR wzRestartResource = NULL; - LPWSTR wzComponent = NULL; - LPWSTR wzResource = NULL; - int iAttributes = NULL; - BOOL fIsComponentNull = FALSE; - WCA_TODO todo = WCA_TODO_UNKNOWN; - int iType = etInvalid; - - hr = WcaInitialize(hInstall, "WixRegisterRestartResources"); - ExitOnFailure(hr, "Failed to initialize."); - - // Skip if the table doesn't exist. - if (S_OK != WcaTableExists(L"Wix4RestartResource")) - { - WcaLog(LOGMSG_STANDARD, "The Wix4RestartResource table does not exist; there are no resources to register with Restart Manager."); - ExitFunction(); - } - - // Get the existing Restart Manager session if available. - hr = WcaGetProperty(L"MsiRestartManagerSessionKey", &wzSessionKey); - ExitOnFailure(hr, "Failed to get the MsiRestartManagerSessionKey property."); - - hr = ::StringCchLengthW(wzSessionKey, CCH_SESSION_KEY, &cchSessionKey); - ExitOnFailure(hr, "Failed to get the MsiRestartManagerSessionKey string length."); - - // Skip if the property doesn't exist. - if (0 == cchSessionKey) - { - WcaLog(LOGMSG_STANDARD, "The MsiRestartManagerSessionKey property is not available to join."); - ExitFunction(); - } - - // Join the existing Restart Manager session if supported. - hr = RmuJoinSession(&pSession, wzSessionKey); - if (E_MODNOTFOUND == hr) - { - WcaLog(LOGMSG_STANDARD, "The Restart Manager is not supported on this platform. Skipping."); - ExitFunction1(hr = S_OK); - } - else if (FAILED(hr)) - { - WcaLog(LOGMSG_STANDARD, "Failed to join the existing Restart Manager session %ls.", wzSessionKey); - ExitFunction1(hr = S_OK); - } - - // Loop through each record in the table. - hr = WcaOpenExecuteView(vcsRestartResourceQuery, &hView); - ExitOnFailure(hr, "Failed to open a view on the RestartResource table."); - - while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) - { - hr = WcaGetRecordString(hRec, rrqRestartResource, &wzRestartResource); - ExitOnFailure(hr, "Failed to get the RestartResource field value."); - - hr = WcaGetRecordString(hRec, rrqComponent, &wzComponent); - ExitOnFailure(hr, "Failed to get the Component_ field value."); - - hr = WcaGetRecordFormattedString(hRec, rrqResource, &wzResource); - ExitOnFailure(hr, "Failed to get the Resource formatted field value."); - - hr = WcaGetRecordInteger(hRec, rrqAttributes, &iAttributes); - ExitOnFailure(hr, "Failed to get the Attributes field value."); - - fIsComponentNull = ::MsiRecordIsNull(hRec, rrqComponent); - todo = WcaGetComponentToDo(wzComponent); - - // Only register resources for components that are null, or being installed, reinstalled, or uninstalled. - if (!fIsComponentNull && WCA_TODO_UNKNOWN == todo) - { - WcaLog(LOGMSG_VERBOSE, "Skipping resource %ls.", wzRestartResource); - continue; - } - - // Get the type from Attributes and add to the Restart Manager. - iType = iAttributes & etTypeMask; - switch (iType) - { - case etFilename: - WcaLog(LOGMSG_VERBOSE, "Registering file name %ls with the Restart Manager.", wzResource); - hr = RmuAddFile(pSession, wzResource); - ExitOnFailure(hr, "Failed to register the file name with the Restart Manager session."); - break; - - case etApplication: - WcaLog(LOGMSG_VERBOSE, "Registering process name %ls with the Restart Manager.", wzResource); - hr = RmuAddProcessesByName(pSession, wzResource); - if (E_NOTFOUND == hr) - { - // ERROR_ACCESS_DENIED was returned when trying to register this process. - // Since other instances may have been registered, log a message and continue the setup rather than failing. - WcaLog(LOGMSG_STANDARD, "The process, %ls, could not be registered with the Restart Manager (probably because the setup is not elevated and the process is in another user context). A reboot may be requested later.", wzResource); - hr = S_OK; - } - else - { - ExitOnFailure(hr, "Failed to register the process name with the Restart Manager session."); - } - break; - - case etServiceName: - WcaLog(LOGMSG_VERBOSE, "Registering service name %ls with the Restart Manager.", wzResource); - hr = RmuAddService(pSession, wzResource); - ExitOnFailure(hr, "Failed to register the service name with the Restart Manager session."); - break; - - default: - WcaLog(LOGMSG_VERBOSE, "The resource type %d for %ls is not supported and will not be registered.", iType, wzRestartResource); - break; - } - } - - if (E_NOMOREITEMS == hr) - { - hr = S_OK; - } - ExitOnFailure(hr, "Failed while looping through all rows to register resources."); - - // Register the resources and unjoin the session. - hr = RmuEndSession(pSession); - if (FAILED(hr)) - { - WcaLog(LOGMSG_VERBOSE, "Failed to register the resources with the Restart Manager."); - ExitFunction1(hr = S_OK); - } - -LExit: - ReleaseStr(wzRestartResource); - ReleaseStr(wzComponent); - ReleaseStr(wzResource); - - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - - return WcaFinalize(er); -} diff --git a/src/ca/TouchFile.cpp b/src/ca/TouchFile.cpp deleted file mode 100644 index e704f922..00000000 --- a/src/ca/TouchFile.cpp +++ /dev/null @@ -1,308 +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 vcsTouchFileQuery = L"SELECT `Wix4TouchFile`, `Component_`, `Path`, `Attributes` FROM `Wix4TouchFile`"; -enum TOUCH_FILE_QUERY { tfqId = 1, tfqComponent, tfqPath, tfqTouchFileAttributes }; - -enum TOUCH_FILE_ATTRIBUTE -{ - TOUCH_FILE_ATTRIBUTE_ON_INSTALL = 0x01, - TOUCH_FILE_ATTRIBUTE_ON_REINSTALL = 0x02, - TOUCH_FILE_ATTRIBUTE_ON_UNINSTALL = 0x04, - TOUCH_FILE_ATTRIBUTE_64BIT = 0x10, - TOUCH_FILE_ATTRIBUTE_VITAL = 0x20 -}; - - -static BOOL SetExistingFileModifiedTime( - __in_z LPCWSTR wzId, - __in_z LPCWSTR wzPath, - __in BOOL f64Bit, - __in FILETIME* pftModified - ) -{ - HRESULT hr = S_OK; - BOOL fReenableFileSystemRedirection = FALSE; - - if (f64Bit) - { - hr = WcaDisableWow64FSRedirection(); - ExitOnFailure(hr, "Failed to disable 64-bit file system redirection to path: '%ls' for: %ls", wzPath, wzId); - - fReenableFileSystemRedirection = TRUE; - } - - hr = FileSetTime(wzPath, NULL, NULL, pftModified); - -LExit: - if (fReenableFileSystemRedirection) - { - WcaRevertWow64FSRedirection(); - } - - return SUCCEEDED(hr); -} - - -static HRESULT AddDataToCustomActionData( - __deref_inout_z LPWSTR* psczCustomActionData, - __in_z LPCWSTR wzId, - __in_z LPCWSTR wzPath, - __in int iTouchFileAttributes, - __in FILETIME ftModified - ) -{ - HRESULT hr = S_OK; - - hr = WcaWriteStringToCaData(wzId, psczCustomActionData); - ExitOnFailure(hr, "Failed to add touch file identity to custom action data."); - - hr = WcaWriteStringToCaData(wzPath, psczCustomActionData); - ExitOnFailure(hr, "Failed to add touch file path to custom action data."); - - hr = WcaWriteIntegerToCaData(iTouchFileAttributes, psczCustomActionData); - ExitOnFailure(hr, "Failed to add touch file attributes to custom action data."); - - hr = WcaWriteIntegerToCaData(ftModified.dwHighDateTime, psczCustomActionData); - ExitOnFailure(hr, "Failed to add touch file high date/time to custom action data."); - - hr = WcaWriteIntegerToCaData(ftModified.dwLowDateTime, psczCustomActionData); - ExitOnFailure(hr, "Failed to add touch file low date/time to custom action data."); - -LExit: - return hr; -} - - -static BOOL TryGetExistingFileModifiedTime( - __in_z LPCWSTR wzId, - __in_z LPCWSTR wzPath, - __in BOOL f64Bit, - __inout FILETIME* pftModified - ) -{ - HRESULT hr = S_OK; - BOOL fReenableFileSystemRedirection = FALSE; - - if (f64Bit) - { - hr = WcaDisableWow64FSRedirection(); - ExitOnFailure(hr, "Failed to disable 64-bit file system redirection to path: '%ls' for: %ls", wzPath, wzId); - - fReenableFileSystemRedirection = TRUE; - } - - hr = FileGetTime(wzPath, NULL, NULL, pftModified); - if (E_PATHNOTFOUND == hr || E_FILENOTFOUND == hr) - { - // If the file doesn't exist yet there is nothing to rollback (i.e. file will probably be removed during rollback), so - // keep the error code but don't log anything. - } - else if (FAILED(hr)) - { - WcaLog(LOGMSG_STANDARD, "Cannot access modified timestamp for file: '%ls' due to error: 0x%x. Continuing with out rollback for: %ls", wzPath, hr, wzId); - } - -LExit: - if (fReenableFileSystemRedirection) - { - WcaRevertWow64FSRedirection(); - } - - return SUCCEEDED(hr); -} - - -static HRESULT ProcessTouchFileTable( - __in BOOL fInstalling - ) -{ - HRESULT hr = S_OK; - - FILETIME ftModified = {}; - - PMSIHANDLE hView; - PMSIHANDLE hRec; - - LPWSTR sczId = NULL; - LPWSTR sczComponent = NULL; - int iTouchFileAttributes = 0; - LPWSTR sczPath = NULL; - - FILETIME ftRollbackModified = {}; - LPWSTR sczRollbackData = NULL; - LPWSTR sczExecuteData = NULL; - - if (S_OK != WcaTableExists(L"Wix4TouchFile")) - { - ExitFunction(); - } - - ::GetSystemTimeAsFileTime(&ftModified); - - hr = WcaOpenExecuteView(vcsTouchFileQuery, &hView); - ExitOnFailure(hr, "Failed to open view on Wix4TouchFile table"); - - while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) - { - hr = WcaGetRecordString(hRec, tfqId, &sczId); - ExitOnFailure(hr, "Failed to get touch file identity."); - - hr = WcaGetRecordString(hRec, tfqComponent, &sczComponent); - ExitOnFailure(hr, "Failed to get touch file component for: %ls", sczId); - - hr = WcaGetRecordInteger(hRec, tfqTouchFileAttributes, &iTouchFileAttributes); - ExitOnFailure(hr, "Failed to get touch file attributes for: %ls", sczId); - - WCA_TODO todo = WcaGetComponentToDo(sczComponent); - - BOOL fOnInstall = fInstalling && WCA_TODO_INSTALL == todo && (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_ON_INSTALL); - BOOL fOnReinstall = fInstalling && WCA_TODO_REINSTALL == todo && (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_ON_REINSTALL); - BOOL fOnUninstall = !fInstalling && WCA_TODO_UNINSTALL == todo && (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_ON_UNINSTALL); - - if (fOnInstall || fOnReinstall || fOnUninstall) - { - hr = WcaGetRecordFormattedString(hRec, tfqPath, &sczPath); - ExitOnFailure(hr, "Failed to get touch file path for: %ls", sczId); - - if (TryGetExistingFileModifiedTime(sczId, sczPath, (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_64BIT), &ftRollbackModified)) - { - hr = AddDataToCustomActionData(&sczRollbackData, sczId, sczPath, iTouchFileAttributes, ftRollbackModified); - ExitOnFailure(hr, "Failed to add to rollback custom action data for: %ls", sczId); - } - - hr = AddDataToCustomActionData(&sczExecuteData, sczId, sczPath, iTouchFileAttributes, ftModified); - ExitOnFailure(hr, "Failed to add to execute custom action data for: %ls", sczId); - } - } - - if (E_NOMOREITEMS == hr) - { - hr = S_OK; - } - ExitOnFailure(hr, "Failure occured while processing Wix4TouchFile table"); - - if (sczRollbackData) - { - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackTouchFile"), sczRollbackData, 0); - ExitOnFailure(hr, "Failed to schedule RollbackTouchFile"); - } - - if (sczExecuteData) - { - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecuteTouchFile"), sczExecuteData, 0); - ExitOnFailure(hr, "Failed to schedule ExecuteTouchFile"); - } - -LExit: - ReleaseStr(sczExecuteData); - ReleaseStr(sczRollbackData); - ReleaseStr(sczPath); - ReleaseStr(sczComponent); - ReleaseStr(sczId); - - return hr; -} - - -extern "C" UINT WINAPI WixTouchFileDuringInstall( - __in MSIHANDLE hInstall - ) -{ - //AssertSz(FALSE, "debug WixTouchFileDuringInstall"); - - HRESULT hr = S_OK; - - hr = WcaInitialize(hInstall, "WixTouchFileDuringInstall"); - ExitOnFailure(hr, "Failed to initialize WixTouchFileDuringInstall."); - - hr = ProcessTouchFileTable(TRUE); - -LExit: - DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - -extern "C" UINT WINAPI WixTouchFileDuringUninstall( - __in MSIHANDLE hInstall - ) -{ - //AssertSz(FALSE, "debug WixTouchFileDuringUninstall"); - - HRESULT hr = S_OK; - - hr = WcaInitialize(hInstall, "WixTouchFileDuringUninstall"); - ExitOnFailure(hr, "Failed to initialize WixTouchFileDuringUninstall."); - - hr = ProcessTouchFileTable(FALSE); - -LExit: - DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - -extern "C" UINT WINAPI WixExecuteTouchFile( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr = S_OK; - - LPWSTR sczData = NULL; - LPWSTR pwz = NULL; - - LPWSTR sczId = NULL; - LPWSTR sczPath = NULL; - int iTouchFileAttributes = 0; - FILETIME ftModified = {}; - - hr = WcaInitialize(hInstall, "WixExecuteTouchFile"); - ExitOnFailure(hr, "Failed to initialize WixExecuteTouchFile."); - - hr = WcaGetProperty(L"CustomActionData", &sczData); - ExitOnFailure(hr, "Failed to get custom action data for WixExecuteTouchFile."); - - pwz = sczData; - - while (pwz && *pwz) - { - hr = WcaReadStringFromCaData(&pwz, &sczId); - ExitOnFailure(hr, "Failed to get touch file identity from custom action data."); - - hr = WcaReadStringFromCaData(&pwz, &sczPath); - ExitOnFailure(hr, "Failed to get touch file path from custom action data for: %ls", sczId); - - hr = WcaReadIntegerFromCaData(&pwz, &iTouchFileAttributes); - ExitOnFailure(hr, "Failed to get touch file attributes from custom action data for: %ls", sczId); - - hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&ftModified.dwHighDateTime)); - ExitOnFailure(hr, "Failed to get touch file high date/time from custom action data for: %ls", sczId); - - hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&ftModified.dwLowDateTime)); - ExitOnFailure(hr, "Failed to get touch file low date/time from custom action data for: %ls", sczId); - - hr = SetExistingFileModifiedTime(sczId, sczPath, (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_64BIT), &ftModified); - if (FAILED(hr)) - { - if (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_VITAL) - { - ExitOnFailure(hr, "Failed to touch file: '%ls' for: %ls", &sczPath, sczId); - } - else - { - WcaLog(LOGMSG_STANDARD, "Could not touch non-vital file: '%ls' for: %ls with error: 0x%x. Continuing...", sczPath, sczId, hr); - hr = S_OK; - } - } - } - -LExit: - ReleaseStr(sczPath); - ReleaseStr(sczId); - ReleaseStr(sczData); - - DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} diff --git a/src/ca/XmlConfig.cpp b/src/ca/XmlConfig.cpp deleted file mode 100644 index a1ec9d6f..00000000 --- a/src/ca/XmlConfig.cpp +++ /dev/null @@ -1,1130 +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 XMLCONFIG_ELEMENT 0x00000001 -#define XMLCONFIG_VALUE 0x00000002 -#define XMLCONFIG_DOCUMENT 0x00000004 -#define XMLCONFIG_CREATE 0x00000010 -#define XMLCONFIG_DELETE 0x00000020 -#define XMLCONFIG_INSTALL 0x00000100 -#define XMLCONFIG_UNINSTALL 0x00000200 -#define XMLCONFIG_PRESERVE_MODIFIED 0x00001000 - -enum eXmlAction -{ - xaUnknown = 0, - xaOpenFile, - xaOpenFilex64, - xaWriteValue, - xaWriteDocument, - xaDeleteValue, - xaCreateElement, - xaDeleteElement, -}; - -enum eXmlPreserveDate -{ - xdDontPreserve = 0, - xdPreserve -}; - -LPCWSTR vcsXmlConfigQuery = - L"SELECT `Wix4XmlConfig`.`Wix4XmlConfig`, `Wix4XmlConfig`.`File`, `Wix4XmlConfig`.`ElementId`, `Wix4XmlConfig`.`ElementPath`, `Wix4XmlConfig`.`VerifyPath`, `Wix4XmlConfig`.`Name`, " - L"`Wix4XmlConfig`.`Value`, `Wix4XmlConfig`.`Flags`, `Wix4XmlConfig`.`Component_`, `Component`.`Attributes` " - L"FROM `Wix4XmlConfig`,`Component` WHERE `Wix4XmlConfig`.`Component_`=`Component`.`Component` ORDER BY `File`, `Sequence`"; -enum eXmlConfigQuery { xfqXmlConfig = 1, xfqFile, xfqElementId, xfqElementPath, xfqVerifyPath, xfqName, xfqValue, xfqXmlFlags, xfqComponent, xfqCompAttributes }; - -struct XML_CONFIG_CHANGE -{ - WCHAR wzId[MAX_DARWIN_KEY + 1]; - - WCHAR wzComponent[MAX_DARWIN_KEY + 1]; - INSTALLSTATE isInstalled; - INSTALLSTATE isAction; - - WCHAR wzFile[MAX_PATH]; - LPWSTR pwzElementId; - LPWSTR pwzElementPath; - LPWSTR pwzVerifyPath; - WCHAR wzName[MAX_DARWIN_COLUMN]; - LPWSTR pwzValue; - BOOL fInstalledFile; - - int iXmlFlags; - int iCompAttributes; - - XML_CONFIG_CHANGE* pxfcAdditionalChanges; - int cAdditionalChanges; - - XML_CONFIG_CHANGE* pxfcPrev; - XML_CONFIG_CHANGE* pxfcNext; -}; - -static HRESULT FreeXmlConfigChangeList( - __in_opt XML_CONFIG_CHANGE* pxfcList - ) -{ - HRESULT hr = S_OK; - - XML_CONFIG_CHANGE* pxfcDelete; - while(pxfcList) - { - pxfcDelete = pxfcList; - pxfcList = pxfcList->pxfcNext; - - if (pxfcDelete->pwzElementId) - { - hr = MemFree(pxfcDelete->pwzElementId); - ExitOnFailure(hr, "failed to free xml config element id in change list item"); - } - - if (pxfcDelete->pwzElementPath) - { - hr = MemFree(pxfcDelete->pwzElementPath); - ExitOnFailure(hr, "failed to free xml config element path in change list item"); - } - - if (pxfcDelete->pwzVerifyPath) - { - hr = MemFree(pxfcDelete->pwzVerifyPath); - ExitOnFailure(hr, "failed to free xml config verify path in change list item"); - } - - if (pxfcDelete->pwzValue) - { - hr = MemFree(pxfcDelete->pwzValue); - ExitOnFailure(hr, "failed to free xml config value in change list item"); - } - - hr = MemFree(pxfcDelete); - ExitOnFailure(hr, "failed to free xml config change list item"); - } - -LExit: - return hr; -} - -static HRESULT AddXmlConfigChangeToList( - __inout XML_CONFIG_CHANGE** ppxfcHead, - __inout XML_CONFIG_CHANGE** ppxfcTail - ) -{ - Assert(ppxfcHead && ppxfcTail); - - HRESULT hr = S_OK; - - XML_CONFIG_CHANGE* pxfc = static_cast(MemAlloc(sizeof(XML_CONFIG_CHANGE), TRUE)); - ExitOnNull(pxfc, hr, E_OUTOFMEMORY, "failed to allocate memory for new xml file change list element"); - - // Add it to the end of the list - if (NULL == *ppxfcHead) - { - *ppxfcHead = pxfc; - *ppxfcTail = pxfc; - } - else - { - Assert(*ppxfcTail && (*ppxfcTail)->pxfcNext == NULL); - (*ppxfcTail)->pxfcNext = pxfc; - pxfc->pxfcPrev = *ppxfcTail; - *ppxfcTail = pxfc; - } - -LExit: - return hr; -} - - -static HRESULT ReadXmlConfigTable( - __inout XML_CONFIG_CHANGE** ppxfcHead, - __inout XML_CONFIG_CHANGE** ppxfcTail - ) -{ - Assert(ppxfcHead && ppxfcTail); - - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - PMSIHANDLE hView = NULL; - PMSIHANDLE hRec = NULL; - - LPWSTR pwzData = NULL; - - // loop through all the xml configurations - hr = WcaOpenExecuteView(vcsXmlConfigQuery, &hView); - ExitOnFailure(hr, "failed to open view on Wix4XmlConfig table"); - - while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) - { - hr = AddXmlConfigChangeToList(ppxfcHead, ppxfcTail); - ExitOnFailure(hr, "failed to add xml file change to list"); - - // Get record Id - hr = WcaGetRecordString(hRec, xfqXmlConfig, &pwzData); - ExitOnFailure(hr, "failed to get Wix4XmlConfig record Id"); - hr = StringCchCopyW((*ppxfcTail)->wzId, countof((*ppxfcTail)->wzId), pwzData); - ExitOnFailure(hr, "failed to copy Wix4XmlConfig record Id"); - - // Get component name - hr = WcaGetRecordString(hRec, xfqComponent, &pwzData); - ExitOnFailure(hr, "failed to get component name for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); - - // Get the component's state - if (pwzData && *pwzData) - { - hr = StringCchCopyW((*ppxfcTail)->wzComponent, countof((*ppxfcTail)->wzComponent), pwzData); - ExitOnFailure(hr, "failed to copy component id"); - - er = ::MsiGetComponentStateW(WcaGetInstallHandle(), (*ppxfcTail)->wzComponent, &(*ppxfcTail)->isInstalled, &(*ppxfcTail)->isAction); - ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "failed to get install state for component id"); - } - - // Get the xml file - hr = WcaGetRecordFormattedString(hRec, xfqFile, &pwzData); - ExitOnFailure(hr, "failed to get xml file for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); - hr = StringCchCopyW((*ppxfcTail)->wzFile, countof((*ppxfcTail)->wzFile), pwzData); - ExitOnFailure(hr, "failed to copy xml file path"); - - // Figure out if the file is already on the machine or if it's being installed - hr = WcaGetRecordString(hRec, xfqFile, &pwzData); - ExitOnFailure(hr, "failed to get xml file for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); - if (NULL != wcsstr(pwzData, L"[!") || NULL != wcsstr(pwzData, L"[#")) - { - (*ppxfcTail)->fInstalledFile = TRUE; - } - - // Get the Wix4XmlConfig table flags - hr = WcaGetRecordInteger(hRec, xfqXmlFlags, &(*ppxfcTail)->iXmlFlags); - ExitOnFailure(hr, "failed to get Wix4XmlConfig flags for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); - - // Get the Element Id - hr = WcaGetRecordFormattedString(hRec, xfqElementId, &(*ppxfcTail)->pwzElementId); - ExitOnFailure(hr, "failed to get Element Id for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); - - // Get the Element Path - hr = WcaGetRecordFormattedString(hRec, xfqElementPath, &(*ppxfcTail)->pwzElementPath); - ExitOnFailure(hr, "failed to get Element Path for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); - - // Get the Verify Path - hr = WcaGetRecordFormattedString(hRec, xfqVerifyPath, &(*ppxfcTail)->pwzVerifyPath); - ExitOnFailure(hr, "failed to get Verify Path for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); - - // Get the name - hr = WcaGetRecordFormattedString(hRec, xfqName, &pwzData); - ExitOnFailure(hr, "failed to get Name for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); - hr = StringCchCopyW((*ppxfcTail)->wzName, countof((*ppxfcTail)->wzName), pwzData); - ExitOnFailure(hr, "failed to copy name of element"); - - // Get the value - hr = WcaGetRecordFormattedString(hRec, xfqValue, &pwzData); - ExitOnFailure(hr, "failed to get Value for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); - hr = StrAllocString(&(*ppxfcTail)->pwzValue, pwzData, 0); - ExitOnFailure(hr, "failed to allocate buffer for value"); - - // Get the component attributes - hr = WcaGetRecordInteger(hRec, xfqCompAttributes, &(*ppxfcTail)->iCompAttributes); - ExitOnFailure(hr, "failed to get component attributes for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); - } - - // if we looped through all records all is well - if (E_NOMOREITEMS == hr) - { - hr = S_OK; - } - ExitOnFailure(hr, "failed while looping through all objects to secure"); - -LExit: - ReleaseStr(pwzData); - - return hr; -} - -static HRESULT ProcessChanges( - __inout XML_CONFIG_CHANGE** ppxfcHead - ) -{ - Assert(ppxfcHead && *ppxfcHead); - HRESULT hr = S_OK; - - XML_CONFIG_CHANGE* pxfc = NULL; - XML_CONFIG_CHANGE* pxfcNext = NULL; - XML_CONFIG_CHANGE* pxfcCheck = NULL; - int cAdditionalChanges = 0; - XML_CONFIG_CHANGE* pxfcLast = NULL; - - // If there's only one item in the list, none of this matters - if (pxfc && !pxfc->pxfcNext) - { - ExitFunction(); - } - - // Loop through the list - pxfc = *ppxfcHead; - while (pxfc) - { - // Keep track of where our next spot will be since our current node may be moved - pxfcNext = pxfc->pxfcNext; - - // With each node, check to see if it's element path matches the Id of some other node in the list - pxfcCheck = *ppxfcHead; - while (pxfcCheck) - { - if (pxfc->pwzElementId) - { - if (0 == lstrcmpW(pxfc->pwzElementId, pxfcCheck->wzId) - && 0 == pxfc->iXmlFlags - && XMLCONFIG_CREATE & pxfcCheck->iXmlFlags - && XMLCONFIG_ELEMENT & pxfcCheck->iXmlFlags) - { - // We found a match. First, take it out of the current list - if (pxfc->pxfcPrev) - { - pxfc->pxfcPrev->pxfcNext = pxfc->pxfcNext; - } - else // it was the head. Update the head - { - *ppxfcHead = pxfc->pxfcNext; - } - - if (pxfc->pxfcNext) - { - pxfc->pxfcNext->pxfcPrev = pxfc->pxfcPrev; - } - - pxfc->pxfcNext = NULL; - pxfc->pxfcPrev = NULL; - - // Now, add this node to the end of the matched node's additional changes list - if (!pxfcCheck->pxfcAdditionalChanges) - { - pxfcCheck->pxfcAdditionalChanges = pxfc; - pxfcCheck->cAdditionalChanges = 1; - } - else - { - pxfcLast = pxfcCheck->pxfcAdditionalChanges; - cAdditionalChanges = 1; - while (pxfcLast->pxfcNext) - { - pxfcLast = pxfcLast->pxfcNext; - ++cAdditionalChanges; - } - pxfcLast->pxfcNext = pxfc; - pxfc->pxfcPrev = pxfcLast; - pxfcCheck->cAdditionalChanges = ++cAdditionalChanges; - } - } - else - { - hr = E_NOTFOUND; - ExitOnRootFailure(hr, "failed to find matching ElementId: %ls", pxfc->pwzElementId); - } - } - - pxfcCheck = pxfcCheck->pxfcNext; - } - - pxfc = pxfcNext; - } - -LExit: - - return hr; -} - - -static HRESULT BeginChangeFile( - __in LPCWSTR pwzFile, - __in int iCompAttributes, - __inout LPWSTR* ppwzCustomActionData - ) -{ - Assert(pwzFile && *pwzFile && ppwzCustomActionData); - - HRESULT hr = S_OK; - BOOL fIs64Bit = iCompAttributes & msidbComponentAttributes64bit; - - LPBYTE pbData = NULL; - SIZE_T cbData = 0; - - LPWSTR pwzRollbackCustomActionData = NULL; - - if (fIs64Bit) - { - hr = WcaWriteIntegerToCaData((int)xaOpenFilex64, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write 64-bit file indicator to custom action data"); - } - else - { - hr = WcaWriteIntegerToCaData((int)xaOpenFile, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write file indicator to custom action data"); - } - - hr = WcaWriteStringToCaData(pwzFile, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write file to custom action data: %ls", pwzFile); - - // If the file already exits, then we have to put it back the way it was on failure - if (FileExistsEx(pwzFile, NULL)) - { - hr = FileRead(&pbData, &cbData, pwzFile); - ExitOnFailure(hr, "failed to read file: %ls", pwzFile); - - // Set up the rollback for this file - hr = WcaWriteIntegerToCaData((int)fIs64Bit, &pwzRollbackCustomActionData); - ExitOnFailure(hr, "failed to write component bitness to rollback custom action data"); - - hr = WcaWriteStringToCaData(pwzFile, &pwzRollbackCustomActionData); - ExitOnFailure(hr, "failed to write file name to rollback custom action data: %ls", pwzFile); - - hr = WcaWriteStreamToCaData(pbData, cbData, &pwzRollbackCustomActionData); - ExitOnFailure(hr, "failed to write file contents to rollback custom action data."); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecXmlConfigRollback"), pwzRollbackCustomActionData, COST_XMLFILE); - ExitOnFailure(hr, "failed to schedule ExecXmlConfigRollback for file: %ls", pwzFile); - - ReleaseStr(pwzRollbackCustomActionData); - } -LExit: - ReleaseMem(pbData); - - return hr; -} - - -static HRESULT WriteChangeData( - __in XML_CONFIG_CHANGE* pxfc, - __in eXmlAction action, - __inout LPWSTR* ppwzCustomActionData - ) -{ - Assert(pxfc && ppwzCustomActionData); - - HRESULT hr = S_OK; - XML_CONFIG_CHANGE* pxfcAdditionalChanges = NULL; - LPCWSTR wzElementPath = pxfc->pwzElementId ? pxfc->pwzElementId : pxfc->pwzElementPath; - - hr = WcaWriteStringToCaData(wzElementPath, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write ElementPath to custom action data: %ls", wzElementPath); - - hr = WcaWriteStringToCaData(pxfc->pwzVerifyPath, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write VerifyPath to custom action data: %ls", pxfc->pwzVerifyPath); - - hr = WcaWriteStringToCaData(pxfc->wzName, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write Name to custom action data: %ls", pxfc->wzName); - - hr = WcaWriteStringToCaData(pxfc->pwzValue, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write Value to custom action data: %ls", pxfc->pwzValue); - - if (pxfc->iXmlFlags & XMLCONFIG_CREATE && pxfc->iXmlFlags & XMLCONFIG_ELEMENT && xaCreateElement == action && pxfc->pxfcAdditionalChanges) - { - hr = WcaWriteIntegerToCaData(pxfc->cAdditionalChanges, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write additional changes value to custom action data"); - - pxfcAdditionalChanges = pxfc->pxfcAdditionalChanges; - while (pxfcAdditionalChanges) - { - Assert((0 == lstrcmpW(pxfcAdditionalChanges->wzComponent, pxfc->wzComponent)) && 0 == pxfcAdditionalChanges->iXmlFlags && (0 == lstrcmpW(pxfcAdditionalChanges->wzFile, pxfc->wzFile))); - - hr = WcaWriteStringToCaData(pxfcAdditionalChanges->wzName, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write Name to custom action data: %ls", pxfc->wzName); - - hr = WcaWriteStringToCaData(pxfcAdditionalChanges->pwzValue, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write Value to custom action data: %ls", pxfc->pwzValue); - - pxfcAdditionalChanges = pxfcAdditionalChanges->pxfcNext; - } - } - else - { - hr = WcaWriteIntegerToCaData(0, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write additional changes value to custom action data"); - } - -LExit: - return hr; -} - - -/****************************************************************** - SchedXmlConfig - entry point for XmlConfig Custom Action - -********************************************************************/ -extern "C" UINT __stdcall SchedXmlConfig( - __in MSIHANDLE hInstall - ) -{ -// AssertSz(FALSE, "debug SchedXmlConfig"); - - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - LPWSTR pwzCurrentFile = NULL; - BOOL fCurrentFileChanged = FALSE; - - PMSIHANDLE hView = NULL; - PMSIHANDLE hRec = NULL; - - XML_CONFIG_CHANGE* pxfcHead = NULL; - XML_CONFIG_CHANGE* pxfcTail = NULL; // TODO: do we need this any more? - XML_CONFIG_CHANGE* pxfc = NULL; - - eXmlAction xa = xaUnknown; - eXmlPreserveDate xd; - - LPWSTR pwzCustomActionData = NULL; - - DWORD cFiles = 0; - - // initialize - hr = WcaInitialize(hInstall, "SchedXmlConfig"); - ExitOnFailure(hr, "failed to initialize"); - - hr = ReadXmlConfigTable(&pxfcHead, &pxfcTail); - MessageExitOnFailure(hr, msierrXmlConfigFailedRead, "failed to read Wix4XmlConfig table"); - - hr = ProcessChanges(&pxfcHead); - ExitOnFailure(hr, "failed to process Wix4XmlConfig changes"); - - // loop through all the xml configurations - for (pxfc = pxfcHead; pxfc; pxfc = pxfc->pxfcNext) - { - // If this is a different file, or the first file... - if (NULL == pwzCurrentFile || 0 != lstrcmpW(pwzCurrentFile, pxfc->wzFile)) - { - // Remember the file we're currently working on - hr = StrAllocString(&pwzCurrentFile, pxfc->wzFile, 0); - ExitOnFailure(hr, "failed to copy file name"); - - fCurrentFileChanged = TRUE; - } - - // - // Figure out what action to take - // - xa = xaUnknown; - - // If it's being installed or reinstalled or uninstalled and that matches - // what we are doing then calculate the right action. - if ((XMLCONFIG_INSTALL & pxfc->iXmlFlags && (WcaIsInstalling(pxfc->isInstalled, pxfc->isAction) || WcaIsReInstalling(pxfc->isInstalled, pxfc->isAction))) || - (XMLCONFIG_UNINSTALL & pxfc->iXmlFlags && WcaIsUninstalling(pxfc->isInstalled, pxfc->isAction))) - { - if (XMLCONFIG_CREATE & pxfc->iXmlFlags && XMLCONFIG_ELEMENT & pxfc->iXmlFlags) - { - xa = xaCreateElement; - } - else if (XMLCONFIG_DELETE & pxfc->iXmlFlags && XMLCONFIG_ELEMENT & pxfc->iXmlFlags) - { - xa = xaDeleteElement; - } - else if (XMLCONFIG_DELETE & pxfc->iXmlFlags && XMLCONFIG_VALUE & pxfc->iXmlFlags) - { - xa = xaDeleteValue; - } - else if (XMLCONFIG_CREATE & pxfc->iXmlFlags && XMLCONFIG_VALUE & pxfc->iXmlFlags) - { - xa = xaWriteValue; - } - else if (XMLCONFIG_CREATE & pxfc->iXmlFlags && XMLCONFIG_DOCUMENT & pxfc->iXmlFlags) - { - xa = xaWriteDocument; - } - else if (XMLCONFIG_DELETE & pxfc->iXmlFlags && XMLCONFIG_DOCUMENT & pxfc->iXmlFlags) - { - hr = E_INVALIDARG; - ExitOnFailure(hr, "Invalid flag configuration. Cannot delete a fragment node."); - } - } - - if (XMLCONFIG_PRESERVE_MODIFIED & pxfc->iXmlFlags) - { - xd = xdPreserve; - } - else - { - xd= xdDontPreserve; - } - - if (xaUnknown != xa) - { - if (fCurrentFileChanged) - { - hr = BeginChangeFile(pwzCurrentFile, pxfc->iCompAttributes, &pwzCustomActionData); - ExitOnFailure(hr, "failed to begin file change for file: %ls", pwzCurrentFile); - - fCurrentFileChanged = FALSE; - ++cFiles; - } - - hr = WcaWriteIntegerToCaData((int)xa, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write action indicator custom action data"); - - hr = WcaWriteIntegerToCaData((int)xd, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write Preserve Date indicator to custom action data"); - - hr = WriteChangeData(pxfc, xa, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write change data"); - } - } - - // If we looped through all records all is well - if (E_NOMOREITEMS == hr) - { - hr = S_OK; - } - ExitOnFailure(hr, "failed while looping through all objects to secure"); - - // Schedule the custom action and add to progress bar - if (pwzCustomActionData && *pwzCustomActionData) - { - Assert(0 < cFiles); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecXmlConfig"), pwzCustomActionData, cFiles * COST_XMLFILE); - ExitOnFailure(hr, "failed to schedule ExecXmlConfig action"); - } - -LExit: - ReleaseStr(pwzCurrentFile); - ReleaseStr(pwzCustomActionData); - - FreeXmlConfigChangeList(pxfcHead); - - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - return WcaFinalize(er); -} - - -/****************************************************************** - ExecXmlConfig - entry point for XmlConfig Custom Action - -*******************************************************************/ -extern "C" UINT __stdcall ExecXmlConfig( - __in MSIHANDLE hInstall - ) -{ - //AssertSz(FALSE, "debug ExecXmlConfig"); - HRESULT hr = S_OK; - HRESULT hrOpenFailure = S_OK; - UINT er = ERROR_SUCCESS; - -#ifndef _WIN64 - BOOL fIsFSRedirectDisabled = FALSE; -#endif - BOOL fPreserveDate = FALSE; - - LPWSTR pwzCustomActionData = NULL; - LPWSTR pwzData = NULL; - LPWSTR pwzFile = NULL; - LPWSTR pwzElementPath = NULL; - LPWSTR pwzVerifyPath = NULL; - LPWSTR pwzName = NULL; - LPWSTR pwzValue = NULL; - LPWSTR pwz = NULL; - int cAdditionalChanges = 0; - - IXMLDOMDocument* pixd = NULL; - IXMLDOMNode* pixn = NULL; - IXMLDOMNode* pixnVerify = NULL; - IXMLDOMNode* pixnNewNode = NULL; - IXMLDOMNode* pixnRemovedChild = NULL; - - IXMLDOMDocument* pixdNew = NULL; - IXMLDOMElement* pixeNew = NULL; - - FILETIME ft; - - int id = IDRETRY; - - eXmlAction xa; - eXmlPreserveDate xd; - - // initialize - hr = WcaInitialize(hInstall, "ExecXmlConfig"); - ExitOnFailure(hr, "failed to initialize"); - - hr = XmlInitialize(); - ExitOnFailure(hr, "failed to initialize xml utilities"); - - hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData); - ExitOnFailure(hr, "failed to get CustomActionData"); - - WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); - - pwz = pwzCustomActionData; - - hr = WcaReadIntegerFromCaData(&pwz, (int*) &xa); - ExitOnFailure(hr, "failed to process CustomActionData"); - -#ifndef _WIN64 - // Initialize the Wow64 API - store the result in fWow64APIPresent - // If it fails, this doesn't warrant an error yet, because we only need the Wow64 API in some cases - WcaInitializeWow64(); - BOOL fIsWow64Process = WcaIsWow64Process(); -#endif - - if (xaOpenFile != xa && xaOpenFilex64 != xa) - { - ExitOnFailure(hr = E_INVALIDARG, "invalid custom action data"); - } - - // loop through all the passed in data - while (pwz && *pwz) - { - hr = WcaReadStringFromCaData(&pwz, &pwzFile); - ExitOnFailure(hr, "failed to read file name from custom action data"); - - // Default to not preserve date, preserve it if any modifications require us to - fPreserveDate = FALSE; - - // Open the file - ReleaseNullObject(pixd); - -#ifndef _WIN64 - if (xaOpenFilex64 == xa) - { - if (!fIsWow64Process) - { - hr = E_NOTIMPL; - ExitOnFailure(hr, "Custom action was told to act on a 64-bit component, but the custom action process is not running in WOW."); - } - - hr = WcaDisableWow64FSRedirection(); - ExitOnFailure(hr, "Custom action was told to act on a 64-bit component, but was unable to disable filesystem redirection through the Wow64 API."); - - fIsFSRedirectDisabled = TRUE; - } -#endif - - hr = XmlLoadDocumentFromFileEx(pwzFile, XML_LOAD_PRESERVE_WHITESPACE, &pixd); - if (FAILED(hr)) - { - // Ignore the return code for now. If they try to add something, we'll fail the install. If all they do is remove stuff then it doesn't matter. - hrOpenFailure = hr; - hr = S_OK; - } - else - { - hrOpenFailure = S_OK; - } - - WcaLog(LOGMSG_VERBOSE, "Configuring Xml File: %ls", pwzFile); - - while (pwz && *pwz) - { - // If we skip past an element that has additional changes we need to strip them off the stream before - // moving on to the next element. Do that now and then restart the outer loop. - if (cAdditionalChanges > 0) - { - while (cAdditionalChanges > 0) - { - hr = WcaReadStringFromCaData(&pwz, &pwzName); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzValue); - ExitOnFailure(hr, "failed to process CustomActionData"); - - cAdditionalChanges--; - } - continue; - } - - hr = WcaReadIntegerFromCaData(&pwz, (int*) &xa); - ExitOnFailure(hr, "failed to process CustomActionData"); - - // Break if we need to move on to a different file - if (xaOpenFile == xa || xaOpenFilex64 == xa) - { - break; - } - - hr = WcaReadIntegerFromCaData(&pwz, (int*) &xd); - ExitOnFailure(hr, "failed to process CustomActionData"); - - if (xdPreserve == xd) - { - fPreserveDate = TRUE; - } - - // Get path, name, and value to be written - hr = WcaReadStringFromCaData(&pwz, &pwzElementPath); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzVerifyPath); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzName); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzValue); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadIntegerFromCaData(&pwz, &cAdditionalChanges); - ExitOnFailure(hr, "failed to process CustomActionData"); - - // If we failed to open the file and we're adding something to the file, we've got a problem. Otherwise, just continue on since the file's already gone. - if (FAILED(hrOpenFailure)) - { - if (xaCreateElement == xa || xaWriteValue == xa || xaWriteDocument == xa) - { - MessageExitOnFailure(hr = hrOpenFailure, msierrXmlConfigFailedOpen, "failed to load XML file: %ls", pwzFile); - } - else - { - continue; - } - } - - // Select the node we're about to modify - ReleaseNullObject(pixn); - - hr = XmlSelectSingleNode(pixd, pwzElementPath, &pixn); - - // If we failed to find the node that we are going to add to, we've got a problem. Otherwise, just continue since the node's already gone. - if (S_FALSE == hr) - { - if (xaCreateElement == xa || xaWriteValue == xa || xaWriteDocument == xa) - { - hr = HRESULT_FROM_WIN32(ERROR_OBJECT_NOT_FOUND); - } - else - { - hr = S_OK; - continue; - } - } - - MessageExitOnFailure(hr, msierrXmlConfigFailedSelect, "failed to find node: %ls in XML file: %ls", pwzElementPath, pwzFile); - - // Make the modification - switch (xa) - { - case xaWriteValue: - if (pwzName && *pwzName) - { - // We're setting an attribute - hr = XmlSetAttribute(pixn, pwzName, pwzValue); - ExitOnFailure(hr, "failed to set attribute: %ls to value %ls", pwzName, pwzValue); - } - else - { - // We're setting the text of the node - hr = XmlSetText(pixn, pwzValue); - ExitOnFailure(hr, "failed to set text to: %ls for element %ls. Make sure that XPath points to an element.", pwzValue, pwzElementPath); - } - break; - case xaWriteDocument: - if (NULL != pwzVerifyPath && 0 != pwzVerifyPath[0]) - { - hr = XmlSelectSingleNode(pixn, pwzVerifyPath, &pixnVerify); - if (S_OK == hr) - { - // We found the verify path which means we have no further work to do - continue; - } - ExitOnFailure(hr, "failed to query verify path: %ls", pwzVerifyPath); - } - - hr = XmlLoadDocumentEx(pwzValue, XML_LOAD_PRESERVE_WHITESPACE, &pixdNew); - ExitOnFailure(hr, "Failed to load value as document."); - - hr = pixdNew->get_documentElement(&pixeNew); - ExitOnFailure(hr, "Failed to get document element."); - - hr = pixn->appendChild(pixeNew, NULL); - ExitOnFailure(hr, "Failed to append document element on to parent element."); - - ReleaseNullObject(pixeNew); - ReleaseNullObject(pixdNew); - break; - - case xaCreateElement: - if (NULL != pwzVerifyPath && 0 != pwzVerifyPath[0]) - { - hr = XmlSelectSingleNode(pixn, pwzVerifyPath, &pixnVerify); - if (S_OK == hr) - { - // We found the verify path which means we have no further work to do - continue; - } - ExitOnFailure(hr, "failed to query verify path: %ls", pwzVerifyPath); - } - - hr = XmlCreateChild(pixn, pwzName, &pixnNewNode); - ExitOnFailure(hr, "failed to create child element: %ls", pwzName); - - if (pwzValue && *pwzValue) - { - hr = XmlSetText(pixnNewNode, pwzValue); - ExitOnFailure(hr, "failed to set text to: %ls for node: %ls", pwzValue, pwzName); - } - - while (cAdditionalChanges > 0) - { - hr = WcaReadStringFromCaData(&pwz, &pwzName); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzValue); - ExitOnFailure(hr, "failed to process CustomActionData"); - - // Set the additional attribute - hr = XmlSetAttribute(pixnNewNode, pwzName, pwzValue); - ExitOnFailure(hr, "failed to set attribute: %ls to value %ls", pwzName, pwzValue); - - cAdditionalChanges--; - } - - ReleaseNullObject(pixnNewNode); - break; - case xaDeleteValue: - if (pwzName && *pwzName) - { - // Delete the attribute - hr = XmlRemoveAttribute(pixn, pwzName); - ExitOnFailure(hr, "failed to remove attribute: %ls", pwzName); - } - else - { - // Clear the text value for the node - hr = XmlSetText(pixn, L""); - ExitOnFailure(hr, "failed to clear text value"); - } - break; - case xaDeleteElement: - if (NULL != pwzVerifyPath && 0 != pwzVerifyPath[0]) - { - hr = XmlSelectSingleNode(pixn, pwzVerifyPath, &pixnVerify); - if (S_OK == hr) - { - hr = pixn->removeChild(pixnVerify, &pixnRemovedChild); - ExitOnFailure(hr, "failed to remove created child element"); - - ReleaseNullObject(pixnRemovedChild); - } - else - { - WcaLog(LOGMSG_VERBOSE, "Failed to select path %ls for deleting. Skipping...", pwzVerifyPath); - hr = S_OK; - } - } - else - { - // TODO: This requires a VerifyPath to delete an element. Should we support not having one? - WcaLog(LOGMSG_VERBOSE, "No VerifyPath specified for delete element of ID: %ls", pwzElementPath); - } - break; - default: - ExitOnFailure(hr = E_UNEXPECTED, "Invalid modification specified in custom action data"); - break; - } - } - - - // Now that we've made all of the changes to this file, save it and move on to the next - if (S_OK == hrOpenFailure) - { - if (fPreserveDate) - { - hr = FileGetTime(pwzFile, NULL, NULL, &ft); - ExitOnFailure(hr, "failed to get modified time of file : %ls", pwzFile); - } - - int iSaveAttempt = 0; - - do - { - hr = XmlSaveDocument(pixd, pwzFile); - if (FAILED(hr)) - { - id = WcaErrorMessage(msierrXmlConfigFailedSave, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 1, pwzFile); - switch (id) - { - case IDABORT: - ExitOnFailure(hr, "Failed to save changes to XML file: %ls", pwzFile); - case IDRETRY: - hr = S_FALSE; // hit me, baby, one more time - break; - case IDIGNORE: - hr = S_OK; // pretend everything is okay and bail - break; - case 0: // No UI case, MsiProcessMessage returns 0 - if (STIERR_SHARING_VIOLATION == hr) - { - // Only in case of sharing violation do we retry 30 times, once a second. - if (iSaveAttempt < 30) - { - hr = S_FALSE; - ++iSaveAttempt; - WcaLog(LOGMSG_VERBOSE, "Unable to save changes to XML file: %ls, retry attempt: %x", pwzFile, iSaveAttempt); - Sleep(1000); - } - else - { - ExitOnFailure(hr, "Failed to save changes to XML file: %ls", pwzFile); - } - } - break; - default: // Unknown error - ExitOnFailure(hr, "Failed to save changes to XML file: %ls", pwzFile); - } - } - } while (S_FALSE == hr); - - if (fPreserveDate) - { - hr = FileSetTime(pwzFile, NULL, NULL, &ft); - ExitOnFailure(hr, "failed to set modified time of file : %ls", pwzFile); - } - -#ifndef _WIN64 - if (fIsFSRedirectDisabled) - { - fIsFSRedirectDisabled = FALSE; - WcaRevertWow64FSRedirection(); - } -#endif - } - } - -LExit: -#ifndef _WIN64 - // Make sure we revert FS Redirection if necessary before exiting - if (fIsFSRedirectDisabled) - { - fIsFSRedirectDisabled = FALSE; - WcaRevertWow64FSRedirection(); - } - WcaFinalizeWow64(); -#endif - - ReleaseStr(pwzCustomActionData); - ReleaseStr(pwzData); - ReleaseStr(pwzFile); - ReleaseStr(pwzElementPath); - ReleaseStr(pwzVerifyPath); - ReleaseStr(pwzName); - ReleaseStr(pwzValue); - - ReleaseObject(pixeNew); - ReleaseObject(pixdNew); - - ReleaseObject(pixn); - ReleaseObject(pixd); - ReleaseObject(pixnNewNode); - ReleaseObject(pixnRemovedChild); - - XmlUninitialize(); - - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - return WcaFinalize(er); -} - - -/****************************************************************** - ExecXmlConfigRollback - entry point for XmlConfig rollback Custom Action - -*******************************************************************/ -extern "C" UINT __stdcall ExecXmlConfigRollback( - __in MSIHANDLE hInstall - ) -{ -// AssertSz(FALSE, "debug ExecXmlConfigRollback"); - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - int iIs64Bit; -#ifndef _WIN64 - BOOL fIs64Bit = FALSE; -#endif - - LPWSTR pwzCustomActionData = NULL; - LPWSTR pwz = NULL; - LPWSTR pwzFileName = NULL; - LPBYTE pbData = NULL; - DWORD_PTR cbData = 0; - - FILETIME ft; - - HANDLE hFile = INVALID_HANDLE_VALUE; - - // initialize - hr = WcaInitialize(hInstall, "ExecXmlConfigRollback"); - ExitOnFailure(hr, "failed to initialize"); - - - hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData); - ExitOnFailure(hr, "failed to get CustomActionData"); - - WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); - - pwz = pwzCustomActionData; - - hr = WcaReadIntegerFromCaData(&pwz, &iIs64Bit); - ExitOnFailure(hr, "failed to read component bitness from custom action data"); - - hr = WcaReadStringFromCaData(&pwz, &pwzFileName); - ExitOnFailure(hr, "failed to read file name from custom action data"); - - hr = WcaReadStreamFromCaData(&pwz, &pbData, &cbData); - ExitOnFailure(hr, "failed to read file contents from custom action data"); - -#ifndef _WIN64 - fIs64Bit = (BOOL)iIs64Bit; - - if (fIs64Bit) - { - hr = WcaInitializeWow64(); - if (S_FALSE == hr) - { - hr = TYPE_E_DLLFUNCTIONNOTFOUND; - } - ExitOnFailure(hr, "failed to initialize Wow64 API"); - - if (!WcaIsWow64Process()) - { - hr = E_NOTIMPL; - ExitOnFailure(hr, "Custom action was told to rollback a 64-bit component, but the Wow64 API is unavailable."); - } - - hr = WcaDisableWow64FSRedirection(); - ExitOnFailure(hr, "Custom action was told to rollback a 64-bit component, but was unable to Disable Filesystem Redirection through the Wow64 API."); - } -#endif - - hr = FileGetTime(pwzFileName, NULL, NULL, &ft); - ExitOnFailure(hr, "Failed to get modified date of file %ls.", pwzFileName); - - // Open the file - hFile = ::CreateFileW(pwzFileName, GENERIC_WRITE, NULL, NULL, TRUNCATE_EXISTING, NULL, NULL); - ExitOnInvalidHandleWithLastError(hFile, hr, "failed to open file: %ls", pwzFileName); - - // Write out the old data - hr = FileWriteHandle(hFile, pbData, cbData); - ExitOnFailure(hr, "failed to write to file: %ls", pwzFileName); - - ReleaseFile(hFile); - - hr = FileSetTime(pwzFileName, NULL, NULL, &ft); - ExitOnFailure(hr, "Failed to set modified date of file %ls.", pwzFileName); - -LExit: - ReleaseStr(pwzCustomActionData); - ReleaseStr(pwzFileName); - - ReleaseFile(hFile); - -#ifndef _WIN64 - if (fIs64Bit) - { - WcaRevertWow64FSRedirection(); - WcaFinalizeWow64(); - } -#endif - - ReleaseMem(pbData); - - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - return WcaFinalize(er); -} diff --git a/src/ca/XmlFile.cpp b/src/ca/XmlFile.cpp deleted file mode 100644 index 04a4ae98..00000000 --- a/src/ca/XmlFile.cpp +++ /dev/null @@ -1,940 +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 XMLFILE_CREATE_ELEMENT 0x00000001 -#define XMLFILE_DELETE_VALUE 0x00000002 -#define XMLFILE_BULKWRITE_VALUE 0x00000004 - -#define XMLFILE_DONT_UNINSTALL 0x00010000 -#define XMLFILE_PRESERVE_MODIFIED 0x00001000 -#define XMLFILE_USE_XPATH 0x00000100 - -extern BOOL vfMsxml30; - -enum eXmlAction -{ - xaOpenFile = 1, - xaOpenFilex64, - xaWriteValue, - xaDeleteValue, - xaCreateElement, - xaDeleteElement, - xaBulkWriteValue, -}; - -enum eXmlPreserveDate -{ - xdDontPreserve = 0, - xdPreserve -}; - -enum eXmlSelectionLanguage -{ - xsXSLPattern = 0, - xsXPath = 1, -}; - -LPCWSTR vcsXmlFileQuery = - L"SELECT `Wix4XmlFile`.`Wix4XmlFile`, `Wix4XmlFile`.`File`, `Wix4XmlFile`.`ElementPath`, `Wix4XmlFile`.`Name`, `Wix4XmlFile`.`Value`, " - L"`Wix4XmlFile`.`Flags`, `Wix4XmlFile`.`Component_`, `Component`.`Attributes` " - L"FROM `Wix4XmlFile`,`Component` WHERE `Wix4XmlFile`.`Component_`=`Component`.`Component` ORDER BY `File`, `Sequence`"; -enum eXmlFileQuery { xfqXmlFile = 1, xfqFile, xfqXPath, xfqName, xfqValue, xfqXmlFlags, xfqComponent, xfqCompAttributes }; - -struct XML_FILE_CHANGE -{ - WCHAR wzId[MAX_DARWIN_KEY]; - - INSTALLSTATE isInstalled; - INSTALLSTATE isAction; - - WCHAR wzFile[MAX_PATH]; - LPWSTR pwzElementPath; - WCHAR wzName[MAX_DARWIN_COLUMN]; - LPWSTR pwzValue; - - int iXmlFlags; - int iCompAttributes; - - XML_FILE_CHANGE* pxfcPrev; - XML_FILE_CHANGE* pxfcNext; -}; - -//static HRESULT FreeXmlFileChangeList( -// __in XML_FILE_CHANGE* pxfcList -// ) -//{ -// HRESULT hr = S_OK; -// -// XML_FILE_CHANGE* pxfcDelete; -// while(pxfcList) -// { -// pxfcDelete = pxfcList; -// pxfcList = pxfcList->pxfcNext; -// -// ReleaseStr(pxfcDelete->pwzElementPath); -// ReleaseStr(pxfcDelete->pwzValue); -// -// hr = MemFree(pxfcDelete); -// ExitOnFailure(hr, "failed to free xml file change list item"); -// } -// -//LExit: -// return hr; -//} - -static HRESULT AddXmlFileChangeToList( - __inout XML_FILE_CHANGE** ppxfcHead, - __inout XML_FILE_CHANGE** ppxfcTail - ) -{ - Assert(ppxfcHead && ppxfcTail); - - HRESULT hr = S_OK; - - XML_FILE_CHANGE* pxfc = static_cast(MemAlloc(sizeof(XML_FILE_CHANGE), TRUE)); - ExitOnNull(pxfc, hr, E_OUTOFMEMORY, "failed to allocate memory for new xml file change list element"); - - // Add it to the end of the list - if (NULL == *ppxfcHead) - { - *ppxfcHead = pxfc; - *ppxfcTail = pxfc; - } - else - { - Assert(*ppxfcTail && (*ppxfcTail)->pxfcNext == NULL); - (*ppxfcTail)->pxfcNext = pxfc; - pxfc->pxfcPrev = *ppxfcTail; - *ppxfcTail = pxfc; - } - -LExit: - return hr; -} - - -static HRESULT ReadXmlFileTable( - __inout XML_FILE_CHANGE** ppxfcHead, - __inout XML_FILE_CHANGE** ppxfcTail - ) -{ - Assert(ppxfcHead && ppxfcTail); - - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - PMSIHANDLE hView = NULL; - PMSIHANDLE hRec = NULL; - - LPWSTR pwzData = NULL; - - // check to see if necessary tables are specified - if (S_FALSE == WcaTableExists(L"Wix4XmlFile")) - { - ExitFunction1(hr = S_FALSE); - } - - // loop through all the xml configurations - hr = WcaOpenExecuteView(vcsXmlFileQuery, &hView); - ExitOnFailure(hr, "failed to open view on Wix4XmlFile table"); - - while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) - { - hr = AddXmlFileChangeToList(ppxfcHead, ppxfcTail); - ExitOnFailure(hr, "failed to add xml file change to list"); - - // Get record Id - hr = WcaGetRecordString(hRec, xfqXmlFile, &pwzData); - ExitOnFailure(hr, "failed to get Wix4XmlFile record Id"); - hr = StringCchCopyW((*ppxfcTail)->wzId, countof((*ppxfcTail)->wzId), pwzData); - ExitOnFailure(hr, "failed to copy Wix4XmlFile record Id"); - - // Get component name - hr = WcaGetRecordString(hRec, xfqComponent, &pwzData); - ExitOnFailure(hr, "failed to get component name for Wix4XmlFile: %ls", (*ppxfcTail)->wzId); - - // Get the component's state - er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &(*ppxfcTail)->isInstalled, &(*ppxfcTail)->isAction); - ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "failed to get install state for Component: %ls", pwzData); - - // Get the xml file - hr = WcaGetRecordFormattedString(hRec, xfqFile, &pwzData); - ExitOnFailure(hr, "failed to get xml file for Wix4XmlFile: %ls", (*ppxfcTail)->wzId); - hr = StringCchCopyW((*ppxfcTail)->wzFile, countof((*ppxfcTail)->wzFile), pwzData); - ExitOnFailure(hr, "failed to copy xml file path"); - - // Get the Wix4XmlFile table flags - hr = WcaGetRecordInteger(hRec, xfqXmlFlags, &(*ppxfcTail)->iXmlFlags); - ExitOnFailure(hr, "failed to get Wix4XmlFile flags for Wix4XmlFile: %ls", (*ppxfcTail)->wzId); - - // Get the XPath - hr = WcaGetRecordFormattedString(hRec, xfqXPath, &(*ppxfcTail)->pwzElementPath); - ExitOnFailure(hr, "failed to get XPath for Wix4XmlFile: %ls", (*ppxfcTail)->wzId); - - // Get the name - hr = WcaGetRecordFormattedString(hRec, xfqName, &pwzData); - ExitOnFailure(hr, "failed to get Name for Wix4XmlFile: %ls", (*ppxfcTail)->wzId); - hr = StringCchCopyW((*ppxfcTail)->wzName, countof((*ppxfcTail)->wzName), pwzData); - ExitOnFailure(hr, "failed to copy name of element"); - - // Get the value - hr = WcaGetRecordFormattedString(hRec, xfqValue, &pwzData); - ExitOnFailure(hr, "failed to get Value for Wix4XmlFile: %ls", (*ppxfcTail)->wzId); - hr = StrAllocString(&(*ppxfcTail)->pwzValue, pwzData, 0); - ExitOnFailure(hr, "failed to allocate buffer for value"); - - // Get the component attributes - hr = WcaGetRecordInteger(hRec, xfqCompAttributes, &(*ppxfcTail)->iCompAttributes); - ExitOnFailure(hr, "failed to get component attributes for Wix4XmlFile: %ls", (*ppxfcTail)->wzId); - } - - // if we looped through all records all is well - if (E_NOMOREITEMS == hr) - hr = S_OK; - ExitOnFailure(hr, "failed while looping through all objects to secure"); - -LExit: - ReleaseStr(pwzData); - - return hr; -} - - -static HRESULT BeginChangeFile( - __in LPCWSTR pwzFile, - __in XML_FILE_CHANGE* pxfc, - __inout LPWSTR* ppwzCustomActionData - ) -{ - Assert(pwzFile && *pwzFile && ppwzCustomActionData); - - HRESULT hr = S_OK; - BOOL fIs64Bit = pxfc->iCompAttributes & msidbComponentAttributes64bit; - BOOL fUseXPath = pxfc->iXmlFlags & XMLFILE_USE_XPATH; - LPBYTE pbData = NULL; - SIZE_T cbData = 0; - - LPWSTR pwzRollbackCustomActionData = NULL; - - if (fIs64Bit) - { - hr = WcaWriteIntegerToCaData((int)xaOpenFilex64, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write 64-bit file indicator to custom action data"); - } - else - { - hr = WcaWriteIntegerToCaData((int)xaOpenFile, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write file indicator to custom action data"); - } - if (fUseXPath) - { - hr = WcaWriteIntegerToCaData((int)xsXPath, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write XPath selectionlanguage indicator to custom action data"); - } - else - { - hr = WcaWriteIntegerToCaData((int)xsXSLPattern, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write XSLPattern selectionlanguage indicator to custom action data"); - } - hr = WcaWriteStringToCaData(pwzFile, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write file to custom action data: %ls", pwzFile); - - // If the file already exits, then we have to put it back the way it was on failure - if (FileExistsEx(pwzFile, NULL)) - { - hr = FileRead(&pbData, &cbData, pwzFile); - ExitOnFailure(hr, "failed to read file: %ls", pwzFile); - - // Set up the rollback for this file - hr = WcaWriteIntegerToCaData((int)fIs64Bit, &pwzRollbackCustomActionData); - ExitOnFailure(hr, "failed to write component bitness to rollback custom action data"); - - hr = WcaWriteStringToCaData(pwzFile, &pwzRollbackCustomActionData); - ExitOnFailure(hr, "failed to write file name to rollback custom action data: %ls", pwzFile); - - hr = WcaWriteStreamToCaData(pbData, cbData, &pwzRollbackCustomActionData); - ExitOnFailure(hr, "failed to write file contents to rollback custom action data."); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecXmlFileRollback"), pwzRollbackCustomActionData, COST_XMLFILE); - ExitOnFailure(hr, "failed to schedule ExecXmlFileRollback for file: %ls", pwzFile); - - ReleaseStr(pwzRollbackCustomActionData); - } -LExit: - ReleaseMem(pbData); - - return hr; -} - - -static HRESULT WriteChangeData( - __in XML_FILE_CHANGE* pxfc, - __inout LPWSTR* ppwzCustomActionData - ) -{ - Assert(pxfc && ppwzCustomActionData); - - HRESULT hr = S_OK; - - hr = WcaWriteStringToCaData(pxfc->pwzElementPath, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write ElementPath to custom action data: %ls", pxfc->pwzElementPath); - - hr = WcaWriteStringToCaData(pxfc->wzName, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write Name to custom action data: %ls", pxfc->wzName); - - hr = WcaWriteStringToCaData(pxfc->pwzValue, ppwzCustomActionData); - ExitOnFailure(hr, "failed to write Value to custom action data: %ls", pxfc->pwzValue); - -LExit: - return hr; -} - - -/****************************************************************** - SchedXmlFile - entry point for XmlFile Custom Action - -********************************************************************/ -extern "C" UINT __stdcall SchedXmlFile( - __in MSIHANDLE hInstall - ) -{ -// AssertSz(FALSE, "debug SchedXmlFile"); - - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - LPWSTR pwzCurrentFile = NULL; - BOOL fCurrentFileChanged = FALSE; - BOOL fCurrentUseXPath = FALSE; - - PMSIHANDLE hView = NULL; - PMSIHANDLE hRec = NULL; - - XML_FILE_CHANGE* pxfcHead = NULL; - XML_FILE_CHANGE* pxfcTail = NULL; - XML_FILE_CHANGE* pxfc = NULL; - XML_FILE_CHANGE* pxfcUninstall = NULL; - - LPWSTR pwzCustomActionData = NULL; - - DWORD cFiles = 0; - - // initialize - hr = WcaInitialize(hInstall, "SchedXmlFile"); - ExitOnFailure(hr, "failed to initialize"); - - hr = ReadXmlFileTable(&pxfcHead, &pxfcTail); - if (S_FALSE == hr) - { - WcaLog(LOGMSG_VERBOSE, "Skipping SchedXmlFile because Wix4XmlFile table not present"); - ExitFunction1(hr = S_OK); - } - - MessageExitOnFailure(hr, msierrXmlFileFailedRead, "failed to read Wix4XmlFile table"); - - // loop through all the xml configurations - for (pxfc = pxfcHead; pxfc; pxfc = pxfc->pxfcNext) - { - // If this is the first file, a different file, the last file, or the SelectionLanguage property changes... - if (NULL == pwzCurrentFile || 0 != lstrcmpW(pwzCurrentFile, pxfc->wzFile) || NULL == pxfc->pxfcNext || fCurrentUseXPath != ((XMLFILE_USE_XPATH & pxfc->iXmlFlags))) - { - // If this isn't the first file - if (NULL != pwzCurrentFile) - { - // Do the uninstall work for the current file by walking backwards through the list (so the sequence is reversed) - for (pxfcUninstall = ((NULL != pxfc->pxfcNext) ? pxfc->pxfcPrev : pxfc); pxfcUninstall && 0 == lstrcmpW(pwzCurrentFile, pxfcUninstall->wzFile) && fCurrentUseXPath == ((XMLFILE_USE_XPATH & pxfcUninstall->iXmlFlags)); pxfcUninstall = pxfcUninstall->pxfcPrev) - { - // If it's being uninstalled - if (WcaIsUninstalling(pxfcUninstall->isInstalled, pxfcUninstall->isAction)) - { - // Uninstall the change - if (!(XMLFILE_DONT_UNINSTALL & pxfcUninstall->iXmlFlags)) - { - if (!fCurrentFileChanged) - { - hr = BeginChangeFile(pwzCurrentFile, pxfcUninstall, &pwzCustomActionData); - ExitOnFailure(hr, "failed to begin file change for file: %ls", pwzCurrentFile); - - fCurrentFileChanged = TRUE; - ++cFiles; - } - if (XMLFILE_CREATE_ELEMENT & pxfcUninstall->iXmlFlags) - { - hr = WcaWriteIntegerToCaData((int)xaDeleteElement, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write delete element action indicator to custom action data"); - } - else - { - hr = WcaWriteIntegerToCaData((int)xaDeleteValue, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write delete value action indicator to custom action data"); - } - - if (XMLFILE_PRESERVE_MODIFIED & pxfc->iXmlFlags) - { - hr = WcaWriteIntegerToCaData((int)xdPreserve, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write Preserve Date indicator to custom action data"); - } - else - { - hr = WcaWriteIntegerToCaData((int)xdDontPreserve, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write Don't Preserve Date indicator to custom action data"); - } - - hr = WriteChangeData(pxfcUninstall, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write uninstall change data"); - } - } - } - } - - // Remember the file we're currently working on - hr = StrAllocString(&pwzCurrentFile, pxfc->wzFile, 0); - ExitOnFailure(hr, "failed to copy file name"); - fCurrentUseXPath = (XMLFILE_USE_XPATH & pxfc->iXmlFlags); - - // We haven't changed the current file yet - fCurrentFileChanged = FALSE; - } - - // If it's being installed - if (WcaIsInstalling(pxfc->isInstalled, pxfc->isAction)) - { - if (!fCurrentFileChanged) - { - hr = BeginChangeFile(pwzCurrentFile, pxfc, &pwzCustomActionData); - ExitOnFailure(hr, "failed to begin file change for file: %ls", pwzCurrentFile); - fCurrentFileChanged = TRUE; - ++cFiles; - } - - // Install the change - if (XMLFILE_CREATE_ELEMENT & pxfc->iXmlFlags) - { - hr = WcaWriteIntegerToCaData((int)xaCreateElement, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write create element action indicator to custom action data"); - } - else if (XMLFILE_DELETE_VALUE & pxfc->iXmlFlags) - { - hr = WcaWriteIntegerToCaData((int)xaDeleteValue, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write delete value action indicator to custom action data"); - } - else if (XMLFILE_BULKWRITE_VALUE & pxfc->iXmlFlags) - { - hr = WcaWriteIntegerToCaData((int)xaBulkWriteValue, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write builkwrite value action indicator to custom action data"); - } - else - { - hr = WcaWriteIntegerToCaData((int)xaWriteValue, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write file indicator to custom action data"); - } - - if (XMLFILE_PRESERVE_MODIFIED & pxfc->iXmlFlags) - { - hr = WcaWriteIntegerToCaData((int)xdPreserve, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write Preserve Date indicator to custom action data"); - } - else - { - hr = WcaWriteIntegerToCaData((int)xdDontPreserve, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write Don't Preserve Date indicator to custom action data"); - } - - hr = WriteChangeData(pxfc, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write change data"); - } - } - - // If we looped through all records all is well - if (E_NOMOREITEMS == hr) - hr = S_OK; - ExitOnFailure(hr, "failed while looping through all objects to secure"); - - // Schedule the custom action and add to progress bar - if (pwzCustomActionData && *pwzCustomActionData) - { - Assert(0 < cFiles); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecXmlFile"), pwzCustomActionData, cFiles * COST_XMLFILE); - ExitOnFailure(hr, "failed to schedule ExecXmlFile action"); - } - -LExit: - ReleaseStr(pwzCurrentFile); - ReleaseStr(pwzCustomActionData); - - return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : er); -} - - -/****************************************************************** - ExecXmlFile - entry point for XmlFile Custom Action - -*******************************************************************/ -extern "C" UINT __stdcall ExecXmlFile( - __in MSIHANDLE hInstall - ) -{ -// AssertSz(FALSE, "debug ExecXmlFile"); - HRESULT hr = S_OK; - HRESULT hrOpenFailure = S_OK; - UINT er = ERROR_SUCCESS; - - BOOL fIsFSRedirectDisabled = FALSE; - BOOL fPreserveDate = FALSE; - - int id = IDRETRY; - - LPWSTR pwzCustomActionData = NULL; - LPWSTR pwzData = NULL; - LPWSTR pwzFile = NULL; - LPWSTR pwzXPath = NULL; - LPWSTR pwzName = NULL; - LPWSTR pwzValue = NULL; - LPWSTR pwz = NULL; - - IXMLDOMDocument* pixd = NULL; - IXMLDOMNode* pixn = NULL; - IXMLDOMNode* pixnNewNode = NULL; - IXMLDOMNodeList* pixNodes = NULL; - IXMLDOMDocument2 *pixdDocument2 = NULL; - - FILETIME ft; - - BSTR bstrProperty = ::SysAllocString(L"SelectionLanguage"); - ExitOnNull(bstrProperty, hr, E_OUTOFMEMORY, "failed SysAllocString"); - VARIANT varValue; - ::VariantInit(&varValue); - varValue.vt = VT_BSTR; - varValue.bstrVal = ::SysAllocString(L"XPath"); - ExitOnNull(varValue.bstrVal, hr, E_OUTOFMEMORY, "failed SysAllocString"); - eXmlAction xa; - eXmlPreserveDate xd; - eXmlSelectionLanguage xl; - - // initialize - hr = WcaInitialize(hInstall, "ExecXmlFile"); - ExitOnFailure(hr, "failed to initialize"); - - hr = XmlInitialize(); - ExitOnFailure(hr, "failed to initialize xml utilities"); - - hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData); - ExitOnFailure(hr, "failed to get CustomActionData"); - - WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); - - pwz = pwzCustomActionData; - - hr = WcaReadIntegerFromCaData(&pwz, (int*) &xa); - ExitOnFailure(hr, "failed to process CustomActionData"); - -#ifndef _WIN64 - // Initialize the Wow64 API - store the result in fWow64APIPresent - // If it fails, this doesn't warrant an error yet, because we only need the Wow64 API in some cases - WcaInitializeWow64(); - BOOL fIsWow64Process = WcaIsWow64Process(); -#endif - - if (xaOpenFile != xa && xaOpenFilex64 != xa) - ExitOnFailure(hr = E_INVALIDARG, "invalid custom action data"); - - // loop through all the passed in data - while (pwz && *pwz) - { - hr = WcaReadIntegerFromCaData(&pwz, (int*) &xl); - ExitOnFailure(hr, "failed to process CustomActionData"); - - hr = WcaReadStringFromCaData(&pwz, &pwzFile); - ExitOnFailure(hr, "failed to read file name from custom action data"); - - // Default to not preserve the modified date - fPreserveDate = FALSE; - - // Open the file - ReleaseNullObject(pixd); - - if (xaOpenFilex64 == xa) - { -#ifndef _WIN64 - if (!fIsWow64Process) - { - hr = E_NOTIMPL; - ExitOnFailure(hr, "Custom action was told to act on a 64-bit component, but the custom action process is not running in WOW."); - } - - hr = WcaDisableWow64FSRedirection(); - ExitOnFailure(hr, "Custom action was told to act on a 64-bit component, but was unable to disable filesystem redirection through the Wow64 API."); - - fIsFSRedirectDisabled = TRUE; -#endif - } - - hr = XmlLoadDocumentFromFileEx(pwzFile, XML_LOAD_PRESERVE_WHITESPACE, &pixd); - if (FAILED(hr)) - { - // Ignore the return code for now. If they try to add something, we'll fail the install. If all they do is remove stuff then it doesn't matter. - hrOpenFailure = hr; - hr = S_OK; - } - else - { - hrOpenFailure = S_OK; - } - WcaLog(LOGMSG_VERBOSE, "Configuring Xml File: %ls", pwzFile); - - if (xsXPath == xl) - { - if (vfMsxml30) - { - // If we failed to open the file, don't fail immediately; just skip setting the selection language, and we'll fail later if appropriate - if (SUCCEEDED(hrOpenFailure)) - { - hr = pixd->QueryInterface(XmlUtil_IID_IXMLDOMDocument2, (void**)&pixdDocument2); - ExitOnFailure(hr, "failed in querying IXMLDOMDocument2 interface"); - hr = pixdDocument2->setProperty(bstrProperty, varValue); - ExitOnFailure(hr, "failed in setting SelectionLanguage"); - } - } - else - { - ExitOnFailure(hr = E_NOTIMPL, "Error: current MSXML version does not support xpath query."); - } - } - - while (pwz && *pwz) - { - hr = WcaReadIntegerFromCaData(&pwz, (int*) &xa); - ExitOnFailure(hr, "failed to process CustomActionData"); - - // Break if we need to move on to a different file - if (xaOpenFile == xa || xaOpenFilex64 == xa) - break; - - hr = WcaReadIntegerFromCaData(&pwz, (int*) &xd); - ExitOnFailure(hr, "failed to process CustomActionData"); - - if (xdPreserve == xd) - { - fPreserveDate = TRUE; - } - - // Get path, name, and value to be written - hr = WcaReadStringFromCaData(&pwz, &pwzXPath); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzName); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzValue); - ExitOnFailure(hr, "failed to process CustomActionData"); - - // If we failed to open the file and we're adding something to the file, we've got a problem. Otherwise, just continue on since the file's already gone. - if (FAILED(hrOpenFailure)) - { - if (xaCreateElement == xa || xaWriteValue == xa || xaBulkWriteValue == xa) - { - MessageExitOnFailure(hr = hrOpenFailure, msierrXmlFileFailedOpen, "failed to load XML file: %ls", pwzFile); - } - else - { - continue; - } - } - - // Select the node we're about to modify - ReleaseNullObject(pixn); - - if (xaBulkWriteValue == xa) - { - hr = XmlSelectNodes(pixd, pwzXPath, &pixNodes); - if (S_FALSE == hr) - { - hr = HRESULT_FROM_WIN32(ERROR_OBJECT_NOT_FOUND); - } - - MessageExitOnFailure(hr, msierrXmlFileFailedSelect, "failed to find any nodes: %ls in XML file: %ls", pwzXPath, pwzFile); - for (;;) - { - pixNodes->nextNode(&pixn); - if (NULL == pixn) - break; - - if (pwzName && *pwzName) - { - // We're setting an attribute - hr = XmlSetAttribute(pixn, pwzName, pwzValue); - ExitOnFailure(hr, "failed to set attribute: %ls to value %ls", pwzName, pwzValue); - } - else - { - // We're setting the text of the node - hr = XmlSetText(pixn, pwzValue); - ExitOnFailure(hr, "failed to set text to: %ls for element %ls. Make sure that XPath points to an element.", pwzValue, pwzXPath); - } - ReleaseNullObject(pixn); - } - } - else - { - hr = XmlSelectSingleNode(pixd, pwzXPath, &pixn); - if (S_FALSE == hr) - hr = HRESULT_FROM_WIN32(ERROR_OBJECT_NOT_FOUND); - MessageExitOnFailure(hr, msierrXmlFileFailedSelect, "failed to find node: %ls in XML file: %ls", pwzXPath, pwzFile); - - // Make the modification - if (xaWriteValue == xa) - { - if (pwzName && *pwzName) - { - // We're setting an attribute - hr = XmlSetAttribute(pixn, pwzName, pwzValue); - ExitOnFailure(hr, "failed to set attribute: %ls to value %ls", pwzName, pwzValue); - } - else - { - // We're setting the text of the node - hr = XmlSetText(pixn, pwzValue); - ExitOnFailure(hr, "failed to set text to: %ls for element %ls. Make sure that XPath points to an element.", pwzValue, pwzXPath); - } - } - else if (xaCreateElement == xa) - { - hr = XmlCreateChild(pixn, pwzName, &pixnNewNode); - ExitOnFailure(hr, "failed to create child element: %ls", pwzName); - - if (pwzValue && *pwzValue) - { - hr = XmlSetText(pixnNewNode, pwzValue); - ExitOnFailure(hr, "failed to set text to: %ls for node: %ls", pwzValue, pwzName); - } - - ReleaseNullObject(pixnNewNode); - } - else if (xaDeleteValue == xa) - { - if (pwzName && *pwzName) - { - // Delete the attribute - hr = XmlRemoveAttribute(pixn, pwzName); - ExitOnFailure(hr, "failed to remove attribute: %ls", pwzName); - } - else - { - // Clear the text value for the node - hr = XmlSetText(pixn, L""); - ExitOnFailure(hr, "failed to clear text value"); - } - } - else if (xaDeleteElement == xa) - { - // TODO: This may be a little heavy handed - hr = XmlRemoveChildren(pixn, pwzName); - ExitOnFailure(hr, "failed to delete child node: %ls", pwzName); - } - else - { - ExitOnFailure(hr = E_UNEXPECTED, "Invalid modification specified in custom action data"); - } - } - } - - // Now that we've made all of the changes to this file, save it and move on to the next - if (S_OK == hrOpenFailure) - { - if (fPreserveDate) - { - hr = FileGetTime(pwzFile, NULL, NULL, &ft); - ExitOnFailure(hr, "failed to get modified time of file : %ls", pwzFile); - } - - int iSaveAttempt = 0; - - do - { - hr = XmlSaveDocument(pixd, pwzFile); - if (FAILED(hr)) - { - id = WcaErrorMessage(msierrXmlConfigFailedSave, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 1, pwzFile); - switch (id) - { - case IDABORT: - ExitOnFailure(hr, "Failed to save changes to XML file: %ls", pwzFile); - case IDRETRY: - hr = S_FALSE; // hit me, baby, one more time - break; - case IDIGNORE: - hr = S_OK; // pretend everything is okay and bail - break; - case 0: // No UI case, MsiProcessMessage returns 0 - if (STIERR_SHARING_VIOLATION == hr) - { - // Only in case of sharing violation do we retry 30 times, once a second. - if (iSaveAttempt < 30) - { - hr = S_FALSE; - ++iSaveAttempt; - WcaLog(LOGMSG_VERBOSE, "Unable to save changes to XML file: %ls, retry attempt: %x", pwzFile, iSaveAttempt); - Sleep(1000); - } - else - { - ExitOnFailure(hr, "Failed to save changes to XML file: %ls", pwzFile); - } - } - break; - default: // Unknown error - ExitOnFailure(hr, "Failed to save changes to XML file: %ls", pwzFile); - } - } - } while (S_FALSE == hr); - - if (fPreserveDate) - { - hr = FileSetTime(pwzFile, NULL, NULL, &ft); - ExitOnFailure(hr, "failed to set modified time of file : %ls", pwzFile); - } - - if (fIsFSRedirectDisabled) - { - fIsFSRedirectDisabled = FALSE; - WcaRevertWow64FSRedirection(); - } - } - } - -LExit: - // Make sure we revert FS Redirection if necessary before exiting - if (fIsFSRedirectDisabled) - { - fIsFSRedirectDisabled = FALSE; - WcaRevertWow64FSRedirection(); - } -#ifndef _WIN64 - WcaFinalizeWow64(); -#endif - - ReleaseStr(pwzCustomActionData); - ReleaseStr(pwzData); - ReleaseStr(pwzFile); - ReleaseStr(pwzXPath); - ReleaseStr(pwzName); - ReleaseStr(pwzValue); - ReleaseBSTR(bstrProperty); - ReleaseVariant(varValue); - - ReleaseObject(pixdDocument2); - ReleaseObject(pixn); - ReleaseObject(pixd); - ReleaseObject(pixnNewNode); - ReleaseObject(pixNodes); - - XmlUninitialize(); - - return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : er); -} - - -/****************************************************************** - ExecXmlFileRollback - entry point for XmlFile rollback Custom Action - -*******************************************************************/ -extern "C" UINT __stdcall ExecXmlFileRollback( - __in MSIHANDLE hInstall - ) -{ -// AssertSz(FALSE, "debug ExecXmlFileRollback"); - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - int iIs64Bit; - BOOL fIs64Bit = FALSE; - - LPWSTR pwzCustomActionData = NULL; - LPWSTR pwz = NULL; - LPWSTR pwzFileName = NULL; - LPBYTE pbData = NULL; - DWORD_PTR cbData = 0; - - FILETIME ft; - - HANDLE hFile = INVALID_HANDLE_VALUE; - - // initialize - hr = WcaInitialize(hInstall, "ExecXmlFileRollback"); - ExitOnFailure(hr, "failed to initialize"); - - - hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData); - ExitOnFailure(hr, "failed to get CustomActionData"); - - WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); - - pwz = pwzCustomActionData; - - hr = WcaReadIntegerFromCaData(&pwz, &iIs64Bit); - ExitOnFailure(hr, "failed to read component bitness from custom action data"); - - hr = WcaReadStringFromCaData(&pwz, &pwzFileName); - ExitOnFailure(hr, "failed to read file name from custom action data"); - - hr = WcaReadStreamFromCaData(&pwz, &pbData, &cbData); - ExitOnFailure(hr, "failed to read file contents from custom action data"); - -#ifndef _WIN64 - fIs64Bit = (BOOL)iIs64Bit; - - if (fIs64Bit) - { - hr = WcaInitializeWow64(); - if (S_FALSE == hr) - { - hr = TYPE_E_DLLFUNCTIONNOTFOUND; - } - ExitOnFailure(hr, "failed to initialize Wow64 API"); - - if (!WcaIsWow64Process()) - { - hr = E_NOTIMPL; - ExitOnFailure(hr, "Custom action was told to rollback a 64-bit component, but the custom action process is not running in WOW."); - } - - hr = WcaDisableWow64FSRedirection(); - ExitOnFailure(hr, "Custom action was told to rollback a 64-bit component, but was unable to Disable Filesystem Redirection through the Wow64 API."); - } -#endif - - // Always preserve the modified date on rollback - hr = FileGetTime(pwzFileName, NULL, NULL, &ft); - ExitOnFailure(hr, "Failed to get modified date of file %ls.", pwzFileName); - - // Open the file - hFile = ::CreateFileW(pwzFileName, GENERIC_WRITE, NULL, NULL, TRUNCATE_EXISTING, NULL, NULL); - ExitOnInvalidHandleWithLastError(hFile, hr, "failed to open file: %ls", pwzFileName); - - // Write out the old data - hr = FileWriteHandle(hFile, pbData, cbData); - ExitOnFailure(hr, "failed to write to file: %ls", pwzFileName); - - ReleaseFile(hFile); - - // Always preserve the modified date on rollback - hr = FileSetTime(pwzFileName, NULL, NULL, &ft); - ExitOnFailure(hr, "Failed to set modified date of file %ls.", pwzFileName); - -LExit: - ReleaseStr(pwzCustomActionData); - ReleaseStr(pwzFileName); - - ReleaseFile(hFile); - - if (fIs64Bit) - { - WcaRevertWow64FSRedirection(); - WcaFinalizeWow64(); - } - - ReleaseMem(pbData); - - return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : er); -} - diff --git a/src/ca/caDecor.h b/src/ca/caDecor.h deleted file mode 100644 index 56cfb201..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/cost.h b/src/ca/cost.h deleted file mode 100644 index 6507e85d..00000000 --- a/src/ca/cost.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. - - -const UINT COST_SECUREOBJECT = 1000; -const UINT COST_SERVICECONFIG = 1000; -const UINT COST_XMLFILE = 1000; -const UINT COST_CLOSEAPP = 500; -const UINT COST_INTERNETSHORTCUT = 2000; 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/exitearlywithsuccess.cpp b/src/ca/exitearlywithsuccess.cpp deleted file mode 100644 index 00828329..00000000 --- a/src/ca/exitearlywithsuccess.cpp +++ /dev/null @@ -1,27 +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" - - -/****************************************************************** -WixExitEarlyWithSuccess - entry point for WixExitEarlyWithSuccess - custom action which does nothing except return exit code - ERROR_NO_MORE_ITEMS. The Windows Installer documentation at - http://msdn.microsoft.com/library/aa368072.aspx indicates that - this exit code is not treated as an error. This will cause a - calling application to receive a successful return code if - this custom action executes. This can be useful for backwards - compatibility when an application redistributes an MSI and - a future major upgrade is released for that MSI. It should be - conditioned on a property set by an entry in the Upgrade table - of the MSI that detects newer major upgrades of the same MSI - already installed on the system. It should be scheduled after - the FindRelatedProducts action so that the property will be - set if appropriate. -********************************************************************/ -extern "C" UINT __stdcall WixExitEarlyWithSuccess( - __in MSIHANDLE /*hInstall*/ - ) -{ - return ERROR_NO_MORE_ITEMS; -} diff --git a/src/ca/netshortcuts.cpp b/src/ca/netshortcuts.cpp deleted file mode 100644 index 06826264..00000000 --- a/src/ca/netshortcuts.cpp +++ /dev/null @@ -1,437 +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 vcsShortcutsQuery = - L"SELECT `Component_`, `Directory_`, `Name`, `Target`, `Attributes`, `IconFile`, `IconIndex` " - L"FROM `Wix4InternetShortcut`"; -enum eShortcutsQuery { esqComponent = 1, esqDirectory, esqFilename, esqTarget, esqAttributes, esqIconFile, esqIconIndex }; -enum eShortcutsAttributes { esaLink = 0, esaURL = 1 }; - -/****************************************************************** - WixSchedInternetShortcuts - entry point - -********************************************************************/ -extern "C" UINT __stdcall WixSchedInternetShortcuts( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - UINT uiCost = 0; - - PMSIHANDLE hView = NULL; - PMSIHANDLE hRec = NULL; - - MSIHANDLE hCreateFolderTable = NULL; - MSIHANDLE hCreateFolderColumns = NULL; - - LPWSTR pwzCustomActionData = NULL; - LPWSTR pwzComponent = NULL; - LPWSTR pwzDirectory = NULL; - LPWSTR pwzFilename = NULL; - LPWSTR pwzTarget = NULL; - LPWSTR pwzShortcutPath = NULL; - int iAttr = 0; - LPWSTR pwzIconFile = NULL; - int iIconIndex = 0; - IUniformResourceLocatorW* piURL = NULL; - IShellLinkW* piShellLink = NULL; - BOOL fInitializedCom = FALSE; - - hr = WcaInitialize(hInstall, "WixSchedInternetShortcuts"); - ExitOnFailure(hr, "failed to initialize WixSchedInternetShortcuts."); - - // anything to do? - if (S_OK != WcaTableExists(L"Wix4InternetShortcut")) - { - WcaLog(LOGMSG_STANDARD, "Wix4InternetShortcut table doesn't exist, so there are no Internet shortcuts to process"); - goto LExit; - } - - // check to see if we can create a shortcut - Server Core and others may not have a shell registered. - hr = ::CoInitialize(NULL); - ExitOnFailure(hr, "failed to initialize COM"); - fInitializedCom = TRUE; - - hr = ::CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_ALL, IID_IUniformResourceLocatorW, (void**)&piURL); - if (S_OK != hr) - { - WcaLog(LOGMSG_STANDARD, "failed to create an instance of IUniformResourceLocatorW, skipping shortcut creation"); - ExitFunction1(hr = S_OK); - } - - hr = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLinkW, (void**)&piShellLink); - if (S_OK != hr) - { - WcaLog(LOGMSG_STANDARD, "failed to create an instance of IShellLinkW, skipping shortcut creation"); - ExitFunction1(hr = S_OK); - } - - // query and loop through all the shortcuts - hr = WcaOpenExecuteView(vcsShortcutsQuery, &hView); - ExitOnFailure(hr, "failed to open view on Wix4InternetShortcut table"); - - while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) - { - // read column values - hr = WcaGetRecordString(hRec, esqComponent, &pwzComponent); - ExitOnFailure(hr, "failed to get shortcut component"); - hr = WcaGetRecordString(hRec, esqDirectory, &pwzDirectory); - ExitOnFailure(hr, "failed to get shortcut directory"); - hr = WcaGetRecordString(hRec, esqFilename, &pwzFilename); - ExitOnFailure(hr, "failed to get shortcut filename"); - hr = WcaGetRecordFormattedString(hRec, esqTarget, &pwzTarget); - ExitOnFailure(hr, "failed to get shortcut target"); - hr = WcaGetRecordInteger(hRec, esqAttributes, &iAttr); - ExitOnFailure(hr, "failed to get shortcut attributes"); - hr = WcaGetRecordFormattedString(hRec, esqIconFile, &pwzIconFile); - ExitOnFailure(hr, "failed to get shortcut icon file"); - hr = WcaGetRecordInteger(hRec, esqIconIndex, &iIconIndex); - ExitOnFailure(hr, "failed to get shortcut icon index"); - - // skip processing this Wix4InternetShortcut row if the component isn't being configured - WCA_TODO todo = WcaGetComponentToDo(pwzComponent); - if (WCA_TODO_UNKNOWN == todo) - { - WcaLog(LOGMSG_VERBOSE, "Skipping shortcut for null-action component '%ls'", pwzComponent); - continue; - } - - // we need to create the directory where the shortcut is supposed to live; rather - // than doing so in our deferred custom action, use the CreateFolder table to have MSI - // make (and remove) them on our behalf (including the correct cleanup of parent directories). - MSIDBERROR dbError = MSIDBERROR_NOERROR; - WcaLog(LOGMSG_STANDARD, "Adding folder '%ls', component '%ls' to the CreateFolder table", pwzDirectory, pwzComponent); - hr = WcaAddTempRecord(&hCreateFolderTable, &hCreateFolderColumns, L"CreateFolder", &dbError, 0, 2, pwzDirectory, pwzComponent); - if (MSIDBERROR_DUPLICATEKEY == dbError) - { - WcaLog(LOGMSG_STANDARD, "Folder '%ls' already exists in the CreateFolder table; the above error is harmless", pwzDirectory); - hr = S_OK; - } - ExitOnFailure(hr, "Couldn't add temporary CreateFolder row"); - - // only if we're installing/reinstalling do we need to schedule the deferred CA - // (uninstallation is handled via permanent RemoveFile rows and temporary CreateFolder rows) - if (WCA_TODO_INSTALL == todo || WCA_TODO_REINSTALL == todo) - { - // turn the Directory_ id into a path - hr = WcaGetTargetPath(pwzDirectory, &pwzShortcutPath); - ExitOnFailure(hr, "failed to allocate string for shortcut directory"); - - // append the shortcut filename - hr = StrAllocConcat(&pwzShortcutPath, pwzFilename, 0); - ExitOnFailure(hr, "failed to allocate string for shortcut filename"); - - // write the shortcut path and target to custom action data for deferred CAs - hr = WcaWriteStringToCaData(pwzShortcutPath, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write shortcut path to custom action data"); - hr = WcaWriteStringToCaData(pwzTarget, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write shortcut target to custom action data"); - hr = WcaWriteIntegerToCaData(iAttr, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write shortcut attributes to custom action data"); - hr = WcaWriteStringToCaData(pwzIconFile, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write icon file to custom action data"); - hr = WcaWriteIntegerToCaData(iIconIndex, &pwzCustomActionData); - ExitOnFailure(hr, "failed to write icon index to custom action data"); - - uiCost += COST_INTERNETSHORTCUT; - } - } - - if (E_NOMOREITEMS == hr) - { - hr = S_OK; - } - ExitOnFailure(hr, "Failure occured while processing Wix4InternetShortcut table"); - - // if we have any shortcuts to install - if (pwzCustomActionData && *pwzCustomActionData) - { - // add cost to progress bar - hr = WcaProgressMessage(uiCost, TRUE); - ExitOnFailure(hr, "failed to extend progress bar for InternetShortcuts"); - - // provide custom action data to deferred and rollback CAs - hr = WcaSetProperty(CUSTOM_ACTION_DECORATION(L"RollbackInternetShortcuts"), pwzCustomActionData); - ExitOnFailure(hr, "failed to set WixRollbackInternetShortcuts rollback custom action data"); - hr = WcaSetProperty(CUSTOM_ACTION_DECORATION(L"CreateInternetShortcuts"), pwzCustomActionData); - ExitOnFailure(hr, "failed to set WixCreateInternetShortcuts custom action data"); - } - -LExit: - if (hCreateFolderTable) - { - ::MsiCloseHandle(hCreateFolderTable); - } - - if (hCreateFolderColumns) - { - ::MsiCloseHandle(hCreateFolderColumns); - } - - ReleaseStr(pwzCustomActionData); - ReleaseStr(pwzComponent); - ReleaseStr(pwzDirectory); - ReleaseStr(pwzFilename); - ReleaseStr(pwzTarget); - ReleaseStr(pwzShortcutPath); - ReleaseObject(piShellLink); - ReleaseObject(piURL); - - if (fInitializedCom) - { - ::CoUninitialize(); - } - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - - -/****************************************************************** - CreateUrl - Creates a shortcut via IUniformResourceLocatorW - -*******************************************************************/ -static HRESULT CreateUrl( - __in_z LPCWSTR wzTarget, - __in_z LPCWSTR wzShortcutPath, - __in_z_opt LPCWSTR wzIconPath, - __in int iconIndex -) -{ - HRESULT hr = S_OK; - IUniformResourceLocatorW* piURL = NULL; - IPersistFile* piPersistFile = NULL; - IPropertySetStorage* piProperties = NULL; - IPropertyStorage* piStorage = NULL; - - // create an internet shortcut object - WcaLog(LOGMSG_STANDARD, "Creating IUniformResourceLocatorW shortcut '%ls' target '%ls'", wzShortcutPath, wzTarget); - hr = ::CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_ALL, IID_IUniformResourceLocatorW, (void**)&piURL); - ExitOnFailure(hr, "failed to create an instance of IUniformResourceLocatorW"); - - // set shortcut target - hr = piURL->SetURL(wzTarget, 0); - ExitOnFailure(hr, "failed to set shortcut '%ls' target '%ls'", wzShortcutPath, wzTarget); - - if (wzIconPath) - { - WcaLog(LOGMSG_STANDARD, "Adding icon '%ls' index '%d'", wzIconPath, iconIndex); - - hr = piURL->QueryInterface(IID_IPropertySetStorage, (void **)&piProperties); - ExitOnFailure(hr, "failed to get IPropertySetStorage for shortcut '%ls'", wzShortcutPath); - - hr = piProperties->Open(FMTID_Intshcut, STGM_WRITE, &piStorage); - ExitOnFailure(hr, "failed to open storage for shortcut '%ls'", wzShortcutPath); - - PROPSPEC ppids[2] = { {PRSPEC_PROPID, PID_IS_ICONINDEX}, {PRSPEC_PROPID, PID_IS_ICONFILE} }; - PROPVARIANT ppvar[2]; - - PropVariantInit(ppvar); - PropVariantInit(ppvar + 1); - - ppvar[0].vt = VT_I4; - ppvar[0].lVal = iconIndex; - ppvar[1].vt = VT_LPWSTR; - ppvar[1].pwszVal = const_cast(wzIconPath); - - hr = piStorage->WriteMultiple(2, ppids, ppvar, 0); - ExitOnFailure(hr, "failed to write icon storage for shortcut '%ls'", wzShortcutPath); - - hr = piStorage->Commit(STGC_DEFAULT); - ExitOnFailure(hr, "failed to commit icon storage for shortcut '%ls'", wzShortcutPath); - } - - // get an IPersistFile and save the shortcut - hr = piURL->QueryInterface(IID_IPersistFile, (void**)&piPersistFile); - ExitOnFailure(hr, "failed to get IPersistFile for shortcut '%ls'", wzShortcutPath); - - hr = piPersistFile->Save(wzShortcutPath, TRUE); - ExitOnFailure(hr, "failed to save shortcut '%ls'", wzShortcutPath); - -LExit: - ReleaseObject(piPersistFile); - ReleaseObject(piURL); - ReleaseObject(piStorage); - ReleaseObject(piProperties); - - return hr; -} - -/****************************************************************** - CreateLink - Creates a shortcut via IShellLinkW - -*******************************************************************/ -static HRESULT CreateLink( - __in_z LPCWSTR wzTarget, - __in_z LPCWSTR wzShortcutPath, - __in_z_opt LPCWSTR wzIconPath, - __in int iconIndex -) -{ - HRESULT hr = S_OK; - IShellLinkW* piShellLink = NULL; - IPersistFile* piPersistFile = NULL; - - // create an internet shortcut object - WcaLog(LOGMSG_STANDARD, "Creating IShellLinkW shortcut '%ls' target '%ls'", wzShortcutPath, wzTarget); - hr = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLinkW, (void**)&piShellLink); - ExitOnFailure(hr, "failed to create an instance of IShellLinkW"); - - // set shortcut target - hr = piShellLink->SetPath(wzTarget); - ExitOnFailure(hr, "failed to set shortcut '%ls' target '%ls'", wzShortcutPath, wzTarget); - - if (wzIconPath) - { - WcaLog(LOGMSG_STANDARD, "Adding icon '%ls' index '%d'", wzIconPath, iconIndex); - hr = piShellLink->SetIconLocation(wzIconPath, iconIndex); - ExitOnFailure(hr, "failed to set icon for shortcut '%ls'", wzShortcutPath); - } - - // get an IPersistFile and save the shortcut - hr = piShellLink->QueryInterface(IID_IPersistFile, (void**)&piPersistFile); - ExitOnFailure(hr, "failed to get IPersistFile for shortcut '%ls'", wzShortcutPath); - - hr = piPersistFile->Save(wzShortcutPath, TRUE); - ExitOnFailure(hr, "failed to save shortcut '%ls'", wzShortcutPath); - -LExit: - ReleaseObject(piPersistFile); - ReleaseObject(piShellLink); - - return hr; -} - - - -/****************************************************************** - WixCreateInternetShortcuts - entry point for Internet shortcuts - custom action -*******************************************************************/ -extern "C" UINT __stdcall WixCreateInternetShortcuts( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - LPWSTR pwz = NULL; - LPWSTR pwzCustomActionData = NULL; - LPWSTR pwzTarget = NULL; - LPWSTR pwzShortcutPath = NULL; - LPWSTR pwzIconPath = NULL; - BOOL fInitializedCom = FALSE; - int iAttr = 0; - int iIconIndex = 0; - - // initialize - hr = WcaInitialize(hInstall, "WixCreateInternetShortcuts"); - ExitOnFailure(hr, "failed to initialize WixCreateInternetShortcuts"); - - hr = ::CoInitialize(NULL); - ExitOnFailure(hr, "failed to initialize COM"); - fInitializedCom = TRUE; - - // extract the custom action data - hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); - ExitOnFailure(hr, "failed to get CustomActionData"); - - // loop through all the custom action data - pwz = pwzCustomActionData; - while (pwz && *pwz) - { - hr = WcaReadStringFromCaData(&pwz, &pwzShortcutPath); - ExitOnFailure(hr, "failed to read shortcut path from custom action data"); - hr = WcaReadStringFromCaData(&pwz, &pwzTarget); - ExitOnFailure(hr, "failed to read shortcut target from custom action data"); - hr = WcaReadIntegerFromCaData(&pwz, &iAttr); - ExitOnFailure(hr, "failed to read shortcut attributes from custom action data"); - hr = WcaReadStringFromCaData(&pwz, &pwzIconPath); - ExitOnFailure(hr, "failed to read shortcut icon path from custom action data"); - hr = WcaReadIntegerFromCaData(&pwz, &iIconIndex); - ExitOnFailure(hr, "failed to read shortcut icon index from custom action data"); - - if ((iAttr & esaURL) == esaURL) - { - hr = CreateUrl(pwzTarget, pwzShortcutPath, pwzIconPath, iIconIndex); - } - else - { - hr = CreateLink(pwzTarget, pwzShortcutPath, pwzIconPath, iIconIndex); - } - ExitOnFailure(hr, "failed to create Internet shortcut"); - - // tick the progress bar - hr = WcaProgressMessage(COST_INTERNETSHORTCUT, FALSE); - ExitOnFailure(hr, "failed to tick progress bar for shortcut: %ls", pwzShortcutPath); - } - -LExit: - ReleaseStr(pwzCustomActionData); - ReleaseStr(pwzTarget); - ReleaseStr(pwzShortcutPath); - - if (fInitializedCom) - { - ::CoUninitialize(); - } - - er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er; - return WcaFinalize(er); -} - - - -/****************************************************************** - WixRollbackInternetShortcuts - entry point for Internet shortcuts - custom action (rollback) -*******************************************************************/ -extern "C" UINT __stdcall WixRollbackInternetShortcuts( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - LPWSTR pwz = NULL; - LPWSTR pwzCustomActionData = NULL; - LPWSTR pwzShortcutPath = NULL; - int iAttr = 0; - - // initialize - hr = WcaInitialize(hInstall, "WixRemoveInternetShortcuts"); - ExitOnFailure(hr, "failed to initialize WixRemoveInternetShortcuts"); - - hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); - ExitOnFailure(hr, "failed to get CustomActionData"); - - // loop through all the custom action data - pwz = pwzCustomActionData; - while (pwz && *pwz) - { - // extract the custom action data we're interested in - hr = WcaReadStringFromCaData(&pwz, &pwzShortcutPath); - ExitOnFailure(hr, "failed to read shortcut path from custom action data for rollback"); - - // delete file - hr = FileEnsureDelete(pwzShortcutPath); - ExitOnFailure(hr, "failed to delete file '%ls'", pwzShortcutPath); - - // skip over the shortcut target and attributes - hr = WcaReadStringFromCaData(&pwz, &pwzShortcutPath); - ExitOnFailure(hr, "failed to skip shortcut target from custom action data for rollback"); - hr = WcaReadIntegerFromCaData(&pwz, &iAttr); - ExitOnFailure(hr, "failed to read shortcut attributes from custom action data"); - } - -LExit: - ReleaseStr(pwzCustomActionData); - ReleaseStr(pwzShortcutPath); - - er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er; - return WcaFinalize(er); -} diff --git a/src/ca/precomp.h b/src/ca/precomp.h deleted file mode 100644 index c5d6afe5..00000000 --- a/src/ca/precomp.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. - - -#if _WIN32_MSI < 150 -#define _WIN32_MSI 150 -#endif - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include // NetApi32.lib -#include -#include -#include -#include - -#define MAXUINT USHRT_MAX - -#include "wcautil.h" -#include "wcawow64.h" -#include "wcawrapquery.h" -#include "aclutil.h" -#include "dirutil.h" -#include "fileutil.h" -#include "memutil.h" -#include "osutil.h" -#include "pathutil.h" -#include "procutil.h" -#include "shelutil.h" -#include "strutil.h" -#include "sczutil.h" -#include "rmutil.h" -#include "userutil.h" -#include "xmlutil.h" -#include "wiutil.h" - -#include "CustomMsiErrors.h" - -#include "sca.h" -#include "scacost.h" -#include "cost.h" -#include "scauser.h" -#include "scasmb.h" -#include "scasmbexec.h" - -#include "caDecor.h" diff --git a/src/ca/qtexecca.cpp b/src/ca/qtexecca.cpp deleted file mode 100644 index ddcc812f..00000000 --- a/src/ca/qtexecca.cpp +++ /dev/null @@ -1,316 +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 OUTPUT_BUFFER 1024 - -// These old "CA" prefix names are deprecated, and intended to go away in wix 4.0, only staying now for compatibility reasons -const LPCWSTR CAQUIET_TIMEOUT_PROPERTY = L"QtExecCmdTimeout"; -const LPCWSTR CAQUIET_ARGUMENTS_PROPERTY = L"QtExecCmdLine"; -const LPCWSTR CAQUIET64_ARGUMENTS_PROPERTY = L"QtExec64CmdLine"; -// end deprecated section - -// WixCA name quiet commandline argument properties -const LPCWSTR WIX_QUIET_ARGUMENTS_PROPERTY = L"WixQuietExecCmdLine"; -const LPCWSTR WIX_QUIET64_ARGUMENTS_PROPERTY = L"WixQuietExec64CmdLine"; - -// WixCA quiet timeout properties -const LPCWSTR WIX_QUIET_TIMEOUT_PROPERTY = L"WixQuietExecCmdTimeout"; -const LPCWSTR WIX_QUIET64_TIMEOUT_PROPERTY = L"WixQuietExec64CmdTimeout"; - -// WixCA silent commandline argument properties -const LPCWSTR WIX_SILENT_ARGUMENTS_PROPERTY = L"WixSilentExecCmdLine"; -const LPCWSTR WIX_SILENT64_ARGUMENTS_PROPERTY = L"WixSilentExec64CmdLine"; - -// WixCA silent timeout properties -const LPCWSTR WIX_SILENT_TIMEOUT_PROPERTY = L"WixSilentExecCmdTimeout"; -const LPCWSTR WIX_SILENT64_TIMEOUT_PROPERTY = L"WixSilentExec64CmdTimeout"; - -HRESULT BuildCommandLine( - __in LPCWSTR wzProperty, - __out LPWSTR *ppwzCommand - ) -{ - Assert(ppwzCommand); - - HRESULT hr = S_OK; - BOOL fScheduled = ::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_SCHEDULED); - BOOL fRollback = ::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK); - BOOL fCommit = ::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_COMMIT); - - if (fScheduled || fRollback || fCommit) - { - if (WcaIsPropertySet("CustomActionData")) - { - hr = WcaGetProperty( L"CustomActionData", ppwzCommand); - ExitOnFailure(hr, "Failed to get CustomActionData"); - } - } - else if (WcaIsUnicodePropertySet(wzProperty)) - { - hr = WcaGetFormattedProperty(wzProperty, ppwzCommand); - ExitOnFailure(hr, "Failed to get %ls", wzProperty); - hr = WcaSetProperty(wzProperty, L""); // clear out the property now that we've read it - ExitOnFailure(hr, "Failed to set %ls", wzProperty); - } - - if (!*ppwzCommand) - { - ExitOnFailure(hr = E_INVALIDARG, "Failed to get command line data"); - } - - if (L'"' != **ppwzCommand) - { - WcaLog(LOGMSG_STANDARD, "Command string must begin with quoted application name."); - ExitOnFailure(hr = E_INVALIDARG, "invalid command line property value"); - } - -LExit: - return hr; -} - -#define ONEMINUTE 60000 - -DWORD GetTimeout(LPCWSTR wzPropertyName) -{ - DWORD dwTimeout = ONEMINUTE; - HRESULT hr = S_OK; - - LPWSTR pwzData = NULL; - - if (WcaIsUnicodePropertySet(wzPropertyName)) - { - hr = WcaGetProperty(wzPropertyName, &pwzData); - ExitOnFailure(hr, "Failed to get %ls", wzPropertyName); - - if ((dwTimeout = (DWORD)_wtoi(pwzData)) == 0) - { - dwTimeout = ONEMINUTE; - } - } - -LExit: - ReleaseStr(pwzData); - - return dwTimeout; - -} - -HRESULT ExecCommon( - __in LPCWSTR wzArgumentsProperty, - __in LPCWSTR wzTimeoutProperty, - __in BOOL fLogCommand, - __in BOOL fLogOutput - ) -{ - HRESULT hr = S_OK; - LPWSTR pwzCommand = NULL; - DWORD dwTimeout = 0; - - hr = BuildCommandLine(wzArgumentsProperty, &pwzCommand); - ExitOnFailure(hr, "Failed to get Command Line"); - - dwTimeout = GetTimeout(wzTimeoutProperty); - - hr = QuietExec(pwzCommand, dwTimeout, fLogCommand, fLogOutput); - ExitOnFailure(hr, "QuietExec Failed"); - -LExit: - ReleaseStr(pwzCommand); - - return hr; -} - -HRESULT ExecCommon64( - __in LPCWSTR wzArgumentsProperty, - __in LPCWSTR wzTimeoutProperty, - __in BOOL fLogCommand, - __in BOOL fLogOutput - ) -{ - HRESULT hr = S_OK; - LPWSTR pwzCommand = NULL; - DWORD dwTimeout = 0; -#ifndef _WIN64 - BOOL fIsWow64Initialized = FALSE; - BOOL fRedirected = FALSE; - - hr = WcaInitializeWow64(); - if (S_FALSE == hr) - { - hr = TYPE_E_DLLFUNCTIONNOTFOUND; - } - ExitOnFailure(hr, "Failed to intialize WOW64."); - fIsWow64Initialized = TRUE; - - hr = WcaDisableWow64FSRedirection(); - ExitOnFailure(hr, "Failed to enable filesystem redirection."); - fRedirected = TRUE; -#endif - - hr = BuildCommandLine(wzArgumentsProperty, &pwzCommand); - ExitOnFailure(hr, "Failed to get Command Line"); - - dwTimeout = GetTimeout(wzTimeoutProperty); - - hr = QuietExec(pwzCommand, dwTimeout, fLogCommand, fLogOutput); - ExitOnFailure(hr, "QuietExec64 Failed"); - -LExit: - ReleaseStr(pwzCommand); - -#ifndef _WIN64 - if (fRedirected) - { - WcaRevertWow64FSRedirection(); - } - - if (fIsWow64Initialized) - { - WcaFinalizeWow64(); - } -#endif - - return hr; -} - -// These two custom actions are deprecated, and should go away in wix v4.0. WixQuietExec replaces this one, -// and is not intended to have any difference in behavior apart from CA name and property names. -extern "C" UINT __stdcall CAQuietExec( - __in MSIHANDLE hInstall - ) -{ - Assert(hInstall); - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - hr = WcaInitialize(hInstall, "CAQuietExec"); - ExitOnFailure(hr, "Failed to initialize"); - - hr = ExecCommon(CAQUIET_ARGUMENTS_PROPERTY, CAQUIET_TIMEOUT_PROPERTY, TRUE, TRUE); - ExitOnFailure(hr, "Failed in ExecCommon method"); - -LExit: - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - - return WcaFinalize(er); -} - -// 2nd deprecated custom action name, superseded by WixQuietExec64 -extern "C" UINT __stdcall CAQuietExec64( - __in MSIHANDLE hInstall - ) -{ - Assert(hInstall); - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - hr = WcaInitialize(hInstall, "CAQuietExec64"); - ExitOnFailure(hr, "Failed to initialize"); - - hr = ExecCommon64(CAQUIET64_ARGUMENTS_PROPERTY, CAQUIET_TIMEOUT_PROPERTY, TRUE, TRUE); - ExitOnFailure(hr, "Failed in ExecCommon64 method"); - -LExit: - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - - return WcaFinalize(er); -} - -extern "C" UINT __stdcall WixQuietExec( - __in MSIHANDLE hInstall - ) -{ - Assert(hInstall); - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - hr = WcaInitialize(hInstall, "WixQuietExec"); - ExitOnFailure(hr, "Failed to initialize"); - - hr = ExecCommon(WIX_QUIET_ARGUMENTS_PROPERTY, WIX_QUIET_TIMEOUT_PROPERTY, TRUE, TRUE); - ExitOnFailure(hr, "Failed in ExecCommon method"); - -LExit: - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - - return WcaFinalize(er); -} - -extern "C" UINT __stdcall WixQuietExec64( - __in MSIHANDLE hInstall - ) -{ - Assert(hInstall); - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - hr = WcaInitialize(hInstall, "WixQuietExec64"); - ExitOnFailure(hr, "Failed to initialize"); - - hr = ExecCommon64(WIX_QUIET64_ARGUMENTS_PROPERTY, WIX_QUIET64_TIMEOUT_PROPERTY, TRUE, TRUE); - ExitOnFailure(hr, "Failed in ExecCommon method"); - -LExit: - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - - return WcaFinalize(er); -} - -extern "C" UINT __stdcall WixSilentExec( - __in MSIHANDLE hInstall - ) -{ - Assert(hInstall); - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - hr = WcaInitialize(hInstall, "WixSilentExec"); - ExitOnFailure(hr, "Failed to initialize"); - - hr = ExecCommon(WIX_SILENT_ARGUMENTS_PROPERTY, WIX_SILENT_TIMEOUT_PROPERTY, FALSE, FALSE); - ExitOnFailure(hr, "Failed in ExecCommon method"); - -LExit: - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - - return WcaFinalize(er); -} - -extern "C" UINT __stdcall WixSilentExec64( - __in MSIHANDLE hInstall - ) -{ - Assert(hInstall); - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - hr = WcaInitialize(hInstall, "WixSilentExec64"); - ExitOnFailure(hr, "Failed to initialize"); - - hr = ExecCommon64(WIX_SILENT64_ARGUMENTS_PROPERTY, WIX_SILENT64_TIMEOUT_PROPERTY, FALSE, FALSE); - ExitOnFailure(hr, "Failed in ExecCommon method"); - -LExit: - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - - return WcaFinalize(er); -} diff --git a/src/ca/sca.h b/src/ca/sca.h deleted file mode 100644 index 599122ff..00000000 --- a/src/ca/sca.h +++ /dev/null @@ -1,19 +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. - -// 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, -}; \ No newline at end of file diff --git a/src/ca/scacost.h b/src/ca/scacost.h deleted file mode 100644 index 5b215035..00000000 --- a/src/ca/scacost.h +++ /dev/null @@ -1,18 +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_PERFMON_REGISTER = 1000; -const UINT COST_PERFMON_UNREGISTER = 1000; - -const UINT COST_SMB_CREATESMB = 10000; -const UINT COST_SMB_DROPSMB = 5000; -const UINT COST_USER_ADD = 10000; -const UINT COST_USER_DELETE = 10000; - -const UINT COST_PERFMONMANIFEST_REGISTER = 1000; -const UINT COST_PERFMONMANIFEST_UNREGISTER = 1000; - -const UINT COST_EVENTMANIFEST_REGISTER = 1000; -const UINT COST_EVENTMANIFEST_UNREGISTER = 1000; - diff --git a/src/ca/scaexec.cpp b/src/ca/scaexec.cpp deleted file mode 100644 index 5845c1b4..00000000 --- a/src/ca/scaexec.cpp +++ /dev/null @@ -1,1082 +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" - - -/******************************************************************** - * CreateSmb - CUSTOM ACTION ENTRY POINT for creating fileshares - * - * Input: deferred CustomActionData - - * wzFsKey\twzShareDesc\twzFullPath\tfIntegratedAuth\twzUserName\tnPermissions\twzUserName\tnPermissions... - * - * ****************************************************************/ -extern "C" UINT __stdcall CreateSmb(MSIHANDLE hInstall) -{ -//AssertSz(0, "debug CreateSmb"); - UINT er = ERROR_SUCCESS; - HRESULT hr = S_OK; - - LPWSTR pwzData = NULL; - LPWSTR pwz = NULL; - LPWSTR pwzFsKey = NULL; - LPWSTR pwzShareDesc = NULL; - LPWSTR pwzDirectory = NULL; - int iAccessMode = 0; - DWORD nExPermissions = 0; - BOOL fIntegratedAuth; - LPWSTR pwzExUser = NULL; - SCA_SMBP ssp = {0}; - DWORD dwExUserPerms = 0; - DWORD dwCounter = 0; - SCA_SMBP_USER_PERMS* pUserPermsList = NULL; - - hr = WcaInitialize(hInstall, "CreateSmb"); - ExitOnFailure(hr, "failed to initialize"); - - hr = WcaGetProperty( L"CustomActionData", &pwzData); - ExitOnFailure(hr, "failed to get CustomActionData"); - - WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); - - pwz = pwzData; - hr = WcaReadStringFromCaData(&pwz, &pwzFsKey); // share name - ExitOnFailure(hr, "failed to read share name"); - hr = WcaReadStringFromCaData(&pwz, &pwzShareDesc); // share description - ExitOnFailure(hr, "failed to read share name"); - hr = WcaReadStringFromCaData(&pwz, &pwzDirectory); // full path to share - ExitOnFailure(hr, "failed to read share name"); - hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&fIntegratedAuth)); - ExitOnFailure(hr, "failed to read integrated authentication"); - - hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwExUserPerms)); - ExitOnFailure(hr, "failed to read count of permissions to set"); - if(dwExUserPerms > 0) - { - pUserPermsList = static_cast(MemAlloc(sizeof(SCA_SMBP_USER_PERMS)*dwExUserPerms, TRUE)); - ExitOnNull(pUserPermsList, hr, E_OUTOFMEMORY, "failed to allocate memory for permissions structure"); - - //Pull out all of the ExUserPerm strings - for (dwCounter = 0; dwCounter < dwExUserPerms; ++dwCounter) - { - hr = WcaReadStringFromCaData(&pwz, &pwzExUser); // user account - ExitOnFailure(hr, "failed to read user account"); - pUserPermsList[dwCounter].wzUser = pwzExUser; - pwzExUser = NULL; - - hr = WcaReadIntegerFromCaData(&pwz, &iAccessMode); - ExitOnFailure(hr, "failed to read access mode"); - pUserPermsList[dwCounter].accessMode = (ACCESS_MODE)iAccessMode; - iAccessMode = 0; - - hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&nExPermissions)); - ExitOnFailure(hr, "failed to read count of permissions"); - pUserPermsList[dwCounter].nPermissions = nExPermissions; - nExPermissions = 0; - } - } - - ssp.wzKey = pwzFsKey; - ssp.wzDescription = pwzShareDesc; - ssp.wzDirectory = pwzDirectory; - ssp.fUseIntegratedAuth = fIntegratedAuth; - ssp.dwUserPermissionCount = dwExUserPerms; - ssp.pUserPerms = pUserPermsList; - - hr = ScaEnsureSmbExists(&ssp); - MessageExitOnFailure(hr, msierrSMBFailedCreate, "failed to create share: '%ls'", pwzFsKey); - - hr = WcaProgressMessage(COST_SMB_CREATESMB, FALSE); - -LExit: - ReleaseStr(pwzFsKey); - ReleaseStr(pwzShareDesc); - ReleaseStr(pwzDirectory); - ReleaseStr(pwzData); - - if (pUserPermsList) - { - MemFree(pUserPermsList); - } - - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - return WcaFinalize(er); -} - - - -/******************************************************************** - DropSmb - CUSTOM ACTION ENTRY POINT for creating fileshares - - Input: deferred CustomActionData - wzFsKey\twzShareDesc\twzFullPath\tnPermissions\tfIntegratedAuth\twzUserName\twzPassword - - * ****************************************************************/ -extern "C" UINT __stdcall DropSmb(MSIHANDLE hInstall) -{ - //AssertSz(0, "debug DropSmb"); - UINT er = ERROR_SUCCESS; - HRESULT hr = S_OK; - - LPWSTR pwzData = NULL; - LPWSTR pwz = NULL; - LPWSTR pwzFsKey = NULL; - SCA_SMBP ssp = {0}; - - hr = WcaInitialize(hInstall, "DropSmb"); - ExitOnFailure(hr, "failed to initialize"); - - hr = WcaGetProperty( L"CustomActionData", &pwzData); - ExitOnFailure(hr, "failed to get CustomActionData"); - - WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); - - pwz = pwzData; - hr = WcaReadStringFromCaData(&pwz, &pwzFsKey); // share name - ExitOnFailure(hr, "failed to read share name"); - - ssp.wzKey = pwzFsKey; - - hr = ScaDropSmb(&ssp); - MessageExitOnFailure(hr, msierrSMBFailedDrop, "failed to delete share: '%ls'", pwzFsKey); - - hr = WcaProgressMessage(COST_SMB_DROPSMB, FALSE); - -LExit: - ReleaseStr(pwzFsKey); - ReleaseStr(pwzData); - - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - return WcaFinalize(er); -} - - -static HRESULT AddUserToGroup( - __in LPWSTR wzUser, - __in LPCWSTR wzUserDomain, - __in LPCWSTR wzGroup, - __in LPCWSTR wzGroupDomain - ) -{ - Assert(wzUser && *wzUser && wzUserDomain && wzGroup && *wzGroup && wzGroupDomain); - - HRESULT hr = S_OK; - IADsGroup *pGroup = NULL; - BSTR bstrUser = NULL; - BSTR bstrGroup = NULL; - LPCWSTR wz = NULL; - LPWSTR pwzUser = NULL; - LOCALGROUP_MEMBERS_INFO_3 lgmi; - - if (*wzGroupDomain) - { - wz = wzGroupDomain; - } - - // Try adding it to the global group first - UINT ui = ::NetGroupAddUser(wz, wzGroup, wzUser); - if (NERR_GroupNotFound == ui) - { - // Try adding it to the local group - if (wzUserDomain) - { - hr = StrAllocFormatted(&pwzUser, L"%s\\%s", wzUserDomain, wzUser); - ExitOnFailure(hr, "failed to allocate user domain string"); - } - - lgmi.lgrmi3_domainandname = (NULL == pwzUser ? wzUser : pwzUser); - ui = ::NetLocalGroupAddMembers(wz, wzGroup, 3 , reinterpret_cast(&lgmi), 1); - } - hr = HRESULT_FROM_WIN32(ui); - if (HRESULT_FROM_WIN32(ERROR_MEMBER_IN_ALIAS) == hr) // if they're already a member of the group don't report an error - hr = S_OK; - - // - // If we failed, try active directory - // - if (FAILED(hr)) - { - WcaLog(LOGMSG_VERBOSE, "Failed to add user: %ls, domain %ls to group: %ls, domain: %ls with error 0x%x. Attempting to use Active Directory", wzUser, wzUserDomain, wzGroup, wzGroupDomain, hr); - - hr = UserCreateADsPath(wzUserDomain, wzUser, &bstrUser); - ExitOnFailure(hr, "failed to create user ADsPath for user: %ls domain: %ls", wzUser, wzUserDomain); - - hr = UserCreateADsPath(wzGroupDomain, wzGroup, &bstrGroup); - ExitOnFailure(hr, "failed to create group ADsPath for group: %ls domain: %ls", wzGroup, wzGroupDomain); - - hr = ::ADsGetObject(bstrGroup,IID_IADsGroup, reinterpret_cast(&pGroup)); - ExitOnFailure(hr, "Failed to get group '%ls'.", reinterpret_cast(bstrGroup) ); - - hr = pGroup->Add(bstrUser); - if ((HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS) == hr) || (HRESULT_FROM_WIN32(ERROR_MEMBER_IN_ALIAS) == hr)) - hr = S_OK; - - ExitOnFailure(hr, "Failed to add user %ls to group '%ls'.", reinterpret_cast(bstrUser), reinterpret_cast(bstrGroup) ); - } - -LExit: - ReleaseObject(pGroup); - ReleaseBSTR(bstrUser); - ReleaseBSTR(bstrGroup); - - return hr; -} - -static HRESULT RemoveUserFromGroup( - __in LPWSTR wzUser, - __in LPCWSTR wzUserDomain, - __in LPCWSTR wzGroup, - __in LPCWSTR wzGroupDomain - ) -{ - Assert(wzUser && *wzUser && wzUserDomain && wzGroup && *wzGroup && wzGroupDomain); - - HRESULT hr = S_OK; - IADsGroup *pGroup = NULL; - BSTR bstrUser = NULL; - BSTR bstrGroup = NULL; - LPCWSTR wz = NULL; - LPWSTR pwzUser = NULL; - LOCALGROUP_MEMBERS_INFO_3 lgmi; - - if (*wzGroupDomain) - { - wz = wzGroupDomain; - } - - // Try removing it from the global group first - UINT ui = ::NetGroupDelUser(wz, wzGroup, wzUser); - if (NERR_GroupNotFound == ui) - { - // Try removing it from the local group - if (wzUserDomain) - { - hr = StrAllocFormatted(&pwzUser, L"%s\\%s", wzUserDomain, wzUser); - ExitOnFailure(hr, "failed to allocate user domain string"); - } - - lgmi.lgrmi3_domainandname = (NULL == pwzUser ? wzUser : pwzUser); - ui = ::NetLocalGroupDelMembers(wz, wzGroup, 3 , reinterpret_cast(&lgmi), 1); - } - hr = HRESULT_FROM_WIN32(ui); - - // - // If we failed, try active directory - // - if (FAILED(hr)) - { - WcaLog(LOGMSG_VERBOSE, "Failed to remove user: %ls, domain %ls from group: %ls, domain: %ls with error 0x%x. Attempting to use Active Directory", wzUser, wzUserDomain, wzGroup, wzGroupDomain, hr); - - hr = UserCreateADsPath(wzUserDomain, wzUser, &bstrUser); - ExitOnFailure(hr, "failed to create user ADsPath in order to remove user: %ls domain: %ls from a group", wzUser, wzUserDomain); - - hr = UserCreateADsPath(wzGroupDomain, wzGroup, &bstrGroup); - ExitOnFailure(hr, "failed to create group ADsPath in order to remove user from group: %ls domain: %ls", wzGroup, wzGroupDomain); - - hr = ::ADsGetObject(bstrGroup,IID_IADsGroup, reinterpret_cast(&pGroup)); - ExitOnFailure(hr, "Failed to get group '%ls'.", reinterpret_cast(bstrGroup) ); - - hr = pGroup->Remove(bstrUser); - ExitOnFailure(hr, "Failed to remove user %ls from group '%ls'.", reinterpret_cast(bstrUser), reinterpret_cast(bstrGroup) ); - } - -LExit: - ReleaseObject(pGroup); - ReleaseBSTR(bstrUser); - ReleaseBSTR(bstrGroup); - - return hr; -} - - -static HRESULT GetUserHasRight( - __in LSA_HANDLE hPolicy, - __in PSID pUserSid, - __in LPWSTR wzRight, - __out BOOL* fHasRight -) -{ - HRESULT hr = S_OK; - NTSTATUS nt = 0; - LSA_UNICODE_STRING lucPrivilege = { 0 }; - PLSA_ENUMERATION_INFORMATION rgSids = NULL; - ULONG cSids = 0; - *fHasRight = FALSE; - - lucPrivilege.Buffer = wzRight; - lucPrivilege.Length = static_cast(lstrlenW(lucPrivilege.Buffer) * sizeof(WCHAR)); - lucPrivilege.MaximumLength = (lucPrivilege.Length + 1) * sizeof(WCHAR); - - nt = ::LsaEnumerateAccountsWithUserRight(hPolicy, &lucPrivilege, reinterpret_cast(&rgSids), &cSids); - hr = HRESULT_FROM_WIN32(::LsaNtStatusToWinError(nt)); - ExitOnFailure(hr, "Failed to enumerate users for right: %ls", lucPrivilege.Buffer); - - for (DWORD i = 0; i < cSids; ++i) - { - PLSA_ENUMERATION_INFORMATION pInfo = rgSids + i; - if (::EqualSid(pUserSid, pInfo->Sid)) - { - *fHasRight = TRUE; - break; - } - } - -LExit: - if (rgSids) - { - ::LsaFreeMemory(rgSids); - } - - return hr; -} - - -static HRESULT GetExistingUserRightsAssignments( - __in_opt LPCWSTR wzDomain, - __in LPCWSTR wzName, - __inout int* iAttributes -) -{ - HRESULT hr = S_OK; - NTSTATUS nt = 0; - BOOL fHasRight = FALSE; - - LSA_HANDLE hPolicy = NULL; - LSA_OBJECT_ATTRIBUTES objectAttributes = { 0 }; - - LPWSTR pwzUser = NULL; - PSID psid = NULL; - - if (wzDomain && *wzDomain) - { - hr = StrAllocFormatted(&pwzUser, L"%s\\%s", wzDomain, wzName); - ExitOnFailure(hr, "Failed to allocate user with domain string"); - } - else - { - hr = StrAllocString(&pwzUser, wzName, 0); - ExitOnFailure(hr, "Failed to allocate string from user name."); - } - - hr = AclGetAccountSid(NULL, pwzUser, &psid); - ExitOnFailure(hr, "Failed to get SID for user: %ls", pwzUser); - - nt = ::LsaOpenPolicy(NULL, &objectAttributes, POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION, &hPolicy); - hr = HRESULT_FROM_WIN32(::LsaNtStatusToWinError(nt)); - ExitOnFailure(hr, "Failed to open LSA policy store"); - - hr = GetUserHasRight(hPolicy, psid, L"SeServiceLogonRight", &fHasRight); - ExitOnFailure(hr, "Failed to check LogonAsService right"); - - if (fHasRight) - { - *iAttributes |= SCAU_ALLOW_LOGON_AS_SERVICE; - } - - hr = GetUserHasRight(hPolicy, psid, L"SeBatchLogonRight", &fHasRight); - ExitOnFailure(hr, "Failed to check LogonAsBatchJob right"); - - if (fHasRight) - { - *iAttributes |= SCAU_ALLOW_LOGON_AS_BATCH; - } - -LExit: - if (hPolicy) - { - ::LsaClose(hPolicy); - } - - ReleaseSid(psid); - ReleaseStr(pwzUser); - return hr; -} - - -static HRESULT ModifyUserLocalServiceRight( - __in_opt LPCWSTR wzDomain, - __in LPCWSTR wzName, - __in BOOL fAdd - ) -{ - HRESULT hr = S_OK; - NTSTATUS nt = 0; - - LPWSTR pwzUser = NULL; - PSID psid = NULL; - LSA_HANDLE hPolicy = NULL; - LSA_OBJECT_ATTRIBUTES ObjectAttributes = { 0 }; - LSA_UNICODE_STRING lucPrivilege = { 0 }; - - if (wzDomain && *wzDomain) - { - hr = StrAllocFormatted(&pwzUser, L"%s\\%s", wzDomain, wzName); - ExitOnFailure(hr, "Failed to allocate user with domain string"); - } - else - { - hr = StrAllocString(&pwzUser, wzName, 0); - ExitOnFailure(hr, "Failed to allocate string from user name."); - } - - hr = AclGetAccountSid(NULL, pwzUser, &psid); - ExitOnFailure(hr, "Failed to get SID for user: %ls", pwzUser); - - nt = ::LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_ALL_ACCESS, &hPolicy); - hr = HRESULT_FROM_WIN32(::LsaNtStatusToWinError(nt)); - ExitOnFailure(hr, "Failed to open LSA policy store."); - - lucPrivilege.Buffer = L"SeServiceLogonRight"; - lucPrivilege.Length = static_cast(lstrlenW(lucPrivilege.Buffer) * sizeof(WCHAR)); - lucPrivilege.MaximumLength = (lucPrivilege.Length + 1) * sizeof(WCHAR); - - if (fAdd) - { - nt = ::LsaAddAccountRights(hPolicy, psid, &lucPrivilege, 1); - hr = HRESULT_FROM_WIN32(::LsaNtStatusToWinError(nt)); - ExitOnFailure(hr, "Failed to add 'logon as service' bit to user: %ls", pwzUser); - } - else - { - nt = ::LsaRemoveAccountRights(hPolicy, psid, FALSE, &lucPrivilege, 1); - hr = HRESULT_FROM_WIN32(::LsaNtStatusToWinError(nt)); - ExitOnFailure(hr, "Failed to remove 'logon as service' bit from user: %ls", pwzUser); - } - -LExit: - if (hPolicy) - { - ::LsaClose(hPolicy); - } - - ReleaseSid(psid); - ReleaseStr(pwzUser); - return hr; -} - - -static HRESULT ModifyUserLocalBatchRight( - __in_opt LPCWSTR wzDomain, - __in LPCWSTR wzName, - __in BOOL fAdd - ) -{ - HRESULT hr = S_OK; - NTSTATUS nt = 0; - - LPWSTR pwzUser = NULL; - PSID psid = NULL; - LSA_HANDLE hPolicy = NULL; - LSA_OBJECT_ATTRIBUTES ObjectAttributes = { 0 }; - LSA_UNICODE_STRING lucPrivilege = { 0 }; - - if (wzDomain && *wzDomain) - { - hr = StrAllocFormatted(&pwzUser, L"%s\\%s", wzDomain, wzName); - ExitOnFailure(hr, "Failed to allocate user with domain string"); - } - else - { - hr = StrAllocString(&pwzUser, wzName, 0); - ExitOnFailure(hr, "Failed to allocate string from user name."); - } - - hr = AclGetAccountSid(NULL, pwzUser, &psid); - ExitOnFailure(hr, "Failed to get SID for user: %ls", pwzUser); - - nt = ::LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_ALL_ACCESS, &hPolicy); - hr = HRESULT_FROM_WIN32(::LsaNtStatusToWinError(nt)); - ExitOnFailure(hr, "Failed to open LSA policy store."); - - lucPrivilege.Buffer = L"SeBatchLogonRight"; - lucPrivilege.Length = static_cast(lstrlenW(lucPrivilege.Buffer) * sizeof(WCHAR)); - lucPrivilege.MaximumLength = (lucPrivilege.Length + 1) * sizeof(WCHAR); - - if (fAdd) - { - nt = ::LsaAddAccountRights(hPolicy, psid, &lucPrivilege, 1); - hr = HRESULT_FROM_WIN32(::LsaNtStatusToWinError(nt)); - ExitOnFailure(hr, "Failed to add 'logon as batch job' bit to user: %ls", pwzUser); - } - else - { - nt = ::LsaRemoveAccountRights(hPolicy, psid, FALSE, &lucPrivilege, 1); - hr = HRESULT_FROM_WIN32(::LsaNtStatusToWinError(nt)); - ExitOnFailure(hr, "Failed to remove 'logon as batch job' bit from user: %ls", pwzUser); - } - - LExit: - if (hPolicy) - { - ::LsaClose(hPolicy); - } - - ReleaseSid(psid); - ReleaseStr(pwzUser); - return hr; -} - -static void SetUserPasswordAndAttributes( - __in USER_INFO_1* puserInfo, - __in LPWSTR wzPassword, - __in int iAttributes - ) -{ - Assert(puserInfo); - - // Set the User's password - puserInfo->usri1_password = wzPassword; - - // Apply the Attributes - if (SCAU_DONT_EXPIRE_PASSWRD & iAttributes) - { - puserInfo->usri1_flags |= UF_DONT_EXPIRE_PASSWD; - } - else - { - puserInfo->usri1_flags &= ~UF_DONT_EXPIRE_PASSWD; - } - - if (SCAU_PASSWD_CANT_CHANGE & iAttributes) - { - puserInfo->usri1_flags |= UF_PASSWD_CANT_CHANGE; - } - else - { - puserInfo->usri1_flags &= ~UF_PASSWD_CANT_CHANGE; - } - - if (SCAU_DISABLE_ACCOUNT & iAttributes) - { - puserInfo->usri1_flags |= UF_ACCOUNTDISABLE; - } - else - { - puserInfo->usri1_flags &= ~UF_ACCOUNTDISABLE; - } - - if (SCAU_PASSWD_CHANGE_REQD_ON_LOGIN & iAttributes) // TODO: for some reason this doesn't work - { - puserInfo->usri1_flags |= UF_PASSWORD_EXPIRED; - } - else - { - puserInfo->usri1_flags &= ~UF_PASSWORD_EXPIRED; - } -} - - -static HRESULT RemoveUserInternal( - LPWSTR wzGroupCaData, - LPWSTR wzDomain, - LPWSTR wzName, - int iAttributes -) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - LPWSTR pwz = NULL; - LPWSTR pwzGroup = NULL; - LPWSTR pwzGroupDomain = NULL; - LPCWSTR wz = NULL; - PDOMAIN_CONTROLLER_INFOW pDomainControllerInfo = NULL; - - // - // Remove the logon as service privilege. - // - if (SCAU_ALLOW_LOGON_AS_SERVICE & iAttributes) - { - hr = ModifyUserLocalServiceRight(wzDomain, wzName, FALSE); - if (FAILED(hr)) - { - WcaLogError(hr, "Failed to remove logon as service right from user, continuing..."); - hr = S_OK; - } - } - - if (SCAU_ALLOW_LOGON_AS_BATCH & iAttributes) - { - hr = ModifyUserLocalBatchRight(wzDomain, wzName, FALSE); - if (FAILED(hr)) - { - WcaLogError(hr, "Failed to remove logon as batch job right from user, continuing..."); - hr = S_OK; - } - } - - // - // Remove the User Account if the user was created by us. - // - if (!(SCAU_DONT_CREATE_USER & iAttributes)) - { - if (wzDomain && *wzDomain) - { - er = ::DsGetDcNameW(NULL, (LPCWSTR)wzDomain, NULL, NULL, NULL, &pDomainControllerInfo); - if (RPC_S_SERVER_UNAVAILABLE == er) - { - // MSDN says, if we get the above error code, try again with the "DS_FORCE_REDISCOVERY" flag - er = ::DsGetDcNameW(NULL, (LPCWSTR)wzDomain, NULL, NULL, DS_FORCE_REDISCOVERY, &pDomainControllerInfo); - } - if (ERROR_SUCCESS == er) - { - wz = pDomainControllerInfo->DomainControllerName + 2; //Add 2 so that we don't get the \\ prefix - } - else - { - wz = wzDomain; - } - } - - er = ::NetUserDel(wz, wzName); - if (NERR_UserNotFound == er) - { - er = NERR_Success; - } - ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "failed to delete user account: %ls", wzName); - } - else - { - // - // Remove the user from the groups - // - pwz = wzGroupCaData; - while (S_OK == (hr = WcaReadStringFromCaData(&pwz, &pwzGroup))) - { - hr = WcaReadStringFromCaData(&pwz, &pwzGroupDomain); - - if (FAILED(hr)) - { - WcaLogError(hr, "failed to get domain for group: %ls, continuing anyway.", pwzGroup); - } - else - { - hr = RemoveUserFromGroup(wzName, wzDomain, pwzGroup, pwzGroupDomain); - if (FAILED(hr)) - { - WcaLogError(hr, "failed to remove user: %ls from group %ls, continuing anyway.", wzName, pwzGroup); - } - } - } - - if (E_NOMOREITEMS == hr) // if there are no more items, all is well - { - hr = S_OK; - } - - ExitOnFailure(hr, "failed to get next group from which to remove user:%ls", wzName); - } - -LExit: - if (pDomainControllerInfo) - { - ::NetApiBufferFree(static_cast(pDomainControllerInfo)); - } - - return hr; -} - - -/******************************************************************** - CreateUser - CUSTOM ACTION ENTRY POINT for creating users - - Input: deferred CustomActionData - UserName\tDomain\tPassword\tAttributes\tGroupName\tDomain\tGroupName\tDomain... - * *****************************************************************/ -extern "C" UINT __stdcall CreateUser( - __in MSIHANDLE hInstall - ) -{ - //AssertSz(0, "Debug CreateUser"); - - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - LPWSTR pwzData = NULL; - LPWSTR pwz = NULL; - LPWSTR pwzName = NULL; - LPWSTR pwzDomain = NULL; - LPWSTR pwzScriptKey = NULL; - LPWSTR pwzPassword = NULL; - LPWSTR pwzGroup = NULL; - LPWSTR pwzGroupDomain = NULL; - PDOMAIN_CONTROLLER_INFOW pDomainControllerInfo = NULL; - int iAttributes = 0; - BOOL fInitializedCom = FALSE; - - WCA_CASCRIPT_HANDLE hRollbackScript = NULL; - int iOriginalAttributes = 0; - int iRollbackAttributes = 0; - - USER_INFO_1 userInfo; - USER_INFO_1* puserInfo = NULL; - DWORD dw; - LPCWSTR wz = NULL; - - hr = WcaInitialize(hInstall, "CreateUser"); - 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); - - // - // Read in the CustomActionData - // - pwz = pwzData; - hr = WcaReadStringFromCaData(&pwz, &pwzName); - ExitOnFailure(hr, "failed to read user name from custom action data"); - - hr = WcaReadStringFromCaData(&pwz, &pwzDomain); - ExitOnFailure(hr, "failed to read domain from custom action data"); - - hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); - ExitOnFailure(hr, "failed to read attributes from custom action data"); - - hr = WcaReadStringFromCaData(&pwz, &pwzScriptKey); - ExitOnFailure(hr, "failed to read encoding key from custom action data"); - - hr = WcaReadStringFromCaData(&pwz, &pwzPassword); - ExitOnFailure(hr, "failed to read password from custom action data"); - - // There is no rollback scheduled if the key is empty. - // Best effort to get original configuration and save it in the script so rollback can restore it. - if (*pwzScriptKey) - { - hr = WcaCaScriptCreate(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, FALSE, &hRollbackScript); - ExitOnFailure(hr, "Failed to open rollback CustomAction script."); - - iRollbackAttributes = 0; - hr = GetExistingUserRightsAssignments(pwzDomain, pwzName, &iOriginalAttributes); - if (FAILED(hr)) - { - WcaLogError(hr, "failed to get existing user rights: %ls, continuing anyway.", pwzName); - } - else - { - if (!(SCAU_ALLOW_LOGON_AS_SERVICE & iOriginalAttributes) && (SCAU_ALLOW_LOGON_AS_SERVICE & iAttributes)) - { - iRollbackAttributes |= SCAU_ALLOW_LOGON_AS_SERVICE; - } - if (!(SCAU_ALLOW_LOGON_AS_BATCH & iOriginalAttributes) && (SCAU_ALLOW_LOGON_AS_BATCH & iAttributes)) - { - iRollbackAttributes |= SCAU_ALLOW_LOGON_AS_BATCH; - } - } - - hr = WcaCaScriptWriteNumber(hRollbackScript, iRollbackAttributes); - ExitOnFailure(hr, "Failed to add data to rollback script."); - - // Nudge the system to get all our rollback data written to disk. - WcaCaScriptFlush(hRollbackScript); - } - - if (!(SCAU_DONT_CREATE_USER & iAttributes)) - { - ::ZeroMemory(&userInfo, sizeof(USER_INFO_1)); - userInfo.usri1_name = pwzName; - userInfo.usri1_priv = USER_PRIV_USER; - userInfo.usri1_flags = UF_SCRIPT; - userInfo.usri1_home_dir = NULL; - userInfo.usri1_comment = NULL; - userInfo.usri1_script_path = NULL; - - SetUserPasswordAndAttributes(&userInfo, pwzPassword, iAttributes); - - // - // Create the User - // - if (pwzDomain && *pwzDomain) - { - er = ::DsGetDcNameW( NULL, (LPCWSTR)pwzDomain, NULL, NULL, NULL, &pDomainControllerInfo ); - if (RPC_S_SERVER_UNAVAILABLE == er) - { - // MSDN says, if we get the above error code, try again with the "DS_FORCE_REDISCOVERY" flag - er = ::DsGetDcNameW( NULL, (LPCWSTR)pwzDomain, NULL, NULL, DS_FORCE_REDISCOVERY, &pDomainControllerInfo ); - } - if (ERROR_SUCCESS == er) - { - wz = pDomainControllerInfo->DomainControllerName + 2; //Add 2 so that we don't get the \\ prefix - } - else - { - wz = pwzDomain; - } - } - - er = ::NetUserAdd(wz, 1, reinterpret_cast(&userInfo), &dw); - if (NERR_UserExists == er) - { - if (SCAU_UPDATE_IF_EXISTS & iAttributes) - { - er = ::NetUserGetInfo(wz, pwzName, 1, reinterpret_cast(&puserInfo)); - if (NERR_Success == er) - { - // Change the existing user's password and attributes again then try - // to update user with this new data - SetUserPasswordAndAttributes(puserInfo, pwzPassword, iAttributes); - - er = ::NetUserSetInfo(wz, pwzName, 1, reinterpret_cast(puserInfo), &dw); - } - } - else if (!(SCAU_FAIL_IF_EXISTS & iAttributes)) - { - er = NERR_Success; - } - } - else if (NERR_PasswordTooShort == er || NERR_PasswordTooLong == er) - { - MessageExitOnFailure(hr = HRESULT_FROM_WIN32(er), msierrUSRFailedUserCreatePswd, "failed to create user: %ls due to invalid password.", pwzName); - } - MessageExitOnFailure(hr = HRESULT_FROM_WIN32(er), msierrUSRFailedUserCreate, "failed to create user: %ls", pwzName); - } - - if (SCAU_ALLOW_LOGON_AS_SERVICE & iAttributes) - { - hr = ModifyUserLocalServiceRight(pwzDomain, pwzName, TRUE); - MessageExitOnFailure(hr, msierrUSRFailedGrantLogonAsService, "Failed to grant logon as service rights to user: %ls", pwzName); - } - - if (SCAU_ALLOW_LOGON_AS_BATCH & iAttributes) - { - hr = ModifyUserLocalBatchRight(pwzDomain, pwzName, TRUE); - MessageExitOnFailure(hr, msierrUSRFailedGrantLogonAsService, "Failed to grant logon as batch job rights to user: %ls", pwzName); - } - - // - // Add the users to groups - // - while (S_OK == (hr = WcaReadStringFromCaData(&pwz, &pwzGroup))) - { - hr = WcaReadStringFromCaData(&pwz, &pwzGroupDomain); - ExitOnFailure(hr, "failed to get domain for group: %ls", pwzGroup); - - hr = AddUserToGroup(pwzName, pwzDomain, pwzGroup, pwzGroupDomain); - MessageExitOnFailure(hr, msierrUSRFailedUserGroupAdd, "failed to add user: %ls to group %ls", pwzName, pwzGroup); - } - if (E_NOMOREITEMS == hr) // if there are no more items, all is well - { - hr = S_OK; - } - ExitOnFailure(hr, "failed to get next group in which to include user:%ls", pwzName); - -LExit: - WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_PRESERVE); - - if (puserInfo) - { - ::NetApiBufferFree((LPVOID)puserInfo); - } - - if (pDomainControllerInfo) - { - ::NetApiBufferFree((LPVOID)pDomainControllerInfo); - } - - ReleaseStr(pwzData); - ReleaseStr(pwzName); - ReleaseStr(pwzDomain); - ReleaseStr(pwzScriptKey); - ReleaseStr(pwzPassword); - ReleaseStr(pwzGroup); - ReleaseStr(pwzGroupDomain); - - if (fInitializedCom) - { - ::CoUninitialize(); - } - - if (SCAU_NON_VITAL & iAttributes) - { - er = ERROR_SUCCESS; - } - else if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - - return WcaFinalize(er); -} - - -/******************************************************************** - CreateUserRollback - CUSTOM ACTION ENTRY POINT for CreateUser rollback - - * *****************************************************************/ -extern "C" UINT __stdcall CreateUserRollback( - MSIHANDLE hInstall -) -{ - //AssertSz(0, "Debug CreateUserRollback"); - - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - LPWSTR pwzData = NULL; - LPWSTR pwz = NULL; - LPWSTR pwzName = NULL; - LPWSTR pwzDomain = NULL; - LPWSTR pwzScriptKey = NULL; - int iAttributes = 0; - BOOL fInitializedCom = FALSE; - - WCA_CASCRIPT_HANDLE hRollbackScript = NULL; - LPWSTR pwzRollbackData = NULL; - int iOriginalAttributes = 0; - - hr = WcaInitialize(hInstall, "CreateUserRollback"); - 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); - - // - // Read in the CustomActionData - // - pwz = pwzData; - hr = WcaReadStringFromCaData(&pwz, &pwzScriptKey); - ExitOnFailure(hr, "failed to read encoding key from custom action data"); - - hr = WcaReadStringFromCaData(&pwz, &pwzName); - ExitOnFailure(hr, "failed to read name from custom action data"); - - hr = WcaReadStringFromCaData(&pwz, &pwzDomain); - ExitOnFailure(hr, "failed to read domain from custom action data"); - - hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); - ExitOnFailure(hr, "failed to read attributes from custom action data"); - - // Best effort to read original configuration from CreateUser. - hr = WcaCaScriptOpen(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, &hRollbackScript); - if (FAILED(hr)) - { - WcaLogError(hr, "Failed to open rollback CustomAction script, continuing anyway."); - } - else - { - hr = WcaCaScriptReadAsCustomActionData(hRollbackScript, &pwzRollbackData); - if (FAILED(hr)) - { - WcaLogError(hr, "Failed to read rollback script into CustomAction data, continuing anyway."); - } - else - { - WcaLog(LOGMSG_TRACEONLY, "Rollback Data: %ls", pwzRollbackData); - - pwz = pwzRollbackData; - hr = WcaReadIntegerFromCaData(&pwz, &iOriginalAttributes); - if (FAILED(hr)) - { - WcaLogError(hr, "failed to read attributes from rollback data, continuing anyway"); - } - else - { - iAttributes |= iOriginalAttributes; - } - } - } - - hr = RemoveUserInternal(pwz, pwzDomain, pwzName, iAttributes); - -LExit: - WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_DELETE); - - ReleaseStr(pwzData); - ReleaseStr(pwzName); - ReleaseStr(pwzDomain); - ReleaseStr(pwzScriptKey); - ReleaseStr(pwzRollbackData); - - if (fInitializedCom) - { - ::CoUninitialize(); - } - - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - - return WcaFinalize(er); -} - - -/******************************************************************** - RemoveUser - CUSTOM ACTION ENTRY POINT for removing users - - Input: deferred CustomActionData - Name\tDomain - * *****************************************************************/ -extern "C" UINT __stdcall RemoveUser( - MSIHANDLE hInstall -) -{ - //AssertSz(0, "Debug RemoveUser"); - - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - LPWSTR pwzData = NULL; - LPWSTR pwz = NULL; - LPWSTR pwzName = NULL; - LPWSTR pwzDomain = NULL; - int iAttributes = 0; - BOOL fInitializedCom = FALSE; - - hr = WcaInitialize(hInstall, "RemoveUser"); - 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); - - // - // Read in the CustomActionData - // - pwz = pwzData; - hr = WcaReadStringFromCaData(&pwz, &pwzName); - ExitOnFailure(hr, "failed to read name from custom action data"); - - hr = WcaReadStringFromCaData(&pwz, &pwzDomain); - ExitOnFailure(hr, "failed to read domain from custom action data"); - - hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); - ExitOnFailure(hr, "failed to read attributes from custom action data"); - - hr = RemoveUserInternal(pwz, pwzDomain, pwzName, iAttributes); - -LExit: - ReleaseStr(pwzData); - ReleaseStr(pwzName); - ReleaseStr(pwzDomain); - - if (fInitializedCom) - { - ::CoUninitialize(); - } - - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - - return WcaFinalize(er); -} diff --git a/src/ca/scamanifest.cpp b/src/ca/scamanifest.cpp deleted file mode 100644 index adb8d3d3..00000000 --- a/src/ca/scamanifest.cpp +++ /dev/null @@ -1,377 +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 vcsPerfmonManifestQuery = L"SELECT `Component_`, `File`, `ResourceFileDirectory` FROM `Wix4PerfmonManifest`"; -LPCWSTR vcsEventManifestQuery = L"SELECT `Component_`, `File` FROM `Wix4EventManifest`"; -enum ePerfMonManifestQuery { pfmComponent = 1, pfmFile, pfmResourceFileDir }; -enum eEventManifestQuery { emComponent = 1, emFile}; - -BOOL IsVistaOrAbove() -{ - OSVERSIONINFO osvi; - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - #pragma warning(suppress: 4996) //TODO: use non-deprecated function to check OS version - if (!::GetVersionEx(&osvi)) - { - return false; - } - return osvi.dwMajorVersion >= 6; -} - - -/******************************************************************** - ConfigurePerfmonManifestRegister - CUSTOM ACTION ENTRY POINT for scheduling - Perfmon counter manifest registering - -********************************************************************/ -extern "C" UINT __stdcall ConfigurePerfmonManifestRegister( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr; - UINT er = ERROR_SUCCESS; - - PMSIHANDLE hView, hRec; - LPWSTR pwzData = NULL, pwzResourceFilePath = NULL, pwzFile = NULL, pwzCommand = NULL; - INSTALLSTATE isInstalled, isAction; - - hr = WcaInitialize(hInstall, "ConfigurePerfmonManifestReg"); - ExitOnFailure(hr, "Failed to initialize"); - - if (!IsVistaOrAbove()) - { - WcaLog(LOGMSG_VERBOSE, "Skipping ConfigurePerfmonManifestRegister() because the target system does not support perfmon manifest"); - ExitFunction1(hr = S_FALSE); - } - // check to see if necessary tables are specified - if (S_OK != WcaTableExists(L"Wix4PerfmonManifest")) - { - WcaLog(LOGMSG_VERBOSE, "Skipping ConfigurePerfmonManifestRegister() because Wix4PerfmonManifest table not present"); - ExitFunction1(hr = S_FALSE); - } - - hr = WcaOpenExecuteView(vcsPerfmonManifestQuery, &hView); - ExitOnFailure(hr, "failed to open view on PerfMonManifest table"); - while ((hr = WcaFetchRecord(hView, &hRec)) == S_OK) - { - // get component install state - hr = WcaGetRecordString(hRec, pfmComponent, &pwzData); - ExitOnFailure(hr, "failed to get Component for PerfMonManifest"); - er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); - hr = HRESULT_FROM_WIN32(er); - ExitOnFailure(hr, "failed to get Component state for PerfMonManifest"); - if (!WcaIsInstalling(isInstalled, isAction)) - { - continue; - } - - hr = WcaGetRecordFormattedString(hRec, pfmFile, &pwzFile); - ExitOnFailure(hr, "failed to get File for PerfMonManifest"); - - hr = WcaGetRecordFormattedString(hRec, pfmResourceFileDir, &pwzResourceFilePath); - ExitOnFailure(hr, "failed to get ApplicationIdentity for PerfMonManifest"); - size_t iResourcePath = lstrlenW(pwzResourceFilePath); - if ( iResourcePath > 0 && *(pwzResourceFilePath + iResourcePath -1) == L'\\') - *(pwzResourceFilePath + iResourcePath -1) = 0; //remove the trailing '\' - - hr = StrAllocFormatted(&pwzCommand, L"\"unlodctr.exe\" /m:\"%s\"", pwzFile); - ExitOnFailure(hr, "failed to copy string in PerfMonManifest"); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackRegisterPerfmonManifest"), pwzCommand, COST_PERFMONMANIFEST_UNREGISTER); - ExitOnFailure(hr, "failed to schedule RollbackRegisterPerfmonManifest action"); - - if ( *pwzResourceFilePath ) - { - hr = StrAllocFormatted(&pwzCommand, L"\"lodctr.exe\" /m:\"%s\" \"%s\"", pwzFile, pwzResourceFilePath); - ExitOnFailure(hr, "failed to copy string in PerfMonManifest"); - } - else - { - hr = StrAllocFormatted(&pwzCommand, L"\"lodctr.exe\" /m:\"%s\"", pwzFile); - ExitOnFailure(hr, "failed to copy string in PerfMonManifest"); - } - - WcaLog(LOGMSG_VERBOSE, "RegisterPerfmonManifest's CustomActionData: '%ls'", pwzCommand); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RegisterPerfmonManifest"), pwzCommand, COST_PERFMONMANIFEST_REGISTER); - ExitOnFailure(hr, "failed to schedule RegisterPerfmonManifest action"); - } - - if (hr == E_NOMOREITEMS) - { - hr = S_OK; - } - ExitOnFailure(hr, "Failure while processing PerfMonManifest"); - - hr = S_OK; - -LExit: - ReleaseStr(pwzData); - ReleaseStr(pwzResourceFilePath); - ReleaseStr(pwzFile); - ReleaseStr(pwzCommand); - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - -/******************************************************************** - ConfigurePerfmonUninstall - CUSTOM ACTION ENTRY POINT for uninstalling - Perfmon counters - -********************************************************************/ -extern "C" UINT __stdcall ConfigurePerfmonManifestUnregister( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr; - UINT er = ERROR_SUCCESS; - - PMSIHANDLE hView, hRec; - LPWSTR pwzData = NULL, pwzResourceFilePath = NULL, pwzFile = NULL, pwzCommand = NULL; - INSTALLSTATE isInstalled, isAction; - - hr = WcaInitialize(hInstall, "ConfigurePerfmonManifestUnreg"); - ExitOnFailure(hr, "Failed to initialize"); - - if (!IsVistaOrAbove()) - { - WcaLog(LOGMSG_VERBOSE, "Skipping ConfigurePerfmonManifestUnregister() because the target system does not support perfmon manifest"); - ExitFunction1(hr = S_FALSE); - } - // check to see if necessary tables are specified - if (WcaTableExists(L"Wix4PerfmonManifest") != S_OK) - { - WcaLog(LOGMSG_VERBOSE, "Skipping ConfigurePerfmonManifestUnregister() because Wix4PerfmonManifest table not present"); - ExitFunction1(hr = S_FALSE); - } - - hr = WcaOpenExecuteView(vcsPerfmonManifestQuery, &hView); - ExitOnFailure(hr, "failed to open view on Wix4PerfmonManifest table"); - while ((hr = WcaFetchRecord(hView, &hRec)) == S_OK) - { - // get component install state - hr = WcaGetRecordString(hRec, pfmComponent, &pwzData); - ExitOnFailure(hr, "failed to get Component for Wix4PerfmonManifest"); - er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); - hr = HRESULT_FROM_WIN32(er); - ExitOnFailure(hr, "failed to get Component state for Wix4PerfmonManifest"); - if (!WcaIsUninstalling(isInstalled, isAction)) - { - continue; - } - - hr = WcaGetRecordFormattedString(hRec, pfmFile, &pwzFile); - ExitOnFailure(hr, "failed to get File for Wix4PerfmonManifest"); - - hr = WcaGetRecordFormattedString(hRec, pfmResourceFileDir, &pwzResourceFilePath); - ExitOnFailure(hr, "failed to get ApplicationIdentity for Wix4PerfmonManifest"); - size_t iResourcePath = lstrlenW(pwzResourceFilePath); - if ( iResourcePath > 0 && *(pwzResourceFilePath + iResourcePath -1) == L'\\') - *(pwzResourceFilePath + iResourcePath -1) = 0; //remove the trailing '\' - - hr = StrAllocFormatted(&pwzCommand, L"\"lodctr.exe\" /m:\"%s\" \"%s\"", pwzFile, pwzResourceFilePath); - ExitOnFailure(hr, "failed to copy string in Wix4PerfmonManifest"); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackUnregisterPerfmonManifest"), pwzCommand, COST_PERFMONMANIFEST_REGISTER); - ExitOnFailure(hr, "failed to schedule RollbackUnregisterPerfmonManifest action"); - - hr = StrAllocFormatted(&pwzCommand, L"\"unlodctr.exe\" /m:\"%s\"", pwzFile); - ExitOnFailure(hr, "failed to copy string in PerfMonManifest"); - - WcaLog(LOGMSG_VERBOSE, "UnRegisterPerfmonManifest's CustomActionData: '%ls'", pwzCommand); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"UnregisterPerfmonManifest"), pwzCommand, COST_PERFMONMANIFEST_UNREGISTER); - ExitOnFailure(hr, "failed to schedule UnregisterPerfmonManifest action"); - } - - if (hr == E_NOMOREITEMS) - { - hr = S_OK; - } - ExitOnFailure(hr, "Failure while processing PerfMonManifest"); - - hr = S_OK; - -LExit: - ReleaseStr(pwzData); - ReleaseStr(pwzResourceFilePath); - ReleaseStr(pwzFile); - ReleaseStr(pwzCommand); - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - -/******************************************************************** - ConfigureEventManifestRegister - CUSTOM ACTION ENTRY POINT for scheduling - Event manifest registering - -********************************************************************/ -extern "C" UINT __stdcall ConfigureEventManifestRegister( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr; - UINT er = ERROR_SUCCESS; - - PMSIHANDLE hView, hRec; - LPWSTR pwzData = NULL, pwzFile = NULL, pwzCommand = NULL; - INSTALLSTATE isInstalled, isAction; - - hr = WcaInitialize(hInstall, "ConfigureEventManifestReg"); - ExitOnFailure(hr, "Failed to initialize"); - - if (!IsVistaOrAbove()) - { - WcaLog(LOGMSG_VERBOSE, "Skipping ConfigureEventManifestRegister() because the target system does not support event manifest"); - ExitFunction1(hr = S_FALSE); - } - // check to see if necessary tables are specified - if (S_OK != WcaTableExists(L"Wix4EventManifest")) - { - WcaLog(LOGMSG_VERBOSE, "Skipping ConfigureEventManifestRegister() because Wix4EventManifest table not present"); - ExitFunction1(hr = S_FALSE); - } - - hr = WcaOpenExecuteView(vcsEventManifestQuery, &hView); - ExitOnFailure(hr, "failed to open view on Wix4EventManifest table"); - while ((hr = WcaFetchRecord(hView, &hRec)) == S_OK) - { - // get component install state - hr = WcaGetRecordString(hRec, emComponent, &pwzData); - ExitOnFailure(hr, "failed to get Component for Wix4EventManifest"); - er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); - hr = HRESULT_FROM_WIN32(er); - ExitOnFailure(hr, "failed to get Component state for Wix4EventManifest"); - if (!WcaIsInstalling(isInstalled, isAction)) - { - continue; - } - - hr = WcaGetRecordFormattedString(hRec, emFile, &pwzFile); - ExitOnFailure(hr, "failed to get File for Wix4EventManifest"); - - hr = StrAllocFormatted(&pwzCommand, L"\"wevtutil.exe\" um \"%s\"", pwzFile); - ExitOnFailure(hr, "failed to copy string in Wix4EventManifest"); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackRegisterEventManifest"), pwzCommand, COST_PERFMONMANIFEST_UNREGISTER); - ExitOnFailure(hr, "failed to schedule RollbackRegisterEventManifest action"); - - hr = StrAllocFormatted(&pwzCommand, L"\"wevtutil.exe\" im \"%s\"", pwzFile); - ExitOnFailure(hr, "failed to copy string in Wix4EventManifest"); - WcaLog(LOGMSG_VERBOSE, "RegisterEventManifest's CustomActionData: '%ls'", pwzCommand); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RegisterEventManifest"), pwzCommand, COST_EVENTMANIFEST_REGISTER); - ExitOnFailure(hr, "failed to schedule RegisterEventManifest action"); - } - - if (hr == E_NOMOREITEMS) - { - hr = S_OK; - } - ExitOnFailure(hr, "Failure while processing Wix4EventManifest"); - - hr = S_OK; - -LExit: - ReleaseStr(pwzData); - ReleaseStr(pwzFile); - ReleaseStr(pwzCommand); - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - - -/******************************************************************** - ConfigureEventManifestRegister - CUSTOM ACTION ENTRY POINT for scheduling - Event manifest registering - -********************************************************************/ -extern "C" UINT __stdcall ConfigureEventManifestUnregister( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr; - UINT er = ERROR_SUCCESS; - - PMSIHANDLE hView, hRec; - LPWSTR pwzData = NULL, pwzFile = NULL, pwzCommand = NULL; - INSTALLSTATE isInstalled, isAction; - - hr = WcaInitialize(hInstall, "ConfigureEventManifestUnreg"); - ExitOnFailure(hr, "Failed to initialize"); - - if (!IsVistaOrAbove()) - { - WcaLog(LOGMSG_VERBOSE, "Skipping ConfigureEventManifestUnregister() because the target system does not support event manifest"); - ExitFunction1(hr = S_FALSE); - } - // check to see if necessary tables are specified - if (S_OK != WcaTableExists(L"Wix4EventManifest")) - { - WcaLog(LOGMSG_VERBOSE, "Skipping ConfigureEventManifestUnregister() because Wix4EventManifest table not present"); - ExitFunction1(hr = S_FALSE); - } - - hr = WcaOpenExecuteView(vcsEventManifestQuery, &hView); - ExitOnFailure(hr, "failed to open view on Wix4EventManifest table"); - while ((hr = WcaFetchRecord(hView, &hRec)) == S_OK) - { - // get component install state - hr = WcaGetRecordString(hRec, emComponent, &pwzData); - ExitOnFailure(hr, "failed to get Component for Wix4EventManifest"); - er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); - hr = HRESULT_FROM_WIN32(er); - ExitOnFailure(hr, "failed to get Component state for Wix4EventManifest"); - - // nothing to do on an install - // schedule the rollback action when reinstalling to re-register pre-patch manifest - if (!WcaIsUninstalling(isInstalled, isAction) && !WcaIsReInstalling(isInstalled, isAction)) - { - continue; - } - - hr = WcaGetRecordFormattedString(hRec, emFile, &pwzFile); - ExitOnFailure(hr, "failed to get File for Wix4EventManifest"); - - hr = StrAllocFormatted(&pwzCommand, L"\"wevtutil.exe\" im \"%s\"", pwzFile); - ExitOnFailure(hr, "failed to copy string in Wix4EventManifest"); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackUnregisterEventManifest"), pwzCommand, COST_PERFMONMANIFEST_REGISTER); - ExitOnFailure(hr, "failed to schedule RollbackUnregisterEventManifest action"); - - // no need to uninstall on a repair/patch. Register action will re-register and update the manifest. - if (!WcaIsReInstalling(isInstalled, isAction)) - { - hr = StrAllocFormatted(&pwzCommand, L"\"wevtutil.exe\" um \"%s\"", pwzFile); - ExitOnFailure(hr, "failed to copy string in Wix4EventManifest"); - WcaLog(LOGMSG_VERBOSE, "UnregisterEventManifest's CustomActionData: '%ls'", pwzCommand); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"UnregisterEventManifest"), pwzCommand, COST_PERFMONMANIFEST_UNREGISTER); - ExitOnFailure(hr, "failed to schedule UnregisterEventManifest action"); - } - } - - if (hr == E_NOMOREITEMS) - { - hr = S_OK; - } - ExitOnFailure(hr, "Failure while processing Wix4EventManifest"); - - hr = S_OK; - -LExit: - ReleaseStr(pwzData); - ReleaseStr(pwzFile); - ReleaseStr(pwzCommand); - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - diff --git a/src/ca/scaperf.cpp b/src/ca/scaperf.cpp deleted file mode 100644 index fd301278..00000000 --- a/src/ca/scaperf.cpp +++ /dev/null @@ -1,310 +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 vcsPerfCounterDataQuery = L"SELECT `Wix4PerformanceCategory`, `Component_`, `Name`, `IniData`, `ConstantData` FROM `Wix4PerformanceCategory`"; -enum ePerfCounterDataQuery { pcdqId = 1, pcdqComponent, pcdqName, pcdqIniData, pcdqConstantData }; - -LPCWSTR vcsPerfMonQuery = L"SELECT `Component_`, `File`, `Name` FROM `Wix4Perfmon`"; -enum ePerfMonQuery { pmqComponent = 1, pmqFile, pmqName }; - - -static HRESULT ProcessPerformanceCategory( - __in MSIHANDLE hInstall, - __in BOOL fInstall - ); - - -/******************************************************************** - InstallPerfCounterData - CUSTOM ACTION ENTRY POINT for installing - Performance Counters. - -********************************************************************/ -extern "C" UINT __stdcall InstallPerfCounterData( - __in MSIHANDLE hInstall - ) -{ - // AssertSz(FALSE, "debug InstallPerfCounterData{}"); - HRESULT hr; - UINT er = ERROR_SUCCESS; - - hr = WcaInitialize(hInstall, "InstallPerfCounterData"); - ExitOnFailure(hr, "Failed to initialize InstallPerfCounterData."); - - hr = ProcessPerformanceCategory(hInstall, TRUE); - MessageExitOnFailure(hr, msierrInstallPerfCounterData, "Failed to process Wix4PerformanceCategory table."); - -LExit: - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - -/******************************************************************** - UninstallPerfCounterData - CUSTOM ACTION ENTRY POINT for installing - Performance Counters. - -********************************************************************/ -extern "C" UINT __stdcall UninstallPerfCounterData( - __in MSIHANDLE hInstall - ) -{ - // AssertSz(FALSE, "debug UninstallPerfCounterData{}"); - HRESULT hr; - UINT er = ERROR_SUCCESS; - - hr = WcaInitialize(hInstall, "UninstallPerfCounterData"); - ExitOnFailure(hr, "Failed to initialize UninstallPerfCounterData."); - - hr = ProcessPerformanceCategory(hInstall, FALSE); - MessageExitOnFailure(hr, msierrUninstallPerfCounterData, "Failed to process Wix4PerformanceCategory table."); - -LExit: - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - -/******************************************************************** - RegisterPerfmon - CUSTOM ACTION ENTRY POINT for installing Perfmon counters - -********************************************************************/ -extern "C" UINT __stdcall ConfigurePerfmonInstall( - __in MSIHANDLE hInstall - ) -{ -// Assert(FALSE); - HRESULT hr; - UINT er = ERROR_SUCCESS; - - PMSIHANDLE hView, hRec; - LPWSTR pwzData = NULL, pwzName = NULL, pwzFile = NULL; - INSTALLSTATE isInstalled, isAction; - - hr = WcaInitialize(hInstall, "ConfigurePerfmonInstall"); - ExitOnFailure(hr, "Failed to initialize"); - - // check to see if necessary tables are specified - if (S_OK != WcaTableExists(L"Wix4Perfmon")) - { - WcaLog(LOGMSG_VERBOSE, "Skipping RegisterPerfmon() because Wix4Perfmon table not present"); - ExitFunction1(hr = S_FALSE); - } - - hr = WcaOpenExecuteView(vcsPerfMonQuery, &hView); - ExitOnFailure(hr, "failed to open view on PerfMon table"); - while ((hr = WcaFetchRecord(hView, &hRec)) == S_OK) - { - // get component install state - hr = WcaGetRecordString(hRec, pmqComponent, &pwzData); - ExitOnFailure(hr, "failed to get Component for PerfMon"); - er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); - hr = HRESULT_FROM_WIN32(er); - ExitOnFailure(hr, "failed to get Component state for PerfMon"); - if (!WcaIsInstalling(isInstalled, isAction)) - { - continue; - } - - hr = WcaGetRecordString(hRec, pmqName, &pwzName); - ExitOnFailure(hr, "failed to get Name for PerfMon"); - - hr = WcaGetRecordFormattedString(hRec, pmqFile, &pwzFile); - ExitOnFailure(hr, "failed to get File for PerfMon"); - - WcaLog(LOGMSG_VERBOSE, "ConfigurePerfmonInstall's CustomActionData: '%ls', '%ls'", pwzName, pwzFile); - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RegisterPerfmon"), pwzFile, COST_PERFMON_REGISTER); - ExitOnFailure(hr, "failed to schedule RegisterPerfmon action"); - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackRegisterPerfmon"), pwzName, COST_PERFMON_UNREGISTER); - ExitOnFailure(hr, "failed to schedule RollbackRegisterPerfmon action"); - } - - if (hr == E_NOMOREITEMS) - { - hr = S_OK; - } - ExitOnFailure(hr, "Failure while processing PerfMon"); - - hr = S_OK; - -LExit: - ReleaseStr(pwzData); - ReleaseStr(pwzName); - ReleaseStr(pwzFile); - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - -/******************************************************************** - ConfigurePerfmonUninstall - CUSTOM ACTION ENTRY POINT for uninstalling - Perfmon counters - -********************************************************************/ -extern "C" UINT __stdcall ConfigurePerfmonUninstall( - __in MSIHANDLE hInstall - ) -{ -// Assert(FALSE); - HRESULT hr; - UINT er = ERROR_SUCCESS; - - PMSIHANDLE hView, hRec; - LPWSTR pwzData = NULL, pwzName = NULL, pwzFile = NULL; - INSTALLSTATE isInstalled, isAction; - - hr = WcaInitialize(hInstall, "ConfigurePerfmonUninstall"); - ExitOnFailure(hr, "Failed to initialize"); - - // check to see if necessary tables are specified - if (WcaTableExists(L"Wix4Perfmon") != S_OK) - { - WcaLog(LOGMSG_VERBOSE, "Skipping UnregisterPerfmon() because Wix4Perfmon table not present"); - ExitFunction1(hr = S_FALSE); - } - - hr = WcaOpenExecuteView(vcsPerfMonQuery, &hView); - ExitOnFailure(hr, "failed to open view on PerfMon table"); - while ((hr = WcaFetchRecord(hView, &hRec)) == S_OK) - { - // get component install state - hr = WcaGetRecordString(hRec, pmqComponent, &pwzData); - ExitOnFailure(hr, "failed to get Component for PerfMon"); - er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); - hr = HRESULT_FROM_WIN32(er); - ExitOnFailure(hr, "failed to get Component state for PerfMon"); - if (!WcaIsUninstalling(isInstalled, isAction)) - { - continue; - } - - hr = WcaGetRecordString(hRec, pmqName, &pwzName); - ExitOnFailure(hr, "failed to get Name for PerfMon"); - - hr = WcaGetRecordFormattedString(hRec, pmqFile, &pwzFile); - ExitOnFailure(hr, "failed to get File for PerfMon"); - - WcaLog(LOGMSG_VERBOSE, "ConfigurePerfmonUninstall's CustomActionData: '%ls', '%ls'", pwzName, pwzFile); - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"UnregisterPerfmon"), pwzName, COST_PERFMON_UNREGISTER); - ExitOnFailure(hr, "failed to schedule UnregisterPerfmon action"); - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackUnregisterPerfmon"), pwzFile, COST_PERFMON_REGISTER); - ExitOnFailure(hr, "failed to schedule RollbackUnregisterPerfmon action"); - } - - if (hr == E_NOMOREITEMS) - { - hr = S_OK; - } - ExitOnFailure(hr, "Failure while processing PerfMon"); - - hr = S_OK; - -LExit: - ReleaseStr(pwzData); - ReleaseStr(pwzName); - ReleaseStr(pwzFile); - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - - -static HRESULT ProcessPerformanceCategory( - __in MSIHANDLE hInstall, - __in BOOL fInstall - ) -{ - HRESULT hr = S_OK; - DWORD er = ERROR_SUCCESS; - - PMSIHANDLE hView, hRec; - LPWSTR pwzId = NULL; - LPWSTR pwzComponent = NULL; - LPWSTR pwzName = NULL; - LPWSTR pwzData = NULL; - INSTALLSTATE isInstalled, isAction; - - LPWSTR pwzCustomActionData = NULL; - - // check to see if necessary tables are specified - if (S_OK != WcaTableExists(L"Wix4PerformanceCategory")) - { - ExitFunction1(hr = S_FALSE); - } - - hr = WcaOpenExecuteView(vcsPerfCounterDataQuery, &hView); - ExitOnFailure(hr, "failed to open view on Wix4PerformanceCategory table"); - while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) - { - hr = WcaGetRecordString(hRec, pcdqId, &pwzId); - ExitOnFailure(hr, "Failed to get id for Wix4PerformanceCategory."); - - // Check to see if the Component is being installed or uninstalled - // when we are processing the same. - hr = WcaGetRecordString(hRec, pcdqComponent, &pwzComponent); - ExitOnFailure(hr, "Failed to get Component for Wix4PerformanceCategory: %ls", pwzId); - - er = ::MsiGetComponentStateW(hInstall, pwzComponent, &isInstalled, &isAction); - hr = HRESULT_FROM_WIN32(er); - ExitOnFailure(hr, "Failed to get Component state for Wix4PerformanceCategory: %ls", pwzId); - - if ((fInstall && !WcaIsInstalling(isInstalled, isAction)) || - (!fInstall && !WcaIsUninstalling(isInstalled, isAction))) - { - continue; - } - - hr = WcaGetRecordString(hRec, pcdqName, &pwzName); - ExitOnFailure(hr, "Failed to get Name for Wix4PerformanceCategory: %ls", pwzId); - hr = WcaWriteStringToCaData(pwzName, &pwzCustomActionData); - ExitOnFailure(hr, "Failed to add Name to CustomActionData for Wix4PerformanceCategory: %ls", pwzId); - - hr = WcaGetRecordString(hRec, pcdqIniData, &pwzData); - ExitOnFailure(hr, "Failed to get IniData for Wix4PerformanceCategory: %ls", pwzId); - hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); - ExitOnFailure(hr, "Failed to add IniData to CustomActionData for Wix4PerformanceCategory: %ls", pwzId); - - hr = WcaGetRecordString(hRec, pcdqConstantData, &pwzData); - ExitOnFailure(hr, "Failed to get ConstantData for Wix4PerformanceCategory: %ls", pwzId); - hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); - ExitOnFailure(hr, "Failed to add ConstantData to CustomActionData for Wix4PerformanceCategory: %ls", pwzId); - } - - if (hr == E_NOMOREITEMS) - { - hr = S_OK; - } - ExitOnFailure(hr, "Failure while processing Wix4PerformanceCategory table."); - - // If there was any data built up, schedule it for execution. - if (pwzCustomActionData) - { - if (fInstall) - { - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackRegisterPerfCounterData"), pwzCustomActionData, COST_PERFMON_UNREGISTER); - ExitOnFailure(hr, "Failed to schedule RollbackRegisterPerfCounterData action for Wix4PerformanceCategory: %ls", pwzId); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RegisterPerfCounterData"), pwzCustomActionData, COST_PERFMON_REGISTER); - ExitOnFailure(hr, "Failed to schedule RegisterPerfCounterData action for Wix4PerformanceCategory: %ls", pwzId); - } - else - { - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackUnregisterPerfCounterData"), pwzCustomActionData, COST_PERFMON_REGISTER); - ExitOnFailure(hr, "Failed to schedule RollbackUnregisterPerfCounterData action for Wix4PerformanceCategory: %ls", pwzId); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"UnregisterPerfCounterData"), pwzCustomActionData, COST_PERFMON_UNREGISTER); - ExitOnFailure(hr, "Failed to schedule UnregisterPerfCounterData action for Wix4PerformanceCategory: %ls", pwzId); - } - } - -LExit: - ReleaseStr(pwzCustomActionData); - ReleaseStr(pwzData); - ReleaseStr(pwzName); - ReleaseStr(pwzComponent); - ReleaseStr(pwzId); - - return hr; -} diff --git a/src/ca/scaperfexec.cpp b/src/ca/scaperfexec.cpp deleted file mode 100644 index c5425754..00000000 --- a/src/ca/scaperfexec.cpp +++ /dev/null @@ -1,423 +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" - -typedef DWORD (STDAPICALLTYPE *PFNPERFCOUNTERTEXTSTRINGS)(LPWSTR lpCommandLine, BOOL bQuietModeArg); - -static HRESULT ExecutePerfCounterData( - __in MSIHANDLE hInstall, - __in BOOL fInstall - ); -static HRESULT CreateDataFile( - __in LPCWSTR wzTempFolder, - __in LPCWSTR wzData, - __in BOOL fIniData, - __out HANDLE *phFile, - __out_opt LPWSTR *ppwzFile - ); - - -/******************************************************************** - RegisterPerfCounterData - CUSTOM ACTION ENTRY POINT for registering - performance counters - - Input: deferred CustomActionData: wzName\twzIniData\twzConstantData\twzName\twzIniData\twzConstantData\t... -*******************************************************************/ -extern "C" UINT __stdcall RegisterPerfCounterData( - __in MSIHANDLE hInstall - ) -{ - // AssertSz(FALSE, "debug RegisterPerfCounterData()"); - HRESULT hr = S_OK; - DWORD er = ERROR_SUCCESS; - - hr = WcaInitialize(hInstall, "RegisterPerfCounterData"); - ExitOnFailure(hr, "Failed to initialize RegisterPerfCounterData."); - - hr = ExecutePerfCounterData(hInstall, TRUE); - MessageExitOnFailure(hr, msierrInstallPerfCounterData, "Failed to execute Wix4PerformanceCategory table."); - -LExit: - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - -/******************************************************************** - UnregisterPerfCounterData - CUSTOM ACTION ENTRY POINT for registering - performance counters - - Input: deferred CustomActionData: wzName\twzIniData\twzConstantData\twzName\twzIniData\twzConstantData\t... -*******************************************************************/ -extern "C" UINT __stdcall UnregisterPerfCounterData( - __in MSIHANDLE hInstall - ) -{ - // AssertSz(FALSE, "debug UnregisterPerfCounterData()"); - HRESULT hr = S_OK; - DWORD er = ERROR_SUCCESS; - - hr = WcaInitialize(hInstall, "UnregisterPerfCounterData"); - ExitOnFailure(hr, "Failed to initialize UnregisterPerfCounterData."); - - hr = ExecutePerfCounterData(hInstall, FALSE); - MessageExitOnFailure(hr, msierrUninstallPerfCounterData, "Failed to execute Wix4PerformanceCategory table."); - -LExit: - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - -/******************************************************************** - RegisterPerfmon - CUSTOM ACTION ENTRY POINT for registering - counters - - Input: deferred CustomActionData - - wzFile or wzName -*******************************************************************/ -extern "C" UINT __stdcall RegisterPerfmon( - __in MSIHANDLE hInstall - ) -{ -// Assert(FALSE); - UINT er = ERROR_SUCCESS; - HRESULT hr = S_OK; - LPWSTR pwzData = NULL; - - HMODULE hMod = NULL; - PFNPERFCOUNTERTEXTSTRINGS pfnPerfCounterTextString; - DWORD dwRet; - LPWSTR pwzShortPath = NULL; - DWORD cchShortPath = MAX_PATH; - DWORD cchShortPathLength = 0; - - LPWSTR pwzCommand = NULL; - - hr = WcaInitialize(hInstall, "RegisterPerfmon"); - ExitOnFailure(hr, "failed to initialize"); - - hr = WcaGetProperty(L"CustomActionData", &pwzData); - ExitOnFailure(hr, "failed to get CustomActionData"); - - WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); - - // do the perfmon registration - if (NULL == hMod) - { - hr = LoadSystemLibrary(L"loadperf.dll", &hMod); - } - ExitOnFailure(hr, "failed to load DLL for PerfMon"); - - pfnPerfCounterTextString = (PFNPERFCOUNTERTEXTSTRINGS)::GetProcAddress(hMod, "LoadPerfCounterTextStringsW"); - ExitOnNullWithLastError(pfnPerfCounterTextString, hr, "failed to get DLL function for PerfMon"); - - hr = StrAlloc(&pwzShortPath, cchShortPath); - ExitOnFailure(hr, "failed to allocate string"); - - WcaLog(LOGMSG_VERBOSE, "Converting DLL path to short format: %ls", pwzData); - cchShortPathLength = ::GetShortPathNameW(pwzData, pwzShortPath, cchShortPath); - if (cchShortPathLength > cchShortPath) - { - cchShortPath = cchShortPathLength + 1; - hr = StrAlloc(&pwzShortPath, cchShortPath); - ExitOnFailure(hr, "failed to allocate string"); - - cchShortPathLength = ::GetShortPathNameW(pwzData, pwzShortPath, cchShortPath); - } - - if (0 == cchShortPathLength) - { - ExitOnLastError(hr, "failed to get short path format of path: %ls", pwzData); - } - - hr = StrAllocFormatted(&pwzCommand, L"lodctr \"%s\"", pwzShortPath); - ExitOnFailure(hr, "failed to format lodctr string"); - - WcaLog(LOGMSG_VERBOSE, "RegisterPerfmon running command: '%ls'", pwzCommand); - dwRet = (*pfnPerfCounterTextString)(pwzCommand, TRUE); - if (dwRet != ERROR_SUCCESS && dwRet != ERROR_ALREADY_EXISTS) - { - hr = HRESULT_FROM_WIN32(dwRet); - MessageExitOnFailure(hr, msierrPERFMONFailedRegisterDLL, "failed to register with PerfMon, DLL: %ls", pwzData); - } - - hr = S_OK; -LExit: - ReleaseStr(pwzData); - - if (FAILED(hr)) - er = ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - -extern "C" UINT __stdcall UnregisterPerfmon( - __in MSIHANDLE hInstall - ) -{ -// Assert(FALSE); - UINT er = ERROR_SUCCESS; - HRESULT hr = S_OK; - LPWSTR pwzData = NULL; - - HMODULE hMod = NULL; - PFNPERFCOUNTERTEXTSTRINGS pfnPerfCounterTextString; - DWORD dwRet; - WCHAR wz[255]; - - hr = WcaInitialize(hInstall, "UnregisterPerfmon"); - ExitOnFailure(hr, "failed to initialize"); - - hr = WcaGetProperty(L"CustomActionData", &pwzData); - ExitOnFailure(hr, "failed to get CustomActionData"); - - WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); - - // do the perfmon unregistration - hr = E_FAIL; - if (hMod == NULL) - { - hr = LoadSystemLibrary(L"loadperf.dll", &hMod); - } - ExitOnFailure(hr, "failed to load DLL for PerfMon"); - - pfnPerfCounterTextString = (PFNPERFCOUNTERTEXTSTRINGS)::GetProcAddress(hMod, "UnloadPerfCounterTextStringsW"); - ExitOnNullWithLastError(pfnPerfCounterTextString, hr, "failed to get DLL function for PerfMon"); - - hr = ::StringCchPrintfW(wz, countof(wz), L"unlodctr \"%s\"", pwzData); - ExitOnFailure(hr, "Failed to format unlodctr string with: %ls", pwzData); - WcaLog(LOGMSG_VERBOSE, "UnregisterPerfmon running command: '%ls'", wz); - dwRet = (*pfnPerfCounterTextString)(wz, TRUE); - // if the counters aren't registered, then OK to continue - if (dwRet != ERROR_SUCCESS && dwRet != ERROR_FILE_NOT_FOUND && dwRet != ERROR_BADKEY) - { - hr = HRESULT_FROM_WIN32(dwRet); - MessageExitOnFailure(hr, msierrPERFMONFailedUnregisterDLL, "failed to unregsister with PerfMon, DLL: %ls", pwzData); - } - - hr = S_OK; -LExit: - ReleaseStr(pwzData); - - if (FAILED(hr)) - er = ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - -static HRESULT ExecutePerfCounterData( - __in MSIHANDLE /*hInstall*/, - __in BOOL fInstall - ) -{ - HRESULT hr = S_OK; - DWORD er = ERROR_SUCCESS; - - HMODULE hModule = NULL; - PFNPERFCOUNTERTEXTSTRINGS pfnPerfCounterTextString = NULL; - LPCWSTR wzPrefix = NULL; - - LPWSTR pwzCustomActionData = NULL; - LPWSTR pwz = NULL; - - LPWSTR pwzName = NULL; - LPWSTR pwzIniData = NULL; - LPWSTR pwzConstantData = NULL; - LPWSTR pwzTempFolder = NULL; - LPWSTR pwzIniFile = NULL; - LPWSTR pwzExecute = NULL; - - HANDLE hIniData = INVALID_HANDLE_VALUE; - HANDLE hConstantData = INVALID_HANDLE_VALUE; - - // Load the system performance counter helper DLL then get the appropriate - // entrypoint out of it. Fortunately, they have the same signature so we - // can use one function pointer to point to both. - hr = LoadSystemLibrary(L"loadperf.dll", &hModule); - ExitOnFailure(hr, "failed to load DLL for PerfMon"); - - if (fInstall) - { - wzPrefix = L"lodctr"; - pfnPerfCounterTextString = (PFNPERFCOUNTERTEXTSTRINGS)::GetProcAddress(hModule, "LoadPerfCounterTextStringsW"); - } - else - { - wzPrefix = L"unlodctr"; - pfnPerfCounterTextString = (PFNPERFCOUNTERTEXTSTRINGS)::GetProcAddress(hModule, "UnloadPerfCounterTextStringsW"); - } - ExitOnNullWithLastError(pfnPerfCounterTextString, hr, "Failed to get DLL function for PerfMon"); - - // Now get the CustomActionData and execute it. - hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); - ExitOnFailure(hr, "Failed to get CustomActionData."); - - WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); - - pwz = pwzCustomActionData; - - while (S_OK == (hr = WcaReadStringFromCaData(&pwz, &pwzName))) - { - hr = WcaReadStringFromCaData(&pwz, &pwzIniData); - ExitOnFailure(hr, "Failed to read IniData from custom action data."); - - hr = WcaReadStringFromCaData(&pwz, &pwzConstantData); - ExitOnFailure(hr, "Failed to read ConstantData from custom action data."); - - if (fInstall) - { - hr = PathCreateTempDirectory(NULL, L"WIXPF%03x", 999, &pwzTempFolder); - ExitOnFailure(hr, "Failed to create temp directory."); - - hr = CreateDataFile(pwzTempFolder, pwzIniData, TRUE, &hIniData, &pwzIniFile); - ExitOnFailure(hr, "Failed to create .ini file for performance counter category: %ls", pwzName); - - hr = CreateDataFile(pwzTempFolder, pwzConstantData, FALSE, &hConstantData, NULL); - ExitOnFailure(hr, "Failed to create .h file for performance counter category: %ls", pwzName); - - hr = StrAllocFormatted(&pwzExecute, L"%s \"%s\"", wzPrefix, pwzIniFile); - ExitOnFailure(hr, "Failed to allocate string to execute."); - - // Execute the install. - er = (*pfnPerfCounterTextString)(pwzExecute, TRUE); - hr = HRESULT_FROM_WIN32(er); - ExitOnFailure(hr, "Failed to execute install of performance counter category: %ls", pwzName); - - if (INVALID_HANDLE_VALUE != hIniData) - { - ::CloseHandle(hIniData); - hIniData = INVALID_HANDLE_VALUE; - } - - if (INVALID_HANDLE_VALUE != hConstantData) - { - ::CloseHandle(hConstantData); - hConstantData = INVALID_HANDLE_VALUE; - } - - DirEnsureDelete(pwzTempFolder, TRUE, TRUE); - } - else - { - hr = StrAllocFormatted(&pwzExecute, L"%s \"%s\"", wzPrefix, pwzName); - ExitOnFailure(hr, "Failed to allocate string to execute."); - - // Execute the uninstall and if the counter isn't registered then ignore - // the error since it won't hurt anything. - er = (*pfnPerfCounterTextString)(pwzExecute, TRUE); - if (ERROR_FILE_NOT_FOUND == er || ERROR_BADKEY == er) - { - er = ERROR_SUCCESS; - } - hr = HRESULT_FROM_WIN32(er); - ExitOnFailure(hr, "Failed to execute uninstall of performance counter category: %ls", pwzName); - } - } - - if (E_NOMOREITEMS == hr) // If there are no more items, all is well - { - hr = S_OK; - } - ExitOnFailure(hr, "Failed to execute all perf counter data."); - - hr = S_OK; - -LExit: - if (INVALID_HANDLE_VALUE != hIniData) - { - ::CloseHandle(hIniData); - } - - if (INVALID_HANDLE_VALUE != hConstantData) - { - ::CloseHandle(hConstantData); - } - - ReleaseStr(pwzExecute); - ReleaseStr(pwzIniFile); - ReleaseStr(pwzTempFolder); - ReleaseStr(pwzConstantData); - ReleaseStr(pwzIniData); - ReleaseStr(pwzName); - ReleaseStr(pwzCustomActionData); - - if (hModule) - { - ::FreeLibrary(hModule); - } - - return hr; -} - - -static HRESULT CreateDataFile( - __in LPCWSTR wzTempFolder, - __in LPCWSTR wzData, - __in BOOL fIniData, - __out HANDLE *phFile, - __out_opt LPWSTR *ppwzFile - ) -{ - HRESULT hr = S_OK; - HANDLE hFile = INVALID_HANDLE_VALUE; - LPWSTR pwzFile = NULL; - LPSTR pszData = NULL; - DWORD cbData = 0; - DWORD cbWritten = 0; - - // Convert the data to UTF-8 because lodctr/unloctr - // doesn't like unicode. - hr = StrAnsiAllocString(&pszData, wzData, 0, CP_UTF8); - ExitOnFailure(hr, "Failed to covert data to ANSI."); - - cbData = lstrlenA(pszData); - - // Concatenate the paths together, open the file data file - // and dump the data in there. - hr = StrAllocString(&pwzFile, wzTempFolder, 0); - ExitOnFailure(hr, "Failed to copy temp directory name."); - - hr = StrAllocConcat(&pwzFile, L"wixperf", 0); - ExitOnFailure(hr, "Failed to add name of file."); - - hr = StrAllocConcat(&pwzFile, fIniData ? L".ini" : L".h", 0); - ExitOnFailure(hr, "Failed to add extension of file."); - - hFile = ::CreateFileW(pwzFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (INVALID_HANDLE_VALUE == hFile) - { - ExitWithLastError(hr, "Failed to open new temp file: %ls", pwzFile); - } - - if (!::WriteFile(hFile, pszData, cbData, &cbWritten, NULL)) - { - ExitWithLastError(hr, "Failed to write data to new temp file: %ls", pwzFile); - } - - if (INVALID_HANDLE_VALUE != hFile) - { - ::CloseHandle(hFile); - hFile = INVALID_HANDLE_VALUE; - } - - // Return the requested values. - *phFile = hFile; - hFile = INVALID_HANDLE_VALUE; - - if (ppwzFile) - { - *ppwzFile = pwzFile; - pwzFile = NULL; - } - -LExit: - if (INVALID_HANDLE_VALUE != hFile) - { - ::CloseHandle(hFile); - } - ReleaseStr(pszData); - ReleaseStr(pwzFile); - - return hr; -} diff --git a/src/ca/scasched.cpp b/src/ca/scasched.cpp deleted file mode 100644 index d81b1f14..00000000 --- a/src/ca/scasched.cpp +++ /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. - -#include "precomp.h" - - -/******************************************************************** -ConfigureSmb - CUSTOM ACTION ENTRY POINT for installing fileshare settings - -********************************************************************/ -extern "C" UINT __stdcall ConfigureSmbInstall( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - SCA_SMB* pssList = NULL; - - // initialize - hr = WcaInitialize(hInstall, "ConfigureSmbInstall"); - ExitOnFailure(hr, "Failed to initialize"); - - // check to see if necessary tables are specified - if (WcaTableExists(L"Wix4FileShare") != S_OK) - { - WcaLog(LOGMSG_VERBOSE, "Skipping SMB CustomAction, no Wix4FileShare table"); - ExitFunction1(hr = S_FALSE); - } - - hr = ScaSmbRead(&pssList); - ExitOnFailure(hr, "failed to read Wix4FileShare table"); - - hr = ScaSmbInstall(pssList); - ExitOnFailure(hr, "failed to install FileShares"); - -LExit: - if (pssList) - ScaSmbFreeList(pssList); - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - -/******************************************************************** -ConfigureSmb - CUSTOM ACTION ENTRY POINT for uninstalling fileshare settings - -********************************************************************/ -extern "C" UINT __stdcall ConfigureSmbUninstall( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - SCA_SMB* pssList = NULL; - - // initialize - hr = WcaInitialize(hInstall, "ConfigureSmbUninstall"); - ExitOnFailure(hr, "Failed to initialize"); - - // check to see if necessary tables are specified - if (WcaTableExists(L"Wix4FileShare") != S_OK) - { - WcaLog(LOGMSG_VERBOSE, "Skipping SMB CustomAction, no Wix4FileShare table"); - ExitFunction1(hr = S_FALSE); - } - - hr = ScaSmbRead(&pssList); - ExitOnFailure(hr, "failed to read Wix4FileShare table"); - - hr = ScaSmbUninstall(pssList); - ExitOnFailure(hr, "failed to uninstall FileShares"); - -LExit: - if (pssList) - ScaSmbFreeList(pssList); - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - -/******************************************************************** -ConfigureUsers - CUSTOM ACTION ENTRY POINT for installing users - -********************************************************************/ -extern "C" UINT __stdcall ConfigureUsers( - __in MSIHANDLE hInstall - ) -{ - //AssertSz(0, "Debug ConfigureUsers"); - - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - BOOL fInitializedCom = FALSE; - SCA_USER* psuList = NULL; - - // initialize - hr = WcaInitialize(hInstall, "ConfigureUsers"); - ExitOnFailure(hr, "Failed to initialize"); - - hr = ::CoInitialize(NULL); - ExitOnFailure(hr, "failed to initialize COM"); - fInitializedCom = TRUE; - - hr = ScaUserRead(&psuList); - ExitOnFailure(hr, "failed to read Wix4User table"); - - hr = ScaUserExecute(psuList); - ExitOnFailure(hr, "failed to add/remove User actions"); - -LExit: - if (psuList) - { - ScaUserFreeList(psuList); - } - - if (fInitializedCom) - { - ::CoUninitialize(); - } - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} \ No newline at end of file diff --git a/src/ca/scasmb.h b/src/ca/scasmb.h deleted file mode 100644 index f2a4b53c..00000000 --- a/src/ca/scasmb.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 "scauser.h" - -// structs -// Structure used to hold and extra user/permission pairs from the Wix4FileSharePermissions Table -struct SCA_SMB_EX_USER_PERMS -{ - int nPermissions; - ACCESS_MODE accessMode; - SCA_USER scau; - SCA_SMB_EX_USER_PERMS* pExUserPermsNext; -}; - -struct SCA_SMB // hungarian ss -{ - WCHAR wzId[MAX_DARWIN_KEY + 1]; - WCHAR wzShareName[MAX_DARWIN_KEY + 1]; - WCHAR wzDescription[MAX_DARWIN_COLUMN + 1]; - WCHAR wzComponent[MAX_DARWIN_KEY + 1]; - WCHAR wzDirectory[MAX_PATH + 1]; - - int nUserPermissionCount; - int nPermissions; - SCA_SMB_EX_USER_PERMS* pExUserPerms; - - INSTALLSTATE isInstalled, isAction; - - BOOL fUseIntegratedAuth; - BOOL fLegacyUserProvided; - struct SCA_USER scau; - - struct SCA_SMB* pssNext; -}; - - -#define RESERVED 0 - -// schedule prototypes -HRESULT ScaSmbRead(SCA_SMB** ppssList); -HRESULT ScaSmbExPermsRead(SCA_SMB* pss); -HRESULT ScaSmbUninstall(SCA_SMB* pssList); -HRESULT ScaSmbInstall(SCA_SMB* pssList); -void ScaSmbFreeList(SCA_SMB* pssList); diff --git a/src/ca/scasmbexec.cpp b/src/ca/scasmbexec.cpp deleted file mode 100644 index ced3aa78..00000000 --- a/src/ca/scasmbexec.cpp +++ /dev/null @@ -1,316 +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" - - -/******************************************************************** - AllocateAcl - allocate an acl and populate it with this user and - permission information user could be user or domain\user - -********************************************************************/ -HRESULT AllocateAcl(SCA_SMBP* pssp, PACL* ppACL) -{ - HRESULT hr = S_OK; - EXPLICIT_ACCESSW* pEA = NULL; - DWORD cEA = 0; - DWORD dwCounter = 0; - - PSID psid = NULL; - LPCWSTR wzUser = NULL; - DWORD nPermissions = 0; - DWORD nErrorReturn = 0; - ACCESS_MODE accessMode = NOT_USED_ACCESS; - - cEA = pssp->dwUserPermissionCount + 1; - if (cEA >= MAXSIZE_T / sizeof(EXPLICIT_ACCESSW)) - { - ExitOnFailure(hr = E_OUTOFMEMORY, "Too many user permissions to allocate: %u", cEA); - } - - pEA = static_cast(MemAlloc(cEA * sizeof(EXPLICIT_ACCESSW), TRUE)); - ExitOnNull(pEA, hr, E_OUTOFMEMORY, "failed to allocate memory for explicit access structure"); - - // figure out how big the psid is - for (dwCounter = 0; dwCounter < pssp->dwUserPermissionCount; ++dwCounter) - { - wzUser = pssp->pUserPerms[dwCounter].wzUser; - nPermissions = pssp->pUserPerms[dwCounter].nPermissions; - accessMode = pssp->pUserPerms[dwCounter].accessMode; - // - // create the appropriate SID - // - - // figure out the right user to put into the access block - if (0 == lstrcmpW(wzUser, L"Everyone")) - { - hr = AclGetWellKnownSid(WinWorldSid, &psid); - } - else if (0 == lstrcmpW(wzUser, L"Administrators")) - { - hr = AclGetWellKnownSid(WinBuiltinAdministratorsSid, &psid); - } - else if (0 == lstrcmpW(wzUser, L"LocalSystem")) - { - hr = AclGetWellKnownSid(WinLocalSystemSid, &psid); - } - else if (0 == lstrcmpW(wzUser, L"LocalService")) - { - hr = AclGetWellKnownSid(WinLocalServiceSid, &psid); - } - else if (0 == lstrcmpW(wzUser, L"NetworkService")) - { - hr = AclGetWellKnownSid(WinNetworkServiceSid, &psid); - } - else if (0 == lstrcmpW(wzUser, L"AuthenticatedUser")) - { - hr = AclGetWellKnownSid(WinAuthenticatedUserSid, &psid); - } - else if (0 == lstrcmpW(wzUser, L"Guests")) - { - hr = AclGetWellKnownSid(WinBuiltinGuestsSid, &psid); - } - else if(0 == lstrcmpW(wzUser, L"CREATOR OWNER")) - { - hr = AclGetWellKnownSid(WinCreatorOwnerSid, &psid); - } - else - { - hr = AclGetAccountSid(NULL, wzUser, &psid); - } - ExitOnFailure(hr, "failed to get sid for account: %ls", wzUser); - - // we now have a valid pSid, fill in the EXPLICIT_ACCESS - - /* Permissions options: (see sca.sdh for defined sdl options) - #define GENERIC_READ (0x80000000L) 2147483648 - #define GENERIC_WRITE (0x40000000L) 1073741824 - #define GENERIC_EXECUTE (0x20000000L) 536870912 - #define GENERIC_ALL (0x10000000L) 268435456 - */ - pEA[dwCounter].grfAccessPermissions = nPermissions; - pEA[dwCounter].grfAccessMode = accessMode; - pEA[dwCounter].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; -#pragma prefast(push) -#pragma prefast(disable:25029) - ::BuildTrusteeWithSidW(&(pEA[dwCounter].Trustee), psid); -#pragma prefast(pop) - } - - // create a new ACL that contains the ACE - *ppACL = NULL; -#pragma prefast(push) -#pragma prefast(disable:25029) - nErrorReturn = ::SetEntriesInAclW(dwCounter, pEA, NULL, ppACL); -#pragma prefast(pop) - ExitOnFailure(hr = HRESULT_FROM_WIN32(nErrorReturn), "failed to allocate ACL"); - -LExit: - if (psid) - { - AclFreeSid(psid); - } - - ReleaseMem(pEA); - - return hr; -} - - - -/******************************************************************** - FillShareInfo - fill the NetShareAdd data structure - -********************************************************************/ -void FillShareInfo(SHARE_INFO_502* psi, SCA_SMBP* pssp, PSECURITY_DESCRIPTOR pSD) -{ - psi->shi502_netname = pssp->wzKey; - psi->shi502_type = STYPE_DISKTREE; - psi->shi502_remark = pssp->wzDescription; - psi->shi502_permissions = 0; // not used - psi->shi502_max_uses = 0xFFFFFFFF; - psi->shi502_current_uses = 0; - psi->shi502_path = pssp->wzDirectory; - psi->shi502_passwd = NULL; // not file share perms - psi->shi502_reserved = 0; - psi->shi502_security_descriptor = pSD; -} - - - -/* NET_API_STATUS return codes -NERR_Success = 0 -NERR_DuplicateShare = 2118 -NERR_BufTooSmall = 2123 -NERR_NetNameNotFound = 2310 -NERR_RedirectedPath = 2117 -NERR_UnknownDevDir = 2116 -*/ - -/******************************************************************** - DoesShareExists - Does a share of this name exist on this computer? - -********************************************************************/ -HRESULT DoesShareExist(__in LPWSTR wzShareName) -{ - HRESULT hr = S_OK; - NET_API_STATUS s; - SHARE_INFO_502* psi = NULL; - s = ::NetShareGetInfo(NULL, wzShareName, 502, (BYTE**) &psi); - - switch (s) - { - case NERR_Success: - hr = S_OK; - break; - case NERR_NetNameNotFound: - hr = E_FILENOTFOUND; - break; - default: - WcaLogError(s, "NetShareGetInfo returned an unexpected value.", NULL); - hr = HRESULT_FROM_WIN32(s); - break; - } - - ::NetApiBufferFree(psi); - - return hr; -} - - - -/******************************************************************** - CreateShare - create the file share on this computer - -********************************************************************/ -HRESULT CreateShare(SCA_SMBP* pssp) -{ - if (!pssp || !(pssp->wzKey)) - return E_INVALIDARG; - - HRESULT hr = S_OK; - PACL pACL = NULL; - SHARE_INFO_502 si; - NET_API_STATUS s; - DWORD dwParamErr = 0; - - BOOL fShareExists = SUCCEEDED(DoesShareExist(pssp->wzKey)); - - PSECURITY_DESCRIPTOR pSD = static_cast(MemAlloc(SECURITY_DESCRIPTOR_MIN_LENGTH, TRUE)); - ExitOnNull(pSD, hr, E_OUTOFMEMORY, "Failed to allocate memory for security descriptor"); - -#pragma prefast(push) -#pragma prefast(disable:25029) - if (!::InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) -#pragma prefast(pop) - { - ExitOnLastError(hr, "failed to initialize security descriptor"); - } - - hr = AllocateAcl(pssp, &pACL); - ExitOnFailure(hr, "Failed to allocate ACL for fileshare"); - - if (NULL == pACL) - { - WcaLog(LOGMSG_VERBOSE, "Ignoring NULL DACL."); - } -#pragma prefast(push) -#pragma prefast(disable:25028) // We only call this when pACL isn't NULL, so this call is safe according to the docs - // add the ACL to the security descriptor. - else if (!::SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE)) - { - ExitOnLastError(hr, "Failed to set security descriptor"); - } -#pragma prefast(pop) - - // all that is left is to create the share - FillShareInfo(&si, pssp, pSD); - - // Fail if the directory doesn't exist - if (!DirExists(pssp->wzDirectory, NULL)) - ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_OBJECT_NOT_FOUND), "Can't create a file share on directory that doesn't exist: %ls.", pssp->wzDirectory); - - WcaLog(LOGMSG_VERBOSE, "Creating file share on directory \'%ls\' named \'%ls\'.", pssp->wzDirectory, pssp->wzKey); - - if (!fShareExists) - { - s = ::NetShareAdd(NULL, 502, (BYTE*) &si, &dwParamErr); - WcaLog(LOGMSG_VERBOSE, "Adding a new file share."); - } - else - { - // The share exists. Write our new permissions over the top. - s = ::NetShareSetInfo(NULL, pssp->wzKey, 502, (BYTE*) &si, &dwParamErr); - WcaLog(LOGMSG_VERBOSE, "Setting permissions on existing share."); - } - - if (NERR_Success != s) - { - hr = E_FAIL; - if (!fShareExists && NERR_DuplicateShare == s) - WcaLog(LOGMSG_VERBOSE, "Duplicate error when existence check failed."); - - // error codes listed above. - ExitOnFailure(hr, "Failed to create/modify file share: Err: %d", s); - } - -LExit: - if (pACL) - { - ::LocalFree(pACL); - } - - ReleaseMem(pSD); - - return hr; -} - - -/******************************************************************** - ScaEnsureSmbExists - -********************************************************************/ -HRESULT ScaEnsureSmbExists(SCA_SMBP* pssp) -{ - HRESULT hr = S_OK; - - // create the share - hr = CreateShare(pssp); - - return hr; -} - - -// -// Delete File Shares - real work -// - -/******************************************************************** - ScaDropSmb - delete this file share from this computer - -********************************************************************/ -HRESULT ScaDropSmb(SCA_SMBP* pssp) -{ - HRESULT hr = S_OK; - NET_API_STATUS s; - - hr = DoesShareExist(pssp->wzKey); - - if (E_FILENOTFOUND == hr) - { - WcaLog(LOGMSG_VERBOSE, "Share doesn't exist, share removal skipped. (%ls)", pssp->wzKey); - ExitFunction1(hr = S_OK); - - } - - ExitOnFailure(hr, "Unable to detect share. (%ls)", pssp->wzKey); - - s = ::NetShareDel(NULL, pssp->wzKey, 0); - if (NERR_Success != s) - { - hr = E_FAIL; - ExitOnFailure(hr, "Failed to remove file share: Err: %d", s); - } - -LExit: - return hr; -} diff --git a/src/ca/scasmbexec.h b/src/ca/scasmbexec.h deleted file mode 100644 index e3c8f8bb..00000000 --- a/src/ca/scasmbexec.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_SMBP_USER_PERMS -{ - DWORD nPermissions; - ACCESS_MODE accessMode; - WCHAR* wzUser; - //Not adding Password because I can't find anywhere that it is used -}; - -struct SCA_SMBP // hungarian ssp -{ - WCHAR* wzKey; - WCHAR* wzDescription; - WCHAR* wzComponent; - WCHAR* wzDirectory; // full path of the dir to share to - - DWORD dwUserPermissionCount; //Count of SCA_SMBP_EX_USER_PERMS structures - SCA_SMBP_USER_PERMS* pUserPerms; - BOOL fUseIntegratedAuth; -}; - - -HRESULT ScaEnsureSmbExists(SCA_SMBP* pssp); -HRESULT ScaDropSmb(SCA_SMBP* pssp); diff --git a/src/ca/scasmbsched.cpp b/src/ca/scasmbsched.cpp deleted file mode 100644 index e29f7f51..00000000 --- a/src/ca/scasmbsched.cpp +++ /dev/null @@ -1,639 +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" - - -/******************************************************************** - Helper functions to maintain a list of file shares to create / remove - -********************************************************************/ -SCA_SMB* NewSmb() -{ - SCA_SMB* pss = (SCA_SMB*)MemAlloc(sizeof(SCA_SMB), TRUE); - Assert(pss); - return pss; -} - - -SCA_SMB_EX_USER_PERMS* NewExUserPermsSmb() -{ - SCA_SMB_EX_USER_PERMS* pExUserPerms = (SCA_SMB_EX_USER_PERMS*)MemAlloc(sizeof(SCA_SMB_EX_USER_PERMS), TRUE); - Assert(pExUserPerms); - return pExUserPerms; -} - - -SCA_SMB* AddSmbToList(SCA_SMB* pssList, SCA_SMB* pss) -{ - if (pssList) - { - SCA_SMB* pssT = pssList; - while (pssT->pssNext) - { - pssT = pssT->pssNext; - } - - pssT->pssNext = pss; - } - else - { - pssList = pss; - } - - return pssList; -} - - -SCA_SMB_EX_USER_PERMS* AddExUserPermsSmbToList( - SCA_SMB_EX_USER_PERMS* pExUserPermsList, - SCA_SMB_EX_USER_PERMS* pExUserPerms - ) -{ - SCA_SMB_EX_USER_PERMS* pExUserPermsTemp = pExUserPermsList; - if (pExUserPermsList) - { - while (pExUserPermsTemp->pExUserPermsNext) - { - pExUserPermsTemp = pExUserPermsTemp->pExUserPermsNext; - } - - pExUserPermsTemp->pExUserPermsNext = pExUserPerms; - } - else - { - pExUserPermsList = pExUserPerms; - } - - return pExUserPermsList; -} - -void ScaSmbFreeList(SCA_SMB* pssList) -{ - SCA_SMB* pssDelete = pssList; - while (pssList) - { - pssDelete = pssList; - pssList = pssList->pssNext; - - MemFree(pssDelete); - } -} - -void ScaExUserPermsSmbFreeList(SCA_SMB_EX_USER_PERMS* pExUserPermsList) -{ - SCA_SMB_EX_USER_PERMS* pExUserPermsDelete = pExUserPermsList; - while (pExUserPermsList) - { - pExUserPermsDelete = pExUserPermsList; - pExUserPermsList = pExUserPermsList->pExUserPermsNext; - - MemFree(pExUserPermsDelete); - } -} - -// sql query constants -LPCWSTR vcsSmbQuery = L"SELECT `Wix4FileShare`, `ShareName`, `Description`, `Directory_`, " - L"`Component_`, `User_`, `Permissions` FROM `Wix4FileShare`"; - -enum eSmbQuery { - ssqFileShare = 1, - ssqShareName, - ssqDescription, - ssqDirectory, - ssqComponent, - ssqUser, - ssqPermissions - }; - - -/******************************************************************** - ScaSmbRead - read all of the information from the msi tables and - return a list of file share jobs to be done. - -********************************************************************/ -HRESULT ScaSmbRead(SCA_SMB** ppssList) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - PMSIHANDLE hView, hRec; - - LPWSTR pwzData = NULL; - - SCA_SMB* pss = NULL; - BOOL bUserPermissionsTableExists = FALSE; - - if (S_OK != WcaTableExists(L"Wix4FileShare")) - { - WcaLog(LOGMSG_VERBOSE, "Skipping ScaSmbCreateShare() - Wix4FileShare table not present"); - ExitFunction1(hr = S_FALSE); - } - - if (S_OK == WcaTableExists(L"Wix4FileSharePermissions")) - { - bUserPermissionsTableExists = TRUE; - } - else - { - WcaLog(LOGMSG_VERBOSE, "No Additional Permissions - Wix4FileSharePermissions table not present"); - } - - WcaLog(LOGMSG_VERBOSE, "Reading File Share Tables"); - - // loop through all the fileshares - hr = WcaOpenExecuteView(vcsSmbQuery, &hView); - ExitOnFailure(hr, "Failed to open view on Wix4FileShare table"); - while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) - { - pss = NewSmb(); - if (!pss) - { - hr = E_OUTOFMEMORY; - break; - } - Assert(pss); - ::ZeroMemory(pss, sizeof(*pss)); - - hr = WcaGetRecordString(hRec, ssqFileShare, &pwzData); - ExitOnFailure(hr, "Failed to get Wix4FileShare.Wix4FileShare"); - hr = ::StringCchCopyW(pss->wzId, countof(pss->wzId), pwzData); - ExitOnFailure(hr, "Failed to copy ID string to smb object"); - - hr = WcaGetRecordFormattedString(hRec, ssqShareName, &pwzData); - ExitOnFailure(hr, "Failed to get Wix4FileShare.ShareName"); - hr = ::StringCchCopyW(pss->wzShareName, countof(pss->wzShareName), pwzData); - ExitOnFailure(hr, "Failed to copy share name string to smb object"); - - hr = WcaGetRecordString(hRec, ssqComponent, &pwzData); - ExitOnFailure(hr, "Failed to get Component for Wix4FileShare: '%ls'", pss->wzShareName); - hr = ::StringCchCopyW(pss->wzComponent, countof(pss->wzComponent), pwzData); - ExitOnFailure(hr, "Failed to copy component string to smb object"); - - hr = WcaGetRecordFormattedString(hRec, ssqDescription, &pwzData); - ExitOnFailure(hr, "Failed to get Share Description for Wix4FileShare: '%ls'", pss->wzShareName); - hr = ::StringCchCopyW(pss->wzDescription, countof(pss->wzDescription), pwzData); - ExitOnFailure(hr, "Failed to copy description string to smb object"); - - // get user info from the user table - hr = WcaGetRecordFormattedString(hRec, ssqUser, &pwzData); - ExitOnFailure(hr, "Failed to get Wix4User record for Wix4FileShare: '%ls'", pss->wzShareName); - - // get component install state - er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pss->wzComponent, &pss->isInstalled, &pss->isAction); - hr = HRESULT_FROM_WIN32(er); - ExitOnFailure(hr, "Failed to get Component state for Wix4FileShare"); - - // if a user was specified - if (*pwzData) - { - pss->fUseIntegratedAuth = FALSE; - pss->fLegacyUserProvided = TRUE; - hr = ScaGetUser(pwzData, &pss->scau); - ExitOnFailure(hr, "Failed to get user information for fileshare: '%ls'", pss->wzShareName); - } - else - { - pss->fLegacyUserProvided = FALSE; - // TODO: figure out whether this is useful still - //pss->fUseIntegratedAuth = TRUE; - // integrated authorization doesn't have a User record - } - - // get the share's directory - hr = WcaGetRecordString(hRec, ssqDirectory, &pwzData); - ExitOnFailure(hr, "Failed to get directory for Wix4FileShare: '%ls'", pss->wzShareName); - - WCHAR wzPath[MAX_PATH]; - DWORD dwLen; - dwLen = countof(wzPath); - // review: relevant for file shares? - if (INSTALLSTATE_SOURCE == pss->isAction) - { - er = ::MsiGetSourcePathW(WcaGetInstallHandle(), pwzData, wzPath, &dwLen); - } - else - { - er = ::MsiGetTargetPathW(WcaGetInstallHandle(), pwzData, wzPath, &dwLen); - } - hr = HRESULT_FROM_WIN32(er); - ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory"); - - // If the path is to the root of a drive, then it needs a trailing backslash. - // Otherwise, it can't have a trailing backslash. - if (3 < dwLen) - { - if (wzPath[dwLen - 1] == L'\\') - { - wzPath[dwLen - 1] = 0; - } - } - else if (2 == dwLen && wzPath[1] == L':') - { - wzPath[2] = L'\\'; - wzPath[3] = 0; - } - - hr = ::StringCchCopyW(pss->wzDirectory, countof(pss->wzDirectory), wzPath); - ExitOnFailure(hr, "Failed to copy directory string to smb object"); - - hr = WcaGetRecordInteger(hRec, ssqPermissions, &pss->nPermissions); - ExitOnFailure(hr, "Failed to get Wix4FileShare.Permissions"); - - // Check to see if additional user & permissions are specified for this share - if (bUserPermissionsTableExists) - { - hr = ScaSmbExPermsRead(pss); - ExitOnFailure(hr, "Failed to get Additional File Share Permissions"); - } - - *ppssList = AddSmbToList(*ppssList, pss); - pss = NULL; // set the smb NULL so it doesn't accidentally get freed below - } - - if (E_NOMOREITEMS == hr) - { - hr = S_OK; - } - ExitOnFailure(hr, "Failure occured while processing Wix4FileShare table"); - -LExit: - // if anything was left over after an error clean it all up - if (pss) - { - ScaSmbFreeList(pss); - } - - ReleaseStr(pwzData); - - return hr; -} - - -/******************************************************************** - RetrieveSMBShareUserPermList - retrieve SMB Share's user permission list - -********************************************************************/ -HRESULT RetrieveFileShareUserPerm(SCA_SMB* pss, SCA_SMB_EX_USER_PERMS** ppExUserPermsList, DWORD *pUserPermsCount) -{ - HRESULT hr = S_OK; - SHARE_INFO_502* psi = NULL; - NET_API_STATUS s; - BOOL bValid, bDaclDefaulted; - PACL acl = NULL; - PEXPLICIT_ACCESSW pEA = NULL; - ULONG nCount = 0; - DWORD er = ERROR_SUCCESS; - PSID pSID = NULL; - DWORD nUserNameSize = MAX_DARWIN_COLUMN; - DWORD nDomainNameSize = MAX_DARWIN_COLUMN; - SID_NAME_USE peUse; - DWORD dwCounter = 0; - SCA_SMB_EX_USER_PERMS* pExUserPermsList = NULL; - DWORD dwUserPermsCount = 0; - - *pUserPermsCount = 0; - s = ::NetShareGetInfo(NULL, pss->wzShareName, 502, (LPBYTE*)&psi); - WcaLog(LOGMSG_VERBOSE, "retrieving permissions on existing file share."); - if (NERR_NetNameNotFound == s) - { - WcaLog(LOGMSG_VERBOSE, "File share has already been removed."); - ExitFunction1(hr = S_OK); - } - else if (NERR_Success != s || psi == NULL) - { - hr = E_FAIL; - ExitOnFailure(hr, "Failed to get share information with return code: %d", s); - } - if (!::GetSecurityDescriptorDacl(psi->shi502_security_descriptor, &bValid, &acl, &bDaclDefaulted) || !bValid) - { - ExitOnLastError(hr, "Failed to get acl from security descriptor"); - } - - er = ::GetExplicitEntriesFromAclW(acl, &nCount, &pEA); - hr = HRESULT_FROM_WIN32(er); - ExitOnFailure(hr, "Failed to get access entries from acl for file share %ls", pss->wzShareName); - for (dwCounter = 0; dwCounter < nCount; ++dwCounter) - { - if (TRUSTEE_IS_SID == pEA[dwCounter].Trustee.TrusteeForm) - { - SCA_SMB_EX_USER_PERMS* pExUserPerms = NewExUserPermsSmb(); - ::ZeroMemory(pExUserPerms, sizeof(*pExUserPerms)); - pExUserPermsList = AddExUserPermsSmbToList(pExUserPermsList, pExUserPerms); - pSID = (PSID)(pEA[dwCounter].Trustee.ptstrName); - if (!::LookupAccountSidW(NULL, pSID, pExUserPerms->scau.wzName, &nUserNameSize, pExUserPerms->scau.wzDomain, &nDomainNameSize, &peUse)) - { - hr = E_FAIL; - ExitOnFailure(hr, "Failed to get account name from SID"); - } - pExUserPerms->nPermissions = pEA[dwCounter].grfAccessPermissions; - pExUserPerms->accessMode = pEA[dwCounter].grfAccessMode; - ++dwUserPermsCount; - nUserNameSize = MAX_DARWIN_COLUMN; - nDomainNameSize = MAX_DARWIN_COLUMN; - } - } - *ppExUserPermsList = pExUserPermsList; - *pUserPermsCount = dwUserPermsCount; - -LExit: - if (psi) - { - ::NetApiBufferFree(psi); - } - - if (pEA) - { - ::LocalFree(pEA); - } - - return hr; -} - - -/******************************************************************** - SchedCreateSmb - schedule one instance of a file share creation - -********************************************************************/ -HRESULT SchedCreateSmb(SCA_SMB* pss) -{ - HRESULT hr = S_OK; - - WCHAR wzDomainUser[255]; // "domain\user" - SCA_SMB_EX_USER_PERMS* pExUserPermsList = NULL; - int nCounter = 0; - WCHAR* pwzRollbackCustomActionData = NULL; - WCHAR* pwzCustomActionData = NULL; - - hr = WcaWriteStringToCaData(pss->wzShareName, &pwzRollbackCustomActionData); - ExitOnFailure(hr, "failed to add ShareName to CustomActionData"); - - hr = WcaWriteStringToCaData(pss->wzShareName, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add ShareName to CustomActionData"); - - hr = WcaWriteStringToCaData(pss->wzDescription, &pwzCustomActionData); - ExitOnFailure(hr, "Failed to add server name to CustomActionData"); - - hr = WcaWriteStringToCaData(pss->wzDirectory, &pwzCustomActionData); - ExitOnFailure(hr, "Failed to add full path instance to CustomActionData"); - - hr = WcaWriteStringToCaData(pss->fUseIntegratedAuth ? L"1" : L"0", &pwzCustomActionData); - ExitOnFailure(hr, "Failed to add server name to CustomActionData"); - - if (pss->fLegacyUserProvided) - { - hr = WcaWriteIntegerToCaData(pss->nUserPermissionCount + 1, &pwzCustomActionData); - ExitOnFailure(hr, "Failed to add additional user permission count to CustomActionData"); - - hr = UserBuildDomainUserName(wzDomainUser, countof(wzDomainUser), pss->scau.wzName, pss->scau.wzDomain); - ExitOnFailure(hr, "Failed to build user and domain name for CustomActionData"); - hr = WcaWriteStringToCaData(wzDomainUser, &pwzCustomActionData); - ExitOnFailure(hr, "Failed to add server Domain\\UserName to CustomActionData"); - - hr = WcaWriteIntegerToCaData(pss->nPermissions, &pwzCustomActionData); - ExitOnFailure(hr, "Failed to add permissions to CustomActionData"); - } - else - { - hr = WcaWriteIntegerToCaData(pss->nUserPermissionCount, &pwzCustomActionData); - ExitOnFailure(hr, "Failed to add additional user permission count to CustomActionData"); - } - - if (pss->nUserPermissionCount > 0) - { - nCounter = 0; - for (pExUserPermsList = pss->pExUserPerms; pExUserPermsList; pExUserPermsList = pExUserPermsList->pExUserPermsNext) - { - Assert(nCounter < pss->nUserPermissionCount); - - hr = UserBuildDomainUserName(wzDomainUser, countof(wzDomainUser), pExUserPermsList->scau.wzName, pExUserPermsList->scau.wzDomain); - ExitOnFailure(hr, "Failed to build user and domain name for CustomActionData"); - hr = WcaWriteStringToCaData(wzDomainUser, &pwzCustomActionData); - ExitOnFailure(hr, "Failed to add server Domain\\UserName to CustomActionData"); - - hr = WcaWriteIntegerToCaData((int)pExUserPermsList->accessMode, &pwzCustomActionData); - ExitOnFailure(hr, "Failed to add access mode to CustomActionData"); - - hr = WcaWriteIntegerToCaData(pExUserPermsList->nPermissions, &pwzCustomActionData); - ExitOnFailure(hr, "Failed to add permissions to CustomActionData"); - ++nCounter; - } - Assert(nCounter == pss->nUserPermissionCount); - } - - // Schedule the rollback first - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CreateSmbRollback"), pwzRollbackCustomActionData, COST_SMB_DROPSMB); - ExitOnFailure(hr, "Failed to schedule DropSmb action"); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CreateSmb"), pwzCustomActionData, COST_SMB_CREATESMB); - ExitOnFailure(hr, "Failed to schedule CreateSmb action"); - -LExit: - ReleaseStr(pwzRollbackCustomActionData); - ReleaseStr(pwzCustomActionData); - - if (pExUserPermsList) - { - ScaExUserPermsSmbFreeList(pExUserPermsList); - } - - return hr; -} - - -/******************************************************************** - ScaSmbInstall - for every file share, schedule the create custom action - -********************************************************************/ -HRESULT ScaSmbInstall(SCA_SMB* pssList) -{ - HRESULT hr = S_FALSE; // assume nothing will be done - SCA_SMB* pss = NULL; - - for (pss = pssList; pss; pss = pss->pssNext) - { - // if installing this component - if (WcaIsInstalling(pss->isInstalled, pss->isAction) ) - { - hr = SchedCreateSmb(pss); - ExitOnFailure(hr, "Failed to schedule the creation of the fileshare: %ls", pss->wzShareName); - } - } - -LExit: - return hr; -} - - -/******************************************************************** - SchedDropSmb - schedule one instance of a file share removal - -********************************************************************/ -HRESULT SchedDropSmb(SCA_SMB* pss) -{ - HRESULT hr = S_OK; - - WCHAR* pwzCustomActionData = NULL; - WCHAR* pwzRollbackCustomActionData = NULL; - SCA_SMB_EX_USER_PERMS *pExUserPermsList = NULL; - SCA_SMB_EX_USER_PERMS *pExUserPerm = NULL; - WCHAR wzDomainUser[255]; // "domain\user" - DWORD dwUserPermsCount = 0; - - // roll back DropSmb - hr = WcaWriteStringToCaData(pss->wzShareName, &pwzRollbackCustomActionData); - ExitOnFailure(hr, "failed to add ShareName to CustomActionData"); - - hr = WcaWriteStringToCaData(pss->wzDescription, &pwzRollbackCustomActionData); - ExitOnFailure(hr, "Failed to add server name to CustomActionData"); - - hr = WcaWriteStringToCaData(pss->wzDirectory, &pwzRollbackCustomActionData); - ExitOnFailure(hr, "Failed to add full path instance to CustomActionData"); - - hr = WcaWriteStringToCaData(L"1", &pwzRollbackCustomActionData); - ExitOnFailure(hr, "Failed to add useintegrated flag to CustomActionData"); - - hr = RetrieveFileShareUserPerm(pss, &pExUserPermsList, &dwUserPermsCount); - ExitOnFailure(hr, "Failed to retrieve SMBShare's user permissions"); - - hr = WcaWriteIntegerToCaData((int)dwUserPermsCount, &pwzRollbackCustomActionData); - ExitOnFailure(hr, "Failed to add additional user permission count to CustomActionData"); - - for (pExUserPerm = pExUserPermsList; pExUserPerm; pExUserPerm = pExUserPerm->pExUserPermsNext) - { - hr = UserBuildDomainUserName(wzDomainUser, countof(wzDomainUser), pExUserPerm->scau.wzName, pExUserPerm->scau.wzDomain); - ExitOnFailure(hr, "Failed to build user and domain name for CustomActionData"); - hr = WcaWriteStringToCaData(wzDomainUser, &pwzRollbackCustomActionData); - ExitOnFailure(hr, "Failed to add server Domain\\UserName to CustomActionData"); - - hr = WcaWriteIntegerToCaData((int)pExUserPerm->accessMode, &pwzRollbackCustomActionData); - ExitOnFailure(hr, "Failed to add access mode to CustomActionData"); - - hr = WcaWriteIntegerToCaData(pExUserPerm->nPermissions, &pwzRollbackCustomActionData); - ExitOnFailure(hr, "Failed to add permissions to CustomActionData"); - } - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"DropSmbRollback"), pwzRollbackCustomActionData, COST_SMB_CREATESMB); - ExitOnFailure(hr, "Failed to schedule DropSmbRollback action"); - - // DropSMB - hr = WcaWriteStringToCaData(pss->wzShareName, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add ShareName to CustomActionData"); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"DropSmb"), pwzCustomActionData, COST_SMB_DROPSMB); - ExitOnFailure(hr, "Failed to schedule DropSmb action"); - -LExit: - ReleaseStr(pwzCustomActionData); - - if (pExUserPermsList) - { - ScaExUserPermsSmbFreeList(pExUserPermsList); - } - - return hr; - -} - - -/******************************************************************** - ScaSmbUninstall - for every file share, schedule the drop custom action - -********************************************************************/ -HRESULT ScaSmbUninstall(SCA_SMB* pssList) -{ - HRESULT hr = S_FALSE; // assume nothing will be done - SCA_SMB* pss = NULL; - - for (pss = pssList; pss; pss = pss->pssNext) - { - // if uninstalling this component - if (WcaIsUninstalling(pss->isInstalled, pss->isAction) ) - { - hr = SchedDropSmb(pss); - ExitOnFailure(hr, "Failed to remove file share %ls", pss->wzShareName); - } - } - -LExit: - return hr; -} - -LPCWSTR vcsSmbExUserPermsQuery = L"SELECT `FileShare_`,`User_`,`Permissions` " - L"FROM `Wix4FileSharePermissions` WHERE `FileShare_`=?"; - -enum eSmbUserPermsQuery { - ssupqFileShare = 1, - ssupqUser, - ssupqPermissions - -}; - - -/******************************************************************** - ScaSmbExPermsRead - for Every entry in File Permissions table add a - User Name & Permissions structure to the List - -********************************************************************/ -HRESULT ScaSmbExPermsRead(SCA_SMB* pss) -{ - HRESULT hr = S_OK; - PMSIHANDLE hView, hRec; - - LPWSTR pwzData = NULL; - SCA_SMB_EX_USER_PERMS* pExUserPermsList = pss->pExUserPerms; - SCA_SMB_EX_USER_PERMS* pExUserPerms = NULL; - int nCounter = 0; - - hRec = ::MsiCreateRecord(1); - hr = WcaSetRecordString(hRec, 1, pss->wzId); - ExitOnFailure(hr, "Failed to look up FileShare"); - - hr = WcaOpenView(vcsSmbExUserPermsQuery, &hView); - ExitOnFailure(hr, "Failed to open view on Wix4FileSharePermissions table"); - hr = WcaExecuteView(hView, hRec); - ExitOnFailure(hr, "Failed to execute view on Wix4FileSharePermissions table"); - - // loop through all User/Permissions paris returned - while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) - { - pExUserPerms = NewExUserPermsSmb(); - if (!pExUserPerms) - { - hr = E_OUTOFMEMORY; - break; - } - Assert(pExUserPerms); - ::ZeroMemory(pExUserPerms, sizeof(*pExUserPerms)); - - hr = WcaGetRecordString(hRec, ssupqUser, &pwzData); - ExitOnFailure(hr, "Failed to get Wix4FileSharePermissions.User"); - hr = ScaGetUser(pwzData, &pExUserPerms->scau); - ExitOnFailure(hr, "Failed to get user information for fileshare: '%ls'", pss->wzShareName); - - hr = WcaGetRecordInteger(hRec, ssupqPermissions, &pExUserPerms->nPermissions); - ExitOnFailure(hr, "Failed to get Wix4FileSharePermissions.Permissions"); - pExUserPerms->accessMode = SET_ACCESS; // we only support SET_ACCESS here - - pExUserPermsList = AddExUserPermsSmbToList(pExUserPermsList, pExUserPerms); - ++nCounter; - pExUserPerms = NULL; // set the smb NULL so it doesn't accidentally get freed below - } - - if (E_NOMOREITEMS == hr) - { - hr = S_OK; - pss->pExUserPerms = pExUserPermsList; - pss->nUserPermissionCount = nCounter; - } - ExitOnFailure(hr, "Failure occured while processing FileShare table"); - -LExit: - // if anything was left over after an error clean it all up - if (pExUserPerms) - { - ScaExUserPermsSmbFreeList(pExUserPerms); - } - - ReleaseStr(pwzData); - - return hr; -} diff --git a/src/ca/scauser.cpp b/src/ca/scauser.cpp deleted file mode 100644 index b25e9daf..00000000 --- a/src/ca/scauser.cpp +++ /dev/null @@ -1,709 +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 `Wix4User`, `Component_`, `Name`, `Domain`, `Password` FROM `Wix4User` WHERE `Wix4User`=?"; -enum eUserQuery { vuqUser = 1, vuqComponent, vuqName, vuqDomain, vuqPassword }; - -LPCWSTR vcsGroupQuery = L"SELECT `Wix4Group`, `Component_`, `Name`, `Domain` FROM `Wix4Group` WHERE `Wix4Group`=?"; -enum eGroupQuery { vgqGroup = 1, vgqComponent, vgqName, vgqDomain }; - -LPCWSTR vcsUserGroupQuery = L"SELECT `Wix4User_`, `Wix4Group_` FROM `Wix4UserGroup` WHERE `Wix4User_`=?"; -enum eUserGroupQuery { vugqUser = 1, vugqGroup }; - -LPCWSTR vActionableQuery = L"SELECT `Wix4User`,`Component_`,`Name`,`Domain`,`Password`,`Attributes` FROM `Wix4User` WHERE `Component_` IS NOT NULL"; -enum eActionableQuery { vaqUser = 1, vaqComponent, vaqName, vaqDomain, vaqPassword, vaqAttributes }; - - -static HRESULT AddUserToList( - __inout SCA_USER** ppsuList - ); - -static HRESULT AddGroupToList( - __inout SCA_GROUP** ppsgList - ); - - -HRESULT __stdcall ScaGetUser( - __in LPCWSTR wzUser, - __out SCA_USER* pscau - ) -{ - if (!wzUser || !pscau) - { - return E_INVALIDARG; - } - - HRESULT hr = S_OK; - PMSIHANDLE hView, hRec; - - 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); - } - - hRec = ::MsiCreateRecord(1); - hr = WcaSetRecordString(hRec, 1, wzUser); - ExitOnFailure(hr, "Failed to look up User"); - - hr = WcaOpenView(vcsUserQuery, &hView); - ExitOnFailure(hr, "Failed to open view on Wix4User table"); - hr = WcaExecuteView(hView, hRec); - ExitOnFailure(hr, "Failed to execute view on Wix4User table"); - - hr = WcaFetchSingleRecord(hView, &hRec); - if (S_OK == hr) - { - hr = WcaGetRecordString(hRec, vuqUser, &pwzData); - ExitOnFailure(hr, "Failed to get Wix4User.User"); - hr = ::StringCchCopyW(pscau->wzKey, countof(pscau->wzKey), pwzData); - ExitOnFailure(hr, "Failed to copy key string to user object"); - - hr = WcaGetRecordString(hRec, vuqComponent, &pwzData); - ExitOnFailure(hr, "Failed to get Wix4User.Component_"); - hr = ::StringCchCopyW(pscau->wzComponent, countof(pscau->wzComponent), pwzData); - ExitOnFailure(hr, "Failed to copy component string to user object"); - - hr = WcaGetRecordFormattedString(hRec, vuqName, &pwzData); - ExitOnFailure(hr, "Failed to get Wix4User.Name"); - hr = ::StringCchCopyW(pscau->wzName, countof(pscau->wzName), pwzData); - ExitOnFailure(hr, "Failed to copy name string to user object"); - - hr = WcaGetRecordFormattedString(hRec, vuqDomain, &pwzData); - ExitOnFailure(hr, "Failed to get Wix4User.Domain"); - hr = ::StringCchCopyW(pscau->wzDomain, countof(pscau->wzDomain), pwzData); - ExitOnFailure(hr, "Failed to copy domain string to user object"); - - hr = WcaGetRecordFormattedString(hRec, vuqPassword, &pwzData); - ExitOnFailure(hr, "Failed to get Wix4User.Password"); - hr = ::StringCchCopyW(pscau->wzPassword, countof(pscau->wzPassword), pwzData); - ExitOnFailure(hr, "Failed to copy password string to user object"); - } - else if (E_NOMOREITEMS == hr) - { - WcaLog(LOGMSG_STANDARD, "Error: Cannot locate Wix4User.User='%ls'", wzUser); - hr = E_FAIL; - } - else - { - ExitOnFailure(hr, "Error or found multiple matching Wix4User rows"); - } - -LExit: - ReleaseStr(pwzData); - - return hr; -} - -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 Wix4User rows"); - } - - hr = WcaGetRecordString(hRec, vuqUser, &pwzData); - ExitOnFailure(hr, "Failed to get Wix4User.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 Wix4User.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 Wix4User.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 Wix4User.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 Wix4User.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 Wix4User.User='%ls'", wzUser); - hr = E_FAIL; - } - else - { - ExitOnFailure(hr, "Error fetching single Wix4User row"); - } - -LExit: - ReleaseStr(pwzData); - - return hr; -} - - -HRESULT __stdcall ScaGetGroup( - __in LPCWSTR wzGroup, - __out SCA_GROUP* pscag - ) -{ - if (!wzGroup || !pscag) - { - return E_INVALIDARG; - } - - HRESULT hr = S_OK; - PMSIHANDLE hView, hRec; - - LPWSTR pwzData = NULL; - - hRec = ::MsiCreateRecord(1); - hr = WcaSetRecordString(hRec, 1, wzGroup); - ExitOnFailure(hr, "Failed to look up Group"); - - hr = WcaOpenView(vcsGroupQuery, &hView); - ExitOnFailure(hr, "Failed to open view on Wix4Group table"); - hr = WcaExecuteView(hView, hRec); - ExitOnFailure(hr, "Failed to execute view on Wix4Group table"); - - hr = WcaFetchSingleRecord(hView, &hRec); - if (S_OK == hr) - { - hr = WcaGetRecordString(hRec, vgqGroup, &pwzData); - ExitOnFailure(hr, "Failed to get Wix4Group.Wix4Group."); - hr = ::StringCchCopyW(pscag->wzKey, countof(pscag->wzKey), pwzData); - ExitOnFailure(hr, "Failed to copy Wix4Group.Wix4Group."); - - hr = WcaGetRecordString(hRec, vgqComponent, &pwzData); - ExitOnFailure(hr, "Failed to get Wix4Group.Component_"); - hr = ::StringCchCopyW(pscag->wzComponent, countof(pscag->wzComponent), pwzData); - ExitOnFailure(hr, "Failed to copy Wix4Group.Component_."); - - hr = WcaGetRecordFormattedString(hRec, vgqName, &pwzData); - ExitOnFailure(hr, "Failed to get Wix4Group.Name"); - hr = ::StringCchCopyW(pscag->wzName, countof(pscag->wzName), pwzData); - ExitOnFailure(hr, "Failed to copy Wix4Group.Name."); - - hr = WcaGetRecordFormattedString(hRec, vgqDomain, &pwzData); - ExitOnFailure(hr, "Failed to get Wix4Group.Domain"); - hr = ::StringCchCopyW(pscag->wzDomain, countof(pscag->wzDomain), pwzData); - ExitOnFailure(hr, "Failed to copy Wix4Group.Domain."); - } - else if (E_NOMOREITEMS == hr) - { - WcaLog(LOGMSG_STANDARD, "Error: Cannot locate Wix4Group.Wix4Group='%ls'", wzGroup); - hr = E_FAIL; - } - else - { - ExitOnFailure(hr, "Error or found multiple matching Wix4Group rows"); - } - -LExit: - ReleaseStr(pwzData); - - return hr; -} - - -void ScaUserFreeList( - __in SCA_USER* psuList - ) -{ - SCA_USER* psuDelete = psuList; - while (psuList) - { - psuDelete = psuList; - psuList = psuList->psuNext; - - ScaGroupFreeList(psuDelete->psgGroups); - MemFree(psuDelete); - } -} - - -void ScaGroupFreeList( - __in SCA_GROUP* psgList - ) -{ - SCA_GROUP* psgDelete = psgList; - while (psgList) - { - psgDelete = psgList; - psgList = psgList->psgNext; - - MemFree(psgDelete); - } -} - - -HRESULT ScaUserRead( - __out SCA_USER** ppsuList - ) -{ - //Assert(FALSE); - Assert(ppsuList); - - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - PMSIHANDLE hView, hRec, hUserRec, hUserGroupView; - - LPWSTR pwzData = NULL; - - BOOL fUserGroupExists = FALSE; - - SCA_USER *psu = NULL; - - INSTALLSTATE isInstalled, isAction; - - if (S_OK != WcaTableExists(L"Wix4User")) - { - WcaLog(LOGMSG_VERBOSE, "Wix4User Table does not exist, exiting"); - ExitFunction1(hr = S_FALSE); - } - - if (S_OK == WcaTableExists(L"Wix4UserGroup")) - { - fUserGroupExists = TRUE; - } - - // - // loop through all the users - // - hr = WcaOpenExecuteView(vActionableQuery, &hView); - ExitOnFailure(hr, "failed to open view on Wix4User table"); - while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) - { - hr = WcaGetRecordString(hRec, vaqComponent, &pwzData); - ExitOnFailure(hr, "failed to get Wix4User.Component"); - - er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &isInstalled, &isAction); - hr = HRESULT_FROM_WIN32(er); - ExitOnFailure(hr, "failed to get Component state for Wix4User"); - - // don't bother if we aren't installing or uninstalling this component - if (WcaIsInstalling(isInstalled, isAction) || WcaIsUninstalling(isInstalled, isAction)) - { - // - // Add the user to the list and populate it's values - // - hr = AddUserToList(ppsuList); - ExitOnFailure(hr, "failed to add user to list"); - - psu = *ppsuList; - - psu->isInstalled = isInstalled; - psu->isAction = isAction; - hr = ::StringCchCopyW(psu->wzComponent, countof(psu->wzComponent), pwzData); - ExitOnFailure(hr, "failed to copy component name: %ls", pwzData); - - hr = WcaGetRecordString(hRec, vaqUser, &pwzData); - ExitOnFailure(hr, "failed to get Wix4User.User"); - hr = ::StringCchCopyW(psu->wzKey, countof(psu->wzKey), pwzData); - ExitOnFailure(hr, "failed to copy user key: %ls", pwzData); - - hr = WcaGetRecordFormattedString(hRec, vaqName, &pwzData); - ExitOnFailure(hr, "failed to get Wix4User.Name"); - hr = ::StringCchCopyW(psu->wzName, countof(psu->wzName), pwzData); - ExitOnFailure(hr, "failed to copy user name: %ls", pwzData); - - hr = WcaGetRecordFormattedString(hRec, vaqDomain, &pwzData); - ExitOnFailure(hr, "failed to get Wix4User.Domain"); - hr = ::StringCchCopyW(psu->wzDomain, countof(psu->wzDomain), pwzData); - ExitOnFailure(hr, "failed to copy user domain: %ls", pwzData); - - hr = WcaGetRecordFormattedString(hRec, vaqPassword, &pwzData); - ExitOnFailure(hr, "failed to get Wix4User.Password"); - hr = ::StringCchCopyW(psu->wzPassword, countof(psu->wzPassword), pwzData); - ExitOnFailure(hr, "failed to copy user password"); - - hr = WcaGetRecordInteger(hRec, vaqAttributes, &psu->iAttributes); - ExitOnFailure(hr, "failed to get Wix4User.Attributes"); - - // Check if this user is to be added to any groups - if (fUserGroupExists) - { - hUserRec = ::MsiCreateRecord(1); - hr = WcaSetRecordString(hUserRec, 1, psu->wzKey); - ExitOnFailure(hr, "Failed to create user record for querying Wix4UserGroup table"); - - hr = WcaOpenView(vcsUserGroupQuery, &hUserGroupView); - ExitOnFailure(hr, "Failed to open view on Wix4UserGroup table for user %ls", psu->wzKey); - hr = WcaExecuteView(hUserGroupView, hUserRec); - ExitOnFailure(hr, "Failed to execute view on Wix4UserGroup table for user: %ls", psu->wzKey); - - while (S_OK == (hr = WcaFetchRecord(hUserGroupView, &hRec))) - { - hr = WcaGetRecordString(hRec, vugqGroup, &pwzData); - ExitOnFailure(hr, "failed to get Wix4UserGroup.Group"); - - hr = AddGroupToList(&(psu->psgGroups)); - ExitOnFailure(hr, "failed to add group to list"); - - hr = ScaGetGroup(pwzData, psu->psgGroups); - ExitOnFailure(hr, "failed to get information for group: %ls", pwzData); - } - - if (E_NOMOREITEMS == hr) - { - hr = S_OK; - } - ExitOnFailure(hr, "failed to enumerate selected rows from Wix4UserGroup table"); - } - } - } - - if (E_NOMOREITEMS == hr) - { - hr = S_OK; - } - ExitOnFailure(hr, "failed to enumerate selected rows from Wix4User table"); - -LExit: - ReleaseStr(pwzData); - - return hr; -} - - -static HRESULT WriteGroupInfo( - __in SCA_GROUP* psgList, - __in LPWSTR *ppwzActionData - ) -{ - HRESULT hr = S_OK; - - for (SCA_GROUP* psg = psgList; psg; psg = psg->psgNext) - { - hr = WcaWriteStringToCaData(psg->wzName, ppwzActionData); - ExitOnFailure(hr, "failed to add group name to custom action data: %ls", psg->wzName); - - hr = WcaWriteStringToCaData(psg->wzDomain, ppwzActionData); - ExitOnFailure(hr, "failed to add group domain to custom action data: %ls", psg->wzDomain); - } - -LExit: - return hr; -} - - -// Behaves like WriteGroupInfo, but it filters out groups the user is currently a member of, -// because we don't want to rollback those -static HRESULT WriteGroupRollbackInfo( - __in LPCWSTR pwzName, - __in LPCWSTR pwzDomain, - __in SCA_GROUP* psgList, - __in LPWSTR *ppwzActionData - ) -{ - HRESULT hr = S_OK; - BOOL fIsMember = FALSE; - - for (SCA_GROUP* psg = psgList; psg; psg = psg->psgNext) - { - hr = UserCheckIsMember(pwzName, pwzDomain, psg->wzName, psg->wzDomain, &fIsMember); - if (FAILED(hr)) - { - WcaLog(LOGMSG_VERBOSE, "Failed to check if user: %ls (domain: %ls) is member of a group while collecting rollback information (error code 0x%x) - continuing", pwzName, pwzDomain, hr); - hr = S_OK; - continue; - } - - // If the user is currently a member, we don't want to undo that on rollback, so skip adding - // this group record to the list of groups to rollback - if (fIsMember) - { - continue; - } - - hr = WcaWriteStringToCaData(psg->wzName, ppwzActionData); - ExitOnFailure(hr, "failed to add group name to custom action data: %ls", psg->wzName); - - hr = WcaWriteStringToCaData(psg->wzDomain, ppwzActionData); - ExitOnFailure(hr, "failed to add group domain to custom action data: %ls", psg->wzDomain); - } - -LExit: - return hr; -} - - -/* **************************************************************** -ScaUserExecute - Schedules user account creation or removal based on -component state. - -******************************************************************/ -HRESULT ScaUserExecute( - __in SCA_USER *psuList - ) -{ - HRESULT hr = S_OK; - DWORD er = 0; - PDOMAIN_CONTROLLER_INFOW pDomainControllerInfo = NULL; - - LPWSTR pwzBaseScriptKey = NULL; - DWORD cScriptKey = 0; - - USER_INFO_0 *pUserInfo = NULL; - LPWSTR pwzScriptKey = NULL; - LPWSTR pwzActionData = NULL; - LPWSTR pwzRollbackData = NULL; - - // Get the base script key for this CustomAction. - hr = WcaCaScriptCreateKey(&pwzBaseScriptKey); - ExitOnFailure(hr, "Failed to get encoding key."); - - // Loop through all the users to be configured. - for (SCA_USER *psu = psuList; psu; psu = psu->psuNext) - { - USER_EXISTS ueUserExists = USER_EXISTS_INDETERMINATE; - - // Always put the User Name and Domain plus Attributes on the front of the CustomAction - // data. Sometimes we'll add more data. - Assert(psu->wzName); - hr = WcaWriteStringToCaData(psu->wzName, &pwzActionData); - ExitOnFailure(hr, "Failed to add user name to custom action data: %ls", psu->wzName); - hr = WcaWriteStringToCaData(psu->wzDomain, &pwzActionData); - ExitOnFailure(hr, "Failed to add user domain to custom action data: %ls", psu->wzDomain); - hr = WcaWriteIntegerToCaData(psu->iAttributes, &pwzActionData); - ExitOnFailure(hr, "failed to add user attributes to custom action data for user: %ls", psu->wzKey); - - // Check to see if the user already exists since we have to be very careful when adding - // and removing users. Note: MSDN says that it is safe to call these APIs from any - // user, so we should be safe calling it during immediate mode. - er = ::NetApiBufferAllocate(sizeof(USER_INFO_0), reinterpret_cast(&pUserInfo)); - hr = HRESULT_FROM_WIN32(er); - ExitOnFailure(hr, "Failed to allocate memory to check existence of user: %ls", psu->wzName); - - LPCWSTR wzDomain = psu->wzDomain; - if (wzDomain && *wzDomain) - { - er = ::DsGetDcNameW(NULL, wzDomain, NULL, NULL, NULL, &pDomainControllerInfo); - if (RPC_S_SERVER_UNAVAILABLE == er) - { - // MSDN says, if we get the above error code, try again with the "DS_FORCE_REDISCOVERY" flag - er = ::DsGetDcNameW(NULL, wzDomain, NULL, NULL, DS_FORCE_REDISCOVERY, &pDomainControllerInfo); - } - if (ERROR_SUCCESS == er) - { - wzDomain = pDomainControllerInfo->DomainControllerName + 2; //Add 2 so that we don't get the \\ prefix - } - } - - er = ::NetUserGetInfo(wzDomain, psu->wzName, 0, reinterpret_cast(pUserInfo)); - if (NERR_Success == er) - { - ueUserExists = USER_EXISTS_YES; - } - else if (NERR_UserNotFound == er) - { - ueUserExists = USER_EXISTS_NO; - } - else - { - ueUserExists = USER_EXISTS_INDETERMINATE; - hr = HRESULT_FROM_WIN32(er); - WcaLog(LOGMSG_VERBOSE, "Failed to check existence of domain: %ls, user: %ls (error code 0x%x) - continuing", wzDomain, psu->wzName, hr); - hr = S_OK; - er = ERROR_SUCCESS; - } - - if (WcaIsInstalling(psu->isInstalled, psu->isAction)) - { - // If the user exists, check to see if we are supposed to fail if user the exists before - // the install. - if (USER_EXISTS_YES == ueUserExists) - { - // Reinstalls will always fail if we don't remove the check for "fail if exists". - if (WcaIsReInstalling(psu->isInstalled, psu->isAction)) - { - psu->iAttributes &= ~SCAU_FAIL_IF_EXISTS; - } - - if ((SCAU_FAIL_IF_EXISTS & (psu->iAttributes)) && !(SCAU_UPDATE_IF_EXISTS & (psu->iAttributes))) - { - hr = HRESULT_FROM_WIN32(NERR_UserExists); - MessageExitOnFailure(hr, msierrUSRFailedUserCreateExists, "Failed to create user: %ls because user already exists.", psu->wzName); - } - } - - // Rollback only if the user already exists, we couldn't determine if the user exists, or we are going to create the user - if ((USER_EXISTS_YES == ueUserExists) || (USER_EXISTS_INDETERMINATE == ueUserExists) || !(psu->iAttributes & SCAU_DONT_CREATE_USER)) - { - ++cScriptKey; - hr = StrAllocFormatted(&pwzScriptKey, L"%ls%u", pwzBaseScriptKey, cScriptKey); - ExitOnFailure(hr, "Failed to create encoding key."); - - // Write the script key to CustomActionData for install and rollback so information can be passed to rollback. - hr = WcaWriteStringToCaData(pwzScriptKey, &pwzActionData); - ExitOnFailure(hr, "Failed to add encoding key to custom action data."); - - hr = WcaWriteStringToCaData(pwzScriptKey, &pwzRollbackData); - ExitOnFailure(hr, "Failed to add encoding key to rollback custom action data."); - - INT iRollbackUserAttributes = psu->iAttributes; - - // If the user already exists, ensure this is accounted for in rollback - if (USER_EXISTS_YES == ueUserExists) - { - iRollbackUserAttributes |= SCAU_DONT_CREATE_USER; - } - else - { - iRollbackUserAttributes &= ~SCAU_DONT_CREATE_USER; - } - - // The deferred CA determines when to rollback User Rights Assignments so these should never be set. - iRollbackUserAttributes &= ~SCAU_ALLOW_LOGON_AS_SERVICE; - iRollbackUserAttributes &= ~SCAU_ALLOW_LOGON_AS_BATCH; - - hr = WcaWriteStringToCaData(psu->wzName, &pwzRollbackData); - ExitOnFailure(hr, "Failed to add user name to rollback custom action data: %ls", psu->wzName); - hr = WcaWriteStringToCaData(psu->wzDomain, &pwzRollbackData); - ExitOnFailure(hr, "Failed to add user domain to rollback custom action data: %ls", psu->wzDomain); - hr = WcaWriteIntegerToCaData(iRollbackUserAttributes, &pwzRollbackData); - ExitOnFailure(hr, "failed to add user attributes to rollback custom action data for user: %ls", psu->wzKey); - - // If the user already exists, add relevant group information to rollback data - if (USER_EXISTS_YES == ueUserExists || USER_EXISTS_INDETERMINATE == ueUserExists) - { - hr = WriteGroupRollbackInfo(psu->wzName, psu->wzDomain, psu->psgGroups, &pwzRollbackData); - ExitOnFailure(hr, "failed to add group information to rollback custom action data"); - } - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CreateUserRollback"), pwzRollbackData, COST_USER_DELETE); - ExitOnFailure(hr, "failed to schedule CreateUserRollback"); - } - else - { - // Write empty script key to CustomActionData since there is no rollback. - hr = WcaWriteStringToCaData(L"", &pwzActionData); - ExitOnFailure(hr, "Failed to add empty encoding key to custom action data."); - } - - // - // Schedule the creation now. - // - hr = WcaWriteStringToCaData(psu->wzPassword, &pwzActionData); - ExitOnFailure(hr, "failed to add user password to custom action data for user: %ls", psu->wzKey); - - // Add user's group information to custom action data - hr = WriteGroupInfo(psu->psgGroups, &pwzActionData); - ExitOnFailure(hr, "failed to add group information to custom action data"); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CreateUser"), pwzActionData, COST_USER_ADD); - ExitOnFailure(hr, "failed to schedule CreateUser"); - } - else if (((USER_EXISTS_YES == ueUserExists) || (USER_EXISTS_INDETERMINATE == ueUserExists)) && WcaIsUninstalling(psu->isInstalled, psu->isAction) && !(psu->iAttributes & SCAU_DONT_REMOVE_ON_UNINSTALL)) - { - // Add user's group information - this will ensure the user can be removed from any groups they were added to, if the user isn't be deleted - hr = WriteGroupInfo(psu->psgGroups, &pwzActionData); - ExitOnFailure(hr, "failed to add group information to custom action data"); - - // - // Schedule the removal because the user exists and we don't have any flags set - // that say, don't remove the user on uninstall. - // - // Note: We can't rollback the removal of a user which is why RemoveUser is a commit - // CustomAction. - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RemoveUser"), pwzActionData, COST_USER_DELETE); - ExitOnFailure(hr, "failed to schedule RemoveUser"); - } - - ReleaseNullStr(pwzScriptKey); - ReleaseNullStr(pwzActionData); - ReleaseNullStr(pwzRollbackData); - if (pUserInfo) - { - ::NetApiBufferFree(static_cast(pUserInfo)); - pUserInfo = NULL; - } - if (pDomainControllerInfo) - { - ::NetApiBufferFree(static_cast(pDomainControllerInfo)); - pDomainControllerInfo = NULL; - } - } - -LExit: - ReleaseStr(pwzBaseScriptKey); - ReleaseStr(pwzScriptKey); - ReleaseStr(pwzActionData); - ReleaseStr(pwzRollbackData); - if (pUserInfo) - { - ::NetApiBufferFree(static_cast(pUserInfo)); - } - if (pDomainControllerInfo) - { - ::NetApiBufferFree(static_cast(pDomainControllerInfo)); - } - - return hr; -} - - -static HRESULT AddUserToList( - __inout SCA_USER** ppsuList - ) -{ - HRESULT hr = S_OK; - SCA_USER* psu = static_cast(MemAlloc(sizeof(SCA_USER), TRUE)); - ExitOnNull(psu, hr, E_OUTOFMEMORY, "failed to allocate memory for new user list element"); - - psu->psuNext = *ppsuList; - *ppsuList = psu; - -LExit: - return hr; -} - - -static HRESULT AddGroupToList( - __inout SCA_GROUP** ppsgList - ) -{ - HRESULT hr = S_OK; - SCA_GROUP* psg = static_cast(MemAlloc(sizeof(SCA_GROUP), TRUE)); - ExitOnNull(psg, hr, E_OUTOFMEMORY, "failed to allocate memory for new group list element"); - - psg->psgNext = *ppsgList; - *ppsgList = psg; - -LExit: - return hr; -} diff --git a/src/ca/scauser.h b/src/ca/scauser.h deleted file mode 100644 index a5fd5ea8..00000000 --- a/src/ca/scauser.h +++ /dev/null @@ -1,67 +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 USER_EXISTS -{ - USER_EXISTS_YES, - USER_EXISTS_NO, - USER_EXISTS_INDETERMINATE -}; - -// 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 ScaGetUser( - __in LPCWSTR wzUser, - __out SCA_USER* pscau - ); -HRESULT __stdcall ScaGetUserDeferred( - __in LPCWSTR wzUser, - __in WCA_WRAPQUERY_HANDLE hUserQuery, - __out SCA_USER* pscau - ); -HRESULT __stdcall ScaGetGroup( - __in LPCWSTR wzGroup, - __out SCA_GROUP* pscag - ); -void ScaUserFreeList( - __in SCA_USER* psuList - ); -void ScaGroupFreeList( - __in SCA_GROUP* psgList - ); -HRESULT ScaUserRead( - __inout SCA_USER** ppsuList - ); -HRESULT ScaUserExecute( - __in SCA_USER *psuList - ); diff --git a/src/ca/secureobj.cpp b/src/ca/secureobj.cpp deleted file mode 100644 index 72842eb5..00000000 --- a/src/ca/secureobj.cpp +++ /dev/null @@ -1,915 +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" - -// structs -LPCWSTR wzQUERY_SECUREOBJECTS = L"SELECT `Wix4SecureObject`.`Wix4SecureObject`, `Wix4SecureObject`.`Table`, `Wix4SecureObject`.`Domain`, `Wix4SecureObject`.`User`, `Wix4SecureObject`.`Attributes`, " - L"`Wix4SecureObject`.`Permission`, `Wix4SecureObject`.`Component_`, `Component`.`Attributes` FROM `Wix4SecureObject`,`Component` WHERE " - L"`Wix4SecureObject`.`Component_`=`Component`.`Component`"; -enum eQUERY_SECUREOBJECTS { QSO_SECUREOBJECT = 1, QSO_TABLE, QSO_DOMAIN, QSO_USER, QSO_ATTRIBUTES, QSO_PERMISSION, QSO_COMPONENT, QSO_COMPATTRIBUTES }; - -LPCWSTR wzQUERY_REGISTRY = L"SELECT `Registry`.`Registry`, `Registry`.`Root`, `Registry`.`Key` FROM `Registry` WHERE `Registry`.`Registry`=?"; -enum eQUERY_OBJECTCOMPONENT { QSOC_REGISTRY = 1, QSOC_REGROOT, QSOC_REGKEY }; - -LPCWSTR wzQUERY_SERVICEINSTALL = L"SELECT `ServiceInstall`.`Name` FROM `ServiceInstall` WHERE `ServiceInstall`.`ServiceInstall`=?"; -enum eQUERY_SECURESERVICEINSTALL { QSSI_NAME = 1 }; - -enum eOBJECTTYPE { OT_UNKNOWN, OT_SERVICE, OT_FOLDER, OT_FILE, OT_REGISTRY }; - -enum eSECURE_OBJECT_ATTRIBUTE -{ - SECURE_OBJECT_ATTRIBUTE_INHERITABLE = 0x1, -}; - -static eOBJECTTYPE EObjectTypeFromString( - __in LPCWSTR pwzTable - ) -{ - if (NULL == pwzTable) - { - return OT_UNKNOWN; - } - - eOBJECTTYPE eType = OT_UNKNOWN; - - // ensure we're looking at a known table - if (0 == lstrcmpW(L"ServiceInstall", pwzTable)) - { - eType = OT_SERVICE; - } - else if (0 == lstrcmpW(L"CreateFolder", pwzTable)) - { - eType = OT_FOLDER; - } - else if (0 == lstrcmpW(L"File", pwzTable)) - { - eType = OT_FILE; - } - else if (0 == lstrcmpW(L"Registry", pwzTable)) - { - eType = OT_REGISTRY; - } - - return eType; -} - -static SE_OBJECT_TYPE SEObjectTypeFromString( - __in LPCWSTR pwzTable - ) -{ - if (NULL == pwzTable) - { - return SE_UNKNOWN_OBJECT_TYPE; - } - - SE_OBJECT_TYPE objectType = SE_UNKNOWN_OBJECT_TYPE; - - if (0 == lstrcmpW(L"ServiceInstall", pwzTable)) - { - objectType = SE_SERVICE; - } - else if (0 == lstrcmpW(L"CreateFolder", pwzTable) || 0 == lstrcmpW(L"File", pwzTable)) - { - objectType = SE_FILE_OBJECT; - } - else if (0 == lstrcmpW(L"Registry", pwzTable)) - { - objectType = SE_REGISTRY_KEY; - } - else - { - // Do nothing; we'll return SE_UNKNOWN_OBJECT_TYPE, and the caller should handle the situation - } - - return objectType; -} - -static HRESULT StoreACLRollbackInfo( - __in LPWSTR pwzObject, - __in LPCWSTR pwzTable - ) -{ - HRESULT hr = S_OK; - DWORD er = ERROR_SUCCESS; - PSECURITY_DESCRIPTOR psd = NULL; - SECURITY_DESCRIPTOR_CONTROL sdc = {0}; - DWORD dwRevision = 0; - LPWSTR pwzCustomActionData = NULL; - LPWSTR pwzSecurityInfo = NULL; - - Assert(pwzObject && pwzTable); - - SE_OBJECT_TYPE objectType = SEObjectTypeFromString(const_cast (pwzTable)); - - if (SE_UNKNOWN_OBJECT_TYPE != objectType) - { - er = ::GetNamedSecurityInfoW(pwzObject, objectType, DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &psd); - if (ERROR_FILE_NOT_FOUND == er || ERROR_PATH_NOT_FOUND == er || ERROR_SERVICE_DOES_NOT_EXIST == HRESULT_CODE(er)) - { - // If the file, path or service doesn't exist yet, skip rollback without a message - hr = HRESULT_FROM_WIN32(er); - ExitFunction(); - } - - ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Unable to schedule rollback for object: %ls", pwzObject); - - //Need to see if DACL is protected so getting Descriptor information - if (!::GetSecurityDescriptorControl(psd, &sdc, &dwRevision)) - { - ExitOnLastError(hr, "Unable to schedule rollback for object (failed to get security descriptor control): %ls", pwzObject); - } - - // Convert the security information to a string, and write this to the custom action data - if (!::ConvertSecurityDescriptorToStringSecurityDescriptorW(psd,SDDL_REVISION_1,DACL_SECURITY_INFORMATION,&pwzSecurityInfo,NULL)) - { - hr = E_UNEXPECTED; - ExitOnFailure(hr, "Unable to schedule rollback for object (failed to convert security descriptor to a valid security descriptor string): %ls", pwzObject); - } - - hr = WcaWriteStringToCaData(pwzObject, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add object data to rollback CustomActionData"); - - hr = WcaWriteStringToCaData(pwzTable, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add table name to rollback CustomActionData"); - - hr = WcaWriteStringToCaData(pwzSecurityInfo, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add security info data to rollback CustomActionData"); - - // Write a 1 if DACL is protected, 0 otherwise - if (sdc & SE_DACL_PROTECTED) - { - hr = WcaWriteIntegerToCaData(1,&pwzCustomActionData); - ExitOnFailure(hr, "failed to add data to rollbackCustomActionData"); - } - else - { - hr = WcaWriteIntegerToCaData(0,&pwzCustomActionData); - ExitOnFailure(hr, "failed to add data to rollback CustomActionData"); - } - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecSecureObjectsRollback"), pwzCustomActionData, COST_SECUREOBJECT); - ExitOnFailure(hr, "failed to schedule ExecSecureObjectsRollback for item: %ls of type: %ls", pwzObject, pwzTable); - - ReleaseStr(pwzCustomActionData); - pwzCustomActionData = NULL; - - } - else - { - MessageExitOnFailure(hr = E_UNEXPECTED, msierrSecureObjectsUnknownType, "unknown object type: %ls", pwzTable); - } -LExit: - ReleaseStr(pwzCustomActionData); - - if (psd) - { - ::LocalFree(psd); - } - - return hr; -} - -static HRESULT GetTargetPath( - __in eOBJECTTYPE eType, - __in LPCWSTR pwzSecureObject, - __out LPWSTR* ppwzTargetPath - ) -{ - HRESULT hr = S_OK; - - PMSIHANDLE hView = NULL; - PMSIHANDLE hRecObject = NULL; - PMSIHANDLE hRec = NULL; - - int iRoot = 0; - int iAllUsers = 0; - LPWSTR pwzKey = NULL; - LPWSTR pwzFormattedString = NULL; - - if (OT_SERVICE == eType) - { - hr = WcaTableExists(L"ServiceInstall"); - if (S_FALSE == hr) - { - hr = E_UNEXPECTED; - } - ExitOnFailure(hr, "failed to open ServiceInstall table to secure object"); - - hr = WcaOpenView(wzQUERY_SERVICEINSTALL, &hView); - ExitOnFailure(hr, "failed to open view on ServiceInstall table"); - - // create a record that stores the object to secure - hRec = MsiCreateRecord(1); - MsiRecordSetStringW(hRec, 1, pwzSecureObject); - - // execute a view looking for the object's ServiceInstall.ServiceInstall row. - hr = WcaExecuteView(hView, hRec); - ExitOnFailure(hr, "failed to execute view on ServiceInstall table"); - hr = WcaFetchSingleRecord(hView, &hRecObject); - ExitOnFailure(hr, "failed to fetch ServiceInstall row for secure object"); - - hr = WcaGetRecordFormattedString(hRecObject, QSSI_NAME, ppwzTargetPath); - ExitOnFailure(hr, "failed to get service name for secure object: %ls", pwzSecureObject); - } - else if (OT_FOLDER == eType) - { - hr = WcaGetTargetPath(pwzSecureObject, ppwzTargetPath); - ExitOnFailure(hr, "failed to get target path for directory id: %ls", pwzSecureObject); - } - else if (OT_FILE == eType) - { - hr = StrAllocFormatted(&pwzFormattedString, L"[#%s]", pwzSecureObject); - ExitOnFailure(hr, "failed to create formatted string for securing file object: %ls", pwzSecureObject); - - hr = WcaGetFormattedString(pwzFormattedString, ppwzTargetPath); - ExitOnFailure(hr, "failed to get file path from formatted string: %ls for secure object: %ls", pwzFormattedString, pwzSecureObject); - } - else if (OT_REGISTRY == eType) - { - hr = WcaTableExists(L"Registry"); - if (S_FALSE == hr) - { - hr = E_UNEXPECTED; - } - ExitOnFailure(hr, "failed to open Registry table to secure object"); - - hr = WcaOpenView(wzQUERY_REGISTRY, &hView); - ExitOnFailure(hr, "failed to open view on Registry table"); - - // create a record that stores the object to secure - hRec = MsiCreateRecord(1); - MsiRecordSetStringW(hRec, 1, pwzSecureObject); - - // execute a view looking for the object's Registry row - hr = WcaExecuteView(hView, hRec); - ExitOnFailure(hr, "failed to execute view on Registry table"); - hr = WcaFetchSingleRecord(hView, &hRecObject); - ExitOnFailure(hr, "failed to fetch Registry row for secure object"); - - hr = WcaGetRecordInteger(hRecObject, QSOC_REGROOT, &iRoot); - ExitOnFailure(hr, "Failed to get reg key root for secure object: %ls", pwzSecureObject); - - hr = WcaGetRecordFormattedString(hRecObject, QSOC_REGKEY, &pwzKey); - ExitOnFailure(hr, "Failed to get reg key for secure object: %ls", pwzSecureObject); - - // Decode the root value - if (-1 == iRoot) - { - // They didn't specify a root so that means it's either HKCU or HKLM depending on ALLUSERS property - hr = WcaGetIntProperty(L"ALLUSERS", &iAllUsers); - ExitOnFailure(hr, "failed to get value of ALLUSERS property"); - - if (1 == iAllUsers) - { - hr = StrAllocString(ppwzTargetPath, L"MACHINE\\", 0); - ExitOnFailure(hr, "failed to allocate target registry string with HKLM root"); - } - else - { - hr = StrAllocString(ppwzTargetPath, L"CURRENT_USER\\", 0); - ExitOnFailure(hr, "failed to allocate target registry string with HKCU root"); - } - } - else if (msidbRegistryRootClassesRoot == iRoot) - { - hr = StrAllocString(ppwzTargetPath, L"CLASSES_ROOT\\", 0); - ExitOnFailure(hr, "failed to allocate target registry string with HKCR root"); - } - else if (msidbRegistryRootCurrentUser == iRoot) - { - hr = StrAllocString(ppwzTargetPath, L"CURRENT_USER\\", 0); - ExitOnFailure(hr, "failed to allocate target registry string with HKCU root"); - } - else if (msidbRegistryRootLocalMachine == iRoot) - { - hr = StrAllocString(ppwzTargetPath, L"MACHINE\\", 0); - ExitOnFailure(hr, "failed to allocate target registry string with HKLM root"); - } - else if (msidbRegistryRootUsers == iRoot) - { - hr = StrAllocString(ppwzTargetPath, L"USERS\\", 0); - ExitOnFailure(hr, "failed to allocate target registry string with HKU root"); - } - else - { - ExitOnFailure(hr = E_UNEXPECTED, "Unknown registry key root specified for secure object: '%ls' root: %d", pwzSecureObject, iRoot); - } - - hr = StrAllocConcat(ppwzTargetPath, pwzKey, 0); - ExitOnFailure(hr, "Failed to concat key: %ls for secure object: %ls", pwzKey, pwzSecureObject); - } - else - { - AssertSz(FALSE, "How did you get here?"); - ExitOnFailure(hr = E_UNEXPECTED, "Unknown secure object type: %d", eType); - } - -LExit: - ReleaseStr(pwzFormattedString); - ReleaseStr(pwzKey); - - return hr; -} - -/****************************************************************** - SchedSecureObjects - entry point for SchedSecureObjects Custom Action - - called as Type 1 CustomAction (binary DLL) from Windows Installer - in InstallExecuteSequence, to schedule ExecSecureObjects -******************************************************************/ -extern "C" UINT __stdcall SchedSecureObjects( - __in MSIHANDLE hInstall - ) -{ -// AssertSz(FALSE, "debug SchedSecureObjects"); - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - LPWSTR pwzSecureObject = NULL; - LPWSTR pwzData = NULL; - LPWSTR pwzTable = NULL; - LPWSTR pwzTargetPath = NULL; - - PMSIHANDLE hView = NULL; - PMSIHANDLE hRec = NULL; - - INSTALLSTATE isInstalled; - INSTALLSTATE isAction; - - LPWSTR pwzCustomActionData = NULL; - - DWORD cObjects = 0; - eOBJECTTYPE eType = OT_UNKNOWN; - DWORD dwAttributes = 0; - - // - // initialize - // - hr = WcaInitialize(hInstall, "SchedSecureObjects"); - ExitOnFailure(hr, "failed to initialize"); - - // anything to do? - if (S_OK != WcaTableExists(L"Wix4SecureObject")) - { - WcaLog(LOGMSG_STANDARD, "Wix4SecureObject table doesn't exist, so there are no objects to secure."); - ExitFunction(); - } - - // - // loop through all the objects to be secured - // - hr = WcaOpenExecuteView(wzQUERY_SECUREOBJECTS, &hView); - ExitOnFailure(hr, "failed to open view on Wix4SecureObject table"); - while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) - { - hr = WcaGetRecordString(hRec, QSO_TABLE, &pwzTable); - ExitOnFailure(hr, "failed to get object table"); - - eType = EObjectTypeFromString(pwzTable); - - if (OT_UNKNOWN == eType) - { - ExitOnFailure(hr = E_INVALIDARG, "unknown SecureObject.Table: %ls", pwzTable); - } - - int iCompAttributes = 0; - hr = WcaGetRecordInteger(hRec, QSO_COMPATTRIBUTES, &iCompAttributes); - ExitOnFailure(hr, "failed to get Component attributes for secure object"); - - BOOL fIs64Bit = iCompAttributes & msidbComponentAttributes64bit; - - // Only process entries in the Wix4SecureObject table whose components match the bitness of this CA -#ifdef _WIN64 - if (!fIs64Bit) - { - continue; - } -#else - if (fIs64Bit) - { - continue; - } -#endif - - // Get the object to secure - hr = WcaGetRecordString(hRec, QSO_SECUREOBJECT, &pwzSecureObject); - ExitOnFailure(hr, "failed to get name of object"); - - hr = GetTargetPath(eType, pwzSecureObject, &pwzTargetPath); - ExitOnFailure(hr, "failed to get target path of object '%ls'", pwzSecureObject); - - hr = WcaGetRecordString(hRec, QSO_COMPONENT, &pwzData); - ExitOnFailure(hr, "failed to get Component name for secure object"); - - // - // if we are installing this Component - // - er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); - ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "failed to get install state for Component: %ls", pwzData); - - if (WcaIsInstalling(isInstalled, isAction)) - { - hr = WcaWriteStringToCaData(pwzTargetPath, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add data to CustomActionData"); - - // add the data to the CustomActionData - hr = WcaGetRecordString(hRec, QSO_SECUREOBJECT, &pwzData); - ExitOnFailure(hr, "failed to get name of object"); - hr = WcaWriteStringToCaData(pwzTable, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add data to CustomActionData"); - - hr = WcaGetRecordFormattedString(hRec, QSO_DOMAIN, &pwzData); - ExitOnFailure(hr, "failed to get domain for user to configure object"); - hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add data to CustomActionData"); - - hr = WcaGetRecordFormattedString(hRec, QSO_USER, &pwzData); - ExitOnFailure(hr, "failed to get user to configure object"); - hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add data to CustomActionData"); - - hr = WcaGetRecordInteger(hRec, QSO_ATTRIBUTES, reinterpret_cast(&dwAttributes)); - ExitOnFailure(hr, "failed to get attributes to configure object"); - hr = WcaWriteIntegerToCaData(dwAttributes, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add data to CustomActionData"); - - hr = WcaGetRecordString(hRec, QSO_PERMISSION, &pwzData); - ExitOnFailure(hr, "failed to get permission to configure object"); - hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add data to CustomActionData"); - - ++cObjects; - } - } - - // if we looped through all records all is well - if (E_NOMOREITEMS == hr) - hr = S_OK; - ExitOnFailure(hr, "failed while looping through all objects to secure"); - - // - // schedule the custom action and add to progress bar - // - if (pwzCustomActionData && *pwzCustomActionData) - { - Assert(0 < cObjects); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecSecureObjects"), pwzCustomActionData, cObjects * COST_SECUREOBJECT); - ExitOnFailure(hr, "failed to schedule ExecSecureObjects action"); - } - -LExit: - ReleaseStr(pwzSecureObject); - ReleaseStr(pwzCustomActionData); - ReleaseStr(pwzData); - ReleaseStr(pwzTable); - ReleaseStr(pwzTargetPath); - - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - return WcaFinalize(er); -} - -/****************************************************************** - SchedSecureObjectsRollback - entry point for SchedSecureObjectsRollback Custom Action - - called as Type 1 CustomAction (binary DLL) from Windows Installer - in InstallExecuteSequence before SchedSecureObjects -******************************************************************/ -extern "C" UINT __stdcall SchedSecureObjectsRollback( - __in MSIHANDLE hInstall - ) -{ -// AssertSz(FALSE, "debug SchedSecureObjectsRollback"); - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - LPWSTR pwzSecureObject = NULL; - LPWSTR pwzTable = NULL; - LPWSTR pwzTargetPath = NULL; - - PMSIHANDLE hView = NULL; - PMSIHANDLE hRec = NULL; - - LPWSTR pwzCustomActionData = NULL; - - eOBJECTTYPE eType = OT_UNKNOWN; - - // - // initialize - // - hr = WcaInitialize(hInstall, "SchedSecureObjectsRollback"); - ExitOnFailure(hr, "failed to initialize"); - - // - // loop through all the objects to be secured - // - hr = WcaOpenExecuteView(wzQUERY_SECUREOBJECTS, &hView); - ExitOnFailure(hr, "failed to open view on Wix4SecureObject table"); - while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) - { - hr = WcaGetRecordString(hRec, QSO_TABLE, &pwzTable); - ExitOnFailure(hr, "failed to get object table"); - - eType = EObjectTypeFromString(pwzTable); - - if (OT_UNKNOWN == eType) - { - ExitOnFailure(hr = E_INVALIDARG, "unknown SecureObject.Table: %ls", pwzTable); - } - - int iCompAttributes = 0; - hr = WcaGetRecordInteger(hRec, QSO_COMPATTRIBUTES, &iCompAttributes); - ExitOnFailure(hr, "failed to get Component attributes for secure object"); - - BOOL fIs64Bit = iCompAttributes & msidbComponentAttributes64bit; - - // Only process entries in the Wix4SecureObject table whose components match the bitness of this CA -#ifdef _WIN64 - if (!fIs64Bit) - { - continue; - } -#else - if (fIs64Bit) - { - continue; - } -#endif - - // get the object being secured that we are planning to schedule rollback for - hr = WcaGetRecordString(hRec, QSO_SECUREOBJECT, &pwzSecureObject); - ExitOnFailure(hr, "failed to get name of object"); - - hr = GetTargetPath(eType, pwzSecureObject, &pwzTargetPath); - ExitOnFailure(hr, "failed to get target path of object '%ls' in order to schedule rollback", pwzSecureObject); - - hr = StoreACLRollbackInfo(pwzTargetPath, pwzTable); - if (FAILED(hr)) - { - WcaLog(LOGMSG_STANDARD, "Failed to store ACL rollback information with error 0x%x - continuing", hr); - } - } - - // if we looped through all records all is well - if (E_NOMOREITEMS == hr) - { - hr = S_OK; - } - ExitOnFailure(hr, "failed while looping through all objects to schedule rollback for"); - -LExit: - ReleaseStr(pwzCustomActionData); - ReleaseStr(pwzSecureObject); - ReleaseStr(pwzTable); - ReleaseStr(pwzTargetPath); - - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - return WcaFinalize(er); -} - -/****************************************************************** - CaExecSecureObjects - entry point for SecureObjects Custom Action - called as Type 1025 CustomAction (deferred binary DLL) - - NOTE: deferred CustomAction since it modifies the machine - NOTE: CustomActionData == wzObject\twzTable\twzDomain\twzUser\tdwAttributes\tdwPermissions\t... -******************************************************************/ -extern "C" UINT __stdcall ExecSecureObjects( - __in MSIHANDLE hInstall - ) -{ -// AssertSz(FALSE, "debug ExecSecureObjects"); - HRESULT hr = S_OK; - DWORD er = ERROR_SUCCESS; - - LPWSTR pwz = NULL; - LPWSTR pwzData = NULL; - LPWSTR pwzObject = NULL; - LPWSTR pwzTable = NULL; - LPWSTR pwzDomain = NULL; - DWORD dwRevision = 0; - LPWSTR pwzUser = NULL; - DWORD dwPermissions = 0; - DWORD dwAttributes = 0; - LPWSTR pwzAccount = NULL; - PSID psid = NULL; - - EXPLICIT_ACCESSW ea = {0}; - SE_OBJECT_TYPE objectType = SE_UNKNOWN_OBJECT_TYPE; - PSECURITY_DESCRIPTOR psd = NULL; - SECURITY_DESCRIPTOR_CONTROL sdc = {0}; - SECURITY_INFORMATION si = {0}; - PACL pAclExisting = NULL; // doesn't get freed - PACL pAclNew = NULL; - - PMSIHANDLE hActionRec = ::MsiCreateRecord(1); - - // - // initialize - // - hr = WcaInitialize(hInstall, "ExecSecureObjects"); - ExitOnFailure(hr, "failed to initialize"); - - hr = WcaGetProperty(L"CustomActionData", &pwzData); - ExitOnFailure(hr, "failed to get CustomActionData"); - - WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); - - pwz = pwzData; - - // - // loop through all the passed in data - // - while (pwz && *pwz) - { - hr = WcaReadStringFromCaData(&pwz, &pwzObject); - ExitOnFailure(hr, "failed to process CustomActionData"); - - hr = WcaReadStringFromCaData(&pwz, &pwzTable); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzDomain); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzUser); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwAttributes)); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwPermissions)); - ExitOnFailure(hr, "failed to process CustomActionData"); - - WcaLog(LOGMSG_VERBOSE, "Securing Object: %ls Type: %ls User: %ls", pwzObject, pwzTable, pwzUser); - - // - // create the appropriate SID - // - - // figure out the right user to put into the access block - if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Everyone")) - { - hr = AclGetWellKnownSid(WinWorldSid, &psid); - } - else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Administrators")) - { - hr = AclGetWellKnownSid(WinBuiltinAdministratorsSid, &psid); - } - else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"LocalSystem")) - { - hr = AclGetWellKnownSid(WinLocalSystemSid, &psid); - } - else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"LocalService")) - { - hr = AclGetWellKnownSid(WinLocalServiceSid, &psid); - } - else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"NetworkService")) - { - hr = AclGetWellKnownSid(WinNetworkServiceSid, &psid); - } - else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"AuthenticatedUser")) - { - hr = AclGetWellKnownSid(WinAuthenticatedUserSid, &psid); - } - else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Guests")) - { - hr = AclGetWellKnownSid(WinBuiltinGuestsSid, &psid); - } - else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"CREATOR OWNER")) - { - hr = AclGetWellKnownSid(WinCreatorOwnerSid, &psid); - } - else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"INTERACTIVE")) - { - hr = AclGetWellKnownSid(WinInteractiveSid, &psid); - } - else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Users")) - { - hr = AclGetWellKnownSid(WinBuiltinUsersSid, &psid); - } - else - { - hr = StrAllocFormatted(&pwzAccount, L"%s%s%s", pwzDomain, *pwzDomain ? L"\\" : L"", pwzUser); - ExitOnFailure(hr, "failed to build domain user name"); - - hr = AclGetAccountSid(NULL, pwzAccount, &psid); - } - ExitOnFailure(hr, "failed to get sid for account: %ls%ls%ls", pwzDomain, *pwzDomain ? L"\\" : L"", pwzUser); - - // - // build up the explicit access - // - ea.grfAccessMode = SET_ACCESS; - - if (dwAttributes & SECURE_OBJECT_ATTRIBUTE_INHERITABLE) - { - ea.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; - } - else - { - ea.grfInheritance = NO_INHERITANCE; - } - -#pragma prefast(push) -#pragma prefast(disable:25029) - ::BuildTrusteeWithSidW(&ea.Trustee, psid); -#pragma prefast(pop) - - objectType = SEObjectTypeFromString(const_cast (pwzTable)); - - // always add these permissions for services - // these are basic permissions that are often forgotten - if (0 == lstrcmpW(L"ServiceInstall", pwzTable)) - { - dwPermissions |= SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_INTERROGATE; - } - - ea.grfAccessPermissions = dwPermissions; - - if (SE_UNKNOWN_OBJECT_TYPE != objectType) - { - er = ::GetNamedSecurityInfoW(pwzObject, objectType, DACL_SECURITY_INFORMATION, NULL, NULL, &pAclExisting, NULL, &psd); - ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "failed to get security info for object: %ls", pwzObject); - - //Need to see if DACL is protected so getting Descriptor information - if (!::GetSecurityDescriptorControl(psd, &sdc, &dwRevision)) - { - ExitOnLastError(hr, "failed to get security descriptor control for object: %ls", pwzObject); - } - -#pragma prefast(push) -#pragma prefast(disable:25029) - er = ::SetEntriesInAclW(1, &ea, pAclExisting, &pAclNew); -#pragma prefast(pop) - ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "failed to add ACLs for object: %ls", pwzObject); - - if (sdc & SE_DACL_PROTECTED) - { - si = DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION; - } - else - { - si = DACL_SECURITY_INFORMATION; - } - er = ::SetNamedSecurityInfoW(pwzObject, objectType, si, NULL, NULL, pAclNew, NULL); - MessageExitOnFailure(hr = HRESULT_FROM_WIN32(er), msierrSecureObjectsFailedSet, "failed to set security info for object: %ls", pwzObject); - } - else - { - MessageExitOnFailure(hr = E_UNEXPECTED, msierrSecureObjectsUnknownType, "unknown object type: %ls", pwzTable); - } - - hr = WcaProgressMessage(COST_SECUREOBJECT, FALSE); - ExitOnFailure(hr, "failed to send progress message"); - - objectType = SE_UNKNOWN_OBJECT_TYPE; - } - -LExit: - ReleaseStr(pwzUser); - ReleaseStr(pwzDomain); - ReleaseStr(pwzTable); - ReleaseStr(pwzObject); - ReleaseStr(pwzData); - ReleaseStr(pwzAccount); - - if (pAclNew) - { - ::LocalFree(pAclNew); - } - if (psd) - { - ::LocalFree(psd); - } - if (psid) - { - AclFreeSid(psid); - } - - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - return WcaFinalize(er); -} - -extern "C" UINT __stdcall ExecSecureObjectsRollback( - __in MSIHANDLE hInstall - ) -{ -// AssertSz(FALSE, "debug ExecSecureObjectsRollback"); - HRESULT hr = S_OK; - DWORD er = ERROR_SUCCESS; - - LPWSTR pwz = NULL; - LPWSTR pwzData = NULL; - LPWSTR pwzObject = NULL; - LPWSTR pwzTable = NULL; - LPWSTR pwzSecurityInfo = NULL; - - SE_OBJECT_TYPE objectType = SE_UNKNOWN_OBJECT_TYPE; - PSECURITY_DESCRIPTOR psd = NULL; - ULONG psdSize; - SECURITY_DESCRIPTOR_CONTROL sdc = {0}; - SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; - PACL pDacl = NULL; - BOOL bDaclPresent = false; - BOOL bDaclDefaulted = false; - DWORD dwRevision = 0; - int iProtected; - - // initialize - hr = WcaInitialize(hInstall, "ExecSecureObjectsRollback"); - ExitOnFailure(hr, "failed to initialize"); - - hr = WcaGetProperty(L"CustomActionData", &pwzData); - ExitOnFailure(hr, "failed to get CustomActionData"); - - WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); - - pwz = pwzData; - - hr = WcaReadStringFromCaData(&pwz, &pwzObject); - ExitOnFailure(hr, "failed to process CustomActionData"); - - hr = WcaReadStringFromCaData(&pwz, &pwzTable); - ExitOnFailure(hr, "failed to process CustomActionData"); - - objectType = SEObjectTypeFromString(const_cast (pwzTable)); - - if (SE_UNKNOWN_OBJECT_TYPE != objectType) - { - hr = WcaReadStringFromCaData(&pwz, &pwzSecurityInfo); - ExitOnFailure(hr, "failed to process CustomActionData"); - - hr = WcaReadIntegerFromCaData(&pwz, &iProtected); - ExitOnFailure(hr, "failed to process CustomActionData"); - - if (!::ConvertStringSecurityDescriptorToSecurityDescriptorW(pwzSecurityInfo,SDDL_REVISION_1,&psd,&psdSize)) - { - ExitOnLastError(hr, "failed to convert security descriptor string to a valid security descriptor"); - } - - if (!::GetSecurityDescriptorDacl(psd,&bDaclPresent,&pDacl,&bDaclDefaulted)) - { - hr = E_UNEXPECTED; - ExitOnFailure(hr, "failed to get security descriptor's DACL - error code: %d",pwzSecurityInfo,GetLastError()); - } - - // The below situation may always be caught by the above if block - the documentation isn't very clear. To be safe, we're going to test for it. - if (!bDaclPresent) - { - hr = E_UNEXPECTED; - ExitOnFailure(hr, "security descriptor does not contain a DACL"); - } - - //Need to see if DACL is protected so getting Descriptor information - if (!::GetSecurityDescriptorControl(psd, &sdc, &dwRevision)) - { - ExitOnLastError(hr, "failed to get security descriptor control for object: %ls", pwzObject); - } - - // Write a 1 if DACL is protected, 0 otherwise - switch (iProtected) - { - case 0: - // Unnecessary to do anything - leave si to the default flags - break; - - case 1: - si = si | PROTECTED_DACL_SECURITY_INFORMATION; - break; - - default: - hr = E_UNEXPECTED; - ExitOnFailure(hr, "unrecognized value in CustomActionData"); - break; - } - - er = ::SetNamedSecurityInfoW(pwzObject, objectType, si, NULL, NULL, pDacl, NULL); - ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "failed to set security info for object: %ls error code: %d", pwzObject, GetLastError()); - } - else - { - MessageExitOnFailure(hr = E_UNEXPECTED, msierrSecureObjectsUnknownType, "unknown object type: %ls", pwzTable); - } - -LExit: - ReleaseStr(pwzData); - ReleaseStr(pwzObject); - ReleaseStr(pwzTable); - ReleaseStr(pwzSecurityInfo); - - if (psd) - { - ::LocalFree(psd); - } - - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - return WcaFinalize(er); -} diff --git a/src/ca/serviceconfig.cpp b/src/ca/serviceconfig.cpp deleted file mode 100644 index 04b25ffa..00000000 --- a/src/ca/serviceconfig.cpp +++ /dev/null @@ -1,821 +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" - -// structs -LPCWSTR wzQUERY_SERVICECONFIG = L"SELECT `ServiceName`, `Component_`, `NewService`, `FirstFailureActionType`, `SecondFailureActionType`, `ThirdFailureActionType`, `ResetPeriodInDays`, `RestartServiceDelayInSeconds`, `ProgramCommandLine`, `RebootMessage` FROM `Wix4ServiceConfig`"; -enum eQUERY_SERVICECONFIG { QSC_SERVICENAME = 1, QSC_COMPONENT, QSC_NEWSERVICE, QSC_FIRSTFAILUREACTIONTYPE, QSC_SECONDFAILUREACTIONTYPE, QSC_THIRDFAILUREACTIONTYPE, QSC_RESETPERIODINDAYS, QSC_RESTARTSERVICEDELAYINSECONDS, QSC_PROGRAMCOMMANDLINE, QSC_REBOOTMESSAGE }; - -// consts -LPCWSTR c_wzActionTypeNone = L"none"; -LPCWSTR c_wzActionTypeReboot = L"reboot"; -LPCWSTR c_wzActionTypeRestart = L"restart"; -LPCWSTR c_wzActionTypeRunCommand = L"runCommand"; - -// prototypes -static SC_ACTION_TYPE GetSCActionType( - __in LPCWSTR pwzActionTypeName - ); - -static HRESULT GetSCActionTypeString( - __in SC_ACTION_TYPE type, - __out_ecount(cchActionTypeString) LPWSTR wzActionTypeString, - __in DWORD cchActionTypeString - ); - -static HRESULT GetService( - __in SC_HANDLE hSCM, - __in LPCWSTR wzService, - __in DWORD dwOpenServiceAccess, - __out SC_HANDLE* phService - ); - -static HRESULT ConfigureService( - __in SC_HANDLE hSCM, - __in SC_HANDLE hService, - __in LPCWSTR wzServiceName, - __in DWORD dwRestartServiceDelayInSeconds, - __in LPCWSTR wzFirstFailureActionType, - __in LPCWSTR wzSecondFailureActionType, - __in LPCWSTR wzThirdFailureActionType, - __in DWORD dwResetPeriodInDays, - __in LPWSTR wzRebootMessage, - __in LPWSTR wzProgramCommandLine - ); - - -/****************************************************************** -SchedServiceConfig - entry point for SchedServiceConfig Custom Action - -called as Type 1 CustomAction (binary DLL) from Windows Installer -in InstallExecuteSequence before CaExecServiceConfig -********************************************************************/ -extern "C" UINT __stdcall SchedServiceConfig( - __in MSIHANDLE hInstall - ) -{ - //AssertSz(FALSE, "debug SchedServiceConfig"); - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - LPWSTR pwzScriptKey = NULL; - LPWSTR pwzCustomActionData = NULL; - - PMSIHANDLE hView = NULL; - PMSIHANDLE hRec = NULL; - LPWSTR pwzData = NULL; - int iData = 0; - DWORD cServices = 0; - - // initialize - hr = WcaInitialize(hInstall, "SchedServiceConfig"); - ExitOnFailure(hr, "Failed to initialize."); - - // Get the script key for this CustomAction and put it on the front of the - // CustomActionData of the install action. - hr = WcaCaScriptCreateKey(&pwzScriptKey); - ExitOnFailure(hr, "Failed to get encoding key."); - - hr = WcaWriteStringToCaData(pwzScriptKey, &pwzCustomActionData); - ExitOnFailure(hr, "Failed to add encoding key to CustomActionData."); - - // Loop through all the services to be configured. - hr = WcaOpenExecuteView(wzQUERY_SERVICECONFIG, &hView); - ExitOnFailure(hr, "Failed to open view on Wix4ServiceConfig table."); - - while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) - { - INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN; - INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN; - - // Get component name to check if we are installing it. If so - // then add the table data to the CustomActionData, otherwise - // skip it. - hr = WcaGetRecordString(hRec, QSC_COMPONENT, &pwzData); - ExitOnFailure(hr, "Failed to get component name"); - - hr = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); - ExitOnFailure(hr = HRESULT_FROM_WIN32(hr), "Failed to get install state for Component: %ls", pwzData); - - if (WcaIsInstalling(isInstalled, isAction)) - { - // Add the data to the CustomActionData (for install). - hr = WcaGetRecordFormattedString(hRec, QSC_SERVICENAME, &pwzData); - ExitOnFailure(hr, "Failed to get name of service."); - hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); - ExitOnFailure(hr, "Failed to add name to CustomActionData."); - - hr = WcaGetRecordInteger(hRec, QSC_NEWSERVICE, &iData); - ExitOnFailure(hr, "Failed to get Wix4ServiceConfig.NewService."); - hr = WcaWriteIntegerToCaData(0 != iData, &pwzCustomActionData); - ExitOnFailure(hr, "Failed to add NewService data to CustomActionData"); - - hr = WcaGetRecordString(hRec, QSC_FIRSTFAILUREACTIONTYPE, &pwzData); - ExitOnFailure(hr, "failed to get first failure action type"); - hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add data to CustomActionData"); - - hr = WcaGetRecordString(hRec, QSC_SECONDFAILUREACTIONTYPE, &pwzData); - ExitOnFailure(hr, "failed to get second failure action type"); - hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add data to CustomActionData"); - - hr = WcaGetRecordString(hRec, QSC_THIRDFAILUREACTIONTYPE, &pwzData); - ExitOnFailure(hr, "failed to get third failure action type"); - hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add data to CustomActionData"); - - hr = WcaGetRecordInteger(hRec, QSC_RESETPERIODINDAYS, &iData); - if (S_FALSE == hr) // deal w/ possible null value - { - iData = 0; - } - ExitOnFailure(hr, "failed to get reset period in days between service restart attempts."); - hr = WcaWriteIntegerToCaData(iData, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add data to CustomActionData"); - - hr = WcaGetRecordInteger(hRec, QSC_RESTARTSERVICEDELAYINSECONDS, &iData); - if (S_FALSE == hr) // deal w/ possible null value - { - iData = 0; - } - ExitOnFailure(hr, "failed to get server restart delay value."); - hr = WcaWriteIntegerToCaData(iData, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add data to CustomActionData"); - - hr = WcaGetRecordFormattedString(hRec, QSC_PROGRAMCOMMANDLINE, &pwzData); // null value already dealt w/ properly - ExitOnFailure(hr, "failed to get command line to run on service failure."); - hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add data to CustomActionData"); - - hr = WcaGetRecordString(hRec, QSC_REBOOTMESSAGE, &pwzData); // null value already dealt w/ properly - ExitOnFailure(hr, "failed to get message to send to users when server reboots due to service failure."); - hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); - ExitOnFailure(hr, "failed to add data to CustomActionData"); - - ++cServices; - } - } - - // if we looped through all records all is well - if (E_NOMOREITEMS == hr) - { - hr = S_OK; - } - ExitOnFailure(hr, "failed while looping through all objects to secure"); - - // setup CustomActionData and add to progress bar for download - if (0 < cServices) - { - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackServiceConfig"), pwzScriptKey, cServices * COST_SERVICECONFIG); - ExitOnFailure(hr, "failed to schedule RollbackServiceConfig action"); - - hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecServiceConfig"), pwzCustomActionData, cServices * COST_SERVICECONFIG); - ExitOnFailure(hr, "failed to schedule ExecServiceConfig action"); - } - -LExit: - ReleaseStr(pwzData); - ReleaseStr(pwzCustomActionData); - ReleaseStr(pwzScriptKey); - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - -/****************************************************************** -CaExecServiceConfig - entry point for ServiceConfig Custom Action. - -NOTE: deferred CustomAction since it modifies the machine -NOTE: CustomActionData == wzServiceName\tfNewService\twzFirstFailureActionType\twzSecondFailureActionType\twzThirdFailureActionType\tdwResetPeriodInDays\tdwRestartServiceDelayInSeconds\twzProgramCommandLine\twzRebootMessage\twzServiceName\tfNewService\t... -*******************************************************************/ -extern "C" UINT __stdcall ExecServiceConfig( - __in MSIHANDLE hInstall - ) -{ - //AssertSz(FALSE, "debug ExecServiceConfig"); - HRESULT hr = S_OK; - DWORD er = 0; - - LPWSTR pwzCustomActionData = NULL; - LPWSTR pwz = NULL; - - LPWSTR pwzScriptKey = NULL; - WCA_CASCRIPT_HANDLE hRollbackScript = NULL; - - LPWSTR pwzServiceName = NULL; - BOOL fNewService = FALSE; - LPWSTR pwzFirstFailureActionType = NULL; - LPWSTR pwzSecondFailureActionType = NULL; - LPWSTR pwzThirdFailureActionType = NULL; - LPWSTR pwzProgramCommandLine = NULL; - LPWSTR pwzRebootMessage = NULL; - DWORD dwResetPeriodInDays = 0; - DWORD dwRestartServiceDelayInSeconds = 0; - - LPVOID lpMsgBuf = NULL; - SC_HANDLE hSCM = NULL; - SC_HANDLE hService = NULL; - - DWORD dwRestartDelay = 0; - WCHAR wzActionName[32] = { 0 }; - - DWORD cbExistingServiceConfig = 0; - - SERVICE_FAILURE_ACTIONSW* psfa = NULL; - - // initialize - hr = WcaInitialize(hInstall, "ExecServiceConfig"); - ExitOnFailure(hr, "failed to initialize"); - - // Open the Services Control Manager up front. - hSCM = ::OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT); - if (NULL == hSCM) - { - er = ::GetLastError(); - hr = HRESULT_FROM_WIN32(er); - -#pragma prefast(push) -#pragma prefast(disable:25028) - ::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, er, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpMsgBuf, 0, NULL); -#pragma prefast(pop) - - ExitOnFailure(hr, "Failed to get handle to SCM. Error: %ls", (LPWSTR)lpMsgBuf); - } - - // First, get the script key out of the CustomActionData and - // use that to create the rollback script for this action. - hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData); - ExitOnFailure(hr, "failed to get CustomActionData"); - - WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); - - pwz = pwzCustomActionData; - - hr = WcaReadStringFromCaData(&pwz, &pwzScriptKey); - if (!pwzScriptKey) - { - hr = E_UNEXPECTED; - ExitOnFailure(hr, "Failed due to unexpected CustomActionData passed."); - } - ExitOnFailure(hr, "Failed to read encoding key from CustomActionData."); - - hr = WcaCaScriptCreate(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, FALSE, &hRollbackScript); - ExitOnFailure(hr, "Failed to open rollback CustomAction script."); - - // Next, loop through the rest of the CustomActionData, processing - // each service config row in turn. - while (pwz && *pwz) - { - hr = WcaReadStringFromCaData(&pwz, &pwzServiceName); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&fNewService)); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzFirstFailureActionType); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzSecondFailureActionType); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzThirdFailureActionType); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwResetPeriodInDays)); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwRestartServiceDelayInSeconds)); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzProgramCommandLine); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzRebootMessage); - ExitOnFailure(hr, "failed to process CustomActionData"); - - WcaLog(LOGMSG_VERBOSE, "Configuring Service: %ls", pwzServiceName); - - // Open the handle with all the permissions we might need: - // SERVICE_QUERY_CONFIG is needed for QueryServiceConfig2(). - // SERVICE_CHANGE_CONFIG is needed for ChangeServiceConfig2(). - // SERVICE_START is required in order to handle SC_ACTION_RESTART action. - hr = GetService(hSCM, pwzServiceName, SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG | SERVICE_START, &hService); - ExitOnFailure(hr, "Failed to get service: %ls", pwzServiceName); - - // If we are configuring a service that existed on the machine, we need to - // read the existing service configuration and write it out to the rollback - // log so rollback can put it back if anything goes wrong. - if (!fNewService) - { - // First, read the existing service config. - if (!::QueryServiceConfig2W(hService, SERVICE_CONFIG_FAILURE_ACTIONS, NULL, 0, &cbExistingServiceConfig) && ERROR_INSUFFICIENT_BUFFER != ::GetLastError()) - { - ExitWithLastError(hr, "Failed to get current service config info."); - } - - psfa = static_cast(MemAlloc(cbExistingServiceConfig, TRUE)); - ExitOnNull(psfa, hr, E_OUTOFMEMORY, "failed to allocate memory for service failure actions."); - - if (!::QueryServiceConfig2W(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPBYTE)psfa, cbExistingServiceConfig, &cbExistingServiceConfig)) - { - ExitOnLastError(hr, "failed to Query Service."); - } - - // Build up rollback log so we can restore service state if necessary - hr = WcaCaScriptWriteString(hRollbackScript, pwzServiceName); - ExitOnFailure(hr, "Failed to add service name to Rollback Log"); - - // If this service struct is empty, fill in default values - if (3 > psfa->cActions) - { - hr = WcaCaScriptWriteString(hRollbackScript, c_wzActionTypeNone); - ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); - - hr = WcaCaScriptWriteString(hRollbackScript, c_wzActionTypeNone); - ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); - - hr = WcaCaScriptWriteString(hRollbackScript, c_wzActionTypeNone); - ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); - } - else - { - // psfa actually had actions defined, so use the first three. - for (int i = 0; i < 3; ++i) - { - hr = GetSCActionTypeString(psfa->lpsaActions[i].Type, wzActionName, countof(wzActionName)); - ExitOnFailure(hr, "failed to query SFA object"); - - if (SC_ACTION_RESTART == psfa->lpsaActions[i].Type) - { - dwRestartDelay = psfa->lpsaActions[i].Delay / 1000; - } - - hr = WcaCaScriptWriteString(hRollbackScript, wzActionName); - ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); - } - } - - hr = WcaCaScriptWriteNumber(hRollbackScript, psfa->dwResetPeriod / (24 * 60 * 60)); - ExitOnFailure(hr, "failed to add data to CustomActionData"); - - hr = WcaCaScriptWriteNumber(hRollbackScript, dwRestartDelay); - ExitOnFailure(hr, "failed to add data to CustomActionData"); - - // Handle the null cases. - if (!psfa->lpCommand) - { - psfa->lpCommand = L""; - } - hr = WcaCaScriptWriteString(hRollbackScript, psfa->lpCommand); - ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); - - // Handle the null cases. - if (!psfa->lpRebootMsg) - { - psfa->lpRebootMsg = L""; - } - hr = WcaCaScriptWriteString(hRollbackScript, psfa->lpRebootMsg); - ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); - - // Nudge the system to get all our rollback data written to disk. - WcaCaScriptFlush(hRollbackScript); - - ReleaseNullMem(psfa); - } - - hr = ConfigureService(hSCM, hService, pwzServiceName, dwRestartServiceDelayInSeconds, pwzFirstFailureActionType, - pwzSecondFailureActionType, pwzThirdFailureActionType, dwResetPeriodInDays, pwzRebootMessage, pwzProgramCommandLine); - ExitOnFailure(hr, "Failed to configure service: %ls", pwzServiceName); - - hr = WcaProgressMessage(COST_SERVICECONFIG, FALSE); - ExitOnFailure(hr, "failed to send progress message"); - - // Per-service cleanup - ::CloseServiceHandle(hService); - hService = NULL; - dwResetPeriodInDays = 0; - dwRestartServiceDelayInSeconds = 0; - } - -LExit: - WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_PRESERVE); - - if (lpMsgBuf) - { - ::LocalFree(lpMsgBuf); - } - - if (hService) - { - ::CloseServiceHandle(hService); - } - - if (hSCM) - { - ::CloseServiceHandle(hSCM); - } - - ReleaseMem(psfa); - - ReleaseStr(pwzRebootMessage); - ReleaseStr(pwzProgramCommandLine); - ReleaseStr(pwzThirdFailureActionType); - ReleaseStr(pwzSecondFailureActionType); - ReleaseStr(pwzFirstFailureActionType); - ReleaseStr(pwzServiceName); - ReleaseStr(pwzScriptKey); - ReleaseStr(pwzCustomActionData); - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - -/****************************************************************** -RollbackServiceConfig - entry point for ServiceConfig rollback - Custom Action. - -NOTE: CustomActionScript Data == wzServiceName\twzFirstFailureActionType\twzSecondFailureActionType\twzThirdFailureActionType\tdwResetPeriodInDays\tdwRestartServiceDelayInSeconds\twzProgramCommandLine\twzRebootMessage\twzServiceName\t... -*******************************************************************/ -extern "C" UINT __stdcall RollbackServiceConfig( - __in MSIHANDLE hInstall - ) -{ - //AssertSz(FALSE, "debug RollbackServiceConfig"); - HRESULT hr = S_OK; - DWORD er = 0; - - LPWSTR pwzCustomActionData = NULL; - LPWSTR pwz = NULL; - - LPWSTR pwzScriptKey = NULL; - WCA_CASCRIPT_HANDLE hRollbackScript = NULL; - - LPWSTR pwzServiceName = NULL; - LPWSTR pwzFirstFailureActionType = NULL; - LPWSTR pwzSecondFailureActionType = NULL; - LPWSTR pwzThirdFailureActionType = NULL; - LPWSTR pwzProgramCommandLine = NULL; - LPWSTR pwzRebootMessage = NULL; - DWORD dwResetPeriodInDays = 0; - DWORD dwRestartServiceDelayInSeconds = 0; - - LPVOID lpMsgBuf = NULL; - SC_HANDLE hSCM = NULL; - SC_HANDLE hService = NULL; - - // initialize - hr = WcaInitialize(hInstall, "RollbackServiceConfig"); - ExitOnFailure(hr, "Failed to initialize 'RollbackServiceConfig'."); - - // Open the Services Control Manager up front. - hSCM = ::OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT); - if (NULL == hSCM) - { - er = ::GetLastError(); - hr = HRESULT_FROM_WIN32(er); - -#pragma prefast(push) -#pragma prefast(disable:25028) - ::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, er, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpMsgBuf, 0, NULL); -#pragma prefast(pop) - - ExitOnFailure(hr, "Failed to get handle to SCM. Error: %ls", (LPWSTR)lpMsgBuf); - - // Make sure we still abort, in case hSCM was NULL but no error was returned from GetLastError - ExitOnNull(hSCM, hr, E_POINTER, "Getting handle to SCM reported success, but no handle was returned."); - } - - // Get the script key from the CustomAction data and use it to open - // the rollback log and read the data over the CustomActionData - // because all of the information is in the script data not the - // CustomActionData. - hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData); - ExitOnFailure(hr, "failed to get CustomActionData"); - - WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); - - pwz = pwzCustomActionData; - - hr = WcaReadStringFromCaData(&pwz, &pwzScriptKey); - if (!pwzScriptKey) - { - hr = E_UNEXPECTED; - ExitOnFailure(hr, "Failed due to unexpected CustomActionData passed."); - } - ExitOnFailure(hr, "Failed to read encoding key from CustomActionData."); - - hr = WcaCaScriptOpen(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, &hRollbackScript); - ExitOnFailure(hr, "Failed to open rollback CustomAction script."); - - hr = WcaCaScriptReadAsCustomActionData(hRollbackScript, &pwzCustomActionData); - ExitOnFailure(hr, "Failed to read rollback script into CustomAction data."); - - // Loop through the script's CustomActionData, processing each - // service config in turn. - pwz = pwzCustomActionData; - while (pwz && *pwz) - { - hr = WcaReadStringFromCaData(&pwz, &pwzServiceName); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzFirstFailureActionType); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzSecondFailureActionType); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzThirdFailureActionType); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwResetPeriodInDays)); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwRestartServiceDelayInSeconds)); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzProgramCommandLine); - ExitOnFailure(hr, "failed to process CustomActionData"); - hr = WcaReadStringFromCaData(&pwz, &pwzRebootMessage); - ExitOnFailure(hr, "failed to process CustomActionData"); - - WcaLog(LOGMSG_VERBOSE, "Reconfiguring Service: %ls", pwzServiceName); - - // Open the handle with all the permissions we might need. - // SERVICE_CHANGE_CONFIG is needed for ChangeServiceConfig2(). - // SERVICE_START is required in order to handle SC_ACTION_RESTART action. - hr = GetService(hSCM, pwzServiceName, SERVICE_CHANGE_CONFIG | SERVICE_START, &hService); - ExitOnFailure(hr, "Failed to get service: %ls", pwzServiceName); - - hr = ConfigureService(hSCM, hService, pwzServiceName, dwRestartServiceDelayInSeconds, pwzFirstFailureActionType, - pwzSecondFailureActionType, pwzThirdFailureActionType, dwResetPeriodInDays, pwzRebootMessage, pwzProgramCommandLine); - ExitOnFailure(hr, "Failed to configure service: %ls", pwzServiceName); - - hr = WcaProgressMessage(COST_SERVICECONFIG, FALSE); - ExitOnFailure(hr, "failed to send progress message"); - - // Per-service cleanup - ::CloseServiceHandle(hService); - hService = NULL; - dwResetPeriodInDays = 0; - dwRestartServiceDelayInSeconds = 0; - } - -LExit: - if (lpMsgBuf) // Allocated with FormatString. - { - ::LocalFree(lpMsgBuf); - } - - if (hService) - { - ::CloseServiceHandle(hService); - } - - if (hSCM) - { - ::CloseServiceHandle(hSCM); - } - - WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_DELETE); - - ReleaseStr(pwzRebootMessage); - ReleaseStr(pwzProgramCommandLine); - ReleaseStr(pwzThirdFailureActionType); - ReleaseStr(pwzSecondFailureActionType); - ReleaseStr(pwzFirstFailureActionType); - ReleaseStr(pwzServiceName); - ReleaseStr(pwzScriptKey); - ReleaseStr(pwzCustomActionData); - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - -/********************************************************** -GetSCActionType - helper function to return the SC_ACTION_TYPE -for a given string matching the allowed set. -REBOOT, RESTART, RUN_COMMAND and NONE -**********************************************************/ -static SC_ACTION_TYPE GetSCActionType( - __in LPCWSTR pwzActionTypeName - ) -{ - SC_ACTION_TYPE actionType; - - // verify that action types are valid. if not, just default to NONE - if (0 == lstrcmpiW(c_wzActionTypeReboot, pwzActionTypeName)) - { - actionType = SC_ACTION_REBOOT; - } - else if (0 == lstrcmpiW(c_wzActionTypeRestart, pwzActionTypeName)) - { - actionType = SC_ACTION_RESTART; - } - else if (0 == lstrcmpiW(c_wzActionTypeRunCommand, pwzActionTypeName)) - { - actionType = SC_ACTION_RUN_COMMAND; - } - else - { - // default to none - actionType = SC_ACTION_NONE; - } - - return actionType; -} - - -static HRESULT GetSCActionTypeString( - __in SC_ACTION_TYPE type, - __out_ecount(cchActionTypeString) LPWSTR wzActionTypeString, - __in DWORD cchActionTypeString - ) -{ - HRESULT hr = S_OK; - - switch (type) - { - case SC_ACTION_REBOOT: - hr = StringCchCopyW(wzActionTypeString, cchActionTypeString, c_wzActionTypeReboot); - ExitOnFailure(hr, "Failed to copy 'reboot' into action type."); - break; - case SC_ACTION_RESTART: - hr = StringCchCopyW(wzActionTypeString, cchActionTypeString, c_wzActionTypeRestart); - ExitOnFailure(hr, "Failed to copy 'restart' into action type."); - break; - case SC_ACTION_RUN_COMMAND: - hr = StringCchCopyW(wzActionTypeString, cchActionTypeString, c_wzActionTypeRunCommand); - ExitOnFailure(hr, "Failed to copy 'runCommand' into action type."); - break; - case SC_ACTION_NONE: - hr = StringCchCopyW(wzActionTypeString, cchActionTypeString, c_wzActionTypeNone); - ExitOnFailure(hr, "Failed to copy 'none' into action type."); - break; - default: - break; - } - -LExit: - return hr; -} - - -static HRESULT GetService( - __in SC_HANDLE hSCM, - __in LPCWSTR wzService, - __in DWORD dwOpenServiceAccess, - __out SC_HANDLE* phService - ) -{ - HRESULT hr = S_OK; - DWORD er = ERROR_SUCCESS; - LPVOID lpMsgBuf = NULL; - - *phService = ::OpenServiceW(hSCM, wzService, dwOpenServiceAccess); - if (NULL == *phService) - { - er = ::GetLastError(); - hr = HRESULT_FROM_WIN32(er); - if (ERROR_SERVICE_DOES_NOT_EXIST == er) - { - ExitOnFailure(hr, "Service '%ls' does not exist on this system.", wzService); - } - else - { -#pragma prefast(push) -#pragma prefast(disable:25028) - ::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, er, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpMsgBuf, 0, NULL); -#pragma prefast(pop) - - ExitOnFailure(hr, "Failed to get handle to the service '%ls'. Error: %ls", wzService, (LPWSTR)lpMsgBuf); - } - } - -LExit: - if (lpMsgBuf) // Allocated with FormatString. - { - ::LocalFree(lpMsgBuf); - } - - return hr; -} - - -static HRESULT ConfigureService( - __in SC_HANDLE /*hSCM*/, - __in SC_HANDLE hService, - __in LPCWSTR wzServiceName, - __in DWORD dwRestartServiceDelayInSeconds, - __in LPCWSTR wzFirstFailureActionType, - __in LPCWSTR wzSecondFailureActionType, - __in LPCWSTR wzThirdFailureActionType, - __in DWORD dwResetPeriodInDays, - __in LPWSTR wzRebootMessage, - __in LPWSTR wzProgramCommandLine - ) -{ - HRESULT hr = S_OK; - DWORD er = ERROR_SUCCESS; - - HANDLE hToken = NULL; - TOKEN_PRIVILEGES priv = { 0 }; - TOKEN_PRIVILEGES* pPrevPriv = NULL; - DWORD cbPrevPriv = 0; - BOOL fAdjustedPrivileges = FALSE; - - SC_ACTION actions[3]; // the UI always shows 3 actions, so we'll always do 3 - SERVICE_FAILURE_ACTIONSW sfa; - LPVOID lpMsgBuf = NULL; - - // Always get the shutdown privilege in case we need to configure service to reboot. - if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) - { - ExitWithLastError(hr, "Failed to get process token."); - } - - priv.PrivilegeCount = 1; - priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - if (!::LookupPrivilegeValueW(NULL, L"SeShutdownPrivilege", &priv.Privileges[0].Luid)) - { - ExitWithLastError(hr, "Failed to get shutdown privilege LUID."); - } - - cbPrevPriv = sizeof(TOKEN_PRIVILEGES); - pPrevPriv = static_cast(MemAlloc(cbPrevPriv, TRUE)); - ExitOnNull(pPrevPriv, hr, E_OUTOFMEMORY, "Failed to allocate memory for empty previous privileges."); - - if (!::AdjustTokenPrivileges(hToken, FALSE, &priv, cbPrevPriv, pPrevPriv, &cbPrevPriv)) - { - LPVOID pv = MemReAlloc(pPrevPriv, cbPrevPriv, TRUE); - ExitOnNull(pv, hr, E_OUTOFMEMORY, "Failed to allocate memory for previous privileges."); - pPrevPriv = static_cast(pv); - - if (!::AdjustTokenPrivileges(hToken, FALSE, &priv, cbPrevPriv, pPrevPriv, &cbPrevPriv)) - { - ExitWithLastError(hr, "Failed to get shutdown privilege LUID."); - } - } - - fAdjustedPrivileges = TRUE; - - // build up SC_ACTION array - // TODO: why is delay only respected when SC_ACTION_RESTART is requested? - actions[0].Type = GetSCActionType(wzFirstFailureActionType); - actions[0].Delay = 0; - if (SC_ACTION_RESTART == actions[0].Type) - { - actions[0].Delay = dwRestartServiceDelayInSeconds * 1000; // seconds to milliseconds - } - - actions[1].Type = GetSCActionType(wzSecondFailureActionType); - actions[1].Delay = 0; - if (SC_ACTION_RESTART == actions[1].Type) - { - actions[1].Delay = dwRestartServiceDelayInSeconds * 1000; // seconds to milliseconds - } - - actions[2].Type = GetSCActionType(wzThirdFailureActionType); - actions[2].Delay = 0; - if (SC_ACTION_RESTART == actions[2].Type) - { - actions[2].Delay = dwRestartServiceDelayInSeconds * 1000; // seconds to milliseconds - } - - // build up the SERVICE_FAILURE_ACTIONSW struct - sfa.dwResetPeriod = dwResetPeriodInDays * (24 * 60 * 60); // days to seconds - sfa.lpRebootMsg = wzRebootMessage; - sfa.lpCommand = wzProgramCommandLine; - sfa.cActions = countof(actions); - sfa.lpsaActions = actions; - - // Call ChangeServiceConfig2 to actually set up the failure actions - if (!::ChangeServiceConfig2W(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPVOID)&sfa)) - { - er = ::GetLastError(); - hr = HRESULT_FROM_WIN32(er); - -#pragma prefast(push) -#pragma prefast(disable:25028) - ::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, er, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpMsgBuf, 0, NULL); -#pragma prefast(pop) - - // Check if this is a service that can't be modified. - if (ERROR_CANNOT_DETECT_PROCESS_ABORT == er) - { - WcaLog(LOGMSG_STANDARD, "WARNING: Service \"%ls\" is not configurable on this server and will not be set.", wzServiceName); - } - ExitOnFailure(hr, "Cannot change service configuration. Error: %ls", (LPWSTR)lpMsgBuf); - - if (lpMsgBuf) - { - ::LocalFree(lpMsgBuf); - lpMsgBuf = NULL; - } - } - -LExit: - if (lpMsgBuf) - { - ::LocalFree(lpMsgBuf); - } - - if (fAdjustedPrivileges) - { - ::AdjustTokenPrivileges(hToken, FALSE, pPrevPriv, 0, NULL, NULL); - } - - ReleaseMem(pPrevPriv); - ReleaseHandle(hToken); - - return hr; -} diff --git a/src/ca/shellexecca.cpp b/src/ca/shellexecca.cpp deleted file mode 100644 index ea21d3bd..00000000 --- a/src/ca/shellexecca.cpp +++ /dev/null @@ -1,271 +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 ShellExec( - __in LPCWSTR wzTarget, - __in BOOL fUnelevated - ) -{ - HRESULT hr = S_OK; - LPWSTR sczWorkingDirectory = NULL; - - // a reasonable working directory (not the system32 default from MSI) is the directory where the target lives - hr = PathGetDirectory(wzTarget, &sczWorkingDirectory); - ExitOnFailure(hr, "failed to get directory for target: %ls", wzTarget); - - if (!DirExists(sczWorkingDirectory, NULL)) - { - ReleaseNullStr(sczWorkingDirectory); - } - - if (fUnelevated) - { - hr = ShelExecUnelevated(wzTarget, NULL, NULL, sczWorkingDirectory, SW_SHOWDEFAULT); - ExitOnFailure(hr, "ShelExecUnelevated failed with target %ls", wzTarget); - } - else - { - HINSTANCE hinst = ::ShellExecuteW(NULL, NULL, wzTarget, NULL, sczWorkingDirectory, SW_SHOWDEFAULT); - if (hinst <= HINSTANCE(32)) - { - LONG64 code = reinterpret_cast(hinst); - switch (code) - { - case ERROR_FILE_NOT_FOUND: - hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - break; - case ERROR_PATH_NOT_FOUND: - hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); - break; - case ERROR_BAD_FORMAT: - hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT); - break; - case SE_ERR_ASSOCINCOMPLETE: - case SE_ERR_NOASSOC: - hr = HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION); - break; - case SE_ERR_DDEBUSY: - case SE_ERR_DDEFAIL: - case SE_ERR_DDETIMEOUT: - hr = HRESULT_FROM_WIN32(ERROR_DDE_FAIL); - break; - case SE_ERR_DLLNOTFOUND: - hr = HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND); - break; - case SE_ERR_OOM: - hr = E_OUTOFMEMORY; - break; - case SE_ERR_ACCESSDENIED: - hr = E_ACCESSDENIED; - break; - default: - hr = E_FAIL; - } - - ExitOnFailure(hr, "ShellExec failed with return code %llu.", code); - } - } - - -LExit: - ReleaseStr(sczWorkingDirectory); - return hr; -} - -extern "C" UINT __stdcall WixShellExec( - __in MSIHANDLE hInstall - ) -{ - Assert(hInstall); - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - LPWSTR pwzTarget = NULL; - - hr = WcaInitialize(hInstall, "WixShellExec"); - ExitOnFailure(hr, "failed to initialize"); - - hr = WcaGetFormattedProperty(L"WixShellExecTarget", &pwzTarget); - ExitOnFailure(hr, "failed to get WixShellExecTarget"); - - WcaLog(LOGMSG_VERBOSE, "WixShellExecTarget is %ls", pwzTarget); - - if (!pwzTarget || !*pwzTarget) - { - hr = E_INVALIDARG; - ExitOnFailure(hr, "failed to get WixShellExecTarget"); - } - - hr = ShellExec(pwzTarget, FALSE); - ExitOnFailure(hr, "failed to launch target"); - -LExit: - ReleaseStr(pwzTarget); - - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - return WcaFinalize(er); -} - -extern "C" UINT __stdcall WixUnelevatedShellExec( - __in MSIHANDLE hInstall - ) -{ - Assert(hInstall); - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - LPWSTR pwzTarget = NULL; - - hr = WcaInitialize(hInstall, "WixUnelevatedShellExec"); - ExitOnFailure(hr, "failed to initialize"); - - hr = WcaGetFormattedProperty(L"WixUnelevatedShellExecTarget", &pwzTarget); - ExitOnFailure(hr, "failed to get WixUnelevatedShellExecTarget"); - - WcaLog(LOGMSG_VERBOSE, "WixUnelevatedShellExecTarget is %ls", pwzTarget); - - if (!pwzTarget || !*pwzTarget) - { - hr = E_INVALIDARG; - ExitOnFailure(hr, "failed to get WixShellExecTarget"); - } - - hr = ShellExec(pwzTarget, TRUE); - ExitOnFailure(hr, "failed to launch target"); - -LExit: - ReleaseStr(pwzTarget); - - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - return WcaFinalize(er); -} - -// -// ExtractBinary extracts the data from the Binary table row with the given ID into a file. -// -HRESULT ExtractBinary( - __in LPCWSTR wzBinaryId, - __out BYTE** pbData, - __out DWORD* pcbData - ) -{ - HRESULT hr = S_OK; - LPWSTR pwzSql = NULL; - PMSIHANDLE hView; - PMSIHANDLE hRec; - - // make sure we're not horked from the get-go - hr = WcaTableExists(L"Binary"); - if (S_OK != hr) - { - if (SUCCEEDED(hr)) - { - hr = E_UNEXPECTED; - } - ExitOnFailure(hr, "There is no Binary table."); - } - - ExitOnNull(wzBinaryId, hr, E_INVALIDARG, "Binary ID cannot be null"); - ExitOnNull(*wzBinaryId, hr, E_INVALIDARG, "Binary ID cannot be empty string"); - - hr = StrAllocFormatted(&pwzSql, L"SELECT `Data` FROM `Binary` WHERE `Name`=\'%s\'", wzBinaryId); - 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, pcbData); - ExitOnFailure(hr, "Failed to read Binary.Data."); - -LExit: - ReleaseStr(pwzSql); - - return hr; -} - -extern "C" UINT __stdcall WixShellExecBinary( - __in MSIHANDLE hInstall - ) -{ - Assert(hInstall); - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - LPWSTR pwzBinary = NULL; - LPWSTR pwzFilename = NULL; - BYTE* pbData = NULL; - DWORD cbData = 0; - HANDLE hFile = INVALID_HANDLE_VALUE; - -#if 0 - ::MessageBoxA(0, "WixShellExecBinary", "-->> ATTACH HERE", MB_OK); -#endif - - hr = WcaInitialize(hInstall, "WixShellExecBinary"); - ExitOnFailure(hr, "failed to initialize"); - - hr = WcaGetFormattedProperty(L"WixShellExecBinaryId", &pwzBinary); - ExitOnFailure(hr, "failed to get WixShellExecBinaryId"); - - WcaLog(LOGMSG_VERBOSE, "WixShellExecBinaryId is %ls", pwzBinary); - - if (!pwzBinary || !*pwzBinary) - { - hr = E_INVALIDARG; - ExitOnFailure(hr, "failed to get WixShellExecBinaryId"); - } - - // get temporary path for extracted file - StrAlloc(&pwzFilename, MAX_PATH); - ExitOnFailure(hr, "Failed to allocate temporary path"); - ::GetTempPathW(MAX_PATH, pwzFilename); - hr = ::StringCchCatW(pwzFilename, MAX_PATH, pwzBinary); - ExitOnFailure(hr, "Failed to append filename."); - - // grab the bits - hr = ExtractBinary(pwzBinary, &pbData, &cbData); - ExitOnFailure(hr, "failed to extract binary data"); - - // write 'em to the temp file - hFile = ::CreateFileW(pwzFilename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (INVALID_HANDLE_VALUE == hFile) - { - ExitWithLastError(hr, "Failed to open new temp file: %ls", pwzFilename); - } - - DWORD cbWritten = 0; - if (!::WriteFile(hFile, pbData, cbData, &cbWritten, NULL)) - { - ExitWithLastError(hr, "Failed to write data to new temp file: %ls", pwzFilename); - } - - // close it - ::CloseHandle(hFile); - hFile = INVALID_HANDLE_VALUE; - - // and run it - hr = ShellExec(pwzFilename, FALSE); - ExitOnFailure(hr, "failed to launch target: %ls", pwzFilename); - -LExit: - ReleaseStr(pwzBinary); - ReleaseStr(pwzFilename); - ReleaseMem(pbData); - if (INVALID_HANDLE_VALUE != hFile) - { - ::CloseHandle(hFile); - } - - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - return WcaFinalize(er); -} diff --git a/src/ca/test.cpp b/src/ca/test.cpp deleted file mode 100644 index c4d215f0..00000000 --- a/src/ca/test.cpp +++ /dev/null @@ -1,269 +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 WIXCA_UITHREAD_CLASS_WINDOW L"WixCaMessageWindow" - -extern HMODULE g_hInstCADLL; - - -// structs - -struct UITHREAD_CONTEXT -{ - HANDLE hInitializedEvent; - HINSTANCE hInstance; - HWND hWnd; -}; - - -// internal function declarations - -static HRESULT CreateMessageWindow( - __out HWND* phWnd - ); - -static void CloseMessageWindow( - __in HWND hWnd - ); - -static DWORD WINAPI ThreadProc( - __in LPVOID pvContext - ); - -static LRESULT CALLBACK WndProc( - __in HWND hWnd, - __in UINT uMsg, - __in WPARAM wParam, - __in LPARAM lParam - ); - - -/****************************************************************** -WixFailWhenDeferred - entry point for WixFailWhenDeferred - custom action which always fails when running as a deferred - custom action (otherwise it blindly succeeds). It's useful when - testing the rollback of deferred custom actions: Schedule it - immediately after the rollback/deferred CA pair you're testing - and it will fail, causing your rollback CA to get invoked. -********************************************************************/ -extern "C" UINT __stdcall WixFailWhenDeferred( - __in MSIHANDLE hInstall - ) -{ - return ::MsiGetMode(hInstall, MSIRUNMODE_SCHEDULED) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS; -} - -/****************************************************************** -WixWaitForEvent - entry point for WixWaitForEvent custom action - which waits for either the WixWaitForEventFail or - WixWaitForEventSucceed named auto reset events. Signaling the - WixWaitForEventFail event will return ERROR_INSTALL_FAILURE or - signaling the WixWaitForEventSucceed event will return - ERROR_SUCCESS. Both events are declared in the Global\ namespace. -********************************************************************/ -extern "C" UINT __stdcall WixWaitForEvent( - __in MSIHANDLE hInstall - ) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - HWND hMessageWindow = NULL; - LPCWSTR wzSDDL = L"D:(A;;GA;;;WD)"; - OS_VERSION version = OS_VERSION_UNKNOWN; - DWORD dwServicePack = 0; - PSECURITY_DESCRIPTOR pSD = NULL; - SECURITY_ATTRIBUTES sa = { }; - HANDLE rghEvents[2]; - - hr = WcaInitialize(hInstall, "WixWaitForEvent"); - ExitOnFailure(hr, "Failed to initialize."); - - // Create a window to prevent shutdown requests. - hr = CreateMessageWindow(&hMessageWindow); - ExitOnFailure(hr, "Failed to create message window."); - - // If running on Vista/2008 or newer use integrity enhancements. - OsGetVersion(&version, &dwServicePack); - if (OS_VERSION_VISTA <= version) - { - // Add SACL to allow Everyone to signal from a medium integrity level. - wzSDDL = L"D:(A;;GA;;;WD)S:(ML;;NW;;;ME)"; - } - - // Create the security descriptor and attributes for the events. - if (!::ConvertStringSecurityDescriptorToSecurityDescriptorW(wzSDDL, SDDL_REVISION_1, &pSD, NULL)) - { - ExitWithLastError(hr, "Failed to create the security descriptor for the events."); - } - - sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = pSD; - sa.bInheritHandle = FALSE; - - rghEvents[0] = ::CreateEventW(&sa, FALSE, FALSE, L"Global\\WixWaitForEventFail"); - ExitOnNullWithLastError(rghEvents[0], hr, "Failed to create the Global\\WixWaitForEventFail event."); - - rghEvents[1] = ::CreateEventW(&sa, FALSE, FALSE, L"Global\\WixWaitForEventSucceed"); - ExitOnNullWithLastError(rghEvents[1], hr, "Failed to create the Global\\WixWaitForEventSucceed event."); - - // Wait for either of the events to be signaled and handle accordingly. - er = ::WaitForMultipleObjects(countof(rghEvents), rghEvents, FALSE, INFINITE); - switch (er) - { - case WAIT_OBJECT_0 + 0: - er = ERROR_INSTALL_FAILURE; - break; - case WAIT_OBJECT_0 + 1: - er = ERROR_SUCCESS; - break; - default: - ExitOnWin32Error(er, hr, "Unexpected failure."); - } - -LExit: - ReleaseHandle(rghEvents[1]); - ReleaseHandle(rghEvents[0]); - - if (pSD) - { - ::LocalFree(pSD); - } - - if (hMessageWindow) - { - CloseMessageWindow(hMessageWindow); - } - - if (FAILED(hr)) - { - er = ERROR_INSTALL_FAILURE; - } - - return WcaFinalize(er); -} - - -// internal function definitions - -static HRESULT CreateMessageWindow( - __out HWND* phWnd - ) -{ - HRESULT hr = S_OK; - HANDLE rgWaitHandles[2] = { }; - UITHREAD_CONTEXT context = { }; - - // Create event to signal after the UI thread / window is initialized. - rgWaitHandles[0] = ::CreateEventW(NULL, TRUE, FALSE, NULL); - ExitOnNullWithLastError(rgWaitHandles[0], hr, "Failed to create initialization event."); - - // Pass necessary information to create the window. - context.hInitializedEvent = rgWaitHandles[0]; - context.hInstance = (HINSTANCE)g_hInstCADLL; - - // Create our separate UI thread. - rgWaitHandles[1] = ::CreateThread(NULL, 0, ThreadProc, &context, 0, NULL); - ExitOnNullWithLastError(rgWaitHandles[1], hr, "Failed to create the UI thread."); - - // Wait for either the thread to be initialized or the window to exit / fail prematurely. - ::WaitForMultipleObjects(countof(rgWaitHandles), rgWaitHandles, FALSE, INFINITE); - - // Pass the window back to the caller. - *phWnd = context.hWnd; - -LExit: - ReleaseHandle(rgWaitHandles[1]); - ReleaseHandle(rgWaitHandles[0]); - - return hr; -} - -static void CloseMessageWindow( - __in HWND hWnd - ) -{ - if (::IsWindow(hWnd)) - { - ::PostMessageW(hWnd, WM_CLOSE, 0, 0); - } -} - -static DWORD WINAPI ThreadProc( - __in LPVOID pvContext - ) -{ - HRESULT hr = S_OK; - UITHREAD_CONTEXT* pContext = static_cast(pvContext); - - WNDCLASSW wc = { }; - BOOL fRegistered = TRUE; - HWND hWnd = NULL; - - BOOL fRet = FALSE; - MSG msg = { }; - - wc.lpfnWndProc = WndProc; - wc.hInstance = pContext->hInstance; - wc.lpszClassName = WIXCA_UITHREAD_CLASS_WINDOW; - - if (!::RegisterClassW(&wc)) - { - ExitWithLastError(hr, "Failed to register window."); - } - - fRegistered = TRUE; - - // Create the window to handle reboots without activating it. - hWnd = ::CreateWindowExW(WS_EX_TOOLWINDOW, wc.lpszClassName, NULL, WS_POPUP | WS_VISIBLE, CW_USEDEFAULT, SW_SHOWNA, 0, 0, HWND_DESKTOP, NULL, pContext->hInstance, NULL); - ExitOnNullWithLastError(hWnd, hr, "Failed to create window."); - - // Persist the window handle and let the caller know we've initialized. - pContext->hWnd = hWnd; - ::SetEvent(pContext->hInitializedEvent); - - // Pump messages until the window is closed. - while (0 != (fRet = ::GetMessageW(&msg, NULL, 0, 0))) - { - if (-1 == fRet) - { - hr = E_UNEXPECTED; - ExitOnFailure(hr, "Unexpected return value from message pump."); - } - else if (!::IsDialogMessageW(msg.hwnd, &msg)) - { - ::TranslateMessage(&msg); - ::DispatchMessageW(&msg); - } - } - -LExit: - if (fRegistered) - { - ::UnregisterClassW(WIXCA_UITHREAD_CLASS_WINDOW, pContext->hInstance); - } - - return hr; -} - -static LRESULT CALLBACK WndProc( - __in HWND hWnd, - __in UINT uMsg, - __in WPARAM wParam, - __in LPARAM lParam - ) -{ - switch (uMsg) - { - case WM_QUERYENDSESSION: - // Prevent the process from being shut down. - WcaLog(LOGMSG_VERBOSE, "Disallowed system request to shut down the custom action server."); - return FALSE; - - case WM_DESTROY: - ::PostQuitMessage(0); - return 0; - } - - return ::DefWindowProcW(hWnd, uMsg, wParam, lParam); -} diff --git a/src/ca/utilca.cpp b/src/ca/utilca.cpp deleted file mode 100644 index 37664a1c..00000000 --- a/src/ca/utilca.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/utilca.def b/src/ca/utilca.def deleted file mode 100644 index 412d86a3..00000000 --- a/src/ca/utilca.def +++ /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. - - -LIBRARY "utilca" - -EXPORTS -; BroadcastSettingChange.cpp - WixBroadcastSettingChange - WixBroadcastEnvironmentChange -; checkreboot.cpp - WixCheckRebootRequired -; closeapps.cpp - WixCloseApplications - WixCloseApplicationsDeferred -; exitearlywithsuccess.cpp - WixExitEarlyWithSuccess -; FormatFiles.cpp - WixSchedFormatFiles - WixExecFormatFiles -; osinfo.cpp - WixQueryOsInfo - WixQueryOsDirs - WixQueryOsWellKnownSID - WixQueryOsDriverInfo -; netshortcuts.cpp - WixSchedInternetShortcuts - WixCreateInternetShortcuts - WixRollbackInternetShortcuts -; qtexecca.cpp - CAQuietExec - CAQuietExec64 - WixQuietExec - WixQuietExec64 - WixSilentExec - WixSilentExec64 -; RemoveFoldersEx.cpp - WixRemoveFoldersEx -; RemoveRegistryKeysEx.cpp - WixRemoveRegistryKeysEx -;scaexec.cpp - RegisterPerfCounterData - UnregisterPerfCounterData - RegisterPerfmon - UnregisterPerfmon - CreateSmb - DropSmb - CreateUser - CreateUserRollback - RemoveUser -;scasched.cpp - ConfigurePerfmonInstall - ConfigurePerfmonUninstall - ConfigureSmbInstall - ConfigureSmbUninstall - ConfigureUsers - InstallPerfCounterData - UninstallPerfCounterData - ConfigurePerfmonManifestRegister - ConfigurePerfmonManifestUnregister - ConfigureEventManifestRegister - ConfigureEventManifestUnregister -; RestartManager.cpp - WixRegisterRestartResources -; secureobj.cpp - SchedSecureObjects - SchedSecureObjectsRollback - ExecSecureObjects - ExecSecureObjectsRollback -; serviceconfig.cpp - SchedServiceConfig - ExecServiceConfig - RollbackServiceConfig -; shellexecca.cpp - WixShellExec - WixShellExecBinary - WixUnelevatedShellExec -; test.cpp - WixFailWhenDeferred - WixWaitForEvent -; TouchFile.cpp - WixTouchFileDuringInstall - WixTouchFileDuringUninstall - WixExecuteTouchFile -; xmlfile.cpp - SchedXmlFile - ExecXmlFile - ExecXmlFileRollback -; xmlconfig.cpp - SchedXmlConfig - ExecXmlConfig - ExecXmlConfigRollback diff --git a/src/ca/utilca.vcxproj b/src/ca/utilca.vcxproj deleted file mode 100644 index 7b64db95..00000000 --- a/src/ca/utilca.vcxproj +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - Debug - ARM64 - - - Release - ARM64 - - - Debug - X64 - - - Release - X64 - - - Debug - Win32 - - - Release - Win32 - - - - - {076018F7-19BD-423A-ABBF-229273DA08D8} - DynamicLibrary - utilca - v142 - Unicode - utilca.def - WiX Toolset Util CustomAction - - - - - - - activeds.lib;adsiid.lib;msi.lib;netapi32.lib;shlwapi.lib - - - - - - - - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ext/Util/CustomizedNativeRecommendedRules.ruleset b/src/ext/Util/CustomizedNativeRecommendedRules.ruleset new file mode 100644 index 00000000..142b141c --- /dev/null +++ b/src/ext/Util/CustomizedNativeRecommendedRules.ruleset @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/ext/Util/Directory.Build.props b/src/ext/Util/Directory.Build.props new file mode 100644 index 00000000..b3c6287c --- /dev/null +++ b/src/ext/Util/Directory.Build.props @@ -0,0 +1,27 @@ + + + + + + Debug + false + MSB3246 + + $(MSBuildProjectName) + $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\build\)) + $(BaseOutputPath)obj\$(ProjectName)\ + $(BaseOutputPath)$(Configuration)\ + + WiX Toolset Team + WiX Toolset + Copyright (c) .NET Foundation and contributors. All rights reserved. + MS-RL + WiX Toolset + + + + + diff --git a/src/ext/Util/Directory.Build.targets b/src/ext/Util/Directory.Build.targets new file mode 100644 index 00000000..2fcc765a --- /dev/null +++ b/src/ext/Util/Directory.Build.targets @@ -0,0 +1,51 @@ + + + + + + + true + $(SolutionPath) + $(NCrunchOriginalSolutionPath) + + + + + + + $([System.IO.File]::ReadAllText($(TheSolutionPath))) + $([System.IO.Path]::GetDirectoryName( $(TheSolutionPath) )) + (?<="[PackageName]", ")(.*)(?=", ") + + + + + + %(Identity) + $(SolutionFileContent.Contains('\%(Identity).csproj')) + + + + + $(RegexPattern.Replace('[PackageName]','%(PackageName)') ) + $([System.Text.RegularExpressions.Regex]::Match('$(SolutionFileContent)', '%(Pattern)')) + + + + + + + + + + + + + + diff --git a/src/ext/Util/Directory.csproj.props b/src/ext/Util/Directory.csproj.props new file mode 100644 index 00000000..81d24ad1 --- /dev/null +++ b/src/ext/Util/Directory.csproj.props @@ -0,0 +1,13 @@ + + + + + true + true + $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)wix.snk)) + false + + diff --git a/src/ext/Util/Directory.csproj.targets b/src/ext/Util/Directory.csproj.targets new file mode 100644 index 00000000..c3270426 --- /dev/null +++ b/src/ext/Util/Directory.csproj.targets @@ -0,0 +1,26 @@ + + + + + false + $(OutputPath)\$(AssemblyName).xml + + + + + $(PrivateRepositoryUrl.Replace('.git','')) + + $(MSBuildProjectName).nuspec + $(OutputPath)..\ + $(NuspecProperties);Id=$(PackageId);Authors=$(Authors);Copyright=$(Copyright);Description=$(Description);Title=$(Title) + $(NuspecProperties);Version=$(PackageVersion);RepositoryCommit=$(SourceRevisionId);RepositoryType=$(RepositoryType);RepositoryUrl=$(PrivateRepositoryUrl);ProjectFolder=$(MSBuildProjectDirectory)\;ProjectUrl=$(ProjectUrl) + true + snupkg + + + + diff --git a/src/ext/Util/Directory.vcxproj.props b/src/ext/Util/Directory.vcxproj.props new file mode 100644 index 00000000..11778f41 --- /dev/null +++ b/src/ext/Util/Directory.vcxproj.props @@ -0,0 +1,97 @@ + + + + + + Win32 + $(BaseIntermediateOutputPath)$(Configuration)\$(Platform)\ + $(OutputPath)$(Platform)\ + + + $(Company) + $(Copyright) + + win-x86;win-x64;win-arm64 + native,Version=v0.0 + + + + $([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0')) + + + + $(MSBuildThisFileDirectory)CustomizedNativeRecommendedRules.ruleset + + + + + $(DisableSpecificCompilerWarnings) + Level4 + $(ProjectDir)inc;$(MSBuildProjectDirectory);$(IntDir);$(SqlCESdkIncludePath);$(ProjectAdditionalIncludeDirectories);%(AdditionalIncludeDirectories) + WIN32;_WINDOWS;_WIN32_MSI=500;_WIN32_WINNT=0x0501;$(ArmPreprocessorDefinitions);$(UnicodePreprocessorDefinitions);_CRT_STDIO_LEGACY_WIDE_SPECIFIERS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions) + Use + precomp.h + StdCall + true + false + -YlprecompDefine + /Zc:threadSafeInit- %(AdditionalOptions) + true + + + $(ArmPreprocessorDefinitions);%(PreprocessorDefinitions) + $(ProjectAdditionalResourceIncludeDirectories);%(AdditionalIncludeDirectories) + + + $(OutDir);$(AdditionalMultiTargetLibraryPath);$(ProjectAdditionalLibraryDirectories);%(AdditionalLibraryDirectories) + + + $(ProjectSubSystem) + $(ProjectModuleDefinitionFile) + $(ResourceOnlyDll) + true + $(ProjectAdditionalLinkLibraries);advapi32.lib;comdlg32.lib;user32.lib;oleaut32.lib;gdi32.lib;shell32.lib;ole32.lib;version.lib;%(AdditionalDependencies) + $(OutDir);$(AdditionalMultiTargetLibraryPath);$(ArmLibraryDirectories);$(ProjectAdditionalLinkLibraryDirectories);%(AdditionalLibraryDirectories) + /IGNORE:4099 %(AdditionalOptions) + + + + + + NoExtensions + + + + + CDecl + + + + + OldStyle + true + true + + + + + Disabled + EnableFastChecks + _DEBUG;DEBUG;%(PreprocessorDefinitions) + MultiThreadedDebug + + + + + MinSpace + NDEBUG;%(PreprocessorDefinitions) + true + true + MultiThreaded + + + true + true + + + diff --git a/src/ext/Util/README.md b/src/ext/Util/README.md new file mode 100644 index 00000000..540c539c --- /dev/null +++ b/src/ext/Util/README.md @@ -0,0 +1,3 @@ +# Util.wixext +WixToolset.Util.wixext - Utility WiX Toolset Extension + diff --git a/src/ext/Util/Util.wixext.sln b/src/ext/Util/Util.wixext.sln new file mode 100644 index 00000000..050fd8b3 --- /dev/null +++ b/src/ext/Util/Util.wixext.sln @@ -0,0 +1,87 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30204.135 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utilbe", "src\be\utilbe.vcxproj", "{630C1EE7-2517-4A8C-83E3-DA1150308B58}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utilca", "src\ca\utilca.vcxproj", "{076018F7-19BD-423A-ABBF-229273DA08D8}" +EndProject +Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "util", "src\wixlib\util.wixproj", "{1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Util.wixext", "src\wixext\WixToolset.Util.wixext.csproj", "{6CF033EB-0A39-4AC6-9D41-9BD506352045}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.Util", "src\test\WixToolsetTest.Util\WixToolsetTest.Util.csproj", "{D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Debug|Any CPU.Build.0 = Debug|Win32 + {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Debug|x64.ActiveCfg = Debug|Win32 + {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Debug|x86.ActiveCfg = Debug|Win32 + {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Debug|x86.Build.0 = Debug|Win32 + {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Release|Any CPU.ActiveCfg = Release|Win32 + {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Release|Any CPU.Build.0 = Release|Win32 + {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Release|x64.ActiveCfg = Release|Win32 + {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Release|x86.ActiveCfg = Release|Win32 + {630C1EE7-2517-4A8C-83E3-DA1150308B58}.Release|x86.Build.0 = Release|Win32 + {076018F7-19BD-423A-ABBF-229273DA08D8}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {076018F7-19BD-423A-ABBF-229273DA08D8}.Debug|Any CPU.Build.0 = Debug|Win32 + {076018F7-19BD-423A-ABBF-229273DA08D8}.Debug|x64.ActiveCfg = Debug|Win32 + {076018F7-19BD-423A-ABBF-229273DA08D8}.Debug|x86.ActiveCfg = Debug|Win32 + {076018F7-19BD-423A-ABBF-229273DA08D8}.Debug|x86.Build.0 = Debug|Win32 + {076018F7-19BD-423A-ABBF-229273DA08D8}.Release|Any CPU.ActiveCfg = Release|Win32 + {076018F7-19BD-423A-ABBF-229273DA08D8}.Release|Any CPU.Build.0 = Release|Win32 + {076018F7-19BD-423A-ABBF-229273DA08D8}.Release|x64.ActiveCfg = Release|Win32 + {076018F7-19BD-423A-ABBF-229273DA08D8}.Release|x86.ActiveCfg = Release|Win32 + {076018F7-19BD-423A-ABBF-229273DA08D8}.Release|x86.Build.0 = Release|Win32 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|Any CPU.ActiveCfg = Debug|x86 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|Any CPU.Build.0 = Debug|x86 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|x64.ActiveCfg = Debug|x86 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|x86.ActiveCfg = Debug|x86 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|x86.Build.0 = Debug|x86 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Release|Any CPU.ActiveCfg = Release|x86 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Release|Any CPU.Build.0 = Release|x86 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Release|x64.ActiveCfg = Release|x86 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Release|x86.ActiveCfg = Release|x86 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Release|x86.Build.0 = Release|x86 + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|x64.ActiveCfg = Debug|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|x64.Build.0 = Debug|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|x86.ActiveCfg = Debug|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|x86.Build.0 = Debug|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|Any CPU.Build.0 = Release|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|x64.ActiveCfg = Release|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|x64.Build.0 = Release|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|x86.ActiveCfg = Release|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|x86.Build.0 = Release|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|x64.ActiveCfg = Debug|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|x64.Build.0 = Debug|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|x86.ActiveCfg = Debug|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|x86.Build.0 = Debug|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|Any CPU.Build.0 = Release|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|x64.ActiveCfg = Release|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|x64.Build.0 = Release|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|x86.ActiveCfg = Release|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E4566A6B-47D0-4EA0-989A-D763AC39105D} + EndGlobalSection +EndGlobal diff --git a/src/ext/Util/Util.wixext.v3.ncrunchsolution b/src/ext/Util/Util.wixext.v3.ncrunchsolution new file mode 100644 index 00000000..10420ac9 --- /dev/null +++ b/src/ext/Util/Util.wixext.v3.ncrunchsolution @@ -0,0 +1,6 @@ + + + True + True + + \ No newline at end of file diff --git a/src/ext/Util/appveyor.cmd b/src/ext/Util/appveyor.cmd new file mode 100644 index 00000000..8322ffae --- /dev/null +++ b/src/ext/Util/appveyor.cmd @@ -0,0 +1,19 @@ +@setlocal +@pushd %~dp0 +@set _C=Release +@if /i "%1"=="debug" set _C=Debug + +:: Restore +msbuild -p:Configuration=%_C% -t:Restore || exit /b + +:: Build +msbuild -p:Configuration=%_C% src\test\WixToolsetTest.Util\WixToolsetTest.Util.csproj || exit /b + +:: Test +dotnet test -c %_C% --no-build src\test\WixToolsetTest.Util || exit /b + +:: Pack +msbuild -p:Configuration=%_C% -p:NoBuild=true -t:Pack src\wixext\WixToolset.Util.wixext.csproj || exit /b + +@popd +@endlocal diff --git a/src/ext/Util/appveyor.yml b/src/ext/Util/appveyor.yml new file mode 100644 index 00000000..7c686b04 --- /dev/null +++ b/src/ext/Util/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/Util/be/UtilBundleExtension.cpp b/src/ext/Util/be/UtilBundleExtension.cpp new file mode 100644 index 00000000..2ac842a5 --- /dev/null +++ b/src/ext/Util/be/UtilBundleExtension.cpp @@ -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. + +#include "precomp.h" +#include "BextBaseBundleExtension.h" + +class CWixUtilBundleExtension : public CBextBaseBundleExtension +{ +public: // IBundleExtension + virtual STDMETHODIMP Search( + __in LPCWSTR wzId, + __in LPCWSTR wzVariable + ) + { + HRESULT hr = S_OK; + + hr = UtilSearchExecute(&m_searches, wzId, wzVariable, m_pEngine); + + return hr; + } + +public: //CBextBaseBundleExtension + virtual STDMETHODIMP Initialize( + __in const BUNDLE_EXTENSION_CREATE_ARGS* pCreateArgs + ) + { + HRESULT hr = S_OK; + IXMLDOMDocument* pixdManifest = NULL; + IXMLDOMNode* pixnBundleExtension = NULL; + + hr = CBextBaseBundleExtension::Initialize(pCreateArgs); + ExitOnFailure(hr, "CBextBaseBundleExtension initialization failed."); + + hr = XmlLoadDocumentFromFile(m_sczBundleExtensionDataPath, &pixdManifest); + ExitOnFailure(hr, "Failed to load bundle extension manifest from path: %ls", m_sczBundleExtensionDataPath); + + hr = BextGetBundleExtensionDataNode(pixdManifest, UTIL_BUNDLE_EXTENSION_ID, &pixnBundleExtension); + ExitOnFailure(hr, "Failed to get BundleExtension '%ls'", UTIL_BUNDLE_EXTENSION_ID); + + hr = UtilSearchParseFromXml(&m_searches, pixnBundleExtension); + ExitOnFailure(hr, "Failed to parse searches from bundle extension manifest."); + + LExit: + ReleaseObject(pixnBundleExtension); + ReleaseObject(pixdManifest); + + return hr; + } + +public: + CWixUtilBundleExtension( + __in IBundleExtensionEngine* pEngine + ) : CBextBaseBundleExtension(pEngine) + { + m_searches = { }; + } + + ~CWixUtilBundleExtension() + { + UtilSearchUninitialize(&m_searches); + } + +private: + UTIL_SEARCHES m_searches; +}; + +HRESULT UtilBundleExtensionCreate( + __in IBundleExtensionEngine* pEngine, + __in const BUNDLE_EXTENSION_CREATE_ARGS* pArgs, + __out IBundleExtension** ppBundleExtension + ) +{ + HRESULT hr = S_OK; + CWixUtilBundleExtension* pExtension = NULL; + + pExtension = new CWixUtilBundleExtension(pEngine); + ExitOnNull(pExtension, hr, E_OUTOFMEMORY, "Failed to create new CWixUtilBundleExtension."); + + hr = pExtension->Initialize(pArgs); + ExitOnFailure(hr, "CWixUtilBundleExtension initialization failed"); + + *ppBundleExtension = pExtension; + pExtension = NULL; + +LExit: + ReleaseObject(pExtension); + return hr; +} diff --git a/src/ext/Util/be/UtilBundleExtension.h b/src/ext/Util/be/UtilBundleExtension.h new file mode 100644 index 00000000..c55d6b85 --- /dev/null +++ b/src/ext/Util/be/UtilBundleExtension.h @@ -0,0 +1,16 @@ +#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. + + +// constants + +#define UTIL_BUNDLE_EXTENSION_ID BUNDLE_EXTENSION_DECORATION(L"UtilBundleExtension") + + +// function declarations + +HRESULT UtilBundleExtensionCreate( + __in IBundleExtensionEngine* pEngine, + __in const BUNDLE_EXTENSION_CREATE_ARGS* pArgs, + __out IBundleExtension** ppBundleExtension + ); diff --git a/src/ext/Util/be/beDecor.h b/src/ext/Util/be/beDecor.h new file mode 100644 index 00000000..2c6a8818 --- /dev/null +++ b/src/ext/Util/be/beDecor.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 BUNDLE_EXTENSION_DECORATION(f) L"Wix4" f L"_A64" +#elif defined(_M_AMD64) +#define BUNDLE_EXTENSION_DECORATION(f) L"Wix4" f L"_X64" +#elif defined(_M_ARM) +#define BUNDLE_EXTENSION_DECORATION(f) L"Wix4" f L"_ARM" +#else +#define BUNDLE_EXTENSION_DECORATION(f) L"Wix4" f L"_X86" +#endif diff --git a/src/ext/Util/be/detectsha2support.cpp b/src/ext/Util/be/detectsha2support.cpp new file mode 100644 index 00000000..90e349cd --- /dev/null +++ b/src/ext/Util/be/detectsha2support.cpp @@ -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. + +#include "precomp.h" + +// https://gist.github.com/navossoc/7572c7d82243e9f818989e2765e7793a +HRESULT DetectSHA2CodeSigning( + __out BOOL* pfSupported + ) +{ + HRESULT hr = S_OK; + HMODULE hModule = NULL; + FARPROC pfn = NULL; + DWORD er = ERROR_SUCCESS; + + hr = LoadSystemLibrary(L"wintrust.dll", &hModule); + ExitOnFailure(hr, "Failed to load wintrust.dll"); + + pfn = ::GetProcAddress(hModule, "CryptCATAdminAcquireContext2"); + if (pfn) + { + *pfSupported = TRUE; + ExitFunction1(hr = S_OK); + } + + er = ::GetLastError(); + if (er == ERROR_PROC_NOT_FOUND) + { + *pfSupported = FALSE; + ExitFunction1(hr = S_OK); + } + + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed to probe for CryptCATAdminAcquireContext2 in wintrust.dll"); + +LExit: + ::FreeLibrary(hModule); + + return hr; +} + +HRESULT UtilPerformDetectSHA2CodeSigning( + __in LPCWSTR wzVariable, + __in UTIL_SEARCH* /*pSearch*/, + __in IBundleExtensionEngine* pEngine + ) +{ + HRESULT hr = S_OK; + BOOL fSupported = FALSE; + + hr = DetectSHA2CodeSigning(&fSupported); + ExitOnFailure(hr, "DetectSHA2CodeSigning failed."); + + hr = pEngine->SetVariableNumeric(wzVariable, fSupported ? 1 : 0); + ExitOnFailure(hr, "Failed to set variable '%ls'", wzVariable); + +LExit: + return hr; +} diff --git a/src/ext/Util/be/detectsha2support.h b/src/ext/Util/be/detectsha2support.h new file mode 100644 index 00000000..c38a3d59 --- /dev/null +++ b/src/ext/Util/be/detectsha2support.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 UtilPerformDetectSHA2CodeSigning( + __in LPCWSTR wzVariable, + __in UTIL_SEARCH* pSearch, + __in IBundleExtensionEngine* pEngine + ); \ No newline at end of file diff --git a/src/ext/Util/be/precomp.cpp b/src/ext/Util/be/precomp.cpp new file mode 100644 index 00000000..37664a1c --- /dev/null +++ b/src/ext/Util/be/precomp.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/Util/be/precomp.h b/src/ext/Util/be/precomp.h new file mode 100644 index 00000000..76d24c7b --- /dev/null +++ b/src/ext/Util/be/precomp.h @@ -0,0 +1,37 @@ +#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 +#include +#include +#include + +#include + +#include + +#define MAXUINT USHRT_MAX + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "beDecor.h" +#include "utilsearch.h" +#include "detectsha2support.h" +#include "UtilBundleExtension.h" diff --git a/src/ext/Util/be/utilbe.cpp b/src/ext/Util/be/utilbe.cpp new file mode 100644 index 00000000..d9816dc7 --- /dev/null +++ b/src/ext/Util/be/utilbe.cpp @@ -0,0 +1,41 @@ +// Copyright (c) .NET 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" +#include "BextBaseBundleExtensionProc.h" + +static IBundleExtension* vpBundleExtension = NULL; + +// function definitions + +extern "C" HRESULT WINAPI BundleExtensionCreate( + __in const BUNDLE_EXTENSION_CREATE_ARGS* pArgs, + __inout BUNDLE_EXTENSION_CREATE_RESULTS* pResults + ) +{ + HRESULT hr = S_OK; + IBundleExtensionEngine* pEngine = NULL; + + hr = XmlInitialize(); + ExitOnFailure(hr, "Failed to initialize XML."); + + hr = BextInitializeFromCreateArgs(pArgs, &pEngine); + ExitOnFailure(hr, "Failed to initialize bext"); + + hr = UtilBundleExtensionCreate(pEngine, pArgs, &vpBundleExtension); + BextExitOnFailure(hr, "Failed to create WixUtilBundleExtension"); + + pResults->pfnBundleExtensionProc = BextBaseBundleExtensionProc; + pResults->pvBundleExtensionProcContext = vpBundleExtension; + +LExit: + ReleaseObject(pEngine); + + return hr; +} + +extern "C" void WINAPI BundleExtensionDestroy() +{ + BextUninitialize(); + ReleaseNullObject(vpBundleExtension); + XmlUninitialize(); +} \ No newline at end of file diff --git a/src/ext/Util/be/utilbe.def b/src/ext/Util/be/utilbe.def new file mode 100644 index 00000000..711b1a5c --- /dev/null +++ b/src/ext/Util/be/utilbe.def @@ -0,0 +1,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. + + +LIBRARY "utilbe" + +EXPORTS + BundleExtensionCreate + BundleExtensionDestroy diff --git a/src/ext/Util/be/utilbe.vcxproj b/src/ext/Util/be/utilbe.vcxproj new file mode 100644 index 00000000..683b376a --- /dev/null +++ b/src/ext/Util/be/utilbe.vcxproj @@ -0,0 +1,80 @@ + + + + + + + Debug + ARM64 + + + Release + ARM64 + + + Debug + X64 + + + Release + X64 + + + Debug + Win32 + + + Release + Win32 + + + + + {630C1EE7-2517-4A8C-83E3-DA1150308B58} + DynamicLibrary + utilbe + v142 + Unicode + utilbe.def + WiX Toolset Util BundleExtension + + + + + + + msi.lib + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ext/Util/be/utilsearch.cpp b/src/ext/Util/be/utilsearch.cpp new file mode 100644 index 00000000..7cd2ea09 --- /dev/null +++ b/src/ext/Util/be/utilsearch.cpp @@ -0,0 +1,160 @@ +// Copyright (c) .NET 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" + + +STDMETHODIMP UtilSearchParseFromXml( + __in UTIL_SEARCHES* pSearches, + __in IXMLDOMNode* pixnBundleExtension + ) +{ + HRESULT hr = S_OK; + IXMLDOMNodeList* pixnNodes = NULL; + IXMLDOMNode* pixnNode = NULL; + DWORD cNodes = 0; + BSTR bstrNodeName = NULL; + LPWSTR scz = NULL; + + // Select Util search nodes. + hr = XmlSelectNodes(pixnBundleExtension, L"WixWindowsFeatureSearch", &pixnNodes); + ExitOnFailure(hr, "Failed to select Util search nodes."); + + // Get Util search node count. + hr = pixnNodes->get_length((long*)&cNodes); + ExitOnFailure(hr, "Failed to get Util search node count."); + + if (!cNodes) + { + ExitFunction(); + } + + // Allocate memory for searches. + pSearches->rgSearches = (UTIL_SEARCH*)MemAlloc(sizeof(UTIL_SEARCH) * cNodes, TRUE); + ExitOnNull(pSearches->rgSearches, hr, E_OUTOFMEMORY, "Failed to allocate memory for search structs."); + + pSearches->cSearches = cNodes; + + // Parse search elements. + for (DWORD i = 0; i < cNodes; ++i) + { + UTIL_SEARCH* pSearch = &pSearches->rgSearches[i]; + + hr = XmlNextElement(pixnNodes, &pixnNode, &bstrNodeName); + ExitOnFailure(hr, "Failed to get next node."); + + // @Id + hr = XmlGetAttributeEx(pixnNode, L"Id", &pSearch->sczId); + ExitOnFailure(hr, "Failed to get @Id."); + + // Read type specific attributes. + if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"WixWindowsFeatureSearch", -1)) + { + pSearch->Type = UTIL_SEARCH_TYPE_WINDOWS_FEATURE_SEARCH; + + // @Type + hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); + ExitOnFailure(hr, "Failed to get @Type."); + + if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"sha2CodeSigning", -1)) + { + pSearch->WindowsFeatureSearch.type = UTIL_WINDOWS_FEATURE_SEARCH_TYPE_SHA2_CODE_SIGNING; + } + else + { + hr = E_INVALIDARG; + ExitOnFailure(hr, "Invalid value for @Type: %ls", scz); + } + } + else + { + hr = E_UNEXPECTED; + ExitOnFailure(hr, "Unexpected element name: %ls", bstrNodeName); + } + + // prepare next iteration + ReleaseNullObject(pixnNode); + ReleaseNullBSTR(bstrNodeName); + } + +LExit: + ReleaseStr(scz); + ReleaseBSTR(bstrNodeName); + ReleaseObject(pixnNode); + ReleaseObject(pixnNodes); + + return hr; +} + +void UtilSearchUninitialize( + __in UTIL_SEARCHES* pSearches + ) +{ + if (pSearches->rgSearches) + { + for (DWORD i = 0; i < pSearches->cSearches; ++i) + { + UTIL_SEARCH* pSearch = &pSearches->rgSearches[i]; + + ReleaseStr(pSearch->sczId); + } + MemFree(pSearches->rgSearches); + } +} + +STDMETHODIMP UtilSearchExecute( + __in UTIL_SEARCHES* pSearches, + __in LPCWSTR wzSearchId, + __in LPCWSTR wzVariable, + __in IBundleExtensionEngine* pEngine + ) +{ + HRESULT hr = S_OK; + UTIL_SEARCH* pSearch = NULL; + + hr = UtilSearchFindById(pSearches, wzSearchId, &pSearch); + ExitOnFailure(hr, "Search id '%ls' is unknown to the util extension."); + + switch (pSearch->Type) + { + case UTIL_SEARCH_TYPE_WINDOWS_FEATURE_SEARCH: + switch (pSearch->WindowsFeatureSearch.type) + { + case UTIL_WINDOWS_FEATURE_SEARCH_TYPE_SHA2_CODE_SIGNING: + hr = UtilPerformDetectSHA2CodeSigning(wzVariable, pSearch, pEngine); + break; + default: + hr = E_UNEXPECTED; + } + break; + default: + hr = E_UNEXPECTED; + } + +LExit: + return hr; +} + +STDMETHODIMP UtilSearchFindById( + __in UTIL_SEARCHES* pSearches, + __in LPCWSTR wzId, + __out UTIL_SEARCH** ppSearch + ) +{ + HRESULT hr = S_OK; + + for (DWORD i = 0; i < pSearches->cSearches; ++i) + { + UTIL_SEARCH* pSearch = &pSearches->rgSearches[i]; + + if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pSearch->sczId, -1, wzId, -1)) + { + *ppSearch = pSearch; + ExitFunction1(hr = S_OK); + } + } + + hr = E_NOTFOUND; + +LExit: + return hr; +} diff --git a/src/ext/Util/be/utilsearch.h b/src/ext/Util/be/utilsearch.h new file mode 100644 index 00000000..deeab1f7 --- /dev/null +++ b/src/ext/Util/be/utilsearch.h @@ -0,0 +1,65 @@ +#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. + + +// constants + +enum UTIL_SEARCH_TYPE +{ + UTIL_SEARCH_TYPE_NONE, + UTIL_SEARCH_TYPE_WINDOWS_FEATURE_SEARCH, +}; + +enum UTIL_WINDOWS_FEATURE_SEARCH_TYPE +{ + UTIL_WINDOWS_FEATURE_SEARCH_TYPE_NONE, + UTIL_WINDOWS_FEATURE_SEARCH_TYPE_SHA2_CODE_SIGNING, +}; + + +// structs + +typedef struct _UTIL_SEARCH +{ + LPWSTR sczId; + + UTIL_SEARCH_TYPE Type; + union + { + struct + { + UTIL_WINDOWS_FEATURE_SEARCH_TYPE type; + } WindowsFeatureSearch; + }; +} UTIL_SEARCH; + +typedef struct _UTIL_SEARCHES +{ + UTIL_SEARCH* rgSearches; + DWORD cSearches; +} UTIL_SEARCHES; + + +// function declarations + +STDMETHODIMP UtilSearchParseFromXml( + __in UTIL_SEARCHES* pSearches, + __in IXMLDOMNode* pixnBundleExtension + ); + +void UtilSearchUninitialize( + __in UTIL_SEARCHES* pSearches + ); + +STDMETHODIMP UtilSearchExecute( + __in UTIL_SEARCHES* pSearches, + __in LPCWSTR wzSearchId, + __in LPCWSTR wzVariable, + __in IBundleExtensionEngine* pEngine + ); + +STDMETHODIMP UtilSearchFindById( + __in UTIL_SEARCHES* pSearches, + __in LPCWSTR wzId, + __out UTIL_SEARCH** ppSearch + ); diff --git a/src/ext/Util/ca/BroadcastSettingChange.cpp b/src/ext/Util/ca/BroadcastSettingChange.cpp new file mode 100644 index 00000000..2e153ad3 --- /dev/null +++ b/src/ext/Util/ca/BroadcastSettingChange.cpp @@ -0,0 +1,45 @@ +// Copyright (c) .NET 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" + + +/******************************************************************** +WixBroadcastSettingChange + + Send WM_SETTINGCHANGE message to all top-level windows indicating + that unspecified settings have changed. +********************************************************************/ +extern "C" UINT __stdcall WixBroadcastSettingChange( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr = WcaInitialize(hInstall, "WixBroadcastSettingChange"); + ExitOnFailure(hr, "failed to initialize WixBroadcastSettingChange"); + + // best effort; ignore failures + ::SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE, NULL, NULL, SMTO_ABORTIFHUNG, 1000, NULL); + +LExit: + return WcaFinalize(ERROR_SUCCESS); +} + + +/******************************************************************** +WixBroadcastEnvironmentChange + + Send WM_SETTINGCHANGE message to all top-level windows indicating + that environment variables have changed. +********************************************************************/ +extern "C" UINT __stdcall WixBroadcastEnvironmentChange( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr = WcaInitialize(hInstall, "WixBroadcastEnvironmentChange"); + ExitOnFailure(hr, "failed to initialize WixBroadcastEnvironmentChange"); + + // best effort; ignore failures + ::SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE, NULL, reinterpret_cast(L"Environment"), SMTO_ABORTIFHUNG, 1000, NULL); + +LExit: + return WcaFinalize(ERROR_SUCCESS); +} diff --git a/src/ext/Util/ca/CheckReboot.cpp b/src/ext/Util/ca/CheckReboot.cpp new file mode 100644 index 00000000..ce056411 --- /dev/null +++ b/src/ext/Util/ca/CheckReboot.cpp @@ -0,0 +1,36 @@ +// Copyright (c) .NET 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" + + +/******************************************************************** +WixCheckRebootRequired - entry point for WixCheckRebootRequired Custom Action + + called as Type 1 CustomAction (binary DLL) from Windows Installer + in InstallExecuteSequence after InstallFinalize +********************************************************************/ +extern "C" UINT __stdcall WixCheckRebootRequired( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "WixCheckRebootRequired"); + ExitOnFailure(hr, "failed to initialize"); + + if (WcaDidDeferredActionRequireReboot()) + { + WcaLog(LOGMSG_STANDARD, "Reboot required by deferred CustomAction."); + + er = ::MsiSetMode(hInstall, MSIRUNMODE_REBOOTATEND, TRUE); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed to schedule reboot."); + } + +LExit: + + if (FAILED(hr)) + er = ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} diff --git a/src/ext/Util/ca/CloseApps.cpp b/src/ext/Util/ca/CloseApps.cpp new file mode 100644 index 00000000..d4256c43 --- /dev/null +++ b/src/ext/Util/ca/CloseApps.cpp @@ -0,0 +1,568 @@ +// Copyright (c) .NET 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 DEFAULT_PROCESS_EXIT_WAIT_TIME 5000 + +// structs +LPCWSTR wzQUERY_CLOSEAPPS = L"SELECT `Wix4CloseApplication`, `Target`, `Description`, `Condition`, `Attributes`, `Property`, `TerminateExitCode`, `Timeout` FROM `Wix4CloseApplication` ORDER BY `Sequence`"; +enum eQUERY_CLOSEAPPS { QCA_ID = 1, QCA_TARGET, QCA_DESCRIPTION, QCA_CONDITION, QCA_ATTRIBUTES, QCA_PROPERTY, QCA_TERMINATEEXITCODE, QCA_TIMEOUT }; + +// CloseApplication.Attributes +enum CLOSEAPP_ATTRIBUTES +{ + CLOSEAPP_ATTRIBUTE_NONE = 0x0, + CLOSEAPP_ATTRIBUTE_CLOSEMESSAGE = 0x1, + CLOSEAPP_ATTRIBUTE_REBOOTPROMPT = 0x2, + CLOSEAPP_ATTRIBUTE_ELEVATEDCLOSEMESSAGE = 0x4, + CLOSEAPP_ATTRIBUTE_ENDSESSIONMESSAGE = 0x8, + CLOSEAPP_ATTRIBUTE_ELEVATEDENDSESSIONMESSAGE = 0x10, + CLOSEAPP_ATTRIBUTE_TERMINATEPROCESS = 0x20, + CLOSEAPP_ATTRIBUTE_PROMPTTOCONTINUE = 0x40, +}; + +struct PROCESS_AND_MESSAGE +{ + DWORD dwProcessId; + DWORD dwMessageId; + DWORD dwTimeout; +}; + + +/****************************************************************** + EnumWindowsProc - callback function which sends message if the + current window matches the passed in process ID + +******************************************************************/ +BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) +{ + PROCESS_AND_MESSAGE* pPM = reinterpret_cast(lParam); + DWORD dwProcessId = 0; + DWORD_PTR dwResult = 0; + BOOL fQueryEndSession = WM_QUERYENDSESSION == pPM->dwMessageId; + BOOL fContinueWindowsInProcess = TRUE; // assume we will send message to all top-level windows in a process. + + ::GetWindowThreadProcessId(hwnd, &dwProcessId); + + // check if the process Id is the one we're looking for + if (dwProcessId != pPM->dwProcessId) + { + return TRUE; + } + + WcaLog(LOGMSG_VERBOSE, "Sending message to process id 0x%x", dwProcessId); + + if (::SendMessageTimeoutW(hwnd, pPM->dwMessageId, 0, fQueryEndSession ? ENDSESSION_CLOSEAPP : 0, SMTO_BLOCK, pPM->dwTimeout, &dwResult)) + { + WcaLog(LOGMSG_VERBOSE, "Result 0x%x", dwResult); + + if (fQueryEndSession) + { + // If application said it was okay to close, do that. + if (dwResult) + { + ::SendMessageTimeoutW(hwnd, WM_ENDSESSION, TRUE, ENDSESSION_CLOSEAPP, SMTO_BLOCK, pPM->dwTimeout, &dwResult); + } + else // application said don't try to close it, so don't bother sending messages to any other top-level windows. + { + fContinueWindowsInProcess = FALSE; + } + } + } + else // log result message. + { + WcaLog(LOGMSG_VERBOSE, "Failed to send message id: %u, error: 0x%x", pPM->dwMessageId, ::GetLastError()); + } + + // so we know we succeeded + ::SetLastError(ERROR_SUCCESS); + + return fContinueWindowsInProcess; +} + +/****************************************************************** + PromptToContinue - displays the prompt if the application is still + running. + +******************************************************************/ +static HRESULT PromptToContinue( + __in_z LPCWSTR wzApplication, + __in_z LPCWSTR wzPrompt + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + PMSIHANDLE hRecMessage = NULL; + DWORD *prgProcessIds = NULL; + DWORD cProcessIds = 0; + + hRecMessage = ::MsiCreateRecord(1); + ExitOnNull(hRecMessage, hr, E_OUTOFMEMORY, "Failed to create record for prompt."); + + er = ::MsiRecordSetStringW(hRecMessage, 0, wzPrompt); + ExitOnWin32Error(er, hr, "Failed to set prompt record field string"); + + do + { + hr = ProcFindAllIdsFromExeName(wzApplication, &prgProcessIds, &cProcessIds); + if (SUCCEEDED(hr) && 0 < cProcessIds) + { + er = WcaProcessMessage(static_cast(INSTALLMESSAGE_WARNING | MB_ABORTRETRYIGNORE | MB_DEFBUTTON3 | MB_ICONWARNING), hRecMessage); + if (IDABORT == er) + { + hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); + } + else if (IDRETRY == er) + { + hr = S_FALSE; + } + else if (IDIGNORE == er) + { + hr = S_OK; + } + else + { + ExitOnWin32Error(er, hr, "Unexpected return value from prompt to continue."); + } + } + + ReleaseNullMem(prgProcessIds); + cProcessIds = 0; + } while (S_FALSE == hr); + +LExit: + ReleaseMem(prgProcessIds); + return hr; +} + +/****************************************************************** + SendProcessMessage - helper function to enumerate the top-level + windows and send to all matching a process ID. + +******************************************************************/ +void SendProcessMessage( + __in DWORD dwProcessId, + __in DWORD dwMessageId, + __in DWORD dwTimeout + ) +{ + WcaLog(LOGMSG_VERBOSE, "Attempting to send process id 0x%x message id: %u", dwProcessId, dwMessageId); + + PROCESS_AND_MESSAGE pm = { }; + pm.dwProcessId = dwProcessId; + pm.dwMessageId = dwMessageId; + pm.dwTimeout = dwTimeout; + + if (!::EnumWindows(EnumWindowsProc, reinterpret_cast(&pm))) + { + DWORD dwLastError = ::GetLastError(); + if (ERROR_SUCCESS != dwLastError) + { + WcaLog(LOGMSG_VERBOSE, "CloseApp enumeration error: 0x%x", dwLastError); + } + } +} + +/****************************************************************** + SendApplicationMessage - helper function to iterate through the + processes for the specified application and send all + applicable process Ids a message and give them time to process + the message. + +******************************************************************/ +void SendApplicationMessage( + __in LPCWSTR wzApplication, + __in DWORD dwMessageId, + __in DWORD dwTimeout + ) +{ + DWORD *prgProcessIds = NULL; + DWORD cProcessIds = 0, iProcessId; + HRESULT hr = S_OK; + + WcaLog(LOGMSG_VERBOSE, "Checking App: %ls ", wzApplication); + + hr = ProcFindAllIdsFromExeName(wzApplication, &prgProcessIds, &cProcessIds); + + if (SUCCEEDED(hr) && 0 < cProcessIds) + { + WcaLog(LOGMSG_VERBOSE, "App: %ls found running, %d processes, attempting to send message.", wzApplication, cProcessIds); + + for (iProcessId = 0; iProcessId < cProcessIds; ++iProcessId) + { + SendProcessMessage(prgProcessIds[iProcessId], dwMessageId, dwTimeout); + } + + ProcWaitForIds(prgProcessIds, cProcessIds, dwTimeout); + } + + ReleaseMem(prgProcessIds); +} + +/****************************************************************** + SetRunningProcessProperty - helper function that sets the specified + property if there are any instances of the specified executable + running. Useful to show custom UI to ask for shutdown. +******************************************************************/ +void SetRunningProcessProperty( + __in LPCWSTR wzApplication, + __in LPCWSTR wzProperty + ) +{ + DWORD *prgProcessIds = NULL; + DWORD cProcessIds = 0; + HRESULT hr = S_OK; + + WcaLog(LOGMSG_VERBOSE, "Checking App: %ls ", wzApplication); + + hr = ProcFindAllIdsFromExeName(wzApplication, &prgProcessIds, &cProcessIds); + + if (SUCCEEDED(hr) && 0 < cProcessIds) + { + WcaLog(LOGMSG_VERBOSE, "App: %ls found running, %d processes, setting '%ls' property.", wzApplication, cProcessIds, wzProperty); + WcaSetIntProperty(wzProperty, cProcessIds); + } + + ReleaseMem(prgProcessIds); +} + +/****************************************************************** + TerminateProcesses - helper function that kills the provided set of + process ids such that they return a particular exit code. +******************************************************************/ +void TerminateProcesses( + __in_ecount(cProcessIds) DWORD rgdwProcessIds[], + __in DWORD cProcessIds, + __in DWORD dwExitCode + ) +{ + for (DWORD i = 0; i < cProcessIds; ++i) + { + HANDLE hProcess = ::OpenProcess(PROCESS_TERMINATE, FALSE, rgdwProcessIds[i]); + if (hProcess) + { + ::TerminateProcess(hProcess, dwExitCode); + ::CloseHandle(hProcess); + } + } +} + +/****************************************************************** + WixCloseApplications - entry point for WixCloseApplications Custom Action + + called as Type 1 CustomAction (binary DLL) from Windows Installer + in InstallExecuteSequence before InstallFiles +******************************************************************/ +extern "C" UINT __stdcall WixCloseApplications( + __in MSIHANDLE hInstall + ) +{ + //AssertSz(FALSE, "debug WixCloseApplications"); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + LPWSTR pwzData = NULL; + LPWSTR pwzId = NULL; + LPWSTR pwzTarget = NULL; + LPWSTR pwzDescription = NULL; + LPWSTR pwzCondition = NULL; + LPWSTR pwzProperty = NULL; + DWORD dwAttributes = 0; + DWORD dwTimeout = 0; + DWORD dwTerminateExitCode = 0; + MSICONDITION condition = MSICONDITION_NONE; + + DWORD cCloseApps = 0; + + PMSIHANDLE hView = NULL; + PMSIHANDLE hRec = NULL; + MSIHANDLE hListboxTable = NULL; + MSIHANDLE hListboxColumns = NULL; + + LPWSTR pwzCustomActionData = NULL; + //DWORD cchCustomActionData = 0; + + // + // initialize + // + hr = WcaInitialize(hInstall, "WixCloseApplications"); + ExitOnFailure(hr, "failed to initialize"); + + // + // loop through all the objects to be secured + // + hr = WcaOpenExecuteView(wzQUERY_CLOSEAPPS, &hView); + ExitOnFailure(hr, "failed to open view on Wix4CloseApplication table"); + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + hr = WcaGetRecordString(hRec, QCA_ID, &pwzId); + ExitOnFailure(hr, "failed to get id from Wix4CloseApplication table"); + + hr = WcaGetRecordString(hRec, QCA_CONDITION, &pwzCondition); + ExitOnFailure(hr, "failed to get condition from Wix4CloseApplication table"); + + if (pwzCondition && *pwzCondition) + { + condition = ::MsiEvaluateConditionW(hInstall, pwzCondition); + if (MSICONDITION_ERROR == condition) + { + hr = E_INVALIDARG; + ExitOnFailure(hr, "failed to process condition for Wix4CloseApplication '%ls'", pwzId); + } + else if (MSICONDITION_FALSE == condition) + { + continue; // skip processing this target + } + } + + hr = WcaGetRecordFormattedString(hRec, QCA_TARGET, &pwzTarget); + ExitOnFailure(hr, "failed to get target from Wix4CloseApplication table"); + + hr = WcaGetRecordFormattedString(hRec, QCA_DESCRIPTION, &pwzDescription); + ExitOnFailure(hr, "failed to get description from Wix4CloseApplication table"); + + hr = WcaGetRecordInteger(hRec, QCA_ATTRIBUTES, reinterpret_cast(&dwAttributes)); + ExitOnFailure(hr, "failed to get attributes from Wix4CloseApplication table"); + + hr = WcaGetRecordFormattedString(hRec, QCA_PROPERTY, &pwzProperty); + ExitOnFailure(hr, "failed to get property from Wix4CloseApplication table"); + + hr = WcaGetRecordInteger(hRec, QCA_TERMINATEEXITCODE, reinterpret_cast(&dwTerminateExitCode)); + if (S_FALSE == hr) + { + dwTerminateExitCode = 0; + hr = S_OK; + } + ExitOnFailure(hr, "failed to get terminate exit-code from Wix4CloseApplication table"); + + hr = WcaGetRecordInteger(hRec, QCA_TIMEOUT, reinterpret_cast(&dwTimeout)); + if (S_FALSE == hr) + { + dwTimeout = DEFAULT_PROCESS_EXIT_WAIT_TIME; + hr = S_OK; + } + ExitOnFailure(hr, "failed to get timeout from Wix4CloseApplication table"); + + // Before trying any changes to the machine, prompt if requested. + if (dwAttributes & CLOSEAPP_ATTRIBUTE_PROMPTTOCONTINUE) + { + hr = PromptToContinue(pwzTarget, pwzDescription ? pwzDescription : L""); + if (HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) == hr) + { + // Skip error message if user canceled. + ExitFunction(); + } + ExitOnFailure(hr, "Failure while prompting user to continue to close application."); + } + + // + // send WM_CLOSE or WM_QUERYENDSESSION to currently running applications + // + if (dwAttributes & CLOSEAPP_ATTRIBUTE_CLOSEMESSAGE) + { + SendApplicationMessage(pwzTarget, WM_CLOSE, dwTimeout); + } + + if (dwAttributes & CLOSEAPP_ATTRIBUTE_ENDSESSIONMESSAGE) + { + SendApplicationMessage(pwzTarget, WM_QUERYENDSESSION, dwTimeout); + } + + // + // Pass the targets to the deferred action in case the app comes back + // even if we close it now. + // + if (dwAttributes & (CLOSEAPP_ATTRIBUTE_ELEVATEDCLOSEMESSAGE | CLOSEAPP_ATTRIBUTE_ELEVATEDENDSESSIONMESSAGE | CLOSEAPP_ATTRIBUTE_REBOOTPROMPT | CLOSEAPP_ATTRIBUTE_TERMINATEPROCESS)) + { + hr = WcaWriteStringToCaData(pwzTarget, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add target data to CustomActionData"); + + hr = WcaWriteIntegerToCaData(dwAttributes, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add attribute data to CustomActionData"); + + hr = WcaWriteIntegerToCaData(dwTimeout, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add timeout data to CustomActionData"); + + hr = WcaWriteIntegerToCaData(dwTerminateExitCode, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add timeout data to CustomActionData"); + } + + if (pwzProperty && *pwzProperty) + { + SetRunningProcessProperty(pwzTarget, pwzProperty); + } + + ++cCloseApps; + } + + // if we looped through all records all is well + if (E_NOMOREITEMS == hr) + { + hr = S_OK; + } + ExitOnFailure(hr, "failed while looping through all apps to close"); + + // + // Do the UI dance now. + // + /* + + TODO: Do this eventually + + if (cCloseApps) + { + while (TRUE) + { + for (DWORD i = 0; i < cCloseApps; ++i) + { + hr = WcaAddTempRecord(&hListboxTable, &hListboxColumns, L"ListBox", NULL, 0, 4, L"FileInUseProcess", i, target, description); + if (FAILED(hr)) + { + } + } + } + } + */ + + // + // schedule the custom action and add to progress bar + // + if (pwzCustomActionData && *pwzCustomActionData) + { + Assert(0 < cCloseApps); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CloseApplicationsDeferred"), pwzCustomActionData, cCloseApps * COST_CLOSEAPP); + ExitOnFailure(hr, "failed to schedule CloseApplicationsDeferred action"); + } + +LExit: + if (hListboxColumns) + { + ::MsiCloseHandle(hListboxColumns); + } + if (hListboxTable) + { + ::MsiCloseHandle(hListboxTable); + } + + ReleaseStr(pwzCustomActionData); + ReleaseStr(pwzData); + ReleaseStr(pwzProperty); + ReleaseStr(pwzCondition); + ReleaseStr(pwzDescription); + ReleaseStr(pwzTarget); + ReleaseStr(pwzId); + + if (FAILED(hr)) + { + er = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) == hr ? ERROR_INSTALL_USEREXIT : ERROR_INSTALL_FAILURE; + } + return WcaFinalize(er); +} + + +/****************************************************************** + WixCloseApplicationsDeferred - entry point for + WixCloseApplicationsDeferred Custom Action + called as Type 1025 CustomAction + (deferred binary DLL) + + NOTE: deferred CustomAction since it modifies the machine + NOTE: CustomActionData == wzTarget\tdwAttributes\tdwTimeout\tdwTerminateExitCode\t... +******************************************************************/ +extern "C" UINT __stdcall WixCloseApplicationsDeferred( + __in MSIHANDLE hInstall + ) +{ + //AssertSz(FALSE, "debug WixCloseApplicationsDeferred"); + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + + LPWSTR pwz = NULL; + LPWSTR pwzData = NULL; + LPWSTR pwzTarget = NULL; + DWORD dwAttributes = 0; + DWORD dwTimeout = 0; + DWORD dwTerminateExitCode = 0; + + DWORD *prgProcessIds = NULL; + DWORD cProcessIds = 0; + + // + // initialize + // + hr = WcaInitialize(hInstall, "WixCloseApplicationsDeferred"); + ExitOnFailure(hr, "failed to initialize"); + + hr = WcaGetProperty(L"CustomActionData", &pwzData); + ExitOnFailure(hr, "failed to get CustomActionData"); + + WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); + + pwz = pwzData; + + // + // loop through all the passed in data + // + while (pwz && *pwz) + { + hr = WcaReadStringFromCaData(&pwz, &pwzTarget); + ExitOnFailure(hr, "failed to process target from CustomActionData"); + + hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwAttributes)); + ExitOnFailure(hr, "failed to process attributes from CustomActionData"); + + hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwTimeout)); + ExitOnFailure(hr, "failed to process timeout from CustomActionData"); + + hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwTerminateExitCode)); + ExitOnFailure(hr, "failed to process terminate exit code from CustomActionData"); + + WcaLog(LOGMSG_VERBOSE, "Checking for App: %ls Attributes: %d", pwzTarget, dwAttributes); + + // + // send WM_CLOSE or WM_QUERYENDSESSION to currently running applications + // + if (dwAttributes & CLOSEAPP_ATTRIBUTE_ELEVATEDCLOSEMESSAGE) + { + SendApplicationMessage(pwzTarget, WM_CLOSE, dwTimeout); + } + + if (dwAttributes & CLOSEAPP_ATTRIBUTE_ELEVATEDENDSESSIONMESSAGE) + { + SendApplicationMessage(pwzTarget, WM_QUERYENDSESSION, dwTimeout); + } + + // If we find that an app that we need closed is still runing, require a + // restart or kill the process as directed. + ProcFindAllIdsFromExeName(pwzTarget, &prgProcessIds, &cProcessIds); + if (0 < cProcessIds) + { + if (dwAttributes & CLOSEAPP_ATTRIBUTE_REBOOTPROMPT) + { + WcaLog(LOGMSG_VERBOSE, "App: %ls found running, requiring a reboot.", pwzTarget); + + WcaDeferredActionRequiresReboot(); + } + else if (dwAttributes & CLOSEAPP_ATTRIBUTE_TERMINATEPROCESS) + { + TerminateProcesses(prgProcessIds, cProcessIds, dwTerminateExitCode); + } + } + + hr = WcaProgressMessage(COST_CLOSEAPP, FALSE); + ExitOnFailure(hr, "failed to send progress message"); + } + +LExit: + ReleaseMem(prgProcessIds); + + ReleaseStr(pwzTarget); + ReleaseStr(pwzData); + + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + return WcaFinalize(er); +} diff --git a/src/ext/Util/ca/CustomMsiErrors.h b/src/ext/Util/ca/CustomMsiErrors.h new file mode 100644 index 00000000..3218b61b --- /dev/null +++ b/src/ext/Util/ca/CustomMsiErrors.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. + + +#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 msierrPERFMONFailedRegisterDLL 26251 +#define msierrPERFMONFailedUnregisterDLL 26252 +#define msierrInstallPerfCounterData 26253 +#define msierrUninstallPerfCounterData 26254 + +#define msierrSMBFailedCreate 26301 +#define msierrSMBFailedDrop 26302 +#define msierrUSRFailedUserCreate 26401 +#define msierrUSRFailedUserCreatePswd 26402 +#define msierrUSRFailedUserGroupAdd 26403 +#define msierrUSRFailedUserCreateExists 26404 +#define msierrUSRFailedGrantLogonAsService 26405 + +//Last available is 26450 \ No newline at end of file diff --git a/src/ext/Util/ca/FormatFiles.cpp b/src/ext/Util/ca/FormatFiles.cpp new file mode 100644 index 00000000..d1533999 --- /dev/null +++ b/src/ext/Util/ca/FormatFiles.cpp @@ -0,0 +1,221 @@ +// Copyright (c) .NET 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 UINT COST_FILEFORMATTING = 2000; + + +// +// WixSchedFormatFiles - immediate CA to schedule format files CAs +// +extern "C" UINT __stdcall WixSchedFormatFiles( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + PSCZ sczBinaryKey; + PSCZ sczFileKey; + PSCZ sczComponentKey; + PSCZ sczFormattedFile; + PSCZ sczFilePath; + PMSIHANDLE hView; + PMSIHANDLE hRec; + PSCZ sczFileContent; + PSCZ sczFormattedContent; + PSCZ sczExecCustomActionData; + PSCZ sczRollbackCustomActionData; + + LPCWSTR wzQuery = + L"SELECT `Wix4FormatFile`.`Binary_`, `Wix4FormatFile`.`File_`, `File`.`Component_` " + L"FROM `Wix4FormatFile`, `File` " + L"WHERE `Wix4FormatFile`.`File_` = `File`.`File`"; + enum eQuery { eqBinaryKey = 1, eqFileKey, eqComponentKey }; + + // initialize + hr = WcaInitialize(hInstall, "WixSchedFormatFiles"); + ExitOnFailure(hr, "Failed to initialize for WixSchedFormatFiles."); + + // query and loop through all the files + hr = WcaOpenExecuteView(wzQuery, &hView); + ExitOnFailure(hr, "Failed to open view on Wix4FormatFile table"); + + DWORD cFiles = 0; + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + ++cFiles; + + hr = WcaGetRecordString(hRec, eqBinaryKey, &sczBinaryKey); + ExitOnFailure(hr, "Failed to get Binary table key."); + + hr = WcaGetRecordString(hRec, eqFileKey, &sczFileKey); + ExitOnFailure(hr, "Failed to get File table key."); + + hr = WcaGetRecordString(hRec, eqComponentKey, &sczComponentKey); + ExitOnFailure(hr, "Failed to get Component table key."); + + // we need to know if the component's being installed, uninstalled, or reinstalled + WCA_TODO todo = WcaGetComponentToDo(sczComponentKey); + if (WCA_TODO_INSTALL == todo || WCA_TODO_REINSTALL == todo) + { + // turn the file key into the path to the target file + hr = StrAllocFormatted(&sczFormattedFile, L"[#%ls]", sczFileKey); + ExitOnFailure(hr, "Failed to format file string for file: %ls", sczFileKey); + hr = WcaGetFormattedString(sczFormattedFile, &sczFilePath); + ExitOnFailure(hr, "Failed to get path for file: %ls", sczFileKey); + + // extract binary to string + WCA_ENCODING encoding = WCA_ENCODING_UNKNOWN; + hr = WcaExtractBinaryToString(sczBinaryKey, &sczFileContent, &encoding); + ExitOnFailure(hr, "Failed to extract binary: %ls", sczBinaryKey); + + // format string + hr = WcaGetFormattedString(sczFileContent, &sczFormattedContent); + ExitOnFailure(hr, "Failed to format file content: %ls", sczFileContent); + + // write to deferred custom action data + hr = WcaWriteStringToCaData(sczFilePath, &sczExecCustomActionData); + ExitOnFailure(hr, "Failed to write deferred custom action data for file: %ls", sczFilePath); + + hr = WcaWriteIntegerToCaData(encoding, &sczExecCustomActionData); + ExitOnFailure(hr, "Failed to write deferred custom action data for encoding: %d", encoding); + + hr = WcaWriteStringToCaData(sczFormattedContent, &sczExecCustomActionData); + ExitOnFailure(hr, "Failed to write deferred custom action data for file content: %ls", sczFilePath); + + // write to rollback custom action data + hr = WcaWriteStringToCaData(sczFilePath, &sczRollbackCustomActionData); + ExitOnFailure(hr, "Failed to write rollback custom action data for file: %ls", sczFilePath); + + hr = WcaWriteIntegerToCaData(encoding, &sczRollbackCustomActionData); + ExitOnFailure(hr, "Failed to write deferred custom action data for encoding: %d", encoding); + + hr = WcaWriteStringToCaData(sczFileContent, &sczRollbackCustomActionData); + ExitOnFailure(hr, "Failed to write rollback custom action data for file content: %ls", sczFilePath); + } + } + + // reaching the end of the list is actually a good thing, not an error + if (E_NOMOREITEMS == hr) + { + hr = S_OK; + } + ExitOnFailure(hr, "Failure occurred while processing Wix4FormatFile table"); + + // schedule deferred CAs if there's anything to do + if (sczRollbackCustomActionData && *sczRollbackCustomActionData) + { + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackFormatFiles"), sczRollbackCustomActionData, cFiles * COST_FILEFORMATTING); + ExitOnFailure(hr, "Failed to schedule RollbackFormatFiles"); + } + + if (sczExecCustomActionData && *sczExecCustomActionData) + { + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecFormatFiles"), sczExecCustomActionData, cFiles * COST_FILEFORMATTING); + ExitOnFailure(hr, "Failed to schedule ExecFormatFiles"); + } + +LExit: + return WcaFinalize(er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er); +} + + +// +// WixExecFormatFiles - deferred and rollback CAs to write formatted files +// +extern "C" UINT __stdcall WixExecFormatFiles( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + PSCZ sczCustomActionData; + LPWSTR pwz = NULL; + PSCZ sczFilePath; + PSCZ sczFileContent; + LPSTR psz = NULL; + + // initialize + hr = WcaInitialize(hInstall, "WixExecFormatFiles"); + ExitOnFailure(hr, "Failed to initialize for WixExecFormatFiles."); + + hr = WcaGetProperty(L"CustomActionData", &sczCustomActionData); + ExitOnFailure(hr, "Failed to get CustomActionData."); +#ifdef _DEBUG + WcaLog(LOGMSG_STANDARD, "CustomActionData: %ls", sczCustomActionData); +#endif + + // loop through all the passed in data + pwz = sczCustomActionData; + while (pwz && *pwz) + { + // extract the custom action data + hr = WcaReadStringFromCaData(&pwz, &sczFilePath); + ExitOnFailure(hr, "Failed to read file path from custom action data"); + + WCA_ENCODING encoding = WCA_ENCODING_UNKNOWN; + hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&encoding)); + ExitOnFailure(hr, "Failed to read encoding from custom action data"); + + hr = WcaReadStringFromCaData(&pwz, &sczFileContent); + ExitOnFailure(hr, "Failed to read file content from custom action data"); + + // re-encode content + LPCBYTE pbData = NULL; + size_t cbData = 0; + switch (encoding) + { + case WCA_ENCODING_UTF_16: + pbData = reinterpret_cast(LPCWSTR(sczFileContent)); + cbData = lstrlenW(sczFileContent) * sizeof(WCHAR); + break; + + case WCA_ENCODING_UTF_8: + hr = StrAnsiAllocString(&psz, sczFileContent, 0, CP_UTF8); + ExitOnFailure(hr, "Failed to convert Unicode to UTF-8."); + pbData = reinterpret_cast(psz); + + hr = ::StringCbLengthA(psz, STRSAFE_MAX_CCH, &cbData); + ExitOnFailure(hr, "Failed to count UTF-8 bytes."); + break; + + case WCA_ENCODING_ANSI: + hr = StrAnsiAllocString(&psz, sczFileContent, 0, CP_ACP); + ExitOnFailure(hr, "Failed to convert Unicode to ANSI."); + pbData = reinterpret_cast(psz); + + hr = ::StringCbLengthA(psz, STRSAFE_MAX_CCH, &cbData); + ExitOnFailure(hr, "Failed to count UTF-8 bytes."); + break; + + default: + break; + } + +#ifdef _DEBUG + WcaLog(LOGMSG_STANDARD, "File: %ls", sczCustomActionData); + WcaLog(LOGMSG_STANDARD, "Content: %ls", sczFileContent); +#endif + + // write file and preserve modified time + FILETIME filetime; + + hr = FileGetTime(sczFilePath, NULL, NULL, &filetime); + ExitOnFailure(hr, "Failed to get modified time of file : %ls", sczFilePath); + + hr = FileWrite(sczFilePath, FILE_ATTRIBUTE_NORMAL, pbData, cbData, NULL); + ExitOnFailure(hr, "Failed to write file content: %ls", sczFilePath); + + hr = FileSetTime(sczFilePath, NULL, NULL, &filetime); + ExitOnFailure(hr, "Failed to set modified time of file : %ls", sczFilePath); + + // Tick the progress bar + hr = WcaProgressMessage(COST_FILEFORMATTING, FALSE); + ExitOnFailure(hr, "Failed to tick progress bar for file: %ls", sczFilePath); + } + +LExit: + ReleaseStr(psz); + + return WcaFinalize(er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er); +} diff --git a/src/ext/Util/ca/OsInfo.cpp b/src/ext/Util/ca/OsInfo.cpp new file mode 100644 index 00000000..4783673e --- /dev/null +++ b/src/ext/Util/ca/OsInfo.cpp @@ -0,0 +1,487 @@ +// Copyright (c) .NET 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" + +// constants we'll pick up from later SDKs +#define SM_TABLETPC 86 +#define SM_MEDIACENTER 87 +#define SM_STARTER 88 +#define SM_SERVERR2 89 +#define VER_SUITE_WH_SERVER 0x00008000 + +/******************************************************************** +WixQueryOsInfo - entry point for WixQueryOsInfo custom action + + Called as Type 1 custom action (DLL from the Binary table) from + Windows Installer to set properties that identify OS information + and predefined directories +********************************************************************/ +extern "C" UINT __stdcall WixQueryOsInfo( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + OSVERSIONINFOEXW ovix = {0}; + + hr = WcaInitialize(hInstall, "WixQueryOsInfo"); + ExitOnFailure(hr, "WixQueryOsInfo failed to initialize"); + + // identify product suites + ovix.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); + #pragma warning(suppress: 4996) //TODO: use osutil + ::GetVersionExW(reinterpret_cast(&ovix)); + + if (VER_SUITE_SMALLBUSINESS == (ovix.wSuiteMask & VER_SUITE_SMALLBUSINESS)) + { + WcaSetIntProperty(L"WIX_SUITE_SMALLBUSINESS", 1); + } + + if (VER_SUITE_ENTERPRISE == (ovix.wSuiteMask & VER_SUITE_ENTERPRISE)) + { + WcaSetIntProperty(L"WIX_SUITE_ENTERPRISE", 1); + } + + if (VER_SUITE_BACKOFFICE == (ovix.wSuiteMask & VER_SUITE_BACKOFFICE)) + { + WcaSetIntProperty(L"WIX_SUITE_BACKOFFICE", 1); + } + + if (VER_SUITE_COMMUNICATIONS == (ovix.wSuiteMask & VER_SUITE_COMMUNICATIONS)) + { + WcaSetIntProperty(L"WIX_SUITE_COMMUNICATIONS", 1); + } + + if (VER_SUITE_TERMINAL == (ovix.wSuiteMask & VER_SUITE_TERMINAL)) + { + WcaSetIntProperty(L"WIX_SUITE_TERMINAL", 1); + } + + if (VER_SUITE_SMALLBUSINESS_RESTRICTED == (ovix.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED)) + { + WcaSetIntProperty(L"WIX_SUITE_SMALLBUSINESS_RESTRICTED", 1); + } + + if (VER_SUITE_EMBEDDEDNT == (ovix.wSuiteMask & VER_SUITE_EMBEDDEDNT)) + { + WcaSetIntProperty(L"WIX_SUITE_EMBEDDEDNT", 1); + } + + if (VER_SUITE_DATACENTER == (ovix.wSuiteMask & VER_SUITE_DATACENTER)) + { + WcaSetIntProperty(L"WIX_SUITE_DATACENTER", 1); + } + + if (VER_SUITE_SINGLEUSERTS == (ovix.wSuiteMask & VER_SUITE_SINGLEUSERTS)) + { + WcaSetIntProperty(L"WIX_SUITE_SINGLEUSERTS", 1); + } + + if (VER_SUITE_PERSONAL == (ovix.wSuiteMask & VER_SUITE_PERSONAL)) + { + WcaSetIntProperty(L"WIX_SUITE_PERSONAL", 1); + } + + if (VER_SUITE_BLADE == (ovix.wSuiteMask & VER_SUITE_BLADE)) + { + WcaSetIntProperty(L"WIX_SUITE_BLADE", 1); + } + + if (VER_SUITE_EMBEDDED_RESTRICTED == (ovix.wSuiteMask & VER_SUITE_EMBEDDED_RESTRICTED)) + { + WcaSetIntProperty(L"WIX_SUITE_EMBEDDED_RESTRICTED", 1); + } + + if (VER_SUITE_SECURITY_APPLIANCE == (ovix.wSuiteMask & VER_SUITE_SECURITY_APPLIANCE)) + { + WcaSetIntProperty(L"WIX_SUITE_SECURITY_APPLIANCE", 1); + } + + if (VER_SUITE_STORAGE_SERVER == (ovix.wSuiteMask & VER_SUITE_STORAGE_SERVER)) + { + WcaSetIntProperty(L"WIX_SUITE_STORAGE_SERVER", 1); + } + + if (VER_SUITE_COMPUTE_SERVER == (ovix.wSuiteMask & VER_SUITE_COMPUTE_SERVER)) + { + WcaSetIntProperty(L"WIX_SUITE_COMPUTE_SERVER", 1); + } + + if (VER_SUITE_WH_SERVER == (ovix.wSuiteMask & VER_SUITE_WH_SERVER)) + { + WcaSetIntProperty(L"WIX_SUITE_WH_SERVER", 1); + } + + // only for XP and later + if (5 < ovix.dwMajorVersion || (5 == ovix.dwMajorVersion && 0 < ovix.dwMinorVersion)) + { + if (::GetSystemMetrics(SM_SERVERR2)) + { + WcaSetIntProperty(L"WIX_SUITE_SERVERR2", 1); + } + + if (::GetSystemMetrics(SM_MEDIACENTER)) + { + WcaSetIntProperty(L"WIX_SUITE_MEDIACENTER", 1); + } + + if (::GetSystemMetrics(SM_STARTER)) + { + WcaSetIntProperty(L"WIX_SUITE_STARTER", 1); + } + + if (::GetSystemMetrics(SM_TABLETPC)) + { + WcaSetIntProperty(L"WIX_SUITE_TABLETPC", 1); + } + } + +LExit: + if (FAILED(hr)) + er = ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + +/******************************************************************** +WixQueryOsDirs - entry point for WixQueryOsDirs custom action + + Called as Type 1 custom action (DLL from the Binary table) from + Windows Installer to set properties that identify predefined directories +********************************************************************/ +extern "C" UINT __stdcall WixQueryOsDirs( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "WixQueryOsDirs"); + ExitOnFailure(hr, "WixQueryOsDirs failed to initialize"); + + // get the paths of the CSIDLs that represent real paths and for which MSI + // doesn't yet have standard folder properties + WCHAR path[MAX_PATH]; + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_ADMINTOOLS", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_ALTSTARTUP, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_ALTSTARTUP", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_CDBURN_AREA, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_CDBURN_AREA", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_COMMON_ADMINTOOLS, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_COMMON_ADMINTOOLS", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_COMMON_ALTSTARTUP, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_COMMON_ALTSTARTUP", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_COMMON_DOCUMENTS, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_COMMON_DOCUMENTS", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_COMMON_FAVORITES, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_COMMON_FAVORITES", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_COMMON_MUSIC, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_COMMON_MUSIC", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_COMMON_PICTURES, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_COMMON_PICTURES", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_COMMON_VIDEO, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_COMMON_VIDEO", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_COOKIES, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_COOKIES", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_DESKTOP", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_HISTORY, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_HISTORY", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_INTERNET_CACHE, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_INTERNET_CACHE", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_MYMUSIC, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_MYMUSIC", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_MYPICTURES", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_MYVIDEO, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_MYVIDEO", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_NETHOOD", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_PERSONAL", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_PRINTHOOD", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_PROFILE", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_RECENT", path); + } + + if (ERROR_SUCCESS == ::SHGetFolderPathW(NULL, CSIDL_RESOURCES, NULL, SHGFP_TYPE_CURRENT, path)) + { + WcaSetProperty(L"WIX_DIR_RESOURCES", path); + } + +LExit: + if (FAILED(hr)) + er = ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + +/******************************************************************** +SetPropertyWellKnownSID + + Set a property with the localized name of a well known windows SID +********************************************************************/ +static HRESULT SetPropertyWellKnownSID( + __in WELL_KNOWN_SID_TYPE sidType, + __in LPCWSTR wzPropertyName, + __in BOOL fIncludeDomainName + ) +{ + HRESULT hr = S_OK; + PSID psid = NULL; + WCHAR wzRefDomain[MAX_PATH] = {0}; + SID_NAME_USE nameUse; + DWORD refSize = MAX_PATH; + WCHAR wzName[MAX_PATH] = {0}; + LPWSTR pwzPropertyValue = NULL; + DWORD size = MAX_PATH; + + hr = AclGetWellKnownSid(sidType, &psid); + ExitOnFailure(hr, "Failed to get SID; skipping account %ls", wzPropertyName); + + if (!::LookupAccountSidW(NULL, psid, wzName, &size, wzRefDomain, &refSize, &nameUse)) + { + ExitWithLastError(hr, "Failed to look up account for SID; skipping account %ls.", wzPropertyName); + } + + if (fIncludeDomainName) + { + hr = StrAllocFormatted(&pwzPropertyValue, L"%s\\%s", wzRefDomain, wzName); + ExitOnFailure(hr, "Failed to format property value"); + + hr = WcaSetProperty(wzPropertyName, pwzPropertyValue); + ExitOnFailure(hr, "Failed write domain\\name property"); + } + else + { + hr = WcaSetProperty(wzPropertyName, wzName); + ExitOnFailure(hr, "Failed write to name-only property"); + } + +LExit: + if (NULL != psid) + { + ::LocalFree(psid); + } + ReleaseStr(pwzPropertyValue); + return hr; +} + +/******************************************************************** +WixQueryOsWellKnownSID - entry point for WixQueryOsWellKnownSID custom action + + Called as Type 1 custom action (DLL from the Binary table) from + Windows Installer to set properties with the localized names of built-in + Windows Security IDs +********************************************************************/ +extern "C" UINT __stdcall WixQueryOsWellKnownSID( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "WixQueryOsWellKnownSID"); + ExitOnFailure(hr, "WixQueryOsWellKnownSID failed to initialize"); + + SetPropertyWellKnownSID(WinLocalSystemSid, L"WIX_ACCOUNT_LOCALSYSTEM", TRUE); + SetPropertyWellKnownSID(WinLocalServiceSid, L"WIX_ACCOUNT_LOCALSERVICE", TRUE); + SetPropertyWellKnownSID(WinNetworkServiceSid, L"WIX_ACCOUNT_NETWORKSERVICE", TRUE); + SetPropertyWellKnownSID(WinBuiltinAdministratorsSid, L"WIX_ACCOUNT_ADMINISTRATORS", TRUE); + SetPropertyWellKnownSID(WinBuiltinUsersSid, L"WIX_ACCOUNT_USERS", TRUE); + SetPropertyWellKnownSID(WinBuiltinGuestsSid, L"WIX_ACCOUNT_GUESTS", TRUE); + SetPropertyWellKnownSID(WinBuiltinPerfLoggingUsersSid, L"WIX_ACCOUNT_PERFLOGUSERS", TRUE); + SetPropertyWellKnownSID(WinBuiltinPerfLoggingUsersSid, L"WIX_ACCOUNT_PERFLOGUSERS_NODOMAIN", FALSE); + +LExit: + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + return WcaFinalize(er); +} + + +/******************************************************************** +DetectWDDMDriver + + Set a property if the driver on the machine is a WDDM driver. One + reliable way to detect the presence of a WDDM driver is to try and + use the Direct3DCreate9Ex() function. This method attempts that + then sets the property appropriately. +********************************************************************/ +static HRESULT DetectWDDMDriver() +{ + HRESULT hr = S_OK; + HMODULE hModule = NULL; + + // Manually load the d3d9.dll library. If the library couldn't be loaded then we obviously won't be able + // to try calling the function so just return. + hr = LoadSystemLibrary(L"d3d9.dll", &hModule); + if (E_MODNOTFOUND == hr) + { + TraceError(hr, "Unable to load DirectX APIs, skipping WDDM driver check."); + ExitFunction1(hr = S_OK); + } + ExitOnFailure(hr, "Failed to the load the existing DirectX APIs."); + + // Obtain the address of the Direct3DCreate9Ex function. If this fails we know it isn't a WDDM + // driver so just exit. + const void* Direct3DCreate9ExPtr = ::GetProcAddress(hModule, "Direct3DCreate9Ex"); + ExitOnNull(Direct3DCreate9ExPtr, hr, S_OK, "Unable to load Direct3DCreateEx function, so the driver is not a WDDM driver."); + + // At this point we know it's a WDDM driver so set the property. + hr = WcaSetIntProperty(L"WIX_WDDM_DRIVER_PRESENT", 1); + ExitOnFailure(hr, "Failed write property"); + +LExit: + if (NULL != hModule) + { + FreeLibrary(hModule); + } + + return hr; +} + +/******************************************************************** +DetectIsCompositionEnabled + + Set a property based on the return value of DwmIsCompositionEnabled(). +********************************************************************/ +static HRESULT DetectIsCompositionEnabled() +{ + HRESULT hr = S_OK; + HMODULE hModule = NULL; + BOOL compositionState = false; + + // Manually load the d3d9.dll library. If the library can't load it's likely because we are not on a Vista + // OS. Just return ok, and the property won't get set. + hr = LoadSystemLibrary(L"dwmapi.dll", &hModule); + if (E_MODNOTFOUND == hr) + { + TraceError(hr, "Unable to load Vista desktop window manager APIs, skipping Composition Enabled check."); + ExitFunction1(hr = S_OK); + } + ExitOnFailure(hr, "Failed to load the existing window manager APIs."); + + // If for some reason we can't get the function pointer that's ok, just return. + typedef HRESULT (WINAPI *DWMISCOMPOSITIONENABLEDPTR)(BOOL*); + DWMISCOMPOSITIONENABLEDPTR DwmIsCompositionEnabledPtr = (DWMISCOMPOSITIONENABLEDPTR)::GetProcAddress(hModule, "DwmIsCompositionEnabled"); + ExitOnNull(hModule, hr, S_OK, "Unable to obtain function information, skipping Composition Enabled check."); + + hr = DwmIsCompositionEnabledPtr(&compositionState); + ExitOnFailure(hr, "Failed to retrieve Composition state"); + + if (compositionState) + { + hr = WcaSetIntProperty(L"WIX_DWM_COMPOSITION_ENABLED", 1); + ExitOnFailure(hr, "Failed write property"); + } + +LExit: + if (NULL != hModule) + { + FreeLibrary(hModule); + } + return hr; +} + +/******************************************************************** +WixQueryOsDriverInfo - entry point for WixQueryOsDriverInfo custom action + + Called as Type 1 custom action (DLL from the Binary table) from + Windows Installer to set properties about drivers installed on + the target machine +********************************************************************/ +extern "C" UINT __stdcall WixQueryOsDriverInfo( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "WixQueryOsDriverInfo"); + ExitOnFailure(hr, "WixQueryOsDriverInfo failed to initialize"); + + // Detect the WDDM driver status + hr = DetectWDDMDriver(); + ExitOnFailure(hr, "Failed to detect WIX_WDDM_DRIVER_PRESENT"); + + // Detect whether composition is enabled + hr = DetectIsCompositionEnabled(); + ExitOnFailure(hr, "Failed to detect WIX_DWM_COMPOSITION_ENABLED"); + +LExit: + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + return WcaFinalize(er); +} diff --git a/src/ext/Util/ca/RemoveFoldersEx.cpp b/src/ext/Util/ca/RemoveFoldersEx.cpp new file mode 100644 index 00000000..cbc7f4bb --- /dev/null +++ b/src/ext/Util/ca/RemoveFoldersEx.cpp @@ -0,0 +1,243 @@ +// Copyright (c) .NET 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 vcsRemoveFolderExQuery = + L"SELECT `Wix4RemoveFolderEx`, `Component_`, `Property`, `InstallMode`, `WixRemoveFolderEx`.`Condition`, `Component`.`Attributes`" + L"FROM `Wix4RemoveFolderEx``,`Component` " + L"WHERE `Wix4RemoveFolderEx`.`Component_`=`Component`.`Component`"; +enum eRemoveFolderExQuery { rfqId = 1, rfqComponent, rfqProperty, rfqMode, rfqCondition, rfqComponentAttributes }; + +static HRESULT RecursePath( + __in_z LPCWSTR wzPath, + __in_z LPCWSTR wzId, + __in_z LPCWSTR wzComponent, + __in_z LPCWSTR wzProperty, + __in int iMode, + __in BOOL fDisableWow64Redirection, + __inout DWORD* pdwCounter, + __inout MSIHANDLE* phTable, + __inout MSIHANDLE* phColumns + ) +{ + HRESULT hr = S_OK; + DWORD er; + LPWSTR sczSearch = NULL; + LPWSTR sczProperty = NULL; + HANDLE hFind = INVALID_HANDLE_VALUE; + WIN32_FIND_DATAW wfd; + LPWSTR sczNext = NULL; + + if (fDisableWow64Redirection) + { + hr = WcaDisableWow64FSRedirection(); + ExitOnFailure(hr, "Custom action was told to act on a 64-bit component, but was unable to disable filesystem redirection through the Wow64 API."); + } + + // First recurse down to all the child directories. + hr = StrAllocFormatted(&sczSearch, L"%s*", wzPath); + ExitOnFailure(hr, "Failed to allocate file search string in path: %S", wzPath); + + hFind = ::FindFirstFileW(sczSearch, &wfd); + if (INVALID_HANDLE_VALUE == hFind) + { + er = ::GetLastError(); + if (ERROR_PATH_NOT_FOUND == er) + { + WcaLog(LOGMSG_STANDARD, "Search path not found: %ls; skipping", sczSearch); + ExitFunction1(hr = S_FALSE); + } + else + { + hr = HRESULT_FROM_WIN32(er); + } + ExitOnFailure(hr, "Failed to find all files in path: %S", wzPath); + } + + do + { + // Skip files and the dot directories. + if (FILE_ATTRIBUTE_DIRECTORY != (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || L'.' == wfd.cFileName[0] && (L'\0' == wfd.cFileName[1] || (L'.' == wfd.cFileName[1] && L'\0' == wfd.cFileName[2]))) + { + continue; + } + + hr = StrAllocFormatted(&sczNext, L"%s%s\\", wzPath, wfd.cFileName); + ExitOnFailure(hr, "Failed to concat filename '%S' to string: %S", wfd.cFileName, wzPath); + + // Don't re-disable redirection; if it was necessary, we've already done it. + hr = RecursePath(sczNext, wzId, wzComponent, wzProperty, iMode, FALSE, pdwCounter, phTable, phColumns); + ExitOnFailure(hr, "Failed to recurse path: %S", sczNext); + } while (::FindNextFileW(hFind, &wfd)); + + er = ::GetLastError(); + if (ERROR_NO_MORE_FILES == er) + { + hr = S_OK; + } + else + { + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed while looping through files in directory: %S", wzPath); + } + + // Finally, set a property that points at our path. + hr = StrAllocFormatted(&sczProperty, L"_%s_%u", wzProperty, *pdwCounter); + ExitOnFailure(hr, "Failed to allocate Property for RemoveFile table with property: %S.", wzProperty); + + ++(*pdwCounter); + + hr = WcaSetProperty(sczProperty, wzPath); + ExitOnFailure(hr, "Failed to set Property: %S with path: %S", sczProperty, wzPath); + + // Add the row to remove any files and another row to remove the folder. + hr = WcaAddTempRecord(phTable, phColumns, L"RemoveFile", NULL, 1, 5, L"RfxFiles", wzComponent, L"*.*", sczProperty, iMode); + ExitOnFailure(hr, "Failed to add row to remove all files for Wix4RemoveFolderEx row: %ls under path: %ls", wzId, wzPath); + + hr = WcaAddTempRecord(phTable, phColumns, L"RemoveFile", NULL, 1, 5, L"RfxFolder", wzComponent, NULL, sczProperty, iMode); + ExitOnFailure(hr, "Failed to add row to remove folder for Wix4RemoveFolderEx row: %ls under path: %ls", wzId, wzPath); + +LExit: + if (INVALID_HANDLE_VALUE != hFind) + { + ::FindClose(hFind); + } + + if (fDisableWow64Redirection) + { + WcaRevertWow64FSRedirection(); + } + + ReleaseStr(sczNext); + ReleaseStr(sczProperty); + ReleaseStr(sczSearch); + return hr; +} + +extern "C" UINT WINAPI WixRemoveFoldersEx( + __in MSIHANDLE hInstall + ) +{ + //AssertSz(FALSE, "debug WixRemoveFoldersEx"); + + HRESULT hr = S_OK; + PMSIHANDLE hView; + PMSIHANDLE hRec; + LPWSTR sczId = NULL; + LPWSTR sczComponent = NULL; + LPWSTR sczProperty = NULL; + LPWSTR sczCondition = NULL; + LPWSTR sczPath = NULL; + LPWSTR sczExpandedPath = NULL; + int iMode = 0; + int iComponentAttributes; + BOOL f64BitComponent = FALSE; + DWORD dwCounter = 0; + DWORD_PTR cchLen = 0; + MSIHANDLE hTable = NULL; + MSIHANDLE hColumns = NULL; + + hr = WcaInitialize(hInstall, "WixRemoveFoldersEx"); + ExitOnFailure(hr, "Failed to initialize WixRemoveFoldersEx."); + + WcaInitializeWow64(); + + // anything to do? + if (S_OK != WcaTableExists(L"Wix4RemoveFolderEx")) + { + WcaLog(LOGMSG_STANDARD, "Wix4RemoveFolderEx table doesn't exist, so there are no folders to remove."); + ExitFunction(); + } + + // query and loop through all the remove folders exceptions + hr = WcaOpenExecuteView(vcsRemoveFolderExQuery, &hView); + ExitOnFailure(hr, "Failed to open view on Wix4RemoveFolderEx table"); + + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + hr = WcaGetRecordString(hRec, rfqId, &sczId); + ExitOnFailure(hr, "Failed to get remove folder identity."); + + hr = WcaGetRecordString(hRec, rfqCondition, &sczCondition); + ExitOnFailure(hr, "Failed to get remove folder condition."); + + if (sczCondition && *sczCondition) + { + MSICONDITION condition = ::MsiEvaluateConditionW(hInstall, sczCondition); + if (MSICONDITION_TRUE == condition) + { + WcaLog(LOGMSG_STANDARD, "True condition for row %S: %S; processing.", sczId, sczCondition); + } + else + { + WcaLog(LOGMSG_STANDARD, "False or invalid condition for row %S: %S; skipping.", sczId, sczCondition); + continue; + } + } + + hr = WcaGetRecordString(hRec, rfqComponent, &sczComponent); + ExitOnFailure(hr, "Failed to get remove folder component."); + + hr = WcaGetRecordString(hRec, rfqProperty, &sczProperty); + ExitOnFailure(hr, "Failed to get remove folder property."); + + hr = WcaGetRecordInteger(hRec, rfqMode, &iMode); + ExitOnFailure(hr, "Failed to get remove folder mode"); + + hr = WcaGetProperty(sczProperty, &sczPath); + ExitOnFailure(hr, "Failed to resolve remove folder property: %S for row: %S", sczProperty, sczId); + + hr = WcaGetRecordInteger(hRec, rfqComponentAttributes, &iComponentAttributes); + ExitOnFailure(hr, "failed to get component attributes for row: %ls", sczId); + + f64BitComponent = iComponentAttributes & msidbComponentAttributes64bit; + + // fail early if the property isn't set as you probably don't want your installers trying to delete SystemFolder + // StringCchLengthW succeeds only if the string is zero characters plus 1 for the terminating null + hr = ::StringCchLengthW(sczPath, 1, reinterpret_cast(&cchLen)); + if (SUCCEEDED(hr)) + { + ExitOnFailure(hr = E_INVALIDARG, "Missing folder property: %S for row: %S", sczProperty, sczId); + } + + hr = PathExpand(&sczExpandedPath, sczPath, PATH_EXPAND_ENVIRONMENT); + ExitOnFailure(hr, "Failed to expand path: %S for row: %S", sczPath, sczId); + + hr = PathBackslashTerminate(&sczExpandedPath); + ExitOnFailure(hr, "Failed to backslash-terminate path: %S", sczExpandedPath); + + WcaLog(LOGMSG_STANDARD, "Recursing path: %S for row: %S.", sczExpandedPath, sczId); + hr = RecursePath(sczExpandedPath, sczId, sczComponent, sczProperty, iMode, f64BitComponent, &dwCounter, &hTable, &hColumns); + ExitOnFailure(hr, "Failed while navigating path: %S for row: %S", sczPath, sczId); + } + + // reaching the end of the list is actually a good thing, not an error + if (E_NOMOREITEMS == hr) + { + hr = S_OK; + } + ExitOnFailure(hr, "Failure occured while processing Wix4RemoveFolderEx table"); + +LExit: + WcaFinalizeWow64(); + + if (hColumns) + { + ::MsiCloseHandle(hColumns); + } + + if (hTable) + { + ::MsiCloseHandle(hTable); + } + + ReleaseStr(sczExpandedPath); + ReleaseStr(sczPath); + ReleaseStr(sczProperty); + ReleaseStr(sczComponent); + ReleaseStr(sczCondition); + ReleaseStr(sczId); + + DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} diff --git a/src/ext/Util/ca/RemoveRegistryKeysEx.cpp b/src/ext/Util/ca/RemoveRegistryKeysEx.cpp new file mode 100644 index 00000000..478c0779 --- /dev/null +++ b/src/ext/Util/ca/RemoveRegistryKeysEx.cpp @@ -0,0 +1,114 @@ +// Copyright (c) .NET 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 vcsRemoveRegistryKeyExQuery = + L"SELECT `Wix4RemoveRegistryKeyEx`, `Component_`, `Root`, `Key`, `InstallMode`, `Condition` FROM `Wix4RemoveRegistryKeyEx`"; +enum eRemoveRegistryKeyExQuery { rrxqId = 1, rrxqComponent, rrxqRoot, rrxqKey, rrxqMode, rrxqCondition }; + +extern "C" UINT WINAPI WixRemoveRegistryKeysEx( + __in MSIHANDLE hInstall +) +{ + //AssertSz(FALSE, "debug WixRemoveRegistryKeyEx"); + + HRESULT hr = S_OK; + PMSIHANDLE hView; + PMSIHANDLE hRec; + LPWSTR sczId = NULL; + LPWSTR sczComponent = NULL; + LPWSTR sczCondition = NULL; + LPWSTR sczKey = NULL; + int iRoot = 0; + int iMode = 0; + MSIHANDLE hTable = NULL; + MSIHANDLE hColumns = NULL; + + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize " __FUNCTION__); + + // anything to do? + if (S_OK != WcaTableExists(L"Wix4RemoveRegistryKeyEx")) + { + WcaLog(LOGMSG_STANDARD, "Wix4RemoveRegistryKeyEx table doesn't exist, so there are no registry keys to remove."); + ExitFunction(); + } + + hr = WcaOpenExecuteView(vcsRemoveRegistryKeyExQuery, &hView); + ExitOnFailure(hr, "Failed to open view on Wix4RemoveRegistryKeyEx table"); + + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + hr = WcaGetRecordString(hRec, rrxqId, &sczId); + ExitOnFailure(hr, "Failed to get Wix4RemoveRegistryKeyEx identity."); + + hr = WcaGetRecordString(hRec, rrxqCondition, &sczCondition); + ExitOnFailure(hr, "Failed to get Wix4RemoveRegistryKeyEx condition."); + + if (sczCondition && *sczCondition) + { + MSICONDITION condition = ::MsiEvaluateConditionW(hInstall, sczCondition); + if (MSICONDITION_TRUE == condition) + { + WcaLog(LOGMSG_STANDARD, "True condition for row %S: %S; processing.", sczId, sczCondition); + } + else + { + WcaLog(LOGMSG_STANDARD, "False or invalid condition for row %S: %S; skipping.", sczId, sczCondition); + continue; + } + } + + hr = WcaGetRecordString(hRec, rrxqComponent, &sczComponent); + ExitOnFailure(hr, "Failed to get Wix4RemoveRegistryKeyEx component."); + + hr = WcaGetRecordInteger(hRec, rrxqRoot, &iRoot); + ExitOnFailure(hr, "Failed to get Wix4RemoveRegistryKeyEx root."); + + hr = WcaGetRecordString(hRec, rrxqKey, &sczKey); + ExitOnFailure(hr, "Failed to get Wix4RemoveRegistryKeyEx key."); + + hr = WcaGetRecordInteger(hRec, rrxqMode, &iMode); + ExitOnFailure(hr, "Failed to get Wix4RemoveRegistryKeyEx mode."); + + switch (iMode) + { + case 1: // remove on install + WcaLog(LOGMSG_STANDARD, "Adding RemoveRegistry row: %ls/%d/%ls/-/%ls", sczId, iRoot, sczKey, sczComponent); + hr = WcaAddTempRecord(&hTable, &hColumns, L"RemoveRegistry", NULL, 0, 5, sczId, iRoot, sczKey, L"-", sczComponent); + ExitOnFailure(hr, "Failed to add RemoveRegistry row for remove-on-install Wix4RemoveRegistryKeyEx row: %ls:", sczId); + break; + case 2: // remove on uninstall + WcaLog(LOGMSG_STANDARD, "Adding Registry row: %ls/%d/%ls/-/null/%ls", sczId, iRoot, sczKey, sczComponent); + hr = WcaAddTempRecord(&hTable, &hColumns, L"Registry", NULL, 0, 6, sczId, iRoot, sczKey, L"-", NULL, sczComponent); + ExitOnFailure(hr, "Failed to add Registry row for remove-on-uninstall Wix4RemoveRegistryKeyEx row: %ls:", sczId); + break; + } + } + + // reaching the end of the list is actually a good thing, not an error + if (E_NOMOREITEMS == hr) + { + hr = S_OK; + } + ExitOnFailure(hr, "Failure occured while processing Wix4RemoveRegistryKeyEx table."); + +LExit: + if (hColumns) + { + ::MsiCloseHandle(hColumns); + } + + if (hTable) + { + ::MsiCloseHandle(hTable); + } + + ReleaseStr(sczKey); + ReleaseStr(sczComponent); + ReleaseStr(sczCondition); + ReleaseStr(sczId); + + DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} diff --git a/src/ext/Util/ca/RestartManager.cpp b/src/ext/Util/ca/RestartManager.cpp new file mode 100644 index 00000000..c31819c1 --- /dev/null +++ b/src/ext/Util/ca/RestartManager.cpp @@ -0,0 +1,185 @@ +// Copyright (c) .NET 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" +#include + +// Include space for the terminating null. +#define CCH_SESSION_KEY CCH_RM_SESSION_KEY + 1 + +enum eRmuResourceType +{ + etInvalid, + etFilename, + etApplication, + etServiceName, + + // Mask types from Attributes. + etTypeMask = 0xf, +}; + +LPCWSTR vcsRestartResourceQuery = + L"SELECT `Wix4RestartResource`.`Wix4RestartResource`, `Wix4RestartResource`.`Component_`, `Wix4RestartResource`.`Resource`, `Wix4RestartResource`.`Attributes` " + L"FROM `Wix4RestartResource`"; +enum eRestartResourceQuery { rrqRestartResource = 1, rrqComponent, rrqResource, rrqAttributes }; + +/******************************************************************** +WixRegisterRestartResources - Immediate CA to register resources with RM. + +Enumerates components before InstallValidate and registers resources +to be restarted by Restart Manager if the component action +is anything other than None. + +Do not disable file system redirection. + +********************************************************************/ +extern "C" UINT __stdcall WixRegisterRestartResources( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + PMSIHANDLE hView = NULL; + PMSIHANDLE hRec = NULL; + + LPWSTR wzSessionKey = NULL; + size_t cchSessionKey = 0; + PRMU_SESSION pSession = NULL; + + LPWSTR wzRestartResource = NULL; + LPWSTR wzComponent = NULL; + LPWSTR wzResource = NULL; + int iAttributes = NULL; + BOOL fIsComponentNull = FALSE; + WCA_TODO todo = WCA_TODO_UNKNOWN; + int iType = etInvalid; + + hr = WcaInitialize(hInstall, "WixRegisterRestartResources"); + ExitOnFailure(hr, "Failed to initialize."); + + // Skip if the table doesn't exist. + if (S_OK != WcaTableExists(L"Wix4RestartResource")) + { + WcaLog(LOGMSG_STANDARD, "The Wix4RestartResource table does not exist; there are no resources to register with Restart Manager."); + ExitFunction(); + } + + // Get the existing Restart Manager session if available. + hr = WcaGetProperty(L"MsiRestartManagerSessionKey", &wzSessionKey); + ExitOnFailure(hr, "Failed to get the MsiRestartManagerSessionKey property."); + + hr = ::StringCchLengthW(wzSessionKey, CCH_SESSION_KEY, &cchSessionKey); + ExitOnFailure(hr, "Failed to get the MsiRestartManagerSessionKey string length."); + + // Skip if the property doesn't exist. + if (0 == cchSessionKey) + { + WcaLog(LOGMSG_STANDARD, "The MsiRestartManagerSessionKey property is not available to join."); + ExitFunction(); + } + + // Join the existing Restart Manager session if supported. + hr = RmuJoinSession(&pSession, wzSessionKey); + if (E_MODNOTFOUND == hr) + { + WcaLog(LOGMSG_STANDARD, "The Restart Manager is not supported on this platform. Skipping."); + ExitFunction1(hr = S_OK); + } + else if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Failed to join the existing Restart Manager session %ls.", wzSessionKey); + ExitFunction1(hr = S_OK); + } + + // Loop through each record in the table. + hr = WcaOpenExecuteView(vcsRestartResourceQuery, &hView); + ExitOnFailure(hr, "Failed to open a view on the RestartResource table."); + + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + hr = WcaGetRecordString(hRec, rrqRestartResource, &wzRestartResource); + ExitOnFailure(hr, "Failed to get the RestartResource field value."); + + hr = WcaGetRecordString(hRec, rrqComponent, &wzComponent); + ExitOnFailure(hr, "Failed to get the Component_ field value."); + + hr = WcaGetRecordFormattedString(hRec, rrqResource, &wzResource); + ExitOnFailure(hr, "Failed to get the Resource formatted field value."); + + hr = WcaGetRecordInteger(hRec, rrqAttributes, &iAttributes); + ExitOnFailure(hr, "Failed to get the Attributes field value."); + + fIsComponentNull = ::MsiRecordIsNull(hRec, rrqComponent); + todo = WcaGetComponentToDo(wzComponent); + + // Only register resources for components that are null, or being installed, reinstalled, or uninstalled. + if (!fIsComponentNull && WCA_TODO_UNKNOWN == todo) + { + WcaLog(LOGMSG_VERBOSE, "Skipping resource %ls.", wzRestartResource); + continue; + } + + // Get the type from Attributes and add to the Restart Manager. + iType = iAttributes & etTypeMask; + switch (iType) + { + case etFilename: + WcaLog(LOGMSG_VERBOSE, "Registering file name %ls with the Restart Manager.", wzResource); + hr = RmuAddFile(pSession, wzResource); + ExitOnFailure(hr, "Failed to register the file name with the Restart Manager session."); + break; + + case etApplication: + WcaLog(LOGMSG_VERBOSE, "Registering process name %ls with the Restart Manager.", wzResource); + hr = RmuAddProcessesByName(pSession, wzResource); + if (E_NOTFOUND == hr) + { + // ERROR_ACCESS_DENIED was returned when trying to register this process. + // Since other instances may have been registered, log a message and continue the setup rather than failing. + WcaLog(LOGMSG_STANDARD, "The process, %ls, could not be registered with the Restart Manager (probably because the setup is not elevated and the process is in another user context). A reboot may be requested later.", wzResource); + hr = S_OK; + } + else + { + ExitOnFailure(hr, "Failed to register the process name with the Restart Manager session."); + } + break; + + case etServiceName: + WcaLog(LOGMSG_VERBOSE, "Registering service name %ls with the Restart Manager.", wzResource); + hr = RmuAddService(pSession, wzResource); + ExitOnFailure(hr, "Failed to register the service name with the Restart Manager session."); + break; + + default: + WcaLog(LOGMSG_VERBOSE, "The resource type %d for %ls is not supported and will not be registered.", iType, wzRestartResource); + break; + } + } + + if (E_NOMOREITEMS == hr) + { + hr = S_OK; + } + ExitOnFailure(hr, "Failed while looping through all rows to register resources."); + + // Register the resources and unjoin the session. + hr = RmuEndSession(pSession); + if (FAILED(hr)) + { + WcaLog(LOGMSG_VERBOSE, "Failed to register the resources with the Restart Manager."); + ExitFunction1(hr = S_OK); + } + +LExit: + ReleaseStr(wzRestartResource); + ReleaseStr(wzComponent); + ReleaseStr(wzResource); + + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + + return WcaFinalize(er); +} diff --git a/src/ext/Util/ca/TouchFile.cpp b/src/ext/Util/ca/TouchFile.cpp new file mode 100644 index 00000000..e704f922 --- /dev/null +++ b/src/ext/Util/ca/TouchFile.cpp @@ -0,0 +1,308 @@ +// Copyright (c) .NET 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 vcsTouchFileQuery = L"SELECT `Wix4TouchFile`, `Component_`, `Path`, `Attributes` FROM `Wix4TouchFile`"; +enum TOUCH_FILE_QUERY { tfqId = 1, tfqComponent, tfqPath, tfqTouchFileAttributes }; + +enum TOUCH_FILE_ATTRIBUTE +{ + TOUCH_FILE_ATTRIBUTE_ON_INSTALL = 0x01, + TOUCH_FILE_ATTRIBUTE_ON_REINSTALL = 0x02, + TOUCH_FILE_ATTRIBUTE_ON_UNINSTALL = 0x04, + TOUCH_FILE_ATTRIBUTE_64BIT = 0x10, + TOUCH_FILE_ATTRIBUTE_VITAL = 0x20 +}; + + +static BOOL SetExistingFileModifiedTime( + __in_z LPCWSTR wzId, + __in_z LPCWSTR wzPath, + __in BOOL f64Bit, + __in FILETIME* pftModified + ) +{ + HRESULT hr = S_OK; + BOOL fReenableFileSystemRedirection = FALSE; + + if (f64Bit) + { + hr = WcaDisableWow64FSRedirection(); + ExitOnFailure(hr, "Failed to disable 64-bit file system redirection to path: '%ls' for: %ls", wzPath, wzId); + + fReenableFileSystemRedirection = TRUE; + } + + hr = FileSetTime(wzPath, NULL, NULL, pftModified); + +LExit: + if (fReenableFileSystemRedirection) + { + WcaRevertWow64FSRedirection(); + } + + return SUCCEEDED(hr); +} + + +static HRESULT AddDataToCustomActionData( + __deref_inout_z LPWSTR* psczCustomActionData, + __in_z LPCWSTR wzId, + __in_z LPCWSTR wzPath, + __in int iTouchFileAttributes, + __in FILETIME ftModified + ) +{ + HRESULT hr = S_OK; + + hr = WcaWriteStringToCaData(wzId, psczCustomActionData); + ExitOnFailure(hr, "Failed to add touch file identity to custom action data."); + + hr = WcaWriteStringToCaData(wzPath, psczCustomActionData); + ExitOnFailure(hr, "Failed to add touch file path to custom action data."); + + hr = WcaWriteIntegerToCaData(iTouchFileAttributes, psczCustomActionData); + ExitOnFailure(hr, "Failed to add touch file attributes to custom action data."); + + hr = WcaWriteIntegerToCaData(ftModified.dwHighDateTime, psczCustomActionData); + ExitOnFailure(hr, "Failed to add touch file high date/time to custom action data."); + + hr = WcaWriteIntegerToCaData(ftModified.dwLowDateTime, psczCustomActionData); + ExitOnFailure(hr, "Failed to add touch file low date/time to custom action data."); + +LExit: + return hr; +} + + +static BOOL TryGetExistingFileModifiedTime( + __in_z LPCWSTR wzId, + __in_z LPCWSTR wzPath, + __in BOOL f64Bit, + __inout FILETIME* pftModified + ) +{ + HRESULT hr = S_OK; + BOOL fReenableFileSystemRedirection = FALSE; + + if (f64Bit) + { + hr = WcaDisableWow64FSRedirection(); + ExitOnFailure(hr, "Failed to disable 64-bit file system redirection to path: '%ls' for: %ls", wzPath, wzId); + + fReenableFileSystemRedirection = TRUE; + } + + hr = FileGetTime(wzPath, NULL, NULL, pftModified); + if (E_PATHNOTFOUND == hr || E_FILENOTFOUND == hr) + { + // If the file doesn't exist yet there is nothing to rollback (i.e. file will probably be removed during rollback), so + // keep the error code but don't log anything. + } + else if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Cannot access modified timestamp for file: '%ls' due to error: 0x%x. Continuing with out rollback for: %ls", wzPath, hr, wzId); + } + +LExit: + if (fReenableFileSystemRedirection) + { + WcaRevertWow64FSRedirection(); + } + + return SUCCEEDED(hr); +} + + +static HRESULT ProcessTouchFileTable( + __in BOOL fInstalling + ) +{ + HRESULT hr = S_OK; + + FILETIME ftModified = {}; + + PMSIHANDLE hView; + PMSIHANDLE hRec; + + LPWSTR sczId = NULL; + LPWSTR sczComponent = NULL; + int iTouchFileAttributes = 0; + LPWSTR sczPath = NULL; + + FILETIME ftRollbackModified = {}; + LPWSTR sczRollbackData = NULL; + LPWSTR sczExecuteData = NULL; + + if (S_OK != WcaTableExists(L"Wix4TouchFile")) + { + ExitFunction(); + } + + ::GetSystemTimeAsFileTime(&ftModified); + + hr = WcaOpenExecuteView(vcsTouchFileQuery, &hView); + ExitOnFailure(hr, "Failed to open view on Wix4TouchFile table"); + + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + hr = WcaGetRecordString(hRec, tfqId, &sczId); + ExitOnFailure(hr, "Failed to get touch file identity."); + + hr = WcaGetRecordString(hRec, tfqComponent, &sczComponent); + ExitOnFailure(hr, "Failed to get touch file component for: %ls", sczId); + + hr = WcaGetRecordInteger(hRec, tfqTouchFileAttributes, &iTouchFileAttributes); + ExitOnFailure(hr, "Failed to get touch file attributes for: %ls", sczId); + + WCA_TODO todo = WcaGetComponentToDo(sczComponent); + + BOOL fOnInstall = fInstalling && WCA_TODO_INSTALL == todo && (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_ON_INSTALL); + BOOL fOnReinstall = fInstalling && WCA_TODO_REINSTALL == todo && (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_ON_REINSTALL); + BOOL fOnUninstall = !fInstalling && WCA_TODO_UNINSTALL == todo && (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_ON_UNINSTALL); + + if (fOnInstall || fOnReinstall || fOnUninstall) + { + hr = WcaGetRecordFormattedString(hRec, tfqPath, &sczPath); + ExitOnFailure(hr, "Failed to get touch file path for: %ls", sczId); + + if (TryGetExistingFileModifiedTime(sczId, sczPath, (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_64BIT), &ftRollbackModified)) + { + hr = AddDataToCustomActionData(&sczRollbackData, sczId, sczPath, iTouchFileAttributes, ftRollbackModified); + ExitOnFailure(hr, "Failed to add to rollback custom action data for: %ls", sczId); + } + + hr = AddDataToCustomActionData(&sczExecuteData, sczId, sczPath, iTouchFileAttributes, ftModified); + ExitOnFailure(hr, "Failed to add to execute custom action data for: %ls", sczId); + } + } + + if (E_NOMOREITEMS == hr) + { + hr = S_OK; + } + ExitOnFailure(hr, "Failure occured while processing Wix4TouchFile table"); + + if (sczRollbackData) + { + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackTouchFile"), sczRollbackData, 0); + ExitOnFailure(hr, "Failed to schedule RollbackTouchFile"); + } + + if (sczExecuteData) + { + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecuteTouchFile"), sczExecuteData, 0); + ExitOnFailure(hr, "Failed to schedule ExecuteTouchFile"); + } + +LExit: + ReleaseStr(sczExecuteData); + ReleaseStr(sczRollbackData); + ReleaseStr(sczPath); + ReleaseStr(sczComponent); + ReleaseStr(sczId); + + return hr; +} + + +extern "C" UINT WINAPI WixTouchFileDuringInstall( + __in MSIHANDLE hInstall + ) +{ + //AssertSz(FALSE, "debug WixTouchFileDuringInstall"); + + HRESULT hr = S_OK; + + hr = WcaInitialize(hInstall, "WixTouchFileDuringInstall"); + ExitOnFailure(hr, "Failed to initialize WixTouchFileDuringInstall."); + + hr = ProcessTouchFileTable(TRUE); + +LExit: + DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + +extern "C" UINT WINAPI WixTouchFileDuringUninstall( + __in MSIHANDLE hInstall + ) +{ + //AssertSz(FALSE, "debug WixTouchFileDuringUninstall"); + + HRESULT hr = S_OK; + + hr = WcaInitialize(hInstall, "WixTouchFileDuringUninstall"); + ExitOnFailure(hr, "Failed to initialize WixTouchFileDuringUninstall."); + + hr = ProcessTouchFileTable(FALSE); + +LExit: + DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + +extern "C" UINT WINAPI WixExecuteTouchFile( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + + LPWSTR sczData = NULL; + LPWSTR pwz = NULL; + + LPWSTR sczId = NULL; + LPWSTR sczPath = NULL; + int iTouchFileAttributes = 0; + FILETIME ftModified = {}; + + hr = WcaInitialize(hInstall, "WixExecuteTouchFile"); + ExitOnFailure(hr, "Failed to initialize WixExecuteTouchFile."); + + hr = WcaGetProperty(L"CustomActionData", &sczData); + ExitOnFailure(hr, "Failed to get custom action data for WixExecuteTouchFile."); + + pwz = sczData; + + while (pwz && *pwz) + { + hr = WcaReadStringFromCaData(&pwz, &sczId); + ExitOnFailure(hr, "Failed to get touch file identity from custom action data."); + + hr = WcaReadStringFromCaData(&pwz, &sczPath); + ExitOnFailure(hr, "Failed to get touch file path from custom action data for: %ls", sczId); + + hr = WcaReadIntegerFromCaData(&pwz, &iTouchFileAttributes); + ExitOnFailure(hr, "Failed to get touch file attributes from custom action data for: %ls", sczId); + + hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&ftModified.dwHighDateTime)); + ExitOnFailure(hr, "Failed to get touch file high date/time from custom action data for: %ls", sczId); + + hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&ftModified.dwLowDateTime)); + ExitOnFailure(hr, "Failed to get touch file low date/time from custom action data for: %ls", sczId); + + hr = SetExistingFileModifiedTime(sczId, sczPath, (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_64BIT), &ftModified); + if (FAILED(hr)) + { + if (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_VITAL) + { + ExitOnFailure(hr, "Failed to touch file: '%ls' for: %ls", &sczPath, sczId); + } + else + { + WcaLog(LOGMSG_STANDARD, "Could not touch non-vital file: '%ls' for: %ls with error: 0x%x. Continuing...", sczPath, sczId, hr); + hr = S_OK; + } + } + } + +LExit: + ReleaseStr(sczPath); + ReleaseStr(sczId); + ReleaseStr(sczData); + + DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} diff --git a/src/ext/Util/ca/XmlConfig.cpp b/src/ext/Util/ca/XmlConfig.cpp new file mode 100644 index 00000000..a1ec9d6f --- /dev/null +++ b/src/ext/Util/ca/XmlConfig.cpp @@ -0,0 +1,1130 @@ +// Copyright (c) .NET 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 XMLCONFIG_ELEMENT 0x00000001 +#define XMLCONFIG_VALUE 0x00000002 +#define XMLCONFIG_DOCUMENT 0x00000004 +#define XMLCONFIG_CREATE 0x00000010 +#define XMLCONFIG_DELETE 0x00000020 +#define XMLCONFIG_INSTALL 0x00000100 +#define XMLCONFIG_UNINSTALL 0x00000200 +#define XMLCONFIG_PRESERVE_MODIFIED 0x00001000 + +enum eXmlAction +{ + xaUnknown = 0, + xaOpenFile, + xaOpenFilex64, + xaWriteValue, + xaWriteDocument, + xaDeleteValue, + xaCreateElement, + xaDeleteElement, +}; + +enum eXmlPreserveDate +{ + xdDontPreserve = 0, + xdPreserve +}; + +LPCWSTR vcsXmlConfigQuery = + L"SELECT `Wix4XmlConfig`.`Wix4XmlConfig`, `Wix4XmlConfig`.`File`, `Wix4XmlConfig`.`ElementId`, `Wix4XmlConfig`.`ElementPath`, `Wix4XmlConfig`.`VerifyPath`, `Wix4XmlConfig`.`Name`, " + L"`Wix4XmlConfig`.`Value`, `Wix4XmlConfig`.`Flags`, `Wix4XmlConfig`.`Component_`, `Component`.`Attributes` " + L"FROM `Wix4XmlConfig`,`Component` WHERE `Wix4XmlConfig`.`Component_`=`Component`.`Component` ORDER BY `File`, `Sequence`"; +enum eXmlConfigQuery { xfqXmlConfig = 1, xfqFile, xfqElementId, xfqElementPath, xfqVerifyPath, xfqName, xfqValue, xfqXmlFlags, xfqComponent, xfqCompAttributes }; + +struct XML_CONFIG_CHANGE +{ + WCHAR wzId[MAX_DARWIN_KEY + 1]; + + WCHAR wzComponent[MAX_DARWIN_KEY + 1]; + INSTALLSTATE isInstalled; + INSTALLSTATE isAction; + + WCHAR wzFile[MAX_PATH]; + LPWSTR pwzElementId; + LPWSTR pwzElementPath; + LPWSTR pwzVerifyPath; + WCHAR wzName[MAX_DARWIN_COLUMN]; + LPWSTR pwzValue; + BOOL fInstalledFile; + + int iXmlFlags; + int iCompAttributes; + + XML_CONFIG_CHANGE* pxfcAdditionalChanges; + int cAdditionalChanges; + + XML_CONFIG_CHANGE* pxfcPrev; + XML_CONFIG_CHANGE* pxfcNext; +}; + +static HRESULT FreeXmlConfigChangeList( + __in_opt XML_CONFIG_CHANGE* pxfcList + ) +{ + HRESULT hr = S_OK; + + XML_CONFIG_CHANGE* pxfcDelete; + while(pxfcList) + { + pxfcDelete = pxfcList; + pxfcList = pxfcList->pxfcNext; + + if (pxfcDelete->pwzElementId) + { + hr = MemFree(pxfcDelete->pwzElementId); + ExitOnFailure(hr, "failed to free xml config element id in change list item"); + } + + if (pxfcDelete->pwzElementPath) + { + hr = MemFree(pxfcDelete->pwzElementPath); + ExitOnFailure(hr, "failed to free xml config element path in change list item"); + } + + if (pxfcDelete->pwzVerifyPath) + { + hr = MemFree(pxfcDelete->pwzVerifyPath); + ExitOnFailure(hr, "failed to free xml config verify path in change list item"); + } + + if (pxfcDelete->pwzValue) + { + hr = MemFree(pxfcDelete->pwzValue); + ExitOnFailure(hr, "failed to free xml config value in change list item"); + } + + hr = MemFree(pxfcDelete); + ExitOnFailure(hr, "failed to free xml config change list item"); + } + +LExit: + return hr; +} + +static HRESULT AddXmlConfigChangeToList( + __inout XML_CONFIG_CHANGE** ppxfcHead, + __inout XML_CONFIG_CHANGE** ppxfcTail + ) +{ + Assert(ppxfcHead && ppxfcTail); + + HRESULT hr = S_OK; + + XML_CONFIG_CHANGE* pxfc = static_cast(MemAlloc(sizeof(XML_CONFIG_CHANGE), TRUE)); + ExitOnNull(pxfc, hr, E_OUTOFMEMORY, "failed to allocate memory for new xml file change list element"); + + // Add it to the end of the list + if (NULL == *ppxfcHead) + { + *ppxfcHead = pxfc; + *ppxfcTail = pxfc; + } + else + { + Assert(*ppxfcTail && (*ppxfcTail)->pxfcNext == NULL); + (*ppxfcTail)->pxfcNext = pxfc; + pxfc->pxfcPrev = *ppxfcTail; + *ppxfcTail = pxfc; + } + +LExit: + return hr; +} + + +static HRESULT ReadXmlConfigTable( + __inout XML_CONFIG_CHANGE** ppxfcHead, + __inout XML_CONFIG_CHANGE** ppxfcTail + ) +{ + Assert(ppxfcHead && ppxfcTail); + + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + PMSIHANDLE hView = NULL; + PMSIHANDLE hRec = NULL; + + LPWSTR pwzData = NULL; + + // loop through all the xml configurations + hr = WcaOpenExecuteView(vcsXmlConfigQuery, &hView); + ExitOnFailure(hr, "failed to open view on Wix4XmlConfig table"); + + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + hr = AddXmlConfigChangeToList(ppxfcHead, ppxfcTail); + ExitOnFailure(hr, "failed to add xml file change to list"); + + // Get record Id + hr = WcaGetRecordString(hRec, xfqXmlConfig, &pwzData); + ExitOnFailure(hr, "failed to get Wix4XmlConfig record Id"); + hr = StringCchCopyW((*ppxfcTail)->wzId, countof((*ppxfcTail)->wzId), pwzData); + ExitOnFailure(hr, "failed to copy Wix4XmlConfig record Id"); + + // Get component name + hr = WcaGetRecordString(hRec, xfqComponent, &pwzData); + ExitOnFailure(hr, "failed to get component name for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); + + // Get the component's state + if (pwzData && *pwzData) + { + hr = StringCchCopyW((*ppxfcTail)->wzComponent, countof((*ppxfcTail)->wzComponent), pwzData); + ExitOnFailure(hr, "failed to copy component id"); + + er = ::MsiGetComponentStateW(WcaGetInstallHandle(), (*ppxfcTail)->wzComponent, &(*ppxfcTail)->isInstalled, &(*ppxfcTail)->isAction); + ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "failed to get install state for component id"); + } + + // Get the xml file + hr = WcaGetRecordFormattedString(hRec, xfqFile, &pwzData); + ExitOnFailure(hr, "failed to get xml file for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); + hr = StringCchCopyW((*ppxfcTail)->wzFile, countof((*ppxfcTail)->wzFile), pwzData); + ExitOnFailure(hr, "failed to copy xml file path"); + + // Figure out if the file is already on the machine or if it's being installed + hr = WcaGetRecordString(hRec, xfqFile, &pwzData); + ExitOnFailure(hr, "failed to get xml file for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); + if (NULL != wcsstr(pwzData, L"[!") || NULL != wcsstr(pwzData, L"[#")) + { + (*ppxfcTail)->fInstalledFile = TRUE; + } + + // Get the Wix4XmlConfig table flags + hr = WcaGetRecordInteger(hRec, xfqXmlFlags, &(*ppxfcTail)->iXmlFlags); + ExitOnFailure(hr, "failed to get Wix4XmlConfig flags for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); + + // Get the Element Id + hr = WcaGetRecordFormattedString(hRec, xfqElementId, &(*ppxfcTail)->pwzElementId); + ExitOnFailure(hr, "failed to get Element Id for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); + + // Get the Element Path + hr = WcaGetRecordFormattedString(hRec, xfqElementPath, &(*ppxfcTail)->pwzElementPath); + ExitOnFailure(hr, "failed to get Element Path for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); + + // Get the Verify Path + hr = WcaGetRecordFormattedString(hRec, xfqVerifyPath, &(*ppxfcTail)->pwzVerifyPath); + ExitOnFailure(hr, "failed to get Verify Path for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); + + // Get the name + hr = WcaGetRecordFormattedString(hRec, xfqName, &pwzData); + ExitOnFailure(hr, "failed to get Name for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); + hr = StringCchCopyW((*ppxfcTail)->wzName, countof((*ppxfcTail)->wzName), pwzData); + ExitOnFailure(hr, "failed to copy name of element"); + + // Get the value + hr = WcaGetRecordFormattedString(hRec, xfqValue, &pwzData); + ExitOnFailure(hr, "failed to get Value for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); + hr = StrAllocString(&(*ppxfcTail)->pwzValue, pwzData, 0); + ExitOnFailure(hr, "failed to allocate buffer for value"); + + // Get the component attributes + hr = WcaGetRecordInteger(hRec, xfqCompAttributes, &(*ppxfcTail)->iCompAttributes); + ExitOnFailure(hr, "failed to get component attributes for Wix4XmlConfig: %ls", (*ppxfcTail)->wzId); + } + + // if we looped through all records all is well + if (E_NOMOREITEMS == hr) + { + hr = S_OK; + } + ExitOnFailure(hr, "failed while looping through all objects to secure"); + +LExit: + ReleaseStr(pwzData); + + return hr; +} + +static HRESULT ProcessChanges( + __inout XML_CONFIG_CHANGE** ppxfcHead + ) +{ + Assert(ppxfcHead && *ppxfcHead); + HRESULT hr = S_OK; + + XML_CONFIG_CHANGE* pxfc = NULL; + XML_CONFIG_CHANGE* pxfcNext = NULL; + XML_CONFIG_CHANGE* pxfcCheck = NULL; + int cAdditionalChanges = 0; + XML_CONFIG_CHANGE* pxfcLast = NULL; + + // If there's only one item in the list, none of this matters + if (pxfc && !pxfc->pxfcNext) + { + ExitFunction(); + } + + // Loop through the list + pxfc = *ppxfcHead; + while (pxfc) + { + // Keep track of where our next spot will be since our current node may be moved + pxfcNext = pxfc->pxfcNext; + + // With each node, check to see if it's element path matches the Id of some other node in the list + pxfcCheck = *ppxfcHead; + while (pxfcCheck) + { + if (pxfc->pwzElementId) + { + if (0 == lstrcmpW(pxfc->pwzElementId, pxfcCheck->wzId) + && 0 == pxfc->iXmlFlags + && XMLCONFIG_CREATE & pxfcCheck->iXmlFlags + && XMLCONFIG_ELEMENT & pxfcCheck->iXmlFlags) + { + // We found a match. First, take it out of the current list + if (pxfc->pxfcPrev) + { + pxfc->pxfcPrev->pxfcNext = pxfc->pxfcNext; + } + else // it was the head. Update the head + { + *ppxfcHead = pxfc->pxfcNext; + } + + if (pxfc->pxfcNext) + { + pxfc->pxfcNext->pxfcPrev = pxfc->pxfcPrev; + } + + pxfc->pxfcNext = NULL; + pxfc->pxfcPrev = NULL; + + // Now, add this node to the end of the matched node's additional changes list + if (!pxfcCheck->pxfcAdditionalChanges) + { + pxfcCheck->pxfcAdditionalChanges = pxfc; + pxfcCheck->cAdditionalChanges = 1; + } + else + { + pxfcLast = pxfcCheck->pxfcAdditionalChanges; + cAdditionalChanges = 1; + while (pxfcLast->pxfcNext) + { + pxfcLast = pxfcLast->pxfcNext; + ++cAdditionalChanges; + } + pxfcLast->pxfcNext = pxfc; + pxfc->pxfcPrev = pxfcLast; + pxfcCheck->cAdditionalChanges = ++cAdditionalChanges; + } + } + else + { + hr = E_NOTFOUND; + ExitOnRootFailure(hr, "failed to find matching ElementId: %ls", pxfc->pwzElementId); + } + } + + pxfcCheck = pxfcCheck->pxfcNext; + } + + pxfc = pxfcNext; + } + +LExit: + + return hr; +} + + +static HRESULT BeginChangeFile( + __in LPCWSTR pwzFile, + __in int iCompAttributes, + __inout LPWSTR* ppwzCustomActionData + ) +{ + Assert(pwzFile && *pwzFile && ppwzCustomActionData); + + HRESULT hr = S_OK; + BOOL fIs64Bit = iCompAttributes & msidbComponentAttributes64bit; + + LPBYTE pbData = NULL; + SIZE_T cbData = 0; + + LPWSTR pwzRollbackCustomActionData = NULL; + + if (fIs64Bit) + { + hr = WcaWriteIntegerToCaData((int)xaOpenFilex64, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write 64-bit file indicator to custom action data"); + } + else + { + hr = WcaWriteIntegerToCaData((int)xaOpenFile, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write file indicator to custom action data"); + } + + hr = WcaWriteStringToCaData(pwzFile, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write file to custom action data: %ls", pwzFile); + + // If the file already exits, then we have to put it back the way it was on failure + if (FileExistsEx(pwzFile, NULL)) + { + hr = FileRead(&pbData, &cbData, pwzFile); + ExitOnFailure(hr, "failed to read file: %ls", pwzFile); + + // Set up the rollback for this file + hr = WcaWriteIntegerToCaData((int)fIs64Bit, &pwzRollbackCustomActionData); + ExitOnFailure(hr, "failed to write component bitness to rollback custom action data"); + + hr = WcaWriteStringToCaData(pwzFile, &pwzRollbackCustomActionData); + ExitOnFailure(hr, "failed to write file name to rollback custom action data: %ls", pwzFile); + + hr = WcaWriteStreamToCaData(pbData, cbData, &pwzRollbackCustomActionData); + ExitOnFailure(hr, "failed to write file contents to rollback custom action data."); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecXmlConfigRollback"), pwzRollbackCustomActionData, COST_XMLFILE); + ExitOnFailure(hr, "failed to schedule ExecXmlConfigRollback for file: %ls", pwzFile); + + ReleaseStr(pwzRollbackCustomActionData); + } +LExit: + ReleaseMem(pbData); + + return hr; +} + + +static HRESULT WriteChangeData( + __in XML_CONFIG_CHANGE* pxfc, + __in eXmlAction action, + __inout LPWSTR* ppwzCustomActionData + ) +{ + Assert(pxfc && ppwzCustomActionData); + + HRESULT hr = S_OK; + XML_CONFIG_CHANGE* pxfcAdditionalChanges = NULL; + LPCWSTR wzElementPath = pxfc->pwzElementId ? pxfc->pwzElementId : pxfc->pwzElementPath; + + hr = WcaWriteStringToCaData(wzElementPath, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write ElementPath to custom action data: %ls", wzElementPath); + + hr = WcaWriteStringToCaData(pxfc->pwzVerifyPath, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write VerifyPath to custom action data: %ls", pxfc->pwzVerifyPath); + + hr = WcaWriteStringToCaData(pxfc->wzName, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write Name to custom action data: %ls", pxfc->wzName); + + hr = WcaWriteStringToCaData(pxfc->pwzValue, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write Value to custom action data: %ls", pxfc->pwzValue); + + if (pxfc->iXmlFlags & XMLCONFIG_CREATE && pxfc->iXmlFlags & XMLCONFIG_ELEMENT && xaCreateElement == action && pxfc->pxfcAdditionalChanges) + { + hr = WcaWriteIntegerToCaData(pxfc->cAdditionalChanges, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write additional changes value to custom action data"); + + pxfcAdditionalChanges = pxfc->pxfcAdditionalChanges; + while (pxfcAdditionalChanges) + { + Assert((0 == lstrcmpW(pxfcAdditionalChanges->wzComponent, pxfc->wzComponent)) && 0 == pxfcAdditionalChanges->iXmlFlags && (0 == lstrcmpW(pxfcAdditionalChanges->wzFile, pxfc->wzFile))); + + hr = WcaWriteStringToCaData(pxfcAdditionalChanges->wzName, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write Name to custom action data: %ls", pxfc->wzName); + + hr = WcaWriteStringToCaData(pxfcAdditionalChanges->pwzValue, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write Value to custom action data: %ls", pxfc->pwzValue); + + pxfcAdditionalChanges = pxfcAdditionalChanges->pxfcNext; + } + } + else + { + hr = WcaWriteIntegerToCaData(0, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write additional changes value to custom action data"); + } + +LExit: + return hr; +} + + +/****************************************************************** + SchedXmlConfig - entry point for XmlConfig Custom Action + +********************************************************************/ +extern "C" UINT __stdcall SchedXmlConfig( + __in MSIHANDLE hInstall + ) +{ +// AssertSz(FALSE, "debug SchedXmlConfig"); + + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + LPWSTR pwzCurrentFile = NULL; + BOOL fCurrentFileChanged = FALSE; + + PMSIHANDLE hView = NULL; + PMSIHANDLE hRec = NULL; + + XML_CONFIG_CHANGE* pxfcHead = NULL; + XML_CONFIG_CHANGE* pxfcTail = NULL; // TODO: do we need this any more? + XML_CONFIG_CHANGE* pxfc = NULL; + + eXmlAction xa = xaUnknown; + eXmlPreserveDate xd; + + LPWSTR pwzCustomActionData = NULL; + + DWORD cFiles = 0; + + // initialize + hr = WcaInitialize(hInstall, "SchedXmlConfig"); + ExitOnFailure(hr, "failed to initialize"); + + hr = ReadXmlConfigTable(&pxfcHead, &pxfcTail); + MessageExitOnFailure(hr, msierrXmlConfigFailedRead, "failed to read Wix4XmlConfig table"); + + hr = ProcessChanges(&pxfcHead); + ExitOnFailure(hr, "failed to process Wix4XmlConfig changes"); + + // loop through all the xml configurations + for (pxfc = pxfcHead; pxfc; pxfc = pxfc->pxfcNext) + { + // If this is a different file, or the first file... + if (NULL == pwzCurrentFile || 0 != lstrcmpW(pwzCurrentFile, pxfc->wzFile)) + { + // Remember the file we're currently working on + hr = StrAllocString(&pwzCurrentFile, pxfc->wzFile, 0); + ExitOnFailure(hr, "failed to copy file name"); + + fCurrentFileChanged = TRUE; + } + + // + // Figure out what action to take + // + xa = xaUnknown; + + // If it's being installed or reinstalled or uninstalled and that matches + // what we are doing then calculate the right action. + if ((XMLCONFIG_INSTALL & pxfc->iXmlFlags && (WcaIsInstalling(pxfc->isInstalled, pxfc->isAction) || WcaIsReInstalling(pxfc->isInstalled, pxfc->isAction))) || + (XMLCONFIG_UNINSTALL & pxfc->iXmlFlags && WcaIsUninstalling(pxfc->isInstalled, pxfc->isAction))) + { + if (XMLCONFIG_CREATE & pxfc->iXmlFlags && XMLCONFIG_ELEMENT & pxfc->iXmlFlags) + { + xa = xaCreateElement; + } + else if (XMLCONFIG_DELETE & pxfc->iXmlFlags && XMLCONFIG_ELEMENT & pxfc->iXmlFlags) + { + xa = xaDeleteElement; + } + else if (XMLCONFIG_DELETE & pxfc->iXmlFlags && XMLCONFIG_VALUE & pxfc->iXmlFlags) + { + xa = xaDeleteValue; + } + else if (XMLCONFIG_CREATE & pxfc->iXmlFlags && XMLCONFIG_VALUE & pxfc->iXmlFlags) + { + xa = xaWriteValue; + } + else if (XMLCONFIG_CREATE & pxfc->iXmlFlags && XMLCONFIG_DOCUMENT & pxfc->iXmlFlags) + { + xa = xaWriteDocument; + } + else if (XMLCONFIG_DELETE & pxfc->iXmlFlags && XMLCONFIG_DOCUMENT & pxfc->iXmlFlags) + { + hr = E_INVALIDARG; + ExitOnFailure(hr, "Invalid flag configuration. Cannot delete a fragment node."); + } + } + + if (XMLCONFIG_PRESERVE_MODIFIED & pxfc->iXmlFlags) + { + xd = xdPreserve; + } + else + { + xd= xdDontPreserve; + } + + if (xaUnknown != xa) + { + if (fCurrentFileChanged) + { + hr = BeginChangeFile(pwzCurrentFile, pxfc->iCompAttributes, &pwzCustomActionData); + ExitOnFailure(hr, "failed to begin file change for file: %ls", pwzCurrentFile); + + fCurrentFileChanged = FALSE; + ++cFiles; + } + + hr = WcaWriteIntegerToCaData((int)xa, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write action indicator custom action data"); + + hr = WcaWriteIntegerToCaData((int)xd, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write Preserve Date indicator to custom action data"); + + hr = WriteChangeData(pxfc, xa, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write change data"); + } + } + + // If we looped through all records all is well + if (E_NOMOREITEMS == hr) + { + hr = S_OK; + } + ExitOnFailure(hr, "failed while looping through all objects to secure"); + + // Schedule the custom action and add to progress bar + if (pwzCustomActionData && *pwzCustomActionData) + { + Assert(0 < cFiles); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecXmlConfig"), pwzCustomActionData, cFiles * COST_XMLFILE); + ExitOnFailure(hr, "failed to schedule ExecXmlConfig action"); + } + +LExit: + ReleaseStr(pwzCurrentFile); + ReleaseStr(pwzCustomActionData); + + FreeXmlConfigChangeList(pxfcHead); + + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + return WcaFinalize(er); +} + + +/****************************************************************** + ExecXmlConfig - entry point for XmlConfig Custom Action + +*******************************************************************/ +extern "C" UINT __stdcall ExecXmlConfig( + __in MSIHANDLE hInstall + ) +{ + //AssertSz(FALSE, "debug ExecXmlConfig"); + HRESULT hr = S_OK; + HRESULT hrOpenFailure = S_OK; + UINT er = ERROR_SUCCESS; + +#ifndef _WIN64 + BOOL fIsFSRedirectDisabled = FALSE; +#endif + BOOL fPreserveDate = FALSE; + + LPWSTR pwzCustomActionData = NULL; + LPWSTR pwzData = NULL; + LPWSTR pwzFile = NULL; + LPWSTR pwzElementPath = NULL; + LPWSTR pwzVerifyPath = NULL; + LPWSTR pwzName = NULL; + LPWSTR pwzValue = NULL; + LPWSTR pwz = NULL; + int cAdditionalChanges = 0; + + IXMLDOMDocument* pixd = NULL; + IXMLDOMNode* pixn = NULL; + IXMLDOMNode* pixnVerify = NULL; + IXMLDOMNode* pixnNewNode = NULL; + IXMLDOMNode* pixnRemovedChild = NULL; + + IXMLDOMDocument* pixdNew = NULL; + IXMLDOMElement* pixeNew = NULL; + + FILETIME ft; + + int id = IDRETRY; + + eXmlAction xa; + eXmlPreserveDate xd; + + // initialize + hr = WcaInitialize(hInstall, "ExecXmlConfig"); + ExitOnFailure(hr, "failed to initialize"); + + hr = XmlInitialize(); + ExitOnFailure(hr, "failed to initialize xml utilities"); + + hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData); + ExitOnFailure(hr, "failed to get CustomActionData"); + + WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); + + pwz = pwzCustomActionData; + + hr = WcaReadIntegerFromCaData(&pwz, (int*) &xa); + ExitOnFailure(hr, "failed to process CustomActionData"); + +#ifndef _WIN64 + // Initialize the Wow64 API - store the result in fWow64APIPresent + // If it fails, this doesn't warrant an error yet, because we only need the Wow64 API in some cases + WcaInitializeWow64(); + BOOL fIsWow64Process = WcaIsWow64Process(); +#endif + + if (xaOpenFile != xa && xaOpenFilex64 != xa) + { + ExitOnFailure(hr = E_INVALIDARG, "invalid custom action data"); + } + + // loop through all the passed in data + while (pwz && *pwz) + { + hr = WcaReadStringFromCaData(&pwz, &pwzFile); + ExitOnFailure(hr, "failed to read file name from custom action data"); + + // Default to not preserve date, preserve it if any modifications require us to + fPreserveDate = FALSE; + + // Open the file + ReleaseNullObject(pixd); + +#ifndef _WIN64 + if (xaOpenFilex64 == xa) + { + if (!fIsWow64Process) + { + hr = E_NOTIMPL; + ExitOnFailure(hr, "Custom action was told to act on a 64-bit component, but the custom action process is not running in WOW."); + } + + hr = WcaDisableWow64FSRedirection(); + ExitOnFailure(hr, "Custom action was told to act on a 64-bit component, but was unable to disable filesystem redirection through the Wow64 API."); + + fIsFSRedirectDisabled = TRUE; + } +#endif + + hr = XmlLoadDocumentFromFileEx(pwzFile, XML_LOAD_PRESERVE_WHITESPACE, &pixd); + if (FAILED(hr)) + { + // Ignore the return code for now. If they try to add something, we'll fail the install. If all they do is remove stuff then it doesn't matter. + hrOpenFailure = hr; + hr = S_OK; + } + else + { + hrOpenFailure = S_OK; + } + + WcaLog(LOGMSG_VERBOSE, "Configuring Xml File: %ls", pwzFile); + + while (pwz && *pwz) + { + // If we skip past an element that has additional changes we need to strip them off the stream before + // moving on to the next element. Do that now and then restart the outer loop. + if (cAdditionalChanges > 0) + { + while (cAdditionalChanges > 0) + { + hr = WcaReadStringFromCaData(&pwz, &pwzName); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzValue); + ExitOnFailure(hr, "failed to process CustomActionData"); + + cAdditionalChanges--; + } + continue; + } + + hr = WcaReadIntegerFromCaData(&pwz, (int*) &xa); + ExitOnFailure(hr, "failed to process CustomActionData"); + + // Break if we need to move on to a different file + if (xaOpenFile == xa || xaOpenFilex64 == xa) + { + break; + } + + hr = WcaReadIntegerFromCaData(&pwz, (int*) &xd); + ExitOnFailure(hr, "failed to process CustomActionData"); + + if (xdPreserve == xd) + { + fPreserveDate = TRUE; + } + + // Get path, name, and value to be written + hr = WcaReadStringFromCaData(&pwz, &pwzElementPath); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzVerifyPath); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzName); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzValue); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadIntegerFromCaData(&pwz, &cAdditionalChanges); + ExitOnFailure(hr, "failed to process CustomActionData"); + + // If we failed to open the file and we're adding something to the file, we've got a problem. Otherwise, just continue on since the file's already gone. + if (FAILED(hrOpenFailure)) + { + if (xaCreateElement == xa || xaWriteValue == xa || xaWriteDocument == xa) + { + MessageExitOnFailure(hr = hrOpenFailure, msierrXmlConfigFailedOpen, "failed to load XML file: %ls", pwzFile); + } + else + { + continue; + } + } + + // Select the node we're about to modify + ReleaseNullObject(pixn); + + hr = XmlSelectSingleNode(pixd, pwzElementPath, &pixn); + + // If we failed to find the node that we are going to add to, we've got a problem. Otherwise, just continue since the node's already gone. + if (S_FALSE == hr) + { + if (xaCreateElement == xa || xaWriteValue == xa || xaWriteDocument == xa) + { + hr = HRESULT_FROM_WIN32(ERROR_OBJECT_NOT_FOUND); + } + else + { + hr = S_OK; + continue; + } + } + + MessageExitOnFailure(hr, msierrXmlConfigFailedSelect, "failed to find node: %ls in XML file: %ls", pwzElementPath, pwzFile); + + // Make the modification + switch (xa) + { + case xaWriteValue: + if (pwzName && *pwzName) + { + // We're setting an attribute + hr = XmlSetAttribute(pixn, pwzName, pwzValue); + ExitOnFailure(hr, "failed to set attribute: %ls to value %ls", pwzName, pwzValue); + } + else + { + // We're setting the text of the node + hr = XmlSetText(pixn, pwzValue); + ExitOnFailure(hr, "failed to set text to: %ls for element %ls. Make sure that XPath points to an element.", pwzValue, pwzElementPath); + } + break; + case xaWriteDocument: + if (NULL != pwzVerifyPath && 0 != pwzVerifyPath[0]) + { + hr = XmlSelectSingleNode(pixn, pwzVerifyPath, &pixnVerify); + if (S_OK == hr) + { + // We found the verify path which means we have no further work to do + continue; + } + ExitOnFailure(hr, "failed to query verify path: %ls", pwzVerifyPath); + } + + hr = XmlLoadDocumentEx(pwzValue, XML_LOAD_PRESERVE_WHITESPACE, &pixdNew); + ExitOnFailure(hr, "Failed to load value as document."); + + hr = pixdNew->get_documentElement(&pixeNew); + ExitOnFailure(hr, "Failed to get document element."); + + hr = pixn->appendChild(pixeNew, NULL); + ExitOnFailure(hr, "Failed to append document element on to parent element."); + + ReleaseNullObject(pixeNew); + ReleaseNullObject(pixdNew); + break; + + case xaCreateElement: + if (NULL != pwzVerifyPath && 0 != pwzVerifyPath[0]) + { + hr = XmlSelectSingleNode(pixn, pwzVerifyPath, &pixnVerify); + if (S_OK == hr) + { + // We found the verify path which means we have no further work to do + continue; + } + ExitOnFailure(hr, "failed to query verify path: %ls", pwzVerifyPath); + } + + hr = XmlCreateChild(pixn, pwzName, &pixnNewNode); + ExitOnFailure(hr, "failed to create child element: %ls", pwzName); + + if (pwzValue && *pwzValue) + { + hr = XmlSetText(pixnNewNode, pwzValue); + ExitOnFailure(hr, "failed to set text to: %ls for node: %ls", pwzValue, pwzName); + } + + while (cAdditionalChanges > 0) + { + hr = WcaReadStringFromCaData(&pwz, &pwzName); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzValue); + ExitOnFailure(hr, "failed to process CustomActionData"); + + // Set the additional attribute + hr = XmlSetAttribute(pixnNewNode, pwzName, pwzValue); + ExitOnFailure(hr, "failed to set attribute: %ls to value %ls", pwzName, pwzValue); + + cAdditionalChanges--; + } + + ReleaseNullObject(pixnNewNode); + break; + case xaDeleteValue: + if (pwzName && *pwzName) + { + // Delete the attribute + hr = XmlRemoveAttribute(pixn, pwzName); + ExitOnFailure(hr, "failed to remove attribute: %ls", pwzName); + } + else + { + // Clear the text value for the node + hr = XmlSetText(pixn, L""); + ExitOnFailure(hr, "failed to clear text value"); + } + break; + case xaDeleteElement: + if (NULL != pwzVerifyPath && 0 != pwzVerifyPath[0]) + { + hr = XmlSelectSingleNode(pixn, pwzVerifyPath, &pixnVerify); + if (S_OK == hr) + { + hr = pixn->removeChild(pixnVerify, &pixnRemovedChild); + ExitOnFailure(hr, "failed to remove created child element"); + + ReleaseNullObject(pixnRemovedChild); + } + else + { + WcaLog(LOGMSG_VERBOSE, "Failed to select path %ls for deleting. Skipping...", pwzVerifyPath); + hr = S_OK; + } + } + else + { + // TODO: This requires a VerifyPath to delete an element. Should we support not having one? + WcaLog(LOGMSG_VERBOSE, "No VerifyPath specified for delete element of ID: %ls", pwzElementPath); + } + break; + default: + ExitOnFailure(hr = E_UNEXPECTED, "Invalid modification specified in custom action data"); + break; + } + } + + + // Now that we've made all of the changes to this file, save it and move on to the next + if (S_OK == hrOpenFailure) + { + if (fPreserveDate) + { + hr = FileGetTime(pwzFile, NULL, NULL, &ft); + ExitOnFailure(hr, "failed to get modified time of file : %ls", pwzFile); + } + + int iSaveAttempt = 0; + + do + { + hr = XmlSaveDocument(pixd, pwzFile); + if (FAILED(hr)) + { + id = WcaErrorMessage(msierrXmlConfigFailedSave, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 1, pwzFile); + switch (id) + { + case IDABORT: + ExitOnFailure(hr, "Failed to save changes to XML file: %ls", pwzFile); + case IDRETRY: + hr = S_FALSE; // hit me, baby, one more time + break; + case IDIGNORE: + hr = S_OK; // pretend everything is okay and bail + break; + case 0: // No UI case, MsiProcessMessage returns 0 + if (STIERR_SHARING_VIOLATION == hr) + { + // Only in case of sharing violation do we retry 30 times, once a second. + if (iSaveAttempt < 30) + { + hr = S_FALSE; + ++iSaveAttempt; + WcaLog(LOGMSG_VERBOSE, "Unable to save changes to XML file: %ls, retry attempt: %x", pwzFile, iSaveAttempt); + Sleep(1000); + } + else + { + ExitOnFailure(hr, "Failed to save changes to XML file: %ls", pwzFile); + } + } + break; + default: // Unknown error + ExitOnFailure(hr, "Failed to save changes to XML file: %ls", pwzFile); + } + } + } while (S_FALSE == hr); + + if (fPreserveDate) + { + hr = FileSetTime(pwzFile, NULL, NULL, &ft); + ExitOnFailure(hr, "failed to set modified time of file : %ls", pwzFile); + } + +#ifndef _WIN64 + if (fIsFSRedirectDisabled) + { + fIsFSRedirectDisabled = FALSE; + WcaRevertWow64FSRedirection(); + } +#endif + } + } + +LExit: +#ifndef _WIN64 + // Make sure we revert FS Redirection if necessary before exiting + if (fIsFSRedirectDisabled) + { + fIsFSRedirectDisabled = FALSE; + WcaRevertWow64FSRedirection(); + } + WcaFinalizeWow64(); +#endif + + ReleaseStr(pwzCustomActionData); + ReleaseStr(pwzData); + ReleaseStr(pwzFile); + ReleaseStr(pwzElementPath); + ReleaseStr(pwzVerifyPath); + ReleaseStr(pwzName); + ReleaseStr(pwzValue); + + ReleaseObject(pixeNew); + ReleaseObject(pixdNew); + + ReleaseObject(pixn); + ReleaseObject(pixd); + ReleaseObject(pixnNewNode); + ReleaseObject(pixnRemovedChild); + + XmlUninitialize(); + + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + return WcaFinalize(er); +} + + +/****************************************************************** + ExecXmlConfigRollback - entry point for XmlConfig rollback Custom Action + +*******************************************************************/ +extern "C" UINT __stdcall ExecXmlConfigRollback( + __in MSIHANDLE hInstall + ) +{ +// AssertSz(FALSE, "debug ExecXmlConfigRollback"); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + int iIs64Bit; +#ifndef _WIN64 + BOOL fIs64Bit = FALSE; +#endif + + LPWSTR pwzCustomActionData = NULL; + LPWSTR pwz = NULL; + LPWSTR pwzFileName = NULL; + LPBYTE pbData = NULL; + DWORD_PTR cbData = 0; + + FILETIME ft; + + HANDLE hFile = INVALID_HANDLE_VALUE; + + // initialize + hr = WcaInitialize(hInstall, "ExecXmlConfigRollback"); + ExitOnFailure(hr, "failed to initialize"); + + + hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData); + ExitOnFailure(hr, "failed to get CustomActionData"); + + WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); + + pwz = pwzCustomActionData; + + hr = WcaReadIntegerFromCaData(&pwz, &iIs64Bit); + ExitOnFailure(hr, "failed to read component bitness from custom action data"); + + hr = WcaReadStringFromCaData(&pwz, &pwzFileName); + ExitOnFailure(hr, "failed to read file name from custom action data"); + + hr = WcaReadStreamFromCaData(&pwz, &pbData, &cbData); + ExitOnFailure(hr, "failed to read file contents from custom action data"); + +#ifndef _WIN64 + fIs64Bit = (BOOL)iIs64Bit; + + if (fIs64Bit) + { + hr = WcaInitializeWow64(); + if (S_FALSE == hr) + { + hr = TYPE_E_DLLFUNCTIONNOTFOUND; + } + ExitOnFailure(hr, "failed to initialize Wow64 API"); + + if (!WcaIsWow64Process()) + { + hr = E_NOTIMPL; + ExitOnFailure(hr, "Custom action was told to rollback a 64-bit component, but the Wow64 API is unavailable."); + } + + hr = WcaDisableWow64FSRedirection(); + ExitOnFailure(hr, "Custom action was told to rollback a 64-bit component, but was unable to Disable Filesystem Redirection through the Wow64 API."); + } +#endif + + hr = FileGetTime(pwzFileName, NULL, NULL, &ft); + ExitOnFailure(hr, "Failed to get modified date of file %ls.", pwzFileName); + + // Open the file + hFile = ::CreateFileW(pwzFileName, GENERIC_WRITE, NULL, NULL, TRUNCATE_EXISTING, NULL, NULL); + ExitOnInvalidHandleWithLastError(hFile, hr, "failed to open file: %ls", pwzFileName); + + // Write out the old data + hr = FileWriteHandle(hFile, pbData, cbData); + ExitOnFailure(hr, "failed to write to file: %ls", pwzFileName); + + ReleaseFile(hFile); + + hr = FileSetTime(pwzFileName, NULL, NULL, &ft); + ExitOnFailure(hr, "Failed to set modified date of file %ls.", pwzFileName); + +LExit: + ReleaseStr(pwzCustomActionData); + ReleaseStr(pwzFileName); + + ReleaseFile(hFile); + +#ifndef _WIN64 + if (fIs64Bit) + { + WcaRevertWow64FSRedirection(); + WcaFinalizeWow64(); + } +#endif + + ReleaseMem(pbData); + + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + return WcaFinalize(er); +} diff --git a/src/ext/Util/ca/XmlFile.cpp b/src/ext/Util/ca/XmlFile.cpp new file mode 100644 index 00000000..04a4ae98 --- /dev/null +++ b/src/ext/Util/ca/XmlFile.cpp @@ -0,0 +1,940 @@ +// Copyright (c) .NET 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 XMLFILE_CREATE_ELEMENT 0x00000001 +#define XMLFILE_DELETE_VALUE 0x00000002 +#define XMLFILE_BULKWRITE_VALUE 0x00000004 + +#define XMLFILE_DONT_UNINSTALL 0x00010000 +#define XMLFILE_PRESERVE_MODIFIED 0x00001000 +#define XMLFILE_USE_XPATH 0x00000100 + +extern BOOL vfMsxml30; + +enum eXmlAction +{ + xaOpenFile = 1, + xaOpenFilex64, + xaWriteValue, + xaDeleteValue, + xaCreateElement, + xaDeleteElement, + xaBulkWriteValue, +}; + +enum eXmlPreserveDate +{ + xdDontPreserve = 0, + xdPreserve +}; + +enum eXmlSelectionLanguage +{ + xsXSLPattern = 0, + xsXPath = 1, +}; + +LPCWSTR vcsXmlFileQuery = + L"SELECT `Wix4XmlFile`.`Wix4XmlFile`, `Wix4XmlFile`.`File`, `Wix4XmlFile`.`ElementPath`, `Wix4XmlFile`.`Name`, `Wix4XmlFile`.`Value`, " + L"`Wix4XmlFile`.`Flags`, `Wix4XmlFile`.`Component_`, `Component`.`Attributes` " + L"FROM `Wix4XmlFile`,`Component` WHERE `Wix4XmlFile`.`Component_`=`Component`.`Component` ORDER BY `File`, `Sequence`"; +enum eXmlFileQuery { xfqXmlFile = 1, xfqFile, xfqXPath, xfqName, xfqValue, xfqXmlFlags, xfqComponent, xfqCompAttributes }; + +struct XML_FILE_CHANGE +{ + WCHAR wzId[MAX_DARWIN_KEY]; + + INSTALLSTATE isInstalled; + INSTALLSTATE isAction; + + WCHAR wzFile[MAX_PATH]; + LPWSTR pwzElementPath; + WCHAR wzName[MAX_DARWIN_COLUMN]; + LPWSTR pwzValue; + + int iXmlFlags; + int iCompAttributes; + + XML_FILE_CHANGE* pxfcPrev; + XML_FILE_CHANGE* pxfcNext; +}; + +//static HRESULT FreeXmlFileChangeList( +// __in XML_FILE_CHANGE* pxfcList +// ) +//{ +// HRESULT hr = S_OK; +// +// XML_FILE_CHANGE* pxfcDelete; +// while(pxfcList) +// { +// pxfcDelete = pxfcList; +// pxfcList = pxfcList->pxfcNext; +// +// ReleaseStr(pxfcDelete->pwzElementPath); +// ReleaseStr(pxfcDelete->pwzValue); +// +// hr = MemFree(pxfcDelete); +// ExitOnFailure(hr, "failed to free xml file change list item"); +// } +// +//LExit: +// return hr; +//} + +static HRESULT AddXmlFileChangeToList( + __inout XML_FILE_CHANGE** ppxfcHead, + __inout XML_FILE_CHANGE** ppxfcTail + ) +{ + Assert(ppxfcHead && ppxfcTail); + + HRESULT hr = S_OK; + + XML_FILE_CHANGE* pxfc = static_cast(MemAlloc(sizeof(XML_FILE_CHANGE), TRUE)); + ExitOnNull(pxfc, hr, E_OUTOFMEMORY, "failed to allocate memory for new xml file change list element"); + + // Add it to the end of the list + if (NULL == *ppxfcHead) + { + *ppxfcHead = pxfc; + *ppxfcTail = pxfc; + } + else + { + Assert(*ppxfcTail && (*ppxfcTail)->pxfcNext == NULL); + (*ppxfcTail)->pxfcNext = pxfc; + pxfc->pxfcPrev = *ppxfcTail; + *ppxfcTail = pxfc; + } + +LExit: + return hr; +} + + +static HRESULT ReadXmlFileTable( + __inout XML_FILE_CHANGE** ppxfcHead, + __inout XML_FILE_CHANGE** ppxfcTail + ) +{ + Assert(ppxfcHead && ppxfcTail); + + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + PMSIHANDLE hView = NULL; + PMSIHANDLE hRec = NULL; + + LPWSTR pwzData = NULL; + + // check to see if necessary tables are specified + if (S_FALSE == WcaTableExists(L"Wix4XmlFile")) + { + ExitFunction1(hr = S_FALSE); + } + + // loop through all the xml configurations + hr = WcaOpenExecuteView(vcsXmlFileQuery, &hView); + ExitOnFailure(hr, "failed to open view on Wix4XmlFile table"); + + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + hr = AddXmlFileChangeToList(ppxfcHead, ppxfcTail); + ExitOnFailure(hr, "failed to add xml file change to list"); + + // Get record Id + hr = WcaGetRecordString(hRec, xfqXmlFile, &pwzData); + ExitOnFailure(hr, "failed to get Wix4XmlFile record Id"); + hr = StringCchCopyW((*ppxfcTail)->wzId, countof((*ppxfcTail)->wzId), pwzData); + ExitOnFailure(hr, "failed to copy Wix4XmlFile record Id"); + + // Get component name + hr = WcaGetRecordString(hRec, xfqComponent, &pwzData); + ExitOnFailure(hr, "failed to get component name for Wix4XmlFile: %ls", (*ppxfcTail)->wzId); + + // Get the component's state + er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &(*ppxfcTail)->isInstalled, &(*ppxfcTail)->isAction); + ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "failed to get install state for Component: %ls", pwzData); + + // Get the xml file + hr = WcaGetRecordFormattedString(hRec, xfqFile, &pwzData); + ExitOnFailure(hr, "failed to get xml file for Wix4XmlFile: %ls", (*ppxfcTail)->wzId); + hr = StringCchCopyW((*ppxfcTail)->wzFile, countof((*ppxfcTail)->wzFile), pwzData); + ExitOnFailure(hr, "failed to copy xml file path"); + + // Get the Wix4XmlFile table flags + hr = WcaGetRecordInteger(hRec, xfqXmlFlags, &(*ppxfcTail)->iXmlFlags); + ExitOnFailure(hr, "failed to get Wix4XmlFile flags for Wix4XmlFile: %ls", (*ppxfcTail)->wzId); + + // Get the XPath + hr = WcaGetRecordFormattedString(hRec, xfqXPath, &(*ppxfcTail)->pwzElementPath); + ExitOnFailure(hr, "failed to get XPath for Wix4XmlFile: %ls", (*ppxfcTail)->wzId); + + // Get the name + hr = WcaGetRecordFormattedString(hRec, xfqName, &pwzData); + ExitOnFailure(hr, "failed to get Name for Wix4XmlFile: %ls", (*ppxfcTail)->wzId); + hr = StringCchCopyW((*ppxfcTail)->wzName, countof((*ppxfcTail)->wzName), pwzData); + ExitOnFailure(hr, "failed to copy name of element"); + + // Get the value + hr = WcaGetRecordFormattedString(hRec, xfqValue, &pwzData); + ExitOnFailure(hr, "failed to get Value for Wix4XmlFile: %ls", (*ppxfcTail)->wzId); + hr = StrAllocString(&(*ppxfcTail)->pwzValue, pwzData, 0); + ExitOnFailure(hr, "failed to allocate buffer for value"); + + // Get the component attributes + hr = WcaGetRecordInteger(hRec, xfqCompAttributes, &(*ppxfcTail)->iCompAttributes); + ExitOnFailure(hr, "failed to get component attributes for Wix4XmlFile: %ls", (*ppxfcTail)->wzId); + } + + // if we looped through all records all is well + if (E_NOMOREITEMS == hr) + hr = S_OK; + ExitOnFailure(hr, "failed while looping through all objects to secure"); + +LExit: + ReleaseStr(pwzData); + + return hr; +} + + +static HRESULT BeginChangeFile( + __in LPCWSTR pwzFile, + __in XML_FILE_CHANGE* pxfc, + __inout LPWSTR* ppwzCustomActionData + ) +{ + Assert(pwzFile && *pwzFile && ppwzCustomActionData); + + HRESULT hr = S_OK; + BOOL fIs64Bit = pxfc->iCompAttributes & msidbComponentAttributes64bit; + BOOL fUseXPath = pxfc->iXmlFlags & XMLFILE_USE_XPATH; + LPBYTE pbData = NULL; + SIZE_T cbData = 0; + + LPWSTR pwzRollbackCustomActionData = NULL; + + if (fIs64Bit) + { + hr = WcaWriteIntegerToCaData((int)xaOpenFilex64, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write 64-bit file indicator to custom action data"); + } + else + { + hr = WcaWriteIntegerToCaData((int)xaOpenFile, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write file indicator to custom action data"); + } + if (fUseXPath) + { + hr = WcaWriteIntegerToCaData((int)xsXPath, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write XPath selectionlanguage indicator to custom action data"); + } + else + { + hr = WcaWriteIntegerToCaData((int)xsXSLPattern, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write XSLPattern selectionlanguage indicator to custom action data"); + } + hr = WcaWriteStringToCaData(pwzFile, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write file to custom action data: %ls", pwzFile); + + // If the file already exits, then we have to put it back the way it was on failure + if (FileExistsEx(pwzFile, NULL)) + { + hr = FileRead(&pbData, &cbData, pwzFile); + ExitOnFailure(hr, "failed to read file: %ls", pwzFile); + + // Set up the rollback for this file + hr = WcaWriteIntegerToCaData((int)fIs64Bit, &pwzRollbackCustomActionData); + ExitOnFailure(hr, "failed to write component bitness to rollback custom action data"); + + hr = WcaWriteStringToCaData(pwzFile, &pwzRollbackCustomActionData); + ExitOnFailure(hr, "failed to write file name to rollback custom action data: %ls", pwzFile); + + hr = WcaWriteStreamToCaData(pbData, cbData, &pwzRollbackCustomActionData); + ExitOnFailure(hr, "failed to write file contents to rollback custom action data."); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecXmlFileRollback"), pwzRollbackCustomActionData, COST_XMLFILE); + ExitOnFailure(hr, "failed to schedule ExecXmlFileRollback for file: %ls", pwzFile); + + ReleaseStr(pwzRollbackCustomActionData); + } +LExit: + ReleaseMem(pbData); + + return hr; +} + + +static HRESULT WriteChangeData( + __in XML_FILE_CHANGE* pxfc, + __inout LPWSTR* ppwzCustomActionData + ) +{ + Assert(pxfc && ppwzCustomActionData); + + HRESULT hr = S_OK; + + hr = WcaWriteStringToCaData(pxfc->pwzElementPath, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write ElementPath to custom action data: %ls", pxfc->pwzElementPath); + + hr = WcaWriteStringToCaData(pxfc->wzName, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write Name to custom action data: %ls", pxfc->wzName); + + hr = WcaWriteStringToCaData(pxfc->pwzValue, ppwzCustomActionData); + ExitOnFailure(hr, "failed to write Value to custom action data: %ls", pxfc->pwzValue); + +LExit: + return hr; +} + + +/****************************************************************** + SchedXmlFile - entry point for XmlFile Custom Action + +********************************************************************/ +extern "C" UINT __stdcall SchedXmlFile( + __in MSIHANDLE hInstall + ) +{ +// AssertSz(FALSE, "debug SchedXmlFile"); + + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + LPWSTR pwzCurrentFile = NULL; + BOOL fCurrentFileChanged = FALSE; + BOOL fCurrentUseXPath = FALSE; + + PMSIHANDLE hView = NULL; + PMSIHANDLE hRec = NULL; + + XML_FILE_CHANGE* pxfcHead = NULL; + XML_FILE_CHANGE* pxfcTail = NULL; + XML_FILE_CHANGE* pxfc = NULL; + XML_FILE_CHANGE* pxfcUninstall = NULL; + + LPWSTR pwzCustomActionData = NULL; + + DWORD cFiles = 0; + + // initialize + hr = WcaInitialize(hInstall, "SchedXmlFile"); + ExitOnFailure(hr, "failed to initialize"); + + hr = ReadXmlFileTable(&pxfcHead, &pxfcTail); + if (S_FALSE == hr) + { + WcaLog(LOGMSG_VERBOSE, "Skipping SchedXmlFile because Wix4XmlFile table not present"); + ExitFunction1(hr = S_OK); + } + + MessageExitOnFailure(hr, msierrXmlFileFailedRead, "failed to read Wix4XmlFile table"); + + // loop through all the xml configurations + for (pxfc = pxfcHead; pxfc; pxfc = pxfc->pxfcNext) + { + // If this is the first file, a different file, the last file, or the SelectionLanguage property changes... + if (NULL == pwzCurrentFile || 0 != lstrcmpW(pwzCurrentFile, pxfc->wzFile) || NULL == pxfc->pxfcNext || fCurrentUseXPath != ((XMLFILE_USE_XPATH & pxfc->iXmlFlags))) + { + // If this isn't the first file + if (NULL != pwzCurrentFile) + { + // Do the uninstall work for the current file by walking backwards through the list (so the sequence is reversed) + for (pxfcUninstall = ((NULL != pxfc->pxfcNext) ? pxfc->pxfcPrev : pxfc); pxfcUninstall && 0 == lstrcmpW(pwzCurrentFile, pxfcUninstall->wzFile) && fCurrentUseXPath == ((XMLFILE_USE_XPATH & pxfcUninstall->iXmlFlags)); pxfcUninstall = pxfcUninstall->pxfcPrev) + { + // If it's being uninstalled + if (WcaIsUninstalling(pxfcUninstall->isInstalled, pxfcUninstall->isAction)) + { + // Uninstall the change + if (!(XMLFILE_DONT_UNINSTALL & pxfcUninstall->iXmlFlags)) + { + if (!fCurrentFileChanged) + { + hr = BeginChangeFile(pwzCurrentFile, pxfcUninstall, &pwzCustomActionData); + ExitOnFailure(hr, "failed to begin file change for file: %ls", pwzCurrentFile); + + fCurrentFileChanged = TRUE; + ++cFiles; + } + if (XMLFILE_CREATE_ELEMENT & pxfcUninstall->iXmlFlags) + { + hr = WcaWriteIntegerToCaData((int)xaDeleteElement, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write delete element action indicator to custom action data"); + } + else + { + hr = WcaWriteIntegerToCaData((int)xaDeleteValue, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write delete value action indicator to custom action data"); + } + + if (XMLFILE_PRESERVE_MODIFIED & pxfc->iXmlFlags) + { + hr = WcaWriteIntegerToCaData((int)xdPreserve, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write Preserve Date indicator to custom action data"); + } + else + { + hr = WcaWriteIntegerToCaData((int)xdDontPreserve, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write Don't Preserve Date indicator to custom action data"); + } + + hr = WriteChangeData(pxfcUninstall, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write uninstall change data"); + } + } + } + } + + // Remember the file we're currently working on + hr = StrAllocString(&pwzCurrentFile, pxfc->wzFile, 0); + ExitOnFailure(hr, "failed to copy file name"); + fCurrentUseXPath = (XMLFILE_USE_XPATH & pxfc->iXmlFlags); + + // We haven't changed the current file yet + fCurrentFileChanged = FALSE; + } + + // If it's being installed + if (WcaIsInstalling(pxfc->isInstalled, pxfc->isAction)) + { + if (!fCurrentFileChanged) + { + hr = BeginChangeFile(pwzCurrentFile, pxfc, &pwzCustomActionData); + ExitOnFailure(hr, "failed to begin file change for file: %ls", pwzCurrentFile); + fCurrentFileChanged = TRUE; + ++cFiles; + } + + // Install the change + if (XMLFILE_CREATE_ELEMENT & pxfc->iXmlFlags) + { + hr = WcaWriteIntegerToCaData((int)xaCreateElement, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write create element action indicator to custom action data"); + } + else if (XMLFILE_DELETE_VALUE & pxfc->iXmlFlags) + { + hr = WcaWriteIntegerToCaData((int)xaDeleteValue, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write delete value action indicator to custom action data"); + } + else if (XMLFILE_BULKWRITE_VALUE & pxfc->iXmlFlags) + { + hr = WcaWriteIntegerToCaData((int)xaBulkWriteValue, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write builkwrite value action indicator to custom action data"); + } + else + { + hr = WcaWriteIntegerToCaData((int)xaWriteValue, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write file indicator to custom action data"); + } + + if (XMLFILE_PRESERVE_MODIFIED & pxfc->iXmlFlags) + { + hr = WcaWriteIntegerToCaData((int)xdPreserve, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write Preserve Date indicator to custom action data"); + } + else + { + hr = WcaWriteIntegerToCaData((int)xdDontPreserve, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write Don't Preserve Date indicator to custom action data"); + } + + hr = WriteChangeData(pxfc, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write change data"); + } + } + + // If we looped through all records all is well + if (E_NOMOREITEMS == hr) + hr = S_OK; + ExitOnFailure(hr, "failed while looping through all objects to secure"); + + // Schedule the custom action and add to progress bar + if (pwzCustomActionData && *pwzCustomActionData) + { + Assert(0 < cFiles); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecXmlFile"), pwzCustomActionData, cFiles * COST_XMLFILE); + ExitOnFailure(hr, "failed to schedule ExecXmlFile action"); + } + +LExit: + ReleaseStr(pwzCurrentFile); + ReleaseStr(pwzCustomActionData); + + return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : er); +} + + +/****************************************************************** + ExecXmlFile - entry point for XmlFile Custom Action + +*******************************************************************/ +extern "C" UINT __stdcall ExecXmlFile( + __in MSIHANDLE hInstall + ) +{ +// AssertSz(FALSE, "debug ExecXmlFile"); + HRESULT hr = S_OK; + HRESULT hrOpenFailure = S_OK; + UINT er = ERROR_SUCCESS; + + BOOL fIsFSRedirectDisabled = FALSE; + BOOL fPreserveDate = FALSE; + + int id = IDRETRY; + + LPWSTR pwzCustomActionData = NULL; + LPWSTR pwzData = NULL; + LPWSTR pwzFile = NULL; + LPWSTR pwzXPath = NULL; + LPWSTR pwzName = NULL; + LPWSTR pwzValue = NULL; + LPWSTR pwz = NULL; + + IXMLDOMDocument* pixd = NULL; + IXMLDOMNode* pixn = NULL; + IXMLDOMNode* pixnNewNode = NULL; + IXMLDOMNodeList* pixNodes = NULL; + IXMLDOMDocument2 *pixdDocument2 = NULL; + + FILETIME ft; + + BSTR bstrProperty = ::SysAllocString(L"SelectionLanguage"); + ExitOnNull(bstrProperty, hr, E_OUTOFMEMORY, "failed SysAllocString"); + VARIANT varValue; + ::VariantInit(&varValue); + varValue.vt = VT_BSTR; + varValue.bstrVal = ::SysAllocString(L"XPath"); + ExitOnNull(varValue.bstrVal, hr, E_OUTOFMEMORY, "failed SysAllocString"); + eXmlAction xa; + eXmlPreserveDate xd; + eXmlSelectionLanguage xl; + + // initialize + hr = WcaInitialize(hInstall, "ExecXmlFile"); + ExitOnFailure(hr, "failed to initialize"); + + hr = XmlInitialize(); + ExitOnFailure(hr, "failed to initialize xml utilities"); + + hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData); + ExitOnFailure(hr, "failed to get CustomActionData"); + + WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); + + pwz = pwzCustomActionData; + + hr = WcaReadIntegerFromCaData(&pwz, (int*) &xa); + ExitOnFailure(hr, "failed to process CustomActionData"); + +#ifndef _WIN64 + // Initialize the Wow64 API - store the result in fWow64APIPresent + // If it fails, this doesn't warrant an error yet, because we only need the Wow64 API in some cases + WcaInitializeWow64(); + BOOL fIsWow64Process = WcaIsWow64Process(); +#endif + + if (xaOpenFile != xa && xaOpenFilex64 != xa) + ExitOnFailure(hr = E_INVALIDARG, "invalid custom action data"); + + // loop through all the passed in data + while (pwz && *pwz) + { + hr = WcaReadIntegerFromCaData(&pwz, (int*) &xl); + ExitOnFailure(hr, "failed to process CustomActionData"); + + hr = WcaReadStringFromCaData(&pwz, &pwzFile); + ExitOnFailure(hr, "failed to read file name from custom action data"); + + // Default to not preserve the modified date + fPreserveDate = FALSE; + + // Open the file + ReleaseNullObject(pixd); + + if (xaOpenFilex64 == xa) + { +#ifndef _WIN64 + if (!fIsWow64Process) + { + hr = E_NOTIMPL; + ExitOnFailure(hr, "Custom action was told to act on a 64-bit component, but the custom action process is not running in WOW."); + } + + hr = WcaDisableWow64FSRedirection(); + ExitOnFailure(hr, "Custom action was told to act on a 64-bit component, but was unable to disable filesystem redirection through the Wow64 API."); + + fIsFSRedirectDisabled = TRUE; +#endif + } + + hr = XmlLoadDocumentFromFileEx(pwzFile, XML_LOAD_PRESERVE_WHITESPACE, &pixd); + if (FAILED(hr)) + { + // Ignore the return code for now. If they try to add something, we'll fail the install. If all they do is remove stuff then it doesn't matter. + hrOpenFailure = hr; + hr = S_OK; + } + else + { + hrOpenFailure = S_OK; + } + WcaLog(LOGMSG_VERBOSE, "Configuring Xml File: %ls", pwzFile); + + if (xsXPath == xl) + { + if (vfMsxml30) + { + // If we failed to open the file, don't fail immediately; just skip setting the selection language, and we'll fail later if appropriate + if (SUCCEEDED(hrOpenFailure)) + { + hr = pixd->QueryInterface(XmlUtil_IID_IXMLDOMDocument2, (void**)&pixdDocument2); + ExitOnFailure(hr, "failed in querying IXMLDOMDocument2 interface"); + hr = pixdDocument2->setProperty(bstrProperty, varValue); + ExitOnFailure(hr, "failed in setting SelectionLanguage"); + } + } + else + { + ExitOnFailure(hr = E_NOTIMPL, "Error: current MSXML version does not support xpath query."); + } + } + + while (pwz && *pwz) + { + hr = WcaReadIntegerFromCaData(&pwz, (int*) &xa); + ExitOnFailure(hr, "failed to process CustomActionData"); + + // Break if we need to move on to a different file + if (xaOpenFile == xa || xaOpenFilex64 == xa) + break; + + hr = WcaReadIntegerFromCaData(&pwz, (int*) &xd); + ExitOnFailure(hr, "failed to process CustomActionData"); + + if (xdPreserve == xd) + { + fPreserveDate = TRUE; + } + + // Get path, name, and value to be written + hr = WcaReadStringFromCaData(&pwz, &pwzXPath); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzName); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzValue); + ExitOnFailure(hr, "failed to process CustomActionData"); + + // If we failed to open the file and we're adding something to the file, we've got a problem. Otherwise, just continue on since the file's already gone. + if (FAILED(hrOpenFailure)) + { + if (xaCreateElement == xa || xaWriteValue == xa || xaBulkWriteValue == xa) + { + MessageExitOnFailure(hr = hrOpenFailure, msierrXmlFileFailedOpen, "failed to load XML file: %ls", pwzFile); + } + else + { + continue; + } + } + + // Select the node we're about to modify + ReleaseNullObject(pixn); + + if (xaBulkWriteValue == xa) + { + hr = XmlSelectNodes(pixd, pwzXPath, &pixNodes); + if (S_FALSE == hr) + { + hr = HRESULT_FROM_WIN32(ERROR_OBJECT_NOT_FOUND); + } + + MessageExitOnFailure(hr, msierrXmlFileFailedSelect, "failed to find any nodes: %ls in XML file: %ls", pwzXPath, pwzFile); + for (;;) + { + pixNodes->nextNode(&pixn); + if (NULL == pixn) + break; + + if (pwzName && *pwzName) + { + // We're setting an attribute + hr = XmlSetAttribute(pixn, pwzName, pwzValue); + ExitOnFailure(hr, "failed to set attribute: %ls to value %ls", pwzName, pwzValue); + } + else + { + // We're setting the text of the node + hr = XmlSetText(pixn, pwzValue); + ExitOnFailure(hr, "failed to set text to: %ls for element %ls. Make sure that XPath points to an element.", pwzValue, pwzXPath); + } + ReleaseNullObject(pixn); + } + } + else + { + hr = XmlSelectSingleNode(pixd, pwzXPath, &pixn); + if (S_FALSE == hr) + hr = HRESULT_FROM_WIN32(ERROR_OBJECT_NOT_FOUND); + MessageExitOnFailure(hr, msierrXmlFileFailedSelect, "failed to find node: %ls in XML file: %ls", pwzXPath, pwzFile); + + // Make the modification + if (xaWriteValue == xa) + { + if (pwzName && *pwzName) + { + // We're setting an attribute + hr = XmlSetAttribute(pixn, pwzName, pwzValue); + ExitOnFailure(hr, "failed to set attribute: %ls to value %ls", pwzName, pwzValue); + } + else + { + // We're setting the text of the node + hr = XmlSetText(pixn, pwzValue); + ExitOnFailure(hr, "failed to set text to: %ls for element %ls. Make sure that XPath points to an element.", pwzValue, pwzXPath); + } + } + else if (xaCreateElement == xa) + { + hr = XmlCreateChild(pixn, pwzName, &pixnNewNode); + ExitOnFailure(hr, "failed to create child element: %ls", pwzName); + + if (pwzValue && *pwzValue) + { + hr = XmlSetText(pixnNewNode, pwzValue); + ExitOnFailure(hr, "failed to set text to: %ls for node: %ls", pwzValue, pwzName); + } + + ReleaseNullObject(pixnNewNode); + } + else if (xaDeleteValue == xa) + { + if (pwzName && *pwzName) + { + // Delete the attribute + hr = XmlRemoveAttribute(pixn, pwzName); + ExitOnFailure(hr, "failed to remove attribute: %ls", pwzName); + } + else + { + // Clear the text value for the node + hr = XmlSetText(pixn, L""); + ExitOnFailure(hr, "failed to clear text value"); + } + } + else if (xaDeleteElement == xa) + { + // TODO: This may be a little heavy handed + hr = XmlRemoveChildren(pixn, pwzName); + ExitOnFailure(hr, "failed to delete child node: %ls", pwzName); + } + else + { + ExitOnFailure(hr = E_UNEXPECTED, "Invalid modification specified in custom action data"); + } + } + } + + // Now that we've made all of the changes to this file, save it and move on to the next + if (S_OK == hrOpenFailure) + { + if (fPreserveDate) + { + hr = FileGetTime(pwzFile, NULL, NULL, &ft); + ExitOnFailure(hr, "failed to get modified time of file : %ls", pwzFile); + } + + int iSaveAttempt = 0; + + do + { + hr = XmlSaveDocument(pixd, pwzFile); + if (FAILED(hr)) + { + id = WcaErrorMessage(msierrXmlConfigFailedSave, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 1, pwzFile); + switch (id) + { + case IDABORT: + ExitOnFailure(hr, "Failed to save changes to XML file: %ls", pwzFile); + case IDRETRY: + hr = S_FALSE; // hit me, baby, one more time + break; + case IDIGNORE: + hr = S_OK; // pretend everything is okay and bail + break; + case 0: // No UI case, MsiProcessMessage returns 0 + if (STIERR_SHARING_VIOLATION == hr) + { + // Only in case of sharing violation do we retry 30 times, once a second. + if (iSaveAttempt < 30) + { + hr = S_FALSE; + ++iSaveAttempt; + WcaLog(LOGMSG_VERBOSE, "Unable to save changes to XML file: %ls, retry attempt: %x", pwzFile, iSaveAttempt); + Sleep(1000); + } + else + { + ExitOnFailure(hr, "Failed to save changes to XML file: %ls", pwzFile); + } + } + break; + default: // Unknown error + ExitOnFailure(hr, "Failed to save changes to XML file: %ls", pwzFile); + } + } + } while (S_FALSE == hr); + + if (fPreserveDate) + { + hr = FileSetTime(pwzFile, NULL, NULL, &ft); + ExitOnFailure(hr, "failed to set modified time of file : %ls", pwzFile); + } + + if (fIsFSRedirectDisabled) + { + fIsFSRedirectDisabled = FALSE; + WcaRevertWow64FSRedirection(); + } + } + } + +LExit: + // Make sure we revert FS Redirection if necessary before exiting + if (fIsFSRedirectDisabled) + { + fIsFSRedirectDisabled = FALSE; + WcaRevertWow64FSRedirection(); + } +#ifndef _WIN64 + WcaFinalizeWow64(); +#endif + + ReleaseStr(pwzCustomActionData); + ReleaseStr(pwzData); + ReleaseStr(pwzFile); + ReleaseStr(pwzXPath); + ReleaseStr(pwzName); + ReleaseStr(pwzValue); + ReleaseBSTR(bstrProperty); + ReleaseVariant(varValue); + + ReleaseObject(pixdDocument2); + ReleaseObject(pixn); + ReleaseObject(pixd); + ReleaseObject(pixnNewNode); + ReleaseObject(pixNodes); + + XmlUninitialize(); + + return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : er); +} + + +/****************************************************************** + ExecXmlFileRollback - entry point for XmlFile rollback Custom Action + +*******************************************************************/ +extern "C" UINT __stdcall ExecXmlFileRollback( + __in MSIHANDLE hInstall + ) +{ +// AssertSz(FALSE, "debug ExecXmlFileRollback"); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + int iIs64Bit; + BOOL fIs64Bit = FALSE; + + LPWSTR pwzCustomActionData = NULL; + LPWSTR pwz = NULL; + LPWSTR pwzFileName = NULL; + LPBYTE pbData = NULL; + DWORD_PTR cbData = 0; + + FILETIME ft; + + HANDLE hFile = INVALID_HANDLE_VALUE; + + // initialize + hr = WcaInitialize(hInstall, "ExecXmlFileRollback"); + ExitOnFailure(hr, "failed to initialize"); + + + hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData); + ExitOnFailure(hr, "failed to get CustomActionData"); + + WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); + + pwz = pwzCustomActionData; + + hr = WcaReadIntegerFromCaData(&pwz, &iIs64Bit); + ExitOnFailure(hr, "failed to read component bitness from custom action data"); + + hr = WcaReadStringFromCaData(&pwz, &pwzFileName); + ExitOnFailure(hr, "failed to read file name from custom action data"); + + hr = WcaReadStreamFromCaData(&pwz, &pbData, &cbData); + ExitOnFailure(hr, "failed to read file contents from custom action data"); + +#ifndef _WIN64 + fIs64Bit = (BOOL)iIs64Bit; + + if (fIs64Bit) + { + hr = WcaInitializeWow64(); + if (S_FALSE == hr) + { + hr = TYPE_E_DLLFUNCTIONNOTFOUND; + } + ExitOnFailure(hr, "failed to initialize Wow64 API"); + + if (!WcaIsWow64Process()) + { + hr = E_NOTIMPL; + ExitOnFailure(hr, "Custom action was told to rollback a 64-bit component, but the custom action process is not running in WOW."); + } + + hr = WcaDisableWow64FSRedirection(); + ExitOnFailure(hr, "Custom action was told to rollback a 64-bit component, but was unable to Disable Filesystem Redirection through the Wow64 API."); + } +#endif + + // Always preserve the modified date on rollback + hr = FileGetTime(pwzFileName, NULL, NULL, &ft); + ExitOnFailure(hr, "Failed to get modified date of file %ls.", pwzFileName); + + // Open the file + hFile = ::CreateFileW(pwzFileName, GENERIC_WRITE, NULL, NULL, TRUNCATE_EXISTING, NULL, NULL); + ExitOnInvalidHandleWithLastError(hFile, hr, "failed to open file: %ls", pwzFileName); + + // Write out the old data + hr = FileWriteHandle(hFile, pbData, cbData); + ExitOnFailure(hr, "failed to write to file: %ls", pwzFileName); + + ReleaseFile(hFile); + + // Always preserve the modified date on rollback + hr = FileSetTime(pwzFileName, NULL, NULL, &ft); + ExitOnFailure(hr, "Failed to set modified date of file %ls.", pwzFileName); + +LExit: + ReleaseStr(pwzCustomActionData); + ReleaseStr(pwzFileName); + + ReleaseFile(hFile); + + if (fIs64Bit) + { + WcaRevertWow64FSRedirection(); + WcaFinalizeWow64(); + } + + ReleaseMem(pbData); + + return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : er); +} + diff --git a/src/ext/Util/ca/caDecor.h b/src/ext/Util/ca/caDecor.h new file mode 100644 index 00000000..da274650 --- /dev/null +++ b/src/ext/Util/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/Util/ca/cost.h b/src/ext/Util/ca/cost.h new file mode 100644 index 00000000..6507e85d --- /dev/null +++ b/src/ext/Util/ca/cost.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. + + +const UINT COST_SECUREOBJECT = 1000; +const UINT COST_SERVICECONFIG = 1000; +const UINT COST_XMLFILE = 1000; +const UINT COST_CLOSEAPP = 500; +const UINT COST_INTERNETSHORTCUT = 2000; diff --git a/src/ext/Util/ca/dllmain.cpp b/src/ext/Util/ca/dllmain.cpp new file mode 100644 index 00000000..35ae6d1c --- /dev/null +++ b/src/ext/Util/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/Util/ca/exitearlywithsuccess.cpp b/src/ext/Util/ca/exitearlywithsuccess.cpp new file mode 100644 index 00000000..00828329 --- /dev/null +++ b/src/ext/Util/ca/exitearlywithsuccess.cpp @@ -0,0 +1,27 @@ +// Copyright (c) .NET 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" + + +/****************************************************************** +WixExitEarlyWithSuccess - entry point for WixExitEarlyWithSuccess + custom action which does nothing except return exit code + ERROR_NO_MORE_ITEMS. The Windows Installer documentation at + http://msdn.microsoft.com/library/aa368072.aspx indicates that + this exit code is not treated as an error. This will cause a + calling application to receive a successful return code if + this custom action executes. This can be useful for backwards + compatibility when an application redistributes an MSI and + a future major upgrade is released for that MSI. It should be + conditioned on a property set by an entry in the Upgrade table + of the MSI that detects newer major upgrades of the same MSI + already installed on the system. It should be scheduled after + the FindRelatedProducts action so that the property will be + set if appropriate. +********************************************************************/ +extern "C" UINT __stdcall WixExitEarlyWithSuccess( + __in MSIHANDLE /*hInstall*/ + ) +{ + return ERROR_NO_MORE_ITEMS; +} diff --git a/src/ext/Util/ca/netshortcuts.cpp b/src/ext/Util/ca/netshortcuts.cpp new file mode 100644 index 00000000..06826264 --- /dev/null +++ b/src/ext/Util/ca/netshortcuts.cpp @@ -0,0 +1,437 @@ +// Copyright (c) .NET 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 vcsShortcutsQuery = + L"SELECT `Component_`, `Directory_`, `Name`, `Target`, `Attributes`, `IconFile`, `IconIndex` " + L"FROM `Wix4InternetShortcut`"; +enum eShortcutsQuery { esqComponent = 1, esqDirectory, esqFilename, esqTarget, esqAttributes, esqIconFile, esqIconIndex }; +enum eShortcutsAttributes { esaLink = 0, esaURL = 1 }; + +/****************************************************************** + WixSchedInternetShortcuts - entry point + +********************************************************************/ +extern "C" UINT __stdcall WixSchedInternetShortcuts( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + UINT uiCost = 0; + + PMSIHANDLE hView = NULL; + PMSIHANDLE hRec = NULL; + + MSIHANDLE hCreateFolderTable = NULL; + MSIHANDLE hCreateFolderColumns = NULL; + + LPWSTR pwzCustomActionData = NULL; + LPWSTR pwzComponent = NULL; + LPWSTR pwzDirectory = NULL; + LPWSTR pwzFilename = NULL; + LPWSTR pwzTarget = NULL; + LPWSTR pwzShortcutPath = NULL; + int iAttr = 0; + LPWSTR pwzIconFile = NULL; + int iIconIndex = 0; + IUniformResourceLocatorW* piURL = NULL; + IShellLinkW* piShellLink = NULL; + BOOL fInitializedCom = FALSE; + + hr = WcaInitialize(hInstall, "WixSchedInternetShortcuts"); + ExitOnFailure(hr, "failed to initialize WixSchedInternetShortcuts."); + + // anything to do? + if (S_OK != WcaTableExists(L"Wix4InternetShortcut")) + { + WcaLog(LOGMSG_STANDARD, "Wix4InternetShortcut table doesn't exist, so there are no Internet shortcuts to process"); + goto LExit; + } + + // check to see if we can create a shortcut - Server Core and others may not have a shell registered. + hr = ::CoInitialize(NULL); + ExitOnFailure(hr, "failed to initialize COM"); + fInitializedCom = TRUE; + + hr = ::CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_ALL, IID_IUniformResourceLocatorW, (void**)&piURL); + if (S_OK != hr) + { + WcaLog(LOGMSG_STANDARD, "failed to create an instance of IUniformResourceLocatorW, skipping shortcut creation"); + ExitFunction1(hr = S_OK); + } + + hr = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLinkW, (void**)&piShellLink); + if (S_OK != hr) + { + WcaLog(LOGMSG_STANDARD, "failed to create an instance of IShellLinkW, skipping shortcut creation"); + ExitFunction1(hr = S_OK); + } + + // query and loop through all the shortcuts + hr = WcaOpenExecuteView(vcsShortcutsQuery, &hView); + ExitOnFailure(hr, "failed to open view on Wix4InternetShortcut table"); + + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + // read column values + hr = WcaGetRecordString(hRec, esqComponent, &pwzComponent); + ExitOnFailure(hr, "failed to get shortcut component"); + hr = WcaGetRecordString(hRec, esqDirectory, &pwzDirectory); + ExitOnFailure(hr, "failed to get shortcut directory"); + hr = WcaGetRecordString(hRec, esqFilename, &pwzFilename); + ExitOnFailure(hr, "failed to get shortcut filename"); + hr = WcaGetRecordFormattedString(hRec, esqTarget, &pwzTarget); + ExitOnFailure(hr, "failed to get shortcut target"); + hr = WcaGetRecordInteger(hRec, esqAttributes, &iAttr); + ExitOnFailure(hr, "failed to get shortcut attributes"); + hr = WcaGetRecordFormattedString(hRec, esqIconFile, &pwzIconFile); + ExitOnFailure(hr, "failed to get shortcut icon file"); + hr = WcaGetRecordInteger(hRec, esqIconIndex, &iIconIndex); + ExitOnFailure(hr, "failed to get shortcut icon index"); + + // skip processing this Wix4InternetShortcut row if the component isn't being configured + WCA_TODO todo = WcaGetComponentToDo(pwzComponent); + if (WCA_TODO_UNKNOWN == todo) + { + WcaLog(LOGMSG_VERBOSE, "Skipping shortcut for null-action component '%ls'", pwzComponent); + continue; + } + + // we need to create the directory where the shortcut is supposed to live; rather + // than doing so in our deferred custom action, use the CreateFolder table to have MSI + // make (and remove) them on our behalf (including the correct cleanup of parent directories). + MSIDBERROR dbError = MSIDBERROR_NOERROR; + WcaLog(LOGMSG_STANDARD, "Adding folder '%ls', component '%ls' to the CreateFolder table", pwzDirectory, pwzComponent); + hr = WcaAddTempRecord(&hCreateFolderTable, &hCreateFolderColumns, L"CreateFolder", &dbError, 0, 2, pwzDirectory, pwzComponent); + if (MSIDBERROR_DUPLICATEKEY == dbError) + { + WcaLog(LOGMSG_STANDARD, "Folder '%ls' already exists in the CreateFolder table; the above error is harmless", pwzDirectory); + hr = S_OK; + } + ExitOnFailure(hr, "Couldn't add temporary CreateFolder row"); + + // only if we're installing/reinstalling do we need to schedule the deferred CA + // (uninstallation is handled via permanent RemoveFile rows and temporary CreateFolder rows) + if (WCA_TODO_INSTALL == todo || WCA_TODO_REINSTALL == todo) + { + // turn the Directory_ id into a path + hr = WcaGetTargetPath(pwzDirectory, &pwzShortcutPath); + ExitOnFailure(hr, "failed to allocate string for shortcut directory"); + + // append the shortcut filename + hr = StrAllocConcat(&pwzShortcutPath, pwzFilename, 0); + ExitOnFailure(hr, "failed to allocate string for shortcut filename"); + + // write the shortcut path and target to custom action data for deferred CAs + hr = WcaWriteStringToCaData(pwzShortcutPath, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write shortcut path to custom action data"); + hr = WcaWriteStringToCaData(pwzTarget, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write shortcut target to custom action data"); + hr = WcaWriteIntegerToCaData(iAttr, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write shortcut attributes to custom action data"); + hr = WcaWriteStringToCaData(pwzIconFile, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write icon file to custom action data"); + hr = WcaWriteIntegerToCaData(iIconIndex, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write icon index to custom action data"); + + uiCost += COST_INTERNETSHORTCUT; + } + } + + if (E_NOMOREITEMS == hr) + { + hr = S_OK; + } + ExitOnFailure(hr, "Failure occured while processing Wix4InternetShortcut table"); + + // if we have any shortcuts to install + if (pwzCustomActionData && *pwzCustomActionData) + { + // add cost to progress bar + hr = WcaProgressMessage(uiCost, TRUE); + ExitOnFailure(hr, "failed to extend progress bar for InternetShortcuts"); + + // provide custom action data to deferred and rollback CAs + hr = WcaSetProperty(CUSTOM_ACTION_DECORATION(L"RollbackInternetShortcuts"), pwzCustomActionData); + ExitOnFailure(hr, "failed to set WixRollbackInternetShortcuts rollback custom action data"); + hr = WcaSetProperty(CUSTOM_ACTION_DECORATION(L"CreateInternetShortcuts"), pwzCustomActionData); + ExitOnFailure(hr, "failed to set WixCreateInternetShortcuts custom action data"); + } + +LExit: + if (hCreateFolderTable) + { + ::MsiCloseHandle(hCreateFolderTable); + } + + if (hCreateFolderColumns) + { + ::MsiCloseHandle(hCreateFolderColumns); + } + + ReleaseStr(pwzCustomActionData); + ReleaseStr(pwzComponent); + ReleaseStr(pwzDirectory); + ReleaseStr(pwzFilename); + ReleaseStr(pwzTarget); + ReleaseStr(pwzShortcutPath); + ReleaseObject(piShellLink); + ReleaseObject(piURL); + + if (fInitializedCom) + { + ::CoUninitialize(); + } + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + + +/****************************************************************** + CreateUrl - Creates a shortcut via IUniformResourceLocatorW + +*******************************************************************/ +static HRESULT CreateUrl( + __in_z LPCWSTR wzTarget, + __in_z LPCWSTR wzShortcutPath, + __in_z_opt LPCWSTR wzIconPath, + __in int iconIndex +) +{ + HRESULT hr = S_OK; + IUniformResourceLocatorW* piURL = NULL; + IPersistFile* piPersistFile = NULL; + IPropertySetStorage* piProperties = NULL; + IPropertyStorage* piStorage = NULL; + + // create an internet shortcut object + WcaLog(LOGMSG_STANDARD, "Creating IUniformResourceLocatorW shortcut '%ls' target '%ls'", wzShortcutPath, wzTarget); + hr = ::CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_ALL, IID_IUniformResourceLocatorW, (void**)&piURL); + ExitOnFailure(hr, "failed to create an instance of IUniformResourceLocatorW"); + + // set shortcut target + hr = piURL->SetURL(wzTarget, 0); + ExitOnFailure(hr, "failed to set shortcut '%ls' target '%ls'", wzShortcutPath, wzTarget); + + if (wzIconPath) + { + WcaLog(LOGMSG_STANDARD, "Adding icon '%ls' index '%d'", wzIconPath, iconIndex); + + hr = piURL->QueryInterface(IID_IPropertySetStorage, (void **)&piProperties); + ExitOnFailure(hr, "failed to get IPropertySetStorage for shortcut '%ls'", wzShortcutPath); + + hr = piProperties->Open(FMTID_Intshcut, STGM_WRITE, &piStorage); + ExitOnFailure(hr, "failed to open storage for shortcut '%ls'", wzShortcutPath); + + PROPSPEC ppids[2] = { {PRSPEC_PROPID, PID_IS_ICONINDEX}, {PRSPEC_PROPID, PID_IS_ICONFILE} }; + PROPVARIANT ppvar[2]; + + PropVariantInit(ppvar); + PropVariantInit(ppvar + 1); + + ppvar[0].vt = VT_I4; + ppvar[0].lVal = iconIndex; + ppvar[1].vt = VT_LPWSTR; + ppvar[1].pwszVal = const_cast(wzIconPath); + + hr = piStorage->WriteMultiple(2, ppids, ppvar, 0); + ExitOnFailure(hr, "failed to write icon storage for shortcut '%ls'", wzShortcutPath); + + hr = piStorage->Commit(STGC_DEFAULT); + ExitOnFailure(hr, "failed to commit icon storage for shortcut '%ls'", wzShortcutPath); + } + + // get an IPersistFile and save the shortcut + hr = piURL->QueryInterface(IID_IPersistFile, (void**)&piPersistFile); + ExitOnFailure(hr, "failed to get IPersistFile for shortcut '%ls'", wzShortcutPath); + + hr = piPersistFile->Save(wzShortcutPath, TRUE); + ExitOnFailure(hr, "failed to save shortcut '%ls'", wzShortcutPath); + +LExit: + ReleaseObject(piPersistFile); + ReleaseObject(piURL); + ReleaseObject(piStorage); + ReleaseObject(piProperties); + + return hr; +} + +/****************************************************************** + CreateLink - Creates a shortcut via IShellLinkW + +*******************************************************************/ +static HRESULT CreateLink( + __in_z LPCWSTR wzTarget, + __in_z LPCWSTR wzShortcutPath, + __in_z_opt LPCWSTR wzIconPath, + __in int iconIndex +) +{ + HRESULT hr = S_OK; + IShellLinkW* piShellLink = NULL; + IPersistFile* piPersistFile = NULL; + + // create an internet shortcut object + WcaLog(LOGMSG_STANDARD, "Creating IShellLinkW shortcut '%ls' target '%ls'", wzShortcutPath, wzTarget); + hr = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLinkW, (void**)&piShellLink); + ExitOnFailure(hr, "failed to create an instance of IShellLinkW"); + + // set shortcut target + hr = piShellLink->SetPath(wzTarget); + ExitOnFailure(hr, "failed to set shortcut '%ls' target '%ls'", wzShortcutPath, wzTarget); + + if (wzIconPath) + { + WcaLog(LOGMSG_STANDARD, "Adding icon '%ls' index '%d'", wzIconPath, iconIndex); + hr = piShellLink->SetIconLocation(wzIconPath, iconIndex); + ExitOnFailure(hr, "failed to set icon for shortcut '%ls'", wzShortcutPath); + } + + // get an IPersistFile and save the shortcut + hr = piShellLink->QueryInterface(IID_IPersistFile, (void**)&piPersistFile); + ExitOnFailure(hr, "failed to get IPersistFile for shortcut '%ls'", wzShortcutPath); + + hr = piPersistFile->Save(wzShortcutPath, TRUE); + ExitOnFailure(hr, "failed to save shortcut '%ls'", wzShortcutPath); + +LExit: + ReleaseObject(piPersistFile); + ReleaseObject(piShellLink); + + return hr; +} + + + +/****************************************************************** + WixCreateInternetShortcuts - entry point for Internet shortcuts + custom action +*******************************************************************/ +extern "C" UINT __stdcall WixCreateInternetShortcuts( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + LPWSTR pwz = NULL; + LPWSTR pwzCustomActionData = NULL; + LPWSTR pwzTarget = NULL; + LPWSTR pwzShortcutPath = NULL; + LPWSTR pwzIconPath = NULL; + BOOL fInitializedCom = FALSE; + int iAttr = 0; + int iIconIndex = 0; + + // initialize + hr = WcaInitialize(hInstall, "WixCreateInternetShortcuts"); + ExitOnFailure(hr, "failed to initialize WixCreateInternetShortcuts"); + + hr = ::CoInitialize(NULL); + ExitOnFailure(hr, "failed to initialize COM"); + fInitializedCom = TRUE; + + // extract the custom action data + hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); + ExitOnFailure(hr, "failed to get CustomActionData"); + + // loop through all the custom action data + pwz = pwzCustomActionData; + while (pwz && *pwz) + { + hr = WcaReadStringFromCaData(&pwz, &pwzShortcutPath); + ExitOnFailure(hr, "failed to read shortcut path from custom action data"); + hr = WcaReadStringFromCaData(&pwz, &pwzTarget); + ExitOnFailure(hr, "failed to read shortcut target from custom action data"); + hr = WcaReadIntegerFromCaData(&pwz, &iAttr); + ExitOnFailure(hr, "failed to read shortcut attributes from custom action data"); + hr = WcaReadStringFromCaData(&pwz, &pwzIconPath); + ExitOnFailure(hr, "failed to read shortcut icon path from custom action data"); + hr = WcaReadIntegerFromCaData(&pwz, &iIconIndex); + ExitOnFailure(hr, "failed to read shortcut icon index from custom action data"); + + if ((iAttr & esaURL) == esaURL) + { + hr = CreateUrl(pwzTarget, pwzShortcutPath, pwzIconPath, iIconIndex); + } + else + { + hr = CreateLink(pwzTarget, pwzShortcutPath, pwzIconPath, iIconIndex); + } + ExitOnFailure(hr, "failed to create Internet shortcut"); + + // tick the progress bar + hr = WcaProgressMessage(COST_INTERNETSHORTCUT, FALSE); + ExitOnFailure(hr, "failed to tick progress bar for shortcut: %ls", pwzShortcutPath); + } + +LExit: + ReleaseStr(pwzCustomActionData); + ReleaseStr(pwzTarget); + ReleaseStr(pwzShortcutPath); + + if (fInitializedCom) + { + ::CoUninitialize(); + } + + er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er; + return WcaFinalize(er); +} + + + +/****************************************************************** + WixRollbackInternetShortcuts - entry point for Internet shortcuts + custom action (rollback) +*******************************************************************/ +extern "C" UINT __stdcall WixRollbackInternetShortcuts( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + LPWSTR pwz = NULL; + LPWSTR pwzCustomActionData = NULL; + LPWSTR pwzShortcutPath = NULL; + int iAttr = 0; + + // initialize + hr = WcaInitialize(hInstall, "WixRemoveInternetShortcuts"); + ExitOnFailure(hr, "failed to initialize WixRemoveInternetShortcuts"); + + hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); + ExitOnFailure(hr, "failed to get CustomActionData"); + + // loop through all the custom action data + pwz = pwzCustomActionData; + while (pwz && *pwz) + { + // extract the custom action data we're interested in + hr = WcaReadStringFromCaData(&pwz, &pwzShortcutPath); + ExitOnFailure(hr, "failed to read shortcut path from custom action data for rollback"); + + // delete file + hr = FileEnsureDelete(pwzShortcutPath); + ExitOnFailure(hr, "failed to delete file '%ls'", pwzShortcutPath); + + // skip over the shortcut target and attributes + hr = WcaReadStringFromCaData(&pwz, &pwzShortcutPath); + ExitOnFailure(hr, "failed to skip shortcut target from custom action data for rollback"); + hr = WcaReadIntegerFromCaData(&pwz, &iAttr); + ExitOnFailure(hr, "failed to read shortcut attributes from custom action data"); + } + +LExit: + ReleaseStr(pwzCustomActionData); + ReleaseStr(pwzShortcutPath); + + er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er; + return WcaFinalize(er); +} diff --git a/src/ext/Util/ca/precomp.h b/src/ext/Util/ca/precomp.h new file mode 100644 index 00000000..c5d6afe5 --- /dev/null +++ b/src/ext/Util/ca/precomp.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. + + +#if _WIN32_MSI < 150 +#define _WIN32_MSI 150 +#endif + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include // NetApi32.lib +#include +#include +#include +#include + +#define MAXUINT USHRT_MAX + +#include "wcautil.h" +#include "wcawow64.h" +#include "wcawrapquery.h" +#include "aclutil.h" +#include "dirutil.h" +#include "fileutil.h" +#include "memutil.h" +#include "osutil.h" +#include "pathutil.h" +#include "procutil.h" +#include "shelutil.h" +#include "strutil.h" +#include "sczutil.h" +#include "rmutil.h" +#include "userutil.h" +#include "xmlutil.h" +#include "wiutil.h" + +#include "CustomMsiErrors.h" + +#include "sca.h" +#include "scacost.h" +#include "cost.h" +#include "scauser.h" +#include "scasmb.h" +#include "scasmbexec.h" + +#include "caDecor.h" diff --git a/src/ext/Util/ca/qtexecca.cpp b/src/ext/Util/ca/qtexecca.cpp new file mode 100644 index 00000000..ddcc812f --- /dev/null +++ b/src/ext/Util/ca/qtexecca.cpp @@ -0,0 +1,316 @@ +// Copyright (c) .NET 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 OUTPUT_BUFFER 1024 + +// These old "CA" prefix names are deprecated, and intended to go away in wix 4.0, only staying now for compatibility reasons +const LPCWSTR CAQUIET_TIMEOUT_PROPERTY = L"QtExecCmdTimeout"; +const LPCWSTR CAQUIET_ARGUMENTS_PROPERTY = L"QtExecCmdLine"; +const LPCWSTR CAQUIET64_ARGUMENTS_PROPERTY = L"QtExec64CmdLine"; +// end deprecated section + +// WixCA name quiet commandline argument properties +const LPCWSTR WIX_QUIET_ARGUMENTS_PROPERTY = L"WixQuietExecCmdLine"; +const LPCWSTR WIX_QUIET64_ARGUMENTS_PROPERTY = L"WixQuietExec64CmdLine"; + +// WixCA quiet timeout properties +const LPCWSTR WIX_QUIET_TIMEOUT_PROPERTY = L"WixQuietExecCmdTimeout"; +const LPCWSTR WIX_QUIET64_TIMEOUT_PROPERTY = L"WixQuietExec64CmdTimeout"; + +// WixCA silent commandline argument properties +const LPCWSTR WIX_SILENT_ARGUMENTS_PROPERTY = L"WixSilentExecCmdLine"; +const LPCWSTR WIX_SILENT64_ARGUMENTS_PROPERTY = L"WixSilentExec64CmdLine"; + +// WixCA silent timeout properties +const LPCWSTR WIX_SILENT_TIMEOUT_PROPERTY = L"WixSilentExecCmdTimeout"; +const LPCWSTR WIX_SILENT64_TIMEOUT_PROPERTY = L"WixSilentExec64CmdTimeout"; + +HRESULT BuildCommandLine( + __in LPCWSTR wzProperty, + __out LPWSTR *ppwzCommand + ) +{ + Assert(ppwzCommand); + + HRESULT hr = S_OK; + BOOL fScheduled = ::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_SCHEDULED); + BOOL fRollback = ::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK); + BOOL fCommit = ::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_COMMIT); + + if (fScheduled || fRollback || fCommit) + { + if (WcaIsPropertySet("CustomActionData")) + { + hr = WcaGetProperty( L"CustomActionData", ppwzCommand); + ExitOnFailure(hr, "Failed to get CustomActionData"); + } + } + else if (WcaIsUnicodePropertySet(wzProperty)) + { + hr = WcaGetFormattedProperty(wzProperty, ppwzCommand); + ExitOnFailure(hr, "Failed to get %ls", wzProperty); + hr = WcaSetProperty(wzProperty, L""); // clear out the property now that we've read it + ExitOnFailure(hr, "Failed to set %ls", wzProperty); + } + + if (!*ppwzCommand) + { + ExitOnFailure(hr = E_INVALIDARG, "Failed to get command line data"); + } + + if (L'"' != **ppwzCommand) + { + WcaLog(LOGMSG_STANDARD, "Command string must begin with quoted application name."); + ExitOnFailure(hr = E_INVALIDARG, "invalid command line property value"); + } + +LExit: + return hr; +} + +#define ONEMINUTE 60000 + +DWORD GetTimeout(LPCWSTR wzPropertyName) +{ + DWORD dwTimeout = ONEMINUTE; + HRESULT hr = S_OK; + + LPWSTR pwzData = NULL; + + if (WcaIsUnicodePropertySet(wzPropertyName)) + { + hr = WcaGetProperty(wzPropertyName, &pwzData); + ExitOnFailure(hr, "Failed to get %ls", wzPropertyName); + + if ((dwTimeout = (DWORD)_wtoi(pwzData)) == 0) + { + dwTimeout = ONEMINUTE; + } + } + +LExit: + ReleaseStr(pwzData); + + return dwTimeout; + +} + +HRESULT ExecCommon( + __in LPCWSTR wzArgumentsProperty, + __in LPCWSTR wzTimeoutProperty, + __in BOOL fLogCommand, + __in BOOL fLogOutput + ) +{ + HRESULT hr = S_OK; + LPWSTR pwzCommand = NULL; + DWORD dwTimeout = 0; + + hr = BuildCommandLine(wzArgumentsProperty, &pwzCommand); + ExitOnFailure(hr, "Failed to get Command Line"); + + dwTimeout = GetTimeout(wzTimeoutProperty); + + hr = QuietExec(pwzCommand, dwTimeout, fLogCommand, fLogOutput); + ExitOnFailure(hr, "QuietExec Failed"); + +LExit: + ReleaseStr(pwzCommand); + + return hr; +} + +HRESULT ExecCommon64( + __in LPCWSTR wzArgumentsProperty, + __in LPCWSTR wzTimeoutProperty, + __in BOOL fLogCommand, + __in BOOL fLogOutput + ) +{ + HRESULT hr = S_OK; + LPWSTR pwzCommand = NULL; + DWORD dwTimeout = 0; +#ifndef _WIN64 + BOOL fIsWow64Initialized = FALSE; + BOOL fRedirected = FALSE; + + hr = WcaInitializeWow64(); + if (S_FALSE == hr) + { + hr = TYPE_E_DLLFUNCTIONNOTFOUND; + } + ExitOnFailure(hr, "Failed to intialize WOW64."); + fIsWow64Initialized = TRUE; + + hr = WcaDisableWow64FSRedirection(); + ExitOnFailure(hr, "Failed to enable filesystem redirection."); + fRedirected = TRUE; +#endif + + hr = BuildCommandLine(wzArgumentsProperty, &pwzCommand); + ExitOnFailure(hr, "Failed to get Command Line"); + + dwTimeout = GetTimeout(wzTimeoutProperty); + + hr = QuietExec(pwzCommand, dwTimeout, fLogCommand, fLogOutput); + ExitOnFailure(hr, "QuietExec64 Failed"); + +LExit: + ReleaseStr(pwzCommand); + +#ifndef _WIN64 + if (fRedirected) + { + WcaRevertWow64FSRedirection(); + } + + if (fIsWow64Initialized) + { + WcaFinalizeWow64(); + } +#endif + + return hr; +} + +// These two custom actions are deprecated, and should go away in wix v4.0. WixQuietExec replaces this one, +// and is not intended to have any difference in behavior apart from CA name and property names. +extern "C" UINT __stdcall CAQuietExec( + __in MSIHANDLE hInstall + ) +{ + Assert(hInstall); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "CAQuietExec"); + ExitOnFailure(hr, "Failed to initialize"); + + hr = ExecCommon(CAQUIET_ARGUMENTS_PROPERTY, CAQUIET_TIMEOUT_PROPERTY, TRUE, TRUE); + ExitOnFailure(hr, "Failed in ExecCommon method"); + +LExit: + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + + return WcaFinalize(er); +} + +// 2nd deprecated custom action name, superseded by WixQuietExec64 +extern "C" UINT __stdcall CAQuietExec64( + __in MSIHANDLE hInstall + ) +{ + Assert(hInstall); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "CAQuietExec64"); + ExitOnFailure(hr, "Failed to initialize"); + + hr = ExecCommon64(CAQUIET64_ARGUMENTS_PROPERTY, CAQUIET_TIMEOUT_PROPERTY, TRUE, TRUE); + ExitOnFailure(hr, "Failed in ExecCommon64 method"); + +LExit: + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + + return WcaFinalize(er); +} + +extern "C" UINT __stdcall WixQuietExec( + __in MSIHANDLE hInstall + ) +{ + Assert(hInstall); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "WixQuietExec"); + ExitOnFailure(hr, "Failed to initialize"); + + hr = ExecCommon(WIX_QUIET_ARGUMENTS_PROPERTY, WIX_QUIET_TIMEOUT_PROPERTY, TRUE, TRUE); + ExitOnFailure(hr, "Failed in ExecCommon method"); + +LExit: + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + + return WcaFinalize(er); +} + +extern "C" UINT __stdcall WixQuietExec64( + __in MSIHANDLE hInstall + ) +{ + Assert(hInstall); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "WixQuietExec64"); + ExitOnFailure(hr, "Failed to initialize"); + + hr = ExecCommon64(WIX_QUIET64_ARGUMENTS_PROPERTY, WIX_QUIET64_TIMEOUT_PROPERTY, TRUE, TRUE); + ExitOnFailure(hr, "Failed in ExecCommon method"); + +LExit: + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + + return WcaFinalize(er); +} + +extern "C" UINT __stdcall WixSilentExec( + __in MSIHANDLE hInstall + ) +{ + Assert(hInstall); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "WixSilentExec"); + ExitOnFailure(hr, "Failed to initialize"); + + hr = ExecCommon(WIX_SILENT_ARGUMENTS_PROPERTY, WIX_SILENT_TIMEOUT_PROPERTY, FALSE, FALSE); + ExitOnFailure(hr, "Failed in ExecCommon method"); + +LExit: + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + + return WcaFinalize(er); +} + +extern "C" UINT __stdcall WixSilentExec64( + __in MSIHANDLE hInstall + ) +{ + Assert(hInstall); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "WixSilentExec64"); + ExitOnFailure(hr, "Failed to initialize"); + + hr = ExecCommon64(WIX_SILENT64_ARGUMENTS_PROPERTY, WIX_SILENT64_TIMEOUT_PROPERTY, FALSE, FALSE); + ExitOnFailure(hr, "Failed in ExecCommon method"); + +LExit: + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + + return WcaFinalize(er); +} diff --git a/src/ext/Util/ca/sca.h b/src/ext/Util/ca/sca.h new file mode 100644 index 00000000..599122ff --- /dev/null +++ b/src/ext/Util/ca/sca.h @@ -0,0 +1,19 @@ +#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. + +// 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, +}; \ No newline at end of file diff --git a/src/ext/Util/ca/scacost.h b/src/ext/Util/ca/scacost.h new file mode 100644 index 00000000..5b215035 --- /dev/null +++ b/src/ext/Util/ca/scacost.h @@ -0,0 +1,18 @@ +#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_PERFMON_REGISTER = 1000; +const UINT COST_PERFMON_UNREGISTER = 1000; + +const UINT COST_SMB_CREATESMB = 10000; +const UINT COST_SMB_DROPSMB = 5000; +const UINT COST_USER_ADD = 10000; +const UINT COST_USER_DELETE = 10000; + +const UINT COST_PERFMONMANIFEST_REGISTER = 1000; +const UINT COST_PERFMONMANIFEST_UNREGISTER = 1000; + +const UINT COST_EVENTMANIFEST_REGISTER = 1000; +const UINT COST_EVENTMANIFEST_UNREGISTER = 1000; + diff --git a/src/ext/Util/ca/scaexec.cpp b/src/ext/Util/ca/scaexec.cpp new file mode 100644 index 00000000..5845c1b4 --- /dev/null +++ b/src/ext/Util/ca/scaexec.cpp @@ -0,0 +1,1082 @@ +// Copyright (c) .NET 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" + + +/******************************************************************** + * CreateSmb - CUSTOM ACTION ENTRY POINT for creating fileshares + * + * Input: deferred CustomActionData - + * wzFsKey\twzShareDesc\twzFullPath\tfIntegratedAuth\twzUserName\tnPermissions\twzUserName\tnPermissions... + * + * ****************************************************************/ +extern "C" UINT __stdcall CreateSmb(MSIHANDLE hInstall) +{ +//AssertSz(0, "debug CreateSmb"); + UINT er = ERROR_SUCCESS; + HRESULT hr = S_OK; + + LPWSTR pwzData = NULL; + LPWSTR pwz = NULL; + LPWSTR pwzFsKey = NULL; + LPWSTR pwzShareDesc = NULL; + LPWSTR pwzDirectory = NULL; + int iAccessMode = 0; + DWORD nExPermissions = 0; + BOOL fIntegratedAuth; + LPWSTR pwzExUser = NULL; + SCA_SMBP ssp = {0}; + DWORD dwExUserPerms = 0; + DWORD dwCounter = 0; + SCA_SMBP_USER_PERMS* pUserPermsList = NULL; + + hr = WcaInitialize(hInstall, "CreateSmb"); + ExitOnFailure(hr, "failed to initialize"); + + hr = WcaGetProperty( L"CustomActionData", &pwzData); + ExitOnFailure(hr, "failed to get CustomActionData"); + + WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); + + pwz = pwzData; + hr = WcaReadStringFromCaData(&pwz, &pwzFsKey); // share name + ExitOnFailure(hr, "failed to read share name"); + hr = WcaReadStringFromCaData(&pwz, &pwzShareDesc); // share description + ExitOnFailure(hr, "failed to read share name"); + hr = WcaReadStringFromCaData(&pwz, &pwzDirectory); // full path to share + ExitOnFailure(hr, "failed to read share name"); + hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&fIntegratedAuth)); + ExitOnFailure(hr, "failed to read integrated authentication"); + + hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwExUserPerms)); + ExitOnFailure(hr, "failed to read count of permissions to set"); + if(dwExUserPerms > 0) + { + pUserPermsList = static_cast(MemAlloc(sizeof(SCA_SMBP_USER_PERMS)*dwExUserPerms, TRUE)); + ExitOnNull(pUserPermsList, hr, E_OUTOFMEMORY, "failed to allocate memory for permissions structure"); + + //Pull out all of the ExUserPerm strings + for (dwCounter = 0; dwCounter < dwExUserPerms; ++dwCounter) + { + hr = WcaReadStringFromCaData(&pwz, &pwzExUser); // user account + ExitOnFailure(hr, "failed to read user account"); + pUserPermsList[dwCounter].wzUser = pwzExUser; + pwzExUser = NULL; + + hr = WcaReadIntegerFromCaData(&pwz, &iAccessMode); + ExitOnFailure(hr, "failed to read access mode"); + pUserPermsList[dwCounter].accessMode = (ACCESS_MODE)iAccessMode; + iAccessMode = 0; + + hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&nExPermissions)); + ExitOnFailure(hr, "failed to read count of permissions"); + pUserPermsList[dwCounter].nPermissions = nExPermissions; + nExPermissions = 0; + } + } + + ssp.wzKey = pwzFsKey; + ssp.wzDescription = pwzShareDesc; + ssp.wzDirectory = pwzDirectory; + ssp.fUseIntegratedAuth = fIntegratedAuth; + ssp.dwUserPermissionCount = dwExUserPerms; + ssp.pUserPerms = pUserPermsList; + + hr = ScaEnsureSmbExists(&ssp); + MessageExitOnFailure(hr, msierrSMBFailedCreate, "failed to create share: '%ls'", pwzFsKey); + + hr = WcaProgressMessage(COST_SMB_CREATESMB, FALSE); + +LExit: + ReleaseStr(pwzFsKey); + ReleaseStr(pwzShareDesc); + ReleaseStr(pwzDirectory); + ReleaseStr(pwzData); + + if (pUserPermsList) + { + MemFree(pUserPermsList); + } + + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + return WcaFinalize(er); +} + + + +/******************************************************************** + DropSmb - CUSTOM ACTION ENTRY POINT for creating fileshares + + Input: deferred CustomActionData - wzFsKey\twzShareDesc\twzFullPath\tnPermissions\tfIntegratedAuth\twzUserName\twzPassword + + * ****************************************************************/ +extern "C" UINT __stdcall DropSmb(MSIHANDLE hInstall) +{ + //AssertSz(0, "debug DropSmb"); + UINT er = ERROR_SUCCESS; + HRESULT hr = S_OK; + + LPWSTR pwzData = NULL; + LPWSTR pwz = NULL; + LPWSTR pwzFsKey = NULL; + SCA_SMBP ssp = {0}; + + hr = WcaInitialize(hInstall, "DropSmb"); + ExitOnFailure(hr, "failed to initialize"); + + hr = WcaGetProperty( L"CustomActionData", &pwzData); + ExitOnFailure(hr, "failed to get CustomActionData"); + + WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); + + pwz = pwzData; + hr = WcaReadStringFromCaData(&pwz, &pwzFsKey); // share name + ExitOnFailure(hr, "failed to read share name"); + + ssp.wzKey = pwzFsKey; + + hr = ScaDropSmb(&ssp); + MessageExitOnFailure(hr, msierrSMBFailedDrop, "failed to delete share: '%ls'", pwzFsKey); + + hr = WcaProgressMessage(COST_SMB_DROPSMB, FALSE); + +LExit: + ReleaseStr(pwzFsKey); + ReleaseStr(pwzData); + + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + return WcaFinalize(er); +} + + +static HRESULT AddUserToGroup( + __in LPWSTR wzUser, + __in LPCWSTR wzUserDomain, + __in LPCWSTR wzGroup, + __in LPCWSTR wzGroupDomain + ) +{ + Assert(wzUser && *wzUser && wzUserDomain && wzGroup && *wzGroup && wzGroupDomain); + + HRESULT hr = S_OK; + IADsGroup *pGroup = NULL; + BSTR bstrUser = NULL; + BSTR bstrGroup = NULL; + LPCWSTR wz = NULL; + LPWSTR pwzUser = NULL; + LOCALGROUP_MEMBERS_INFO_3 lgmi; + + if (*wzGroupDomain) + { + wz = wzGroupDomain; + } + + // Try adding it to the global group first + UINT ui = ::NetGroupAddUser(wz, wzGroup, wzUser); + if (NERR_GroupNotFound == ui) + { + // Try adding it to the local group + if (wzUserDomain) + { + hr = StrAllocFormatted(&pwzUser, L"%s\\%s", wzUserDomain, wzUser); + ExitOnFailure(hr, "failed to allocate user domain string"); + } + + lgmi.lgrmi3_domainandname = (NULL == pwzUser ? wzUser : pwzUser); + ui = ::NetLocalGroupAddMembers(wz, wzGroup, 3 , reinterpret_cast(&lgmi), 1); + } + hr = HRESULT_FROM_WIN32(ui); + if (HRESULT_FROM_WIN32(ERROR_MEMBER_IN_ALIAS) == hr) // if they're already a member of the group don't report an error + hr = S_OK; + + // + // If we failed, try active directory + // + if (FAILED(hr)) + { + WcaLog(LOGMSG_VERBOSE, "Failed to add user: %ls, domain %ls to group: %ls, domain: %ls with error 0x%x. Attempting to use Active Directory", wzUser, wzUserDomain, wzGroup, wzGroupDomain, hr); + + hr = UserCreateADsPath(wzUserDomain, wzUser, &bstrUser); + ExitOnFailure(hr, "failed to create user ADsPath for user: %ls domain: %ls", wzUser, wzUserDomain); + + hr = UserCreateADsPath(wzGroupDomain, wzGroup, &bstrGroup); + ExitOnFailure(hr, "failed to create group ADsPath for group: %ls domain: %ls", wzGroup, wzGroupDomain); + + hr = ::ADsGetObject(bstrGroup,IID_IADsGroup, reinterpret_cast(&pGroup)); + ExitOnFailure(hr, "Failed to get group '%ls'.", reinterpret_cast(bstrGroup) ); + + hr = pGroup->Add(bstrUser); + if ((HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS) == hr) || (HRESULT_FROM_WIN32(ERROR_MEMBER_IN_ALIAS) == hr)) + hr = S_OK; + + ExitOnFailure(hr, "Failed to add user %ls to group '%ls'.", reinterpret_cast(bstrUser), reinterpret_cast(bstrGroup) ); + } + +LExit: + ReleaseObject(pGroup); + ReleaseBSTR(bstrUser); + ReleaseBSTR(bstrGroup); + + return hr; +} + +static HRESULT RemoveUserFromGroup( + __in LPWSTR wzUser, + __in LPCWSTR wzUserDomain, + __in LPCWSTR wzGroup, + __in LPCWSTR wzGroupDomain + ) +{ + Assert(wzUser && *wzUser && wzUserDomain && wzGroup && *wzGroup && wzGroupDomain); + + HRESULT hr = S_OK; + IADsGroup *pGroup = NULL; + BSTR bstrUser = NULL; + BSTR bstrGroup = NULL; + LPCWSTR wz = NULL; + LPWSTR pwzUser = NULL; + LOCALGROUP_MEMBERS_INFO_3 lgmi; + + if (*wzGroupDomain) + { + wz = wzGroupDomain; + } + + // Try removing it from the global group first + UINT ui = ::NetGroupDelUser(wz, wzGroup, wzUser); + if (NERR_GroupNotFound == ui) + { + // Try removing it from the local group + if (wzUserDomain) + { + hr = StrAllocFormatted(&pwzUser, L"%s\\%s", wzUserDomain, wzUser); + ExitOnFailure(hr, "failed to allocate user domain string"); + } + + lgmi.lgrmi3_domainandname = (NULL == pwzUser ? wzUser : pwzUser); + ui = ::NetLocalGroupDelMembers(wz, wzGroup, 3 , reinterpret_cast(&lgmi), 1); + } + hr = HRESULT_FROM_WIN32(ui); + + // + // If we failed, try active directory + // + if (FAILED(hr)) + { + WcaLog(LOGMSG_VERBOSE, "Failed to remove user: %ls, domain %ls from group: %ls, domain: %ls with error 0x%x. Attempting to use Active Directory", wzUser, wzUserDomain, wzGroup, wzGroupDomain, hr); + + hr = UserCreateADsPath(wzUserDomain, wzUser, &bstrUser); + ExitOnFailure(hr, "failed to create user ADsPath in order to remove user: %ls domain: %ls from a group", wzUser, wzUserDomain); + + hr = UserCreateADsPath(wzGroupDomain, wzGroup, &bstrGroup); + ExitOnFailure(hr, "failed to create group ADsPath in order to remove user from group: %ls domain: %ls", wzGroup, wzGroupDomain); + + hr = ::ADsGetObject(bstrGroup,IID_IADsGroup, reinterpret_cast(&pGroup)); + ExitOnFailure(hr, "Failed to get group '%ls'.", reinterpret_cast(bstrGroup) ); + + hr = pGroup->Remove(bstrUser); + ExitOnFailure(hr, "Failed to remove user %ls from group '%ls'.", reinterpret_cast(bstrUser), reinterpret_cast(bstrGroup) ); + } + +LExit: + ReleaseObject(pGroup); + ReleaseBSTR(bstrUser); + ReleaseBSTR(bstrGroup); + + return hr; +} + + +static HRESULT GetUserHasRight( + __in LSA_HANDLE hPolicy, + __in PSID pUserSid, + __in LPWSTR wzRight, + __out BOOL* fHasRight +) +{ + HRESULT hr = S_OK; + NTSTATUS nt = 0; + LSA_UNICODE_STRING lucPrivilege = { 0 }; + PLSA_ENUMERATION_INFORMATION rgSids = NULL; + ULONG cSids = 0; + *fHasRight = FALSE; + + lucPrivilege.Buffer = wzRight; + lucPrivilege.Length = static_cast(lstrlenW(lucPrivilege.Buffer) * sizeof(WCHAR)); + lucPrivilege.MaximumLength = (lucPrivilege.Length + 1) * sizeof(WCHAR); + + nt = ::LsaEnumerateAccountsWithUserRight(hPolicy, &lucPrivilege, reinterpret_cast(&rgSids), &cSids); + hr = HRESULT_FROM_WIN32(::LsaNtStatusToWinError(nt)); + ExitOnFailure(hr, "Failed to enumerate users for right: %ls", lucPrivilege.Buffer); + + for (DWORD i = 0; i < cSids; ++i) + { + PLSA_ENUMERATION_INFORMATION pInfo = rgSids + i; + if (::EqualSid(pUserSid, pInfo->Sid)) + { + *fHasRight = TRUE; + break; + } + } + +LExit: + if (rgSids) + { + ::LsaFreeMemory(rgSids); + } + + return hr; +} + + +static HRESULT GetExistingUserRightsAssignments( + __in_opt LPCWSTR wzDomain, + __in LPCWSTR wzName, + __inout int* iAttributes +) +{ + HRESULT hr = S_OK; + NTSTATUS nt = 0; + BOOL fHasRight = FALSE; + + LSA_HANDLE hPolicy = NULL; + LSA_OBJECT_ATTRIBUTES objectAttributes = { 0 }; + + LPWSTR pwzUser = NULL; + PSID psid = NULL; + + if (wzDomain && *wzDomain) + { + hr = StrAllocFormatted(&pwzUser, L"%s\\%s", wzDomain, wzName); + ExitOnFailure(hr, "Failed to allocate user with domain string"); + } + else + { + hr = StrAllocString(&pwzUser, wzName, 0); + ExitOnFailure(hr, "Failed to allocate string from user name."); + } + + hr = AclGetAccountSid(NULL, pwzUser, &psid); + ExitOnFailure(hr, "Failed to get SID for user: %ls", pwzUser); + + nt = ::LsaOpenPolicy(NULL, &objectAttributes, POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION, &hPolicy); + hr = HRESULT_FROM_WIN32(::LsaNtStatusToWinError(nt)); + ExitOnFailure(hr, "Failed to open LSA policy store"); + + hr = GetUserHasRight(hPolicy, psid, L"SeServiceLogonRight", &fHasRight); + ExitOnFailure(hr, "Failed to check LogonAsService right"); + + if (fHasRight) + { + *iAttributes |= SCAU_ALLOW_LOGON_AS_SERVICE; + } + + hr = GetUserHasRight(hPolicy, psid, L"SeBatchLogonRight", &fHasRight); + ExitOnFailure(hr, "Failed to check LogonAsBatchJob right"); + + if (fHasRight) + { + *iAttributes |= SCAU_ALLOW_LOGON_AS_BATCH; + } + +LExit: + if (hPolicy) + { + ::LsaClose(hPolicy); + } + + ReleaseSid(psid); + ReleaseStr(pwzUser); + return hr; +} + + +static HRESULT ModifyUserLocalServiceRight( + __in_opt LPCWSTR wzDomain, + __in LPCWSTR wzName, + __in BOOL fAdd + ) +{ + HRESULT hr = S_OK; + NTSTATUS nt = 0; + + LPWSTR pwzUser = NULL; + PSID psid = NULL; + LSA_HANDLE hPolicy = NULL; + LSA_OBJECT_ATTRIBUTES ObjectAttributes = { 0 }; + LSA_UNICODE_STRING lucPrivilege = { 0 }; + + if (wzDomain && *wzDomain) + { + hr = StrAllocFormatted(&pwzUser, L"%s\\%s", wzDomain, wzName); + ExitOnFailure(hr, "Failed to allocate user with domain string"); + } + else + { + hr = StrAllocString(&pwzUser, wzName, 0); + ExitOnFailure(hr, "Failed to allocate string from user name."); + } + + hr = AclGetAccountSid(NULL, pwzUser, &psid); + ExitOnFailure(hr, "Failed to get SID for user: %ls", pwzUser); + + nt = ::LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_ALL_ACCESS, &hPolicy); + hr = HRESULT_FROM_WIN32(::LsaNtStatusToWinError(nt)); + ExitOnFailure(hr, "Failed to open LSA policy store."); + + lucPrivilege.Buffer = L"SeServiceLogonRight"; + lucPrivilege.Length = static_cast(lstrlenW(lucPrivilege.Buffer) * sizeof(WCHAR)); + lucPrivilege.MaximumLength = (lucPrivilege.Length + 1) * sizeof(WCHAR); + + if (fAdd) + { + nt = ::LsaAddAccountRights(hPolicy, psid, &lucPrivilege, 1); + hr = HRESULT_FROM_WIN32(::LsaNtStatusToWinError(nt)); + ExitOnFailure(hr, "Failed to add 'logon as service' bit to user: %ls", pwzUser); + } + else + { + nt = ::LsaRemoveAccountRights(hPolicy, psid, FALSE, &lucPrivilege, 1); + hr = HRESULT_FROM_WIN32(::LsaNtStatusToWinError(nt)); + ExitOnFailure(hr, "Failed to remove 'logon as service' bit from user: %ls", pwzUser); + } + +LExit: + if (hPolicy) + { + ::LsaClose(hPolicy); + } + + ReleaseSid(psid); + ReleaseStr(pwzUser); + return hr; +} + + +static HRESULT ModifyUserLocalBatchRight( + __in_opt LPCWSTR wzDomain, + __in LPCWSTR wzName, + __in BOOL fAdd + ) +{ + HRESULT hr = S_OK; + NTSTATUS nt = 0; + + LPWSTR pwzUser = NULL; + PSID psid = NULL; + LSA_HANDLE hPolicy = NULL; + LSA_OBJECT_ATTRIBUTES ObjectAttributes = { 0 }; + LSA_UNICODE_STRING lucPrivilege = { 0 }; + + if (wzDomain && *wzDomain) + { + hr = StrAllocFormatted(&pwzUser, L"%s\\%s", wzDomain, wzName); + ExitOnFailure(hr, "Failed to allocate user with domain string"); + } + else + { + hr = StrAllocString(&pwzUser, wzName, 0); + ExitOnFailure(hr, "Failed to allocate string from user name."); + } + + hr = AclGetAccountSid(NULL, pwzUser, &psid); + ExitOnFailure(hr, "Failed to get SID for user: %ls", pwzUser); + + nt = ::LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_ALL_ACCESS, &hPolicy); + hr = HRESULT_FROM_WIN32(::LsaNtStatusToWinError(nt)); + ExitOnFailure(hr, "Failed to open LSA policy store."); + + lucPrivilege.Buffer = L"SeBatchLogonRight"; + lucPrivilege.Length = static_cast(lstrlenW(lucPrivilege.Buffer) * sizeof(WCHAR)); + lucPrivilege.MaximumLength = (lucPrivilege.Length + 1) * sizeof(WCHAR); + + if (fAdd) + { + nt = ::LsaAddAccountRights(hPolicy, psid, &lucPrivilege, 1); + hr = HRESULT_FROM_WIN32(::LsaNtStatusToWinError(nt)); + ExitOnFailure(hr, "Failed to add 'logon as batch job' bit to user: %ls", pwzUser); + } + else + { + nt = ::LsaRemoveAccountRights(hPolicy, psid, FALSE, &lucPrivilege, 1); + hr = HRESULT_FROM_WIN32(::LsaNtStatusToWinError(nt)); + ExitOnFailure(hr, "Failed to remove 'logon as batch job' bit from user: %ls", pwzUser); + } + + LExit: + if (hPolicy) + { + ::LsaClose(hPolicy); + } + + ReleaseSid(psid); + ReleaseStr(pwzUser); + return hr; +} + +static void SetUserPasswordAndAttributes( + __in USER_INFO_1* puserInfo, + __in LPWSTR wzPassword, + __in int iAttributes + ) +{ + Assert(puserInfo); + + // Set the User's password + puserInfo->usri1_password = wzPassword; + + // Apply the Attributes + if (SCAU_DONT_EXPIRE_PASSWRD & iAttributes) + { + puserInfo->usri1_flags |= UF_DONT_EXPIRE_PASSWD; + } + else + { + puserInfo->usri1_flags &= ~UF_DONT_EXPIRE_PASSWD; + } + + if (SCAU_PASSWD_CANT_CHANGE & iAttributes) + { + puserInfo->usri1_flags |= UF_PASSWD_CANT_CHANGE; + } + else + { + puserInfo->usri1_flags &= ~UF_PASSWD_CANT_CHANGE; + } + + if (SCAU_DISABLE_ACCOUNT & iAttributes) + { + puserInfo->usri1_flags |= UF_ACCOUNTDISABLE; + } + else + { + puserInfo->usri1_flags &= ~UF_ACCOUNTDISABLE; + } + + if (SCAU_PASSWD_CHANGE_REQD_ON_LOGIN & iAttributes) // TODO: for some reason this doesn't work + { + puserInfo->usri1_flags |= UF_PASSWORD_EXPIRED; + } + else + { + puserInfo->usri1_flags &= ~UF_PASSWORD_EXPIRED; + } +} + + +static HRESULT RemoveUserInternal( + LPWSTR wzGroupCaData, + LPWSTR wzDomain, + LPWSTR wzName, + int iAttributes +) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + LPWSTR pwz = NULL; + LPWSTR pwzGroup = NULL; + LPWSTR pwzGroupDomain = NULL; + LPCWSTR wz = NULL; + PDOMAIN_CONTROLLER_INFOW pDomainControllerInfo = NULL; + + // + // Remove the logon as service privilege. + // + if (SCAU_ALLOW_LOGON_AS_SERVICE & iAttributes) + { + hr = ModifyUserLocalServiceRight(wzDomain, wzName, FALSE); + if (FAILED(hr)) + { + WcaLogError(hr, "Failed to remove logon as service right from user, continuing..."); + hr = S_OK; + } + } + + if (SCAU_ALLOW_LOGON_AS_BATCH & iAttributes) + { + hr = ModifyUserLocalBatchRight(wzDomain, wzName, FALSE); + if (FAILED(hr)) + { + WcaLogError(hr, "Failed to remove logon as batch job right from user, continuing..."); + hr = S_OK; + } + } + + // + // Remove the User Account if the user was created by us. + // + if (!(SCAU_DONT_CREATE_USER & iAttributes)) + { + if (wzDomain && *wzDomain) + { + er = ::DsGetDcNameW(NULL, (LPCWSTR)wzDomain, NULL, NULL, NULL, &pDomainControllerInfo); + if (RPC_S_SERVER_UNAVAILABLE == er) + { + // MSDN says, if we get the above error code, try again with the "DS_FORCE_REDISCOVERY" flag + er = ::DsGetDcNameW(NULL, (LPCWSTR)wzDomain, NULL, NULL, DS_FORCE_REDISCOVERY, &pDomainControllerInfo); + } + if (ERROR_SUCCESS == er) + { + wz = pDomainControllerInfo->DomainControllerName + 2; //Add 2 so that we don't get the \\ prefix + } + else + { + wz = wzDomain; + } + } + + er = ::NetUserDel(wz, wzName); + if (NERR_UserNotFound == er) + { + er = NERR_Success; + } + ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "failed to delete user account: %ls", wzName); + } + else + { + // + // Remove the user from the groups + // + pwz = wzGroupCaData; + while (S_OK == (hr = WcaReadStringFromCaData(&pwz, &pwzGroup))) + { + hr = WcaReadStringFromCaData(&pwz, &pwzGroupDomain); + + if (FAILED(hr)) + { + WcaLogError(hr, "failed to get domain for group: %ls, continuing anyway.", pwzGroup); + } + else + { + hr = RemoveUserFromGroup(wzName, wzDomain, pwzGroup, pwzGroupDomain); + if (FAILED(hr)) + { + WcaLogError(hr, "failed to remove user: %ls from group %ls, continuing anyway.", wzName, pwzGroup); + } + } + } + + if (E_NOMOREITEMS == hr) // if there are no more items, all is well + { + hr = S_OK; + } + + ExitOnFailure(hr, "failed to get next group from which to remove user:%ls", wzName); + } + +LExit: + if (pDomainControllerInfo) + { + ::NetApiBufferFree(static_cast(pDomainControllerInfo)); + } + + return hr; +} + + +/******************************************************************** + CreateUser - CUSTOM ACTION ENTRY POINT for creating users + + Input: deferred CustomActionData - UserName\tDomain\tPassword\tAttributes\tGroupName\tDomain\tGroupName\tDomain... + * *****************************************************************/ +extern "C" UINT __stdcall CreateUser( + __in MSIHANDLE hInstall + ) +{ + //AssertSz(0, "Debug CreateUser"); + + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + LPWSTR pwzData = NULL; + LPWSTR pwz = NULL; + LPWSTR pwzName = NULL; + LPWSTR pwzDomain = NULL; + LPWSTR pwzScriptKey = NULL; + LPWSTR pwzPassword = NULL; + LPWSTR pwzGroup = NULL; + LPWSTR pwzGroupDomain = NULL; + PDOMAIN_CONTROLLER_INFOW pDomainControllerInfo = NULL; + int iAttributes = 0; + BOOL fInitializedCom = FALSE; + + WCA_CASCRIPT_HANDLE hRollbackScript = NULL; + int iOriginalAttributes = 0; + int iRollbackAttributes = 0; + + USER_INFO_1 userInfo; + USER_INFO_1* puserInfo = NULL; + DWORD dw; + LPCWSTR wz = NULL; + + hr = WcaInitialize(hInstall, "CreateUser"); + 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); + + // + // Read in the CustomActionData + // + pwz = pwzData; + hr = WcaReadStringFromCaData(&pwz, &pwzName); + ExitOnFailure(hr, "failed to read user name from custom action data"); + + hr = WcaReadStringFromCaData(&pwz, &pwzDomain); + ExitOnFailure(hr, "failed to read domain from custom action data"); + + hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); + ExitOnFailure(hr, "failed to read attributes from custom action data"); + + hr = WcaReadStringFromCaData(&pwz, &pwzScriptKey); + ExitOnFailure(hr, "failed to read encoding key from custom action data"); + + hr = WcaReadStringFromCaData(&pwz, &pwzPassword); + ExitOnFailure(hr, "failed to read password from custom action data"); + + // There is no rollback scheduled if the key is empty. + // Best effort to get original configuration and save it in the script so rollback can restore it. + if (*pwzScriptKey) + { + hr = WcaCaScriptCreate(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, FALSE, &hRollbackScript); + ExitOnFailure(hr, "Failed to open rollback CustomAction script."); + + iRollbackAttributes = 0; + hr = GetExistingUserRightsAssignments(pwzDomain, pwzName, &iOriginalAttributes); + if (FAILED(hr)) + { + WcaLogError(hr, "failed to get existing user rights: %ls, continuing anyway.", pwzName); + } + else + { + if (!(SCAU_ALLOW_LOGON_AS_SERVICE & iOriginalAttributes) && (SCAU_ALLOW_LOGON_AS_SERVICE & iAttributes)) + { + iRollbackAttributes |= SCAU_ALLOW_LOGON_AS_SERVICE; + } + if (!(SCAU_ALLOW_LOGON_AS_BATCH & iOriginalAttributes) && (SCAU_ALLOW_LOGON_AS_BATCH & iAttributes)) + { + iRollbackAttributes |= SCAU_ALLOW_LOGON_AS_BATCH; + } + } + + hr = WcaCaScriptWriteNumber(hRollbackScript, iRollbackAttributes); + ExitOnFailure(hr, "Failed to add data to rollback script."); + + // Nudge the system to get all our rollback data written to disk. + WcaCaScriptFlush(hRollbackScript); + } + + if (!(SCAU_DONT_CREATE_USER & iAttributes)) + { + ::ZeroMemory(&userInfo, sizeof(USER_INFO_1)); + userInfo.usri1_name = pwzName; + userInfo.usri1_priv = USER_PRIV_USER; + userInfo.usri1_flags = UF_SCRIPT; + userInfo.usri1_home_dir = NULL; + userInfo.usri1_comment = NULL; + userInfo.usri1_script_path = NULL; + + SetUserPasswordAndAttributes(&userInfo, pwzPassword, iAttributes); + + // + // Create the User + // + if (pwzDomain && *pwzDomain) + { + er = ::DsGetDcNameW( NULL, (LPCWSTR)pwzDomain, NULL, NULL, NULL, &pDomainControllerInfo ); + if (RPC_S_SERVER_UNAVAILABLE == er) + { + // MSDN says, if we get the above error code, try again with the "DS_FORCE_REDISCOVERY" flag + er = ::DsGetDcNameW( NULL, (LPCWSTR)pwzDomain, NULL, NULL, DS_FORCE_REDISCOVERY, &pDomainControllerInfo ); + } + if (ERROR_SUCCESS == er) + { + wz = pDomainControllerInfo->DomainControllerName + 2; //Add 2 so that we don't get the \\ prefix + } + else + { + wz = pwzDomain; + } + } + + er = ::NetUserAdd(wz, 1, reinterpret_cast(&userInfo), &dw); + if (NERR_UserExists == er) + { + if (SCAU_UPDATE_IF_EXISTS & iAttributes) + { + er = ::NetUserGetInfo(wz, pwzName, 1, reinterpret_cast(&puserInfo)); + if (NERR_Success == er) + { + // Change the existing user's password and attributes again then try + // to update user with this new data + SetUserPasswordAndAttributes(puserInfo, pwzPassword, iAttributes); + + er = ::NetUserSetInfo(wz, pwzName, 1, reinterpret_cast(puserInfo), &dw); + } + } + else if (!(SCAU_FAIL_IF_EXISTS & iAttributes)) + { + er = NERR_Success; + } + } + else if (NERR_PasswordTooShort == er || NERR_PasswordTooLong == er) + { + MessageExitOnFailure(hr = HRESULT_FROM_WIN32(er), msierrUSRFailedUserCreatePswd, "failed to create user: %ls due to invalid password.", pwzName); + } + MessageExitOnFailure(hr = HRESULT_FROM_WIN32(er), msierrUSRFailedUserCreate, "failed to create user: %ls", pwzName); + } + + if (SCAU_ALLOW_LOGON_AS_SERVICE & iAttributes) + { + hr = ModifyUserLocalServiceRight(pwzDomain, pwzName, TRUE); + MessageExitOnFailure(hr, msierrUSRFailedGrantLogonAsService, "Failed to grant logon as service rights to user: %ls", pwzName); + } + + if (SCAU_ALLOW_LOGON_AS_BATCH & iAttributes) + { + hr = ModifyUserLocalBatchRight(pwzDomain, pwzName, TRUE); + MessageExitOnFailure(hr, msierrUSRFailedGrantLogonAsService, "Failed to grant logon as batch job rights to user: %ls", pwzName); + } + + // + // Add the users to groups + // + while (S_OK == (hr = WcaReadStringFromCaData(&pwz, &pwzGroup))) + { + hr = WcaReadStringFromCaData(&pwz, &pwzGroupDomain); + ExitOnFailure(hr, "failed to get domain for group: %ls", pwzGroup); + + hr = AddUserToGroup(pwzName, pwzDomain, pwzGroup, pwzGroupDomain); + MessageExitOnFailure(hr, msierrUSRFailedUserGroupAdd, "failed to add user: %ls to group %ls", pwzName, pwzGroup); + } + if (E_NOMOREITEMS == hr) // if there are no more items, all is well + { + hr = S_OK; + } + ExitOnFailure(hr, "failed to get next group in which to include user:%ls", pwzName); + +LExit: + WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_PRESERVE); + + if (puserInfo) + { + ::NetApiBufferFree((LPVOID)puserInfo); + } + + if (pDomainControllerInfo) + { + ::NetApiBufferFree((LPVOID)pDomainControllerInfo); + } + + ReleaseStr(pwzData); + ReleaseStr(pwzName); + ReleaseStr(pwzDomain); + ReleaseStr(pwzScriptKey); + ReleaseStr(pwzPassword); + ReleaseStr(pwzGroup); + ReleaseStr(pwzGroupDomain); + + if (fInitializedCom) + { + ::CoUninitialize(); + } + + if (SCAU_NON_VITAL & iAttributes) + { + er = ERROR_SUCCESS; + } + else if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + + return WcaFinalize(er); +} + + +/******************************************************************** + CreateUserRollback - CUSTOM ACTION ENTRY POINT for CreateUser rollback + + * *****************************************************************/ +extern "C" UINT __stdcall CreateUserRollback( + MSIHANDLE hInstall +) +{ + //AssertSz(0, "Debug CreateUserRollback"); + + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + LPWSTR pwzData = NULL; + LPWSTR pwz = NULL; + LPWSTR pwzName = NULL; + LPWSTR pwzDomain = NULL; + LPWSTR pwzScriptKey = NULL; + int iAttributes = 0; + BOOL fInitializedCom = FALSE; + + WCA_CASCRIPT_HANDLE hRollbackScript = NULL; + LPWSTR pwzRollbackData = NULL; + int iOriginalAttributes = 0; + + hr = WcaInitialize(hInstall, "CreateUserRollback"); + 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); + + // + // Read in the CustomActionData + // + pwz = pwzData; + hr = WcaReadStringFromCaData(&pwz, &pwzScriptKey); + ExitOnFailure(hr, "failed to read encoding key from custom action data"); + + hr = WcaReadStringFromCaData(&pwz, &pwzName); + ExitOnFailure(hr, "failed to read name from custom action data"); + + hr = WcaReadStringFromCaData(&pwz, &pwzDomain); + ExitOnFailure(hr, "failed to read domain from custom action data"); + + hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); + ExitOnFailure(hr, "failed to read attributes from custom action data"); + + // Best effort to read original configuration from CreateUser. + hr = WcaCaScriptOpen(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, &hRollbackScript); + if (FAILED(hr)) + { + WcaLogError(hr, "Failed to open rollback CustomAction script, continuing anyway."); + } + else + { + hr = WcaCaScriptReadAsCustomActionData(hRollbackScript, &pwzRollbackData); + if (FAILED(hr)) + { + WcaLogError(hr, "Failed to read rollback script into CustomAction data, continuing anyway."); + } + else + { + WcaLog(LOGMSG_TRACEONLY, "Rollback Data: %ls", pwzRollbackData); + + pwz = pwzRollbackData; + hr = WcaReadIntegerFromCaData(&pwz, &iOriginalAttributes); + if (FAILED(hr)) + { + WcaLogError(hr, "failed to read attributes from rollback data, continuing anyway"); + } + else + { + iAttributes |= iOriginalAttributes; + } + } + } + + hr = RemoveUserInternal(pwz, pwzDomain, pwzName, iAttributes); + +LExit: + WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_DELETE); + + ReleaseStr(pwzData); + ReleaseStr(pwzName); + ReleaseStr(pwzDomain); + ReleaseStr(pwzScriptKey); + ReleaseStr(pwzRollbackData); + + if (fInitializedCom) + { + ::CoUninitialize(); + } + + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + + return WcaFinalize(er); +} + + +/******************************************************************** + RemoveUser - CUSTOM ACTION ENTRY POINT for removing users + + Input: deferred CustomActionData - Name\tDomain + * *****************************************************************/ +extern "C" UINT __stdcall RemoveUser( + MSIHANDLE hInstall +) +{ + //AssertSz(0, "Debug RemoveUser"); + + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + LPWSTR pwzData = NULL; + LPWSTR pwz = NULL; + LPWSTR pwzName = NULL; + LPWSTR pwzDomain = NULL; + int iAttributes = 0; + BOOL fInitializedCom = FALSE; + + hr = WcaInitialize(hInstall, "RemoveUser"); + 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); + + // + // Read in the CustomActionData + // + pwz = pwzData; + hr = WcaReadStringFromCaData(&pwz, &pwzName); + ExitOnFailure(hr, "failed to read name from custom action data"); + + hr = WcaReadStringFromCaData(&pwz, &pwzDomain); + ExitOnFailure(hr, "failed to read domain from custom action data"); + + hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); + ExitOnFailure(hr, "failed to read attributes from custom action data"); + + hr = RemoveUserInternal(pwz, pwzDomain, pwzName, iAttributes); + +LExit: + ReleaseStr(pwzData); + ReleaseStr(pwzName); + ReleaseStr(pwzDomain); + + if (fInitializedCom) + { + ::CoUninitialize(); + } + + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + + return WcaFinalize(er); +} diff --git a/src/ext/Util/ca/scamanifest.cpp b/src/ext/Util/ca/scamanifest.cpp new file mode 100644 index 00000000..adb8d3d3 --- /dev/null +++ b/src/ext/Util/ca/scamanifest.cpp @@ -0,0 +1,377 @@ +// Copyright (c) .NET 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 vcsPerfmonManifestQuery = L"SELECT `Component_`, `File`, `ResourceFileDirectory` FROM `Wix4PerfmonManifest`"; +LPCWSTR vcsEventManifestQuery = L"SELECT `Component_`, `File` FROM `Wix4EventManifest`"; +enum ePerfMonManifestQuery { pfmComponent = 1, pfmFile, pfmResourceFileDir }; +enum eEventManifestQuery { emComponent = 1, emFile}; + +BOOL IsVistaOrAbove() +{ + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + #pragma warning(suppress: 4996) //TODO: use non-deprecated function to check OS version + if (!::GetVersionEx(&osvi)) + { + return false; + } + return osvi.dwMajorVersion >= 6; +} + + +/******************************************************************** + ConfigurePerfmonManifestRegister - CUSTOM ACTION ENTRY POINT for scheduling + Perfmon counter manifest registering + +********************************************************************/ +extern "C" UINT __stdcall ConfigurePerfmonManifestRegister( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr; + UINT er = ERROR_SUCCESS; + + PMSIHANDLE hView, hRec; + LPWSTR pwzData = NULL, pwzResourceFilePath = NULL, pwzFile = NULL, pwzCommand = NULL; + INSTALLSTATE isInstalled, isAction; + + hr = WcaInitialize(hInstall, "ConfigurePerfmonManifestReg"); + ExitOnFailure(hr, "Failed to initialize"); + + if (!IsVistaOrAbove()) + { + WcaLog(LOGMSG_VERBOSE, "Skipping ConfigurePerfmonManifestRegister() because the target system does not support perfmon manifest"); + ExitFunction1(hr = S_FALSE); + } + // check to see if necessary tables are specified + if (S_OK != WcaTableExists(L"Wix4PerfmonManifest")) + { + WcaLog(LOGMSG_VERBOSE, "Skipping ConfigurePerfmonManifestRegister() because Wix4PerfmonManifest table not present"); + ExitFunction1(hr = S_FALSE); + } + + hr = WcaOpenExecuteView(vcsPerfmonManifestQuery, &hView); + ExitOnFailure(hr, "failed to open view on PerfMonManifest table"); + while ((hr = WcaFetchRecord(hView, &hRec)) == S_OK) + { + // get component install state + hr = WcaGetRecordString(hRec, pfmComponent, &pwzData); + ExitOnFailure(hr, "failed to get Component for PerfMonManifest"); + er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to get Component state for PerfMonManifest"); + if (!WcaIsInstalling(isInstalled, isAction)) + { + continue; + } + + hr = WcaGetRecordFormattedString(hRec, pfmFile, &pwzFile); + ExitOnFailure(hr, "failed to get File for PerfMonManifest"); + + hr = WcaGetRecordFormattedString(hRec, pfmResourceFileDir, &pwzResourceFilePath); + ExitOnFailure(hr, "failed to get ApplicationIdentity for PerfMonManifest"); + size_t iResourcePath = lstrlenW(pwzResourceFilePath); + if ( iResourcePath > 0 && *(pwzResourceFilePath + iResourcePath -1) == L'\\') + *(pwzResourceFilePath + iResourcePath -1) = 0; //remove the trailing '\' + + hr = StrAllocFormatted(&pwzCommand, L"\"unlodctr.exe\" /m:\"%s\"", pwzFile); + ExitOnFailure(hr, "failed to copy string in PerfMonManifest"); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackRegisterPerfmonManifest"), pwzCommand, COST_PERFMONMANIFEST_UNREGISTER); + ExitOnFailure(hr, "failed to schedule RollbackRegisterPerfmonManifest action"); + + if ( *pwzResourceFilePath ) + { + hr = StrAllocFormatted(&pwzCommand, L"\"lodctr.exe\" /m:\"%s\" \"%s\"", pwzFile, pwzResourceFilePath); + ExitOnFailure(hr, "failed to copy string in PerfMonManifest"); + } + else + { + hr = StrAllocFormatted(&pwzCommand, L"\"lodctr.exe\" /m:\"%s\"", pwzFile); + ExitOnFailure(hr, "failed to copy string in PerfMonManifest"); + } + + WcaLog(LOGMSG_VERBOSE, "RegisterPerfmonManifest's CustomActionData: '%ls'", pwzCommand); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RegisterPerfmonManifest"), pwzCommand, COST_PERFMONMANIFEST_REGISTER); + ExitOnFailure(hr, "failed to schedule RegisterPerfmonManifest action"); + } + + if (hr == E_NOMOREITEMS) + { + hr = S_OK; + } + ExitOnFailure(hr, "Failure while processing PerfMonManifest"); + + hr = S_OK; + +LExit: + ReleaseStr(pwzData); + ReleaseStr(pwzResourceFilePath); + ReleaseStr(pwzFile); + ReleaseStr(pwzCommand); + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + +/******************************************************************** + ConfigurePerfmonUninstall - CUSTOM ACTION ENTRY POINT for uninstalling + Perfmon counters + +********************************************************************/ +extern "C" UINT __stdcall ConfigurePerfmonManifestUnregister( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr; + UINT er = ERROR_SUCCESS; + + PMSIHANDLE hView, hRec; + LPWSTR pwzData = NULL, pwzResourceFilePath = NULL, pwzFile = NULL, pwzCommand = NULL; + INSTALLSTATE isInstalled, isAction; + + hr = WcaInitialize(hInstall, "ConfigurePerfmonManifestUnreg"); + ExitOnFailure(hr, "Failed to initialize"); + + if (!IsVistaOrAbove()) + { + WcaLog(LOGMSG_VERBOSE, "Skipping ConfigurePerfmonManifestUnregister() because the target system does not support perfmon manifest"); + ExitFunction1(hr = S_FALSE); + } + // check to see if necessary tables are specified + if (WcaTableExists(L"Wix4PerfmonManifest") != S_OK) + { + WcaLog(LOGMSG_VERBOSE, "Skipping ConfigurePerfmonManifestUnregister() because Wix4PerfmonManifest table not present"); + ExitFunction1(hr = S_FALSE); + } + + hr = WcaOpenExecuteView(vcsPerfmonManifestQuery, &hView); + ExitOnFailure(hr, "failed to open view on Wix4PerfmonManifest table"); + while ((hr = WcaFetchRecord(hView, &hRec)) == S_OK) + { + // get component install state + hr = WcaGetRecordString(hRec, pfmComponent, &pwzData); + ExitOnFailure(hr, "failed to get Component for Wix4PerfmonManifest"); + er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to get Component state for Wix4PerfmonManifest"); + if (!WcaIsUninstalling(isInstalled, isAction)) + { + continue; + } + + hr = WcaGetRecordFormattedString(hRec, pfmFile, &pwzFile); + ExitOnFailure(hr, "failed to get File for Wix4PerfmonManifest"); + + hr = WcaGetRecordFormattedString(hRec, pfmResourceFileDir, &pwzResourceFilePath); + ExitOnFailure(hr, "failed to get ApplicationIdentity for Wix4PerfmonManifest"); + size_t iResourcePath = lstrlenW(pwzResourceFilePath); + if ( iResourcePath > 0 && *(pwzResourceFilePath + iResourcePath -1) == L'\\') + *(pwzResourceFilePath + iResourcePath -1) = 0; //remove the trailing '\' + + hr = StrAllocFormatted(&pwzCommand, L"\"lodctr.exe\" /m:\"%s\" \"%s\"", pwzFile, pwzResourceFilePath); + ExitOnFailure(hr, "failed to copy string in Wix4PerfmonManifest"); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackUnregisterPerfmonManifest"), pwzCommand, COST_PERFMONMANIFEST_REGISTER); + ExitOnFailure(hr, "failed to schedule RollbackUnregisterPerfmonManifest action"); + + hr = StrAllocFormatted(&pwzCommand, L"\"unlodctr.exe\" /m:\"%s\"", pwzFile); + ExitOnFailure(hr, "failed to copy string in PerfMonManifest"); + + WcaLog(LOGMSG_VERBOSE, "UnRegisterPerfmonManifest's CustomActionData: '%ls'", pwzCommand); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"UnregisterPerfmonManifest"), pwzCommand, COST_PERFMONMANIFEST_UNREGISTER); + ExitOnFailure(hr, "failed to schedule UnregisterPerfmonManifest action"); + } + + if (hr == E_NOMOREITEMS) + { + hr = S_OK; + } + ExitOnFailure(hr, "Failure while processing PerfMonManifest"); + + hr = S_OK; + +LExit: + ReleaseStr(pwzData); + ReleaseStr(pwzResourceFilePath); + ReleaseStr(pwzFile); + ReleaseStr(pwzCommand); + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + +/******************************************************************** + ConfigureEventManifestRegister - CUSTOM ACTION ENTRY POINT for scheduling + Event manifest registering + +********************************************************************/ +extern "C" UINT __stdcall ConfigureEventManifestRegister( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr; + UINT er = ERROR_SUCCESS; + + PMSIHANDLE hView, hRec; + LPWSTR pwzData = NULL, pwzFile = NULL, pwzCommand = NULL; + INSTALLSTATE isInstalled, isAction; + + hr = WcaInitialize(hInstall, "ConfigureEventManifestReg"); + ExitOnFailure(hr, "Failed to initialize"); + + if (!IsVistaOrAbove()) + { + WcaLog(LOGMSG_VERBOSE, "Skipping ConfigureEventManifestRegister() because the target system does not support event manifest"); + ExitFunction1(hr = S_FALSE); + } + // check to see if necessary tables are specified + if (S_OK != WcaTableExists(L"Wix4EventManifest")) + { + WcaLog(LOGMSG_VERBOSE, "Skipping ConfigureEventManifestRegister() because Wix4EventManifest table not present"); + ExitFunction1(hr = S_FALSE); + } + + hr = WcaOpenExecuteView(vcsEventManifestQuery, &hView); + ExitOnFailure(hr, "failed to open view on Wix4EventManifest table"); + while ((hr = WcaFetchRecord(hView, &hRec)) == S_OK) + { + // get component install state + hr = WcaGetRecordString(hRec, emComponent, &pwzData); + ExitOnFailure(hr, "failed to get Component for Wix4EventManifest"); + er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to get Component state for Wix4EventManifest"); + if (!WcaIsInstalling(isInstalled, isAction)) + { + continue; + } + + hr = WcaGetRecordFormattedString(hRec, emFile, &pwzFile); + ExitOnFailure(hr, "failed to get File for Wix4EventManifest"); + + hr = StrAllocFormatted(&pwzCommand, L"\"wevtutil.exe\" um \"%s\"", pwzFile); + ExitOnFailure(hr, "failed to copy string in Wix4EventManifest"); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackRegisterEventManifest"), pwzCommand, COST_PERFMONMANIFEST_UNREGISTER); + ExitOnFailure(hr, "failed to schedule RollbackRegisterEventManifest action"); + + hr = StrAllocFormatted(&pwzCommand, L"\"wevtutil.exe\" im \"%s\"", pwzFile); + ExitOnFailure(hr, "failed to copy string in Wix4EventManifest"); + WcaLog(LOGMSG_VERBOSE, "RegisterEventManifest's CustomActionData: '%ls'", pwzCommand); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RegisterEventManifest"), pwzCommand, COST_EVENTMANIFEST_REGISTER); + ExitOnFailure(hr, "failed to schedule RegisterEventManifest action"); + } + + if (hr == E_NOMOREITEMS) + { + hr = S_OK; + } + ExitOnFailure(hr, "Failure while processing Wix4EventManifest"); + + hr = S_OK; + +LExit: + ReleaseStr(pwzData); + ReleaseStr(pwzFile); + ReleaseStr(pwzCommand); + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + + +/******************************************************************** + ConfigureEventManifestRegister - CUSTOM ACTION ENTRY POINT for scheduling + Event manifest registering + +********************************************************************/ +extern "C" UINT __stdcall ConfigureEventManifestUnregister( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr; + UINT er = ERROR_SUCCESS; + + PMSIHANDLE hView, hRec; + LPWSTR pwzData = NULL, pwzFile = NULL, pwzCommand = NULL; + INSTALLSTATE isInstalled, isAction; + + hr = WcaInitialize(hInstall, "ConfigureEventManifestUnreg"); + ExitOnFailure(hr, "Failed to initialize"); + + if (!IsVistaOrAbove()) + { + WcaLog(LOGMSG_VERBOSE, "Skipping ConfigureEventManifestUnregister() because the target system does not support event manifest"); + ExitFunction1(hr = S_FALSE); + } + // check to see if necessary tables are specified + if (S_OK != WcaTableExists(L"Wix4EventManifest")) + { + WcaLog(LOGMSG_VERBOSE, "Skipping ConfigureEventManifestUnregister() because Wix4EventManifest table not present"); + ExitFunction1(hr = S_FALSE); + } + + hr = WcaOpenExecuteView(vcsEventManifestQuery, &hView); + ExitOnFailure(hr, "failed to open view on Wix4EventManifest table"); + while ((hr = WcaFetchRecord(hView, &hRec)) == S_OK) + { + // get component install state + hr = WcaGetRecordString(hRec, emComponent, &pwzData); + ExitOnFailure(hr, "failed to get Component for Wix4EventManifest"); + er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to get Component state for Wix4EventManifest"); + + // nothing to do on an install + // schedule the rollback action when reinstalling to re-register pre-patch manifest + if (!WcaIsUninstalling(isInstalled, isAction) && !WcaIsReInstalling(isInstalled, isAction)) + { + continue; + } + + hr = WcaGetRecordFormattedString(hRec, emFile, &pwzFile); + ExitOnFailure(hr, "failed to get File for Wix4EventManifest"); + + hr = StrAllocFormatted(&pwzCommand, L"\"wevtutil.exe\" im \"%s\"", pwzFile); + ExitOnFailure(hr, "failed to copy string in Wix4EventManifest"); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackUnregisterEventManifest"), pwzCommand, COST_PERFMONMANIFEST_REGISTER); + ExitOnFailure(hr, "failed to schedule RollbackUnregisterEventManifest action"); + + // no need to uninstall on a repair/patch. Register action will re-register and update the manifest. + if (!WcaIsReInstalling(isInstalled, isAction)) + { + hr = StrAllocFormatted(&pwzCommand, L"\"wevtutil.exe\" um \"%s\"", pwzFile); + ExitOnFailure(hr, "failed to copy string in Wix4EventManifest"); + WcaLog(LOGMSG_VERBOSE, "UnregisterEventManifest's CustomActionData: '%ls'", pwzCommand); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"UnregisterEventManifest"), pwzCommand, COST_PERFMONMANIFEST_UNREGISTER); + ExitOnFailure(hr, "failed to schedule UnregisterEventManifest action"); + } + } + + if (hr == E_NOMOREITEMS) + { + hr = S_OK; + } + ExitOnFailure(hr, "Failure while processing Wix4EventManifest"); + + hr = S_OK; + +LExit: + ReleaseStr(pwzData); + ReleaseStr(pwzFile); + ReleaseStr(pwzCommand); + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + diff --git a/src/ext/Util/ca/scaperf.cpp b/src/ext/Util/ca/scaperf.cpp new file mode 100644 index 00000000..fd301278 --- /dev/null +++ b/src/ext/Util/ca/scaperf.cpp @@ -0,0 +1,310 @@ +// Copyright (c) .NET 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 vcsPerfCounterDataQuery = L"SELECT `Wix4PerformanceCategory`, `Component_`, `Name`, `IniData`, `ConstantData` FROM `Wix4PerformanceCategory`"; +enum ePerfCounterDataQuery { pcdqId = 1, pcdqComponent, pcdqName, pcdqIniData, pcdqConstantData }; + +LPCWSTR vcsPerfMonQuery = L"SELECT `Component_`, `File`, `Name` FROM `Wix4Perfmon`"; +enum ePerfMonQuery { pmqComponent = 1, pmqFile, pmqName }; + + +static HRESULT ProcessPerformanceCategory( + __in MSIHANDLE hInstall, + __in BOOL fInstall + ); + + +/******************************************************************** + InstallPerfCounterData - CUSTOM ACTION ENTRY POINT for installing + Performance Counters. + +********************************************************************/ +extern "C" UINT __stdcall InstallPerfCounterData( + __in MSIHANDLE hInstall + ) +{ + // AssertSz(FALSE, "debug InstallPerfCounterData{}"); + HRESULT hr; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "InstallPerfCounterData"); + ExitOnFailure(hr, "Failed to initialize InstallPerfCounterData."); + + hr = ProcessPerformanceCategory(hInstall, TRUE); + MessageExitOnFailure(hr, msierrInstallPerfCounterData, "Failed to process Wix4PerformanceCategory table."); + +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + +/******************************************************************** + UninstallPerfCounterData - CUSTOM ACTION ENTRY POINT for installing + Performance Counters. + +********************************************************************/ +extern "C" UINT __stdcall UninstallPerfCounterData( + __in MSIHANDLE hInstall + ) +{ + // AssertSz(FALSE, "debug UninstallPerfCounterData{}"); + HRESULT hr; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "UninstallPerfCounterData"); + ExitOnFailure(hr, "Failed to initialize UninstallPerfCounterData."); + + hr = ProcessPerformanceCategory(hInstall, FALSE); + MessageExitOnFailure(hr, msierrUninstallPerfCounterData, "Failed to process Wix4PerformanceCategory table."); + +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + +/******************************************************************** + RegisterPerfmon - CUSTOM ACTION ENTRY POINT for installing Perfmon counters + +********************************************************************/ +extern "C" UINT __stdcall ConfigurePerfmonInstall( + __in MSIHANDLE hInstall + ) +{ +// Assert(FALSE); + HRESULT hr; + UINT er = ERROR_SUCCESS; + + PMSIHANDLE hView, hRec; + LPWSTR pwzData = NULL, pwzName = NULL, pwzFile = NULL; + INSTALLSTATE isInstalled, isAction; + + hr = WcaInitialize(hInstall, "ConfigurePerfmonInstall"); + ExitOnFailure(hr, "Failed to initialize"); + + // check to see if necessary tables are specified + if (S_OK != WcaTableExists(L"Wix4Perfmon")) + { + WcaLog(LOGMSG_VERBOSE, "Skipping RegisterPerfmon() because Wix4Perfmon table not present"); + ExitFunction1(hr = S_FALSE); + } + + hr = WcaOpenExecuteView(vcsPerfMonQuery, &hView); + ExitOnFailure(hr, "failed to open view on PerfMon table"); + while ((hr = WcaFetchRecord(hView, &hRec)) == S_OK) + { + // get component install state + hr = WcaGetRecordString(hRec, pmqComponent, &pwzData); + ExitOnFailure(hr, "failed to get Component for PerfMon"); + er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to get Component state for PerfMon"); + if (!WcaIsInstalling(isInstalled, isAction)) + { + continue; + } + + hr = WcaGetRecordString(hRec, pmqName, &pwzName); + ExitOnFailure(hr, "failed to get Name for PerfMon"); + + hr = WcaGetRecordFormattedString(hRec, pmqFile, &pwzFile); + ExitOnFailure(hr, "failed to get File for PerfMon"); + + WcaLog(LOGMSG_VERBOSE, "ConfigurePerfmonInstall's CustomActionData: '%ls', '%ls'", pwzName, pwzFile); + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RegisterPerfmon"), pwzFile, COST_PERFMON_REGISTER); + ExitOnFailure(hr, "failed to schedule RegisterPerfmon action"); + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackRegisterPerfmon"), pwzName, COST_PERFMON_UNREGISTER); + ExitOnFailure(hr, "failed to schedule RollbackRegisterPerfmon action"); + } + + if (hr == E_NOMOREITEMS) + { + hr = S_OK; + } + ExitOnFailure(hr, "Failure while processing PerfMon"); + + hr = S_OK; + +LExit: + ReleaseStr(pwzData); + ReleaseStr(pwzName); + ReleaseStr(pwzFile); + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + +/******************************************************************** + ConfigurePerfmonUninstall - CUSTOM ACTION ENTRY POINT for uninstalling + Perfmon counters + +********************************************************************/ +extern "C" UINT __stdcall ConfigurePerfmonUninstall( + __in MSIHANDLE hInstall + ) +{ +// Assert(FALSE); + HRESULT hr; + UINT er = ERROR_SUCCESS; + + PMSIHANDLE hView, hRec; + LPWSTR pwzData = NULL, pwzName = NULL, pwzFile = NULL; + INSTALLSTATE isInstalled, isAction; + + hr = WcaInitialize(hInstall, "ConfigurePerfmonUninstall"); + ExitOnFailure(hr, "Failed to initialize"); + + // check to see if necessary tables are specified + if (WcaTableExists(L"Wix4Perfmon") != S_OK) + { + WcaLog(LOGMSG_VERBOSE, "Skipping UnregisterPerfmon() because Wix4Perfmon table not present"); + ExitFunction1(hr = S_FALSE); + } + + hr = WcaOpenExecuteView(vcsPerfMonQuery, &hView); + ExitOnFailure(hr, "failed to open view on PerfMon table"); + while ((hr = WcaFetchRecord(hView, &hRec)) == S_OK) + { + // get component install state + hr = WcaGetRecordString(hRec, pmqComponent, &pwzData); + ExitOnFailure(hr, "failed to get Component for PerfMon"); + er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to get Component state for PerfMon"); + if (!WcaIsUninstalling(isInstalled, isAction)) + { + continue; + } + + hr = WcaGetRecordString(hRec, pmqName, &pwzName); + ExitOnFailure(hr, "failed to get Name for PerfMon"); + + hr = WcaGetRecordFormattedString(hRec, pmqFile, &pwzFile); + ExitOnFailure(hr, "failed to get File for PerfMon"); + + WcaLog(LOGMSG_VERBOSE, "ConfigurePerfmonUninstall's CustomActionData: '%ls', '%ls'", pwzName, pwzFile); + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"UnregisterPerfmon"), pwzName, COST_PERFMON_UNREGISTER); + ExitOnFailure(hr, "failed to schedule UnregisterPerfmon action"); + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackUnregisterPerfmon"), pwzFile, COST_PERFMON_REGISTER); + ExitOnFailure(hr, "failed to schedule RollbackUnregisterPerfmon action"); + } + + if (hr == E_NOMOREITEMS) + { + hr = S_OK; + } + ExitOnFailure(hr, "Failure while processing PerfMon"); + + hr = S_OK; + +LExit: + ReleaseStr(pwzData); + ReleaseStr(pwzName); + ReleaseStr(pwzFile); + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + + +static HRESULT ProcessPerformanceCategory( + __in MSIHANDLE hInstall, + __in BOOL fInstall + ) +{ + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + + PMSIHANDLE hView, hRec; + LPWSTR pwzId = NULL; + LPWSTR pwzComponent = NULL; + LPWSTR pwzName = NULL; + LPWSTR pwzData = NULL; + INSTALLSTATE isInstalled, isAction; + + LPWSTR pwzCustomActionData = NULL; + + // check to see if necessary tables are specified + if (S_OK != WcaTableExists(L"Wix4PerformanceCategory")) + { + ExitFunction1(hr = S_FALSE); + } + + hr = WcaOpenExecuteView(vcsPerfCounterDataQuery, &hView); + ExitOnFailure(hr, "failed to open view on Wix4PerformanceCategory table"); + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + hr = WcaGetRecordString(hRec, pcdqId, &pwzId); + ExitOnFailure(hr, "Failed to get id for Wix4PerformanceCategory."); + + // Check to see if the Component is being installed or uninstalled + // when we are processing the same. + hr = WcaGetRecordString(hRec, pcdqComponent, &pwzComponent); + ExitOnFailure(hr, "Failed to get Component for Wix4PerformanceCategory: %ls", pwzId); + + er = ::MsiGetComponentStateW(hInstall, pwzComponent, &isInstalled, &isAction); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed to get Component state for Wix4PerformanceCategory: %ls", pwzId); + + if ((fInstall && !WcaIsInstalling(isInstalled, isAction)) || + (!fInstall && !WcaIsUninstalling(isInstalled, isAction))) + { + continue; + } + + hr = WcaGetRecordString(hRec, pcdqName, &pwzName); + ExitOnFailure(hr, "Failed to get Name for Wix4PerformanceCategory: %ls", pwzId); + hr = WcaWriteStringToCaData(pwzName, &pwzCustomActionData); + ExitOnFailure(hr, "Failed to add Name to CustomActionData for Wix4PerformanceCategory: %ls", pwzId); + + hr = WcaGetRecordString(hRec, pcdqIniData, &pwzData); + ExitOnFailure(hr, "Failed to get IniData for Wix4PerformanceCategory: %ls", pwzId); + hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); + ExitOnFailure(hr, "Failed to add IniData to CustomActionData for Wix4PerformanceCategory: %ls", pwzId); + + hr = WcaGetRecordString(hRec, pcdqConstantData, &pwzData); + ExitOnFailure(hr, "Failed to get ConstantData for Wix4PerformanceCategory: %ls", pwzId); + hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); + ExitOnFailure(hr, "Failed to add ConstantData to CustomActionData for Wix4PerformanceCategory: %ls", pwzId); + } + + if (hr == E_NOMOREITEMS) + { + hr = S_OK; + } + ExitOnFailure(hr, "Failure while processing Wix4PerformanceCategory table."); + + // If there was any data built up, schedule it for execution. + if (pwzCustomActionData) + { + if (fInstall) + { + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackRegisterPerfCounterData"), pwzCustomActionData, COST_PERFMON_UNREGISTER); + ExitOnFailure(hr, "Failed to schedule RollbackRegisterPerfCounterData action for Wix4PerformanceCategory: %ls", pwzId); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RegisterPerfCounterData"), pwzCustomActionData, COST_PERFMON_REGISTER); + ExitOnFailure(hr, "Failed to schedule RegisterPerfCounterData action for Wix4PerformanceCategory: %ls", pwzId); + } + else + { + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackUnregisterPerfCounterData"), pwzCustomActionData, COST_PERFMON_REGISTER); + ExitOnFailure(hr, "Failed to schedule RollbackUnregisterPerfCounterData action for Wix4PerformanceCategory: %ls", pwzId); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"UnregisterPerfCounterData"), pwzCustomActionData, COST_PERFMON_UNREGISTER); + ExitOnFailure(hr, "Failed to schedule UnregisterPerfCounterData action for Wix4PerformanceCategory: %ls", pwzId); + } + } + +LExit: + ReleaseStr(pwzCustomActionData); + ReleaseStr(pwzData); + ReleaseStr(pwzName); + ReleaseStr(pwzComponent); + ReleaseStr(pwzId); + + return hr; +} diff --git a/src/ext/Util/ca/scaperfexec.cpp b/src/ext/Util/ca/scaperfexec.cpp new file mode 100644 index 00000000..c5425754 --- /dev/null +++ b/src/ext/Util/ca/scaperfexec.cpp @@ -0,0 +1,423 @@ +// Copyright (c) .NET 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" + +typedef DWORD (STDAPICALLTYPE *PFNPERFCOUNTERTEXTSTRINGS)(LPWSTR lpCommandLine, BOOL bQuietModeArg); + +static HRESULT ExecutePerfCounterData( + __in MSIHANDLE hInstall, + __in BOOL fInstall + ); +static HRESULT CreateDataFile( + __in LPCWSTR wzTempFolder, + __in LPCWSTR wzData, + __in BOOL fIniData, + __out HANDLE *phFile, + __out_opt LPWSTR *ppwzFile + ); + + +/******************************************************************** + RegisterPerfCounterData - CUSTOM ACTION ENTRY POINT for registering + performance counters + + Input: deferred CustomActionData: wzName\twzIniData\twzConstantData\twzName\twzIniData\twzConstantData\t... +*******************************************************************/ +extern "C" UINT __stdcall RegisterPerfCounterData( + __in MSIHANDLE hInstall + ) +{ + // AssertSz(FALSE, "debug RegisterPerfCounterData()"); + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "RegisterPerfCounterData"); + ExitOnFailure(hr, "Failed to initialize RegisterPerfCounterData."); + + hr = ExecutePerfCounterData(hInstall, TRUE); + MessageExitOnFailure(hr, msierrInstallPerfCounterData, "Failed to execute Wix4PerformanceCategory table."); + +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + +/******************************************************************** + UnregisterPerfCounterData - CUSTOM ACTION ENTRY POINT for registering + performance counters + + Input: deferred CustomActionData: wzName\twzIniData\twzConstantData\twzName\twzIniData\twzConstantData\t... +*******************************************************************/ +extern "C" UINT __stdcall UnregisterPerfCounterData( + __in MSIHANDLE hInstall + ) +{ + // AssertSz(FALSE, "debug UnregisterPerfCounterData()"); + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "UnregisterPerfCounterData"); + ExitOnFailure(hr, "Failed to initialize UnregisterPerfCounterData."); + + hr = ExecutePerfCounterData(hInstall, FALSE); + MessageExitOnFailure(hr, msierrUninstallPerfCounterData, "Failed to execute Wix4PerformanceCategory table."); + +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + +/******************************************************************** + RegisterPerfmon - CUSTOM ACTION ENTRY POINT for registering + counters + + Input: deferred CustomActionData - + wzFile or wzName +*******************************************************************/ +extern "C" UINT __stdcall RegisterPerfmon( + __in MSIHANDLE hInstall + ) +{ +// Assert(FALSE); + UINT er = ERROR_SUCCESS; + HRESULT hr = S_OK; + LPWSTR pwzData = NULL; + + HMODULE hMod = NULL; + PFNPERFCOUNTERTEXTSTRINGS pfnPerfCounterTextString; + DWORD dwRet; + LPWSTR pwzShortPath = NULL; + DWORD cchShortPath = MAX_PATH; + DWORD cchShortPathLength = 0; + + LPWSTR pwzCommand = NULL; + + hr = WcaInitialize(hInstall, "RegisterPerfmon"); + ExitOnFailure(hr, "failed to initialize"); + + hr = WcaGetProperty(L"CustomActionData", &pwzData); + ExitOnFailure(hr, "failed to get CustomActionData"); + + WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); + + // do the perfmon registration + if (NULL == hMod) + { + hr = LoadSystemLibrary(L"loadperf.dll", &hMod); + } + ExitOnFailure(hr, "failed to load DLL for PerfMon"); + + pfnPerfCounterTextString = (PFNPERFCOUNTERTEXTSTRINGS)::GetProcAddress(hMod, "LoadPerfCounterTextStringsW"); + ExitOnNullWithLastError(pfnPerfCounterTextString, hr, "failed to get DLL function for PerfMon"); + + hr = StrAlloc(&pwzShortPath, cchShortPath); + ExitOnFailure(hr, "failed to allocate string"); + + WcaLog(LOGMSG_VERBOSE, "Converting DLL path to short format: %ls", pwzData); + cchShortPathLength = ::GetShortPathNameW(pwzData, pwzShortPath, cchShortPath); + if (cchShortPathLength > cchShortPath) + { + cchShortPath = cchShortPathLength + 1; + hr = StrAlloc(&pwzShortPath, cchShortPath); + ExitOnFailure(hr, "failed to allocate string"); + + cchShortPathLength = ::GetShortPathNameW(pwzData, pwzShortPath, cchShortPath); + } + + if (0 == cchShortPathLength) + { + ExitOnLastError(hr, "failed to get short path format of path: %ls", pwzData); + } + + hr = StrAllocFormatted(&pwzCommand, L"lodctr \"%s\"", pwzShortPath); + ExitOnFailure(hr, "failed to format lodctr string"); + + WcaLog(LOGMSG_VERBOSE, "RegisterPerfmon running command: '%ls'", pwzCommand); + dwRet = (*pfnPerfCounterTextString)(pwzCommand, TRUE); + if (dwRet != ERROR_SUCCESS && dwRet != ERROR_ALREADY_EXISTS) + { + hr = HRESULT_FROM_WIN32(dwRet); + MessageExitOnFailure(hr, msierrPERFMONFailedRegisterDLL, "failed to register with PerfMon, DLL: %ls", pwzData); + } + + hr = S_OK; +LExit: + ReleaseStr(pwzData); + + if (FAILED(hr)) + er = ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + +extern "C" UINT __stdcall UnregisterPerfmon( + __in MSIHANDLE hInstall + ) +{ +// Assert(FALSE); + UINT er = ERROR_SUCCESS; + HRESULT hr = S_OK; + LPWSTR pwzData = NULL; + + HMODULE hMod = NULL; + PFNPERFCOUNTERTEXTSTRINGS pfnPerfCounterTextString; + DWORD dwRet; + WCHAR wz[255]; + + hr = WcaInitialize(hInstall, "UnregisterPerfmon"); + ExitOnFailure(hr, "failed to initialize"); + + hr = WcaGetProperty(L"CustomActionData", &pwzData); + ExitOnFailure(hr, "failed to get CustomActionData"); + + WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); + + // do the perfmon unregistration + hr = E_FAIL; + if (hMod == NULL) + { + hr = LoadSystemLibrary(L"loadperf.dll", &hMod); + } + ExitOnFailure(hr, "failed to load DLL for PerfMon"); + + pfnPerfCounterTextString = (PFNPERFCOUNTERTEXTSTRINGS)::GetProcAddress(hMod, "UnloadPerfCounterTextStringsW"); + ExitOnNullWithLastError(pfnPerfCounterTextString, hr, "failed to get DLL function for PerfMon"); + + hr = ::StringCchPrintfW(wz, countof(wz), L"unlodctr \"%s\"", pwzData); + ExitOnFailure(hr, "Failed to format unlodctr string with: %ls", pwzData); + WcaLog(LOGMSG_VERBOSE, "UnregisterPerfmon running command: '%ls'", wz); + dwRet = (*pfnPerfCounterTextString)(wz, TRUE); + // if the counters aren't registered, then OK to continue + if (dwRet != ERROR_SUCCESS && dwRet != ERROR_FILE_NOT_FOUND && dwRet != ERROR_BADKEY) + { + hr = HRESULT_FROM_WIN32(dwRet); + MessageExitOnFailure(hr, msierrPERFMONFailedUnregisterDLL, "failed to unregsister with PerfMon, DLL: %ls", pwzData); + } + + hr = S_OK; +LExit: + ReleaseStr(pwzData); + + if (FAILED(hr)) + er = ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + +static HRESULT ExecutePerfCounterData( + __in MSIHANDLE /*hInstall*/, + __in BOOL fInstall + ) +{ + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + + HMODULE hModule = NULL; + PFNPERFCOUNTERTEXTSTRINGS pfnPerfCounterTextString = NULL; + LPCWSTR wzPrefix = NULL; + + LPWSTR pwzCustomActionData = NULL; + LPWSTR pwz = NULL; + + LPWSTR pwzName = NULL; + LPWSTR pwzIniData = NULL; + LPWSTR pwzConstantData = NULL; + LPWSTR pwzTempFolder = NULL; + LPWSTR pwzIniFile = NULL; + LPWSTR pwzExecute = NULL; + + HANDLE hIniData = INVALID_HANDLE_VALUE; + HANDLE hConstantData = INVALID_HANDLE_VALUE; + + // Load the system performance counter helper DLL then get the appropriate + // entrypoint out of it. Fortunately, they have the same signature so we + // can use one function pointer to point to both. + hr = LoadSystemLibrary(L"loadperf.dll", &hModule); + ExitOnFailure(hr, "failed to load DLL for PerfMon"); + + if (fInstall) + { + wzPrefix = L"lodctr"; + pfnPerfCounterTextString = (PFNPERFCOUNTERTEXTSTRINGS)::GetProcAddress(hModule, "LoadPerfCounterTextStringsW"); + } + else + { + wzPrefix = L"unlodctr"; + pfnPerfCounterTextString = (PFNPERFCOUNTERTEXTSTRINGS)::GetProcAddress(hModule, "UnloadPerfCounterTextStringsW"); + } + ExitOnNullWithLastError(pfnPerfCounterTextString, hr, "Failed to get DLL function for PerfMon"); + + // Now get the CustomActionData and execute it. + hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); + ExitOnFailure(hr, "Failed to get CustomActionData."); + + WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); + + pwz = pwzCustomActionData; + + while (S_OK == (hr = WcaReadStringFromCaData(&pwz, &pwzName))) + { + hr = WcaReadStringFromCaData(&pwz, &pwzIniData); + ExitOnFailure(hr, "Failed to read IniData from custom action data."); + + hr = WcaReadStringFromCaData(&pwz, &pwzConstantData); + ExitOnFailure(hr, "Failed to read ConstantData from custom action data."); + + if (fInstall) + { + hr = PathCreateTempDirectory(NULL, L"WIXPF%03x", 999, &pwzTempFolder); + ExitOnFailure(hr, "Failed to create temp directory."); + + hr = CreateDataFile(pwzTempFolder, pwzIniData, TRUE, &hIniData, &pwzIniFile); + ExitOnFailure(hr, "Failed to create .ini file for performance counter category: %ls", pwzName); + + hr = CreateDataFile(pwzTempFolder, pwzConstantData, FALSE, &hConstantData, NULL); + ExitOnFailure(hr, "Failed to create .h file for performance counter category: %ls", pwzName); + + hr = StrAllocFormatted(&pwzExecute, L"%s \"%s\"", wzPrefix, pwzIniFile); + ExitOnFailure(hr, "Failed to allocate string to execute."); + + // Execute the install. + er = (*pfnPerfCounterTextString)(pwzExecute, TRUE); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed to execute install of performance counter category: %ls", pwzName); + + if (INVALID_HANDLE_VALUE != hIniData) + { + ::CloseHandle(hIniData); + hIniData = INVALID_HANDLE_VALUE; + } + + if (INVALID_HANDLE_VALUE != hConstantData) + { + ::CloseHandle(hConstantData); + hConstantData = INVALID_HANDLE_VALUE; + } + + DirEnsureDelete(pwzTempFolder, TRUE, TRUE); + } + else + { + hr = StrAllocFormatted(&pwzExecute, L"%s \"%s\"", wzPrefix, pwzName); + ExitOnFailure(hr, "Failed to allocate string to execute."); + + // Execute the uninstall and if the counter isn't registered then ignore + // the error since it won't hurt anything. + er = (*pfnPerfCounterTextString)(pwzExecute, TRUE); + if (ERROR_FILE_NOT_FOUND == er || ERROR_BADKEY == er) + { + er = ERROR_SUCCESS; + } + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed to execute uninstall of performance counter category: %ls", pwzName); + } + } + + if (E_NOMOREITEMS == hr) // If there are no more items, all is well + { + hr = S_OK; + } + ExitOnFailure(hr, "Failed to execute all perf counter data."); + + hr = S_OK; + +LExit: + if (INVALID_HANDLE_VALUE != hIniData) + { + ::CloseHandle(hIniData); + } + + if (INVALID_HANDLE_VALUE != hConstantData) + { + ::CloseHandle(hConstantData); + } + + ReleaseStr(pwzExecute); + ReleaseStr(pwzIniFile); + ReleaseStr(pwzTempFolder); + ReleaseStr(pwzConstantData); + ReleaseStr(pwzIniData); + ReleaseStr(pwzName); + ReleaseStr(pwzCustomActionData); + + if (hModule) + { + ::FreeLibrary(hModule); + } + + return hr; +} + + +static HRESULT CreateDataFile( + __in LPCWSTR wzTempFolder, + __in LPCWSTR wzData, + __in BOOL fIniData, + __out HANDLE *phFile, + __out_opt LPWSTR *ppwzFile + ) +{ + HRESULT hr = S_OK; + HANDLE hFile = INVALID_HANDLE_VALUE; + LPWSTR pwzFile = NULL; + LPSTR pszData = NULL; + DWORD cbData = 0; + DWORD cbWritten = 0; + + // Convert the data to UTF-8 because lodctr/unloctr + // doesn't like unicode. + hr = StrAnsiAllocString(&pszData, wzData, 0, CP_UTF8); + ExitOnFailure(hr, "Failed to covert data to ANSI."); + + cbData = lstrlenA(pszData); + + // Concatenate the paths together, open the file data file + // and dump the data in there. + hr = StrAllocString(&pwzFile, wzTempFolder, 0); + ExitOnFailure(hr, "Failed to copy temp directory name."); + + hr = StrAllocConcat(&pwzFile, L"wixperf", 0); + ExitOnFailure(hr, "Failed to add name of file."); + + hr = StrAllocConcat(&pwzFile, fIniData ? L".ini" : L".h", 0); + ExitOnFailure(hr, "Failed to add extension of file."); + + hFile = ::CreateFileW(pwzFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (INVALID_HANDLE_VALUE == hFile) + { + ExitWithLastError(hr, "Failed to open new temp file: %ls", pwzFile); + } + + if (!::WriteFile(hFile, pszData, cbData, &cbWritten, NULL)) + { + ExitWithLastError(hr, "Failed to write data to new temp file: %ls", pwzFile); + } + + if (INVALID_HANDLE_VALUE != hFile) + { + ::CloseHandle(hFile); + hFile = INVALID_HANDLE_VALUE; + } + + // Return the requested values. + *phFile = hFile; + hFile = INVALID_HANDLE_VALUE; + + if (ppwzFile) + { + *ppwzFile = pwzFile; + pwzFile = NULL; + } + +LExit: + if (INVALID_HANDLE_VALUE != hFile) + { + ::CloseHandle(hFile); + } + ReleaseStr(pszData); + ReleaseStr(pwzFile); + + return hr; +} diff --git a/src/ext/Util/ca/scasched.cpp b/src/ext/Util/ca/scasched.cpp new file mode 100644 index 00000000..d81b1f14 --- /dev/null +++ b/src/ext/Util/ca/scasched.cpp @@ -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. + +#include "precomp.h" + + +/******************************************************************** +ConfigureSmb - CUSTOM ACTION ENTRY POINT for installing fileshare settings + +********************************************************************/ +extern "C" UINT __stdcall ConfigureSmbInstall( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + SCA_SMB* pssList = NULL; + + // initialize + hr = WcaInitialize(hInstall, "ConfigureSmbInstall"); + ExitOnFailure(hr, "Failed to initialize"); + + // check to see if necessary tables are specified + if (WcaTableExists(L"Wix4FileShare") != S_OK) + { + WcaLog(LOGMSG_VERBOSE, "Skipping SMB CustomAction, no Wix4FileShare table"); + ExitFunction1(hr = S_FALSE); + } + + hr = ScaSmbRead(&pssList); + ExitOnFailure(hr, "failed to read Wix4FileShare table"); + + hr = ScaSmbInstall(pssList); + ExitOnFailure(hr, "failed to install FileShares"); + +LExit: + if (pssList) + ScaSmbFreeList(pssList); + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + +/******************************************************************** +ConfigureSmb - CUSTOM ACTION ENTRY POINT for uninstalling fileshare settings + +********************************************************************/ +extern "C" UINT __stdcall ConfigureSmbUninstall( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + SCA_SMB* pssList = NULL; + + // initialize + hr = WcaInitialize(hInstall, "ConfigureSmbUninstall"); + ExitOnFailure(hr, "Failed to initialize"); + + // check to see if necessary tables are specified + if (WcaTableExists(L"Wix4FileShare") != S_OK) + { + WcaLog(LOGMSG_VERBOSE, "Skipping SMB CustomAction, no Wix4FileShare table"); + ExitFunction1(hr = S_FALSE); + } + + hr = ScaSmbRead(&pssList); + ExitOnFailure(hr, "failed to read Wix4FileShare table"); + + hr = ScaSmbUninstall(pssList); + ExitOnFailure(hr, "failed to uninstall FileShares"); + +LExit: + if (pssList) + ScaSmbFreeList(pssList); + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + +/******************************************************************** +ConfigureUsers - CUSTOM ACTION ENTRY POINT for installing users + +********************************************************************/ +extern "C" UINT __stdcall ConfigureUsers( + __in MSIHANDLE hInstall + ) +{ + //AssertSz(0, "Debug ConfigureUsers"); + + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + BOOL fInitializedCom = FALSE; + SCA_USER* psuList = NULL; + + // initialize + hr = WcaInitialize(hInstall, "ConfigureUsers"); + ExitOnFailure(hr, "Failed to initialize"); + + hr = ::CoInitialize(NULL); + ExitOnFailure(hr, "failed to initialize COM"); + fInitializedCom = TRUE; + + hr = ScaUserRead(&psuList); + ExitOnFailure(hr, "failed to read Wix4User table"); + + hr = ScaUserExecute(psuList); + ExitOnFailure(hr, "failed to add/remove User actions"); + +LExit: + if (psuList) + { + ScaUserFreeList(psuList); + } + + if (fInitializedCom) + { + ::CoUninitialize(); + } + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} \ No newline at end of file diff --git a/src/ext/Util/ca/scasmb.h b/src/ext/Util/ca/scasmb.h new file mode 100644 index 00000000..f2a4b53c --- /dev/null +++ b/src/ext/Util/ca/scasmb.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 "scauser.h" + +// structs +// Structure used to hold and extra user/permission pairs from the Wix4FileSharePermissions Table +struct SCA_SMB_EX_USER_PERMS +{ + int nPermissions; + ACCESS_MODE accessMode; + SCA_USER scau; + SCA_SMB_EX_USER_PERMS* pExUserPermsNext; +}; + +struct SCA_SMB // hungarian ss +{ + WCHAR wzId[MAX_DARWIN_KEY + 1]; + WCHAR wzShareName[MAX_DARWIN_KEY + 1]; + WCHAR wzDescription[MAX_DARWIN_COLUMN + 1]; + WCHAR wzComponent[MAX_DARWIN_KEY + 1]; + WCHAR wzDirectory[MAX_PATH + 1]; + + int nUserPermissionCount; + int nPermissions; + SCA_SMB_EX_USER_PERMS* pExUserPerms; + + INSTALLSTATE isInstalled, isAction; + + BOOL fUseIntegratedAuth; + BOOL fLegacyUserProvided; + struct SCA_USER scau; + + struct SCA_SMB* pssNext; +}; + + +#define RESERVED 0 + +// schedule prototypes +HRESULT ScaSmbRead(SCA_SMB** ppssList); +HRESULT ScaSmbExPermsRead(SCA_SMB* pss); +HRESULT ScaSmbUninstall(SCA_SMB* pssList); +HRESULT ScaSmbInstall(SCA_SMB* pssList); +void ScaSmbFreeList(SCA_SMB* pssList); diff --git a/src/ext/Util/ca/scasmbexec.cpp b/src/ext/Util/ca/scasmbexec.cpp new file mode 100644 index 00000000..ced3aa78 --- /dev/null +++ b/src/ext/Util/ca/scasmbexec.cpp @@ -0,0 +1,316 @@ +// Copyright (c) .NET 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" + + +/******************************************************************** + AllocateAcl - allocate an acl and populate it with this user and + permission information user could be user or domain\user + +********************************************************************/ +HRESULT AllocateAcl(SCA_SMBP* pssp, PACL* ppACL) +{ + HRESULT hr = S_OK; + EXPLICIT_ACCESSW* pEA = NULL; + DWORD cEA = 0; + DWORD dwCounter = 0; + + PSID psid = NULL; + LPCWSTR wzUser = NULL; + DWORD nPermissions = 0; + DWORD nErrorReturn = 0; + ACCESS_MODE accessMode = NOT_USED_ACCESS; + + cEA = pssp->dwUserPermissionCount + 1; + if (cEA >= MAXSIZE_T / sizeof(EXPLICIT_ACCESSW)) + { + ExitOnFailure(hr = E_OUTOFMEMORY, "Too many user permissions to allocate: %u", cEA); + } + + pEA = static_cast(MemAlloc(cEA * sizeof(EXPLICIT_ACCESSW), TRUE)); + ExitOnNull(pEA, hr, E_OUTOFMEMORY, "failed to allocate memory for explicit access structure"); + + // figure out how big the psid is + for (dwCounter = 0; dwCounter < pssp->dwUserPermissionCount; ++dwCounter) + { + wzUser = pssp->pUserPerms[dwCounter].wzUser; + nPermissions = pssp->pUserPerms[dwCounter].nPermissions; + accessMode = pssp->pUserPerms[dwCounter].accessMode; + // + // create the appropriate SID + // + + // figure out the right user to put into the access block + if (0 == lstrcmpW(wzUser, L"Everyone")) + { + hr = AclGetWellKnownSid(WinWorldSid, &psid); + } + else if (0 == lstrcmpW(wzUser, L"Administrators")) + { + hr = AclGetWellKnownSid(WinBuiltinAdministratorsSid, &psid); + } + else if (0 == lstrcmpW(wzUser, L"LocalSystem")) + { + hr = AclGetWellKnownSid(WinLocalSystemSid, &psid); + } + else if (0 == lstrcmpW(wzUser, L"LocalService")) + { + hr = AclGetWellKnownSid(WinLocalServiceSid, &psid); + } + else if (0 == lstrcmpW(wzUser, L"NetworkService")) + { + hr = AclGetWellKnownSid(WinNetworkServiceSid, &psid); + } + else if (0 == lstrcmpW(wzUser, L"AuthenticatedUser")) + { + hr = AclGetWellKnownSid(WinAuthenticatedUserSid, &psid); + } + else if (0 == lstrcmpW(wzUser, L"Guests")) + { + hr = AclGetWellKnownSid(WinBuiltinGuestsSid, &psid); + } + else if(0 == lstrcmpW(wzUser, L"CREATOR OWNER")) + { + hr = AclGetWellKnownSid(WinCreatorOwnerSid, &psid); + } + else + { + hr = AclGetAccountSid(NULL, wzUser, &psid); + } + ExitOnFailure(hr, "failed to get sid for account: %ls", wzUser); + + // we now have a valid pSid, fill in the EXPLICIT_ACCESS + + /* Permissions options: (see sca.sdh for defined sdl options) + #define GENERIC_READ (0x80000000L) 2147483648 + #define GENERIC_WRITE (0x40000000L) 1073741824 + #define GENERIC_EXECUTE (0x20000000L) 536870912 + #define GENERIC_ALL (0x10000000L) 268435456 + */ + pEA[dwCounter].grfAccessPermissions = nPermissions; + pEA[dwCounter].grfAccessMode = accessMode; + pEA[dwCounter].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; +#pragma prefast(push) +#pragma prefast(disable:25029) + ::BuildTrusteeWithSidW(&(pEA[dwCounter].Trustee), psid); +#pragma prefast(pop) + } + + // create a new ACL that contains the ACE + *ppACL = NULL; +#pragma prefast(push) +#pragma prefast(disable:25029) + nErrorReturn = ::SetEntriesInAclW(dwCounter, pEA, NULL, ppACL); +#pragma prefast(pop) + ExitOnFailure(hr = HRESULT_FROM_WIN32(nErrorReturn), "failed to allocate ACL"); + +LExit: + if (psid) + { + AclFreeSid(psid); + } + + ReleaseMem(pEA); + + return hr; +} + + + +/******************************************************************** + FillShareInfo - fill the NetShareAdd data structure + +********************************************************************/ +void FillShareInfo(SHARE_INFO_502* psi, SCA_SMBP* pssp, PSECURITY_DESCRIPTOR pSD) +{ + psi->shi502_netname = pssp->wzKey; + psi->shi502_type = STYPE_DISKTREE; + psi->shi502_remark = pssp->wzDescription; + psi->shi502_permissions = 0; // not used + psi->shi502_max_uses = 0xFFFFFFFF; + psi->shi502_current_uses = 0; + psi->shi502_path = pssp->wzDirectory; + psi->shi502_passwd = NULL; // not file share perms + psi->shi502_reserved = 0; + psi->shi502_security_descriptor = pSD; +} + + + +/* NET_API_STATUS return codes +NERR_Success = 0 +NERR_DuplicateShare = 2118 +NERR_BufTooSmall = 2123 +NERR_NetNameNotFound = 2310 +NERR_RedirectedPath = 2117 +NERR_UnknownDevDir = 2116 +*/ + +/******************************************************************** + DoesShareExists - Does a share of this name exist on this computer? + +********************************************************************/ +HRESULT DoesShareExist(__in LPWSTR wzShareName) +{ + HRESULT hr = S_OK; + NET_API_STATUS s; + SHARE_INFO_502* psi = NULL; + s = ::NetShareGetInfo(NULL, wzShareName, 502, (BYTE**) &psi); + + switch (s) + { + case NERR_Success: + hr = S_OK; + break; + case NERR_NetNameNotFound: + hr = E_FILENOTFOUND; + break; + default: + WcaLogError(s, "NetShareGetInfo returned an unexpected value.", NULL); + hr = HRESULT_FROM_WIN32(s); + break; + } + + ::NetApiBufferFree(psi); + + return hr; +} + + + +/******************************************************************** + CreateShare - create the file share on this computer + +********************************************************************/ +HRESULT CreateShare(SCA_SMBP* pssp) +{ + if (!pssp || !(pssp->wzKey)) + return E_INVALIDARG; + + HRESULT hr = S_OK; + PACL pACL = NULL; + SHARE_INFO_502 si; + NET_API_STATUS s; + DWORD dwParamErr = 0; + + BOOL fShareExists = SUCCEEDED(DoesShareExist(pssp->wzKey)); + + PSECURITY_DESCRIPTOR pSD = static_cast(MemAlloc(SECURITY_DESCRIPTOR_MIN_LENGTH, TRUE)); + ExitOnNull(pSD, hr, E_OUTOFMEMORY, "Failed to allocate memory for security descriptor"); + +#pragma prefast(push) +#pragma prefast(disable:25029) + if (!::InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) +#pragma prefast(pop) + { + ExitOnLastError(hr, "failed to initialize security descriptor"); + } + + hr = AllocateAcl(pssp, &pACL); + ExitOnFailure(hr, "Failed to allocate ACL for fileshare"); + + if (NULL == pACL) + { + WcaLog(LOGMSG_VERBOSE, "Ignoring NULL DACL."); + } +#pragma prefast(push) +#pragma prefast(disable:25028) // We only call this when pACL isn't NULL, so this call is safe according to the docs + // add the ACL to the security descriptor. + else if (!::SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE)) + { + ExitOnLastError(hr, "Failed to set security descriptor"); + } +#pragma prefast(pop) + + // all that is left is to create the share + FillShareInfo(&si, pssp, pSD); + + // Fail if the directory doesn't exist + if (!DirExists(pssp->wzDirectory, NULL)) + ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_OBJECT_NOT_FOUND), "Can't create a file share on directory that doesn't exist: %ls.", pssp->wzDirectory); + + WcaLog(LOGMSG_VERBOSE, "Creating file share on directory \'%ls\' named \'%ls\'.", pssp->wzDirectory, pssp->wzKey); + + if (!fShareExists) + { + s = ::NetShareAdd(NULL, 502, (BYTE*) &si, &dwParamErr); + WcaLog(LOGMSG_VERBOSE, "Adding a new file share."); + } + else + { + // The share exists. Write our new permissions over the top. + s = ::NetShareSetInfo(NULL, pssp->wzKey, 502, (BYTE*) &si, &dwParamErr); + WcaLog(LOGMSG_VERBOSE, "Setting permissions on existing share."); + } + + if (NERR_Success != s) + { + hr = E_FAIL; + if (!fShareExists && NERR_DuplicateShare == s) + WcaLog(LOGMSG_VERBOSE, "Duplicate error when existence check failed."); + + // error codes listed above. + ExitOnFailure(hr, "Failed to create/modify file share: Err: %d", s); + } + +LExit: + if (pACL) + { + ::LocalFree(pACL); + } + + ReleaseMem(pSD); + + return hr; +} + + +/******************************************************************** + ScaEnsureSmbExists + +********************************************************************/ +HRESULT ScaEnsureSmbExists(SCA_SMBP* pssp) +{ + HRESULT hr = S_OK; + + // create the share + hr = CreateShare(pssp); + + return hr; +} + + +// +// Delete File Shares - real work +// + +/******************************************************************** + ScaDropSmb - delete this file share from this computer + +********************************************************************/ +HRESULT ScaDropSmb(SCA_SMBP* pssp) +{ + HRESULT hr = S_OK; + NET_API_STATUS s; + + hr = DoesShareExist(pssp->wzKey); + + if (E_FILENOTFOUND == hr) + { + WcaLog(LOGMSG_VERBOSE, "Share doesn't exist, share removal skipped. (%ls)", pssp->wzKey); + ExitFunction1(hr = S_OK); + + } + + ExitOnFailure(hr, "Unable to detect share. (%ls)", pssp->wzKey); + + s = ::NetShareDel(NULL, pssp->wzKey, 0); + if (NERR_Success != s) + { + hr = E_FAIL; + ExitOnFailure(hr, "Failed to remove file share: Err: %d", s); + } + +LExit: + return hr; +} diff --git a/src/ext/Util/ca/scasmbexec.h b/src/ext/Util/ca/scasmbexec.h new file mode 100644 index 00000000..e3c8f8bb --- /dev/null +++ b/src/ext/Util/ca/scasmbexec.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_SMBP_USER_PERMS +{ + DWORD nPermissions; + ACCESS_MODE accessMode; + WCHAR* wzUser; + //Not adding Password because I can't find anywhere that it is used +}; + +struct SCA_SMBP // hungarian ssp +{ + WCHAR* wzKey; + WCHAR* wzDescription; + WCHAR* wzComponent; + WCHAR* wzDirectory; // full path of the dir to share to + + DWORD dwUserPermissionCount; //Count of SCA_SMBP_EX_USER_PERMS structures + SCA_SMBP_USER_PERMS* pUserPerms; + BOOL fUseIntegratedAuth; +}; + + +HRESULT ScaEnsureSmbExists(SCA_SMBP* pssp); +HRESULT ScaDropSmb(SCA_SMBP* pssp); diff --git a/src/ext/Util/ca/scasmbsched.cpp b/src/ext/Util/ca/scasmbsched.cpp new file mode 100644 index 00000000..e29f7f51 --- /dev/null +++ b/src/ext/Util/ca/scasmbsched.cpp @@ -0,0 +1,639 @@ +// Copyright (c) .NET 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" + + +/******************************************************************** + Helper functions to maintain a list of file shares to create / remove + +********************************************************************/ +SCA_SMB* NewSmb() +{ + SCA_SMB* pss = (SCA_SMB*)MemAlloc(sizeof(SCA_SMB), TRUE); + Assert(pss); + return pss; +} + + +SCA_SMB_EX_USER_PERMS* NewExUserPermsSmb() +{ + SCA_SMB_EX_USER_PERMS* pExUserPerms = (SCA_SMB_EX_USER_PERMS*)MemAlloc(sizeof(SCA_SMB_EX_USER_PERMS), TRUE); + Assert(pExUserPerms); + return pExUserPerms; +} + + +SCA_SMB* AddSmbToList(SCA_SMB* pssList, SCA_SMB* pss) +{ + if (pssList) + { + SCA_SMB* pssT = pssList; + while (pssT->pssNext) + { + pssT = pssT->pssNext; + } + + pssT->pssNext = pss; + } + else + { + pssList = pss; + } + + return pssList; +} + + +SCA_SMB_EX_USER_PERMS* AddExUserPermsSmbToList( + SCA_SMB_EX_USER_PERMS* pExUserPermsList, + SCA_SMB_EX_USER_PERMS* pExUserPerms + ) +{ + SCA_SMB_EX_USER_PERMS* pExUserPermsTemp = pExUserPermsList; + if (pExUserPermsList) + { + while (pExUserPermsTemp->pExUserPermsNext) + { + pExUserPermsTemp = pExUserPermsTemp->pExUserPermsNext; + } + + pExUserPermsTemp->pExUserPermsNext = pExUserPerms; + } + else + { + pExUserPermsList = pExUserPerms; + } + + return pExUserPermsList; +} + +void ScaSmbFreeList(SCA_SMB* pssList) +{ + SCA_SMB* pssDelete = pssList; + while (pssList) + { + pssDelete = pssList; + pssList = pssList->pssNext; + + MemFree(pssDelete); + } +} + +void ScaExUserPermsSmbFreeList(SCA_SMB_EX_USER_PERMS* pExUserPermsList) +{ + SCA_SMB_EX_USER_PERMS* pExUserPermsDelete = pExUserPermsList; + while (pExUserPermsList) + { + pExUserPermsDelete = pExUserPermsList; + pExUserPermsList = pExUserPermsList->pExUserPermsNext; + + MemFree(pExUserPermsDelete); + } +} + +// sql query constants +LPCWSTR vcsSmbQuery = L"SELECT `Wix4FileShare`, `ShareName`, `Description`, `Directory_`, " + L"`Component_`, `User_`, `Permissions` FROM `Wix4FileShare`"; + +enum eSmbQuery { + ssqFileShare = 1, + ssqShareName, + ssqDescription, + ssqDirectory, + ssqComponent, + ssqUser, + ssqPermissions + }; + + +/******************************************************************** + ScaSmbRead - read all of the information from the msi tables and + return a list of file share jobs to be done. + +********************************************************************/ +HRESULT ScaSmbRead(SCA_SMB** ppssList) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + PMSIHANDLE hView, hRec; + + LPWSTR pwzData = NULL; + + SCA_SMB* pss = NULL; + BOOL bUserPermissionsTableExists = FALSE; + + if (S_OK != WcaTableExists(L"Wix4FileShare")) + { + WcaLog(LOGMSG_VERBOSE, "Skipping ScaSmbCreateShare() - Wix4FileShare table not present"); + ExitFunction1(hr = S_FALSE); + } + + if (S_OK == WcaTableExists(L"Wix4FileSharePermissions")) + { + bUserPermissionsTableExists = TRUE; + } + else + { + WcaLog(LOGMSG_VERBOSE, "No Additional Permissions - Wix4FileSharePermissions table not present"); + } + + WcaLog(LOGMSG_VERBOSE, "Reading File Share Tables"); + + // loop through all the fileshares + hr = WcaOpenExecuteView(vcsSmbQuery, &hView); + ExitOnFailure(hr, "Failed to open view on Wix4FileShare table"); + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + pss = NewSmb(); + if (!pss) + { + hr = E_OUTOFMEMORY; + break; + } + Assert(pss); + ::ZeroMemory(pss, sizeof(*pss)); + + hr = WcaGetRecordString(hRec, ssqFileShare, &pwzData); + ExitOnFailure(hr, "Failed to get Wix4FileShare.Wix4FileShare"); + hr = ::StringCchCopyW(pss->wzId, countof(pss->wzId), pwzData); + ExitOnFailure(hr, "Failed to copy ID string to smb object"); + + hr = WcaGetRecordFormattedString(hRec, ssqShareName, &pwzData); + ExitOnFailure(hr, "Failed to get Wix4FileShare.ShareName"); + hr = ::StringCchCopyW(pss->wzShareName, countof(pss->wzShareName), pwzData); + ExitOnFailure(hr, "Failed to copy share name string to smb object"); + + hr = WcaGetRecordString(hRec, ssqComponent, &pwzData); + ExitOnFailure(hr, "Failed to get Component for Wix4FileShare: '%ls'", pss->wzShareName); + hr = ::StringCchCopyW(pss->wzComponent, countof(pss->wzComponent), pwzData); + ExitOnFailure(hr, "Failed to copy component string to smb object"); + + hr = WcaGetRecordFormattedString(hRec, ssqDescription, &pwzData); + ExitOnFailure(hr, "Failed to get Share Description for Wix4FileShare: '%ls'", pss->wzShareName); + hr = ::StringCchCopyW(pss->wzDescription, countof(pss->wzDescription), pwzData); + ExitOnFailure(hr, "Failed to copy description string to smb object"); + + // get user info from the user table + hr = WcaGetRecordFormattedString(hRec, ssqUser, &pwzData); + ExitOnFailure(hr, "Failed to get Wix4User record for Wix4FileShare: '%ls'", pss->wzShareName); + + // get component install state + er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pss->wzComponent, &pss->isInstalled, &pss->isAction); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed to get Component state for Wix4FileShare"); + + // if a user was specified + if (*pwzData) + { + pss->fUseIntegratedAuth = FALSE; + pss->fLegacyUserProvided = TRUE; + hr = ScaGetUser(pwzData, &pss->scau); + ExitOnFailure(hr, "Failed to get user information for fileshare: '%ls'", pss->wzShareName); + } + else + { + pss->fLegacyUserProvided = FALSE; + // TODO: figure out whether this is useful still + //pss->fUseIntegratedAuth = TRUE; + // integrated authorization doesn't have a User record + } + + // get the share's directory + hr = WcaGetRecordString(hRec, ssqDirectory, &pwzData); + ExitOnFailure(hr, "Failed to get directory for Wix4FileShare: '%ls'", pss->wzShareName); + + WCHAR wzPath[MAX_PATH]; + DWORD dwLen; + dwLen = countof(wzPath); + // review: relevant for file shares? + if (INSTALLSTATE_SOURCE == pss->isAction) + { + er = ::MsiGetSourcePathW(WcaGetInstallHandle(), pwzData, wzPath, &dwLen); + } + else + { + er = ::MsiGetTargetPathW(WcaGetInstallHandle(), pwzData, wzPath, &dwLen); + } + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory"); + + // If the path is to the root of a drive, then it needs a trailing backslash. + // Otherwise, it can't have a trailing backslash. + if (3 < dwLen) + { + if (wzPath[dwLen - 1] == L'\\') + { + wzPath[dwLen - 1] = 0; + } + } + else if (2 == dwLen && wzPath[1] == L':') + { + wzPath[2] = L'\\'; + wzPath[3] = 0; + } + + hr = ::StringCchCopyW(pss->wzDirectory, countof(pss->wzDirectory), wzPath); + ExitOnFailure(hr, "Failed to copy directory string to smb object"); + + hr = WcaGetRecordInteger(hRec, ssqPermissions, &pss->nPermissions); + ExitOnFailure(hr, "Failed to get Wix4FileShare.Permissions"); + + // Check to see if additional user & permissions are specified for this share + if (bUserPermissionsTableExists) + { + hr = ScaSmbExPermsRead(pss); + ExitOnFailure(hr, "Failed to get Additional File Share Permissions"); + } + + *ppssList = AddSmbToList(*ppssList, pss); + pss = NULL; // set the smb NULL so it doesn't accidentally get freed below + } + + if (E_NOMOREITEMS == hr) + { + hr = S_OK; + } + ExitOnFailure(hr, "Failure occured while processing Wix4FileShare table"); + +LExit: + // if anything was left over after an error clean it all up + if (pss) + { + ScaSmbFreeList(pss); + } + + ReleaseStr(pwzData); + + return hr; +} + + +/******************************************************************** + RetrieveSMBShareUserPermList - retrieve SMB Share's user permission list + +********************************************************************/ +HRESULT RetrieveFileShareUserPerm(SCA_SMB* pss, SCA_SMB_EX_USER_PERMS** ppExUserPermsList, DWORD *pUserPermsCount) +{ + HRESULT hr = S_OK; + SHARE_INFO_502* psi = NULL; + NET_API_STATUS s; + BOOL bValid, bDaclDefaulted; + PACL acl = NULL; + PEXPLICIT_ACCESSW pEA = NULL; + ULONG nCount = 0; + DWORD er = ERROR_SUCCESS; + PSID pSID = NULL; + DWORD nUserNameSize = MAX_DARWIN_COLUMN; + DWORD nDomainNameSize = MAX_DARWIN_COLUMN; + SID_NAME_USE peUse; + DWORD dwCounter = 0; + SCA_SMB_EX_USER_PERMS* pExUserPermsList = NULL; + DWORD dwUserPermsCount = 0; + + *pUserPermsCount = 0; + s = ::NetShareGetInfo(NULL, pss->wzShareName, 502, (LPBYTE*)&psi); + WcaLog(LOGMSG_VERBOSE, "retrieving permissions on existing file share."); + if (NERR_NetNameNotFound == s) + { + WcaLog(LOGMSG_VERBOSE, "File share has already been removed."); + ExitFunction1(hr = S_OK); + } + else if (NERR_Success != s || psi == NULL) + { + hr = E_FAIL; + ExitOnFailure(hr, "Failed to get share information with return code: %d", s); + } + if (!::GetSecurityDescriptorDacl(psi->shi502_security_descriptor, &bValid, &acl, &bDaclDefaulted) || !bValid) + { + ExitOnLastError(hr, "Failed to get acl from security descriptor"); + } + + er = ::GetExplicitEntriesFromAclW(acl, &nCount, &pEA); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed to get access entries from acl for file share %ls", pss->wzShareName); + for (dwCounter = 0; dwCounter < nCount; ++dwCounter) + { + if (TRUSTEE_IS_SID == pEA[dwCounter].Trustee.TrusteeForm) + { + SCA_SMB_EX_USER_PERMS* pExUserPerms = NewExUserPermsSmb(); + ::ZeroMemory(pExUserPerms, sizeof(*pExUserPerms)); + pExUserPermsList = AddExUserPermsSmbToList(pExUserPermsList, pExUserPerms); + pSID = (PSID)(pEA[dwCounter].Trustee.ptstrName); + if (!::LookupAccountSidW(NULL, pSID, pExUserPerms->scau.wzName, &nUserNameSize, pExUserPerms->scau.wzDomain, &nDomainNameSize, &peUse)) + { + hr = E_FAIL; + ExitOnFailure(hr, "Failed to get account name from SID"); + } + pExUserPerms->nPermissions = pEA[dwCounter].grfAccessPermissions; + pExUserPerms->accessMode = pEA[dwCounter].grfAccessMode; + ++dwUserPermsCount; + nUserNameSize = MAX_DARWIN_COLUMN; + nDomainNameSize = MAX_DARWIN_COLUMN; + } + } + *ppExUserPermsList = pExUserPermsList; + *pUserPermsCount = dwUserPermsCount; + +LExit: + if (psi) + { + ::NetApiBufferFree(psi); + } + + if (pEA) + { + ::LocalFree(pEA); + } + + return hr; +} + + +/******************************************************************** + SchedCreateSmb - schedule one instance of a file share creation + +********************************************************************/ +HRESULT SchedCreateSmb(SCA_SMB* pss) +{ + HRESULT hr = S_OK; + + WCHAR wzDomainUser[255]; // "domain\user" + SCA_SMB_EX_USER_PERMS* pExUserPermsList = NULL; + int nCounter = 0; + WCHAR* pwzRollbackCustomActionData = NULL; + WCHAR* pwzCustomActionData = NULL; + + hr = WcaWriteStringToCaData(pss->wzShareName, &pwzRollbackCustomActionData); + ExitOnFailure(hr, "failed to add ShareName to CustomActionData"); + + hr = WcaWriteStringToCaData(pss->wzShareName, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add ShareName to CustomActionData"); + + hr = WcaWriteStringToCaData(pss->wzDescription, &pwzCustomActionData); + ExitOnFailure(hr, "Failed to add server name to CustomActionData"); + + hr = WcaWriteStringToCaData(pss->wzDirectory, &pwzCustomActionData); + ExitOnFailure(hr, "Failed to add full path instance to CustomActionData"); + + hr = WcaWriteStringToCaData(pss->fUseIntegratedAuth ? L"1" : L"0", &pwzCustomActionData); + ExitOnFailure(hr, "Failed to add server name to CustomActionData"); + + if (pss->fLegacyUserProvided) + { + hr = WcaWriteIntegerToCaData(pss->nUserPermissionCount + 1, &pwzCustomActionData); + ExitOnFailure(hr, "Failed to add additional user permission count to CustomActionData"); + + hr = UserBuildDomainUserName(wzDomainUser, countof(wzDomainUser), pss->scau.wzName, pss->scau.wzDomain); + ExitOnFailure(hr, "Failed to build user and domain name for CustomActionData"); + hr = WcaWriteStringToCaData(wzDomainUser, &pwzCustomActionData); + ExitOnFailure(hr, "Failed to add server Domain\\UserName to CustomActionData"); + + hr = WcaWriteIntegerToCaData(pss->nPermissions, &pwzCustomActionData); + ExitOnFailure(hr, "Failed to add permissions to CustomActionData"); + } + else + { + hr = WcaWriteIntegerToCaData(pss->nUserPermissionCount, &pwzCustomActionData); + ExitOnFailure(hr, "Failed to add additional user permission count to CustomActionData"); + } + + if (pss->nUserPermissionCount > 0) + { + nCounter = 0; + for (pExUserPermsList = pss->pExUserPerms; pExUserPermsList; pExUserPermsList = pExUserPermsList->pExUserPermsNext) + { + Assert(nCounter < pss->nUserPermissionCount); + + hr = UserBuildDomainUserName(wzDomainUser, countof(wzDomainUser), pExUserPermsList->scau.wzName, pExUserPermsList->scau.wzDomain); + ExitOnFailure(hr, "Failed to build user and domain name for CustomActionData"); + hr = WcaWriteStringToCaData(wzDomainUser, &pwzCustomActionData); + ExitOnFailure(hr, "Failed to add server Domain\\UserName to CustomActionData"); + + hr = WcaWriteIntegerToCaData((int)pExUserPermsList->accessMode, &pwzCustomActionData); + ExitOnFailure(hr, "Failed to add access mode to CustomActionData"); + + hr = WcaWriteIntegerToCaData(pExUserPermsList->nPermissions, &pwzCustomActionData); + ExitOnFailure(hr, "Failed to add permissions to CustomActionData"); + ++nCounter; + } + Assert(nCounter == pss->nUserPermissionCount); + } + + // Schedule the rollback first + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CreateSmbRollback"), pwzRollbackCustomActionData, COST_SMB_DROPSMB); + ExitOnFailure(hr, "Failed to schedule DropSmb action"); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CreateSmb"), pwzCustomActionData, COST_SMB_CREATESMB); + ExitOnFailure(hr, "Failed to schedule CreateSmb action"); + +LExit: + ReleaseStr(pwzRollbackCustomActionData); + ReleaseStr(pwzCustomActionData); + + if (pExUserPermsList) + { + ScaExUserPermsSmbFreeList(pExUserPermsList); + } + + return hr; +} + + +/******************************************************************** + ScaSmbInstall - for every file share, schedule the create custom action + +********************************************************************/ +HRESULT ScaSmbInstall(SCA_SMB* pssList) +{ + HRESULT hr = S_FALSE; // assume nothing will be done + SCA_SMB* pss = NULL; + + for (pss = pssList; pss; pss = pss->pssNext) + { + // if installing this component + if (WcaIsInstalling(pss->isInstalled, pss->isAction) ) + { + hr = SchedCreateSmb(pss); + ExitOnFailure(hr, "Failed to schedule the creation of the fileshare: %ls", pss->wzShareName); + } + } + +LExit: + return hr; +} + + +/******************************************************************** + SchedDropSmb - schedule one instance of a file share removal + +********************************************************************/ +HRESULT SchedDropSmb(SCA_SMB* pss) +{ + HRESULT hr = S_OK; + + WCHAR* pwzCustomActionData = NULL; + WCHAR* pwzRollbackCustomActionData = NULL; + SCA_SMB_EX_USER_PERMS *pExUserPermsList = NULL; + SCA_SMB_EX_USER_PERMS *pExUserPerm = NULL; + WCHAR wzDomainUser[255]; // "domain\user" + DWORD dwUserPermsCount = 0; + + // roll back DropSmb + hr = WcaWriteStringToCaData(pss->wzShareName, &pwzRollbackCustomActionData); + ExitOnFailure(hr, "failed to add ShareName to CustomActionData"); + + hr = WcaWriteStringToCaData(pss->wzDescription, &pwzRollbackCustomActionData); + ExitOnFailure(hr, "Failed to add server name to CustomActionData"); + + hr = WcaWriteStringToCaData(pss->wzDirectory, &pwzRollbackCustomActionData); + ExitOnFailure(hr, "Failed to add full path instance to CustomActionData"); + + hr = WcaWriteStringToCaData(L"1", &pwzRollbackCustomActionData); + ExitOnFailure(hr, "Failed to add useintegrated flag to CustomActionData"); + + hr = RetrieveFileShareUserPerm(pss, &pExUserPermsList, &dwUserPermsCount); + ExitOnFailure(hr, "Failed to retrieve SMBShare's user permissions"); + + hr = WcaWriteIntegerToCaData((int)dwUserPermsCount, &pwzRollbackCustomActionData); + ExitOnFailure(hr, "Failed to add additional user permission count to CustomActionData"); + + for (pExUserPerm = pExUserPermsList; pExUserPerm; pExUserPerm = pExUserPerm->pExUserPermsNext) + { + hr = UserBuildDomainUserName(wzDomainUser, countof(wzDomainUser), pExUserPerm->scau.wzName, pExUserPerm->scau.wzDomain); + ExitOnFailure(hr, "Failed to build user and domain name for CustomActionData"); + hr = WcaWriteStringToCaData(wzDomainUser, &pwzRollbackCustomActionData); + ExitOnFailure(hr, "Failed to add server Domain\\UserName to CustomActionData"); + + hr = WcaWriteIntegerToCaData((int)pExUserPerm->accessMode, &pwzRollbackCustomActionData); + ExitOnFailure(hr, "Failed to add access mode to CustomActionData"); + + hr = WcaWriteIntegerToCaData(pExUserPerm->nPermissions, &pwzRollbackCustomActionData); + ExitOnFailure(hr, "Failed to add permissions to CustomActionData"); + } + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"DropSmbRollback"), pwzRollbackCustomActionData, COST_SMB_CREATESMB); + ExitOnFailure(hr, "Failed to schedule DropSmbRollback action"); + + // DropSMB + hr = WcaWriteStringToCaData(pss->wzShareName, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add ShareName to CustomActionData"); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"DropSmb"), pwzCustomActionData, COST_SMB_DROPSMB); + ExitOnFailure(hr, "Failed to schedule DropSmb action"); + +LExit: + ReleaseStr(pwzCustomActionData); + + if (pExUserPermsList) + { + ScaExUserPermsSmbFreeList(pExUserPermsList); + } + + return hr; + +} + + +/******************************************************************** + ScaSmbUninstall - for every file share, schedule the drop custom action + +********************************************************************/ +HRESULT ScaSmbUninstall(SCA_SMB* pssList) +{ + HRESULT hr = S_FALSE; // assume nothing will be done + SCA_SMB* pss = NULL; + + for (pss = pssList; pss; pss = pss->pssNext) + { + // if uninstalling this component + if (WcaIsUninstalling(pss->isInstalled, pss->isAction) ) + { + hr = SchedDropSmb(pss); + ExitOnFailure(hr, "Failed to remove file share %ls", pss->wzShareName); + } + } + +LExit: + return hr; +} + +LPCWSTR vcsSmbExUserPermsQuery = L"SELECT `FileShare_`,`User_`,`Permissions` " + L"FROM `Wix4FileSharePermissions` WHERE `FileShare_`=?"; + +enum eSmbUserPermsQuery { + ssupqFileShare = 1, + ssupqUser, + ssupqPermissions + +}; + + +/******************************************************************** + ScaSmbExPermsRead - for Every entry in File Permissions table add a + User Name & Permissions structure to the List + +********************************************************************/ +HRESULT ScaSmbExPermsRead(SCA_SMB* pss) +{ + HRESULT hr = S_OK; + PMSIHANDLE hView, hRec; + + LPWSTR pwzData = NULL; + SCA_SMB_EX_USER_PERMS* pExUserPermsList = pss->pExUserPerms; + SCA_SMB_EX_USER_PERMS* pExUserPerms = NULL; + int nCounter = 0; + + hRec = ::MsiCreateRecord(1); + hr = WcaSetRecordString(hRec, 1, pss->wzId); + ExitOnFailure(hr, "Failed to look up FileShare"); + + hr = WcaOpenView(vcsSmbExUserPermsQuery, &hView); + ExitOnFailure(hr, "Failed to open view on Wix4FileSharePermissions table"); + hr = WcaExecuteView(hView, hRec); + ExitOnFailure(hr, "Failed to execute view on Wix4FileSharePermissions table"); + + // loop through all User/Permissions paris returned + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + pExUserPerms = NewExUserPermsSmb(); + if (!pExUserPerms) + { + hr = E_OUTOFMEMORY; + break; + } + Assert(pExUserPerms); + ::ZeroMemory(pExUserPerms, sizeof(*pExUserPerms)); + + hr = WcaGetRecordString(hRec, ssupqUser, &pwzData); + ExitOnFailure(hr, "Failed to get Wix4FileSharePermissions.User"); + hr = ScaGetUser(pwzData, &pExUserPerms->scau); + ExitOnFailure(hr, "Failed to get user information for fileshare: '%ls'", pss->wzShareName); + + hr = WcaGetRecordInteger(hRec, ssupqPermissions, &pExUserPerms->nPermissions); + ExitOnFailure(hr, "Failed to get Wix4FileSharePermissions.Permissions"); + pExUserPerms->accessMode = SET_ACCESS; // we only support SET_ACCESS here + + pExUserPermsList = AddExUserPermsSmbToList(pExUserPermsList, pExUserPerms); + ++nCounter; + pExUserPerms = NULL; // set the smb NULL so it doesn't accidentally get freed below + } + + if (E_NOMOREITEMS == hr) + { + hr = S_OK; + pss->pExUserPerms = pExUserPermsList; + pss->nUserPermissionCount = nCounter; + } + ExitOnFailure(hr, "Failure occured while processing FileShare table"); + +LExit: + // if anything was left over after an error clean it all up + if (pExUserPerms) + { + ScaExUserPermsSmbFreeList(pExUserPerms); + } + + ReleaseStr(pwzData); + + return hr; +} diff --git a/src/ext/Util/ca/scauser.cpp b/src/ext/Util/ca/scauser.cpp new file mode 100644 index 00000000..b25e9daf --- /dev/null +++ b/src/ext/Util/ca/scauser.cpp @@ -0,0 +1,709 @@ +// Copyright (c) .NET 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 `Wix4User`, `Component_`, `Name`, `Domain`, `Password` FROM `Wix4User` WHERE `Wix4User`=?"; +enum eUserQuery { vuqUser = 1, vuqComponent, vuqName, vuqDomain, vuqPassword }; + +LPCWSTR vcsGroupQuery = L"SELECT `Wix4Group`, `Component_`, `Name`, `Domain` FROM `Wix4Group` WHERE `Wix4Group`=?"; +enum eGroupQuery { vgqGroup = 1, vgqComponent, vgqName, vgqDomain }; + +LPCWSTR vcsUserGroupQuery = L"SELECT `Wix4User_`, `Wix4Group_` FROM `Wix4UserGroup` WHERE `Wix4User_`=?"; +enum eUserGroupQuery { vugqUser = 1, vugqGroup }; + +LPCWSTR vActionableQuery = L"SELECT `Wix4User`,`Component_`,`Name`,`Domain`,`Password`,`Attributes` FROM `Wix4User` WHERE `Component_` IS NOT NULL"; +enum eActionableQuery { vaqUser = 1, vaqComponent, vaqName, vaqDomain, vaqPassword, vaqAttributes }; + + +static HRESULT AddUserToList( + __inout SCA_USER** ppsuList + ); + +static HRESULT AddGroupToList( + __inout SCA_GROUP** ppsgList + ); + + +HRESULT __stdcall ScaGetUser( + __in LPCWSTR wzUser, + __out SCA_USER* pscau + ) +{ + if (!wzUser || !pscau) + { + return E_INVALIDARG; + } + + HRESULT hr = S_OK; + PMSIHANDLE hView, hRec; + + 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); + } + + hRec = ::MsiCreateRecord(1); + hr = WcaSetRecordString(hRec, 1, wzUser); + ExitOnFailure(hr, "Failed to look up User"); + + hr = WcaOpenView(vcsUserQuery, &hView); + ExitOnFailure(hr, "Failed to open view on Wix4User table"); + hr = WcaExecuteView(hView, hRec); + ExitOnFailure(hr, "Failed to execute view on Wix4User table"); + + hr = WcaFetchSingleRecord(hView, &hRec); + if (S_OK == hr) + { + hr = WcaGetRecordString(hRec, vuqUser, &pwzData); + ExitOnFailure(hr, "Failed to get Wix4User.User"); + hr = ::StringCchCopyW(pscau->wzKey, countof(pscau->wzKey), pwzData); + ExitOnFailure(hr, "Failed to copy key string to user object"); + + hr = WcaGetRecordString(hRec, vuqComponent, &pwzData); + ExitOnFailure(hr, "Failed to get Wix4User.Component_"); + hr = ::StringCchCopyW(pscau->wzComponent, countof(pscau->wzComponent), pwzData); + ExitOnFailure(hr, "Failed to copy component string to user object"); + + hr = WcaGetRecordFormattedString(hRec, vuqName, &pwzData); + ExitOnFailure(hr, "Failed to get Wix4User.Name"); + hr = ::StringCchCopyW(pscau->wzName, countof(pscau->wzName), pwzData); + ExitOnFailure(hr, "Failed to copy name string to user object"); + + hr = WcaGetRecordFormattedString(hRec, vuqDomain, &pwzData); + ExitOnFailure(hr, "Failed to get Wix4User.Domain"); + hr = ::StringCchCopyW(pscau->wzDomain, countof(pscau->wzDomain), pwzData); + ExitOnFailure(hr, "Failed to copy domain string to user object"); + + hr = WcaGetRecordFormattedString(hRec, vuqPassword, &pwzData); + ExitOnFailure(hr, "Failed to get Wix4User.Password"); + hr = ::StringCchCopyW(pscau->wzPassword, countof(pscau->wzPassword), pwzData); + ExitOnFailure(hr, "Failed to copy password string to user object"); + } + else if (E_NOMOREITEMS == hr) + { + WcaLog(LOGMSG_STANDARD, "Error: Cannot locate Wix4User.User='%ls'", wzUser); + hr = E_FAIL; + } + else + { + ExitOnFailure(hr, "Error or found multiple matching Wix4User rows"); + } + +LExit: + ReleaseStr(pwzData); + + return hr; +} + +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 Wix4User rows"); + } + + hr = WcaGetRecordString(hRec, vuqUser, &pwzData); + ExitOnFailure(hr, "Failed to get Wix4User.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 Wix4User.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 Wix4User.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 Wix4User.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 Wix4User.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 Wix4User.User='%ls'", wzUser); + hr = E_FAIL; + } + else + { + ExitOnFailure(hr, "Error fetching single Wix4User row"); + } + +LExit: + ReleaseStr(pwzData); + + return hr; +} + + +HRESULT __stdcall ScaGetGroup( + __in LPCWSTR wzGroup, + __out SCA_GROUP* pscag + ) +{ + if (!wzGroup || !pscag) + { + return E_INVALIDARG; + } + + HRESULT hr = S_OK; + PMSIHANDLE hView, hRec; + + LPWSTR pwzData = NULL; + + hRec = ::MsiCreateRecord(1); + hr = WcaSetRecordString(hRec, 1, wzGroup); + ExitOnFailure(hr, "Failed to look up Group"); + + hr = WcaOpenView(vcsGroupQuery, &hView); + ExitOnFailure(hr, "Failed to open view on Wix4Group table"); + hr = WcaExecuteView(hView, hRec); + ExitOnFailure(hr, "Failed to execute view on Wix4Group table"); + + hr = WcaFetchSingleRecord(hView, &hRec); + if (S_OK == hr) + { + hr = WcaGetRecordString(hRec, vgqGroup, &pwzData); + ExitOnFailure(hr, "Failed to get Wix4Group.Wix4Group."); + hr = ::StringCchCopyW(pscag->wzKey, countof(pscag->wzKey), pwzData); + ExitOnFailure(hr, "Failed to copy Wix4Group.Wix4Group."); + + hr = WcaGetRecordString(hRec, vgqComponent, &pwzData); + ExitOnFailure(hr, "Failed to get Wix4Group.Component_"); + hr = ::StringCchCopyW(pscag->wzComponent, countof(pscag->wzComponent), pwzData); + ExitOnFailure(hr, "Failed to copy Wix4Group.Component_."); + + hr = WcaGetRecordFormattedString(hRec, vgqName, &pwzData); + ExitOnFailure(hr, "Failed to get Wix4Group.Name"); + hr = ::StringCchCopyW(pscag->wzName, countof(pscag->wzName), pwzData); + ExitOnFailure(hr, "Failed to copy Wix4Group.Name."); + + hr = WcaGetRecordFormattedString(hRec, vgqDomain, &pwzData); + ExitOnFailure(hr, "Failed to get Wix4Group.Domain"); + hr = ::StringCchCopyW(pscag->wzDomain, countof(pscag->wzDomain), pwzData); + ExitOnFailure(hr, "Failed to copy Wix4Group.Domain."); + } + else if (E_NOMOREITEMS == hr) + { + WcaLog(LOGMSG_STANDARD, "Error: Cannot locate Wix4Group.Wix4Group='%ls'", wzGroup); + hr = E_FAIL; + } + else + { + ExitOnFailure(hr, "Error or found multiple matching Wix4Group rows"); + } + +LExit: + ReleaseStr(pwzData); + + return hr; +} + + +void ScaUserFreeList( + __in SCA_USER* psuList + ) +{ + SCA_USER* psuDelete = psuList; + while (psuList) + { + psuDelete = psuList; + psuList = psuList->psuNext; + + ScaGroupFreeList(psuDelete->psgGroups); + MemFree(psuDelete); + } +} + + +void ScaGroupFreeList( + __in SCA_GROUP* psgList + ) +{ + SCA_GROUP* psgDelete = psgList; + while (psgList) + { + psgDelete = psgList; + psgList = psgList->psgNext; + + MemFree(psgDelete); + } +} + + +HRESULT ScaUserRead( + __out SCA_USER** ppsuList + ) +{ + //Assert(FALSE); + Assert(ppsuList); + + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + PMSIHANDLE hView, hRec, hUserRec, hUserGroupView; + + LPWSTR pwzData = NULL; + + BOOL fUserGroupExists = FALSE; + + SCA_USER *psu = NULL; + + INSTALLSTATE isInstalled, isAction; + + if (S_OK != WcaTableExists(L"Wix4User")) + { + WcaLog(LOGMSG_VERBOSE, "Wix4User Table does not exist, exiting"); + ExitFunction1(hr = S_FALSE); + } + + if (S_OK == WcaTableExists(L"Wix4UserGroup")) + { + fUserGroupExists = TRUE; + } + + // + // loop through all the users + // + hr = WcaOpenExecuteView(vActionableQuery, &hView); + ExitOnFailure(hr, "failed to open view on Wix4User table"); + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + hr = WcaGetRecordString(hRec, vaqComponent, &pwzData); + ExitOnFailure(hr, "failed to get Wix4User.Component"); + + er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &isInstalled, &isAction); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to get Component state for Wix4User"); + + // don't bother if we aren't installing or uninstalling this component + if (WcaIsInstalling(isInstalled, isAction) || WcaIsUninstalling(isInstalled, isAction)) + { + // + // Add the user to the list and populate it's values + // + hr = AddUserToList(ppsuList); + ExitOnFailure(hr, "failed to add user to list"); + + psu = *ppsuList; + + psu->isInstalled = isInstalled; + psu->isAction = isAction; + hr = ::StringCchCopyW(psu->wzComponent, countof(psu->wzComponent), pwzData); + ExitOnFailure(hr, "failed to copy component name: %ls", pwzData); + + hr = WcaGetRecordString(hRec, vaqUser, &pwzData); + ExitOnFailure(hr, "failed to get Wix4User.User"); + hr = ::StringCchCopyW(psu->wzKey, countof(psu->wzKey), pwzData); + ExitOnFailure(hr, "failed to copy user key: %ls", pwzData); + + hr = WcaGetRecordFormattedString(hRec, vaqName, &pwzData); + ExitOnFailure(hr, "failed to get Wix4User.Name"); + hr = ::StringCchCopyW(psu->wzName, countof(psu->wzName), pwzData); + ExitOnFailure(hr, "failed to copy user name: %ls", pwzData); + + hr = WcaGetRecordFormattedString(hRec, vaqDomain, &pwzData); + ExitOnFailure(hr, "failed to get Wix4User.Domain"); + hr = ::StringCchCopyW(psu->wzDomain, countof(psu->wzDomain), pwzData); + ExitOnFailure(hr, "failed to copy user domain: %ls", pwzData); + + hr = WcaGetRecordFormattedString(hRec, vaqPassword, &pwzData); + ExitOnFailure(hr, "failed to get Wix4User.Password"); + hr = ::StringCchCopyW(psu->wzPassword, countof(psu->wzPassword), pwzData); + ExitOnFailure(hr, "failed to copy user password"); + + hr = WcaGetRecordInteger(hRec, vaqAttributes, &psu->iAttributes); + ExitOnFailure(hr, "failed to get Wix4User.Attributes"); + + // Check if this user is to be added to any groups + if (fUserGroupExists) + { + hUserRec = ::MsiCreateRecord(1); + hr = WcaSetRecordString(hUserRec, 1, psu->wzKey); + ExitOnFailure(hr, "Failed to create user record for querying Wix4UserGroup table"); + + hr = WcaOpenView(vcsUserGroupQuery, &hUserGroupView); + ExitOnFailure(hr, "Failed to open view on Wix4UserGroup table for user %ls", psu->wzKey); + hr = WcaExecuteView(hUserGroupView, hUserRec); + ExitOnFailure(hr, "Failed to execute view on Wix4UserGroup table for user: %ls", psu->wzKey); + + while (S_OK == (hr = WcaFetchRecord(hUserGroupView, &hRec))) + { + hr = WcaGetRecordString(hRec, vugqGroup, &pwzData); + ExitOnFailure(hr, "failed to get Wix4UserGroup.Group"); + + hr = AddGroupToList(&(psu->psgGroups)); + ExitOnFailure(hr, "failed to add group to list"); + + hr = ScaGetGroup(pwzData, psu->psgGroups); + ExitOnFailure(hr, "failed to get information for group: %ls", pwzData); + } + + if (E_NOMOREITEMS == hr) + { + hr = S_OK; + } + ExitOnFailure(hr, "failed to enumerate selected rows from Wix4UserGroup table"); + } + } + } + + if (E_NOMOREITEMS == hr) + { + hr = S_OK; + } + ExitOnFailure(hr, "failed to enumerate selected rows from Wix4User table"); + +LExit: + ReleaseStr(pwzData); + + return hr; +} + + +static HRESULT WriteGroupInfo( + __in SCA_GROUP* psgList, + __in LPWSTR *ppwzActionData + ) +{ + HRESULT hr = S_OK; + + for (SCA_GROUP* psg = psgList; psg; psg = psg->psgNext) + { + hr = WcaWriteStringToCaData(psg->wzName, ppwzActionData); + ExitOnFailure(hr, "failed to add group name to custom action data: %ls", psg->wzName); + + hr = WcaWriteStringToCaData(psg->wzDomain, ppwzActionData); + ExitOnFailure(hr, "failed to add group domain to custom action data: %ls", psg->wzDomain); + } + +LExit: + return hr; +} + + +// Behaves like WriteGroupInfo, but it filters out groups the user is currently a member of, +// because we don't want to rollback those +static HRESULT WriteGroupRollbackInfo( + __in LPCWSTR pwzName, + __in LPCWSTR pwzDomain, + __in SCA_GROUP* psgList, + __in LPWSTR *ppwzActionData + ) +{ + HRESULT hr = S_OK; + BOOL fIsMember = FALSE; + + for (SCA_GROUP* psg = psgList; psg; psg = psg->psgNext) + { + hr = UserCheckIsMember(pwzName, pwzDomain, psg->wzName, psg->wzDomain, &fIsMember); + if (FAILED(hr)) + { + WcaLog(LOGMSG_VERBOSE, "Failed to check if user: %ls (domain: %ls) is member of a group while collecting rollback information (error code 0x%x) - continuing", pwzName, pwzDomain, hr); + hr = S_OK; + continue; + } + + // If the user is currently a member, we don't want to undo that on rollback, so skip adding + // this group record to the list of groups to rollback + if (fIsMember) + { + continue; + } + + hr = WcaWriteStringToCaData(psg->wzName, ppwzActionData); + ExitOnFailure(hr, "failed to add group name to custom action data: %ls", psg->wzName); + + hr = WcaWriteStringToCaData(psg->wzDomain, ppwzActionData); + ExitOnFailure(hr, "failed to add group domain to custom action data: %ls", psg->wzDomain); + } + +LExit: + return hr; +} + + +/* **************************************************************** +ScaUserExecute - Schedules user account creation or removal based on +component state. + +******************************************************************/ +HRESULT ScaUserExecute( + __in SCA_USER *psuList + ) +{ + HRESULT hr = S_OK; + DWORD er = 0; + PDOMAIN_CONTROLLER_INFOW pDomainControllerInfo = NULL; + + LPWSTR pwzBaseScriptKey = NULL; + DWORD cScriptKey = 0; + + USER_INFO_0 *pUserInfo = NULL; + LPWSTR pwzScriptKey = NULL; + LPWSTR pwzActionData = NULL; + LPWSTR pwzRollbackData = NULL; + + // Get the base script key for this CustomAction. + hr = WcaCaScriptCreateKey(&pwzBaseScriptKey); + ExitOnFailure(hr, "Failed to get encoding key."); + + // Loop through all the users to be configured. + for (SCA_USER *psu = psuList; psu; psu = psu->psuNext) + { + USER_EXISTS ueUserExists = USER_EXISTS_INDETERMINATE; + + // Always put the User Name and Domain plus Attributes on the front of the CustomAction + // data. Sometimes we'll add more data. + Assert(psu->wzName); + hr = WcaWriteStringToCaData(psu->wzName, &pwzActionData); + ExitOnFailure(hr, "Failed to add user name to custom action data: %ls", psu->wzName); + hr = WcaWriteStringToCaData(psu->wzDomain, &pwzActionData); + ExitOnFailure(hr, "Failed to add user domain to custom action data: %ls", psu->wzDomain); + hr = WcaWriteIntegerToCaData(psu->iAttributes, &pwzActionData); + ExitOnFailure(hr, "failed to add user attributes to custom action data for user: %ls", psu->wzKey); + + // Check to see if the user already exists since we have to be very careful when adding + // and removing users. Note: MSDN says that it is safe to call these APIs from any + // user, so we should be safe calling it during immediate mode. + er = ::NetApiBufferAllocate(sizeof(USER_INFO_0), reinterpret_cast(&pUserInfo)); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed to allocate memory to check existence of user: %ls", psu->wzName); + + LPCWSTR wzDomain = psu->wzDomain; + if (wzDomain && *wzDomain) + { + er = ::DsGetDcNameW(NULL, wzDomain, NULL, NULL, NULL, &pDomainControllerInfo); + if (RPC_S_SERVER_UNAVAILABLE == er) + { + // MSDN says, if we get the above error code, try again with the "DS_FORCE_REDISCOVERY" flag + er = ::DsGetDcNameW(NULL, wzDomain, NULL, NULL, DS_FORCE_REDISCOVERY, &pDomainControllerInfo); + } + if (ERROR_SUCCESS == er) + { + wzDomain = pDomainControllerInfo->DomainControllerName + 2; //Add 2 so that we don't get the \\ prefix + } + } + + er = ::NetUserGetInfo(wzDomain, psu->wzName, 0, reinterpret_cast(pUserInfo)); + if (NERR_Success == er) + { + ueUserExists = USER_EXISTS_YES; + } + else if (NERR_UserNotFound == er) + { + ueUserExists = USER_EXISTS_NO; + } + else + { + ueUserExists = USER_EXISTS_INDETERMINATE; + hr = HRESULT_FROM_WIN32(er); + WcaLog(LOGMSG_VERBOSE, "Failed to check existence of domain: %ls, user: %ls (error code 0x%x) - continuing", wzDomain, psu->wzName, hr); + hr = S_OK; + er = ERROR_SUCCESS; + } + + if (WcaIsInstalling(psu->isInstalled, psu->isAction)) + { + // If the user exists, check to see if we are supposed to fail if user the exists before + // the install. + if (USER_EXISTS_YES == ueUserExists) + { + // Reinstalls will always fail if we don't remove the check for "fail if exists". + if (WcaIsReInstalling(psu->isInstalled, psu->isAction)) + { + psu->iAttributes &= ~SCAU_FAIL_IF_EXISTS; + } + + if ((SCAU_FAIL_IF_EXISTS & (psu->iAttributes)) && !(SCAU_UPDATE_IF_EXISTS & (psu->iAttributes))) + { + hr = HRESULT_FROM_WIN32(NERR_UserExists); + MessageExitOnFailure(hr, msierrUSRFailedUserCreateExists, "Failed to create user: %ls because user already exists.", psu->wzName); + } + } + + // Rollback only if the user already exists, we couldn't determine if the user exists, or we are going to create the user + if ((USER_EXISTS_YES == ueUserExists) || (USER_EXISTS_INDETERMINATE == ueUserExists) || !(psu->iAttributes & SCAU_DONT_CREATE_USER)) + { + ++cScriptKey; + hr = StrAllocFormatted(&pwzScriptKey, L"%ls%u", pwzBaseScriptKey, cScriptKey); + ExitOnFailure(hr, "Failed to create encoding key."); + + // Write the script key to CustomActionData for install and rollback so information can be passed to rollback. + hr = WcaWriteStringToCaData(pwzScriptKey, &pwzActionData); + ExitOnFailure(hr, "Failed to add encoding key to custom action data."); + + hr = WcaWriteStringToCaData(pwzScriptKey, &pwzRollbackData); + ExitOnFailure(hr, "Failed to add encoding key to rollback custom action data."); + + INT iRollbackUserAttributes = psu->iAttributes; + + // If the user already exists, ensure this is accounted for in rollback + if (USER_EXISTS_YES == ueUserExists) + { + iRollbackUserAttributes |= SCAU_DONT_CREATE_USER; + } + else + { + iRollbackUserAttributes &= ~SCAU_DONT_CREATE_USER; + } + + // The deferred CA determines when to rollback User Rights Assignments so these should never be set. + iRollbackUserAttributes &= ~SCAU_ALLOW_LOGON_AS_SERVICE; + iRollbackUserAttributes &= ~SCAU_ALLOW_LOGON_AS_BATCH; + + hr = WcaWriteStringToCaData(psu->wzName, &pwzRollbackData); + ExitOnFailure(hr, "Failed to add user name to rollback custom action data: %ls", psu->wzName); + hr = WcaWriteStringToCaData(psu->wzDomain, &pwzRollbackData); + ExitOnFailure(hr, "Failed to add user domain to rollback custom action data: %ls", psu->wzDomain); + hr = WcaWriteIntegerToCaData(iRollbackUserAttributes, &pwzRollbackData); + ExitOnFailure(hr, "failed to add user attributes to rollback custom action data for user: %ls", psu->wzKey); + + // If the user already exists, add relevant group information to rollback data + if (USER_EXISTS_YES == ueUserExists || USER_EXISTS_INDETERMINATE == ueUserExists) + { + hr = WriteGroupRollbackInfo(psu->wzName, psu->wzDomain, psu->psgGroups, &pwzRollbackData); + ExitOnFailure(hr, "failed to add group information to rollback custom action data"); + } + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CreateUserRollback"), pwzRollbackData, COST_USER_DELETE); + ExitOnFailure(hr, "failed to schedule CreateUserRollback"); + } + else + { + // Write empty script key to CustomActionData since there is no rollback. + hr = WcaWriteStringToCaData(L"", &pwzActionData); + ExitOnFailure(hr, "Failed to add empty encoding key to custom action data."); + } + + // + // Schedule the creation now. + // + hr = WcaWriteStringToCaData(psu->wzPassword, &pwzActionData); + ExitOnFailure(hr, "failed to add user password to custom action data for user: %ls", psu->wzKey); + + // Add user's group information to custom action data + hr = WriteGroupInfo(psu->psgGroups, &pwzActionData); + ExitOnFailure(hr, "failed to add group information to custom action data"); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CreateUser"), pwzActionData, COST_USER_ADD); + ExitOnFailure(hr, "failed to schedule CreateUser"); + } + else if (((USER_EXISTS_YES == ueUserExists) || (USER_EXISTS_INDETERMINATE == ueUserExists)) && WcaIsUninstalling(psu->isInstalled, psu->isAction) && !(psu->iAttributes & SCAU_DONT_REMOVE_ON_UNINSTALL)) + { + // Add user's group information - this will ensure the user can be removed from any groups they were added to, if the user isn't be deleted + hr = WriteGroupInfo(psu->psgGroups, &pwzActionData); + ExitOnFailure(hr, "failed to add group information to custom action data"); + + // + // Schedule the removal because the user exists and we don't have any flags set + // that say, don't remove the user on uninstall. + // + // Note: We can't rollback the removal of a user which is why RemoveUser is a commit + // CustomAction. + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RemoveUser"), pwzActionData, COST_USER_DELETE); + ExitOnFailure(hr, "failed to schedule RemoveUser"); + } + + ReleaseNullStr(pwzScriptKey); + ReleaseNullStr(pwzActionData); + ReleaseNullStr(pwzRollbackData); + if (pUserInfo) + { + ::NetApiBufferFree(static_cast(pUserInfo)); + pUserInfo = NULL; + } + if (pDomainControllerInfo) + { + ::NetApiBufferFree(static_cast(pDomainControllerInfo)); + pDomainControllerInfo = NULL; + } + } + +LExit: + ReleaseStr(pwzBaseScriptKey); + ReleaseStr(pwzScriptKey); + ReleaseStr(pwzActionData); + ReleaseStr(pwzRollbackData); + if (pUserInfo) + { + ::NetApiBufferFree(static_cast(pUserInfo)); + } + if (pDomainControllerInfo) + { + ::NetApiBufferFree(static_cast(pDomainControllerInfo)); + } + + return hr; +} + + +static HRESULT AddUserToList( + __inout SCA_USER** ppsuList + ) +{ + HRESULT hr = S_OK; + SCA_USER* psu = static_cast(MemAlloc(sizeof(SCA_USER), TRUE)); + ExitOnNull(psu, hr, E_OUTOFMEMORY, "failed to allocate memory for new user list element"); + + psu->psuNext = *ppsuList; + *ppsuList = psu; + +LExit: + return hr; +} + + +static HRESULT AddGroupToList( + __inout SCA_GROUP** ppsgList + ) +{ + HRESULT hr = S_OK; + SCA_GROUP* psg = static_cast(MemAlloc(sizeof(SCA_GROUP), TRUE)); + ExitOnNull(psg, hr, E_OUTOFMEMORY, "failed to allocate memory for new group list element"); + + psg->psgNext = *ppsgList; + *ppsgList = psg; + +LExit: + return hr; +} diff --git a/src/ext/Util/ca/scauser.h b/src/ext/Util/ca/scauser.h new file mode 100644 index 00000000..a5fd5ea8 --- /dev/null +++ b/src/ext/Util/ca/scauser.h @@ -0,0 +1,67 @@ +#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 USER_EXISTS +{ + USER_EXISTS_YES, + USER_EXISTS_NO, + USER_EXISTS_INDETERMINATE +}; + +// 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 ScaGetUser( + __in LPCWSTR wzUser, + __out SCA_USER* pscau + ); +HRESULT __stdcall ScaGetUserDeferred( + __in LPCWSTR wzUser, + __in WCA_WRAPQUERY_HANDLE hUserQuery, + __out SCA_USER* pscau + ); +HRESULT __stdcall ScaGetGroup( + __in LPCWSTR wzGroup, + __out SCA_GROUP* pscag + ); +void ScaUserFreeList( + __in SCA_USER* psuList + ); +void ScaGroupFreeList( + __in SCA_GROUP* psgList + ); +HRESULT ScaUserRead( + __inout SCA_USER** ppsuList + ); +HRESULT ScaUserExecute( + __in SCA_USER *psuList + ); diff --git a/src/ext/Util/ca/secureobj.cpp b/src/ext/Util/ca/secureobj.cpp new file mode 100644 index 00000000..72842eb5 --- /dev/null +++ b/src/ext/Util/ca/secureobj.cpp @@ -0,0 +1,915 @@ +// Copyright (c) .NET 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" + +// structs +LPCWSTR wzQUERY_SECUREOBJECTS = L"SELECT `Wix4SecureObject`.`Wix4SecureObject`, `Wix4SecureObject`.`Table`, `Wix4SecureObject`.`Domain`, `Wix4SecureObject`.`User`, `Wix4SecureObject`.`Attributes`, " + L"`Wix4SecureObject`.`Permission`, `Wix4SecureObject`.`Component_`, `Component`.`Attributes` FROM `Wix4SecureObject`,`Component` WHERE " + L"`Wix4SecureObject`.`Component_`=`Component`.`Component`"; +enum eQUERY_SECUREOBJECTS { QSO_SECUREOBJECT = 1, QSO_TABLE, QSO_DOMAIN, QSO_USER, QSO_ATTRIBUTES, QSO_PERMISSION, QSO_COMPONENT, QSO_COMPATTRIBUTES }; + +LPCWSTR wzQUERY_REGISTRY = L"SELECT `Registry`.`Registry`, `Registry`.`Root`, `Registry`.`Key` FROM `Registry` WHERE `Registry`.`Registry`=?"; +enum eQUERY_OBJECTCOMPONENT { QSOC_REGISTRY = 1, QSOC_REGROOT, QSOC_REGKEY }; + +LPCWSTR wzQUERY_SERVICEINSTALL = L"SELECT `ServiceInstall`.`Name` FROM `ServiceInstall` WHERE `ServiceInstall`.`ServiceInstall`=?"; +enum eQUERY_SECURESERVICEINSTALL { QSSI_NAME = 1 }; + +enum eOBJECTTYPE { OT_UNKNOWN, OT_SERVICE, OT_FOLDER, OT_FILE, OT_REGISTRY }; + +enum eSECURE_OBJECT_ATTRIBUTE +{ + SECURE_OBJECT_ATTRIBUTE_INHERITABLE = 0x1, +}; + +static eOBJECTTYPE EObjectTypeFromString( + __in LPCWSTR pwzTable + ) +{ + if (NULL == pwzTable) + { + return OT_UNKNOWN; + } + + eOBJECTTYPE eType = OT_UNKNOWN; + + // ensure we're looking at a known table + if (0 == lstrcmpW(L"ServiceInstall", pwzTable)) + { + eType = OT_SERVICE; + } + else if (0 == lstrcmpW(L"CreateFolder", pwzTable)) + { + eType = OT_FOLDER; + } + else if (0 == lstrcmpW(L"File", pwzTable)) + { + eType = OT_FILE; + } + else if (0 == lstrcmpW(L"Registry", pwzTable)) + { + eType = OT_REGISTRY; + } + + return eType; +} + +static SE_OBJECT_TYPE SEObjectTypeFromString( + __in LPCWSTR pwzTable + ) +{ + if (NULL == pwzTable) + { + return SE_UNKNOWN_OBJECT_TYPE; + } + + SE_OBJECT_TYPE objectType = SE_UNKNOWN_OBJECT_TYPE; + + if (0 == lstrcmpW(L"ServiceInstall", pwzTable)) + { + objectType = SE_SERVICE; + } + else if (0 == lstrcmpW(L"CreateFolder", pwzTable) || 0 == lstrcmpW(L"File", pwzTable)) + { + objectType = SE_FILE_OBJECT; + } + else if (0 == lstrcmpW(L"Registry", pwzTable)) + { + objectType = SE_REGISTRY_KEY; + } + else + { + // Do nothing; we'll return SE_UNKNOWN_OBJECT_TYPE, and the caller should handle the situation + } + + return objectType; +} + +static HRESULT StoreACLRollbackInfo( + __in LPWSTR pwzObject, + __in LPCWSTR pwzTable + ) +{ + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + PSECURITY_DESCRIPTOR psd = NULL; + SECURITY_DESCRIPTOR_CONTROL sdc = {0}; + DWORD dwRevision = 0; + LPWSTR pwzCustomActionData = NULL; + LPWSTR pwzSecurityInfo = NULL; + + Assert(pwzObject && pwzTable); + + SE_OBJECT_TYPE objectType = SEObjectTypeFromString(const_cast (pwzTable)); + + if (SE_UNKNOWN_OBJECT_TYPE != objectType) + { + er = ::GetNamedSecurityInfoW(pwzObject, objectType, DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &psd); + if (ERROR_FILE_NOT_FOUND == er || ERROR_PATH_NOT_FOUND == er || ERROR_SERVICE_DOES_NOT_EXIST == HRESULT_CODE(er)) + { + // If the file, path or service doesn't exist yet, skip rollback without a message + hr = HRESULT_FROM_WIN32(er); + ExitFunction(); + } + + ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Unable to schedule rollback for object: %ls", pwzObject); + + //Need to see if DACL is protected so getting Descriptor information + if (!::GetSecurityDescriptorControl(psd, &sdc, &dwRevision)) + { + ExitOnLastError(hr, "Unable to schedule rollback for object (failed to get security descriptor control): %ls", pwzObject); + } + + // Convert the security information to a string, and write this to the custom action data + if (!::ConvertSecurityDescriptorToStringSecurityDescriptorW(psd,SDDL_REVISION_1,DACL_SECURITY_INFORMATION,&pwzSecurityInfo,NULL)) + { + hr = E_UNEXPECTED; + ExitOnFailure(hr, "Unable to schedule rollback for object (failed to convert security descriptor to a valid security descriptor string): %ls", pwzObject); + } + + hr = WcaWriteStringToCaData(pwzObject, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add object data to rollback CustomActionData"); + + hr = WcaWriteStringToCaData(pwzTable, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add table name to rollback CustomActionData"); + + hr = WcaWriteStringToCaData(pwzSecurityInfo, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add security info data to rollback CustomActionData"); + + // Write a 1 if DACL is protected, 0 otherwise + if (sdc & SE_DACL_PROTECTED) + { + hr = WcaWriteIntegerToCaData(1,&pwzCustomActionData); + ExitOnFailure(hr, "failed to add data to rollbackCustomActionData"); + } + else + { + hr = WcaWriteIntegerToCaData(0,&pwzCustomActionData); + ExitOnFailure(hr, "failed to add data to rollback CustomActionData"); + } + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecSecureObjectsRollback"), pwzCustomActionData, COST_SECUREOBJECT); + ExitOnFailure(hr, "failed to schedule ExecSecureObjectsRollback for item: %ls of type: %ls", pwzObject, pwzTable); + + ReleaseStr(pwzCustomActionData); + pwzCustomActionData = NULL; + + } + else + { + MessageExitOnFailure(hr = E_UNEXPECTED, msierrSecureObjectsUnknownType, "unknown object type: %ls", pwzTable); + } +LExit: + ReleaseStr(pwzCustomActionData); + + if (psd) + { + ::LocalFree(psd); + } + + return hr; +} + +static HRESULT GetTargetPath( + __in eOBJECTTYPE eType, + __in LPCWSTR pwzSecureObject, + __out LPWSTR* ppwzTargetPath + ) +{ + HRESULT hr = S_OK; + + PMSIHANDLE hView = NULL; + PMSIHANDLE hRecObject = NULL; + PMSIHANDLE hRec = NULL; + + int iRoot = 0; + int iAllUsers = 0; + LPWSTR pwzKey = NULL; + LPWSTR pwzFormattedString = NULL; + + if (OT_SERVICE == eType) + { + hr = WcaTableExists(L"ServiceInstall"); + if (S_FALSE == hr) + { + hr = E_UNEXPECTED; + } + ExitOnFailure(hr, "failed to open ServiceInstall table to secure object"); + + hr = WcaOpenView(wzQUERY_SERVICEINSTALL, &hView); + ExitOnFailure(hr, "failed to open view on ServiceInstall table"); + + // create a record that stores the object to secure + hRec = MsiCreateRecord(1); + MsiRecordSetStringW(hRec, 1, pwzSecureObject); + + // execute a view looking for the object's ServiceInstall.ServiceInstall row. + hr = WcaExecuteView(hView, hRec); + ExitOnFailure(hr, "failed to execute view on ServiceInstall table"); + hr = WcaFetchSingleRecord(hView, &hRecObject); + ExitOnFailure(hr, "failed to fetch ServiceInstall row for secure object"); + + hr = WcaGetRecordFormattedString(hRecObject, QSSI_NAME, ppwzTargetPath); + ExitOnFailure(hr, "failed to get service name for secure object: %ls", pwzSecureObject); + } + else if (OT_FOLDER == eType) + { + hr = WcaGetTargetPath(pwzSecureObject, ppwzTargetPath); + ExitOnFailure(hr, "failed to get target path for directory id: %ls", pwzSecureObject); + } + else if (OT_FILE == eType) + { + hr = StrAllocFormatted(&pwzFormattedString, L"[#%s]", pwzSecureObject); + ExitOnFailure(hr, "failed to create formatted string for securing file object: %ls", pwzSecureObject); + + hr = WcaGetFormattedString(pwzFormattedString, ppwzTargetPath); + ExitOnFailure(hr, "failed to get file path from formatted string: %ls for secure object: %ls", pwzFormattedString, pwzSecureObject); + } + else if (OT_REGISTRY == eType) + { + hr = WcaTableExists(L"Registry"); + if (S_FALSE == hr) + { + hr = E_UNEXPECTED; + } + ExitOnFailure(hr, "failed to open Registry table to secure object"); + + hr = WcaOpenView(wzQUERY_REGISTRY, &hView); + ExitOnFailure(hr, "failed to open view on Registry table"); + + // create a record that stores the object to secure + hRec = MsiCreateRecord(1); + MsiRecordSetStringW(hRec, 1, pwzSecureObject); + + // execute a view looking for the object's Registry row + hr = WcaExecuteView(hView, hRec); + ExitOnFailure(hr, "failed to execute view on Registry table"); + hr = WcaFetchSingleRecord(hView, &hRecObject); + ExitOnFailure(hr, "failed to fetch Registry row for secure object"); + + hr = WcaGetRecordInteger(hRecObject, QSOC_REGROOT, &iRoot); + ExitOnFailure(hr, "Failed to get reg key root for secure object: %ls", pwzSecureObject); + + hr = WcaGetRecordFormattedString(hRecObject, QSOC_REGKEY, &pwzKey); + ExitOnFailure(hr, "Failed to get reg key for secure object: %ls", pwzSecureObject); + + // Decode the root value + if (-1 == iRoot) + { + // They didn't specify a root so that means it's either HKCU or HKLM depending on ALLUSERS property + hr = WcaGetIntProperty(L"ALLUSERS", &iAllUsers); + ExitOnFailure(hr, "failed to get value of ALLUSERS property"); + + if (1 == iAllUsers) + { + hr = StrAllocString(ppwzTargetPath, L"MACHINE\\", 0); + ExitOnFailure(hr, "failed to allocate target registry string with HKLM root"); + } + else + { + hr = StrAllocString(ppwzTargetPath, L"CURRENT_USER\\", 0); + ExitOnFailure(hr, "failed to allocate target registry string with HKCU root"); + } + } + else if (msidbRegistryRootClassesRoot == iRoot) + { + hr = StrAllocString(ppwzTargetPath, L"CLASSES_ROOT\\", 0); + ExitOnFailure(hr, "failed to allocate target registry string with HKCR root"); + } + else if (msidbRegistryRootCurrentUser == iRoot) + { + hr = StrAllocString(ppwzTargetPath, L"CURRENT_USER\\", 0); + ExitOnFailure(hr, "failed to allocate target registry string with HKCU root"); + } + else if (msidbRegistryRootLocalMachine == iRoot) + { + hr = StrAllocString(ppwzTargetPath, L"MACHINE\\", 0); + ExitOnFailure(hr, "failed to allocate target registry string with HKLM root"); + } + else if (msidbRegistryRootUsers == iRoot) + { + hr = StrAllocString(ppwzTargetPath, L"USERS\\", 0); + ExitOnFailure(hr, "failed to allocate target registry string with HKU root"); + } + else + { + ExitOnFailure(hr = E_UNEXPECTED, "Unknown registry key root specified for secure object: '%ls' root: %d", pwzSecureObject, iRoot); + } + + hr = StrAllocConcat(ppwzTargetPath, pwzKey, 0); + ExitOnFailure(hr, "Failed to concat key: %ls for secure object: %ls", pwzKey, pwzSecureObject); + } + else + { + AssertSz(FALSE, "How did you get here?"); + ExitOnFailure(hr = E_UNEXPECTED, "Unknown secure object type: %d", eType); + } + +LExit: + ReleaseStr(pwzFormattedString); + ReleaseStr(pwzKey); + + return hr; +} + +/****************************************************************** + SchedSecureObjects - entry point for SchedSecureObjects Custom Action + + called as Type 1 CustomAction (binary DLL) from Windows Installer + in InstallExecuteSequence, to schedule ExecSecureObjects +******************************************************************/ +extern "C" UINT __stdcall SchedSecureObjects( + __in MSIHANDLE hInstall + ) +{ +// AssertSz(FALSE, "debug SchedSecureObjects"); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + LPWSTR pwzSecureObject = NULL; + LPWSTR pwzData = NULL; + LPWSTR pwzTable = NULL; + LPWSTR pwzTargetPath = NULL; + + PMSIHANDLE hView = NULL; + PMSIHANDLE hRec = NULL; + + INSTALLSTATE isInstalled; + INSTALLSTATE isAction; + + LPWSTR pwzCustomActionData = NULL; + + DWORD cObjects = 0; + eOBJECTTYPE eType = OT_UNKNOWN; + DWORD dwAttributes = 0; + + // + // initialize + // + hr = WcaInitialize(hInstall, "SchedSecureObjects"); + ExitOnFailure(hr, "failed to initialize"); + + // anything to do? + if (S_OK != WcaTableExists(L"Wix4SecureObject")) + { + WcaLog(LOGMSG_STANDARD, "Wix4SecureObject table doesn't exist, so there are no objects to secure."); + ExitFunction(); + } + + // + // loop through all the objects to be secured + // + hr = WcaOpenExecuteView(wzQUERY_SECUREOBJECTS, &hView); + ExitOnFailure(hr, "failed to open view on Wix4SecureObject table"); + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + hr = WcaGetRecordString(hRec, QSO_TABLE, &pwzTable); + ExitOnFailure(hr, "failed to get object table"); + + eType = EObjectTypeFromString(pwzTable); + + if (OT_UNKNOWN == eType) + { + ExitOnFailure(hr = E_INVALIDARG, "unknown SecureObject.Table: %ls", pwzTable); + } + + int iCompAttributes = 0; + hr = WcaGetRecordInteger(hRec, QSO_COMPATTRIBUTES, &iCompAttributes); + ExitOnFailure(hr, "failed to get Component attributes for secure object"); + + BOOL fIs64Bit = iCompAttributes & msidbComponentAttributes64bit; + + // Only process entries in the Wix4SecureObject table whose components match the bitness of this CA +#ifdef _WIN64 + if (!fIs64Bit) + { + continue; + } +#else + if (fIs64Bit) + { + continue; + } +#endif + + // Get the object to secure + hr = WcaGetRecordString(hRec, QSO_SECUREOBJECT, &pwzSecureObject); + ExitOnFailure(hr, "failed to get name of object"); + + hr = GetTargetPath(eType, pwzSecureObject, &pwzTargetPath); + ExitOnFailure(hr, "failed to get target path of object '%ls'", pwzSecureObject); + + hr = WcaGetRecordString(hRec, QSO_COMPONENT, &pwzData); + ExitOnFailure(hr, "failed to get Component name for secure object"); + + // + // if we are installing this Component + // + er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); + ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "failed to get install state for Component: %ls", pwzData); + + if (WcaIsInstalling(isInstalled, isAction)) + { + hr = WcaWriteStringToCaData(pwzTargetPath, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add data to CustomActionData"); + + // add the data to the CustomActionData + hr = WcaGetRecordString(hRec, QSO_SECUREOBJECT, &pwzData); + ExitOnFailure(hr, "failed to get name of object"); + hr = WcaWriteStringToCaData(pwzTable, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add data to CustomActionData"); + + hr = WcaGetRecordFormattedString(hRec, QSO_DOMAIN, &pwzData); + ExitOnFailure(hr, "failed to get domain for user to configure object"); + hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add data to CustomActionData"); + + hr = WcaGetRecordFormattedString(hRec, QSO_USER, &pwzData); + ExitOnFailure(hr, "failed to get user to configure object"); + hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add data to CustomActionData"); + + hr = WcaGetRecordInteger(hRec, QSO_ATTRIBUTES, reinterpret_cast(&dwAttributes)); + ExitOnFailure(hr, "failed to get attributes to configure object"); + hr = WcaWriteIntegerToCaData(dwAttributes, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add data to CustomActionData"); + + hr = WcaGetRecordString(hRec, QSO_PERMISSION, &pwzData); + ExitOnFailure(hr, "failed to get permission to configure object"); + hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add data to CustomActionData"); + + ++cObjects; + } + } + + // if we looped through all records all is well + if (E_NOMOREITEMS == hr) + hr = S_OK; + ExitOnFailure(hr, "failed while looping through all objects to secure"); + + // + // schedule the custom action and add to progress bar + // + if (pwzCustomActionData && *pwzCustomActionData) + { + Assert(0 < cObjects); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecSecureObjects"), pwzCustomActionData, cObjects * COST_SECUREOBJECT); + ExitOnFailure(hr, "failed to schedule ExecSecureObjects action"); + } + +LExit: + ReleaseStr(pwzSecureObject); + ReleaseStr(pwzCustomActionData); + ReleaseStr(pwzData); + ReleaseStr(pwzTable); + ReleaseStr(pwzTargetPath); + + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + return WcaFinalize(er); +} + +/****************************************************************** + SchedSecureObjectsRollback - entry point for SchedSecureObjectsRollback Custom Action + + called as Type 1 CustomAction (binary DLL) from Windows Installer + in InstallExecuteSequence before SchedSecureObjects +******************************************************************/ +extern "C" UINT __stdcall SchedSecureObjectsRollback( + __in MSIHANDLE hInstall + ) +{ +// AssertSz(FALSE, "debug SchedSecureObjectsRollback"); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + LPWSTR pwzSecureObject = NULL; + LPWSTR pwzTable = NULL; + LPWSTR pwzTargetPath = NULL; + + PMSIHANDLE hView = NULL; + PMSIHANDLE hRec = NULL; + + LPWSTR pwzCustomActionData = NULL; + + eOBJECTTYPE eType = OT_UNKNOWN; + + // + // initialize + // + hr = WcaInitialize(hInstall, "SchedSecureObjectsRollback"); + ExitOnFailure(hr, "failed to initialize"); + + // + // loop through all the objects to be secured + // + hr = WcaOpenExecuteView(wzQUERY_SECUREOBJECTS, &hView); + ExitOnFailure(hr, "failed to open view on Wix4SecureObject table"); + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + hr = WcaGetRecordString(hRec, QSO_TABLE, &pwzTable); + ExitOnFailure(hr, "failed to get object table"); + + eType = EObjectTypeFromString(pwzTable); + + if (OT_UNKNOWN == eType) + { + ExitOnFailure(hr = E_INVALIDARG, "unknown SecureObject.Table: %ls", pwzTable); + } + + int iCompAttributes = 0; + hr = WcaGetRecordInteger(hRec, QSO_COMPATTRIBUTES, &iCompAttributes); + ExitOnFailure(hr, "failed to get Component attributes for secure object"); + + BOOL fIs64Bit = iCompAttributes & msidbComponentAttributes64bit; + + // Only process entries in the Wix4SecureObject table whose components match the bitness of this CA +#ifdef _WIN64 + if (!fIs64Bit) + { + continue; + } +#else + if (fIs64Bit) + { + continue; + } +#endif + + // get the object being secured that we are planning to schedule rollback for + hr = WcaGetRecordString(hRec, QSO_SECUREOBJECT, &pwzSecureObject); + ExitOnFailure(hr, "failed to get name of object"); + + hr = GetTargetPath(eType, pwzSecureObject, &pwzTargetPath); + ExitOnFailure(hr, "failed to get target path of object '%ls' in order to schedule rollback", pwzSecureObject); + + hr = StoreACLRollbackInfo(pwzTargetPath, pwzTable); + if (FAILED(hr)) + { + WcaLog(LOGMSG_STANDARD, "Failed to store ACL rollback information with error 0x%x - continuing", hr); + } + } + + // if we looped through all records all is well + if (E_NOMOREITEMS == hr) + { + hr = S_OK; + } + ExitOnFailure(hr, "failed while looping through all objects to schedule rollback for"); + +LExit: + ReleaseStr(pwzCustomActionData); + ReleaseStr(pwzSecureObject); + ReleaseStr(pwzTable); + ReleaseStr(pwzTargetPath); + + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + return WcaFinalize(er); +} + +/****************************************************************** + CaExecSecureObjects - entry point for SecureObjects Custom Action + called as Type 1025 CustomAction (deferred binary DLL) + + NOTE: deferred CustomAction since it modifies the machine + NOTE: CustomActionData == wzObject\twzTable\twzDomain\twzUser\tdwAttributes\tdwPermissions\t... +******************************************************************/ +extern "C" UINT __stdcall ExecSecureObjects( + __in MSIHANDLE hInstall + ) +{ +// AssertSz(FALSE, "debug ExecSecureObjects"); + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + + LPWSTR pwz = NULL; + LPWSTR pwzData = NULL; + LPWSTR pwzObject = NULL; + LPWSTR pwzTable = NULL; + LPWSTR pwzDomain = NULL; + DWORD dwRevision = 0; + LPWSTR pwzUser = NULL; + DWORD dwPermissions = 0; + DWORD dwAttributes = 0; + LPWSTR pwzAccount = NULL; + PSID psid = NULL; + + EXPLICIT_ACCESSW ea = {0}; + SE_OBJECT_TYPE objectType = SE_UNKNOWN_OBJECT_TYPE; + PSECURITY_DESCRIPTOR psd = NULL; + SECURITY_DESCRIPTOR_CONTROL sdc = {0}; + SECURITY_INFORMATION si = {0}; + PACL pAclExisting = NULL; // doesn't get freed + PACL pAclNew = NULL; + + PMSIHANDLE hActionRec = ::MsiCreateRecord(1); + + // + // initialize + // + hr = WcaInitialize(hInstall, "ExecSecureObjects"); + ExitOnFailure(hr, "failed to initialize"); + + hr = WcaGetProperty(L"CustomActionData", &pwzData); + ExitOnFailure(hr, "failed to get CustomActionData"); + + WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); + + pwz = pwzData; + + // + // loop through all the passed in data + // + while (pwz && *pwz) + { + hr = WcaReadStringFromCaData(&pwz, &pwzObject); + ExitOnFailure(hr, "failed to process CustomActionData"); + + hr = WcaReadStringFromCaData(&pwz, &pwzTable); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzDomain); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzUser); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwAttributes)); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwPermissions)); + ExitOnFailure(hr, "failed to process CustomActionData"); + + WcaLog(LOGMSG_VERBOSE, "Securing Object: %ls Type: %ls User: %ls", pwzObject, pwzTable, pwzUser); + + // + // create the appropriate SID + // + + // figure out the right user to put into the access block + if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Everyone")) + { + hr = AclGetWellKnownSid(WinWorldSid, &psid); + } + else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Administrators")) + { + hr = AclGetWellKnownSid(WinBuiltinAdministratorsSid, &psid); + } + else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"LocalSystem")) + { + hr = AclGetWellKnownSid(WinLocalSystemSid, &psid); + } + else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"LocalService")) + { + hr = AclGetWellKnownSid(WinLocalServiceSid, &psid); + } + else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"NetworkService")) + { + hr = AclGetWellKnownSid(WinNetworkServiceSid, &psid); + } + else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"AuthenticatedUser")) + { + hr = AclGetWellKnownSid(WinAuthenticatedUserSid, &psid); + } + else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Guests")) + { + hr = AclGetWellKnownSid(WinBuiltinGuestsSid, &psid); + } + else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"CREATOR OWNER")) + { + hr = AclGetWellKnownSid(WinCreatorOwnerSid, &psid); + } + else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"INTERACTIVE")) + { + hr = AclGetWellKnownSid(WinInteractiveSid, &psid); + } + else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Users")) + { + hr = AclGetWellKnownSid(WinBuiltinUsersSid, &psid); + } + else + { + hr = StrAllocFormatted(&pwzAccount, L"%s%s%s", pwzDomain, *pwzDomain ? L"\\" : L"", pwzUser); + ExitOnFailure(hr, "failed to build domain user name"); + + hr = AclGetAccountSid(NULL, pwzAccount, &psid); + } + ExitOnFailure(hr, "failed to get sid for account: %ls%ls%ls", pwzDomain, *pwzDomain ? L"\\" : L"", pwzUser); + + // + // build up the explicit access + // + ea.grfAccessMode = SET_ACCESS; + + if (dwAttributes & SECURE_OBJECT_ATTRIBUTE_INHERITABLE) + { + ea.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; + } + else + { + ea.grfInheritance = NO_INHERITANCE; + } + +#pragma prefast(push) +#pragma prefast(disable:25029) + ::BuildTrusteeWithSidW(&ea.Trustee, psid); +#pragma prefast(pop) + + objectType = SEObjectTypeFromString(const_cast (pwzTable)); + + // always add these permissions for services + // these are basic permissions that are often forgotten + if (0 == lstrcmpW(L"ServiceInstall", pwzTable)) + { + dwPermissions |= SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_INTERROGATE; + } + + ea.grfAccessPermissions = dwPermissions; + + if (SE_UNKNOWN_OBJECT_TYPE != objectType) + { + er = ::GetNamedSecurityInfoW(pwzObject, objectType, DACL_SECURITY_INFORMATION, NULL, NULL, &pAclExisting, NULL, &psd); + ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "failed to get security info for object: %ls", pwzObject); + + //Need to see if DACL is protected so getting Descriptor information + if (!::GetSecurityDescriptorControl(psd, &sdc, &dwRevision)) + { + ExitOnLastError(hr, "failed to get security descriptor control for object: %ls", pwzObject); + } + +#pragma prefast(push) +#pragma prefast(disable:25029) + er = ::SetEntriesInAclW(1, &ea, pAclExisting, &pAclNew); +#pragma prefast(pop) + ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "failed to add ACLs for object: %ls", pwzObject); + + if (sdc & SE_DACL_PROTECTED) + { + si = DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION; + } + else + { + si = DACL_SECURITY_INFORMATION; + } + er = ::SetNamedSecurityInfoW(pwzObject, objectType, si, NULL, NULL, pAclNew, NULL); + MessageExitOnFailure(hr = HRESULT_FROM_WIN32(er), msierrSecureObjectsFailedSet, "failed to set security info for object: %ls", pwzObject); + } + else + { + MessageExitOnFailure(hr = E_UNEXPECTED, msierrSecureObjectsUnknownType, "unknown object type: %ls", pwzTable); + } + + hr = WcaProgressMessage(COST_SECUREOBJECT, FALSE); + ExitOnFailure(hr, "failed to send progress message"); + + objectType = SE_UNKNOWN_OBJECT_TYPE; + } + +LExit: + ReleaseStr(pwzUser); + ReleaseStr(pwzDomain); + ReleaseStr(pwzTable); + ReleaseStr(pwzObject); + ReleaseStr(pwzData); + ReleaseStr(pwzAccount); + + if (pAclNew) + { + ::LocalFree(pAclNew); + } + if (psd) + { + ::LocalFree(psd); + } + if (psid) + { + AclFreeSid(psid); + } + + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + return WcaFinalize(er); +} + +extern "C" UINT __stdcall ExecSecureObjectsRollback( + __in MSIHANDLE hInstall + ) +{ +// AssertSz(FALSE, "debug ExecSecureObjectsRollback"); + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + + LPWSTR pwz = NULL; + LPWSTR pwzData = NULL; + LPWSTR pwzObject = NULL; + LPWSTR pwzTable = NULL; + LPWSTR pwzSecurityInfo = NULL; + + SE_OBJECT_TYPE objectType = SE_UNKNOWN_OBJECT_TYPE; + PSECURITY_DESCRIPTOR psd = NULL; + ULONG psdSize; + SECURITY_DESCRIPTOR_CONTROL sdc = {0}; + SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; + PACL pDacl = NULL; + BOOL bDaclPresent = false; + BOOL bDaclDefaulted = false; + DWORD dwRevision = 0; + int iProtected; + + // initialize + hr = WcaInitialize(hInstall, "ExecSecureObjectsRollback"); + ExitOnFailure(hr, "failed to initialize"); + + hr = WcaGetProperty(L"CustomActionData", &pwzData); + ExitOnFailure(hr, "failed to get CustomActionData"); + + WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); + + pwz = pwzData; + + hr = WcaReadStringFromCaData(&pwz, &pwzObject); + ExitOnFailure(hr, "failed to process CustomActionData"); + + hr = WcaReadStringFromCaData(&pwz, &pwzTable); + ExitOnFailure(hr, "failed to process CustomActionData"); + + objectType = SEObjectTypeFromString(const_cast (pwzTable)); + + if (SE_UNKNOWN_OBJECT_TYPE != objectType) + { + hr = WcaReadStringFromCaData(&pwz, &pwzSecurityInfo); + ExitOnFailure(hr, "failed to process CustomActionData"); + + hr = WcaReadIntegerFromCaData(&pwz, &iProtected); + ExitOnFailure(hr, "failed to process CustomActionData"); + + if (!::ConvertStringSecurityDescriptorToSecurityDescriptorW(pwzSecurityInfo,SDDL_REVISION_1,&psd,&psdSize)) + { + ExitOnLastError(hr, "failed to convert security descriptor string to a valid security descriptor"); + } + + if (!::GetSecurityDescriptorDacl(psd,&bDaclPresent,&pDacl,&bDaclDefaulted)) + { + hr = E_UNEXPECTED; + ExitOnFailure(hr, "failed to get security descriptor's DACL - error code: %d",pwzSecurityInfo,GetLastError()); + } + + // The below situation may always be caught by the above if block - the documentation isn't very clear. To be safe, we're going to test for it. + if (!bDaclPresent) + { + hr = E_UNEXPECTED; + ExitOnFailure(hr, "security descriptor does not contain a DACL"); + } + + //Need to see if DACL is protected so getting Descriptor information + if (!::GetSecurityDescriptorControl(psd, &sdc, &dwRevision)) + { + ExitOnLastError(hr, "failed to get security descriptor control for object: %ls", pwzObject); + } + + // Write a 1 if DACL is protected, 0 otherwise + switch (iProtected) + { + case 0: + // Unnecessary to do anything - leave si to the default flags + break; + + case 1: + si = si | PROTECTED_DACL_SECURITY_INFORMATION; + break; + + default: + hr = E_UNEXPECTED; + ExitOnFailure(hr, "unrecognized value in CustomActionData"); + break; + } + + er = ::SetNamedSecurityInfoW(pwzObject, objectType, si, NULL, NULL, pDacl, NULL); + ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "failed to set security info for object: %ls error code: %d", pwzObject, GetLastError()); + } + else + { + MessageExitOnFailure(hr = E_UNEXPECTED, msierrSecureObjectsUnknownType, "unknown object type: %ls", pwzTable); + } + +LExit: + ReleaseStr(pwzData); + ReleaseStr(pwzObject); + ReleaseStr(pwzTable); + ReleaseStr(pwzSecurityInfo); + + if (psd) + { + ::LocalFree(psd); + } + + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + return WcaFinalize(er); +} diff --git a/src/ext/Util/ca/serviceconfig.cpp b/src/ext/Util/ca/serviceconfig.cpp new file mode 100644 index 00000000..04b25ffa --- /dev/null +++ b/src/ext/Util/ca/serviceconfig.cpp @@ -0,0 +1,821 @@ +// Copyright (c) .NET 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" + +// structs +LPCWSTR wzQUERY_SERVICECONFIG = L"SELECT `ServiceName`, `Component_`, `NewService`, `FirstFailureActionType`, `SecondFailureActionType`, `ThirdFailureActionType`, `ResetPeriodInDays`, `RestartServiceDelayInSeconds`, `ProgramCommandLine`, `RebootMessage` FROM `Wix4ServiceConfig`"; +enum eQUERY_SERVICECONFIG { QSC_SERVICENAME = 1, QSC_COMPONENT, QSC_NEWSERVICE, QSC_FIRSTFAILUREACTIONTYPE, QSC_SECONDFAILUREACTIONTYPE, QSC_THIRDFAILUREACTIONTYPE, QSC_RESETPERIODINDAYS, QSC_RESTARTSERVICEDELAYINSECONDS, QSC_PROGRAMCOMMANDLINE, QSC_REBOOTMESSAGE }; + +// consts +LPCWSTR c_wzActionTypeNone = L"none"; +LPCWSTR c_wzActionTypeReboot = L"reboot"; +LPCWSTR c_wzActionTypeRestart = L"restart"; +LPCWSTR c_wzActionTypeRunCommand = L"runCommand"; + +// prototypes +static SC_ACTION_TYPE GetSCActionType( + __in LPCWSTR pwzActionTypeName + ); + +static HRESULT GetSCActionTypeString( + __in SC_ACTION_TYPE type, + __out_ecount(cchActionTypeString) LPWSTR wzActionTypeString, + __in DWORD cchActionTypeString + ); + +static HRESULT GetService( + __in SC_HANDLE hSCM, + __in LPCWSTR wzService, + __in DWORD dwOpenServiceAccess, + __out SC_HANDLE* phService + ); + +static HRESULT ConfigureService( + __in SC_HANDLE hSCM, + __in SC_HANDLE hService, + __in LPCWSTR wzServiceName, + __in DWORD dwRestartServiceDelayInSeconds, + __in LPCWSTR wzFirstFailureActionType, + __in LPCWSTR wzSecondFailureActionType, + __in LPCWSTR wzThirdFailureActionType, + __in DWORD dwResetPeriodInDays, + __in LPWSTR wzRebootMessage, + __in LPWSTR wzProgramCommandLine + ); + + +/****************************************************************** +SchedServiceConfig - entry point for SchedServiceConfig Custom Action + +called as Type 1 CustomAction (binary DLL) from Windows Installer +in InstallExecuteSequence before CaExecServiceConfig +********************************************************************/ +extern "C" UINT __stdcall SchedServiceConfig( + __in MSIHANDLE hInstall + ) +{ + //AssertSz(FALSE, "debug SchedServiceConfig"); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + LPWSTR pwzScriptKey = NULL; + LPWSTR pwzCustomActionData = NULL; + + PMSIHANDLE hView = NULL; + PMSIHANDLE hRec = NULL; + LPWSTR pwzData = NULL; + int iData = 0; + DWORD cServices = 0; + + // initialize + hr = WcaInitialize(hInstall, "SchedServiceConfig"); + ExitOnFailure(hr, "Failed to initialize."); + + // Get the script key for this CustomAction and put it on the front of the + // CustomActionData of the install action. + hr = WcaCaScriptCreateKey(&pwzScriptKey); + ExitOnFailure(hr, "Failed to get encoding key."); + + hr = WcaWriteStringToCaData(pwzScriptKey, &pwzCustomActionData); + ExitOnFailure(hr, "Failed to add encoding key to CustomActionData."); + + // Loop through all the services to be configured. + hr = WcaOpenExecuteView(wzQUERY_SERVICECONFIG, &hView); + ExitOnFailure(hr, "Failed to open view on Wix4ServiceConfig table."); + + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN; + INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN; + + // Get component name to check if we are installing it. If so + // then add the table data to the CustomActionData, otherwise + // skip it. + hr = WcaGetRecordString(hRec, QSC_COMPONENT, &pwzData); + ExitOnFailure(hr, "Failed to get component name"); + + hr = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); + ExitOnFailure(hr = HRESULT_FROM_WIN32(hr), "Failed to get install state for Component: %ls", pwzData); + + if (WcaIsInstalling(isInstalled, isAction)) + { + // Add the data to the CustomActionData (for install). + hr = WcaGetRecordFormattedString(hRec, QSC_SERVICENAME, &pwzData); + ExitOnFailure(hr, "Failed to get name of service."); + hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); + ExitOnFailure(hr, "Failed to add name to CustomActionData."); + + hr = WcaGetRecordInteger(hRec, QSC_NEWSERVICE, &iData); + ExitOnFailure(hr, "Failed to get Wix4ServiceConfig.NewService."); + hr = WcaWriteIntegerToCaData(0 != iData, &pwzCustomActionData); + ExitOnFailure(hr, "Failed to add NewService data to CustomActionData"); + + hr = WcaGetRecordString(hRec, QSC_FIRSTFAILUREACTIONTYPE, &pwzData); + ExitOnFailure(hr, "failed to get first failure action type"); + hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add data to CustomActionData"); + + hr = WcaGetRecordString(hRec, QSC_SECONDFAILUREACTIONTYPE, &pwzData); + ExitOnFailure(hr, "failed to get second failure action type"); + hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add data to CustomActionData"); + + hr = WcaGetRecordString(hRec, QSC_THIRDFAILUREACTIONTYPE, &pwzData); + ExitOnFailure(hr, "failed to get third failure action type"); + hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add data to CustomActionData"); + + hr = WcaGetRecordInteger(hRec, QSC_RESETPERIODINDAYS, &iData); + if (S_FALSE == hr) // deal w/ possible null value + { + iData = 0; + } + ExitOnFailure(hr, "failed to get reset period in days between service restart attempts."); + hr = WcaWriteIntegerToCaData(iData, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add data to CustomActionData"); + + hr = WcaGetRecordInteger(hRec, QSC_RESTARTSERVICEDELAYINSECONDS, &iData); + if (S_FALSE == hr) // deal w/ possible null value + { + iData = 0; + } + ExitOnFailure(hr, "failed to get server restart delay value."); + hr = WcaWriteIntegerToCaData(iData, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add data to CustomActionData"); + + hr = WcaGetRecordFormattedString(hRec, QSC_PROGRAMCOMMANDLINE, &pwzData); // null value already dealt w/ properly + ExitOnFailure(hr, "failed to get command line to run on service failure."); + hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add data to CustomActionData"); + + hr = WcaGetRecordString(hRec, QSC_REBOOTMESSAGE, &pwzData); // null value already dealt w/ properly + ExitOnFailure(hr, "failed to get message to send to users when server reboots due to service failure."); + hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); + ExitOnFailure(hr, "failed to add data to CustomActionData"); + + ++cServices; + } + } + + // if we looped through all records all is well + if (E_NOMOREITEMS == hr) + { + hr = S_OK; + } + ExitOnFailure(hr, "failed while looping through all objects to secure"); + + // setup CustomActionData and add to progress bar for download + if (0 < cServices) + { + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackServiceConfig"), pwzScriptKey, cServices * COST_SERVICECONFIG); + ExitOnFailure(hr, "failed to schedule RollbackServiceConfig action"); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecServiceConfig"), pwzCustomActionData, cServices * COST_SERVICECONFIG); + ExitOnFailure(hr, "failed to schedule ExecServiceConfig action"); + } + +LExit: + ReleaseStr(pwzData); + ReleaseStr(pwzCustomActionData); + ReleaseStr(pwzScriptKey); + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + +/****************************************************************** +CaExecServiceConfig - entry point for ServiceConfig Custom Action. + +NOTE: deferred CustomAction since it modifies the machine +NOTE: CustomActionData == wzServiceName\tfNewService\twzFirstFailureActionType\twzSecondFailureActionType\twzThirdFailureActionType\tdwResetPeriodInDays\tdwRestartServiceDelayInSeconds\twzProgramCommandLine\twzRebootMessage\twzServiceName\tfNewService\t... +*******************************************************************/ +extern "C" UINT __stdcall ExecServiceConfig( + __in MSIHANDLE hInstall + ) +{ + //AssertSz(FALSE, "debug ExecServiceConfig"); + HRESULT hr = S_OK; + DWORD er = 0; + + LPWSTR pwzCustomActionData = NULL; + LPWSTR pwz = NULL; + + LPWSTR pwzScriptKey = NULL; + WCA_CASCRIPT_HANDLE hRollbackScript = NULL; + + LPWSTR pwzServiceName = NULL; + BOOL fNewService = FALSE; + LPWSTR pwzFirstFailureActionType = NULL; + LPWSTR pwzSecondFailureActionType = NULL; + LPWSTR pwzThirdFailureActionType = NULL; + LPWSTR pwzProgramCommandLine = NULL; + LPWSTR pwzRebootMessage = NULL; + DWORD dwResetPeriodInDays = 0; + DWORD dwRestartServiceDelayInSeconds = 0; + + LPVOID lpMsgBuf = NULL; + SC_HANDLE hSCM = NULL; + SC_HANDLE hService = NULL; + + DWORD dwRestartDelay = 0; + WCHAR wzActionName[32] = { 0 }; + + DWORD cbExistingServiceConfig = 0; + + SERVICE_FAILURE_ACTIONSW* psfa = NULL; + + // initialize + hr = WcaInitialize(hInstall, "ExecServiceConfig"); + ExitOnFailure(hr, "failed to initialize"); + + // Open the Services Control Manager up front. + hSCM = ::OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT); + if (NULL == hSCM) + { + er = ::GetLastError(); + hr = HRESULT_FROM_WIN32(er); + +#pragma prefast(push) +#pragma prefast(disable:25028) + ::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, er, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpMsgBuf, 0, NULL); +#pragma prefast(pop) + + ExitOnFailure(hr, "Failed to get handle to SCM. Error: %ls", (LPWSTR)lpMsgBuf); + } + + // First, get the script key out of the CustomActionData and + // use that to create the rollback script for this action. + hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData); + ExitOnFailure(hr, "failed to get CustomActionData"); + + WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); + + pwz = pwzCustomActionData; + + hr = WcaReadStringFromCaData(&pwz, &pwzScriptKey); + if (!pwzScriptKey) + { + hr = E_UNEXPECTED; + ExitOnFailure(hr, "Failed due to unexpected CustomActionData passed."); + } + ExitOnFailure(hr, "Failed to read encoding key from CustomActionData."); + + hr = WcaCaScriptCreate(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, FALSE, &hRollbackScript); + ExitOnFailure(hr, "Failed to open rollback CustomAction script."); + + // Next, loop through the rest of the CustomActionData, processing + // each service config row in turn. + while (pwz && *pwz) + { + hr = WcaReadStringFromCaData(&pwz, &pwzServiceName); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&fNewService)); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzFirstFailureActionType); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzSecondFailureActionType); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzThirdFailureActionType); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwResetPeriodInDays)); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwRestartServiceDelayInSeconds)); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzProgramCommandLine); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzRebootMessage); + ExitOnFailure(hr, "failed to process CustomActionData"); + + WcaLog(LOGMSG_VERBOSE, "Configuring Service: %ls", pwzServiceName); + + // Open the handle with all the permissions we might need: + // SERVICE_QUERY_CONFIG is needed for QueryServiceConfig2(). + // SERVICE_CHANGE_CONFIG is needed for ChangeServiceConfig2(). + // SERVICE_START is required in order to handle SC_ACTION_RESTART action. + hr = GetService(hSCM, pwzServiceName, SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG | SERVICE_START, &hService); + ExitOnFailure(hr, "Failed to get service: %ls", pwzServiceName); + + // If we are configuring a service that existed on the machine, we need to + // read the existing service configuration and write it out to the rollback + // log so rollback can put it back if anything goes wrong. + if (!fNewService) + { + // First, read the existing service config. + if (!::QueryServiceConfig2W(hService, SERVICE_CONFIG_FAILURE_ACTIONS, NULL, 0, &cbExistingServiceConfig) && ERROR_INSUFFICIENT_BUFFER != ::GetLastError()) + { + ExitWithLastError(hr, "Failed to get current service config info."); + } + + psfa = static_cast(MemAlloc(cbExistingServiceConfig, TRUE)); + ExitOnNull(psfa, hr, E_OUTOFMEMORY, "failed to allocate memory for service failure actions."); + + if (!::QueryServiceConfig2W(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPBYTE)psfa, cbExistingServiceConfig, &cbExistingServiceConfig)) + { + ExitOnLastError(hr, "failed to Query Service."); + } + + // Build up rollback log so we can restore service state if necessary + hr = WcaCaScriptWriteString(hRollbackScript, pwzServiceName); + ExitOnFailure(hr, "Failed to add service name to Rollback Log"); + + // If this service struct is empty, fill in default values + if (3 > psfa->cActions) + { + hr = WcaCaScriptWriteString(hRollbackScript, c_wzActionTypeNone); + ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); + + hr = WcaCaScriptWriteString(hRollbackScript, c_wzActionTypeNone); + ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); + + hr = WcaCaScriptWriteString(hRollbackScript, c_wzActionTypeNone); + ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); + } + else + { + // psfa actually had actions defined, so use the first three. + for (int i = 0; i < 3; ++i) + { + hr = GetSCActionTypeString(psfa->lpsaActions[i].Type, wzActionName, countof(wzActionName)); + ExitOnFailure(hr, "failed to query SFA object"); + + if (SC_ACTION_RESTART == psfa->lpsaActions[i].Type) + { + dwRestartDelay = psfa->lpsaActions[i].Delay / 1000; + } + + hr = WcaCaScriptWriteString(hRollbackScript, wzActionName); + ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); + } + } + + hr = WcaCaScriptWriteNumber(hRollbackScript, psfa->dwResetPeriod / (24 * 60 * 60)); + ExitOnFailure(hr, "failed to add data to CustomActionData"); + + hr = WcaCaScriptWriteNumber(hRollbackScript, dwRestartDelay); + ExitOnFailure(hr, "failed to add data to CustomActionData"); + + // Handle the null cases. + if (!psfa->lpCommand) + { + psfa->lpCommand = L""; + } + hr = WcaCaScriptWriteString(hRollbackScript, psfa->lpCommand); + ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); + + // Handle the null cases. + if (!psfa->lpRebootMsg) + { + psfa->lpRebootMsg = L""; + } + hr = WcaCaScriptWriteString(hRollbackScript, psfa->lpRebootMsg); + ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); + + // Nudge the system to get all our rollback data written to disk. + WcaCaScriptFlush(hRollbackScript); + + ReleaseNullMem(psfa); + } + + hr = ConfigureService(hSCM, hService, pwzServiceName, dwRestartServiceDelayInSeconds, pwzFirstFailureActionType, + pwzSecondFailureActionType, pwzThirdFailureActionType, dwResetPeriodInDays, pwzRebootMessage, pwzProgramCommandLine); + ExitOnFailure(hr, "Failed to configure service: %ls", pwzServiceName); + + hr = WcaProgressMessage(COST_SERVICECONFIG, FALSE); + ExitOnFailure(hr, "failed to send progress message"); + + // Per-service cleanup + ::CloseServiceHandle(hService); + hService = NULL; + dwResetPeriodInDays = 0; + dwRestartServiceDelayInSeconds = 0; + } + +LExit: + WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_PRESERVE); + + if (lpMsgBuf) + { + ::LocalFree(lpMsgBuf); + } + + if (hService) + { + ::CloseServiceHandle(hService); + } + + if (hSCM) + { + ::CloseServiceHandle(hSCM); + } + + ReleaseMem(psfa); + + ReleaseStr(pwzRebootMessage); + ReleaseStr(pwzProgramCommandLine); + ReleaseStr(pwzThirdFailureActionType); + ReleaseStr(pwzSecondFailureActionType); + ReleaseStr(pwzFirstFailureActionType); + ReleaseStr(pwzServiceName); + ReleaseStr(pwzScriptKey); + ReleaseStr(pwzCustomActionData); + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + +/****************************************************************** +RollbackServiceConfig - entry point for ServiceConfig rollback + Custom Action. + +NOTE: CustomActionScript Data == wzServiceName\twzFirstFailureActionType\twzSecondFailureActionType\twzThirdFailureActionType\tdwResetPeriodInDays\tdwRestartServiceDelayInSeconds\twzProgramCommandLine\twzRebootMessage\twzServiceName\t... +*******************************************************************/ +extern "C" UINT __stdcall RollbackServiceConfig( + __in MSIHANDLE hInstall + ) +{ + //AssertSz(FALSE, "debug RollbackServiceConfig"); + HRESULT hr = S_OK; + DWORD er = 0; + + LPWSTR pwzCustomActionData = NULL; + LPWSTR pwz = NULL; + + LPWSTR pwzScriptKey = NULL; + WCA_CASCRIPT_HANDLE hRollbackScript = NULL; + + LPWSTR pwzServiceName = NULL; + LPWSTR pwzFirstFailureActionType = NULL; + LPWSTR pwzSecondFailureActionType = NULL; + LPWSTR pwzThirdFailureActionType = NULL; + LPWSTR pwzProgramCommandLine = NULL; + LPWSTR pwzRebootMessage = NULL; + DWORD dwResetPeriodInDays = 0; + DWORD dwRestartServiceDelayInSeconds = 0; + + LPVOID lpMsgBuf = NULL; + SC_HANDLE hSCM = NULL; + SC_HANDLE hService = NULL; + + // initialize + hr = WcaInitialize(hInstall, "RollbackServiceConfig"); + ExitOnFailure(hr, "Failed to initialize 'RollbackServiceConfig'."); + + // Open the Services Control Manager up front. + hSCM = ::OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT); + if (NULL == hSCM) + { + er = ::GetLastError(); + hr = HRESULT_FROM_WIN32(er); + +#pragma prefast(push) +#pragma prefast(disable:25028) + ::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, er, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpMsgBuf, 0, NULL); +#pragma prefast(pop) + + ExitOnFailure(hr, "Failed to get handle to SCM. Error: %ls", (LPWSTR)lpMsgBuf); + + // Make sure we still abort, in case hSCM was NULL but no error was returned from GetLastError + ExitOnNull(hSCM, hr, E_POINTER, "Getting handle to SCM reported success, but no handle was returned."); + } + + // Get the script key from the CustomAction data and use it to open + // the rollback log and read the data over the CustomActionData + // because all of the information is in the script data not the + // CustomActionData. + hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData); + ExitOnFailure(hr, "failed to get CustomActionData"); + + WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); + + pwz = pwzCustomActionData; + + hr = WcaReadStringFromCaData(&pwz, &pwzScriptKey); + if (!pwzScriptKey) + { + hr = E_UNEXPECTED; + ExitOnFailure(hr, "Failed due to unexpected CustomActionData passed."); + } + ExitOnFailure(hr, "Failed to read encoding key from CustomActionData."); + + hr = WcaCaScriptOpen(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, &hRollbackScript); + ExitOnFailure(hr, "Failed to open rollback CustomAction script."); + + hr = WcaCaScriptReadAsCustomActionData(hRollbackScript, &pwzCustomActionData); + ExitOnFailure(hr, "Failed to read rollback script into CustomAction data."); + + // Loop through the script's CustomActionData, processing each + // service config in turn. + pwz = pwzCustomActionData; + while (pwz && *pwz) + { + hr = WcaReadStringFromCaData(&pwz, &pwzServiceName); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzFirstFailureActionType); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzSecondFailureActionType); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzThirdFailureActionType); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwResetPeriodInDays)); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast(&dwRestartServiceDelayInSeconds)); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzProgramCommandLine); + ExitOnFailure(hr, "failed to process CustomActionData"); + hr = WcaReadStringFromCaData(&pwz, &pwzRebootMessage); + ExitOnFailure(hr, "failed to process CustomActionData"); + + WcaLog(LOGMSG_VERBOSE, "Reconfiguring Service: %ls", pwzServiceName); + + // Open the handle with all the permissions we might need. + // SERVICE_CHANGE_CONFIG is needed for ChangeServiceConfig2(). + // SERVICE_START is required in order to handle SC_ACTION_RESTART action. + hr = GetService(hSCM, pwzServiceName, SERVICE_CHANGE_CONFIG | SERVICE_START, &hService); + ExitOnFailure(hr, "Failed to get service: %ls", pwzServiceName); + + hr = ConfigureService(hSCM, hService, pwzServiceName, dwRestartServiceDelayInSeconds, pwzFirstFailureActionType, + pwzSecondFailureActionType, pwzThirdFailureActionType, dwResetPeriodInDays, pwzRebootMessage, pwzProgramCommandLine); + ExitOnFailure(hr, "Failed to configure service: %ls", pwzServiceName); + + hr = WcaProgressMessage(COST_SERVICECONFIG, FALSE); + ExitOnFailure(hr, "failed to send progress message"); + + // Per-service cleanup + ::CloseServiceHandle(hService); + hService = NULL; + dwResetPeriodInDays = 0; + dwRestartServiceDelayInSeconds = 0; + } + +LExit: + if (lpMsgBuf) // Allocated with FormatString. + { + ::LocalFree(lpMsgBuf); + } + + if (hService) + { + ::CloseServiceHandle(hService); + } + + if (hSCM) + { + ::CloseServiceHandle(hSCM); + } + + WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_DELETE); + + ReleaseStr(pwzRebootMessage); + ReleaseStr(pwzProgramCommandLine); + ReleaseStr(pwzThirdFailureActionType); + ReleaseStr(pwzSecondFailureActionType); + ReleaseStr(pwzFirstFailureActionType); + ReleaseStr(pwzServiceName); + ReleaseStr(pwzScriptKey); + ReleaseStr(pwzCustomActionData); + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + +/********************************************************** +GetSCActionType - helper function to return the SC_ACTION_TYPE +for a given string matching the allowed set. +REBOOT, RESTART, RUN_COMMAND and NONE +**********************************************************/ +static SC_ACTION_TYPE GetSCActionType( + __in LPCWSTR pwzActionTypeName + ) +{ + SC_ACTION_TYPE actionType; + + // verify that action types are valid. if not, just default to NONE + if (0 == lstrcmpiW(c_wzActionTypeReboot, pwzActionTypeName)) + { + actionType = SC_ACTION_REBOOT; + } + else if (0 == lstrcmpiW(c_wzActionTypeRestart, pwzActionTypeName)) + { + actionType = SC_ACTION_RESTART; + } + else if (0 == lstrcmpiW(c_wzActionTypeRunCommand, pwzActionTypeName)) + { + actionType = SC_ACTION_RUN_COMMAND; + } + else + { + // default to none + actionType = SC_ACTION_NONE; + } + + return actionType; +} + + +static HRESULT GetSCActionTypeString( + __in SC_ACTION_TYPE type, + __out_ecount(cchActionTypeString) LPWSTR wzActionTypeString, + __in DWORD cchActionTypeString + ) +{ + HRESULT hr = S_OK; + + switch (type) + { + case SC_ACTION_REBOOT: + hr = StringCchCopyW(wzActionTypeString, cchActionTypeString, c_wzActionTypeReboot); + ExitOnFailure(hr, "Failed to copy 'reboot' into action type."); + break; + case SC_ACTION_RESTART: + hr = StringCchCopyW(wzActionTypeString, cchActionTypeString, c_wzActionTypeRestart); + ExitOnFailure(hr, "Failed to copy 'restart' into action type."); + break; + case SC_ACTION_RUN_COMMAND: + hr = StringCchCopyW(wzActionTypeString, cchActionTypeString, c_wzActionTypeRunCommand); + ExitOnFailure(hr, "Failed to copy 'runCommand' into action type."); + break; + case SC_ACTION_NONE: + hr = StringCchCopyW(wzActionTypeString, cchActionTypeString, c_wzActionTypeNone); + ExitOnFailure(hr, "Failed to copy 'none' into action type."); + break; + default: + break; + } + +LExit: + return hr; +} + + +static HRESULT GetService( + __in SC_HANDLE hSCM, + __in LPCWSTR wzService, + __in DWORD dwOpenServiceAccess, + __out SC_HANDLE* phService + ) +{ + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + LPVOID lpMsgBuf = NULL; + + *phService = ::OpenServiceW(hSCM, wzService, dwOpenServiceAccess); + if (NULL == *phService) + { + er = ::GetLastError(); + hr = HRESULT_FROM_WIN32(er); + if (ERROR_SERVICE_DOES_NOT_EXIST == er) + { + ExitOnFailure(hr, "Service '%ls' does not exist on this system.", wzService); + } + else + { +#pragma prefast(push) +#pragma prefast(disable:25028) + ::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, er, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpMsgBuf, 0, NULL); +#pragma prefast(pop) + + ExitOnFailure(hr, "Failed to get handle to the service '%ls'. Error: %ls", wzService, (LPWSTR)lpMsgBuf); + } + } + +LExit: + if (lpMsgBuf) // Allocated with FormatString. + { + ::LocalFree(lpMsgBuf); + } + + return hr; +} + + +static HRESULT ConfigureService( + __in SC_HANDLE /*hSCM*/, + __in SC_HANDLE hService, + __in LPCWSTR wzServiceName, + __in DWORD dwRestartServiceDelayInSeconds, + __in LPCWSTR wzFirstFailureActionType, + __in LPCWSTR wzSecondFailureActionType, + __in LPCWSTR wzThirdFailureActionType, + __in DWORD dwResetPeriodInDays, + __in LPWSTR wzRebootMessage, + __in LPWSTR wzProgramCommandLine + ) +{ + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + + HANDLE hToken = NULL; + TOKEN_PRIVILEGES priv = { 0 }; + TOKEN_PRIVILEGES* pPrevPriv = NULL; + DWORD cbPrevPriv = 0; + BOOL fAdjustedPrivileges = FALSE; + + SC_ACTION actions[3]; // the UI always shows 3 actions, so we'll always do 3 + SERVICE_FAILURE_ACTIONSW sfa; + LPVOID lpMsgBuf = NULL; + + // Always get the shutdown privilege in case we need to configure service to reboot. + if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) + { + ExitWithLastError(hr, "Failed to get process token."); + } + + priv.PrivilegeCount = 1; + priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + if (!::LookupPrivilegeValueW(NULL, L"SeShutdownPrivilege", &priv.Privileges[0].Luid)) + { + ExitWithLastError(hr, "Failed to get shutdown privilege LUID."); + } + + cbPrevPriv = sizeof(TOKEN_PRIVILEGES); + pPrevPriv = static_cast(MemAlloc(cbPrevPriv, TRUE)); + ExitOnNull(pPrevPriv, hr, E_OUTOFMEMORY, "Failed to allocate memory for empty previous privileges."); + + if (!::AdjustTokenPrivileges(hToken, FALSE, &priv, cbPrevPriv, pPrevPriv, &cbPrevPriv)) + { + LPVOID pv = MemReAlloc(pPrevPriv, cbPrevPriv, TRUE); + ExitOnNull(pv, hr, E_OUTOFMEMORY, "Failed to allocate memory for previous privileges."); + pPrevPriv = static_cast(pv); + + if (!::AdjustTokenPrivileges(hToken, FALSE, &priv, cbPrevPriv, pPrevPriv, &cbPrevPriv)) + { + ExitWithLastError(hr, "Failed to get shutdown privilege LUID."); + } + } + + fAdjustedPrivileges = TRUE; + + // build up SC_ACTION array + // TODO: why is delay only respected when SC_ACTION_RESTART is requested? + actions[0].Type = GetSCActionType(wzFirstFailureActionType); + actions[0].Delay = 0; + if (SC_ACTION_RESTART == actions[0].Type) + { + actions[0].Delay = dwRestartServiceDelayInSeconds * 1000; // seconds to milliseconds + } + + actions[1].Type = GetSCActionType(wzSecondFailureActionType); + actions[1].Delay = 0; + if (SC_ACTION_RESTART == actions[1].Type) + { + actions[1].Delay = dwRestartServiceDelayInSeconds * 1000; // seconds to milliseconds + } + + actions[2].Type = GetSCActionType(wzThirdFailureActionType); + actions[2].Delay = 0; + if (SC_ACTION_RESTART == actions[2].Type) + { + actions[2].Delay = dwRestartServiceDelayInSeconds * 1000; // seconds to milliseconds + } + + // build up the SERVICE_FAILURE_ACTIONSW struct + sfa.dwResetPeriod = dwResetPeriodInDays * (24 * 60 * 60); // days to seconds + sfa.lpRebootMsg = wzRebootMessage; + sfa.lpCommand = wzProgramCommandLine; + sfa.cActions = countof(actions); + sfa.lpsaActions = actions; + + // Call ChangeServiceConfig2 to actually set up the failure actions + if (!::ChangeServiceConfig2W(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPVOID)&sfa)) + { + er = ::GetLastError(); + hr = HRESULT_FROM_WIN32(er); + +#pragma prefast(push) +#pragma prefast(disable:25028) + ::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, er, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpMsgBuf, 0, NULL); +#pragma prefast(pop) + + // Check if this is a service that can't be modified. + if (ERROR_CANNOT_DETECT_PROCESS_ABORT == er) + { + WcaLog(LOGMSG_STANDARD, "WARNING: Service \"%ls\" is not configurable on this server and will not be set.", wzServiceName); + } + ExitOnFailure(hr, "Cannot change service configuration. Error: %ls", (LPWSTR)lpMsgBuf); + + if (lpMsgBuf) + { + ::LocalFree(lpMsgBuf); + lpMsgBuf = NULL; + } + } + +LExit: + if (lpMsgBuf) + { + ::LocalFree(lpMsgBuf); + } + + if (fAdjustedPrivileges) + { + ::AdjustTokenPrivileges(hToken, FALSE, pPrevPriv, 0, NULL, NULL); + } + + ReleaseMem(pPrevPriv); + ReleaseHandle(hToken); + + return hr; +} diff --git a/src/ext/Util/ca/shellexecca.cpp b/src/ext/Util/ca/shellexecca.cpp new file mode 100644 index 00000000..ea21d3bd --- /dev/null +++ b/src/ext/Util/ca/shellexecca.cpp @@ -0,0 +1,271 @@ +// Copyright (c) .NET 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 ShellExec( + __in LPCWSTR wzTarget, + __in BOOL fUnelevated + ) +{ + HRESULT hr = S_OK; + LPWSTR sczWorkingDirectory = NULL; + + // a reasonable working directory (not the system32 default from MSI) is the directory where the target lives + hr = PathGetDirectory(wzTarget, &sczWorkingDirectory); + ExitOnFailure(hr, "failed to get directory for target: %ls", wzTarget); + + if (!DirExists(sczWorkingDirectory, NULL)) + { + ReleaseNullStr(sczWorkingDirectory); + } + + if (fUnelevated) + { + hr = ShelExecUnelevated(wzTarget, NULL, NULL, sczWorkingDirectory, SW_SHOWDEFAULT); + ExitOnFailure(hr, "ShelExecUnelevated failed with target %ls", wzTarget); + } + else + { + HINSTANCE hinst = ::ShellExecuteW(NULL, NULL, wzTarget, NULL, sczWorkingDirectory, SW_SHOWDEFAULT); + if (hinst <= HINSTANCE(32)) + { + LONG64 code = reinterpret_cast(hinst); + switch (code) + { + case ERROR_FILE_NOT_FOUND: + hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + break; + case ERROR_PATH_NOT_FOUND: + hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); + break; + case ERROR_BAD_FORMAT: + hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT); + break; + case SE_ERR_ASSOCINCOMPLETE: + case SE_ERR_NOASSOC: + hr = HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION); + break; + case SE_ERR_DDEBUSY: + case SE_ERR_DDEFAIL: + case SE_ERR_DDETIMEOUT: + hr = HRESULT_FROM_WIN32(ERROR_DDE_FAIL); + break; + case SE_ERR_DLLNOTFOUND: + hr = HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND); + break; + case SE_ERR_OOM: + hr = E_OUTOFMEMORY; + break; + case SE_ERR_ACCESSDENIED: + hr = E_ACCESSDENIED; + break; + default: + hr = E_FAIL; + } + + ExitOnFailure(hr, "ShellExec failed with return code %llu.", code); + } + } + + +LExit: + ReleaseStr(sczWorkingDirectory); + return hr; +} + +extern "C" UINT __stdcall WixShellExec( + __in MSIHANDLE hInstall + ) +{ + Assert(hInstall); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + LPWSTR pwzTarget = NULL; + + hr = WcaInitialize(hInstall, "WixShellExec"); + ExitOnFailure(hr, "failed to initialize"); + + hr = WcaGetFormattedProperty(L"WixShellExecTarget", &pwzTarget); + ExitOnFailure(hr, "failed to get WixShellExecTarget"); + + WcaLog(LOGMSG_VERBOSE, "WixShellExecTarget is %ls", pwzTarget); + + if (!pwzTarget || !*pwzTarget) + { + hr = E_INVALIDARG; + ExitOnFailure(hr, "failed to get WixShellExecTarget"); + } + + hr = ShellExec(pwzTarget, FALSE); + ExitOnFailure(hr, "failed to launch target"); + +LExit: + ReleaseStr(pwzTarget); + + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + return WcaFinalize(er); +} + +extern "C" UINT __stdcall WixUnelevatedShellExec( + __in MSIHANDLE hInstall + ) +{ + Assert(hInstall); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + LPWSTR pwzTarget = NULL; + + hr = WcaInitialize(hInstall, "WixUnelevatedShellExec"); + ExitOnFailure(hr, "failed to initialize"); + + hr = WcaGetFormattedProperty(L"WixUnelevatedShellExecTarget", &pwzTarget); + ExitOnFailure(hr, "failed to get WixUnelevatedShellExecTarget"); + + WcaLog(LOGMSG_VERBOSE, "WixUnelevatedShellExecTarget is %ls", pwzTarget); + + if (!pwzTarget || !*pwzTarget) + { + hr = E_INVALIDARG; + ExitOnFailure(hr, "failed to get WixShellExecTarget"); + } + + hr = ShellExec(pwzTarget, TRUE); + ExitOnFailure(hr, "failed to launch target"); + +LExit: + ReleaseStr(pwzTarget); + + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + return WcaFinalize(er); +} + +// +// ExtractBinary extracts the data from the Binary table row with the given ID into a file. +// +HRESULT ExtractBinary( + __in LPCWSTR wzBinaryId, + __out BYTE** pbData, + __out DWORD* pcbData + ) +{ + HRESULT hr = S_OK; + LPWSTR pwzSql = NULL; + PMSIHANDLE hView; + PMSIHANDLE hRec; + + // make sure we're not horked from the get-go + hr = WcaTableExists(L"Binary"); + if (S_OK != hr) + { + if (SUCCEEDED(hr)) + { + hr = E_UNEXPECTED; + } + ExitOnFailure(hr, "There is no Binary table."); + } + + ExitOnNull(wzBinaryId, hr, E_INVALIDARG, "Binary ID cannot be null"); + ExitOnNull(*wzBinaryId, hr, E_INVALIDARG, "Binary ID cannot be empty string"); + + hr = StrAllocFormatted(&pwzSql, L"SELECT `Data` FROM `Binary` WHERE `Name`=\'%s\'", wzBinaryId); + 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, pcbData); + ExitOnFailure(hr, "Failed to read Binary.Data."); + +LExit: + ReleaseStr(pwzSql); + + return hr; +} + +extern "C" UINT __stdcall WixShellExecBinary( + __in MSIHANDLE hInstall + ) +{ + Assert(hInstall); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + LPWSTR pwzBinary = NULL; + LPWSTR pwzFilename = NULL; + BYTE* pbData = NULL; + DWORD cbData = 0; + HANDLE hFile = INVALID_HANDLE_VALUE; + +#if 0 + ::MessageBoxA(0, "WixShellExecBinary", "-->> ATTACH HERE", MB_OK); +#endif + + hr = WcaInitialize(hInstall, "WixShellExecBinary"); + ExitOnFailure(hr, "failed to initialize"); + + hr = WcaGetFormattedProperty(L"WixShellExecBinaryId", &pwzBinary); + ExitOnFailure(hr, "failed to get WixShellExecBinaryId"); + + WcaLog(LOGMSG_VERBOSE, "WixShellExecBinaryId is %ls", pwzBinary); + + if (!pwzBinary || !*pwzBinary) + { + hr = E_INVALIDARG; + ExitOnFailure(hr, "failed to get WixShellExecBinaryId"); + } + + // get temporary path for extracted file + StrAlloc(&pwzFilename, MAX_PATH); + ExitOnFailure(hr, "Failed to allocate temporary path"); + ::GetTempPathW(MAX_PATH, pwzFilename); + hr = ::StringCchCatW(pwzFilename, MAX_PATH, pwzBinary); + ExitOnFailure(hr, "Failed to append filename."); + + // grab the bits + hr = ExtractBinary(pwzBinary, &pbData, &cbData); + ExitOnFailure(hr, "failed to extract binary data"); + + // write 'em to the temp file + hFile = ::CreateFileW(pwzFilename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (INVALID_HANDLE_VALUE == hFile) + { + ExitWithLastError(hr, "Failed to open new temp file: %ls", pwzFilename); + } + + DWORD cbWritten = 0; + if (!::WriteFile(hFile, pbData, cbData, &cbWritten, NULL)) + { + ExitWithLastError(hr, "Failed to write data to new temp file: %ls", pwzFilename); + } + + // close it + ::CloseHandle(hFile); + hFile = INVALID_HANDLE_VALUE; + + // and run it + hr = ShellExec(pwzFilename, FALSE); + ExitOnFailure(hr, "failed to launch target: %ls", pwzFilename); + +LExit: + ReleaseStr(pwzBinary); + ReleaseStr(pwzFilename); + ReleaseMem(pbData); + if (INVALID_HANDLE_VALUE != hFile) + { + ::CloseHandle(hFile); + } + + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + return WcaFinalize(er); +} diff --git a/src/ext/Util/ca/test.cpp b/src/ext/Util/ca/test.cpp new file mode 100644 index 00000000..c4d215f0 --- /dev/null +++ b/src/ext/Util/ca/test.cpp @@ -0,0 +1,269 @@ +// Copyright (c) .NET 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 WIXCA_UITHREAD_CLASS_WINDOW L"WixCaMessageWindow" + +extern HMODULE g_hInstCADLL; + + +// structs + +struct UITHREAD_CONTEXT +{ + HANDLE hInitializedEvent; + HINSTANCE hInstance; + HWND hWnd; +}; + + +// internal function declarations + +static HRESULT CreateMessageWindow( + __out HWND* phWnd + ); + +static void CloseMessageWindow( + __in HWND hWnd + ); + +static DWORD WINAPI ThreadProc( + __in LPVOID pvContext + ); + +static LRESULT CALLBACK WndProc( + __in HWND hWnd, + __in UINT uMsg, + __in WPARAM wParam, + __in LPARAM lParam + ); + + +/****************************************************************** +WixFailWhenDeferred - entry point for WixFailWhenDeferred + custom action which always fails when running as a deferred + custom action (otherwise it blindly succeeds). It's useful when + testing the rollback of deferred custom actions: Schedule it + immediately after the rollback/deferred CA pair you're testing + and it will fail, causing your rollback CA to get invoked. +********************************************************************/ +extern "C" UINT __stdcall WixFailWhenDeferred( + __in MSIHANDLE hInstall + ) +{ + return ::MsiGetMode(hInstall, MSIRUNMODE_SCHEDULED) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS; +} + +/****************************************************************** +WixWaitForEvent - entry point for WixWaitForEvent custom action + which waits for either the WixWaitForEventFail or + WixWaitForEventSucceed named auto reset events. Signaling the + WixWaitForEventFail event will return ERROR_INSTALL_FAILURE or + signaling the WixWaitForEventSucceed event will return + ERROR_SUCCESS. Both events are declared in the Global\ namespace. +********************************************************************/ +extern "C" UINT __stdcall WixWaitForEvent( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + HWND hMessageWindow = NULL; + LPCWSTR wzSDDL = L"D:(A;;GA;;;WD)"; + OS_VERSION version = OS_VERSION_UNKNOWN; + DWORD dwServicePack = 0; + PSECURITY_DESCRIPTOR pSD = NULL; + SECURITY_ATTRIBUTES sa = { }; + HANDLE rghEvents[2]; + + hr = WcaInitialize(hInstall, "WixWaitForEvent"); + ExitOnFailure(hr, "Failed to initialize."); + + // Create a window to prevent shutdown requests. + hr = CreateMessageWindow(&hMessageWindow); + ExitOnFailure(hr, "Failed to create message window."); + + // If running on Vista/2008 or newer use integrity enhancements. + OsGetVersion(&version, &dwServicePack); + if (OS_VERSION_VISTA <= version) + { + // Add SACL to allow Everyone to signal from a medium integrity level. + wzSDDL = L"D:(A;;GA;;;WD)S:(ML;;NW;;;ME)"; + } + + // Create the security descriptor and attributes for the events. + if (!::ConvertStringSecurityDescriptorToSecurityDescriptorW(wzSDDL, SDDL_REVISION_1, &pSD, NULL)) + { + ExitWithLastError(hr, "Failed to create the security descriptor for the events."); + } + + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = pSD; + sa.bInheritHandle = FALSE; + + rghEvents[0] = ::CreateEventW(&sa, FALSE, FALSE, L"Global\\WixWaitForEventFail"); + ExitOnNullWithLastError(rghEvents[0], hr, "Failed to create the Global\\WixWaitForEventFail event."); + + rghEvents[1] = ::CreateEventW(&sa, FALSE, FALSE, L"Global\\WixWaitForEventSucceed"); + ExitOnNullWithLastError(rghEvents[1], hr, "Failed to create the Global\\WixWaitForEventSucceed event."); + + // Wait for either of the events to be signaled and handle accordingly. + er = ::WaitForMultipleObjects(countof(rghEvents), rghEvents, FALSE, INFINITE); + switch (er) + { + case WAIT_OBJECT_0 + 0: + er = ERROR_INSTALL_FAILURE; + break; + case WAIT_OBJECT_0 + 1: + er = ERROR_SUCCESS; + break; + default: + ExitOnWin32Error(er, hr, "Unexpected failure."); + } + +LExit: + ReleaseHandle(rghEvents[1]); + ReleaseHandle(rghEvents[0]); + + if (pSD) + { + ::LocalFree(pSD); + } + + if (hMessageWindow) + { + CloseMessageWindow(hMessageWindow); + } + + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + + return WcaFinalize(er); +} + + +// internal function definitions + +static HRESULT CreateMessageWindow( + __out HWND* phWnd + ) +{ + HRESULT hr = S_OK; + HANDLE rgWaitHandles[2] = { }; + UITHREAD_CONTEXT context = { }; + + // Create event to signal after the UI thread / window is initialized. + rgWaitHandles[0] = ::CreateEventW(NULL, TRUE, FALSE, NULL); + ExitOnNullWithLastError(rgWaitHandles[0], hr, "Failed to create initialization event."); + + // Pass necessary information to create the window. + context.hInitializedEvent = rgWaitHandles[0]; + context.hInstance = (HINSTANCE)g_hInstCADLL; + + // Create our separate UI thread. + rgWaitHandles[1] = ::CreateThread(NULL, 0, ThreadProc, &context, 0, NULL); + ExitOnNullWithLastError(rgWaitHandles[1], hr, "Failed to create the UI thread."); + + // Wait for either the thread to be initialized or the window to exit / fail prematurely. + ::WaitForMultipleObjects(countof(rgWaitHandles), rgWaitHandles, FALSE, INFINITE); + + // Pass the window back to the caller. + *phWnd = context.hWnd; + +LExit: + ReleaseHandle(rgWaitHandles[1]); + ReleaseHandle(rgWaitHandles[0]); + + return hr; +} + +static void CloseMessageWindow( + __in HWND hWnd + ) +{ + if (::IsWindow(hWnd)) + { + ::PostMessageW(hWnd, WM_CLOSE, 0, 0); + } +} + +static DWORD WINAPI ThreadProc( + __in LPVOID pvContext + ) +{ + HRESULT hr = S_OK; + UITHREAD_CONTEXT* pContext = static_cast(pvContext); + + WNDCLASSW wc = { }; + BOOL fRegistered = TRUE; + HWND hWnd = NULL; + + BOOL fRet = FALSE; + MSG msg = { }; + + wc.lpfnWndProc = WndProc; + wc.hInstance = pContext->hInstance; + wc.lpszClassName = WIXCA_UITHREAD_CLASS_WINDOW; + + if (!::RegisterClassW(&wc)) + { + ExitWithLastError(hr, "Failed to register window."); + } + + fRegistered = TRUE; + + // Create the window to handle reboots without activating it. + hWnd = ::CreateWindowExW(WS_EX_TOOLWINDOW, wc.lpszClassName, NULL, WS_POPUP | WS_VISIBLE, CW_USEDEFAULT, SW_SHOWNA, 0, 0, HWND_DESKTOP, NULL, pContext->hInstance, NULL); + ExitOnNullWithLastError(hWnd, hr, "Failed to create window."); + + // Persist the window handle and let the caller know we've initialized. + pContext->hWnd = hWnd; + ::SetEvent(pContext->hInitializedEvent); + + // Pump messages until the window is closed. + while (0 != (fRet = ::GetMessageW(&msg, NULL, 0, 0))) + { + if (-1 == fRet) + { + hr = E_UNEXPECTED; + ExitOnFailure(hr, "Unexpected return value from message pump."); + } + else if (!::IsDialogMessageW(msg.hwnd, &msg)) + { + ::TranslateMessage(&msg); + ::DispatchMessageW(&msg); + } + } + +LExit: + if (fRegistered) + { + ::UnregisterClassW(WIXCA_UITHREAD_CLASS_WINDOW, pContext->hInstance); + } + + return hr; +} + +static LRESULT CALLBACK WndProc( + __in HWND hWnd, + __in UINT uMsg, + __in WPARAM wParam, + __in LPARAM lParam + ) +{ + switch (uMsg) + { + case WM_QUERYENDSESSION: + // Prevent the process from being shut down. + WcaLog(LOGMSG_VERBOSE, "Disallowed system request to shut down the custom action server."); + return FALSE; + + case WM_DESTROY: + ::PostQuitMessage(0); + return 0; + } + + return ::DefWindowProcW(hWnd, uMsg, wParam, lParam); +} diff --git a/src/ext/Util/ca/utilca.cpp b/src/ext/Util/ca/utilca.cpp new file mode 100644 index 00000000..37664a1c --- /dev/null +++ b/src/ext/Util/ca/utilca.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/Util/ca/utilca.def b/src/ext/Util/ca/utilca.def new file mode 100644 index 00000000..412d86a3 --- /dev/null +++ b/src/ext/Util/ca/utilca.def @@ -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. + + +LIBRARY "utilca" + +EXPORTS +; BroadcastSettingChange.cpp + WixBroadcastSettingChange + WixBroadcastEnvironmentChange +; checkreboot.cpp + WixCheckRebootRequired +; closeapps.cpp + WixCloseApplications + WixCloseApplicationsDeferred +; exitearlywithsuccess.cpp + WixExitEarlyWithSuccess +; FormatFiles.cpp + WixSchedFormatFiles + WixExecFormatFiles +; osinfo.cpp + WixQueryOsInfo + WixQueryOsDirs + WixQueryOsWellKnownSID + WixQueryOsDriverInfo +; netshortcuts.cpp + WixSchedInternetShortcuts + WixCreateInternetShortcuts + WixRollbackInternetShortcuts +; qtexecca.cpp + CAQuietExec + CAQuietExec64 + WixQuietExec + WixQuietExec64 + WixSilentExec + WixSilentExec64 +; RemoveFoldersEx.cpp + WixRemoveFoldersEx +; RemoveRegistryKeysEx.cpp + WixRemoveRegistryKeysEx +;scaexec.cpp + RegisterPerfCounterData + UnregisterPerfCounterData + RegisterPerfmon + UnregisterPerfmon + CreateSmb + DropSmb + CreateUser + CreateUserRollback + RemoveUser +;scasched.cpp + ConfigurePerfmonInstall + ConfigurePerfmonUninstall + ConfigureSmbInstall + ConfigureSmbUninstall + ConfigureUsers + InstallPerfCounterData + UninstallPerfCounterData + ConfigurePerfmonManifestRegister + ConfigurePerfmonManifestUnregister + ConfigureEventManifestRegister + ConfigureEventManifestUnregister +; RestartManager.cpp + WixRegisterRestartResources +; secureobj.cpp + SchedSecureObjects + SchedSecureObjectsRollback + ExecSecureObjects + ExecSecureObjectsRollback +; serviceconfig.cpp + SchedServiceConfig + ExecServiceConfig + RollbackServiceConfig +; shellexecca.cpp + WixShellExec + WixShellExecBinary + WixUnelevatedShellExec +; test.cpp + WixFailWhenDeferred + WixWaitForEvent +; TouchFile.cpp + WixTouchFileDuringInstall + WixTouchFileDuringUninstall + WixExecuteTouchFile +; xmlfile.cpp + SchedXmlFile + ExecXmlFile + ExecXmlFileRollback +; xmlconfig.cpp + SchedXmlConfig + ExecXmlConfig + ExecXmlConfigRollback diff --git a/src/ext/Util/ca/utilca.vcxproj b/src/ext/Util/ca/utilca.vcxproj new file mode 100644 index 00000000..7b64db95 --- /dev/null +++ b/src/ext/Util/ca/utilca.vcxproj @@ -0,0 +1,106 @@ + + + + + + + Debug + ARM64 + + + Release + ARM64 + + + Debug + X64 + + + Release + X64 + + + Debug + Win32 + + + Release + Win32 + + + + + {076018F7-19BD-423A-ABBF-229273DA08D8} + DynamicLibrary + utilca + v142 + Unicode + utilca.def + WiX Toolset Util CustomAction + + + + + + + activeds.lib;adsiid.lib;msi.lib;netapi32.lib;shlwapi.lib + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ext/Util/nuget.config b/src/ext/Util/nuget.config new file mode 100644 index 00000000..8d711148 --- /dev/null +++ b/src/ext/Util/nuget.config @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/.Data/burn.exe b/src/ext/Util/test/WixToolsetTest.Util/TestData/.Data/burn.exe new file mode 100644 index 00000000..2a4f423f Binary files /dev/null and b/src/ext/Util/test/WixToolsetTest.Util/TestData/.Data/burn.exe differ diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.en-us.wxl b/src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.en-us.wxl new file mode 100644 index 00000000..f50a5386 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.en-us.wxl @@ -0,0 +1,8 @@ + + + + ~TestBundle + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.wxs new file mode 100644 index 00000000..7fef0725 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.wxs @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/MsiPackage/Shared.dll b/src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/MsiPackage/Shared.dll new file mode 100644 index 00000000..0e461ba8 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/MsiPackage/Shared.dll @@ -0,0 +1 @@ +This is Shared.dll. \ No newline at end of file diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/MsiPackage/test.txt b/src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/MsiPackage/test.txt new file mode 100644 index 00000000..8b986220 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/MsiPackage/test.txt @@ -0,0 +1 @@ +This is test.txt \ No newline at end of file diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/fakeba.dll b/src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/fakeba.dll new file mode 100644 index 00000000..970efdf0 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/fakeba.dll @@ -0,0 +1 @@ +This is a fakeba.dll \ No newline at end of file diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/test.msi b/src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/test.msi new file mode 100644 index 00000000..0722d60e Binary files /dev/null and b/src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/test.msi differ diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/CloseApplication/Package.en-us.wxl b/src/ext/Util/test/WixToolsetTest.Util/TestData/CloseApplication/Package.en-us.wxl new file mode 100644 index 00000000..5301bb1a --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/CloseApplication/Package.en-us.wxl @@ -0,0 +1,9 @@ + + + + A newer version of [ProductName] is already installed. + MsiPackage + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/CloseApplication/Package.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/CloseApplication/Package.wxs new file mode 100644 index 00000000..8e054256 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/CloseApplication/Package.wxs @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/CloseApplication/PackageComponents.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/CloseApplication/PackageComponents.wxs new file mode 100644 index 00000000..e27b3c43 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/CloseApplication/PackageComponents.wxs @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/CloseApplication/example.txt b/src/ext/Util/test/WixToolsetTest.Util/TestData/CloseApplication/example.txt new file mode 100644 index 00000000..1b4ffe8a --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/CloseApplication/example.txt @@ -0,0 +1 @@ +This is example.txt. \ No newline at end of file diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/EventManifest/Package.en-us.wxl b/src/ext/Util/test/WixToolsetTest.Util/TestData/EventManifest/Package.en-us.wxl new file mode 100644 index 00000000..5301bb1a --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/EventManifest/Package.en-us.wxl @@ -0,0 +1,9 @@ + + + + A newer version of [ProductName] is already installed. + MsiPackage + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/EventManifest/Package.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/EventManifest/Package.wxs new file mode 100644 index 00000000..daae573a --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/EventManifest/Package.wxs @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/EventManifest/PackageComponents.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/EventManifest/PackageComponents.wxs new file mode 100644 index 00000000..2ec8ce82 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/EventManifest/PackageComponents.wxs @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/EventManifest/example.txt b/src/ext/Util/test/WixToolsetTest.Util/TestData/EventManifest/example.txt new file mode 100644 index 00000000..1b4ffe8a --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/EventManifest/example.txt @@ -0,0 +1 @@ +This is example.txt. \ No newline at end of file diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.en-us.wxl b/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.en-us.wxl new file mode 100644 index 00000000..5301bb1a --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.en-us.wxl @@ -0,0 +1,9 @@ + + + + A newer version of [ProductName] is already installed. + MsiPackage + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.ico b/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.ico new file mode 100644 index 00000000..53134de7 Binary files /dev/null and b/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.ico differ diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.wxs new file mode 100644 index 00000000..daae573a --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.wxs @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/PackageComponents.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/PackageComponents.wxs new file mode 100644 index 00000000..2a1b4347 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/PackageComponents.wxs @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/example.txt b/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/example.txt new file mode 100644 index 00000000..1b4ffe8a --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcut/example.txt @@ -0,0 +1 @@ +This is example.txt. \ No newline at end of file diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcutModule/Module.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcutModule/Module.wxs new file mode 100644 index 00000000..1355d42e --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcutModule/Module.wxs @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcutModule/ModuleComponents.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcutModule/ModuleComponents.wxs new file mode 100644 index 00000000..2a1b4347 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcutModule/ModuleComponents.wxs @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcutModule/Package.ico b/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcutModule/Package.ico new file mode 100644 index 00000000..53134de7 Binary files /dev/null and b/src/ext/Util/test/WixToolsetTest.Util/TestData/InternetShortcutModule/Package.ico differ diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/Package.en-us.wxl b/src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/Package.en-us.wxl new file mode 100644 index 00000000..5301bb1a --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/Package.en-us.wxl @@ -0,0 +1,9 @@ + + + + A newer version of [ProductName] is already installed. + MsiPackage + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/Package.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/Package.wxs new file mode 100644 index 00000000..daae573a --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/Package.wxs @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/PackageComponents.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/PackageComponents.wxs new file mode 100644 index 00000000..0634d7d4 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/PackageComponents.wxs @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/example.txt b/src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/example.txt new file mode 100644 index 00000000..1b4ffe8a --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/example.txt @@ -0,0 +1 @@ +This is example.txt. \ No newline at end of file diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/Package.en-us.wxl b/src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/Package.en-us.wxl new file mode 100644 index 00000000..5301bb1a --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/Package.en-us.wxl @@ -0,0 +1,9 @@ + + + + A newer version of [ProductName] is already installed. + MsiPackage + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/Package.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/Package.wxs new file mode 100644 index 00000000..abf0dbb4 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/Package.wxs @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/PackageComponents.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/PackageComponents.wxs new file mode 100644 index 00000000..e27b3c43 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/PackageComponents.wxs @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/example.txt b/src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/example.txt new file mode 100644 index 00000000..1b4ffe8a --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/example.txt @@ -0,0 +1 @@ +This is example.txt. \ No newline at end of file diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/RemoveFolderEx/Module.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/RemoveFolderEx/Module.wxs new file mode 100644 index 00000000..2c2be584 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/RemoveFolderEx/Module.wxs @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/RemoveFolderEx/ModuleComponents.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/RemoveFolderEx/ModuleComponents.wxs new file mode 100644 index 00000000..236d9df0 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/RemoveFolderEx/ModuleComponents.wxs @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/RemoveRegistryKeyEx/Module.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/RemoveRegistryKeyEx/Module.wxs new file mode 100644 index 00000000..32b246f4 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/RemoveRegistryKeyEx/Module.wxs @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/RemoveRegistryKeyEx/ModuleComponents.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/RemoveRegistryKeyEx/ModuleComponents.wxs new file mode 100644 index 00000000..0a0c8cb6 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/RemoveRegistryKeyEx/ModuleComponents.wxs @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/UsingFileShare/Package.en-us.wxl b/src/ext/Util/test/WixToolsetTest.Util/TestData/UsingFileShare/Package.en-us.wxl new file mode 100644 index 00000000..5301bb1a --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/UsingFileShare/Package.en-us.wxl @@ -0,0 +1,9 @@ + + + + A newer version of [ProductName] is already installed. + MsiPackage + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/UsingFileShare/Package.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/UsingFileShare/Package.wxs new file mode 100644 index 00000000..daae573a --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/UsingFileShare/Package.wxs @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/UsingFileShare/PackageComponents.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/UsingFileShare/PackageComponents.wxs new file mode 100644 index 00000000..7cedbb30 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/UsingFileShare/PackageComponents.wxs @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/UsingFileShare/example.txt b/src/ext/Util/test/WixToolsetTest.Util/TestData/UsingFileShare/example.txt new file mode 100644 index 00000000..1b4ffe8a --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/UsingFileShare/example.txt @@ -0,0 +1 @@ +This is example.txt. \ No newline at end of file diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/XmlConfig/Package.en-us.wxl b/src/ext/Util/test/WixToolsetTest.Util/TestData/XmlConfig/Package.en-us.wxl new file mode 100644 index 00000000..5301bb1a --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/XmlConfig/Package.en-us.wxl @@ -0,0 +1,9 @@ + + + + A newer version of [ProductName] is already installed. + MsiPackage + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/XmlConfig/Package.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/XmlConfig/Package.wxs new file mode 100644 index 00000000..a2002634 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/XmlConfig/Package.wxs @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/XmlConfigModule/Module.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/XmlConfigModule/Module.wxs new file mode 100644 index 00000000..29e8555b --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/XmlConfigModule/Module.wxs @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/XmlConfigModule/my.xml b/src/ext/Util/test/WixToolsetTest.Util/TestData/XmlConfigModule/my.xml new file mode 100644 index 00000000..bad25217 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/XmlConfigModule/my.xml @@ -0,0 +1 @@ +This is my.xml file. diff --git a/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs b/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs new file mode 100644 index 00000000..883f9794 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs @@ -0,0 +1,317 @@ +// Copyright (c) .NET 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.Util +{ + using System.IO; + using System.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Core.TestPackage; + using WixToolset.Data; + using WixToolset.Data.Symbols; + using WixToolset.Util; + using Xunit; + + public class UtilExtensionFixture + { + [Fact] + public void CanBuildUsingFileShare() + { + var folder = TestData.Get(@"TestData\UsingFileShare"); + var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); + + var results = build.BuildAndQuery(Build, "Binary", "CustomAction", "Wix4FileShare", "Wix4FileSharePermissions"); + WixAssert.CompareLineByLine(new[] + { + "Binary:Wix4UtilCA_X86\t[Binary data]", + "CustomAction:Wix4ConfigureSmbInstall_X86\t1\tWix4UtilCA_X86\tConfigureSmbInstall\t", + "CustomAction:Wix4ConfigureSmbUninstall_X86\t1\tWix4UtilCA_X86\tConfigureSmbUninstall\t", + "CustomAction:Wix4CreateSmb_X86\t11265\tWix4UtilCA_X86\tCreateSmb\t", + "CustomAction:Wix4CreateSmbRollback_X86\t11585\tWix4UtilCA_X86\tDropSmb\t", + "CustomAction:Wix4DropSmb_X86\t11265\tWix4UtilCA_X86\tDropSmb\t", + "CustomAction:Wix4DropSmbRollback_X86\t11585\tWix4UtilCA_X86\tCreateSmb\t", + "Wix4FileShare:ExampleFileShare\texample\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example file share\tINSTALLFOLDER", + "Wix4FileSharePermissions:ExampleFileShare\tEveryone\t1", + }, results.OrderBy(s => s).ToArray()); + } + + [Fact] + public void CanBuildUsingFileShareX64() + { + var folder = TestData.Get(@"TestData\UsingFileShare"); + var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); + + var results = build.BuildAndQuery(BuildX64, "Binary", "CustomAction", "Wix4FileShare", "Wix4FileSharePermissions"); + WixAssert.CompareLineByLine(new[] + { + "Binary:Wix4UtilCA_X64\t[Binary data]", + "CustomAction:Wix4ConfigureSmbInstall_X64\t1\tWix4UtilCA_X64\tConfigureSmbInstall\t", + "CustomAction:Wix4ConfigureSmbUninstall_X64\t1\tWix4UtilCA_X64\tConfigureSmbUninstall\t", + "CustomAction:Wix4CreateSmb_X64\t11265\tWix4UtilCA_X64\tCreateSmb\t", + "CustomAction:Wix4CreateSmbRollback_X64\t11585\tWix4UtilCA_X64\tDropSmb\t", + "CustomAction:Wix4DropSmb_X64\t11265\tWix4UtilCA_X64\tDropSmb\t", + "CustomAction:Wix4DropSmbRollback_X64\t11585\tWix4UtilCA_X64\tCreateSmb\t", + "Wix4FileShare:ExampleFileShare\texample\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example file share\tINSTALLFOLDER", + "Wix4FileSharePermissions:ExampleFileShare\tEveryone\t1", + }, results.OrderBy(s => s).ToArray()); + } + + [Fact] + public void CanBuildCloseApplication() + { + var folder = TestData.Get(@"TestData\CloseApplication"); + var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); + + var results = build.BuildAndQuery(BuildARM64, "Binary", "CustomAction", "Wix4CloseApplication"); + WixAssert.CompareLineByLine(new[] + { + "Binary:Wix4UtilCA_A64\t[Binary data]", + "CustomAction:Wix4CheckRebootRequired_A64\t65\tWix4UtilCA_A64\tWixCheckRebootRequired\t", + "CustomAction:Wix4CloseApplications_A64\t1\tWix4UtilCA_A64\tWixCloseApplications\t", + "CustomAction:Wix4CloseApplicationsDeferred_A64\t3073\tWix4UtilCA_A64\tWixCloseApplicationsDeferred\t", + "Wix4CloseApplication:CloseMyApp\texplorer.exe\t\t\t3\t\tMYAPPISRUNNING\t\t", + }, results.OrderBy(s => s).ToArray()); + } + + [Fact] + public void CanBuildInternetShortcutInProduct() + { + var folder = TestData.Get(@"TestData\InternetShortcut"); + var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); + + var results = build.BuildAndQuery(BuildX64, "Binary", "CustomAction", "RemoveFile", "Wix4InternetShortcut"); + WixAssert.CompareLineByLine(new[] + { + "Binary:Wix4UtilCA_X64\t[Binary data]", + "CustomAction:Wix4CreateInternetShortcuts_X64\t3073\tWix4UtilCA_X64\tWixCreateInternetShortcuts\t", + "CustomAction:Wix4RollbackInternetShortcuts_X64\t3329\tWix4UtilCA_X64\tWixRollbackInternetShortcuts\t", + "CustomAction:Wix4SchedInternetShortcuts_X64\t1\tWix4UtilCA_X64\tWixSchedInternetShortcuts\t", + "RemoveFile:uisdCsU32.1i4Hebrg1N7E194zJQ8Y\tPackage.ico\thoiptxrr.url|WiX Toolset (url).url\tINSTALLFOLDER\t2", + "RemoveFile:uisjV.q0ROZZYR3h_lkpbkZtLtPH0A\tPackage.ico\tjcxd1dwf.lnk|WiX Toolset (link).lnk\tINSTALLFOLDER\t2", + "Wix4InternetShortcut:uisdCsU32.1i4Hebrg1N7E194zJQ8Y\tPackage.ico\tINSTALLFOLDER\tWiX Toolset (url).url\thttps://wixtoolset.org\t1\t[#Package.ico]\t0", + "Wix4InternetShortcut:uisjV.q0ROZZYR3h_lkpbkZtLtPH0A\tPackage.ico\tINSTALLFOLDER\tWiX Toolset (link).lnk\thttps://wixtoolset.org\t0\t[#Package.ico]\t0", + }, results.OrderBy(s => s).ToArray()); + } + + [Fact] + public void CanBuildInternetShortcutInMergeModule() + { + var folder = TestData.Get(@"TestData\InternetShortcutModule"); + var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }, "test.msm"); + + var results = build.BuildAndQuery(BuildX64, "Binary", "CustomAction", "RemoveFile", "Wix4InternetShortcut"); + WixAssert.CompareLineByLine(new[] + { + "Binary:Wix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\t[Binary data]", + "CustomAction:Wix4CreateInternetShortcuts_X64\t3073\tWix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\tWixCreateInternetShortcuts\t", + "CustomAction:Wix4RollbackInternetShortcuts_X64\t3329\tWix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\tWixRollbackInternetShortcuts\t", + "CustomAction:Wix4SchedInternetShortcuts_X64\t1\tWix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\tWixSchedInternetShortcuts\t", + "RemoveFile:uisdCsU32.1i4Hebrg1N7E194zJQ8Y.047730A5_30FE_4A62_A520_DA9381B8226A\tPackage.ico.047730A5_30FE_4A62_A520_DA9381B8226A\thoiptxrr.url|WiX Toolset (url).url\tINSTALLFOLDER.047730A5_30FE_4A62_A520_DA9381B8226A\t2", + "RemoveFile:uisjV.q0ROZZYR3h_lkpbkZtLtPH0A.047730A5_30FE_4A62_A520_DA9381B8226A\tPackage.ico.047730A5_30FE_4A62_A520_DA9381B8226A\tjcxd1dwf.lnk|WiX Toolset (link).lnk\tINSTALLFOLDER.047730A5_30FE_4A62_A520_DA9381B8226A\t2", + "Wix4InternetShortcut:uisdCsU32.1i4Hebrg1N7E194zJQ8Y.047730A5_30FE_4A62_A520_DA9381B8226A\tPackage.ico.047730A5_30FE_4A62_A520_DA9381B8226A\tINSTALLFOLDER.047730A5_30FE_4A62_A520_DA9381B8226A\tWiX Toolset (url).url\thttps://wixtoolset.org\t1\t[#Package.ico.047730A5_30FE_4A62_A520_DA9381B8226A]\t0", + "Wix4InternetShortcut:uisjV.q0ROZZYR3h_lkpbkZtLtPH0A.047730A5_30FE_4A62_A520_DA9381B8226A\tPackage.ico.047730A5_30FE_4A62_A520_DA9381B8226A\tINSTALLFOLDER.047730A5_30FE_4A62_A520_DA9381B8226A\tWiX Toolset (link).lnk\thttps://wixtoolset.org\t0\t[#Package.ico.047730A5_30FE_4A62_A520_DA9381B8226A]\t0", + }, results.OrderBy(s => s).ToArray()); + } + + [Fact] + public void CanBuildWithPermissionEx() + { + var folder = TestData.Get(@"TestData\PermissionEx"); + var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); + + var results = build.BuildAndQuery(BuildX64, "Wix4SecureObject"); + WixAssert.CompareLineByLine(new[] + { + "Wix4SecureObject:ExampleRegistryKey\tRegistry\t\tEveryone\t1\t268435456\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo", + "Wix4SecureObject:filF5_pLhBuF5b4N9XEo52g_hUM5Lo\tFile\t\tEveryone\t1\t268435456\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo", + "Wix4SecureObject:INSTALLFOLDER\tCreateFolder\t\tEveryone\t1\t268435456\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo", + "Wix4SecureObject:regL6DnQ9yJpDJH5OdcVji4YXsdX2c\tRegistry\t\tEveryone\t1\t268435456\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo", + "Wix4SecureObject:testsvc\tServiceInstall\t\tEveryone\t1\t268435456\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo", + }, results.OrderBy(s => s).ToArray()); + } + + [Fact] + public void CanBuildRemoveRegistryKeyExInMergeModule() + { + var folder = TestData.Get(@"TestData", "RemoveRegistryKeyEx"); + var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }, "test.msm"); + + var results = build.BuildAndQuery(BuildX64, "Binary", "CustomAction", "RemoveRegistry", "Wix4RemoveRegistryKeyEx"); + WixAssert.CompareLineByLine(new[] + { + "Binary:Wix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\t[Binary data]", + "CustomAction:Wix4RemoveRegistryKeysEx_X64.047730A5_30FE_4A62_A520_DA9381B8226A\t65\tWix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\tWixRemoveRegistryKeysEx\t", + "Wix4RemoveRegistryKeyEx:rrxfcDhR4HhE3v3rYiQcNtQjyahQNg.047730A5_30FE_4A62_A520_DA9381B8226A\tfilh4juyUVjoUcWWtcQmd5L07FoON4.047730A5_30FE_4A62_A520_DA9381B8226A\t2\tSOFTWARE\\Example\t1\t", + }, results.OrderBy(s => s).ToArray()); + } + + [Fact] + public void CanBuildRemoveFolderExInMergeModule() + { + var folder = TestData.Get(@"TestData\RemoveFolderEx"); + var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }, "test.msm"); + + var results = build.BuildAndQuery(BuildX64, "Binary", "CustomAction", "RemoveFile", "Wix4RemoveFolderEx"); + WixAssert.CompareLineByLine(new[] + { + "Binary:Wix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\t[Binary data]", + "CustomAction:Wix4RemoveFoldersEx_X64.047730A5_30FE_4A62_A520_DA9381B8226A\t65\tWix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\tWixRemoveFoldersEx\t", + "Wix4RemoveFolderEx:wrf5qCm1SE.zp8djrlk78l1IYFXsEw.047730A5_30FE_4A62_A520_DA9381B8226A\tfilh4juyUVjoUcWWtcQmd5L07FoON4.047730A5_30FE_4A62_A520_DA9381B8226A\tRemoveProp.047730A5_30FE_4A62_A520_DA9381B8226A\t3\t", + }, results.OrderBy(s => s).ToArray()); + } + + [Fact] + public void CanBuildWithEventManifest() + { + var folder = TestData.Get(@"TestData\EventManifest"); + var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); + + var results = build.BuildAndQuery(BuildARM64, "Binary", "CustomAction", "Wix4EventManifest", "Wix4XmlFile"); + WixAssert.CompareLineByLine(new[] + { + "Binary:Wix4UtilCA_A64\t[Binary data]", + "CustomAction:Wix4ConfigureEventManifestRegister_A64\t1\tWix4UtilCA_A64\tConfigureEventManifestRegister\t", + "CustomAction:Wix4ConfigureEventManifestUnregister_A64\t1\tWix4UtilCA_A64\tConfigureEventManifestUnregister\t", + "CustomAction:Wix4ExecXmlFile_A64\t11265\tWix4UtilCA_A64\tExecXmlFile\t", + "CustomAction:Wix4ExecXmlFileRollback_A64\t11521\tWix4UtilCA_A64\tExecXmlFileRollback\t", + "CustomAction:Wix4RegisterEventManifest_A64\t3073\tWix4UtilCA_A64\tWixQuietExec\t", + "CustomAction:Wix4RollbackRegisterEventManifest_A64\t3393\tWix4UtilCA_A64\tWixQuietExec\t", + "CustomAction:Wix4RollbackUnregisterEventManifest_A64\t3329\tWix4UtilCA_A64\tWixQuietExec\t", + "CustomAction:Wix4SchedXmlFile_A64\t1\tWix4UtilCA_A64\tSchedXmlFile\t", + "CustomAction:Wix4UnregisterEventManifest_A64\t3137\tWix4UtilCA_A64\tWixQuietExec\t", + "Wix4EventManifest:Manifest.dll\t[#Manifest.dll]", + "Wix4XmlFile:Config_Manifest.dllMessageFile\t[#Manifest.dll]\t/*/*/*/*[\\[]@messageFileName[\\]]\tmessageFileName\t[Manifest.dll]\t4100\tManifest.dll\t", + "Wix4XmlFile:Config_Manifest.dllResourceFile\t[#Manifest.dll]\t/*/*/*/*[\\[]@resourceFileName[\\]]\tresourceFileName\t[Manifest.dll]\t4100\tManifest.dll\t", + }, results.OrderBy(s => s).ToArray()); + } + + [Fact] + public void CanBuildWithQueries() + { + var folder = TestData.Get(@"TestData\Queries"); + var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); + + var results = build.BuildAndQuery(BuildARM64, "Binary", "CustomAction"); + WixAssert.CompareLineByLine(new[] + { + "Binary:Wix4UtilCA_A64\t[Binary data]", + "CustomAction:Wix4BroadcastEnvironmentChange_A64\t65\tWix4UtilCA_A64\tWixBroadcastEnvironmentChange\t", + "CustomAction:Wix4BroadcastSettingChange_A64\t65\tWix4UtilCA_A64\tWixBroadcastSettingChange\t", + "CustomAction:Wix4CheckRebootRequired_A64\t65\tWix4UtilCA_A64\tWixCheckRebootRequired\t", + "CustomAction:Wix4QueryOsDriverInfo_A64\t257\tWix4UtilCA_A64\tWixQueryOsDriverInfo\t", + "CustomAction:Wix4QueryOsInfo_A64\t257\tWix4UtilCA_A64\tWixQueryOsInfo\t", + }, results.OrderBy(s => s).ToArray()); + } + + [Fact] + public void CanBuildWithXmlConfig() + { + var folder = TestData.Get(@"TestData", "XmlConfig"); + var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); + + var results = build.BuildAndQuery(BuildX64, "Wix4XmlConfig"); + WixAssert.CompareLineByLine(new[] + { + "Wix4XmlConfig:DelElement\t[INSTALLFOLDER]my.xml\t\t//root/sub\txxx\t\t\t289\tDel\t1", + }, results.OrderBy(s => s).ToArray()); + } + + [Fact] + public void CanBuildModuleWithXmlConfig() + { + var folder = TestData.Get(@"TestData", "XmlConfigModule"); + var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); + + var results = build.BuildAndQuery(BuildX64, "Wix4XmlConfig"); + WixAssert.CompareLineByLine(new[] + { + "Wix4XmlConfig:AddElement.047730A5_30FE_4A62_A520_DA9381B8226A\t[my.xml.047730A5_30FE_4A62_A520_DA9381B8226A]\t\t//root/sub\txxx\t\t\t273\tParent.047730A5_30FE_4A62_A520_DA9381B8226A\t1", + "Wix4XmlConfig:ChildElement.047730A5_30FE_4A62_A520_DA9381B8226A\t[my.xml.047730A5_30FE_4A62_A520_DA9381B8226A]\tAddElement.047730A5_30FE_4A62_A520_DA9381B8226A\t\txxx\t\t\t0\tChild.047730A5_30FE_4A62_A520_DA9381B8226A\t1", + }, results.OrderBy(s => s).ToArray()); + } + + [Fact] + public void CanBuildBundleWithSearches() + { + var burnStubPath = TestData.Get(@"TestData\.Data\burn.exe"); + var folder = TestData.Get(@"TestData\BundleWithSearches"); + var rootFolder = TestData.Get(); + var wixext = Path.Combine(rootFolder, "WixToolset.Util.wixext.dll"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(); + var intermediateFolder = Path.Combine(baseFolder, "obj"); + var bundlePath = Path.Combine(baseFolder, @"bin\test.exe"); + var baFolderPath = Path.Combine(baseFolder, "ba"); + var extractFolderPath = Path.Combine(baseFolder, "extract"); + + var result = WixRunner.Execute(new[] + { + "build", + Path.Combine(folder, "Bundle.wxs"), + "-ext", wixext, + "-loc", Path.Combine(folder, "Bundle.en-us.wxl"), + "-bindpath", Path.Combine(folder, "data"), + "-intermediateFolder", intermediateFolder, + "-o", bundlePath + }); + + result.AssertSuccess(); + + Assert.True(File.Exists(bundlePath)); +#if TODO + Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.wixpdb"))); +#endif + + var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath); + extractResult.AssertSuccess(); + + var bundleExtensionDatas = extractResult.SelectBundleExtensionDataNodes("/be:BundleExtensionData/be:BundleExtension[@Id='Wix4UtilBundleExtension_X86']"); + Assert.Equal(1, bundleExtensionDatas.Count); + Assert.Equal("" + + "" + + "", bundleExtensionDatas[0].GetTestXml()); + + var utilSearches = extractResult.SelectManifestNodes("/burn:BurnManifest/*[self::burn:ExtensionSearch or self::burn:FileSearch or self::burn:MsiProductSearch or self::burn:RegistrySearch]"); + Assert.Equal(5, utilSearches.Count); + Assert.Equal("", utilSearches[0].GetTestXml()); + Assert.Equal("", utilSearches[1].GetTestXml()); + Assert.Equal("", utilSearches[2].GetTestXml()); + Assert.Equal("", utilSearches[3].GetTestXml()); + Assert.Equal("", utilSearches[4].GetTestXml()); + } + } + + private static void Build(string[] args) + { + var result = WixRunner.Execute(args); + result.AssertSuccess(); + } + + private static void BuildX64(string[] args) + { + var newArgs = args.ToList(); + newArgs.Add("-platform"); + newArgs.Add("x64"); + newArgs.Add("-sw1072"); + + var result = WixRunner.Execute(newArgs.ToArray()); + result.AssertSuccess(); + } + + private static void BuildARM64(string[] args) + { + var newArgs = args.ToList(); + newArgs.Add("-platform"); + newArgs.Add("arm64"); + + var result = WixRunner.Execute(newArgs.ToArray()); + result.AssertSuccess(); + } + } +} diff --git a/src/ext/Util/test/WixToolsetTest.Util/WixToolsetTest.Util.csproj b/src/ext/Util/test/WixToolsetTest.Util/WixToolsetTest.Util.csproj new file mode 100644 index 00000000..e77ecbed --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/WixToolsetTest.Util.csproj @@ -0,0 +1,38 @@ + + + + + + netcoreapp3.1 + false + + + + NU1701 + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/WixToolsetTest.Util.v3.ncrunchproject b/src/ext/Util/test/WixToolsetTest.Util/WixToolsetTest.Util.v3.ncrunchproject new file mode 100644 index 00000000..7b5b2139 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/WixToolsetTest.Util.v3.ncrunchproject @@ -0,0 +1,5 @@ + + + True + + \ No newline at end of file diff --git a/src/ext/Util/wix.snk b/src/ext/Util/wix.snk new file mode 100644 index 00000000..3908a66a Binary files /dev/null and b/src/ext/Util/wix.snk differ diff --git a/src/ext/Util/wixext/PerformanceCounterType.cs b/src/ext/Util/wixext/PerformanceCounterType.cs new file mode 100644 index 00000000..1e06efd3 --- /dev/null +++ b/src/ext/Util/wixext/PerformanceCounterType.cs @@ -0,0 +1,192 @@ +// Captured from: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.dll + +namespace System.Diagnostics +{ + public enum PerformanceCounterType + { + // + // Summary: + // An instantaneous counter that shows the most recently observed value in hexadecimal + // format. Used, for example, to maintain a simple count of items or operations. + NumberOfItemsHEX32 = 0, + // + // Summary: + // An instantaneous counter that shows the most recently observed value. Used, for + // example, to maintain a simple count of a very large number of items or operations. + // It is the same as NumberOfItemsHEX32 except that it uses larger fields to accommodate + // larger values. + NumberOfItemsHEX64 = 256, + // + // Summary: + // An instantaneous counter that shows the most recently observed value. Used, for + // example, to maintain a simple count of items or operations. + NumberOfItems32 = 65536, + // + // Summary: + // An instantaneous counter that shows the most recently observed value. Used, for + // example, to maintain a simple count of a very large number of items or operations. + // It is the same as NumberOfItems32 except that it uses larger fields to accommodate + // larger values. + NumberOfItems64 = 65792, + // + // Summary: + // A difference counter that shows the change in the measured attribute between + // the two most recent sample intervals. + CounterDelta32 = 4195328, + // + // Summary: + // A difference counter that shows the change in the measured attribute between + // the two most recent sample intervals. It is the same as the CounterDelta32 counter + // type except that is uses larger fields to accomodate larger values. + CounterDelta64 = 4195584, + // + // Summary: + // An average counter that shows the average number of operations completed in one + // second. When a counter of this type samples the data, each sampling interrupt + // returns one or zero. The counter data is the number of ones that were sampled. + // It measures time in units of ticks of the system performance timer. + SampleCounter = 4260864, + // + // Summary: + // An average counter designed to monitor the average length of a queue to a resource + // over time. It shows the difference between the queue lengths observed during + // the last two sample intervals divided by the duration of the interval. This type + // of counter is typically used to track the number of items that are queued or + // waiting. + CountPerTimeInterval32 = 4523008, + // + // Summary: + // An average counter that monitors the average length of a queue to a resource + // over time. Counters of this type display the difference between the queue lengths + // observed during the last two sample intervals, divided by the duration of the + // interval. This counter type is the same as CountPerTimeInterval32 except that + // it uses larger fields to accommodate larger values. This type of counter is typically + // used to track a high-volume or very large number of items that are queued or + // waiting. + CountPerTimeInterval64 = 4523264, + // + // Summary: + // A difference counter that shows the average number of operations completed during + // each second of the sample interval. Counters of this type measure time in ticks + // of the system clock. + RateOfCountsPerSecond32 = 272696320, + // + // Summary: + // A difference counter that shows the average number of operations completed during + // each second of the sample interval. Counters of this type measure time in ticks + // of the system clock. This counter type is the same as the RateOfCountsPerSecond32 + // type, but it uses larger fields to accommodate larger values to track a high-volume + // number of items or operations per second, such as a byte-transmission rate. + RateOfCountsPerSecond64 = 272696576, + // + // Summary: + // An instantaneous percentage counter that shows the ratio of a subset to its set + // as a percentage. For example, it compares the number of bytes in use on a disk + // to the total number of bytes on the disk. Counters of this type display the current + // percentage only, not an average over time. + RawFraction = 537003008, + // + // Summary: + // A percentage counter that shows the average time that a component is active as + // a percentage of the total sample time. + CounterTimer = 541132032, + // + // Summary: + // A percentage counter that shows the active time of a component as a percentage + // of the total elapsed time of the sample interval. It measures time in units of + // 100 nanoseconds (ns). Counters of this type are designed to measure the activity + // of one component at a time. + Timer100Ns = 542180608, + // + // Summary: + // A percentage counter that shows the average ratio of hits to all operations during + // the last two sample intervals. + SampleFraction = 549585920, + // + // Summary: + // A percentage counter that displays the average percentage of active time observed + // during sample interval. The value of these counters is calculated by monitoring + // the percentage of time that the service was inactive and then subtracting that + // value from 100 percent. + CounterTimerInverse = 557909248, + // + // Summary: + // A percentage counter that shows the average percentage of active time observed + // during the sample interval. + Timer100NsInverse = 558957824, + // + // Summary: + // A percentage counter that displays the active time of one or more components + // as a percentage of the total time of the sample interval. Because the numerator + // records the active time of components operating simultaneously, the resulting + // percentage can exceed 100 percent. + CounterMultiTimer = 574686464, + // + // Summary: + // A percentage counter that shows the active time of one or more components as + // a percentage of the total time of the sample interval. It measures time in 100 + // nanosecond (ns) units. + CounterMultiTimer100Ns = 575735040, + // + // Summary: + // A percentage counter that shows the active time of one or more components as + // a percentage of the total time of the sample interval. It derives the active + // time by measuring the time that the components were not active and subtracting + // the result from 100 percent by the number of objects monitored. + CounterMultiTimerInverse = 591463680, + // + // Summary: + // A percentage counter that shows the active time of one or more components as + // a percentage of the total time of the sample interval. Counters of this type + // measure time in 100 nanosecond (ns) units. They derive the active time by measuring + // the time that the components were not active and subtracting the result from + // multiplying 100 percent by the number of objects monitored. + CounterMultiTimer100NsInverse = 592512256, + // + // Summary: + // An average counter that measures the time it takes, on average, to complete a + // process or operation. Counters of this type display a ratio of the total elapsed + // time of the sample interval to the number of processes or operations completed + // during that time. This counter type measures time in ticks of the system clock. + AverageTimer32 = 805438464, + // + // Summary: + // A difference timer that shows the total time between when the component or process + // started and the time when this value is calculated. + ElapsedTime = 807666944, + // + // Summary: + // An average counter that shows how many items are processed, on average, during + // an operation. Counters of this type display a ratio of the items processed to + // the number of operations completed. The ratio is calculated by comparing the + // number of items processed during the last interval to the number of operations + // completed during the last interval. + AverageCount64 = 1073874176, + // + // Summary: + // A base counter that stores the number of sampling interrupts taken and is used + // as a denominator in the sampling fraction. The sampling fraction is the number + // of samples that were 1 (or true) for a sample interrupt. Check that this value + // is greater than zero before using it as the denominator in a calculation of SampleFraction. + SampleBase = 1073939457, + // + // Summary: + // A base counter that is used in the calculation of time or count averages, such + // as AverageTimer32 and AverageCount64. Stores the denominator for calculating + // a counter to present "time per operation" or "count per operation". + AverageBase = 1073939458, + // + // Summary: + // A base counter that stores the denominator of a counter that presents a general + // arithmetic fraction. Check that this value is greater than zero before using + // it as the denominator in a RawFraction value calculation. + RawBase = 1073939459, + // + // Summary: + // A base counter that indicates the number of items sampled. It is used as the + // denominator in the calculations to get an average among the items sampled when + // taking timings of multiple, but similar items. Used with CounterMultiTimer, CounterMultiTimerInverse, + // CounterMultiTimer100Ns, and CounterMultiTimer100NsInverse. + CounterMultiBase = 1107494144 + } +} diff --git a/src/ext/Util/wixext/Symbols/EventManifestSymbol.cs b/src/ext/Util/wixext/Symbols/EventManifestSymbol.cs new file mode 100644 index 00000000..ccd3c899 --- /dev/null +++ b/src/ext/Util/wixext/Symbols/EventManifestSymbol.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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition EventManifest = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.EventManifest.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(EventManifestSymbolFields.ComponentRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(EventManifestSymbolFields.File), IntermediateFieldType.String), + }, + typeof(EventManifestSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum EventManifestSymbolFields + { + ComponentRef, + File, + } + + public class EventManifestSymbol : IntermediateSymbol + { + public EventManifestSymbol() : base(UtilSymbolDefinitions.EventManifest, null, null) + { + } + + public EventManifestSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.EventManifest, sourceLineNumber, id) + { + } + + public IntermediateField this[EventManifestSymbolFields index] => this.Fields[(int)index]; + + public string ComponentRef + { + get => this.Fields[(int)EventManifestSymbolFields.ComponentRef].AsString(); + set => this.Set((int)EventManifestSymbolFields.ComponentRef, value); + } + + public string File + { + get => this.Fields[(int)EventManifestSymbolFields.File].AsString(); + set => this.Set((int)EventManifestSymbolFields.File, value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/Symbols/FileSharePermissionsSymbol.cs b/src/ext/Util/wixext/Symbols/FileSharePermissionsSymbol.cs new file mode 100644 index 00000000..3db92f22 --- /dev/null +++ b/src/ext/Util/wixext/Symbols/FileSharePermissionsSymbol.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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition FileSharePermissions = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.FileSharePermissions.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(FileSharePermissionsSymbolFields.FileShareRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(FileSharePermissionsSymbolFields.UserRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(FileSharePermissionsSymbolFields.Permissions), IntermediateFieldType.Number), + }, + typeof(FileSharePermissionsSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum FileSharePermissionsSymbolFields + { + FileShareRef, + UserRef, + Permissions, + } + + public class FileSharePermissionsSymbol : IntermediateSymbol + { + public FileSharePermissionsSymbol() : base(UtilSymbolDefinitions.FileSharePermissions, null, null) + { + } + + public FileSharePermissionsSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.FileSharePermissions, sourceLineNumber, id) + { + } + + public IntermediateField this[FileSharePermissionsSymbolFields index] => this.Fields[(int)index]; + + public string FileShareRef + { + get => this.Fields[(int)FileSharePermissionsSymbolFields.FileShareRef].AsString(); + set => this.Set((int)FileSharePermissionsSymbolFields.FileShareRef, value); + } + + public string UserRef + { + get => this.Fields[(int)FileSharePermissionsSymbolFields.UserRef].AsString(); + set => this.Set((int)FileSharePermissionsSymbolFields.UserRef, value); + } + + public int Permissions + { + get => this.Fields[(int)FileSharePermissionsSymbolFields.Permissions].AsNumber(); + set => this.Set((int)FileSharePermissionsSymbolFields.Permissions, value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/Symbols/FileShareSymbol.cs b/src/ext/Util/wixext/Symbols/FileShareSymbol.cs new file mode 100644 index 00000000..c956ff42 --- /dev/null +++ b/src/ext/Util/wixext/Symbols/FileShareSymbol.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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition FileShare = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.FileShare.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(FileShareSymbolFields.ShareName), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(FileShareSymbolFields.ComponentRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(FileShareSymbolFields.Description), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(FileShareSymbolFields.DirectoryRef), IntermediateFieldType.String), + }, + typeof(FileShareSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum FileShareSymbolFields + { + ShareName, + ComponentRef, + Description, + DirectoryRef, + } + + public class FileShareSymbol : IntermediateSymbol + { + public FileShareSymbol() : base(UtilSymbolDefinitions.FileShare, null, null) + { + } + + public FileShareSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.FileShare, sourceLineNumber, id) + { + } + + public IntermediateField this[FileShareSymbolFields index] => this.Fields[(int)index]; + + public string ShareName + { + get => this.Fields[(int)FileShareSymbolFields.ShareName].AsString(); + set => this.Set((int)FileShareSymbolFields.ShareName, value); + } + + public string ComponentRef + { + get => this.Fields[(int)FileShareSymbolFields.ComponentRef].AsString(); + set => this.Set((int)FileShareSymbolFields.ComponentRef, value); + } + + public string Description + { + get => this.Fields[(int)FileShareSymbolFields.Description].AsString(); + set => this.Set((int)FileShareSymbolFields.Description, value); + } + + public string DirectoryRef + { + get => this.Fields[(int)FileShareSymbolFields.DirectoryRef].AsString(); + set => this.Set((int)FileShareSymbolFields.DirectoryRef, value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/Symbols/GroupSymbol.cs b/src/ext/Util/wixext/Symbols/GroupSymbol.cs new file mode 100644 index 00000000..b378db44 --- /dev/null +++ b/src/ext/Util/wixext/Symbols/GroupSymbol.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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition Group = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.Group.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(GroupSymbolFields.ComponentRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(GroupSymbolFields.Name), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(GroupSymbolFields.Domain), IntermediateFieldType.String), + }, + typeof(GroupSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum GroupSymbolFields + { + ComponentRef, + Name, + Domain, + } + + public class GroupSymbol : IntermediateSymbol + { + public GroupSymbol() : base(UtilSymbolDefinitions.Group, null, null) + { + } + + public GroupSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.Group, sourceLineNumber, id) + { + } + + public IntermediateField this[GroupSymbolFields index] => this.Fields[(int)index]; + + public string ComponentRef + { + get => this.Fields[(int)GroupSymbolFields.ComponentRef].AsString(); + set => this.Set((int)GroupSymbolFields.ComponentRef, value); + } + + public string Name + { + get => this.Fields[(int)GroupSymbolFields.Name].AsString(); + set => this.Set((int)GroupSymbolFields.Name, value); + } + + public string Domain + { + get => this.Fields[(int)GroupSymbolFields.Domain].AsString(); + set => this.Set((int)GroupSymbolFields.Domain, value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/Symbols/PerfmonManifestSymbol.cs b/src/ext/Util/wixext/Symbols/PerfmonManifestSymbol.cs new file mode 100644 index 00000000..03fef14e --- /dev/null +++ b/src/ext/Util/wixext/Symbols/PerfmonManifestSymbol.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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition PerfmonManifest = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.PerfmonManifest.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(PerfmonManifestSymbolFields.ComponentRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(PerfmonManifestSymbolFields.File), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(PerfmonManifestSymbolFields.ResourceFileDirectory), IntermediateFieldType.String), + }, + typeof(PerfmonManifestSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum PerfmonManifestSymbolFields + { + ComponentRef, + File, + ResourceFileDirectory, + } + + public class PerfmonManifestSymbol : IntermediateSymbol + { + public PerfmonManifestSymbol() : base(UtilSymbolDefinitions.PerfmonManifest, null, null) + { + } + + public PerfmonManifestSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.PerfmonManifest, sourceLineNumber, id) + { + } + + public IntermediateField this[PerfmonManifestSymbolFields index] => this.Fields[(int)index]; + + public string ComponentRef + { + get => this.Fields[(int)PerfmonManifestSymbolFields.ComponentRef].AsString(); + set => this.Set((int)PerfmonManifestSymbolFields.ComponentRef, value); + } + + public string File + { + get => this.Fields[(int)PerfmonManifestSymbolFields.File].AsString(); + set => this.Set((int)PerfmonManifestSymbolFields.File, value); + } + + public string ResourceFileDirectory + { + get => this.Fields[(int)PerfmonManifestSymbolFields.ResourceFileDirectory].AsString(); + set => this.Set((int)PerfmonManifestSymbolFields.ResourceFileDirectory, value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/Symbols/PerfmonSymbol.cs b/src/ext/Util/wixext/Symbols/PerfmonSymbol.cs new file mode 100644 index 00000000..6784ebd1 --- /dev/null +++ b/src/ext/Util/wixext/Symbols/PerfmonSymbol.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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition Perfmon = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.Perfmon.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(PerfmonSymbolFields.ComponentRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(PerfmonSymbolFields.File), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(PerfmonSymbolFields.Name), IntermediateFieldType.String), + }, + typeof(PerfmonSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum PerfmonSymbolFields + { + ComponentRef, + File, + Name, + } + + public class PerfmonSymbol : IntermediateSymbol + { + public PerfmonSymbol() : base(UtilSymbolDefinitions.Perfmon, null, null) + { + } + + public PerfmonSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.Perfmon, sourceLineNumber, id) + { + } + + public IntermediateField this[PerfmonSymbolFields index] => this.Fields[(int)index]; + + public string ComponentRef + { + get => this.Fields[(int)PerfmonSymbolFields.ComponentRef].AsString(); + set => this.Set((int)PerfmonSymbolFields.ComponentRef, value); + } + + public string File + { + get => this.Fields[(int)PerfmonSymbolFields.File].AsString(); + set => this.Set((int)PerfmonSymbolFields.File, value); + } + + public string Name + { + get => this.Fields[(int)PerfmonSymbolFields.Name].AsString(); + set => this.Set((int)PerfmonSymbolFields.Name, value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/Symbols/PerformanceCategorySymbol.cs b/src/ext/Util/wixext/Symbols/PerformanceCategorySymbol.cs new file mode 100644 index 00000000..5ecf388c --- /dev/null +++ b/src/ext/Util/wixext/Symbols/PerformanceCategorySymbol.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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition PerformanceCategory = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.PerformanceCategory.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(PerformanceCategorySymbolFields.ComponentRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(PerformanceCategorySymbolFields.Name), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(PerformanceCategorySymbolFields.IniData), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(PerformanceCategorySymbolFields.ConstantData), IntermediateFieldType.String), + }, + typeof(PerformanceCategorySymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum PerformanceCategorySymbolFields + { + ComponentRef, + Name, + IniData, + ConstantData, + } + + public class PerformanceCategorySymbol : IntermediateSymbol + { + public PerformanceCategorySymbol() : base(UtilSymbolDefinitions.PerformanceCategory, null, null) + { + } + + public PerformanceCategorySymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.PerformanceCategory, sourceLineNumber, id) + { + } + + public IntermediateField this[PerformanceCategorySymbolFields index] => this.Fields[(int)index]; + + public string ComponentRef + { + get => this.Fields[(int)PerformanceCategorySymbolFields.ComponentRef].AsString(); + set => this.Set((int)PerformanceCategorySymbolFields.ComponentRef, value); + } + + public string Name + { + get => this.Fields[(int)PerformanceCategorySymbolFields.Name].AsString(); + set => this.Set((int)PerformanceCategorySymbolFields.Name, value); + } + + public string IniData + { + get => this.Fields[(int)PerformanceCategorySymbolFields.IniData].AsString(); + set => this.Set((int)PerformanceCategorySymbolFields.IniData, value); + } + + public string ConstantData + { + get => this.Fields[(int)PerformanceCategorySymbolFields.ConstantData].AsString(); + set => this.Set((int)PerformanceCategorySymbolFields.ConstantData, value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/Symbols/SecureObjectsSymbol.cs b/src/ext/Util/wixext/Symbols/SecureObjectsSymbol.cs new file mode 100644 index 00000000..25fc6dca --- /dev/null +++ b/src/ext/Util/wixext/Symbols/SecureObjectsSymbol.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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition SecureObjects = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.SecureObjects.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.SecureObject), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.Table), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.Domain), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.User), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.Attributes), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.Permission), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.ComponentRef), IntermediateFieldType.String), + }, + typeof(SecureObjectsSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using System; + using WixToolset.Data; + + public enum SecureObjectsSymbolFields + { + SecureObject, + Table, + Domain, + User, + Attributes, + Permission, + ComponentRef, + } + + [Flags] + public enum WixPermissionExAttributes + { + None = 0x0, + Inheritable = 0x01 + } + + public class SecureObjectsSymbol : IntermediateSymbol + { + public SecureObjectsSymbol() : base(UtilSymbolDefinitions.SecureObjects, null, null) + { + } + + public SecureObjectsSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.SecureObjects, sourceLineNumber, id) + { + } + + public IntermediateField this[SecureObjectsSymbolFields index] => this.Fields[(int)index]; + + public string SecureObject + { + get => this.Fields[(int)SecureObjectsSymbolFields.SecureObject].AsString(); + set => this.Set((int)SecureObjectsSymbolFields.SecureObject, value); + } + + public string Table + { + get => this.Fields[(int)SecureObjectsSymbolFields.Table].AsString(); + set => this.Set((int)SecureObjectsSymbolFields.Table, value); + } + + public string Domain + { + get => this.Fields[(int)SecureObjectsSymbolFields.Domain].AsString(); + set => this.Set((int)SecureObjectsSymbolFields.Domain, value); + } + + public string User + { + get => this.Fields[(int)SecureObjectsSymbolFields.User].AsString(); + set => this.Set((int)SecureObjectsSymbolFields.User, value); + } + + public WixPermissionExAttributes Attributes + { + get => (WixPermissionExAttributes)this.Fields[(int)SecureObjectsSymbolFields.Attributes].AsNumber(); + set => this.Set((int)SecureObjectsSymbolFields.Attributes, (int)value); + } + + public int? Permission + { + get => this.Fields[(int)SecureObjectsSymbolFields.Permission].AsNullableNumber(); + set => this.Set((int)SecureObjectsSymbolFields.Permission, value); + } + + public string ComponentRef + { + get => this.Fields[(int)SecureObjectsSymbolFields.ComponentRef].AsString(); + set => this.Set((int)SecureObjectsSymbolFields.ComponentRef, value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/Symbols/ServiceConfigSymbol.cs b/src/ext/Util/wixext/Symbols/ServiceConfigSymbol.cs new file mode 100644 index 00000000..3a877f9b --- /dev/null +++ b/src/ext/Util/wixext/Symbols/ServiceConfigSymbol.cs @@ -0,0 +1,119 @@ +// Copyright (c) .NET 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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition ServiceConfig = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.ServiceConfig.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.ServiceName), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.ComponentRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.NewService), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.FirstFailureActionType), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.SecondFailureActionType), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.ThirdFailureActionType), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.ResetPeriodInDays), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.RestartServiceDelayInSeconds), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.ProgramCommandLine), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.RebootMessage), IntermediateFieldType.String), + }, + typeof(ServiceConfigSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum ServiceConfigSymbolFields + { + ServiceName, + ComponentRef, + NewService, + FirstFailureActionType, + SecondFailureActionType, + ThirdFailureActionType, + ResetPeriodInDays, + RestartServiceDelayInSeconds, + ProgramCommandLine, + RebootMessage, + } + + public class ServiceConfigSymbol : IntermediateSymbol + { + public ServiceConfigSymbol() : base(UtilSymbolDefinitions.ServiceConfig, null, null) + { + } + + public ServiceConfigSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.ServiceConfig, sourceLineNumber, id) + { + } + + public IntermediateField this[ServiceConfigSymbolFields index] => this.Fields[(int)index]; + + public string ServiceName + { + get => this.Fields[(int)ServiceConfigSymbolFields.ServiceName].AsString(); + set => this.Set((int)ServiceConfigSymbolFields.ServiceName, value); + } + + public string ComponentRef + { + get => this.Fields[(int)ServiceConfigSymbolFields.ComponentRef].AsString(); + set => this.Set((int)ServiceConfigSymbolFields.ComponentRef, value); + } + + public int NewService + { + get => this.Fields[(int)ServiceConfigSymbolFields.NewService].AsNumber(); + set => this.Set((int)ServiceConfigSymbolFields.NewService, value); + } + + public string FirstFailureActionType + { + get => this.Fields[(int)ServiceConfigSymbolFields.FirstFailureActionType].AsString(); + set => this.Set((int)ServiceConfigSymbolFields.FirstFailureActionType, value); + } + + public string SecondFailureActionType + { + get => this.Fields[(int)ServiceConfigSymbolFields.SecondFailureActionType].AsString(); + set => this.Set((int)ServiceConfigSymbolFields.SecondFailureActionType, value); + } + + public string ThirdFailureActionType + { + get => this.Fields[(int)ServiceConfigSymbolFields.ThirdFailureActionType].AsString(); + set => this.Set((int)ServiceConfigSymbolFields.ThirdFailureActionType, value); + } + + public int? ResetPeriodInDays + { + get => this.Fields[(int)ServiceConfigSymbolFields.ResetPeriodInDays].AsNullableNumber(); + set => this.Set((int)ServiceConfigSymbolFields.ResetPeriodInDays, value); + } + + public int? RestartServiceDelayInSeconds + { + get => this.Fields[(int)ServiceConfigSymbolFields.RestartServiceDelayInSeconds].AsNullableNumber(); + set => this.Set((int)ServiceConfigSymbolFields.RestartServiceDelayInSeconds, value); + } + + public string ProgramCommandLine + { + get => this.Fields[(int)ServiceConfigSymbolFields.ProgramCommandLine].AsString(); + set => this.Set((int)ServiceConfigSymbolFields.ProgramCommandLine, value); + } + + public string RebootMessage + { + get => this.Fields[(int)ServiceConfigSymbolFields.RebootMessage].AsString(); + set => this.Set((int)ServiceConfigSymbolFields.RebootMessage, value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/Symbols/UserGroupSymbol.cs b/src/ext/Util/wixext/Symbols/UserGroupSymbol.cs new file mode 100644 index 00000000..c8f3998e --- /dev/null +++ b/src/ext/Util/wixext/Symbols/UserGroupSymbol.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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition UserGroup = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.UserGroup.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(UserGroupSymbolFields.UserRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(UserGroupSymbolFields.GroupRef), IntermediateFieldType.String), + }, + typeof(UserGroupSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum UserGroupSymbolFields + { + UserRef, + GroupRef, + } + + public class UserGroupSymbol : IntermediateSymbol + { + public UserGroupSymbol() : base(UtilSymbolDefinitions.UserGroup, null, null) + { + } + + public UserGroupSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.UserGroup, sourceLineNumber, id) + { + } + + public IntermediateField this[UserGroupSymbolFields index] => this.Fields[(int)index]; + + public string UserRef + { + get => this.Fields[(int)UserGroupSymbolFields.UserRef].AsString(); + set => this.Set((int)UserGroupSymbolFields.UserRef, value); + } + + public string GroupRef + { + get => this.Fields[(int)UserGroupSymbolFields.GroupRef].AsString(); + set => this.Set((int)UserGroupSymbolFields.GroupRef, value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/Symbols/UserSymbol.cs b/src/ext/Util/wixext/Symbols/UserSymbol.cs new file mode 100644 index 00000000..5f00064b --- /dev/null +++ b/src/ext/Util/wixext/Symbols/UserSymbol.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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition User = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.User.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(UserSymbolFields.ComponentRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(UserSymbolFields.Name), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(UserSymbolFields.Domain), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(UserSymbolFields.Password), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(UserSymbolFields.Attributes), IntermediateFieldType.Number), + }, + typeof(UserSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum UserSymbolFields + { + ComponentRef, + Name, + Domain, + Password, + Attributes, + } + + public class UserSymbol : IntermediateSymbol + { + public UserSymbol() : base(UtilSymbolDefinitions.User, null, null) + { + } + + public UserSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.User, sourceLineNumber, id) + { + } + + public IntermediateField this[UserSymbolFields index] => this.Fields[(int)index]; + + public string ComponentRef + { + get => this.Fields[(int)UserSymbolFields.ComponentRef].AsString(); + set => this.Set((int)UserSymbolFields.ComponentRef, value); + } + + public string Name + { + get => this.Fields[(int)UserSymbolFields.Name].AsString(); + set => this.Set((int)UserSymbolFields.Name, value); + } + + public string Domain + { + get => this.Fields[(int)UserSymbolFields.Domain].AsString(); + set => this.Set((int)UserSymbolFields.Domain, value); + } + + public string Password + { + get => this.Fields[(int)UserSymbolFields.Password].AsString(); + set => this.Set((int)UserSymbolFields.Password, value); + } + + public int Attributes + { + get => this.Fields[(int)UserSymbolFields.Attributes].AsNumber(); + set => this.Set((int)UserSymbolFields.Attributes, value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/Symbols/UtilSymbolDefinitions.cs b/src/ext/Util/wixext/Symbols/UtilSymbolDefinitions.cs new file mode 100644 index 00000000..72091c3b --- /dev/null +++ b/src/ext/Util/wixext/Symbols/UtilSymbolDefinitions.cs @@ -0,0 +1,125 @@ +// Copyright (c) .NET 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.Util +{ + using System; + using WixToolset.Data; + using WixToolset.Data.Burn; + + public enum UtilSymbolDefinitionType + { + EventManifest, + FileShare, + FileSharePermissions, + Group, + Perfmon, + PerfmonManifest, + PerformanceCategory, + SecureObjects, + ServiceConfig, + User, + UserGroup, + WixCloseApplication, + WixFormatFiles, + WixInternetShortcut, + WixRemoveFolderEx, + WixRemoveRegistryKeyEx, + WixRestartResource, + WixTouchFile, + WixWindowsFeatureSearch, + XmlConfig, + XmlFile, + } + + public static partial class UtilSymbolDefinitions + { + public static readonly Version Version = new Version("4.0.0"); + + public static IntermediateSymbolDefinition ByName(string name) + { + if (!Enum.TryParse(name, out UtilSymbolDefinitionType type)) + { + return null; + } + + return ByType(type); + } + + public static IntermediateSymbolDefinition ByType(UtilSymbolDefinitionType type) + { + switch (type) + { + case UtilSymbolDefinitionType.EventManifest: + return UtilSymbolDefinitions.EventManifest; + + case UtilSymbolDefinitionType.FileShare: + return UtilSymbolDefinitions.FileShare; + + case UtilSymbolDefinitionType.FileSharePermissions: + return UtilSymbolDefinitions.FileSharePermissions; + + case UtilSymbolDefinitionType.Group: + return UtilSymbolDefinitions.Group; + + case UtilSymbolDefinitionType.Perfmon: + return UtilSymbolDefinitions.Perfmon; + + case UtilSymbolDefinitionType.PerfmonManifest: + return UtilSymbolDefinitions.PerfmonManifest; + + case UtilSymbolDefinitionType.PerformanceCategory: + return UtilSymbolDefinitions.PerformanceCategory; + + case UtilSymbolDefinitionType.SecureObjects: + return UtilSymbolDefinitions.SecureObjects; + + case UtilSymbolDefinitionType.ServiceConfig: + return UtilSymbolDefinitions.ServiceConfig; + + case UtilSymbolDefinitionType.User: + return UtilSymbolDefinitions.User; + + case UtilSymbolDefinitionType.UserGroup: + return UtilSymbolDefinitions.UserGroup; + + case UtilSymbolDefinitionType.WixCloseApplication: + return UtilSymbolDefinitions.WixCloseApplication; + + case UtilSymbolDefinitionType.WixFormatFiles: + return UtilSymbolDefinitions.WixFormatFiles; + + case UtilSymbolDefinitionType.WixInternetShortcut: + return UtilSymbolDefinitions.WixInternetShortcut; + + case UtilSymbolDefinitionType.WixRemoveFolderEx: + return UtilSymbolDefinitions.WixRemoveFolderEx; + + case UtilSymbolDefinitionType.WixRemoveRegistryKeyEx: + return UtilSymbolDefinitions.WixRemoveRegistryKeyEx; + + case UtilSymbolDefinitionType.WixRestartResource: + return UtilSymbolDefinitions.WixRestartResource; + + case UtilSymbolDefinitionType.WixTouchFile: + return UtilSymbolDefinitions.WixTouchFile; + + case UtilSymbolDefinitionType.WixWindowsFeatureSearch: + return UtilSymbolDefinitions.WixWindowsFeatureSearch; + + case UtilSymbolDefinitionType.XmlConfig: + return UtilSymbolDefinitions.XmlConfig; + + case UtilSymbolDefinitionType.XmlFile: + return UtilSymbolDefinitions.XmlFile; + + default: + throw new ArgumentOutOfRangeException(nameof(type)); + } + } + + static UtilSymbolDefinitions() + { + WixWindowsFeatureSearch.AddTag(BurnConstants.BundleExtensionSearchSymbolDefinitionTag); + } + } +} diff --git a/src/ext/Util/wixext/Symbols/WixCloseApplicationSymbol.cs b/src/ext/Util/wixext/Symbols/WixCloseApplicationSymbol.cs new file mode 100644 index 00000000..0738e3e4 --- /dev/null +++ b/src/ext/Util/wixext/Symbols/WixCloseApplicationSymbol.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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition WixCloseApplication = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.WixCloseApplication.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Target), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Description), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Condition), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Attributes), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Sequence), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Property), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.TerminateExitCode), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Timeout), IntermediateFieldType.Number), + }, + typeof(WixCloseApplicationSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum WixCloseApplicationSymbolFields + { + Target, + Description, + Condition, + Attributes, + Sequence, + Property, + TerminateExitCode, + Timeout, + } + + public class WixCloseApplicationSymbol : IntermediateSymbol + { + public WixCloseApplicationSymbol() : base(UtilSymbolDefinitions.WixCloseApplication, null, null) + { + } + + public WixCloseApplicationSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixCloseApplication, sourceLineNumber, id) + { + } + + public IntermediateField this[WixCloseApplicationSymbolFields index] => this.Fields[(int)index]; + + public string Target + { + get => this.Fields[(int)WixCloseApplicationSymbolFields.Target].AsString(); + set => this.Set((int)WixCloseApplicationSymbolFields.Target, value); + } + + public string Description + { + get => this.Fields[(int)WixCloseApplicationSymbolFields.Description].AsString(); + set => this.Set((int)WixCloseApplicationSymbolFields.Description, value); + } + + public string Condition + { + get => this.Fields[(int)WixCloseApplicationSymbolFields.Condition].AsString(); + set => this.Set((int)WixCloseApplicationSymbolFields.Condition, value); + } + + public int Attributes + { + get => this.Fields[(int)WixCloseApplicationSymbolFields.Attributes].AsNumber(); + set => this.Set((int)WixCloseApplicationSymbolFields.Attributes, value); + } + + public int? Sequence + { + get => this.Fields[(int)WixCloseApplicationSymbolFields.Sequence].AsNullableNumber(); + set => this.Set((int)WixCloseApplicationSymbolFields.Sequence, value); + } + + public string Property + { + get => this.Fields[(int)WixCloseApplicationSymbolFields.Property].AsString(); + set => this.Set((int)WixCloseApplicationSymbolFields.Property, value); + } + + public int? TerminateExitCode + { + get => this.Fields[(int)WixCloseApplicationSymbolFields.TerminateExitCode].AsNullableNumber(); + set => this.Set((int)WixCloseApplicationSymbolFields.TerminateExitCode, value); + } + + public int? Timeout + { + get => this.Fields[(int)WixCloseApplicationSymbolFields.Timeout].AsNullableNumber(); + set => this.Set((int)WixCloseApplicationSymbolFields.Timeout, value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/Symbols/WixFormatFilesSymbol.cs b/src/ext/Util/wixext/Symbols/WixFormatFilesSymbol.cs new file mode 100644 index 00000000..38a9b8ff --- /dev/null +++ b/src/ext/Util/wixext/Symbols/WixFormatFilesSymbol.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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition WixFormatFiles = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.WixFormatFiles.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(WixFormatFilesSymbolFields.BinaryRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixFormatFilesSymbolFields.FileRef), IntermediateFieldType.String), + }, + typeof(WixFormatFilesSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum WixFormatFilesSymbolFields + { + BinaryRef, + FileRef, + } + + public class WixFormatFilesSymbol : IntermediateSymbol + { + public WixFormatFilesSymbol() : base(UtilSymbolDefinitions.WixFormatFiles, null, null) + { + } + + public WixFormatFilesSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixFormatFiles, sourceLineNumber, id) + { + } + + public IntermediateField this[WixFormatFilesSymbolFields index] => this.Fields[(int)index]; + + public string BinaryRef + { + get => this.Fields[(int)WixFormatFilesSymbolFields.BinaryRef].AsString(); + set => this.Set((int)WixFormatFilesSymbolFields.BinaryRef, value); + } + + public string FileRef + { + get => this.Fields[(int)WixFormatFilesSymbolFields.FileRef].AsString(); + set => this.Set((int)WixFormatFilesSymbolFields.FileRef, value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/Symbols/WixInternetShortcutSymbol.cs b/src/ext/Util/wixext/Symbols/WixInternetShortcutSymbol.cs new file mode 100644 index 00000000..e8265e02 --- /dev/null +++ b/src/ext/Util/wixext/Symbols/WixInternetShortcutSymbol.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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition WixInternetShortcut = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.WixInternetShortcut.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.ComponentRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.DirectoryRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.Name), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.Target), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.Attributes), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.IconFile), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.IconIndex), IntermediateFieldType.Number), + }, + typeof(WixInternetShortcutSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum WixInternetShortcutSymbolFields + { + ComponentRef, + DirectoryRef, + Name, + Target, + Attributes, + IconFile, + IconIndex, + } + + public class WixInternetShortcutSymbol : IntermediateSymbol + { + public WixInternetShortcutSymbol() : base(UtilSymbolDefinitions.WixInternetShortcut, null, null) + { + } + + public WixInternetShortcutSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixInternetShortcut, sourceLineNumber, id) + { + } + + public IntermediateField this[WixInternetShortcutSymbolFields index] => this.Fields[(int)index]; + + public string ComponentRef + { + get => this.Fields[(int)WixInternetShortcutSymbolFields.ComponentRef].AsString(); + set => this.Set((int)WixInternetShortcutSymbolFields.ComponentRef, value); + } + + public string DirectoryRef + { + get => this.Fields[(int)WixInternetShortcutSymbolFields.DirectoryRef].AsString(); + set => this.Set((int)WixInternetShortcutSymbolFields.DirectoryRef, value); + } + + public string Name + { + get => this.Fields[(int)WixInternetShortcutSymbolFields.Name].AsString(); + set => this.Set((int)WixInternetShortcutSymbolFields.Name, value); + } + + public string Target + { + get => this.Fields[(int)WixInternetShortcutSymbolFields.Target].AsString(); + set => this.Set((int)WixInternetShortcutSymbolFields.Target, value); + } + + public int Attributes + { + get => this.Fields[(int)WixInternetShortcutSymbolFields.Attributes].AsNumber(); + set => this.Set((int)WixInternetShortcutSymbolFields.Attributes, value); + } + + public string IconFile + { + get => this.Fields[(int)WixInternetShortcutSymbolFields.IconFile].AsString(); + set => this.Set((int)WixInternetShortcutSymbolFields.IconFile, value); + } + + public int? IconIndex + { + get => this.Fields[(int)WixInternetShortcutSymbolFields.IconIndex].AsNullableNumber(); + set => this.Set((int)WixInternetShortcutSymbolFields.IconIndex, value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/Symbols/WixRemoveFolderExSymbol.cs b/src/ext/Util/wixext/Symbols/WixRemoveFolderExSymbol.cs new file mode 100644 index 00000000..86352b6c --- /dev/null +++ b/src/ext/Util/wixext/Symbols/WixRemoveFolderExSymbol.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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition WixRemoveFolderEx = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.WixRemoveFolderEx.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.ComponentRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.Property), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.InstallMode), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.Condition), IntermediateFieldType.String), + }, + typeof(WixRemoveFolderExSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum WixRemoveFolderExSymbolFields + { + ComponentRef, + Property, + InstallMode, + Condition, + } + + public enum WixRemoveFolderExInstallMode + { + Install = 1, + Uninstall = 2, + Both = 3, + } + + public class WixRemoveFolderExSymbol : IntermediateSymbol + { + public WixRemoveFolderExSymbol() : base(UtilSymbolDefinitions.WixRemoveFolderEx, null, null) + { + } + + public WixRemoveFolderExSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixRemoveFolderEx, sourceLineNumber, id) + { + } + + public IntermediateField this[WixRemoveFolderExSymbolFields index] => this.Fields[(int)index]; + + public string ComponentRef + { + get => this.Fields[(int)WixRemoveFolderExSymbolFields.ComponentRef].AsString(); + set => this.Set((int)WixRemoveFolderExSymbolFields.ComponentRef, value); + } + + public string Property + { + get => this.Fields[(int)WixRemoveFolderExSymbolFields.Property].AsString(); + set => this.Set((int)WixRemoveFolderExSymbolFields.Property, value); + } + + public WixRemoveFolderExInstallMode InstallMode + { + get => (WixRemoveFolderExInstallMode)this.Fields[(int)WixRemoveFolderExSymbolFields.InstallMode].AsNumber(); + set => this.Set((int)WixRemoveFolderExSymbolFields.InstallMode, (int)value); + } + + public string Condition + { + get => this.Fields[(int)WixRemoveFolderExSymbolFields.Condition].AsString(); + set => this.Set((int)WixRemoveFolderExSymbolFields.Condition, value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/Symbols/WixRemoveRegistryKeyExSymbol.cs b/src/ext/Util/wixext/Symbols/WixRemoveRegistryKeyExSymbol.cs new file mode 100644 index 00000000..8e4bd212 --- /dev/null +++ b/src/ext/Util/wixext/Symbols/WixRemoveRegistryKeyExSymbol.cs @@ -0,0 +1,86 @@ +// Copyright (c) .NET 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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition WixRemoveRegistryKeyEx = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.WixRemoveRegistryKeyEx.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(WixRemoveRegistryKeyExSymbolFields.ComponentRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixRemoveRegistryKeyExSymbolFields.Root), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(WixRemoveRegistryKeyExSymbolFields.Key), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixRemoveRegistryKeyExSymbolFields.InstallMode), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(WixRemoveRegistryKeyExSymbolFields.Condition), IntermediateFieldType.String), + }, + typeof(WixRemoveRegistryKeyExSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + using WixToolset.Data.Symbols; + + public enum WixRemoveRegistryKeyExSymbolFields + { + ComponentRef, + Root, + Key, + InstallMode, + Condition, + } + + public enum WixRemoveRegistryKeyExInstallMode + { + Install = 1, + Uninstall = 2, + } + + public class WixRemoveRegistryKeyExSymbol : IntermediateSymbol + { + public WixRemoveRegistryKeyExSymbol() : base(UtilSymbolDefinitions.WixRemoveRegistryKeyEx, null, null) + { + } + + public WixRemoveRegistryKeyExSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixRemoveRegistryKeyEx, sourceLineNumber, id) + { + } + + public IntermediateField this[WixRemoveRegistryKeyExSymbolFields index] => this.Fields[(int)index]; + + public string ComponentRef + { + get => this.Fields[(int)WixRemoveRegistryKeyExSymbolFields.ComponentRef].AsString(); + set => this.Set((int)WixRemoveRegistryKeyExSymbolFields.ComponentRef, value); + } + + public RegistryRootType Root + { + get => (RegistryRootType)this.Fields[(int)WixRemoveRegistryKeyExSymbolFields.Root].AsNumber(); + set => this.Set((int)WixRemoveRegistryKeyExSymbolFields.Root, (int)value); + } + + public string Key + { + get => (string)this.Fields[(int)WixRemoveRegistryKeyExSymbolFields.Key]; + set => this.Set((int)WixRemoveRegistryKeyExSymbolFields.Key, value); + } + + public WixRemoveRegistryKeyExInstallMode InstallMode + { + get => (WixRemoveRegistryKeyExInstallMode)this.Fields[(int)WixRemoveRegistryKeyExSymbolFields.InstallMode].AsNumber(); + set => this.Set((int)WixRemoveRegistryKeyExSymbolFields.InstallMode, (int)value); + } + + public string Condition + { + get => this.Fields[(int)WixRemoveRegistryKeyExSymbolFields.Condition].AsString(); + set => this.Set((int)WixRemoveRegistryKeyExSymbolFields.Condition, value); + } + } +} diff --git a/src/ext/Util/wixext/Symbols/WixRestartResourceSymbol.cs b/src/ext/Util/wixext/Symbols/WixRestartResourceSymbol.cs new file mode 100644 index 00000000..01b92b63 --- /dev/null +++ b/src/ext/Util/wixext/Symbols/WixRestartResourceSymbol.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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition WixRestartResource = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.WixRestartResource.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(WixRestartResourceSymbolFields.ComponentRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixRestartResourceSymbolFields.Resource), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixRestartResourceSymbolFields.Attributes), IntermediateFieldType.Number), + }, + typeof(WixRestartResourceSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum WixRestartResourceSymbolFields + { + ComponentRef, + Resource, + Attributes, + } + + public enum WixRestartResourceAttributes + { + Filename = 1, + ProcessName, + ServiceName, + TypeMask = 0xf, + } + + public class WixRestartResourceSymbol : IntermediateSymbol + { + public WixRestartResourceSymbol() : base(UtilSymbolDefinitions.WixRestartResource, null, null) + { + } + + public WixRestartResourceSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixRestartResource, sourceLineNumber, id) + { + } + + public IntermediateField this[WixRestartResourceSymbolFields index] => this.Fields[(int)index]; + + public string ComponentRef + { + get => this.Fields[(int)WixRestartResourceSymbolFields.ComponentRef].AsString(); + set => this.Set((int)WixRestartResourceSymbolFields.ComponentRef, value); + } + + public string Resource + { + get => this.Fields[(int)WixRestartResourceSymbolFields.Resource].AsString(); + set => this.Set((int)WixRestartResourceSymbolFields.Resource, value); + } + + public WixRestartResourceAttributes? Attributes + { + get => (WixRestartResourceAttributes?)this.Fields[(int)WixRestartResourceSymbolFields.Attributes].AsNullableNumber(); + set => this.Set((int)WixRestartResourceSymbolFields.Attributes, (int?)value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/Symbols/WixTouchFileSymbol.cs b/src/ext/Util/wixext/Symbols/WixTouchFileSymbol.cs new file mode 100644 index 00000000..447c21ba --- /dev/null +++ b/src/ext/Util/wixext/Symbols/WixTouchFileSymbol.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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition WixTouchFile = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.WixTouchFile.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(WixTouchFileSymbolFields.ComponentRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixTouchFileSymbolFields.Path), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixTouchFileSymbolFields.Attributes), IntermediateFieldType.Number), + }, + typeof(WixTouchFileSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum WixTouchFileSymbolFields + { + ComponentRef, + Path, + Attributes, + } + + public class WixTouchFileSymbol : IntermediateSymbol + { + public WixTouchFileSymbol() : base(UtilSymbolDefinitions.WixTouchFile, null, null) + { + } + + public WixTouchFileSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixTouchFile, sourceLineNumber, id) + { + } + + public IntermediateField this[WixTouchFileSymbolFields index] => this.Fields[(int)index]; + + public string ComponentRef + { + get => this.Fields[(int)WixTouchFileSymbolFields.ComponentRef].AsString(); + set => this.Set((int)WixTouchFileSymbolFields.ComponentRef, value); + } + + public string Path + { + get => this.Fields[(int)WixTouchFileSymbolFields.Path].AsString(); + set => this.Set((int)WixTouchFileSymbolFields.Path, value); + } + + public int Attributes + { + get => this.Fields[(int)WixTouchFileSymbolFields.Attributes].AsNumber(); + set => this.Set((int)WixTouchFileSymbolFields.Attributes, value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/Symbols/WixWindowsFeatureSearchSymbol.cs b/src/ext/Util/wixext/Symbols/WixWindowsFeatureSearchSymbol.cs new file mode 100644 index 00000000..9a43692c --- /dev/null +++ b/src/ext/Util/wixext/Symbols/WixWindowsFeatureSearchSymbol.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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition WixWindowsFeatureSearch = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.WixWindowsFeatureSearch.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(WixWindowsFeatureSearchSymbolFields.Type), IntermediateFieldType.String), + }, + typeof(WixWindowsFeatureSearchSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum WixWindowsFeatureSearchSymbolFields + { + Type, + } + + public class WixWindowsFeatureSearchSymbol : IntermediateSymbol + { + public WixWindowsFeatureSearchSymbol() : base(UtilSymbolDefinitions.WixWindowsFeatureSearch, null, null) + { + } + + public WixWindowsFeatureSearchSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixWindowsFeatureSearch, sourceLineNumber, id) + { + } + + public IntermediateField this[WixWindowsFeatureSearchSymbolFields index] => this.Fields[(int)index]; + + public string Type + { + get => this.Fields[(int)WixWindowsFeatureSearchSymbolFields.Type].AsString(); + set => this.Set((int)WixWindowsFeatureSearchSymbolFields.Type, value); + } + } +} diff --git a/src/ext/Util/wixext/Symbols/XmlConfigSymbol.cs b/src/ext/Util/wixext/Symbols/XmlConfigSymbol.cs new file mode 100644 index 00000000..6503a586 --- /dev/null +++ b/src/ext/Util/wixext/Symbols/XmlConfigSymbol.cs @@ -0,0 +1,111 @@ +// Copyright (c) .NET 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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition XmlConfig = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.XmlConfig.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.File), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.ElementId), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.ElementPath), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.VerifyPath), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.Name), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.Value), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.Flags), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.ComponentRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.Sequence), IntermediateFieldType.Number), + }, + typeof(XmlConfigSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum XmlConfigSymbolFields + { + File, + ElementId, + ElementPath, + VerifyPath, + Name, + Value, + Flags, + ComponentRef, + Sequence, + } + + public class XmlConfigSymbol : IntermediateSymbol + { + public XmlConfigSymbol() : base(UtilSymbolDefinitions.XmlConfig, null, null) + { + } + + public XmlConfigSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.XmlConfig, sourceLineNumber, id) + { + } + + public IntermediateField this[XmlConfigSymbolFields index] => this.Fields[(int)index]; + + public string File + { + get => this.Fields[(int)XmlConfigSymbolFields.File].AsString(); + set => this.Set((int)XmlConfigSymbolFields.File, value); + } + + public string ElementId + { + get => this.Fields[(int)XmlConfigSymbolFields.ElementId].AsString(); + set => this.Set((int)XmlConfigSymbolFields.ElementId, value); + } + + public string ElementPath + { + get => this.Fields[(int)XmlConfigSymbolFields.ElementPath].AsString(); + set => this.Set((int)XmlConfigSymbolFields.ElementPath, value); + } + + public string VerifyPath + { + get => this.Fields[(int)XmlConfigSymbolFields.VerifyPath].AsString(); + set => this.Set((int)XmlConfigSymbolFields.VerifyPath, value); + } + + public string Name + { + get => this.Fields[(int)XmlConfigSymbolFields.Name].AsString(); + set => this.Set((int)XmlConfigSymbolFields.Name, value); + } + + public string Value + { + get => this.Fields[(int)XmlConfigSymbolFields.Value].AsString(); + set => this.Set((int)XmlConfigSymbolFields.Value, value); + } + + public int Flags + { + get => this.Fields[(int)XmlConfigSymbolFields.Flags].AsNumber(); + set => this.Set((int)XmlConfigSymbolFields.Flags, value); + } + + public string ComponentRef + { + get => this.Fields[(int)XmlConfigSymbolFields.ComponentRef].AsString(); + set => this.Set((int)XmlConfigSymbolFields.ComponentRef, value); + } + + public int? Sequence + { + get => this.Fields[(int)XmlConfigSymbolFields.Sequence].AsNullableNumber(); + set => this.Set((int)XmlConfigSymbolFields.Sequence, value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/Symbols/XmlFileSymbol.cs b/src/ext/Util/wixext/Symbols/XmlFileSymbol.cs new file mode 100644 index 00000000..7d5d991b --- /dev/null +++ b/src/ext/Util/wixext/Symbols/XmlFileSymbol.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.Util +{ + using WixToolset.Data; + using WixToolset.Util.Symbols; + + public static partial class UtilSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition XmlFile = new IntermediateSymbolDefinition( + UtilSymbolDefinitionType.XmlFile.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.File), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.ElementPath), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.Name), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.Value), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.Flags), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.ComponentRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.Sequence), IntermediateFieldType.Number), + }, + typeof(XmlFileSymbol)); + } +} + +namespace WixToolset.Util.Symbols +{ + using WixToolset.Data; + + public enum XmlFileSymbolFields + { + File, + ElementPath, + Name, + Value, + Flags, + ComponentRef, + Sequence, + } + + public class XmlFileSymbol : IntermediateSymbol + { + public XmlFileSymbol() : base(UtilSymbolDefinitions.XmlFile, null, null) + { + } + + public XmlFileSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.XmlFile, sourceLineNumber, id) + { + } + + public IntermediateField this[XmlFileSymbolFields index] => this.Fields[(int)index]; + + public string File + { + get => this.Fields[(int)XmlFileSymbolFields.File].AsString(); + set => this.Set((int)XmlFileSymbolFields.File, value); + } + + public string ElementPath + { + get => this.Fields[(int)XmlFileSymbolFields.ElementPath].AsString(); + set => this.Set((int)XmlFileSymbolFields.ElementPath, value); + } + + public string Name + { + get => this.Fields[(int)XmlFileSymbolFields.Name].AsString(); + set => this.Set((int)XmlFileSymbolFields.Name, value); + } + + public string Value + { + get => this.Fields[(int)XmlFileSymbolFields.Value].AsString(); + set => this.Set((int)XmlFileSymbolFields.Value, value); + } + + public int Flags + { + get => this.Fields[(int)XmlFileSymbolFields.Flags].AsNumber(); + set => this.Set((int)XmlFileSymbolFields.Flags, value); + } + + public string ComponentRef + { + get => this.Fields[(int)XmlFileSymbolFields.ComponentRef].AsString(); + set => this.Set((int)XmlFileSymbolFields.ComponentRef, value); + } + + public int? Sequence + { + get => this.Fields[(int)XmlFileSymbolFields.Sequence].AsNullableNumber(); + set => this.Set((int)XmlFileSymbolFields.Sequence, value); + } + } +} \ No newline at end of file diff --git a/src/ext/Util/wixext/UtilCompiler.cs b/src/ext/Util/wixext/UtilCompiler.cs new file mode 100644 index 00000000..45079150 --- /dev/null +++ b/src/ext/Util/wixext/UtilCompiler.cs @@ -0,0 +1,3889 @@ +// Copyright (c) .NET 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.Util +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + using System.Text; + using System.Text.RegularExpressions; + using System.Xml.Linq; + using WixToolset.Data; + using WixToolset.Data.Symbols; + using WixToolset.Extensibility; + using WixToolset.Extensibility.Data; + using WixToolset.Util.Symbols; + + /// + /// The compiler for the WiX Toolset Utility Extension. + /// + public sealed class UtilCompiler : BaseCompilerExtension + { + // user creation attributes definitions (from sca.h) + internal const int UserDontExpirePasswrd = 0x00000001; + internal const int UserPasswdCantChange = 0x00000002; + internal const int UserPasswdChangeReqdOnLogin = 0x00000004; + internal const int UserDisableAccount = 0x00000008; + internal const int UserFailIfExists = 0x00000010; + internal const int UserUpdateIfExists = 0x00000020; + internal const int UserLogonAsService = 0x00000040; + internal const int UserLogonAsBatchJob = 0x00000080; + + internal const int UserDontRemoveOnUninstall = 0x00000100; + internal const int UserDontCreateUser = 0x00000200; + internal const int UserNonVital = 0x00000400; + + private static readonly Regex FindPropertyBrackets = new Regex(@"\[(?!\\|\])|(? "http://wixtoolset.org/schemas/v4/wxs/util"; + + /// + /// Types of Internet shortcuts. + /// + public enum InternetShortcutType + { + /// Create a .lnk file. + Link = 0, + + /// Create a .url file. + Url, + } + + /// + /// Types of permission setting methods. + /// + private enum PermissionType + { + /// LockPermissions (normal) type permission setting. + LockPermissions, + + /// FileSharePermissions type permission setting. + FileSharePermissions, + + /// SecureObjects type permission setting. + SecureObjects, + } + + /// + /// Processes an element for the Compiler. + /// + /// Parent element of element to process. + /// Element to process. + /// Extra information about the context in which this element is being parsed. + public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary context) + { + this.ParsePossibleKeyPathElement(intermediate, section, parentElement, element, context); + } + + /// + /// Processes an element for the Compiler. + /// + /// Source line number for the parent element. + /// Parent element of element to process. + /// Element to process. + /// Extra information about the context in which this element is being parsed. + public override IComponentKeyPath ParsePossibleKeyPathElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary context) + { + IComponentKeyPath possibleKeyPath = null; + + switch (parentElement.Name.LocalName) + { + case "CreateFolder": + var createFolderId = context["DirectoryId"]; + var createFolderComponentId = context["ComponentId"]; + + // If this doesn't parse successfully, something really odd is going on, so let the exception get thrown + var createFolderWin64 = Boolean.Parse(context["Win64"]); + + switch (element.Name.LocalName) + { + case "PermissionEx": + this.ParsePermissionExElement(intermediate, section, element, createFolderId, createFolderComponentId, createFolderWin64, "CreateFolder"); + break; + default: + this.ParseHelper.UnexpectedElement(parentElement, element); + break; + } + break; + case "Component": + var componentId = context["ComponentId"]; + var directoryId = context["DirectoryId"]; + var componentWin64 = Boolean.Parse(context["Win64"]); + + switch (element.Name.LocalName) + { + case "EventSource": + possibleKeyPath = this.ParseEventSourceElement(intermediate, section, element, componentId); + break; + case "FileShare": + this.ParseFileShareElement(intermediate, section, element, componentId, directoryId); + break; + case "InternetShortcut": + this.ParseInternetShortcutElement(intermediate, section, element, componentId, directoryId); + break; + case "PerformanceCategory": + this.ParsePerformanceCategoryElement(intermediate, section, element, componentId); + break; + case "RemoveFolderEx": + this.ParseRemoveFolderExElement(intermediate, section, element, componentId); + break; + case "RemoveRegistryKey": + this.ParseRemoveRegistryKeyExElement(intermediate, section, element, componentId); + break; + case "RestartResource": + this.ParseRestartResourceElement(intermediate, section, element, componentId); + break; + case "ServiceConfig": + this.ParseServiceConfigElement(intermediate, section, element, componentId, "Component", null); + break; + case "TouchFile": + this.ParseTouchFileElement(intermediate, section, element, componentId, componentWin64); + break; + case "User": + this.ParseUserElement(intermediate, section, element, componentId); + break; + case "XmlFile": + this.ParseXmlFileElement(intermediate, section, element, componentId); + break; + case "XmlConfig": + this.ParseXmlConfigElement(intermediate, section, element, componentId, false); + break; + default: + this.ParseHelper.UnexpectedElement(parentElement, element); + break; + } + break; + case "File": + var fileId = context["FileId"]; + var fileComponentId = context["ComponentId"]; + + // If this doesn't parse successfully, something really odd is going on, so let the exception get thrown + var fileWin64 = Boolean.Parse(context["Win64"]); + + switch (element.Name.LocalName) + { + case "PerfCounter": + this.ParsePerfCounterElement(intermediate, section, element, fileComponentId, fileId); + break; + case "PermissionEx": + this.ParsePermissionExElement(intermediate, section, element, fileId, fileComponentId, fileWin64, "File"); + break; + case "PerfCounterManifest": + this.ParsePerfCounterManifestElement(intermediate, section, element, fileComponentId, fileId); + break; + case "EventManifest": + this.ParseEventManifestElement(intermediate, section, element, fileComponentId, fileId); + break; + case "FormatFile": + this.ParseFormatFileElement(intermediate, section, element, fileId, fileWin64); + break; + default: + this.ParseHelper.UnexpectedElement(parentElement, element); + break; + } + break; + case "Bundle": + case "Fragment": + case "Module": + case "Package": + switch (element.Name.LocalName) + { + case "CloseApplication": + this.ParseCloseApplicationElement(intermediate, section, element); + break; + case "Group": + this.ParseGroupElement(intermediate, section, element, null); + break; + case "RestartResource": + // Currently not supported for Bundles. + if (parentElement.Name.LocalName != "Bundle") + { + this.ParseRestartResourceElement(intermediate, section, element, null); + } + else + { + this.ParseHelper.UnexpectedElement(parentElement, element); + } + break; + case "User": + this.ParseUserElement(intermediate, section, element, null); + break; + case "BroadcastEnvironmentChange": + case "BroadcastSettingChange": + case "CheckRebootRequired": + case "ExitEarlyWithSuccess": + case "FailWhenDeferred": + case "QueryWindowsDirectories": + case "QueryWindowsDriverInfo": + case "QueryWindowsSuiteInfo": + case "QueryWindowsWellKnownSIDs": + case "WaitForEvent": + case "WaitForEventDeferred": + this.AddCustomActionReference(intermediate, section, element, parentElement); + break; + case "ComponentSearch": + case "ComponentSearchRef": + case "DirectorySearch": + case "DirectorySearchRef": + case "FileSearch": + case "FileSearchRef": + case "ProductSearch": + case "ProductSearchRef": + case "RegistrySearch": + case "RegistrySearchRef": + case "WindowsFeatureSearch": + case "WindowsFeatureSearchRef": + // These will eventually be supported under Module/Product, but are not yet. + if (parentElement.Name.LocalName == "Bundle" || parentElement.Name.LocalName == "Fragment") + { + // TODO: When these are supported by all section types, move + // these out of the nested switch and back into the surrounding one. + switch (element.Name.LocalName) + { + case "ComponentSearch": + this.ParseComponentSearchElement(intermediate, section, element); + break; + case "ComponentSearchRef": + this.ParseComponentSearchRefElement(intermediate, section, element); + break; + case "DirectorySearch": + this.ParseDirectorySearchElement(intermediate, section, element); + break; + case "DirectorySearchRef": + this.ParseWixSearchRefElement(intermediate, section, element); + break; + case "FileSearch": + this.ParseFileSearchElement(intermediate, section, element); + break; + case "FileSearchRef": + this.ParseWixSearchRefElement(intermediate, section, element); + break; + case "ProductSearch": + this.ParseProductSearchElement(intermediate, section, element); + break; + case "ProductSearchRef": + this.ParseWixSearchRefElement(intermediate, section, element); + break; + case "RegistrySearch": + this.ParseRegistrySearchElement(intermediate, section, element); + break; + case "RegistrySearchRef": + this.ParseWixSearchRefElement(intermediate, section, element); + break; + case "WindowsFeatureSearch": + this.ParseWindowsFeatureSearchElement(intermediate, section, element); + break; + case "WindowsFeatureSearchRef": + this.ParseWindowsFeatureSearchRefElement(intermediate, section, element); + break; + } + } + else + { + this.ParseHelper.UnexpectedElement(parentElement, element); + } + break; + default: + this.ParseHelper.UnexpectedElement(parentElement, element); + break; + } + break; + case "Registry": + case "RegistryKey": + case "RegistryValue": + var registryId = context["RegistryId"]; + var registryComponentId = context["ComponentId"]; + + // If this doesn't parse successfully, something really odd is going on, so let the exception get thrown + var registryWin64 = Boolean.Parse(context["Win64"]); + + switch (element.Name.LocalName) + { + case "PermissionEx": + this.ParsePermissionExElement(intermediate, section, element, registryId, registryComponentId, registryWin64, "Registry"); + break; + default: + this.ParseHelper.UnexpectedElement(parentElement, element); + break; + } + break; + case "ServiceInstall": + var serviceInstallId = context["ServiceInstallId"]; + var serviceInstallName = context["ServiceInstallName"]; + var serviceInstallComponentId = context["ServiceInstallComponentId"]; + + // If this doesn't parse successfully, something really odd is going on, so let the exception get thrown + var serviceInstallWin64 = Boolean.Parse(context["Win64"]); + + switch (element.Name.LocalName) + { + case "PermissionEx": + this.ParsePermissionExElement(intermediate, section, element, serviceInstallId, serviceInstallComponentId, serviceInstallWin64, "ServiceInstall"); + break; + case "ServiceConfig": + this.ParseServiceConfigElement(intermediate, section, element, serviceInstallComponentId, "ServiceInstall", serviceInstallName); + break; + default: + this.ParseHelper.UnexpectedElement(parentElement, element); + break; + } + break; + case "UI": + switch (element.Name.LocalName) + { + case "BroadcastEnvironmentChange": + case "BroadcastSettingChange": + case "CheckRebootRequired": + case "ExitEarlyWithSuccess": + case "FailWhenDeferred": + case "QueryWindowsDirectories": + case "QueryWindowsDriverInfo": + case "QueryWindowsSuiteInfo": + case "QueryWindowsWellKnownSIDs": + case "WaitForEvent": + case "WaitForEventDeferred": + this.AddCustomActionReference(intermediate, section, element, parentElement); + break; + } + break; + default: + this.ParseHelper.UnexpectedElement(parentElement, element); + break; + } + + return possibleKeyPath; + } + + private void AddCustomActionReference(Intermediate intermediate, IntermediateSection section, XElement element, XElement parentElement) + { + // These elements are not supported for bundles. + if (parentElement.Name.LocalName == "Bundle") + { + this.ParseHelper.UnexpectedElement(parentElement, element); + return; + } + + var customAction = element.Name.LocalName; + switch (element.Name.LocalName) + { + case "BroadcastEnvironmentChange": + case "BroadcastSettingChange": + case "CheckRebootRequired": + case "ExitEarlyWithSuccess": + case "FailWhenDeferred": + case "WaitForEvent": + case "WaitForEventDeferred": + //default: customAction = element.Name.LocalName; + break; + case "QueryWindowsDirectories": + customAction = "QueryOsDirs"; + break; + case "QueryWindowsDriverInfo": + customAction = "QueryOsDriverInfo"; + break; + case "QueryWindowsSuiteInfo": + customAction = "QueryOsInfo"; + break; + case "QueryWindowsWellKnownSIDs": + customAction = "QueryOsWellKnownSID"; + break; + } + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + // no attributes today + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4" + customAction, this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + } + + /// + /// Parses the common search attributes shared across all searches. + /// + /// Source line number for the parent element. + /// Attribute to parse. + /// Value of the Id attribute. + /// Value of the Variable attribute. + /// Value of the Condition attribute. + /// Value of the After attribute. + private void ParseCommonSearchAttributes(SourceLineNumber sourceLineNumbers, XAttribute attrib, ref Identifier id, ref string variable, ref string condition, ref string after) + { + switch (attrib.Name.LocalName) + { + case "Id": + id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); + break; + case "Variable": + variable = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + // TODO: handle standard bundle variables + break; + case "Condition": + condition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "After": + after = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + default: + System.Diagnostics.Debug.Assert(false); + break; + } + } + + /// + /// Parses a ComponentSearch element. + /// + /// Element to parse. + private void ParseComponentSearchElement(Intermediate intermediate, IntermediateSection section, XElement element) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + Identifier id = null; + string variable = null; + string condition = null; + string after = null; + string guid = null; + string productCode = null; + var attributes = WixComponentSearchAttributes.KeyPath; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + case "Variable": + case "Condition": + case "After": + this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after); + break; + case "Guid": + guid = this.ParseHelper.GetAttributeGuidValue(sourceLineNumbers, attrib); + break; + case "ProductCode": + productCode = this.ParseHelper.GetAttributeGuidValue(sourceLineNumbers, attrib); + break; + case "Result": + var result = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + switch (result) + { + case "directory": + attributes = WixComponentSearchAttributes.WantDirectory; + break; + case "keyPath": + attributes = WixComponentSearchAttributes.KeyPath; + break; + case "state": + attributes = WixComponentSearchAttributes.State; + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Parent.Name.LocalName, attrib.Name.LocalName, result, "directory", "keyPath", "state")); + break; + } + break; + default: + this.ParseHelper.UnexpectedAttribute(element, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + if (null == guid) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Guid")); + } + + if (null == id) + { + id = this.ParseHelper.CreateIdentifier("wcs", variable, condition, after, guid, productCode, attributes.ToString()); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, null); + + if (!this.Messaging.EncounteredError) + { + section.AddSymbol(new WixComponentSearchSymbol(sourceLineNumbers, id) + { + Guid = guid, + ProductCode = productCode, + Attributes = attributes, + }); + } + } + + /// + /// Parses a ComponentSearchRef element + /// + /// Element to parse. + private void ParseComponentSearchRefElement(Intermediate intermediate, IntermediateSection section, XElement element) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + string refId = null; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + refId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixComponentSearch, refId); + 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); + } + + /// + /// Parses a WindowsFeatureSearch element. + /// + /// Element to parse. + private void ParseWindowsFeatureSearchElement(Intermediate intermediate, IntermediateSection section, XElement element) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + Identifier id = null; + string variable = null; + string condition = null; + string after = null; + string feature = null; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + case "Variable": + case "Condition": + case "After": + this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after); + break; + case "Feature": + feature = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + switch (feature) + { + case "sha2CodeSigning": + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Feature", feature, "sha2CodeSigning")); + break; + } + break; + default: + this.ParseHelper.UnexpectedAttribute(element, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + if (id == null) + { + id = this.ParseHelper.CreateIdentifier("wwfs", variable, condition, after); + } + + if (feature == null) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Feature")); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + var bundleExtensionId = this.ParseHelper.CreateIdentifierValueFromPlatform("Wix4UtilBundleExtension", this.Context.Platform, BurnPlatforms.X86 | BurnPlatforms.X64 | BurnPlatforms.ARM64); + if (bundleExtensionId == null) + { + this.Messaging.Write(ErrorMessages.UnsupportedPlatformForElement(sourceLineNumbers, this.Context.Platform.ToString(), element.Name.LocalName)); + } + + this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, bundleExtensionId); + + if (!this.Messaging.EncounteredError) + { + section.AddSymbol(new WixWindowsFeatureSearchSymbol(sourceLineNumbers, id) + { + Type = feature, + }); + } + } + + /// + /// Parses a WindowsFeatureSearchRef element + /// + /// Element to parse. + private void ParseWindowsFeatureSearchRefElement(Intermediate intermediate, IntermediateSection section, XElement element) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + var refId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, UtilSymbolDefinitions.WixWindowsFeatureSearch, refId); + 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); + } + + /// + /// Parses an event source element. + /// + /// Element to parse. + /// Identifier of parent component. + private IComponentKeyPath ParseEventSourceElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + string sourceName = null; + string logName = null; + string categoryMessageFile = null; + var categoryCount = CompilerConstants.IntegerNotSet; + string eventMessageFile = null; + string parameterMessageFile = null; + int typesSupported = 0; + var isKeyPath = false; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "CategoryCount": + categoryCount = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue); + break; + case "CategoryMessageFile": + categoryMessageFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "EventMessageFile": + eventMessageFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "KeyPath": + isKeyPath = YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "Log": + logName = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + if ("Security" == logName) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, logName, "Application", "System", "")); + } + break; + case "Name": + sourceName = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "ParameterMessageFile": + parameterMessageFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "SupportsErrors": + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + typesSupported |= 0x01; // EVENTLOG_ERROR_TYPE + } + break; + case "SupportsFailureAudits": + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + typesSupported |= 0x10; // EVENTLOG_AUDIT_FAILURE + } + break; + case "SupportsInformationals": + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + typesSupported |= 0x04; // EVENTLOG_INFORMATION_TYPE + } + break; + case "SupportsSuccessAudits": + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + typesSupported |= 0x08; // EVENTLOG_AUDIT_SUCCESS + } + break; + case "SupportsWarnings": + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + typesSupported |= 0x02; // EVENTLOG_WARNING_TYPE + } + break; + default: + this.ParseHelper.UnexpectedAttribute(element, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + if (null == sourceName) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); + } + + if (null == logName) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "EventLog")); + } + + if (null == eventMessageFile) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "EventMessageFile")); + } + + if (null == categoryMessageFile && 0 < categoryCount) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeWithoutOtherAttributes(sourceLineNumbers, element.Name.LocalName, "CategoryCount", "CategoryMessageFile")); + } + + if (null != categoryMessageFile && CompilerConstants.IntegerNotSet == categoryCount) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeWithoutOtherAttributes(sourceLineNumbers, element.Name.LocalName, "CategoryMessageFile", "CategoryCount")); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + string eventSourceKey = $@"SYSTEM\CurrentControlSet\Services\EventLog\{logName}\{sourceName}"; + var id = this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, eventSourceKey, "EventMessageFile", String.Concat("#%", eventMessageFile), componentId, false); + + if (null != categoryMessageFile) + { + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, eventSourceKey, "CategoryMessageFile", String.Concat("#%", categoryMessageFile), componentId, false); + } + + if (CompilerConstants.IntegerNotSet != categoryCount) + { + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, eventSourceKey, "CategoryCount", String.Concat("#", categoryCount), componentId, false); + } + + if (null != parameterMessageFile) + { + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, eventSourceKey, "ParameterMessageFile", String.Concat("#%", parameterMessageFile), componentId, false); + } + + if (0 != typesSupported) + { + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, eventSourceKey, "TypesSupported", String.Concat("#", typesSupported), componentId, false); + } + + var componentKeyPath = this.CreateComponentKeyPath(); + componentKeyPath.Id = id.Id; + componentKeyPath.Explicit = isKeyPath; + componentKeyPath.Type = PossibleKeyPathType.Registry; + return componentKeyPath; + } + + /// + /// Parses a close application element. + /// + /// Element to parse. + private void ParseCloseApplicationElement(Intermediate intermediate, IntermediateSection section, XElement element) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + string condition = null; + string description = null; + string target = null; + string property = null; + Identifier id = null; + int attributes = 2; // default to CLOSEAPP_ATTRIBUTE_REBOOTPROMPT enabled + var sequence = CompilerConstants.IntegerNotSet; + var terminateExitCode = CompilerConstants.IntegerNotSet; + var timeout = 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 "Condition": + condition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Description": + description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Property": + property = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + break; + case "Sequence": + sequence = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue); + break; + case "Timeout": + timeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue); + break; + case "Target": + target = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "CloseMessage": + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= 1; // CLOSEAPP_ATTRIBUTE_CLOSEMESSAGE + } + else + { + attributes &= ~1; // CLOSEAPP_ATTRIBUTE_CLOSEMESSAGE + } + break; + case "EndSessionMessage": + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= 8; // CLOSEAPP_ATTRIBUTE_ENDSESSIONMESSAGE + } + else + { + attributes &= ~8; // CLOSEAPP_ATTRIBUTE_ENDSESSIONMESSAGE + } + break; + case "PromptToContinue": + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= 0x40; // CLOSEAPP_ATTRIBUTE_PROMPTTOCONTINUE + } + else + { + attributes &= ~0x40; // CLOSEAPP_ATTRIBUTE_PROMPTTOCONTINUE + } + break; + case "RebootPrompt": + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= 2; // CLOSEAPP_ATTRIBUTE_REBOOTPROMPT + } + else + { + attributes &= ~2; // CLOSEAPP_ATTRIBUTE_REBOOTPROMPT + } + break; + case "ElevatedCloseMessage": + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= 4; // CLOSEAPP_ATTRIBUTE_ELEVATEDCLOSEMESSAGE + } + else + { + attributes &= ~4; // CLOSEAPP_ATTRIBUTE_ELEVATEDCLOSEMESSAGE + } + break; + case "ElevatedEndSessionMessage": + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= 0x10; // CLOSEAPP_ATTRIBUTE_ELEVATEDENDSESSIONMESSAGE + } + else + { + attributes &= ~0x10; // CLOSEAPP_ATTRIBUTE_ELEVATEDENDSESSIONMESSAGE + } + break; + case "TerminateProcess": + terminateExitCode = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue); + attributes |= 0x20; // CLOSEAPP_ATTRIBUTE_TERMINATEPROCESS + break; + default: + this.ParseHelper.UnexpectedAttribute(element, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + if (null == target) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Target")); + } + else if (null == id) + { + id = this.ParseHelper.CreateIdentifier("ca", target); + } + + if (String.IsNullOrEmpty(description) && 0x40 == (attributes & 0x40)) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeValueWithoutOtherAttribute(sourceLineNumbers, element.Name.LocalName, "PromptToContinue", "yes", "Description")); + } + + if (0x22 == (attributes & 0x22)) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "TerminateProcess", "RebootPrompt", "yes")); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4CloseApplications", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + + if (!this.Messaging.EncounteredError) + { + var symbol = section.AddSymbol(new WixCloseApplicationSymbol(sourceLineNumbers, id) + { + Target = target, + Description = description, + Condition = condition, + Attributes = attributes, + Property = property, + }); + if (CompilerConstants.IntegerNotSet != sequence) + { + symbol.Sequence = sequence; + } + if (CompilerConstants.IntegerNotSet != terminateExitCode) + { + symbol.TerminateExitCode = terminateExitCode; + } + if (CompilerConstants.IntegerNotSet != timeout) + { + symbol.Timeout = timeout * 1000; // make the timeout milliseconds in the table. + } + } + } + + /// + /// Parses a DirectorySearch element. + /// + /// Element to parse. + private void ParseDirectorySearchElement(Intermediate intermediate, IntermediateSection section, XElement element) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + Identifier id = null; + string variable = null; + string condition = null; + string after = null; + string path = null; + var attributes = WixFileSearchAttributes.IsDirectory; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + case "Variable": + case "Condition": + case "After": + this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after); + break; + case "Path": + path = this.ParseHelper.GetAttributeLongFilename(sourceLineNumbers, attrib, false, true); + break; + case "Result": + var result = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + switch (result) + { + case "exists": + attributes |= WixFileSearchAttributes.WantExists; + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Parent.Name.LocalName, attrib.Name.LocalName, result, "exists")); + break; + } + break; + default: + this.ParseHelper.UnexpectedAttribute(element, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + if (null == path) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Path")); + } + + if (null == id) + { + id = this.ParseHelper.CreateIdentifier("wds", variable, condition, after, path, attributes.ToString()); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, null); + + if (!this.Messaging.EncounteredError) + { + this.CreateWixFileSearchRow(section, sourceLineNumbers, id, path, attributes); + } + } + + /// + /// Parses a DirectorySearchRef, FileSearchRef, ProductSearchRef, and RegistrySearchRef elements + /// + /// Element to parse. + private void ParseWixSearchRefElement(Intermediate intermediate, IntermediateSection section, XElement node) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(node); + + foreach (XAttribute attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + var refId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixSearch, refId); + break; + default: + this.ParseHelper.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, node, attrib); + } + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, node); + } + + /// + /// Parses a FileSearch element. + /// + /// Element to parse. + private void ParseFileSearchElement(Intermediate intermediate, IntermediateSection section, XElement node) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(node); + Identifier id = null; + string variable = null; + string condition = null; + string after = null; + string path = null; + var attributes = WixFileSearchAttributes.Default; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + case "Variable": + case "Condition": + case "After": + this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after); + break; + case "Path": + path = this.ParseHelper.GetAttributeLongFilename(sourceLineNumbers, attrib, false, true); + break; + case "Result": + string result = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + switch (result) + { + case "exists": + attributes |= WixFileSearchAttributes.WantExists; + break; + case "version": + attributes |= WixFileSearchAttributes.WantVersion; + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Parent.Name.LocalName, attrib.Name.LocalName, result, "exists", "version")); + break; + } + break; + default: + this.ParseHelper.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, node, attrib); + } + } + + if (null == path) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Path")); + } + + if (null == id) + { + id = this.ParseHelper.CreateIdentifier("wfs", variable, condition, after, path, attributes.ToString()); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, node); + + this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, node.Name.LocalName, id, variable, condition, after, null); + + if (!this.Messaging.EncounteredError) + { + this.CreateWixFileSearchRow(section, sourceLineNumbers, id, path, attributes); + } + } + + /// + /// Creates a row in the WixFileSearch table. + /// + /// Source line number for the parent element. + /// Identifier of the search (key into the WixSearch table) + /// File/directory path to search for. + /// + private void CreateWixFileSearchRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier id, string path, WixFileSearchAttributes attributes) + { + section.AddSymbol(new WixFileSearchSymbol(sourceLineNumbers, id) + { + Path = path, + Attributes = attributes, + }); + } + + /// + /// Parses a file share element. + /// + /// Element to parse. + /// Identifier of parent component. + /// Identifier of referred to directory. + private void ParseFileShareElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string directoryId) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + string description = null; + string name = null; + 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); + break; + case "Name": + name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Description": + description = 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("ufs", componentId, name); + } + + if (null == name) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); + } + + if (!element.Elements().Any()) + { + this.Messaging.Write(ErrorMessages.ExpectedElement(sourceLineNumbers, element.Name.LocalName, "FileSharePermission")); + } + + foreach (var child in element.Elements()) + { + if (this.Namespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "FileSharePermission": + this.ParseFileSharePermissionElement(intermediate, section, child, id); + break; + default: + this.ParseHelper.UnexpectedElement(element, child); + break; + } + } + else + { + this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child); + } + } + + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureSmbInstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureSmbUninstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + + if (!this.Messaging.EncounteredError) + { + section.AddSymbol(new FileShareSymbol(sourceLineNumbers, id) + { + ShareName = name, + ComponentRef = componentId, + Description = description, + DirectoryRef = directoryId, + }); + } + } + + /// + /// Parses a FileSharePermission element. + /// + /// Element to parse. + /// The identifier of the parent FileShare element. + private void ParseFileSharePermissionElement(Intermediate intermediate, IntermediateSection section, XElement element, Identifier fileShareId) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + var bits = new BitArray(32); + string user = null; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "User": + user = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, UtilSymbolDefinitions.User, user); + break; + default: + var attribValue = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); + if (!this.TrySetBitFromName(UtilConstants.StandardPermissions, attrib.Name.LocalName, attribValue, bits, 16)) + { + if (!this.TrySetBitFromName(UtilConstants.GenericPermissions, attrib.Name.LocalName, attribValue, bits, 28)) + { + if (!this.TrySetBitFromName(UtilConstants.FolderPermissions, attrib.Name.LocalName, attribValue, bits, 0)) + { + this.ParseHelper.UnexpectedAttribute(element, attrib); + break; + } + } + } + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + var permission = this.CreateIntegerFromBitArray(bits); + + if (null == user) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "User")); + } + + if (Int32.MinValue == permission) // just GENERIC_READ, which is MSI_NULL + { + this.Messaging.Write(ErrorMessages.GenericReadNotAllowed(sourceLineNumbers)); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + if (!this.Messaging.EncounteredError) + { + section.AddSymbol(new FileSharePermissionsSymbol(sourceLineNumbers) + { + FileShareRef = fileShareId.Id, + UserRef = user, + Permissions = permission, + }); + } + } + + /// + /// Parses a group element. + /// + /// Node to be parsed. + /// Component Id of the parent component of this element. + private void ParseGroupElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + Identifier id = null; + string domain = null; + string name = 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": + name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Domain": + domain = 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("ugr", componentId, domain, name); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + if (!this.Messaging.EncounteredError) + { + section.AddSymbol(new GroupSymbol(sourceLineNumbers, id) + { + ComponentRef = componentId, + Name = name, + Domain = domain, + }); + } + } + + /// + /// Parses a GroupRef element + /// + /// Element to parse. + /// Required user id to be joined to the group. + private void ParseGroupRefElement(Intermediate intermediate, IntermediateSection section, XElement element, string userId) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + string groupId = null; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + groupId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, UtilSymbolDefinitions.Group, groupId); + 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) + { + section.AddSymbol(new UserGroupSymbol(sourceLineNumbers) + { + UserRef = userId, + GroupRef = groupId, + }); + } + } + + /// + /// Parses an InternetShortcut element. + /// + /// Element to parse. + /// Identifier of parent component. + /// Default directory if none is specified on the InternetShortcut element. + private void ParseInternetShortcutElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string defaultTarget) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + Identifier id = null; + string name = null; + string target = null; + string directoryId = null; + string type = null; + string iconFile = null; + int iconIndex = 0; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Directory": + directoryId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + break; + case "Id": + id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); + break; + case "Name": + name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Target": + target = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Type": + type = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "IconFile": + iconFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "IconIndex": + iconIndex = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue); + break; + default: + this.ParseHelper.UnexpectedAttribute(element, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + // If there was no directoryId specified on the InternetShortcut element, default to the one on + // the parent component. + if (null == directoryId) + { + directoryId = defaultTarget; + } + + if (null == id) + { + id = this.ParseHelper.CreateIdentifier("uis", componentId, directoryId, name, target); + } + + // In theory this can never be the case, since InternetShortcut can only be under + // a component element, and if the Directory wasn't specified the default will come + // from the component. However, better safe than sorry, so here's a check to make sure + // it didn't wind up being null after setting it to the defaultTarget. + if (null == directoryId) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Directory")); + } + + if (null == name) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); + } + + if (null == target) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Target")); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + var shortcutType = InternetShortcutType.Link; + if (String.Equals(type, "url", StringComparison.OrdinalIgnoreCase)) + { + shortcutType = InternetShortcutType.Url; + } + + if (!this.Messaging.EncounteredError) + { + this.CreateWixInternetShortcut(section, sourceLineNumbers, componentId, directoryId, id, name, target, shortcutType, iconFile, iconIndex); + } + } + + /// + /// Creates the rows needed for WixInternetShortcut to work. + /// + /// The CompilerCore object used to create rows. + /// Source line information about the owner element. + /// Identifier of parent component. + /// Identifier of directory containing shortcut. + /// Identifier of shortcut. + /// Name of shortcut without extension. + /// Target URL of shortcut. + private void CreateWixInternetShortcut(IntermediateSection section, SourceLineNumber sourceLineNumbers, string componentId, string directoryId, Identifier shortcutId, string name, string target, InternetShortcutType type, string iconFile, int iconIndex) + { + // add the appropriate extension based on type of shortcut + name = String.Concat(name, InternetShortcutType.Url == type ? ".url" : ".lnk"); + + section.AddSymbol(new WixInternetShortcutSymbol(sourceLineNumbers, shortcutId) + { + ComponentRef = componentId, + DirectoryRef = directoryId, + Name = name, + Target = target, + Attributes = (int)type, + IconFile = iconFile, + IconIndex = iconIndex, + }); + + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedInternetShortcuts", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + + // make sure we have a CreateFolder table so that the immediate CA can add temporary rows to handle installation and uninstallation + this.ParseHelper.EnsureTable(section, sourceLineNumbers, "CreateFolder"); + + // use built-in MSI functionality to remove the shortcuts rather than doing so via CA + section.AddSymbol(new RemoveFileSymbol(sourceLineNumbers, shortcutId) + { + ComponentRef = componentId, + DirPropertyRef = directoryId, + OnUninstall = true, + FileName = name, + }); + } + + /// + /// Parses a performance category element. + /// + /// Element to parse. + /// Identifier of parent component. + private void ParsePerformanceCategoryElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + Identifier id = null; + string name = null; + string help = null; + var multiInstance = YesNoType.No; + int defaultLanguage = 0x09; // default to "english" + + var parsedPerformanceCounters = new List(); + + // default to managed performance counter + var library = "netfxperf.dll"; + var openEntryPoint = "OpenPerformanceData"; + var collectEntryPoint = "CollectPerformanceData"; + var closeEntryPoint = "ClosePerformanceData"; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Close": + closeEntryPoint = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Collect": + collectEntryPoint = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "DefaultLanguage": + defaultLanguage = this.GetPerformanceCounterLanguage(sourceLineNumbers, attrib); + break; + case "Help": + help = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Id": + id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); + break; + case "Library": + library = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "MultiInstance": + multiInstance = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "Name": + name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Open": + openEntryPoint = 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 && null == name) + { + this.Messaging.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, element.Name.LocalName, "Id", "Name")); + } + else if (null == id) + { + id = this.ParseHelper.CreateIdentifier("upc", componentId, name); + } + else if (null == name) + { + name = id.Id; + } + + // Process the child counter elements. + foreach (var child in element.Elements()) + { + if (this.Namespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "PerformanceCounter": + var counter = this.ParsePerformanceCounterElement(intermediate, section, child, defaultLanguage); + if (null != counter) + { + parsedPerformanceCounters.Add(counter); + } + break; + default: + this.ParseHelper.UnexpectedElement(element, child); + break; + } + } + else + { + this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child); + } + } + + + if (!this.Messaging.EncounteredError) + { + // Calculate the ini and h file content. + var objectName = "OBJECT_1"; + var objectLanguage = defaultLanguage.ToString("D3", CultureInfo.InvariantCulture); + + var sbIniData = new StringBuilder(); + sbIniData.AppendFormat("[info]\r\ndrivername={0}\r\nsymbolfile=wixperf.h\r\n\r\n[objects]\r\n{1}_{2}_NAME=\r\n\r\n[languages]\r\n{2}=LANG{2}\r\n\r\n", name, objectName, objectLanguage); + sbIniData.AppendFormat("[text]\r\n{0}_{1}_NAME={2}\r\n", objectName, objectLanguage, name); + if (null != help) + { + sbIniData.AppendFormat("{0}_{1}_HELP={2}\r\n", objectName, objectLanguage, help); + } + + int symbolConstantsCounter = 0; + var sbSymbolicConstants = new StringBuilder(); + sbSymbolicConstants.AppendFormat("#define {0} {1}\r\n", objectName, symbolConstantsCounter); + + var sbCounterNames = new StringBuilder("[~]"); + var sbCounterTypes = new StringBuilder("[~]"); + for (int i = 0; i < parsedPerformanceCounters.Count; ++i) + { + var counter = parsedPerformanceCounters[i]; + var counterName = String.Concat("DEVICE_COUNTER_", i + 1); + + sbIniData.AppendFormat("{0}_{1}_NAME={2}\r\n", counterName, counter.Language, counter.Name); + if (null != counter.Help) + { + sbIniData.AppendFormat("{0}_{1}_HELP={2}\r\n", counterName, counter.Language, counter.Help); + } + + symbolConstantsCounter += 2; + sbSymbolicConstants.AppendFormat("#define {0} {1}\r\n", counterName, symbolConstantsCounter); + + sbCounterNames.Append(UtilCompiler.FindPropertyBrackets.Replace(counter.Name, this.EscapeProperties)); + sbCounterNames.Append("[~]"); + sbCounterTypes.Append(counter.Type); + sbCounterTypes.Append("[~]"); + } + + sbSymbolicConstants.AppendFormat("#define LAST_{0}_COUNTER_OFFSET {1}\r\n", objectName, symbolConstantsCounter); + + // Add the calculated INI and H strings to the PerformanceCategory table. + section.AddSymbol(new PerformanceCategorySymbol(sourceLineNumbers, id) + { + ComponentRef = componentId, + Name = name, + IniData = sbIniData.ToString(), + ConstantData = sbSymbolicConstants.ToString(), + }); + + // Set up the application's performance key. + var escapedName = UtilCompiler.FindPropertyBrackets.Replace(name, this.EscapeProperties); + var linkageKey = String.Format(@"SYSTEM\CurrentControlSet\Services\{0}\Linkage", escapedName); + var performanceKey = String.Format(@"SYSTEM\CurrentControlSet\Services\{0}\Performance", escapedName); + + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, linkageKey, "Export", escapedName, componentId, false); + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "-", null, componentId, false); + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "Library", library, componentId, false); + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "Open", openEntryPoint, componentId, false); + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "Collect", collectEntryPoint, componentId, false); + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "Close", closeEntryPoint, componentId, false); + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "IsMultiInstance", YesNoType.Yes == multiInstance ? "#1" : "#0", componentId, false); + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "Counter Names", sbCounterNames.ToString(), componentId, false); + this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "Counter Types", sbCounterTypes.ToString(), componentId, false); + } + + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4InstallPerfCounterData", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4UninstallPerfCounterData", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + } + + /// + /// Gets the performance counter language as a decimal number. + /// + /// Source line information about the owner element. + /// The attribute containing the value to get. + /// Numeric representation of the language as per WinNT.h. + private int GetPerformanceCounterLanguage(SourceLineNumber sourceLineNumbers, XAttribute attribute) + { + int language = 0; + if (String.Empty == attribute.Value) + { + this.Messaging.Write(ErrorMessages.IllegalEmptyAttributeValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName)); + } + else + { + switch (attribute.Value) + { + case "afrikaans": + language = 0x36; + break; + case "albanian": + language = 0x1c; + break; + case "arabic": + language = 0x01; + break; + case "armenian": + language = 0x2b; + break; + case "assamese": + language = 0x4d; + break; + case "azeri": + language = 0x2c; + break; + case "basque": + language = 0x2d; + break; + case "belarusian": + language = 0x23; + break; + case "bengali": + language = 0x45; + break; + case "bulgarian": + language = 0x02; + break; + case "catalan": + language = 0x03; + break; + case "chinese": + language = 0x04; + break; + case "croatian": + language = 0x1a; + break; + case "czech": + language = 0x05; + break; + case "danish": + language = 0x06; + break; + case "divehi": + language = 0x65; + break; + case "dutch": + language = 0x13; + break; + case "piglatin": + case "english": + language = 0x09; + break; + case "estonian": + language = 0x25; + break; + case "faeroese": + language = 0x38; + break; + case "farsi": + language = 0x29; + break; + case "finnish": + language = 0x0b; + break; + case "french": + language = 0x0c; + break; + case "galician": + language = 0x56; + break; + case "georgian": + language = 0x37; + break; + case "german": + language = 0x07; + break; + case "greek": + language = 0x08; + break; + case "gujarati": + language = 0x47; + break; + case "hebrew": + language = 0x0d; + break; + case "hindi": + language = 0x39; + break; + case "hungarian": + language = 0x0e; + break; + case "icelandic": + language = 0x0f; + break; + case "indonesian": + language = 0x21; + break; + case "italian": + language = 0x10; + break; + case "japanese": + language = 0x11; + break; + case "kannada": + language = 0x4b; + break; + case "kashmiri": + language = 0x60; + break; + case "kazak": + language = 0x3f; + break; + case "konkani": + language = 0x57; + break; + case "korean": + language = 0x12; + break; + case "kyrgyz": + language = 0x40; + break; + case "latvian": + language = 0x26; + break; + case "lithuanian": + language = 0x27; + break; + case "macedonian": + language = 0x2f; + break; + case "malay": + language = 0x3e; + break; + case "malayalam": + language = 0x4c; + break; + case "manipuri": + language = 0x58; + break; + case "marathi": + language = 0x4e; + break; + case "mongolian": + language = 0x50; + break; + case "nepali": + language = 0x61; + break; + case "norwegian": + language = 0x14; + break; + case "oriya": + language = 0x48; + break; + case "polish": + language = 0x15; + break; + case "portuguese": + language = 0x16; + break; + case "punjabi": + language = 0x46; + break; + case "romanian": + language = 0x18; + break; + case "russian": + language = 0x19; + break; + case "sanskrit": + language = 0x4f; + break; + case "serbian": + language = 0x1a; + break; + case "sindhi": + language = 0x59; + break; + case "slovak": + language = 0x1b; + break; + case "slovenian": + language = 0x24; + break; + case "spanish": + language = 0x0a; + break; + case "swahili": + language = 0x41; + break; + case "swedish": + language = 0x1d; + break; + case "syriac": + language = 0x5a; + break; + case "tamil": + language = 0x49; + break; + case "tatar": + language = 0x44; + break; + case "telugu": + language = 0x4a; + break; + case "thai": + language = 0x1e; + break; + case "turkish": + language = 0x1f; + break; + case "ukrainian": + language = 0x22; + break; + case "urdu": + language = 0x20; + break; + case "uzbek": + language = 0x43; + break; + case "vietnamese": + language = 0x2a; + break; + default: + this.Messaging.Write(ErrorMessages.IllegalEmptyAttributeValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName)); + break; + } + } + + return language; + } + + /// + /// Parses a performance counter element. + /// + /// Element to parse. + /// Default language for the performance counter. + private ParsedPerformanceCounter ParsePerformanceCounterElement(Intermediate intermediate, IntermediateSection section, XElement element, int defaultLanguage) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + ParsedPerformanceCounter parsedPerformanceCounter = null; + string name = null; + string help = null; + var type = System.Diagnostics.PerformanceCounterType.NumberOfItems32; + int language = defaultLanguage; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Help": + help = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Name": + name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Type": + type = this.GetPerformanceCounterType(sourceLineNumbers, attrib); + break; + case "Language": + language = this.GetPerformanceCounterLanguage(sourceLineNumbers, attrib); + break; + default: + this.ParseHelper.UnexpectedAttribute(element, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + if (null == name) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); + } + + if (null == help) + { + this.Messaging.Write(UtilWarnings.RequiredAttributeForWindowsXP(sourceLineNumbers, element.Name.LocalName, "Help")); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + if (!this.Messaging.EncounteredError) + { + parsedPerformanceCounter = new ParsedPerformanceCounter(name, help, type, language); + } + + return parsedPerformanceCounter; + } + + /// + /// Gets the performance counter type. + /// + /// Source line information about the owner element. + /// The attribute containing the value to get. + /// Numeric representation of the language as per WinNT.h. + private System.Diagnostics.PerformanceCounterType GetPerformanceCounterType(SourceLineNumber sourceLineNumbers, XAttribute attribute) + { + var type = System.Diagnostics.PerformanceCounterType.NumberOfItems32; + if (String.Empty == attribute.Value) + { + this.Messaging.Write(ErrorMessages.IllegalEmptyAttributeValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName)); + } + else + { + switch (attribute.Value) + { + case "averageBase": + type = System.Diagnostics.PerformanceCounterType.AverageBase; + break; + case "averageCount64": + type = System.Diagnostics.PerformanceCounterType.AverageCount64; + break; + case "averageTimer32": + type = System.Diagnostics.PerformanceCounterType.AverageTimer32; + break; + case "counterDelta32": + type = System.Diagnostics.PerformanceCounterType.CounterDelta32; + break; + case "counterTimerInverse": + type = System.Diagnostics.PerformanceCounterType.CounterTimerInverse; + break; + case "sampleFraction": + type = System.Diagnostics.PerformanceCounterType.SampleFraction; + break; + case "timer100Ns": + type = System.Diagnostics.PerformanceCounterType.Timer100Ns; + break; + case "counterTimer": + type = System.Diagnostics.PerformanceCounterType.CounterTimer; + break; + case "rawFraction": + type = System.Diagnostics.PerformanceCounterType.RawFraction; + break; + case "timer100NsInverse": + type = System.Diagnostics.PerformanceCounterType.Timer100NsInverse; + break; + case "counterMultiTimer": + type = System.Diagnostics.PerformanceCounterType.CounterMultiTimer; + break; + case "counterMultiTimer100Ns": + type = System.Diagnostics.PerformanceCounterType.CounterMultiTimer100Ns; + break; + case "counterMultiTimerInverse": + type = System.Diagnostics.PerformanceCounterType.CounterMultiTimerInverse; + break; + case "counterMultiTimer100NsInverse": + type = System.Diagnostics.PerformanceCounterType.CounterMultiTimer100NsInverse; + break; + case "elapsedTime": + type = System.Diagnostics.PerformanceCounterType.ElapsedTime; + break; + case "sampleBase": + type = System.Diagnostics.PerformanceCounterType.SampleBase; + break; + case "rawBase": + type = System.Diagnostics.PerformanceCounterType.RawBase; + break; + case "counterMultiBase": + type = System.Diagnostics.PerformanceCounterType.CounterMultiBase; + break; + case "rateOfCountsPerSecond64": + type = System.Diagnostics.PerformanceCounterType.RateOfCountsPerSecond64; + break; + case "rateOfCountsPerSecond32": + type = System.Diagnostics.PerformanceCounterType.RateOfCountsPerSecond32; + break; + case "countPerTimeInterval64": + type = System.Diagnostics.PerformanceCounterType.CountPerTimeInterval64; + break; + case "countPerTimeInterval32": + type = System.Diagnostics.PerformanceCounterType.CountPerTimeInterval32; + break; + case "sampleCounter": + type = System.Diagnostics.PerformanceCounterType.SampleCounter; + break; + case "counterDelta64": + type = System.Diagnostics.PerformanceCounterType.CounterDelta64; + break; + case "numberOfItems64": + type = System.Diagnostics.PerformanceCounterType.NumberOfItems64; + break; + case "numberOfItems32": + type = System.Diagnostics.PerformanceCounterType.NumberOfItems32; + break; + case "numberOfItemsHEX64": + type = System.Diagnostics.PerformanceCounterType.NumberOfItemsHEX64; + break; + case "numberOfItemsHEX32": + type = System.Diagnostics.PerformanceCounterType.NumberOfItemsHEX32; + break; + default: + this.Messaging.Write(ErrorMessages.IllegalEmptyAttributeValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName)); + break; + } + } + + return type; + } + + /// + /// Parses a perf counter element. + /// + /// Element to parse. + /// Identifier of parent component. + /// Identifier of referenced file. + private void ParsePerfCounterElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string fileId) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + string name = null; + + this.Messaging.Write(UtilWarnings.DeprecatedPerfCounterElement(sourceLineNumbers)); + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Name": + name = 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 == name) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + if (!this.Messaging.EncounteredError) + { + section.AddSymbol(new PerfmonSymbol(sourceLineNumbers) + { + ComponentRef = componentId, + File = $"[#{fileId}]", + Name = name, + }); + } + + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigurePerfmonInstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigurePerfmonUninstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + } + + + /// + /// Parses a perf manifest element. + /// + /// Element to parse. + /// Identifier of parent component. + /// Identifier of referenced file. + private void ParsePerfCounterManifestElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string fileId) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + string resourceFileDirectory = null; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "ResourceFileDirectory": + resourceFileDirectory = 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) + { + section.AddSymbol(new PerfmonManifestSymbol(sourceLineNumbers) + { + ComponentRef = componentId, + File = $"[#{fileId}]", + ResourceFileDirectory = resourceFileDirectory, + }); + } + + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigurePerfmonManifestRegister", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigurePerfmonManifestUnregister", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + } + + /// + /// Parses a format files element. + /// + /// Element to parse. + /// Identifier of referenced file. + /// Flag to determine whether the component is 64-bit. + private void ParseFormatFileElement(Intermediate intermediate, IntermediateSection section, XElement element, string fileId, bool win64) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + string binaryId = null; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "BinaryRef": + binaryId = 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 (null == binaryId) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "BinaryRef")); + } + + if (!this.Messaging.EncounteredError) + { + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedFormatFiles", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + + section.AddSymbol(new WixFormatFilesSymbol(sourceLineNumbers) + { + BinaryRef = binaryId, + FileRef = fileId, + }); + + this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Binary, binaryId); + } + } + + /// + /// Parses a event manifest element. + /// + /// Element to parse. + /// Identifier of parent component. + /// Identifier of referenced file. + private void ParseEventManifestElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string fileId) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + string messageFile = null; + string resourceFile = null; + string parameterFile = null; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "MessageFile": + messageFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "ResourceFile": + resourceFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "ParameterFile": + parameterFile = 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) + { + section.AddSymbol(new EventManifestSymbol(sourceLineNumbers) + { + ComponentRef = componentId, + File = $"[#{fileId}]", + }); + + if (null != messageFile) + { + section.AddSymbol(new XmlFileSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, $"Config_{fileId}MessageFile")) + { + File = $"[#{fileId}]", + ElementPath = "/*/*/*/*[\\[]@messageFileName[\\]]", + Name = "messageFileName", + Value = messageFile, + Flags = 4 | 0x00001000, //bulk write | preserve modified date + ComponentRef = componentId, + }); + } + if (null != parameterFile) + { + section.AddSymbol(new XmlFileSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, $"Config_{fileId}ParameterFile")) + { + File = $"[#{fileId}]", + ElementPath = "/*/*/*/*[\\[]@parameterFileName[\\]]", + Name = "parameterFileName", + Value = parameterFile, + Flags = 4 | 0x00001000, //bulk write | preserve modified date + ComponentRef = componentId, + }); + } + if (null != resourceFile) + { + section.AddSymbol(new XmlFileSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, $"Config_{fileId}ResourceFile")) + { + File = $"[#{fileId}]", + ElementPath = "/*/*/*/*[\\[]@resourceFileName[\\]]", + Name = "resourceFileName", + Value = resourceFile, + Flags = 4 | 0x00001000, //bulk write | preserve modified date + ComponentRef = componentId, + }); + } + + } + + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureEventManifestRegister", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureEventManifestUnregister", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + + if (null != messageFile || null != parameterFile || null != resourceFile) + { + this.AddReferenceToSchedXmlFile(sourceLineNumbers, section); + } + } + + /// + /// Parses a PermissionEx element. + /// + /// Element to parse. + /// Identifier of object to be secured. + /// Identifier of component, used to determine install state. + /// Flag to determine whether the component is 64-bit. + /// Name of table that contains objectId. + private void ParsePermissionExElement(Intermediate intermediate, IntermediateSection section, XElement element, string objectId, string componentId, bool win64, string tableName) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + var bits = new BitArray(32); + string domain = null; + string[] specialPermissions = null; + string user = null; + var attributes = WixPermissionExAttributes.Inheritable; // default to inheritable. + + var permissionType = PermissionType.SecureObjects; + + switch (tableName) + { + case "CreateFolder": + specialPermissions = UtilConstants.FolderPermissions; + break; + case "File": + specialPermissions = UtilConstants.FilePermissions; + break; + case "Registry": + specialPermissions = UtilConstants.RegistryPermissions; + if (String.IsNullOrEmpty(objectId)) + { + this.Messaging.Write(UtilErrors.InvalidRegistryObject(sourceLineNumbers, element.Parent.Name.LocalName)); + } + break; + case "ServiceInstall": + specialPermissions = UtilConstants.ServicePermissions; + permissionType = PermissionType.SecureObjects; + break; + default: + this.ParseHelper.UnexpectedElement(element.Parent, element); + break; + } + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Domain": + if (PermissionType.FileSharePermissions == permissionType) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, element.Parent.Name.LocalName)); + } + domain = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Inheritable": + if (this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib) == YesNoType.No) + { + attributes &= ~WixPermissionExAttributes.Inheritable; + } + break; + case "User": + user = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + default: + var attribValue = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); + if (!this.TrySetBitFromName(UtilConstants.StandardPermissions, attrib.Name.LocalName, attribValue, bits, 16)) + { + if (!this.TrySetBitFromName(UtilConstants.GenericPermissions, attrib.Name.LocalName, attribValue, bits, 28)) + { + if (!this.TrySetBitFromName(specialPermissions, attrib.Name.LocalName, attribValue, bits, 0)) + { + this.ParseHelper.UnexpectedAttribute(element, attrib); + break; + } + } + } + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + var permission = this.CreateIntegerFromBitArray(bits); + + if (null == user) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "User")); + } + + if (Int32.MinValue == permission) // just GENERIC_READ, which is MSI_NULL + { + this.Messaging.Write(ErrorMessages.GenericReadNotAllowed(sourceLineNumbers)); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + if (!this.Messaging.EncounteredError) + { + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedSecureObjects", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + + var id = this.ParseHelper.CreateIdentifier("sec", objectId, tableName, domain, user); + section.AddSymbol(new SecureObjectsSymbol(sourceLineNumbers, id) + { + SecureObject = objectId, + Table = tableName, + Domain = domain, + User = user, + Attributes = attributes, + Permission = permission, + ComponentRef = componentId, + }); + } + } + + /// + /// Parses a ProductSearch element. + /// + /// Element to parse. + private void ParseProductSearchElement(Intermediate intermediate, IntermediateSection section, XElement element) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + Identifier id = null; + string variable = null; + string condition = null; + string after = null; + string productCode = null; + string upgradeCode = null; + var attributes = WixProductSearchAttributes.Version; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + case "Variable": + case "Condition": + case "After": + this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after); + break; + case "ProductCode": + productCode = this.ParseHelper.GetAttributeGuidValue(sourceLineNumbers, attrib, false); + break; + case "UpgradeCode": + upgradeCode = this.ParseHelper.GetAttributeGuidValue(sourceLineNumbers, attrib, false); + break; + case "Result": + var result = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + switch (result) + { + case "version": + attributes = WixProductSearchAttributes.Version; + break; + case "language": + attributes = WixProductSearchAttributes.Language; + break; + case "state": + attributes = WixProductSearchAttributes.State; + break; + case "assignment": + attributes = WixProductSearchAttributes.Assignment; + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Parent.Name.LocalName, attrib.Name.LocalName, result, "version", "language", "state", "assignment")); + break; + } + break; + default: + this.ParseHelper.UnexpectedAttribute(element, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + if (null == upgradeCode && null == productCode) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "ProductCode", "UpgradeCode", true)); + } + + if (null != upgradeCode && null != productCode) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "UpgradeCode", "ProductCode")); + } + + if (null == id) + { + id = this.ParseHelper.CreateIdentifier("wps", variable, condition, after, (productCode == null ? upgradeCode : productCode), attributes.ToString()); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, null); + + if (!this.Messaging.EncounteredError) + { + // set an additional flag if this is an upgrade code + if (null != upgradeCode) + { + attributes |= WixProductSearchAttributes.UpgradeCode; + } + + section.AddSymbol(new WixProductSearchSymbol(sourceLineNumbers, id) + { + Guid = productCode ?? upgradeCode, + Attributes = attributes, + }); + } + } + + /// + /// Parses a RegistrySearch element. + /// + /// Element to parse. + private void ParseRegistrySearchElement(Intermediate intermediate, IntermediateSection section, XElement element) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + Identifier id = null; + string variable = null; + string condition = null; + string after = null; + RegistryRootType? root = null; + string key = null; + string value = null; + var expand = YesNoType.NotSet; + var win64 = this.Context.IsCurrentPlatform64Bit; + var attributes = WixRegistrySearchAttributes.Raw | WixRegistrySearchAttributes.WantValue; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + case "Variable": + case "Condition": + case "After": + this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after); + break; + case "Bitness": + var bitnessValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + switch (bitnessValue) + { + case "always32": + win64 = false; + break; + case "always64": + win64 = true; + break; + case "default": + case "": + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Name.LocalName, attrib.Name.LocalName, bitnessValue, "default", "always32", "always64")); + break; + } + break; + case "Root": + root = this.ParseHelper.GetAttributeRegistryRootValue(sourceLineNumbers, attrib, false); + break; + case "Key": + key = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Value": + value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "ExpandEnvironmentVariables": + expand = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "Format": + string format = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + switch (format) + { + case "raw": + attributes |= WixRegistrySearchAttributes.Raw; + break; + case "compatible": + attributes |= WixRegistrySearchAttributes.Compatible; + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Parent.Name.LocalName, attrib.Name.LocalName, format, "raw", "compatible")); + break; + } + break; + case "Result": + var result = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + switch (result) + { + case "exists": + attributes |= WixRegistrySearchAttributes.WantExists; + break; + case "value": + attributes |= WixRegistrySearchAttributes.WantValue; + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Parent.Name.LocalName, attrib.Name.LocalName, result, "exists", "value")); + break; + } + break; + default: + this.ParseHelper.UnexpectedAttribute(element, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + if (!root.HasValue) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Root")); + } + + if (null == key) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Key")); + } + + if (null == id) + { + id = this.ParseHelper.CreateIdentifier("wrs", variable, condition, after, root.ToString(), key, value, attributes.ToString()); + } + + if (expand == YesNoType.Yes) + { + if (0 != (attributes & WixRegistrySearchAttributes.WantExists)) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeValueWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "ExpandEnvironmentVariables", expand.ToString(), "Result", "exists")); + } + + attributes |= WixRegistrySearchAttributes.ExpandEnvironmentVariables; + } + + if (win64) + { + attributes |= WixRegistrySearchAttributes.Win64; + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, null); + + if (!this.Messaging.EncounteredError) + { + section.AddSymbol(new WixRegistrySearchSymbol(sourceLineNumbers, id) + { + Root = root.Value, + Key = key, + Value = value, + Attributes = attributes, + }); + } + } + + /// + /// Parses a RemoveFolderEx element. + /// + /// Element to parse. + /// Identifier of parent component. + private void ParseRemoveFolderExElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + Identifier id = null; + var mode = WixRemoveFolderExInstallMode.Uninstall; + string property = null; + string condition = null; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Condition": + condition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Id": + id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); + break; + case "On": + var onValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + if (onValue.Length == 0) + { + } + else + { + switch (onValue) + { + case "install": + mode = WixRemoveFolderExInstallMode.Install; + break; + case "uninstall": + mode = WixRemoveFolderExInstallMode.Uninstall; + break; + case "both": + mode = WixRemoveFolderExInstallMode.Both; + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "On", onValue, "install", "uninstall", "both")); + break; + } + } + break; + case "Property": + property = 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 (String.IsNullOrEmpty(property)) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Property")); + } + + if (id == null) + { + id = this.ParseHelper.CreateIdentifier("wrf", componentId, property, mode.ToString()); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + if (!this.Messaging.EncounteredError) + { + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4RemoveFoldersEx", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + + section.AddSymbol(new WixRemoveFolderExSymbol(sourceLineNumbers, id) + { + ComponentRef = componentId, + Property = property, + InstallMode = mode, + Condition = condition + }); + + this.ParseHelper.EnsureTable(section, sourceLineNumbers, "RemoveFile"); + } + } + + /// + /// Parses a RemoveRegistryKeyEx element. + /// + /// Element to parse. + /// Identifier of parent component. + private void ParseRemoveRegistryKeyExElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + Identifier id = null; + var mode = WixRemoveRegistryKeyExInstallMode.Uninstall; + string condition = null; + RegistryRootType? root = null; + string key = null; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Condition": + condition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Id": + id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); + break; + case "On": + var actionValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + switch (actionValue) + { + case "": + break; + case "install": + mode = WixRemoveRegistryKeyExInstallMode.Install; + break; + case "uninstall": + mode = WixRemoveRegistryKeyExInstallMode.Uninstall; + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "On", actionValue, "install", "uninstall")); + break; + } + break; + case "Root": + root = this.ParseHelper.GetAttributeRegistryRootValue(sourceLineNumbers, attrib, false); + break; + case "Key": + key = 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 (!root.HasValue) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Root")); + } + + if (key == null) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Key")); + } + + if (id == null) + { + id = this.ParseHelper.CreateIdentifier("rrx", componentId, condition, root.ToString(), key, mode.ToString()); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + if (!this.Messaging.EncounteredError) + { + this.ParseHelper.EnsureTable(section, sourceLineNumbers, "Registry"); + this.ParseHelper.EnsureTable(section, sourceLineNumbers, "RemoveRegistry"); + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4RemoveRegistryKeysEx", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + + section.AddSymbol(new WixRemoveRegistryKeyExSymbol(sourceLineNumbers, id) + { + ComponentRef = componentId, + Root = root.Value, + Key = key, + InstallMode = mode, + Condition = condition + }); + } + } + + /// + /// Parses a RestartResource element. + /// + /// The element to parse. + /// The identity of the parent component. + private void ParseRestartResourceElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + Identifier id = null; + string resource = null; + WixRestartResourceAttributes? attributes = 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 "Path": + resource = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + attributes = WixRestartResourceAttributes.Filename; + break; + + case "ProcessName": + resource = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + attributes = WixRestartResourceAttributes.ProcessName; + break; + + case "ServiceName": + resource = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + attributes = WixRestartResourceAttributes.ServiceName; + break; + + default: + this.ParseHelper.UnexpectedAttribute(element, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + // Validate the attribute. + if (id == null) + { + id = this.ParseHelper.CreateIdentifier("wrr", componentId, resource, attributes.ToString()); + } + + if (!attributes.HasValue) + { + this.Messaging.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, element.Name.LocalName, "Path", "ProcessName", "ServiceName")); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + if (!this.Messaging.EncounteredError) + { + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4RegisterRestartResources", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + + section.AddSymbol(new WixRestartResourceSymbol(sourceLineNumbers, id) + { + ComponentRef = componentId, + Resource = resource, + Attributes = attributes, + }); + } + } + + /// + /// Parses a service configuration element. + /// + /// Element to parse. + /// Identifier of parent component. + /// Name of parent element. + /// Optional name of service + private void ParseServiceConfigElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string parentTableName, string parentTableServiceName) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + string firstFailureActionType = null; + var newService = false; + string programCommandLine = null; + string rebootMessage = null; + var resetPeriod = CompilerConstants.IntegerNotSet; + var restartServiceDelay = CompilerConstants.IntegerNotSet; + string secondFailureActionType = null; + string serviceName = null; + string thirdFailureActionType = null; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "FirstFailureActionType": + firstFailureActionType = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "ProgramCommandLine": + programCommandLine = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "RebootMessage": + rebootMessage = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "ResetPeriodInDays": + resetPeriod = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue); + break; + case "RestartServiceDelayInSeconds": + restartServiceDelay = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue); + break; + case "SecondFailureActionType": + secondFailureActionType = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "ServiceName": + serviceName = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "ThirdFailureActionType": + thirdFailureActionType = 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 this element is a child of ServiceInstall then ignore the service name provided. + if ("ServiceInstall" == parentTableName) + { + // TODO: the ServiceName attribute should not be allowed in this case (the overwriting behavior may confuse users) + serviceName = parentTableServiceName; + newService = true; + } + else + { + // not a child of ServiceInstall, so ServiceName must have been provided + if (null == serviceName) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "ServiceName")); + } + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + if (!this.Messaging.EncounteredError) + { + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedServiceConfig", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + + section.AddSymbol(new ServiceConfigSymbol(sourceLineNumbers) + { + ServiceName = serviceName, + ComponentRef = componentId, + NewService = newService ? 1 : 0, + FirstFailureActionType = firstFailureActionType, + SecondFailureActionType = secondFailureActionType, + ThirdFailureActionType = thirdFailureActionType, + ResetPeriodInDays = resetPeriod, + RestartServiceDelayInSeconds = restartServiceDelay, + ProgramCommandLine = programCommandLine, + RebootMessage = rebootMessage, + }); + } + } + + /// + /// Parses a touch file element. + /// + /// Element to parse. + /// Identifier of parent component. + /// Indicates whether the path is a 64-bit path. + private void ParseTouchFileElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, bool win64) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + Identifier id = null; + string path = null; + var onInstall = YesNoType.NotSet; + var onReinstall = YesNoType.NotSet; + var onUninstall = YesNoType.NotSet; + var nonvital = YesNoType.NotSet; + int attributes = 0; + + 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 "Path": + path = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "OnInstall": + onInstall = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "OnReinstall": + onReinstall = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "OnUninstall": + onUninstall = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "Nonvital": + nonvital = 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 == path) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Path")); + } + + // If none of the scheduling actions are set, default to touching on install and reinstall. + if (YesNoType.NotSet == onInstall && YesNoType.NotSet == onReinstall && YesNoType.NotSet == onUninstall) + { + onInstall = YesNoType.Yes; + onReinstall = YesNoType.Yes; + } + + attributes |= YesNoType.Yes == onInstall ? 0x1 : 0; + attributes |= YesNoType.Yes == onReinstall ? 0x2 : 0; + attributes |= YesNoType.Yes == onUninstall ? 0x4 : 0; + attributes |= win64 ? 0x10 : 0; + attributes |= YesNoType.Yes == nonvital ? 0 : 0x20; + + if (null == id) + { + id = this.ParseHelper.CreateIdentifier("tf", path, attributes.ToString()); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + if (!this.Messaging.EncounteredError) + { + section.AddSymbol(new WixTouchFileSymbol(sourceLineNumbers, id) + { + ComponentRef = componentId, + Path = path, + Attributes = attributes, + }); + + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4TouchFileDuringInstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + } + } + + /// + /// Parses an user element. + /// + /// Element to parse. + /// Optional identifier of parent component. + private void ParseUserElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + Identifier id = null; + int attributes = 0; + string domain = null; + string name = null; + string password = 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 "CanNotChangePassword": + if (null == componentId) + { + this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); + } + + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= UserPasswdCantChange; + } + break; + case "CreateUser": + if (null == componentId) + { + this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); + } + + if (YesNoType.No == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= UserDontCreateUser; + } + break; + case "Disabled": + if (null == componentId) + { + this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); + } + + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= UserDisableAccount; + } + break; + case "Domain": + domain = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "FailIfExists": + if (null == componentId) + { + this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); + } + + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= UserFailIfExists; + } + break; + case "LogonAsService": + if (null == componentId) + { + this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); + } + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= UserLogonAsService; + } + break; + case "LogonAsBatchJob": + if (null == componentId) + { + this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); + } + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= UserLogonAsBatchJob; + } + break; + case "Name": + name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Password": + password = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "PasswordExpired": + if (null == componentId) + { + this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); + } + + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= UserPasswdChangeReqdOnLogin; + } + break; + case "PasswordNeverExpires": + if (null == componentId) + { + this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); + } + + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= UserDontExpirePasswrd; + } + break; + case "RemoveOnUninstall": + if (null == componentId) + { + this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); + } + + if (YesNoType.No == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= UserDontRemoveOnUninstall; + } + break; + case "UpdateIfExists": + if (null == componentId) + { + this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); + } + + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= UserUpdateIfExists; + } + break; + case "Vital": + if (null == componentId) + { + this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); + } + + if (YesNoType.No == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= UserNonVital; + } + 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("usr", componentId, name); + } + + if (null == name) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); + } + + foreach (var child in element.Elements()) + { + if (this.Namespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "GroupRef": + if (null == componentId) + { + var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child); + this.Messaging.Write(UtilErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); + } + + this.ParseGroupRefElement(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 (null != componentId) + { + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureUsers", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + } + + if (!this.Messaging.EncounteredError) + { + section.AddSymbol(new UserSymbol(sourceLineNumbers, id) + { + ComponentRef = componentId, + Name = name, + Domain = domain, + Password = password, + Attributes = attributes, + }); + } + } + + /// + /// Parses a XmlFile element. + /// + /// Element to parse. + /// Identifier of parent component. + private void ParseXmlFileElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + Identifier id = null; + string file = null; + string elementPath = null; + string name = null; + string value = null; + int sequence = -1; + int flags = 0; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Action": + var actionValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + switch (actionValue) + { + case "createElement": + flags |= 0x00000001; // XMLFILE_CREATE_ELEMENT + break; + case "deleteValue": + flags |= 0x00000002; // XMLFILE_DELETE_VALUE + break; + case "bulkSetValue": + flags |= 0x00000004; // XMLFILE_BULKWRITE_VALUE + break; + case "setValue": + // no flag for set value since it's the default + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Action", actionValue, "createElement", "deleteValue", "setValue", "bulkSetValue")); + break; + } + break; + case "SelectionLanguage": + string selectionLanguage = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + switch (selectionLanguage) + { + case "XPath": + flags |= 0x00000100; // XMLFILE_USE_XPATH + break; + case "XSLPattern": + // no flag for since it's the default + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "SelectionLanguage", selectionLanguage, "XPath", "XSLPattern")); + break; + } + break; + case "Id": + id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); + break; + case "File": + file = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "ElementPath": + elementPath = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Name": + name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Permanent": + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + flags |= 0x00010000; // XMLFILE_DONT_UNINSTALL + } + break; + case "Sequence": + sequence = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, Int16.MaxValue); + break; + case "Value": + value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "PreserveModifiedDate": + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + flags |= 0x00001000; // XMLFILE_PRESERVE_MODIFIED + } + 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("uxf", componentId, file, elementPath, name); + } + + if (null == file) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "File")); + } + + if (null == elementPath) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "ElementPath")); + } + + if ((0x00000001 /*XMLFILE_CREATE_ELEMENT*/ & flags) != 0 && null == name) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeWithoutOtherAttributes(sourceLineNumbers, element.Name.LocalName, "Action", "Name")); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + if (!this.Messaging.EncounteredError) + { + var symbol = section.AddSymbol(new XmlFileSymbol(sourceLineNumbers, id) + { + File = file, + ElementPath = elementPath, + Name = name, + Value = value, + Flags = flags, + ComponentRef = componentId, + }); + if (-1 != sequence) + { + symbol.Sequence = sequence; + } + } + + this.AddReferenceToSchedXmlFile(sourceLineNumbers, section); + } + + /// + /// Parses a XmlConfig element. + /// + /// Element to parse. + /// Identifier of parent component. + /// Whether or not the element is nested. + private void ParseXmlConfigElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, bool nested) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + Identifier id = null; + string elementId = null; + string elementPath = null; + int flags = 0; + string file = null; + string name = null; + var sequence = CompilerConstants.IntegerNotSet; + string value = null; + string verifyPath = 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 "Action": + if (nested) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, element.Parent.Name.LocalName)); + } + else + { + string actionValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + switch (actionValue) + { + case "create": + flags |= 0x10; // XMLCONFIG_CREATE + break; + case "delete": + flags |= 0x20; // XMLCONFIG_DELETE + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, actionValue, "create", "delete")); + break; + } + } + break; + case "ElementId": + elementId = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "ElementPath": + elementPath = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "File": + file = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Name": + name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Node": + if (nested) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, element.Parent.Name.LocalName)); + } + else + { + var nodeValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + switch (nodeValue) + { + case "element": + flags |= 0x1; // XMLCONFIG_ELEMENT + break; + case "value": + flags |= 0x2; // XMLCONFIG_VALUE + break; + case "document": + flags |= 0x4; // XMLCONFIG_DOCUMENT + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, nodeValue, "element", "value", "document")); + break; + } + } + break; + case "On": + if (nested) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, element.Parent.Name.LocalName)); + } + else + { + var onValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + switch (onValue) + { + case "install": + flags |= 0x100; // XMLCONFIG_INSTALL + break; + case "uninstall": + flags |= 0x200; // XMLCONFIG_UNINSTALL + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, onValue, "install", "uninstall")); + break; + } + } + break; + case "PreserveModifiedDate": + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + flags |= 0x00001000; // XMLCONFIG_PRESERVE_MODIFIED + } + break; + case "Sequence": + sequence = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, Int16.MaxValue); + break; + case "Value": + value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "VerifyPath": + verifyPath = 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("uxc", componentId, file, elementId, elementPath); + } + + if (null == file) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "File")); + } + + if (null == elementId && null == elementPath) + { + this.Messaging.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, element.Name.LocalName, "ElementId", "ElementPath")); + } + else if (null != elementId) + { + if (null != elementPath) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "ElementId", "ElementPath")); + } + + if (0 != flags) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, "ElementId", "Action", "Node", "On")); + } + + this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, UtilSymbolDefinitions.XmlConfig, elementId); + } + + // find unexpected child elements + foreach (var child in element.Elements()) + { + if (this.Namespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "XmlConfig": + if (nested) + { + this.Messaging.Write(ErrorMessages.UnexpectedElement(sourceLineNumbers, element.Name.LocalName, child.Name.LocalName)); + } + else + { + this.ParseXmlConfigElement(intermediate, section, child, componentId, true); + } + 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 XmlConfigSymbol(sourceLineNumbers, id) + { + File = file, + ElementId = elementId, + ElementPath = elementPath, + VerifyPath = verifyPath, + Name = name, + Value = value, + Flags = flags, + ComponentRef = componentId, + }); + + if (CompilerConstants.IntegerNotSet != sequence) + { + symbol.Sequence = sequence; + } + } + + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedXmlConfig", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + } + + /// + /// Match evaluator to escape properties in a string. + /// + private string EscapeProperties(Match match) + { + string escape = null; + switch (match.Value) + { + case "[": + escape = @"[\[]"; + break; + case "]": + escape = @"[\]]"; + break; + } + + return escape; + } + + private int CreateIntegerFromBitArray(BitArray bits) + { + if (32 != bits.Length) + { + throw new ArgumentException(String.Format("Can only convert a bit array with 32-bits to integer. Actual number of bits in array: {0}", bits.Length), "bits"); + } + + var intArray = new int[1]; + bits.CopyTo(intArray, 0); + + return intArray[0]; + } + + private bool TrySetBitFromName(string[] attributeNames, string attributeName, YesNoType attributeValue, BitArray bits, int offset) + { + for (var i = 0; i < attributeNames.Length; i++) + { + if (attributeName.Equals(attributeNames[i], StringComparison.Ordinal)) + { + bits.Set(i + offset, YesNoType.Yes == attributeValue); + return true; + } + } + + return false; + } + + private void AddReferenceToSchedXmlFile(SourceLineNumber sourceLineNumbers, IntermediateSection section) + { + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedXmlFile", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + } + + /// + /// Private class that stores the data from a parsed PerformanceCounter element. + /// + private class ParsedPerformanceCounter + { + internal ParsedPerformanceCounter(string name, string help, System.Diagnostics.PerformanceCounterType type, int language) + { + this.Name = name; + this.Help = help; + this.Type = (int)type; + this.Language = language.ToString("D3", CultureInfo.InvariantCulture); + } + + internal string Name { get; } + + internal string Help { get; } + + internal int Type { get; } + + internal string Language { get; } + } + } +} diff --git a/src/ext/Util/wixext/UtilConstants.cs b/src/ext/Util/wixext/UtilConstants.cs new file mode 100644 index 00000000..28ff368f --- /dev/null +++ b/src/ext/Util/wixext/UtilConstants.cs @@ -0,0 +1,17 @@ +// Copyright (c) .NET 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.Util +{ + /// + /// Constants used by Utility Extension. + /// + internal static class UtilConstants + { + internal static readonly string[] FilePermissions = { "Read", "Write", "Append", "ReadExtendedAttributes", "WriteExtendedAttributes", "Execute", null, "ReadAttributes", "WriteAttributes" }; + internal static readonly string[] FolderPermissions = { "Read", "CreateFile", "CreateChild", "ReadExtendedAttributes", "WriteExtendedAttributes", "Traverse", "DeleteChild", "ReadAttributes", "WriteAttributes" }; + internal static readonly string[] GenericPermissions = { "GenericAll", "GenericExecute", "GenericWrite", "GenericRead" }; + internal static readonly string[] RegistryPermissions = { "Read", "Write", "CreateSubkeys", "EnumerateSubkeys", "Notify", "CreateLink" }; + internal static readonly string[] ServicePermissions = { "ServiceQueryConfig", "ServiceChangeConfig", "ServiceQueryStatus", "ServiceEnumerateDependents", "ServiceStart", "ServiceStop", "ServicePauseContinue", "ServiceInterrogate", "ServiceUserDefinedControl" }; + internal static readonly string[] StandardPermissions = { "Delete", "ReadPermission", "ChangePermission", "TakeOwnership", "Synchronize" }; + } +} diff --git a/src/ext/Util/wixext/UtilDecompiler.cs b/src/ext/Util/wixext/UtilDecompiler.cs new file mode 100644 index 00000000..9ef3390f --- /dev/null +++ b/src/ext/Util/wixext/UtilDecompiler.cs @@ -0,0 +1,1543 @@ +// Copyright (c) .NET 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.Extensions +{ +#if TODO_CONSIDER_DECOMPILER + using System; + using System.IO; + using System.Text; + using System.Collections; + using System.Diagnostics; + using System.Globalization; + + using Util = WixToolset.Extensions.Serialize.Util; + using WixToolset.Data; + using WixToolset.Extensibility; + using Wix = WixToolset.Data.Serialize; + + /// + /// The decompiler for the WiX Toolset Utility Extension. + /// + public sealed class UtilDecompiler : DecompilerExtension + { + /// + /// Creates a decompiler for Utility Extension. + /// + public UtilDecompiler() + { + this.TableDefinitions = UtilExtensionData.GetExtensionTableDefinitions(); + } + + /// + /// Get the extensions library to be removed. + /// + /// Table definitions for library. + /// Library to remove from decompiled output. + public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions) + { + return UtilExtensionData.GetExtensionLibrary(tableDefinitions); + } + + /// + /// Called at the beginning of the decompilation of a database. + /// + /// The collection of all tables. + public override void Initialize(TableIndexedCollection tables) + { + this.CleanupSecureCustomProperties(tables); + this.CleanupInternetShortcutRemoveFileTables(tables); + } + + /// + /// Decompile the SecureCustomProperties field to PropertyRefs for known extension properties. + /// + /// + /// If we've referenced any of the suite or directory properties, add + /// a PropertyRef to refer to the Property (and associated custom action) + /// from the extension's library. Then remove the property from + /// SecureCustomExtensions property so later decompilation won't create + /// new Property elements. + /// + /// The collection of all tables. + private void CleanupSecureCustomProperties(TableIndexedCollection tables) + { + Table propertyTable = tables["Property"]; + + if (null != propertyTable) + { + foreach (Row row in propertyTable.Rows) + { + if ("SecureCustomProperties" == row[0].ToString()) + { + StringBuilder remainingProperties = new StringBuilder(); + string[] secureCustomProperties = row[1].ToString().Split(';'); + foreach (string property in secureCustomProperties) + { + if (property.StartsWith("WIX_SUITE_", StringComparison.Ordinal) || property.StartsWith("WIX_DIR_", StringComparison.Ordinal) + || property.StartsWith("WIX_ACCOUNT_", StringComparison.Ordinal)) + { + Wix.PropertyRef propertyRef = new Wix.PropertyRef(); + propertyRef.Id = property; + this.Core.RootElement.AddChild(propertyRef); + } + else + { + if (0 < remainingProperties.Length) + { + remainingProperties.Append(";"); + } + remainingProperties.Append(property); + } + } + + row[1] = remainingProperties.ToString(); + break; + } + } + } + } + + /// + /// Remove RemoveFile rows that the InternetShortcut compiler extension adds for us. + /// + /// The collection of all tables. + private void CleanupInternetShortcutRemoveFileTables(TableIndexedCollection tables) + { + // index the WixInternetShortcut table + Table wixInternetShortcutTable = tables["WixInternetShortcut"]; + Hashtable wixInternetShortcuts = new Hashtable(); + if (null != wixInternetShortcutTable) + { + foreach (Row row in wixInternetShortcutTable.Rows) + { + wixInternetShortcuts.Add(row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), row); + } + } + + // remove the RemoveFile rows with primary keys that match the WixInternetShortcut table's + Table removeFileTable = tables["RemoveFile"]; + if (null != removeFileTable) + { + for (int i = removeFileTable.Rows.Count - 1; 0 <= i; i--) + { + if (null != wixInternetShortcuts[removeFileTable.Rows[i][0]]) + { + removeFileTable.Rows.RemoveAt(i); + } + } + } + } + + /// + /// Decompiles an extension table. + /// + /// The table to decompile. + public override void DecompileTable(Table table) + { + switch (table.Name) + { + case "WixCloseApplication": + this.DecompileWixCloseApplicationTable(table); + break; + case "WixRemoveFolderEx": + this.DecompileWixRemoveFolderExTable(table); + break; + case "WixRestartResource": + this.DecompileWixRestartResourceTable(table); + break; + case "FileShare": + this.DecompileFileShareTable(table); + break; + case "FileSharePermissions": + this.DecompileFileSharePermissionsTable(table); + break; + case "WixInternetShortcut": + this.DecompileWixInternetShortcutTable(table); + break; + case "Group": + this.DecompileGroupTable(table); + break; + case "Perfmon": + this.DecompilePerfmonTable(table); + break; + case "PerfmonManifest": + this.DecompilePerfmonManifestTable(table); + break; + case "EventManifest": + this.DecompileEventManifestTable(table); + break; + case "SecureObjects": + this.DecompileSecureObjectsTable(table); + break; + case "ServiceConfig": + this.DecompileServiceConfigTable(table); + break; + case "User": + this.DecompileUserTable(table); + break; + case "UserGroup": + this.DecompileUserGroupTable(table); + break; + case "XmlConfig": + this.DecompileXmlConfigTable(table); + break; + case "XmlFile": + // XmlFile decompilation has been moved to FinalizeXmlFileTable function + break; + default: + base.DecompileTable(table); + break; + } + } + + /// + /// Finalize decompilation. + /// + /// The collection of all tables. + public override void Finish(TableIndexedCollection tables) + { + this.FinalizePerfmonTable(tables); + this.FinalizePerfmonManifestTable(tables); + this.FinalizeSecureObjectsTable(tables); + this.FinalizeServiceConfigTable(tables); + this.FinalizeXmlConfigTable(tables); + this.FinalizeXmlFileTable(tables); + this.FinalizeEventManifestTable(tables); + } + + /// + /// Decompile the WixCloseApplication table. + /// + /// The table to decompile. + private void DecompileWixCloseApplicationTable(Table table) + { + foreach (Row row in table.Rows) + { + Util.CloseApplication closeApplication = new Util.CloseApplication(); + + closeApplication.Id = (string)row[0]; + + closeApplication.Target = (string)row[1]; + + if (null != row[2]) + { + closeApplication.Description = (string)row[2]; + } + + if (null != row[3]) + { + closeApplication.Content = (string)row[3]; + } + + // set defaults + closeApplication.CloseMessage = Util.YesNoType.no; + closeApplication.RebootPrompt = Util.YesNoType.yes; + closeApplication.ElevatedCloseMessage = Util.YesNoType.no; + + if (null != row[4]) + { + int attribute = (int)row[4]; + + closeApplication.CloseMessage = (0x1 == (attribute & 0x1)) ? Util.YesNoType.yes : Util.YesNoType.no; + closeApplication.RebootPrompt = (0x2 == (attribute & 0x2)) ? Util.YesNoType.yes : Util.YesNoType.no; + closeApplication.ElevatedCloseMessage = (0x4 == (attribute & 0x4)) ? Util.YesNoType.yes : Util.YesNoType.no; + } + + if (null != row[5]) + { + closeApplication.Sequence = (int)row[5]; + } + + if (null != row[6]) + { + closeApplication.Property = (string)row[6]; + } + + this.Core.RootElement.AddChild(closeApplication); + } + } + + /// + /// Decompile the WixRemoveFolderEx table. + /// + /// The table to decompile. + private void DecompileWixRemoveFolderExTable(Table table) + { + foreach (Row row in table.Rows) + { + // Set the Id even if auto-generated previously. + Util.RemoveFolderEx removeFolder = new Util.RemoveFolderEx(); + removeFolder.Id = (string)row[0]; + removeFolder.Property = (string)row[2]; + + int installMode = (int)row[3]; + switch ((UtilCompiler.WixRemoveFolderExOn)installMode) + { + case UtilCompiler.WixRemoveFolderExOn.Install: + removeFolder.On = Util.RemoveFolderEx.OnType.install; + break; + + case UtilCompiler.WixRemoveFolderExOn.Uninstall: + removeFolder.On = Util.RemoveFolderEx.OnType.uninstall; + break; + + case UtilCompiler.WixRemoveFolderExOn.Both: + removeFolder.On = Util.RemoveFolderEx.OnType.both; + break; + + default: + this.Core.OnMessage(WixWarnings.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, "InstallMode", installMode)); + break; + } + + // Add to the appropriate Component or section element. + string componentId = (string)row[1]; + Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", componentId); + if (null != component) + { + component.AddChild(removeFolder); + } + else + { + this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", componentId, "Component")); + } + } + } + + /// + /// Decompile the WixRestartResource table. + /// + /// The table to decompile. + private void DecompileWixRestartResourceTable(Table table) + { + foreach (Row row in table.Rows) + { + // Set the Id even if auto-generated previously. + Util.RestartResource restartResource = new Util.RestartResource(); + restartResource.Id = (string)row[0]; + + // Determine the resource type and set accordingly. + string resource = (string)row[2]; + int attributes = (int)row[3]; + UtilCompiler.WixRestartResourceAttributes type = (UtilCompiler.WixRestartResourceAttributes)(attributes & (int)UtilCompiler.WixRestartResourceAttributes.TypeMask); + + switch (type) + { + case UtilCompiler.WixRestartResourceAttributes.Filename: + restartResource.Path = resource; + break; + + case UtilCompiler.WixRestartResourceAttributes.ProcessName: + restartResource.ProcessName = resource; + break; + + case UtilCompiler.WixRestartResourceAttributes.ServiceName: + restartResource.ServiceName = resource; + break; + + default: + this.Core.OnMessage(WixWarnings.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, "Attributes", attributes)); + break; + } + + // Add to the appropriate Component or section element. + string componentId = (string)row[1]; + if (!String.IsNullOrEmpty(componentId)) + { + Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", componentId); + if (null != component) + { + component.AddChild(restartResource); + } + else + { + this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", componentId, "Component")); + } + } + else + { + this.Core.RootElement.AddChild(restartResource); + } + } + } + + /// + /// Decompile the FileShare table. + /// + /// The table to decompile. + private void DecompileFileShareTable(Table table) + { + foreach (Row row in table.Rows) + { + Util.FileShare fileShare = new Util.FileShare(); + + fileShare.Id = (string)row[0]; + + fileShare.Name = (string)row[1]; + + if (null != row[3]) + { + fileShare.Description = (string)row[3]; + } + + // the Directory_ column is set by the parent Component + + // the User_ and Permissions columns are deprecated + + Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); + if (null != component) + { + component.AddChild(fileShare); + } + else + { + this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); + } + this.Core.IndexElement(row, fileShare); + } + } + + /// + /// Decompile the FileSharePermissions table. + /// + /// The table to decompile. + private void DecompileFileSharePermissionsTable(Table table) + { + foreach (Row row in table.Rows) + { + Util.FileSharePermission fileSharePermission = new Util.FileSharePermission(); + + fileSharePermission.User = (string)row[1]; + + string[] specialPermissions = UtilConstants.FolderPermissions; + int permissions = (int)row[2]; + for (int i = 0; i < 32; i++) + { + if (0 != ((permissions >> i) & 1)) + { + string name = null; + + if (16 > i && specialPermissions.Length > i) + { + name = specialPermissions[i]; + } + else if (28 > i && UtilConstants.StandardPermissions.Length > (i - 16)) + { + name = UtilConstants.StandardPermissions[i - 16]; + } + else if (0 <= (i - 28) && UtilConstants.GenericPermissions.Length > (i - 28)) + { + name = UtilConstants.GenericPermissions[i - 28]; + } + + if (null == name) + { + this.Core.OnMessage(WixWarnings.UnknownPermission(row.SourceLineNumbers, row.Table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), i)); + } + else + { + switch (name) + { + case "ChangePermission": + fileSharePermission.ChangePermission = Util.YesNoType.yes; + break; + case "CreateChild": + fileSharePermission.CreateChild = Util.YesNoType.yes; + break; + case "CreateFile": + fileSharePermission.CreateFile = Util.YesNoType.yes; + break; + case "Delete": + fileSharePermission.Delete = Util.YesNoType.yes; + break; + case "DeleteChild": + fileSharePermission.DeleteChild = Util.YesNoType.yes; + break; + case "GenericAll": + fileSharePermission.GenericAll = Util.YesNoType.yes; + break; + case "GenericExecute": + fileSharePermission.GenericExecute = Util.YesNoType.yes; + break; + case "GenericRead": + fileSharePermission.GenericRead = Util.YesNoType.yes; + break; + case "GenericWrite": + fileSharePermission.GenericWrite = Util.YesNoType.yes; + break; + case "Read": + fileSharePermission.Read = Util.YesNoType.yes; + break; + case "ReadAttributes": + fileSharePermission.ReadAttributes = Util.YesNoType.yes; + break; + case "ReadExtendedAttributes": + fileSharePermission.ReadExtendedAttributes = Util.YesNoType.yes; + break; + case "ReadPermission": + fileSharePermission.ReadPermission = Util.YesNoType.yes; + break; + case "Synchronize": + fileSharePermission.Synchronize = Util.YesNoType.yes; + break; + case "TakeOwnership": + fileSharePermission.TakeOwnership = Util.YesNoType.yes; + break; + case "Traverse": + fileSharePermission.Traverse = Util.YesNoType.yes; + break; + case "WriteAttributes": + fileSharePermission.WriteAttributes = Util.YesNoType.yes; + break; + case "WriteExtendedAttributes": + fileSharePermission.WriteExtendedAttributes = Util.YesNoType.yes; + break; + default: + Debug.Fail(String.Format("Unknown permission '{0}'.", name)); + break; + } + } + } + } + + Util.FileShare fileShare = (Util.FileShare)this.Core.GetIndexedElement("FileShare", (string)row[0]); + if (null != fileShare) + { + fileShare.AddChild(fileSharePermission); + } + else + { + this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "FileShare_", (string)row[0], "FileShare")); + } + } + } + + /// + /// Decompile the Group table. + /// + /// The table to decompile. + private void DecompileGroupTable(Table table) + { + foreach (Row row in table.Rows) + { + Util.Group group = new Util.Group(); + + group.Id = (string)row[0]; + + if (null != row[1]) + { + this.Core.OnMessage(WixWarnings.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, "Component_", (string)row[1])); + } + + group.Name = (string)row[2]; + + if (null != row[3]) + { + group.Domain = (string)row[3]; + } + + this.Core.RootElement.AddChild(group); + } + } + + /// + /// Decompile the WixInternetShortcut table. + /// + /// The table to decompile. + private void DecompileWixInternetShortcutTable(Table table) + { + foreach (Row row in table.Rows) + { + Util.InternetShortcut internetShortcut = new Util.InternetShortcut(); + internetShortcut.Id = (string)row[0]; + internetShortcut.Directory = (string)row[2]; + // remove .lnk/.url extension because compiler extension adds it back for us + internetShortcut.Name = Path.ChangeExtension((string)row[3], null); + internetShortcut.Target = (string)row[4]; + internetShortcut.IconFile = (string)row[6]; + internetShortcut.IconIndex = (int)row[7]; + + UtilCompiler.InternetShortcutType shortcutType = (UtilCompiler.InternetShortcutType)row[5]; + switch (shortcutType) + { + case UtilCompiler.InternetShortcutType.Link: + internetShortcut.Type = Util.InternetShortcut.TypeType.link; + break; + case UtilCompiler.InternetShortcutType.Url: + internetShortcut.Type = Util.InternetShortcut.TypeType.url; + break; + } + + Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]); + if (null != component) + { + component.AddChild(internetShortcut); + } + else + { + this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); + } + + this.Core.IndexElement(row, internetShortcut); + } + } + + /// + /// Decompile the Perfmon table. + /// + /// The table to decompile. + private void DecompilePerfmonTable(Table table) + { + foreach (Row row in table.Rows) + { + Util.PerfCounter perfCounter = new Util.PerfCounter(); + + perfCounter.Name = (string)row[2]; + + this.Core.IndexElement(row, perfCounter); + } + } + + /// + /// Decompile the PerfmonManifest table. + /// + /// The table to decompile. + private void DecompilePerfmonManifestTable(Table table) + { + foreach (Row row in table.Rows) + { + Util.PerfCounterManifest perfCounterManifest = new Util.PerfCounterManifest(); + + perfCounterManifest.ResourceFileDirectory = (string)row[2]; + + this.Core.IndexElement(row, perfCounterManifest); + } + } + + /// + /// Decompile the EventManifest table. + /// + /// The table to decompile. + private void DecompileEventManifestTable(Table table) + { + foreach (Row row in table.Rows) + { + Util.EventManifest eventManifest = new Util.EventManifest(); + this.Core.IndexElement(row, eventManifest); + } + } + + /// + /// Decompile the SecureObjects table. + /// + /// The table to decompile. + private void DecompileSecureObjectsTable(Table table) + { + foreach (Row row in table.Rows) + { + Util.PermissionEx permissionEx = new Util.PermissionEx(); + + string[] specialPermissions; + switch ((string)row[1]) + { + case "CreateFolder": + specialPermissions = UtilConstants.FolderPermissions; + break; + case "File": + specialPermissions = UtilConstants.FilePermissions; + break; + case "Registry": + specialPermissions = UtilConstants.RegistryPermissions; + break; + case "ServiceInstall": + specialPermissions = UtilConstants.ServicePermissions; + break; + default: + this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, row.Table.Name, row.Fields[1].Column.Name, row[1])); + return; + } + + int permissionBits = (int)row[4]; + for (int i = 0; i < 32; i++) + { + if (0 != ((permissionBits >> i) & 1)) + { + string name = null; + + if (16 > i && specialPermissions.Length > i) + { + name = specialPermissions[i]; + } + else if (28 > i && UtilConstants.StandardPermissions.Length > (i - 16)) + { + name = UtilConstants.StandardPermissions[i - 16]; + } + else if (0 <= (i - 28) && UtilConstants.GenericPermissions.Length > (i - 28)) + { + name = UtilConstants.GenericPermissions[i - 28]; + } + + if (null == name) + { + this.Core.OnMessage(WixWarnings.UnknownPermission(row.SourceLineNumbers, row.Table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), i)); + } + else + { + switch (name) + { + case "Append": + permissionEx.Append = Util.YesNoType.yes; + break; + case "ChangePermission": + permissionEx.ChangePermission = Util.YesNoType.yes; + break; + case "CreateChild": + permissionEx.CreateChild = Util.YesNoType.yes; + break; + case "CreateFile": + permissionEx.CreateFile = Util.YesNoType.yes; + break; + case "CreateLink": + permissionEx.CreateLink = Util.YesNoType.yes; + break; + case "CreateSubkeys": + permissionEx.CreateSubkeys = Util.YesNoType.yes; + break; + case "Delete": + permissionEx.Delete = Util.YesNoType.yes; + break; + case "DeleteChild": + permissionEx.DeleteChild = Util.YesNoType.yes; + break; + case "EnumerateSubkeys": + permissionEx.EnumerateSubkeys = Util.YesNoType.yes; + break; + case "Execute": + permissionEx.Execute = Util.YesNoType.yes; + break; + case "GenericAll": + permissionEx.GenericAll = Util.YesNoType.yes; + break; + case "GenericExecute": + permissionEx.GenericExecute = Util.YesNoType.yes; + break; + case "GenericRead": + permissionEx.GenericRead = Util.YesNoType.yes; + break; + case "GenericWrite": + permissionEx.GenericWrite = Util.YesNoType.yes; + break; + case "Notify": + permissionEx.Notify = Util.YesNoType.yes; + break; + case "Read": + permissionEx.Read = Util.YesNoType.yes; + break; + case "ReadAttributes": + permissionEx.ReadAttributes = Util.YesNoType.yes; + break; + case "ReadExtendedAttributes": + permissionEx.ReadExtendedAttributes = Util.YesNoType.yes; + break; + case "ReadPermission": + permissionEx.ReadPermission = Util.YesNoType.yes; + break; + case "ServiceChangeConfig": + permissionEx.ServiceChangeConfig = Util.YesNoType.yes; + break; + case "ServiceEnumerateDependents": + permissionEx.ServiceEnumerateDependents = Util.YesNoType.yes; + break; + case "ServiceInterrogate": + permissionEx.ServiceInterrogate = Util.YesNoType.yes; + break; + case "ServicePauseContinue": + permissionEx.ServicePauseContinue = Util.YesNoType.yes; + break; + case "ServiceQueryConfig": + permissionEx.ServiceQueryConfig = Util.YesNoType.yes; + break; + case "ServiceQueryStatus": + permissionEx.ServiceQueryStatus = Util.YesNoType.yes; + break; + case "ServiceStart": + permissionEx.ServiceStart = Util.YesNoType.yes; + break; + case "ServiceStop": + permissionEx.ServiceStop = Util.YesNoType.yes; + break; + case "ServiceUserDefinedControl": + permissionEx.ServiceUserDefinedControl = Util.YesNoType.yes; + break; + case "Synchronize": + permissionEx.Synchronize = Util.YesNoType.yes; + break; + case "TakeOwnership": + permissionEx.TakeOwnership = Util.YesNoType.yes; + break; + case "Traverse": + permissionEx.Traverse = Util.YesNoType.yes; + break; + case "Write": + permissionEx.Write = Util.YesNoType.yes; + break; + case "WriteAttributes": + permissionEx.WriteAttributes = Util.YesNoType.yes; + break; + case "WriteExtendedAttributes": + permissionEx.WriteExtendedAttributes = Util.YesNoType.yes; + break; + default: + throw new InvalidOperationException(String.Format("Unknown permission attribute '{0}'.", name)); + } + } + } + } + + if (null != row[2]) + { + permissionEx.Domain = (string)row[2]; + } + + permissionEx.User = (string)row[3]; + + this.Core.IndexElement(row, permissionEx); + } + } + + /// + /// Decompile the ServiceConfig table. + /// + /// The table to decompile. + private void DecompileServiceConfigTable(Table table) + { + foreach (Row row in table.Rows) + { + Util.ServiceConfig serviceConfig = new Util.ServiceConfig(); + + serviceConfig.ServiceName = (string)row[0]; + + switch ((string)row[3]) + { + case "none": + serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.none; + break; + case "reboot": + serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.reboot; + break; + case "restart": + serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.restart; + break; + case "runCommand": + serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.runCommand; + break; + default: + this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[3].Column.Name, row[3])); + break; + } + + switch ((string)row[4]) + { + case "none": + serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.none; + break; + case "reboot": + serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.reboot; + break; + case "restart": + serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.restart; + break; + case "runCommand": + serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.runCommand; + break; + default: + this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[4].Column.Name, row[4])); + break; + } + + switch ((string)row[5]) + { + case "none": + serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.none; + break; + case "reboot": + serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.reboot; + break; + case "restart": + serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.restart; + break; + case "runCommand": + serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.runCommand; + break; + default: + this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[5].Column.Name, row[5])); + break; + } + + if (null != row[6]) + { + serviceConfig.ResetPeriodInDays = (int)row[6]; + } + + if (null != row[7]) + { + serviceConfig.RestartServiceDelayInSeconds = (int)row[7]; + } + + if (null != row[8]) + { + serviceConfig.ProgramCommandLine = (string)row[8]; + } + + if (null != row[9]) + { + serviceConfig.RebootMessage = (string)row[9]; + } + + this.Core.IndexElement(row, serviceConfig); + } + } + + /// + /// Decompile the User table. + /// + /// The table to decompile. + private void DecompileUserTable(Table table) + { + foreach (Row row in table.Rows) + { + Util.User user = new Util.User(); + + user.Id = (string)row[0]; + + user.Name = (string)row[2]; + + if (null != row[3]) + { + user.Domain = (string)row[3]; + } + + if (null != row[4]) + { + user.Password = (string)row[4]; + } + + if (null != row[5]) + { + int attributes = (int)row[5]; + + if (UtilCompiler.UserDontExpirePasswrd == (attributes & UtilCompiler.UserDontExpirePasswrd)) + { + user.PasswordNeverExpires = Util.YesNoType.yes; + } + + if (UtilCompiler.UserPasswdCantChange == (attributes & UtilCompiler.UserPasswdCantChange)) + { + user.CanNotChangePassword = Util.YesNoType.yes; + } + + if (UtilCompiler.UserPasswdChangeReqdOnLogin == (attributes & UtilCompiler.UserPasswdChangeReqdOnLogin)) + { + user.PasswordExpired = Util.YesNoType.yes; + } + + if (UtilCompiler.UserDisableAccount == (attributes & UtilCompiler.UserDisableAccount)) + { + user.Disabled = Util.YesNoType.yes; + } + + if (UtilCompiler.UserFailIfExists == (attributes & UtilCompiler.UserFailIfExists)) + { + user.FailIfExists = Util.YesNoType.yes; + } + + if (UtilCompiler.UserUpdateIfExists == (attributes & UtilCompiler.UserUpdateIfExists)) + { + user.UpdateIfExists = Util.YesNoType.yes; + } + + if (UtilCompiler.UserLogonAsService == (attributes & UtilCompiler.UserLogonAsService)) + { + user.LogonAsService = Util.YesNoType.yes; + } + + if (UtilCompiler.UserDontRemoveOnUninstall == (attributes & UtilCompiler.UserDontRemoveOnUninstall)) + { + user.RemoveOnUninstall = Util.YesNoType.no; + } + + if (UtilCompiler.UserDontCreateUser == (attributes & UtilCompiler.UserDontCreateUser)) + { + user.CreateUser = Util.YesNoType.no; + } + + if (UtilCompiler.UserNonVital == (attributes & UtilCompiler.UserNonVital)) + { + user.Vital = Util.YesNoType.no; + } + } + + if (null != row[1]) + { + Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]); + + if (null != component) + { + component.AddChild(user); + } + else + { + this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); + } + } + else + { + this.Core.RootElement.AddChild(user); + } + this.Core.IndexElement(row, user); + } + } + + /// + /// Decompile the UserGroup table. + /// + /// The table to decompile. + private void DecompileUserGroupTable(Table table) + { + foreach (Row row in table.Rows) + { + Util.User user = (Util.User)this.Core.GetIndexedElement("User", (string)row[0]); + + if (null != user) + { + Util.GroupRef groupRef = new Util.GroupRef(); + + groupRef.Id = (string)row[1]; + + user.AddChild(groupRef); + } + else + { + this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Group_", (string)row[0], "Group")); + } + } + } + + /// + /// Decompile the XmlConfig table. + /// + /// The table to decompile. + private void DecompileXmlConfigTable(Table table) + { + foreach (Row row in table.Rows) + { + Util.XmlConfig xmlConfig = new Util.XmlConfig(); + + xmlConfig.Id = (string)row[0]; + + xmlConfig.File = (string)row[1]; + + xmlConfig.ElementPath = (string)row[2]; + + if (null != row[3]) + { + xmlConfig.VerifyPath = (string)row[3]; + } + + if (null != row[4]) + { + xmlConfig.Name = (string)row[4]; + } + + if (null != row[5]) + { + xmlConfig.Value = (string)row[5]; + } + + int flags = (int)row[6]; + + if (0x1 == (flags & 0x1)) + { + xmlConfig.Node = Util.XmlConfig.NodeType.element; + } + else if (0x2 == (flags & 0x2)) + { + xmlConfig.Node = Util.XmlConfig.NodeType.value; + } + else if (0x4 == (flags & 0x4)) + { + xmlConfig.Node = Util.XmlConfig.NodeType.document; + } + + if (0x10 == (flags & 0x10)) + { + xmlConfig.Action = Util.XmlConfig.ActionType.create; + } + else if (0x20 == (flags & 0x20)) + { + xmlConfig.Action = Util.XmlConfig.ActionType.delete; + } + + if (0x100 == (flags & 0x100)) + { + xmlConfig.On = Util.XmlConfig.OnType.install; + } + else if (0x200 == (flags & 0x200)) + { + xmlConfig.On = Util.XmlConfig.OnType.uninstall; + } + + if (0x00001000 == (flags & 0x00001000)) + { + xmlConfig.PreserveModifiedDate = Util.YesNoType.yes; + } + + if (null != row[8]) + { + xmlConfig.Sequence = (int)row[8]; + } + + this.Core.IndexElement(row, xmlConfig); + } + } + + /// + /// Finalize the Perfmon table. + /// + /// The collection of all tables. + /// + /// Since the PerfCounter element nests under a File element, but + /// the Perfmon table does not have a foreign key relationship with + /// the File table (instead it has a formatted string that usually + /// refers to a file row - but doesn't have to), the nesting must + /// be inferred during finalization. + /// + private void FinalizePerfmonTable(TableIndexedCollection tables) + { + Table perfmonTable = tables["Perfmon"]; + + if (null != perfmonTable) + { + foreach (Row row in perfmonTable.Rows) + { + string formattedFile = (string)row[1]; + Util.PerfCounter perfCounter = (Util.PerfCounter)this.Core.GetIndexedElement(row); + + // try to "de-format" the File column's value to determine the proper parent File element + if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal)) + && formattedFile.EndsWith("]", StringComparison.Ordinal)) + { + string fileId = formattedFile.Substring(2, formattedFile.Length - 3); + + Wix.File file = (Wix.File)this.Core.GetIndexedElement("File", fileId); + if (null != file) + { + file.AddChild(perfCounter); + } + else + { + this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, perfmonTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "File", formattedFile, "File")); + } + } + else + { + this.Core.OnMessage(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "Perfmon")); + } + } + } + } + + /// + /// Finalize the PerfmonManifest table. + /// + /// The collection of all tables. + private void FinalizePerfmonManifestTable(TableIndexedCollection tables) + { + Table perfmonManifestTable = tables["PerfmonManifest"]; + + if (null != perfmonManifestTable) + { + foreach (Row row in perfmonManifestTable.Rows) + { + string formattedFile = (string)row[1]; + Util.PerfCounterManifest perfCounterManifest = (Util.PerfCounterManifest)this.Core.GetIndexedElement(row); + + // try to "de-format" the File column's value to determine the proper parent File element + if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal)) + && formattedFile.EndsWith("]", StringComparison.Ordinal)) + { + string fileId = formattedFile.Substring(2, formattedFile.Length - 3); + + Wix.File file = (Wix.File)this.Core.GetIndexedElement("File", fileId); + if (null != file) + { + file.AddChild(perfCounterManifest); + } + else + { + this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, perfCounterManifest.ResourceFileDirectory, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "File", formattedFile, "File")); + } + } + else + { + this.Core.OnMessage(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "PerfmonManifest")); + } + } + } + } + + /// + /// Finalize the SecureObjects table. + /// + /// The collection of all tables. + /// + /// Nests the PermissionEx elements below their parent elements. There are no declared foreign + /// keys for the parents of the SecureObjects table. + /// + private void FinalizeSecureObjectsTable(TableIndexedCollection tables) + { + Table createFolderTable = tables["CreateFolder"]; + Table secureObjectsTable = tables["SecureObjects"]; + + Hashtable createFolders = new Hashtable(); + + // index the CreateFolder table because the foreign key to this table from the + // LockPermissions table is only part of the primary key of this table + if (null != createFolderTable) + { + foreach (Row row in createFolderTable.Rows) + { + Wix.CreateFolder createFolder = (Wix.CreateFolder)this.Core.GetIndexedElement(row); + string directoryId = (string)row[0]; + + if (!createFolders.Contains(directoryId)) + { + createFolders.Add(directoryId, new ArrayList()); + } + ((ArrayList)createFolders[directoryId]).Add(createFolder); + } + } + + if (null != secureObjectsTable) + { + foreach (Row row in secureObjectsTable.Rows) + { + string id = (string)row[0]; + string table = (string)row[1]; + + Util.PermissionEx permissionEx = (Util.PermissionEx)this.Core.GetIndexedElement(row); + + if ("CreateFolder" == table) + { + ArrayList createFolderElements = (ArrayList)createFolders[id]; + + if (null != createFolderElements) + { + foreach (Wix.CreateFolder createFolder in createFolderElements) + { + createFolder.AddChild(permissionEx); + } + } + else + { + this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "SecureObjects", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table)); + } + } + else + { + Wix.IParentElement parentElement = (Wix.IParentElement)this.Core.GetIndexedElement(table, id); + + if (null != parentElement) + { + parentElement.AddChild(permissionEx); + } + else + { + this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "SecureObjects", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table)); + } + } + } + } + } + + /// + /// Finalize the ServiceConfig table. + /// + /// The collection of all tables. + /// + /// Since there is no foreign key from the ServiceName column to the + /// ServiceInstall table, this relationship must be handled late. + /// + private void FinalizeServiceConfigTable(TableIndexedCollection tables) + { + Table serviceConfigTable = tables["ServiceConfig"]; + Table serviceInstallTable = tables["ServiceInstall"]; + + Hashtable serviceInstalls = new Hashtable(); + + // index the ServiceInstall table because the foreign key used by the ServiceConfig + // table is actually the ServiceInstall.Name, not the ServiceInstall.ServiceInstall + // this is unfortunate because the service Name is not guaranteed to be unique, so + // decompiler must assume there could be multiple matches and add the ServiceConfig to each + // TODO: the Component column information should be taken into acount to accurately identify + // the correct column to use + if (null != serviceInstallTable) + { + foreach (Row row in serviceInstallTable.Rows) + { + string name = (string)row[1]; + Wix.ServiceInstall serviceInstall = (Wix.ServiceInstall)this.Core.GetIndexedElement(row); + + if (!serviceInstalls.Contains(name)) + { + serviceInstalls.Add(name, new ArrayList()); + } + + ((ArrayList)serviceInstalls[name]).Add(serviceInstall); + } + } + + if (null != serviceConfigTable) + { + foreach (Row row in serviceConfigTable.Rows) + { + Util.ServiceConfig serviceConfig = (Util.ServiceConfig)this.Core.GetIndexedElement(row); + + if (0 == (int)row[2]) + { + Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]); + + if (null != component) + { + component.AddChild(serviceConfig); + } + else + { + this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, serviceConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); + } + } + else + { + ArrayList serviceInstallElements = (ArrayList)serviceInstalls[row[0]]; + + if (null != serviceInstallElements) + { + foreach (Wix.ServiceInstall serviceInstall in serviceInstallElements) + { + serviceInstall.AddChild(serviceConfig); + } + } + else + { + this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, serviceConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ServiceName", (string)row[0], "ServiceInstall")); + } + } + } + } + } + + /// + /// Finalize the XmlConfig table. + /// + /// Collection of all tables. + private void FinalizeXmlConfigTable(TableIndexedCollection tables) + { + Table xmlConfigTable = tables["XmlConfig"]; + + if (null != xmlConfigTable) + { + foreach (Row row in xmlConfigTable.Rows) + { + Util.XmlConfig xmlConfig = (Util.XmlConfig)this.Core.GetIndexedElement(row); + + if (null == row[6] || 0 == (int)row[6]) + { + Util.XmlConfig parentXmlConfig = (Util.XmlConfig)this.Core.GetIndexedElement("XmlConfig", (string)row[2]); + + if (null != parentXmlConfig) + { + parentXmlConfig.AddChild(xmlConfig); + } + else + { + this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, xmlConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ElementPath", (string)row[2], "XmlConfig")); + } + } + else + { + Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[7]); + + if (null != component) + { + component.AddChild(xmlConfig); + } + else + { + this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, xmlConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[7], "Component")); + } + } + } + } + } + + + /// + /// Finalize the XmlFile table. + /// + /// The collection of all tables. + /// + /// Some of the XmlFile table rows are compiler generated from util:EventManifest node + /// These rows should not be appended to component. + /// + private void FinalizeXmlFileTable(TableIndexedCollection tables) + { + Table xmlFileTable = tables["XmlFile"]; + Table eventManifestTable = tables["EventManifest"]; + + if (null != xmlFileTable) + { + foreach (Row row in xmlFileTable.Rows) + { + bool bManifestGenerated = false; + string xmlFileConfigId = (string)row[0]; + if (null != eventManifestTable) + { + foreach (Row emrow in eventManifestTable.Rows) + { + string formattedFile = (string)emrow[1]; + if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal)) + && formattedFile.EndsWith("]", StringComparison.Ordinal)) + { + string fileId = formattedFile.Substring(2, formattedFile.Length - 3); + if (String.Equals(String.Concat("Config_", fileId, "ResourceFile"), xmlFileConfigId)) + { + Util.EventManifest eventManifest = (Util.EventManifest)this.Core.GetIndexedElement(emrow); + if (null != eventManifest) + { + eventManifest.ResourceFile = (string)row[4]; + } + bManifestGenerated = true; + } + + else if (String.Equals(String.Concat("Config_", fileId, "MessageFile"), xmlFileConfigId)) + { + Util.EventManifest eventManifest = (Util.EventManifest)this.Core.GetIndexedElement(emrow); + if (null != eventManifest) + { + eventManifest.MessageFile = (string)row[4]; + } + bManifestGenerated = true; + } + } + } + } + + if (true == bManifestGenerated) + continue; + + Util.XmlFile xmlFile = new Util.XmlFile(); + + xmlFile.Id = (string)row[0]; + xmlFile.File = (string)row[1]; + xmlFile.ElementPath = (string)row[2]; + + if (null != row[3]) + { + xmlFile.Name = (string)row[3]; + } + + if (null != row[4]) + { + xmlFile.Value = (string)row[4]; + } + + int flags = (int)row[5]; + if (0x1 == (flags & 0x1) && 0x2 == (flags & 0x2)) + { + this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, xmlFileTable.Name, row.Fields[5].Column.Name, row[5])); + } + else if (0x1 == (flags & 0x1)) + { + xmlFile.Action = Util.XmlFile.ActionType.createElement; + } + else if (0x2 == (flags & 0x2)) + { + xmlFile.Action = Util.XmlFile.ActionType.deleteValue; + } + else + { + xmlFile.Action = Util.XmlFile.ActionType.setValue; + } + + if (0x100 == (flags & 0x100)) + { + xmlFile.SelectionLanguage = Util.XmlFile.SelectionLanguageType.XPath; + } + + if (0x00001000 == (flags & 0x00001000)) + { + xmlFile.PreserveModifiedDate = Util.YesNoType.yes; + } + + if (0x00010000 == (flags & 0x00010000)) + { + xmlFile.Permanent = Util.YesNoType.yes; + } + + if (null != row[7]) + { + xmlFile.Sequence = (int)row[7]; + } + + Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[6]); + + if (null != component) + { + component.AddChild(xmlFile); + } + else + { + this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, xmlFileTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[6], "Component")); + } + } + } + } + + /// + /// Finalize the eventManifest table. + /// This function must be called after FinalizeXmlFileTable + /// + /// The collection of all tables. + private void FinalizeEventManifestTable(TableIndexedCollection tables) + { + Table eventManifestTable = tables["EventManifest"]; + + if (null != eventManifestTable) + { + foreach (Row row in eventManifestTable.Rows) + { + string formattedFile = (string)row[1]; + Util.EventManifest eventManifest = (Util.EventManifest)this.Core.GetIndexedElement(row); + + // try to "de-format" the File column's value to determine the proper parent File element + if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal)) + && formattedFile.EndsWith("]", StringComparison.Ordinal)) + { + string fileId = formattedFile.Substring(2, formattedFile.Length - 3); + + Wix.File file = (Wix.File)this.Core.GetIndexedElement("File", fileId); + if (null != file) + { + file.AddChild(eventManifest); + } + } + else + { + this.Core.OnMessage(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "EventManifest")); + } + } + } + } + } +#endif +} diff --git a/src/ext/Util/wixext/UtilErrors.cs b/src/ext/Util/wixext/UtilErrors.cs new file mode 100644 index 00000000..b9ce1688 --- /dev/null +++ b/src/ext/Util/wixext/UtilErrors.cs @@ -0,0 +1,49 @@ +// Copyright (c) .NET 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.Util +{ + using System; + using System.Resources; + using WixToolset.Data; + + public static class UtilErrors + { + 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 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 IllegalFileValueInPerfmonOrManifest(string file, string table) + { + return Message(null, Ids.IllegalFileValueInPerfmonOrManifest, "The value '{0}' in the File column, {1} table is invalid. It should be in the form of '[#file]' or '[!file]'.", file, table); + } + + public static Message InvalidRegistryObject(SourceLineNumber sourceLineNumbers, string registryElementName) + { + return Message(sourceLineNumbers, Ids.InvalidRegistryObject, "The {0} element has no id and cannot have its permissions set. If you want to set permissions on a 'placeholder' registry key, force its creation by setting the ForceCreateOnInstall attribute to yes.", registryElementName); + } + + 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 + { + IllegalAttributeWithoutComponent = 5050, + IllegalElementWithoutComponent = 5051, + IllegalFileValueInPerfmonOrManifest = 5054, + InvalidRegistryObject = 5063, + } + } +} diff --git a/src/ext/Util/wixext/UtilExtensionData.cs b/src/ext/Util/wixext/UtilExtensionData.cs new file mode 100644 index 00000000..d3ca3358 --- /dev/null +++ b/src/ext/Util/wixext/UtilExtensionData.cs @@ -0,0 +1,23 @@ +// Copyright (c) .NET 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.Util +{ + using WixToolset.Data; + using WixToolset.Extensibility; + + public sealed class UtilExtensionData : BaseExtensionData + { + public override string DefaultCulture => "en-US"; + + public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition) + { + symbolDefinition = UtilSymbolDefinitions.ByName(name); + return symbolDefinition != null; + } + + public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions) + { + return Intermediate.Load(typeof(UtilExtensionData).Assembly, "WixToolset.Util.util.wixlib", symbolDefinitions); + } + } +} diff --git a/src/ext/Util/wixext/UtilExtensionFactory.cs b/src/ext/Util/wixext/UtilExtensionFactory.cs new file mode 100644 index 00000000..08352813 --- /dev/null +++ b/src/ext/Util/wixext/UtilExtensionFactory.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.Util +{ + using System; + using System.Collections.Generic; + using WixToolset.Extensibility; + + public class UtilExtensionFactory : BaseExtensionFactory + { + protected override IReadOnlyCollection ExtensionTypes => new[] + { + typeof(UtilCompiler), + typeof(UtilExtensionData), + typeof(UtilWindowsInstallerBackendBinderExtension), + }; + } +} diff --git a/src/ext/Util/wixext/UtilTableDefinitions.cs b/src/ext/Util/wixext/UtilTableDefinitions.cs new file mode 100644 index 00000000..12f423cc --- /dev/null +++ b/src/ext/Util/wixext/UtilTableDefinitions.cs @@ -0,0 +1,319 @@ +// Copyright (c) .NET 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.Util +{ + using WixToolset.Data.WindowsInstaller; + + public static class UtilTableDefinitions + { + public static readonly TableDefinition Wix4CloseApplication = new TableDefinition( + "Wix4CloseApplication", + UtilSymbolDefinitions.WixCloseApplication, + new[] + { + new ColumnDefinition("Wix4CloseApplication", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token in table.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Target", ColumnType.Localized, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Name of executable to ensure is closed.", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Description", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Description string displayed to user when executable is in use.", modularizeType: ColumnModularizeType.Property, forceLocalizable: true), + new ColumnDefinition("Condition", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Condition, description: "Optional expression which skips the closing.", modularizeType: ColumnModularizeType.Condition, forceLocalizable: true), + new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 2147483647, description: "A 32-bit word that specifies the attribute flags to be applied."), + new ColumnDefinition("Sequence", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, minValue: 1, maxValue: 2147483647, description: "Sequence to order the closings by."), + new ColumnDefinition("Property", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, description: "Optional property that is set to the number of running instances of the app.", modularizeType: ColumnModularizeType.Property, forceLocalizable: true), + new ColumnDefinition("TerminateExitCode", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, minValue: 0, maxValue: 2147483647, description: "Exit code to return from a terminated application."), + new ColumnDefinition("Timeout", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, minValue: 1, maxValue: 2147483647, description: "Timeout in milliseconds before scheduling restart or terminating application."), + }, + symbolIdIsPrimaryKey: true + ); + + public static readonly TableDefinition Wix4RemoveFolderEx = new TableDefinition( + "Wix4RemoveFolderEx", + UtilSymbolDefinitions.WixRemoveFolderEx, + new[] + { + new ColumnDefinition("Wix4RemoveFolderEx", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Identifier for the WixRemoveFolderEx row in the package.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Property", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, description: "Name of Property that contains the root of the directory tree to remove.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("InstallMode", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 1, maxValue: 3, description: "1 == Remove only when the associated component is being installed (msiInstallStateLocal or msiInstallStateSource), 2 == Remove only when the associated component is being removed (msiInstallStateAbsent), 3 = Remove in either of the above cases."), + new ColumnDefinition("Condition", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Condition, description: "Optional expression which skips the removing of folders.", modularizeType: ColumnModularizeType.Condition, forceLocalizable: true), + }, + symbolIdIsPrimaryKey: true + ); + + public static readonly TableDefinition Wix4RemoveRegistryKeyEx = new TableDefinition( + "Wix4RemoveRegistryKeyEx", + UtilSymbolDefinitions.WixRemoveRegistryKeyEx, + new[] + { + new ColumnDefinition("Wix4RemoveRegistryKeyEx", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Identifier for the Wix4RemoveRegistryKeyEx row in the package.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Root", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: -1, maxValue: 3, description: "The predefined root key for the registry value, one of rrkEnum."), + new ColumnDefinition("Key", ColumnType.Localized, 255, primaryKey: false, nullable: false, ColumnCategory.RegPath, description: "The key for the registry value.", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("InstallMode", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 1, maxValue: 3, description: "1 == Remove only when the associated component is being installed (msiInstallStateLocal or msiInstallStateSource), 2 == Remove only when the associated component is being removed (msiInstallStateAbsent), 3 = Remove in either of the above cases."), + new ColumnDefinition("Condition", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Condition, description: "Optional expression to control whether the registry key is removed.", modularizeType: ColumnModularizeType.Condition, forceLocalizable: true), + }, + symbolIdIsPrimaryKey: true + ); + + public static readonly TableDefinition Wix4RestartResource = new TableDefinition( + "Wix4RestartResource", + UtilSymbolDefinitions.WixRestartResource, + new[] + { + new ColumnDefinition("Wix4RestartResource", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized identifier.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Resource", ColumnType.String, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "The resource to be registered with the Restart Manager.", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 2147483647, description: "A 32-bit word that specifies the type of resource and flags used for processing."), + }, + symbolIdIsPrimaryKey: true + ); + + public static readonly TableDefinition Wix4FileShare = new TableDefinition( + "Wix4FileShare", + UtilSymbolDefinitions.FileShare, + new[] + { + new ColumnDefinition("Wix4FileShare", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized identifier", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("ShareName", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "The actual share name used"), + new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Description", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Description string displayed for the file share"), + new ColumnDefinition("Directory_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Directory", keyColumn: 1, description: "Foreign key referencing directory that the share is created on", modularizeType: ColumnModularizeType.Column), + }, + symbolIdIsPrimaryKey: true + ); + + public static readonly TableDefinition Wix4FileSharePermissions = new TableDefinition( + "Wix4FileSharePermissions", + UtilSymbolDefinitions.FileSharePermissions, + new[] + { + new ColumnDefinition("Wix4FileShare_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "FileShare", keyColumn: 1, description: "FileShare that these premissions are to be applied to.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Wix4User_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Wix4User", description: "User that these premissions are to apply to.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Permissions", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, description: "Permissions int, as in EXPLICIT_ACCESS.grfAccessPermissions in MSDN"), + }, + symbolIdIsPrimaryKey: false + ); + + public static readonly TableDefinition Wix4Group = new TableDefinition( + "Wix4Group", + UtilSymbolDefinitions.Group, + new[] + { + new ColumnDefinition("Wix4Group", 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.Text, keyTable: "Component", keyColumn: 1, description: "Foreign key, Component used to determine install state", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Name", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Group name", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Domain", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Group domain", modularizeType: ColumnModularizeType.Property), + }, + symbolIdIsPrimaryKey: true + ); + + public static readonly TableDefinition Wix4InternetShortcut = new TableDefinition( + "Wix4InternetShortcut", + UtilSymbolDefinitions.WixInternetShortcut, + new[] + { + new ColumnDefinition("Wix4InternetShortcut", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token in table.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Text, keyTable: "Component", keyColumn: 1, description: "Foreign key, Component used to determine install state", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Directory_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Directory", keyColumn: 1, description: "Foreign key referencing directory that the shortcut is created in", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Name", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Name used for shortcut.", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Target", ColumnType.Localized, 0, primaryKey: false, nullable: false, ColumnCategory.Text, description: "URL target."), + new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, description: "Attribute flags that control how the shortcut is created."), + new ColumnDefinition("IconFile", ColumnType.Localized, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Icon file for shortcut", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("IconIndex", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Index of the icon being referenced."), + }, + symbolIdIsPrimaryKey: true + ); + + public static readonly TableDefinition Wix4PerformanceCategory = new TableDefinition( + "Wix4PerformanceCategory", + UtilSymbolDefinitions.PerformanceCategory, + new[] + { + new ColumnDefinition("Wix4PerformanceCategory", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token in table.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Component used to determine install state", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Name", ColumnType.String, 80, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Name of the performance counter category."), + new ColumnDefinition("IniData", ColumnType.Localized, 0, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Data that goes into the performance counter .ini file."), + new ColumnDefinition("ConstantData", ColumnType.Localized, 0, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Data that goes into the performance counter .h file."), + }, + symbolIdIsPrimaryKey: true + ); + + public static readonly TableDefinition Wix4Perfmon = new TableDefinition( + "Wix4Perfmon", + UtilSymbolDefinitions.Perfmon, + new[] + { + new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Component used to determine install state", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("File", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Formatted, description: "Name of .INI file", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Name", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Text, description: "Service name in registry"), + }, + symbolIdIsPrimaryKey: false + ); + + public static readonly TableDefinition Wix4PerfmonManifest = new TableDefinition( + "Wix4PerfmonManifest", + UtilSymbolDefinitions.PerfmonManifest, + new[] + { + new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Component used to determine install state", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("File", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Formatted, description: "Name of perfmon manifest file", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("ResourceFileDirectory", ColumnType.String, 255, primaryKey: true, nullable: false, ColumnCategory.Formatted, description: "The path of the Resource File Directory"), + }, + symbolIdIsPrimaryKey: false + ); + + public static readonly TableDefinition Wix4EventManifest = new TableDefinition( + "Wix4EventManifest", + UtilSymbolDefinitions.EventManifest, + new[] + { + new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Component used to determine install state", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("File", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Formatted, description: "Name of event manifest file", modularizeType: ColumnModularizeType.Property), + }, + symbolIdIsPrimaryKey: false + ); + + public static readonly TableDefinition Wix4SecureObject = new TableDefinition( + "Wix4SecureObject", + UtilSymbolDefinitions.SecureObjects, + new[] + { + new ColumnDefinition("Wix4SecureObject", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token in Table", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Table", ColumnType.String, 32, primaryKey: true, nullable: false, ColumnCategory.Text, description: "Table SecureObject should be securing"), + new ColumnDefinition("Domain", ColumnType.String, 255, primaryKey: true, nullable: true, ColumnCategory.Text, description: "Domain half of user account to secure", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("User", ColumnType.String, 255, primaryKey: true, nullable: false, ColumnCategory.Text, description: "User name half of user account to secure", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Integer, minValue: 0, maxValue: 2147483647, description: "A 32-bit word that specifies the attribute flags to be applied."), + new ColumnDefinition("Permission", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, minValue: -2147483647, maxValue: 2147483647, description: "Permissions to grant to User"), + new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state", modularizeType: ColumnModularizeType.Column), + }, + symbolIdIsPrimaryKey: false + ); + + public static readonly TableDefinition Wix4ServiceConfig = new TableDefinition( + "Wix4ServiceConfig", + UtilSymbolDefinitions.ServiceConfig, + new[] + { + new ColumnDefinition("ServiceName", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Formatted, description: "Primary key, non-localized token"), + new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key, Component used to determine install state ", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("NewService", ColumnType.Number, 1, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 1, description: "Whether the affected service is being installed or already exists."), + new ColumnDefinition("FirstFailureActionType", ColumnType.String, 32, primaryKey: false, nullable: false, ColumnCategory.Text, description: "First failure action type for configured service to take."), + new ColumnDefinition("SecondFailureActionType", ColumnType.String, 32, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Second failure action type for configured service to take."), + new ColumnDefinition("ThirdFailureActionType", ColumnType.String, 32, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Third failure action type for configured service to take."), + new ColumnDefinition("ResetPeriodInDays", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Integer, minValue: 0, description: "Period after which to reset the failure count for the service."), + new ColumnDefinition("RestartServiceDelayInSeconds", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Integer, minValue: 0, description: "Period after which to restart the service after a given failure."), + new ColumnDefinition("ProgramCommandLine", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Command line for program to run if failure action is RUN_COMMAND."), + new ColumnDefinition("RebootMessage", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Message to show to users when rebooting if failure action is REBOOT."), + }, + symbolIdIsPrimaryKey: false + ); + + public static readonly TableDefinition Wix4TouchFile = new TableDefinition( + "Wix4TouchFile", + UtilSymbolDefinitions.WixTouchFile, + new[] + { + new ColumnDefinition("Wix4TouchFile", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Identifier for the Wix4TouchFile row in the package.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Path", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Formatted column that resolves to the path to touch.", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 1, maxValue: 63, description: "1 == Touch only when the associated component is being installed, 2 == Touch only when the associated component is being repaired , 4 == Touch only when the associated component is being removed, 16 = path is in 64-bit location, 32 = touching the file is vital."), + }, + symbolIdIsPrimaryKey: true + ); + + public static readonly TableDefinition Wix4User = new TableDefinition( + "Wix4User", + UtilSymbolDefinitions.User, + new[] + { + new ColumnDefinition("Wix4User", 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.Text, keyTable: "Component", keyColumn: 1, description: "Foreign key, Component used to determine install state", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Name", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "User name", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Domain", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "User domain", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Password", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "User password", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, minValue: 0, maxValue: 65535, description: "Attributes describing how to create the user"), + }, + symbolIdIsPrimaryKey: true + ); + + public static readonly TableDefinition Wix4UserGroup = new TableDefinition( + "Wix4UserGroup", + UtilSymbolDefinitions.UserGroup, + new[] + { + new ColumnDefinition("Wix4User_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Wix4User", keyColumn: 1, description: "User to be joined to a Group.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Wix4Group_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Wix4Group", keyColumn: 1, description: "Group to join User to.", modularizeType: ColumnModularizeType.Column), + }, + symbolIdIsPrimaryKey: false + ); + + public static readonly TableDefinition Wix4XmlFile = new TableDefinition( + "Wix4XmlFile", + UtilSymbolDefinitions.XmlFile, + new[] + { + new ColumnDefinition("Wix4XmlFile", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("File", ColumnType.Localized, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "The .XML file in which to write the information", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("ElementPath", ColumnType.Localized, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "The .XML file element to modify.", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Name", ColumnType.Localized, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The .XML file node to set/add in the element.", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Value", ColumnType.Localized, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The value to be written.", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Flags", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 70143, description: "Flags"), + new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table referencing component that controls the installing of the .XML value.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Sequence", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Order to execute the XML modifications."), + }, + symbolIdIsPrimaryKey: true + ); + + public static readonly TableDefinition Wix4XmlConfig = new TableDefinition( + "Wix4XmlConfig", + UtilSymbolDefinitions.XmlConfig, + new[] + { + new ColumnDefinition("Wix4XmlConfig", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("File", ColumnType.Localized, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "The .XML file in which to write the information", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("ElementId", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "Wix4XmlConfig", keyColumn: 1, description: "A foreign key reference to another Wix4XmlConfig row if no attributes are set and the row referenced is a create element row.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("ElementPath", ColumnType.Localized, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The XPATH query for an element to modify or add children to. Must be null if ElementId is provided", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("VerifyPath", ColumnType.Localized, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The XPATH query run from ElementPath to verify whether a repair is necessary. Also used to uninstall.", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Name", ColumnType.Localized, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The .XML file node to set/add in the element.", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Value", ColumnType.Localized, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The value to be written.", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Flags", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 65536, description: "Element=1,Value=2,Document=4,Create=16,Delete=32,Install=256,Uninstall=512"), + new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table referencing component that controls the installing of the .XML value.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Sequence", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Order to execute the XML modifications."), + }, + symbolIdIsPrimaryKey: true + ); + + public static readonly TableDefinition Wix4FormatFile = new TableDefinition( + "Wix4FormatFile", + UtilSymbolDefinitions.WixFormatFiles, + new[] + { + new ColumnDefinition("Binary_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Binary", keyColumn: 1, description: "Binary data to be formatted.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("File_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "File", keyColumn: 1, description: "File whose component controls the custom action and where the formatted data is written.", modularizeType: ColumnModularizeType.Column), + }, + symbolIdIsPrimaryKey: false + ); + + public static readonly TableDefinition[] All = new[] + { + Wix4CloseApplication, + Wix4RemoveFolderEx, + Wix4RemoveRegistryKeyEx, + Wix4RestartResource, + Wix4FileShare, + Wix4FileSharePermissions, + Wix4Group, + Wix4InternetShortcut, + Wix4PerformanceCategory, + Wix4Perfmon, + Wix4PerfmonManifest, + Wix4EventManifest, + Wix4SecureObject, + Wix4ServiceConfig, + Wix4TouchFile, + Wix4User, + Wix4UserGroup, + Wix4XmlFile, + Wix4XmlConfig, + Wix4FormatFile, + }; + } +} diff --git a/src/ext/Util/wixext/UtilWarnings.cs b/src/ext/Util/wixext/UtilWarnings.cs new file mode 100644 index 00000000..b65abe45 --- /dev/null +++ b/src/ext/Util/wixext/UtilWarnings.cs @@ -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. + +namespace WixToolset.Util +{ + using System; + using System.Resources; + using WixToolset.Data; + + public static class UtilWarnings + { + public static Message DeprecatedPerfCounterElement(SourceLineNumber sourceLineNumbers) + { + return Message(sourceLineNumbers, Ids.DeprecatedPerfCounterElement, "The PerfCounter element has been deprecated. Please use the PerformanceCounter element instead."); + } + + public static Message RequiredAttributeForWindowsXP(SourceLineNumber sourceLineNumbers, string elementName, string attributeName) + { + return Message(sourceLineNumbers, Ids.RequiredAttributeForWindowsXP, "The {0}/@{1} attribute must be specified to successfully install on Windows XP. You can ignore this warning if this installation does not install on Windows XP.", elementName, attributeName); + } + + private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) + { + return new Message(sourceLineNumber, MessageLevel.Warning, (int)id, format, args); + } + + private static Message Message(SourceLineNumber sourceLineNumber, Ids id, ResourceManager resourceManager, string resourceName, params object[] args) + { + return new Message(sourceLineNumber, MessageLevel.Warning, (int)id, resourceManager, resourceName, args); + } + + public enum Ids + { + DeprecatedPerfCounterElement = 5153, + RequiredAttributeForWindowsXP = 5154, + } + } +} diff --git a/src/ext/Util/wixext/UtilWindowsInstallerBackendExtension.cs b/src/ext/Util/wixext/UtilWindowsInstallerBackendExtension.cs new file mode 100644 index 00000000..bca7c700 --- /dev/null +++ b/src/ext/Util/wixext/UtilWindowsInstallerBackendExtension.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.Util +{ + using System.Collections.Generic; + using WixToolset.Data.WindowsInstaller; + using WixToolset.Extensibility; + + public class UtilWindowsInstallerBackendBinderExtension : BaseWindowsInstallerBackendBinderExtension + { + public override IReadOnlyCollection TableDefinitions => UtilTableDefinitions.All; + } +} diff --git a/src/ext/Util/wixext/WixToolset.Util.wixext.csproj b/src/ext/Util/wixext/WixToolset.Util.wixext.csproj new file mode 100644 index 00000000..10fc569e --- /dev/null +++ b/src/ext/Util/wixext/WixToolset.Util.wixext.csproj @@ -0,0 +1,31 @@ + + + + + + netstandard2.0 + WixToolset.Util + WiX Toolset Utility Extension + WiX Toolset Util Extension + embedded + true + + + + + + + + + + + + + + + + + + + + diff --git a/src/ext/Util/wixext/WixToolset.Util.wixext.nuspec b/src/ext/Util/wixext/WixToolset.Util.wixext.nuspec new file mode 100644 index 00000000..ba3eaade --- /dev/null +++ b/src/ext/Util/wixext/WixToolset.Util.wixext.nuspec @@ -0,0 +1,25 @@ + + + + $id$ + $version$ + $title$ + $description$ + $authors$ + MS-RL + false + $copyright$ + $projectUrl$ + + + + + + + + + + + + + diff --git a/src/ext/Util/wixext/WixToolset.Util.wixext.targets b/src/ext/Util/wixext/WixToolset.Util.wixext.targets new file mode 100644 index 00000000..64dff429 --- /dev/null +++ b/src/ext/Util/wixext/WixToolset.Util.wixext.targets @@ -0,0 +1,11 @@ + + + + + + $(MSBuildThisFileDirectory)..\tools\WixToolset.Util.wixext.dll + + + + + diff --git a/src/ext/Util/wixext/WixToolset.Util.wixext.v3.ncrunchproject b/src/ext/Util/wixext/WixToolset.Util.wixext.v3.ncrunchproject new file mode 100644 index 00000000..d75e7ab3 --- /dev/null +++ b/src/ext/Util/wixext/WixToolset.Util.wixext.v3.ncrunchproject @@ -0,0 +1,7 @@ + + + + ..\..\build\Debug\util.wixlib + + + \ No newline at end of file diff --git a/src/ext/Util/wixlib/UtilBundleExtension_Platform.wxi b/src/ext/Util/wixlib/UtilBundleExtension_Platform.wxi new file mode 100644 index 00000000..379c8f57 --- /dev/null +++ b/src/ext/Util/wixlib/UtilBundleExtension_Platform.wxi @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/ext/Util/wixlib/UtilBundleExtension_arm64.wxs b/src/ext/Util/wixlib/UtilBundleExtension_arm64.wxs new file mode 100644 index 00000000..b17be031 --- /dev/null +++ b/src/ext/Util/wixlib/UtilBundleExtension_arm64.wxs @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/ext/Util/wixlib/UtilBundleExtension_x64.wxs b/src/ext/Util/wixlib/UtilBundleExtension_x64.wxs new file mode 100644 index 00000000..96c85a5b --- /dev/null +++ b/src/ext/Util/wixlib/UtilBundleExtension_x64.wxs @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/ext/Util/wixlib/UtilBundleExtension_x86.wxs b/src/ext/Util/wixlib/UtilBundleExtension_x86.wxs new file mode 100644 index 00000000..3b458687 --- /dev/null +++ b/src/ext/Util/wixlib/UtilBundleExtension_x86.wxs @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/ext/Util/wixlib/UtilExtension.wxs b/src/ext/Util/wixlib/UtilExtension.wxs new file mode 100644 index 00000000..0f445ab4 --- /dev/null +++ b/src/ext/Util/wixlib/UtilExtension.wxs @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ext/Util/wixlib/UtilExtension_Platform.wxi b/src/ext/Util/wixlib/UtilExtension_Platform.wxi new file mode 100644 index 00000000..913c01b9 --- /dev/null +++ b/src/ext/Util/wixlib/UtilExtension_Platform.wxi @@ -0,0 +1,360 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ext/Util/wixlib/UtilExtension_arm64.wxs b/src/ext/Util/wixlib/UtilExtension_arm64.wxs new file mode 100644 index 00000000..b9dc73b8 --- /dev/null +++ b/src/ext/Util/wixlib/UtilExtension_arm64.wxs @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/ext/Util/wixlib/UtilExtension_x64.wxs b/src/ext/Util/wixlib/UtilExtension_x64.wxs new file mode 100644 index 00000000..40cdf306 --- /dev/null +++ b/src/ext/Util/wixlib/UtilExtension_x64.wxs @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/ext/Util/wixlib/UtilExtension_x86.wxs b/src/ext/Util/wixlib/UtilExtension_x86.wxs new file mode 100644 index 00000000..bd0fa562 --- /dev/null +++ b/src/ext/Util/wixlib/UtilExtension_x86.wxs @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/ext/Util/wixlib/caDecor.wxi b/src/ext/Util/wixlib/caDecor.wxi new file mode 100644 index 00000000..b1711518 --- /dev/null +++ b/src/ext/Util/wixlib/caDecor.wxi @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ext/Util/wixlib/caerr.wxi b/src/ext/Util/wixlib/caerr.wxi new file mode 100644 index 00000000..ff7ec121 --- /dev/null +++ b/src/ext/Util/wixlib/caerr.wxi @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ext/Util/wixlib/de-de.wxl b/src/ext/Util/wixlib/de-de.wxl new file mode 100644 index 00000000..65785a3b --- /dev/null +++ b/src/ext/Util/wixlib/de-de.wxl @@ -0,0 +1,32 @@ + + + + + Konnte den Benutzer nicht anlegen. ([2] [3] [4] [5]) + Konnte den Benutzer auf Grund eines falschen Passwortes nicht anlegen. ([2] [3] [4] [5]) + Konnte Benutzer nicht zur Gruppe hinzufügen. ([2] [3] [4] [5]) + Konnte den Benutzer nicht anlegen, da er bereits existierte. ([2] [3] [4] [5]) + + Konnte Netzwerkfreigabe nicht anlegen. ([2] [3] [4] [5]) + Konnte Netzwerkfreigabe nicht entfernen. ([2] [3] [4] [5]) + + Konnte die DLL nicht für PerfMon registrieren. ([2] [3] [4] [5]) + Konnte die DLL nicht für PerfMon deregistrieren. ([2] [3] [4] [5]) + + Konnte die Daten der Leistungsüberwachung (performance counters) nicht installieren. ([2] [3] [4] [5]) + Konnte die Daten der Leistungsüberwachung (performance counters) nicht deinstallieren. ([2] [3] [4] [5]) + + Konnte keinen Security Descriptor für [3]\[4] erstellen, System Fehler: [2] + Konnte keinen Security Descriptor für das Objekt [3] erstellen, System Fehler: [2] + Unbekannter Objekt Typ [3], System Fehler: [2] + + Beim Lesen der XML Dateien trat ein Fehler auf. + Konnte XML Datei [3] nicht öffnen, System Fehler: [2] + Konnte Knoten [3] in der XML Datei [4] nicht finden, System Fehler: [2] + Beim Speichern der Änderungen an der XML Datei [3] trat ein Fehler auf, System Fehler: [2] + + Bei der Konfiguration der XML Dateien trat ein Fehler auf. + Konnte XML Datei [3] nicht öffnen, System Fehler: [2] + Konnte Knoten [3] in der XML Datei [4] nicht finden, System Fehler: [2] + Beim Speichern der Änderungen an der XML Datei [3] trat ein Fehler auf, System Fehler: [2] + diff --git a/src/ext/Util/wixlib/en-us.wxl b/src/ext/Util/wixlib/en-us.wxl new file mode 100644 index 00000000..e8b146a4 --- /dev/null +++ b/src/ext/Util/wixlib/en-us.wxl @@ -0,0 +1,32 @@ + + + + + Failed to create user. ([2] [3] [4] [5]) + Failed to create user due to invalid password. ([2] [3] [4] [5]) + Failed to add user to group. ([2] [3] [4] [5]) + Failed to create user because it already exists. ([2] [3] [4] [5]) + + Failed to create network share. ([2] [3] [4] [5]) + Failed to drop network share. ([2] [3] [4] [5]) + + Failed to register DLL with PerfMon. ([2] [3] [4] [5]) + Failed to unregister DLL with PerfMon. ([2] [3] [4] [5]) + + Failed to install performance counters. ([2] [3] [4] [5]) + Failed to uninstall performance counters. ([2] [3] [4] [5]) + + Failed to create security descriptor for [3]\[4], system error: [2] + Failed to set security descriptor on object [3], system error: [2] + Unknown Object Type [3], system error: [2] + + There was a failure while configuring XML files. + Failed to open XML file [3], system error: [2] + Failed to find node: [3] in XML file: [4], system error: [2] + Failed to save changes to XML file [3], system error: [2] + + There was a failure while configuring XML files. + Failed to open XML file [3], system error: [2] + Failed to find node: [3] in XML file: [4], system error: [2] + Failed to save changes to XML file [3], system error: [2] + diff --git a/src/ext/Util/wixlib/es-es.wxl b/src/ext/Util/wixlib/es-es.wxl new file mode 100644 index 00000000..ca5ab8bb --- /dev/null +++ b/src/ext/Util/wixlib/es-es.wxl @@ -0,0 +1,31 @@ + + + + La creación del usuario ha fracasado. ([2] [3] [4] [5]) + La creación del usuario ha fracasado porque la contraseña es incorrecta. ([2] [3] [4] [5]) + El aditamento del usuario al grupo ha fracasado. ([2] [3] [4] [5]) + La creación del usuario ha fracasado porque ya existe. ([2] [3] [4] [5]) + + La creación de la red compartida ha fracasado. ([2] [3] [4] [5]) + La eliminación de la red compartida ha fracasado. ([2] [3] [4] [5]) + + La inscripción al registro de la DLL con PerfMon ha fracasado. ([2] [3] [4] [5]) + La cancelación de la inscripción al registro de la DLL con PerfMon ha fracasado. ([2] [3] [4] [5]) + + La instalación de los contadores de rendimiento ha fracasado. ([2] [3] [4] [5]) + La desinstalación de los contadores de rendimiento ha fracasado. ([2] [3] [4] [5]) + + La creación de los ACLs ha fracasado por [3]\[4], error del sistema : [2] + El posicionamiento de los ACLs por el objecto [3] ha fracasado, error del sistema: [2] + Tipo de objecto no conocido [3], error del sistema: [2] + + Un problema ha aparecido durante la configuración de los ficheros XML. + Fracaso de la apertura de los ficheros XML [3], error del sistema: [2] + Fracaso de la búsqueda del nodo: [3] en el fichero XML: [4], error del sistema: [2] + Fracaso durante la salvaguardia de las modificaciones en el fichero XML [3], error del sistema: [2] + + Un problema ha aparecido durante la configuración de los ficheros XML. + Fracaso de la apertura de los ficheros XML [3], error del sistema: [2] + Fracaso de la búsqueda del nodo: [3] en el fichero XML: [4], error del sistema: [2] + Fracaso durante la salvaguardia de las modificaciones en el fichero XML [3], error del sistema: [2] + \ No newline at end of file diff --git a/src/ext/Util/wixlib/fr-fr.wxl b/src/ext/Util/wixlib/fr-fr.wxl new file mode 100644 index 00000000..ad34b56a --- /dev/null +++ b/src/ext/Util/wixlib/fr-fr.wxl @@ -0,0 +1,31 @@ + + + + La création de l'utilisateur a échoué. ([2] [3] [4] [5]) + La création de l'utilisateur a échoué car le mot de passe est invalide. ([2] [3] [4] [5]) + L'ajout de l'utilisateur au groupe a échoué. ([2] [3] [4] [5]) + La création de l'utilisateur a échoué car il existe dejà. ([2] [3] [4] [5]) + + La création du partage reseau a échoué. ([2] [3] [4] [5]) + La suppression du partage reseau a échoué. ([2] [3] [4] [5]) + + L'inscription au registre de la DLL avec PerfMon a échoué. ([2] [3] [4] [5]) + La desinscription au registre de la DLL avec PerfMon a échoué. ([2] [3] [4] [5]) + + L'installation des compteurs de performance a échoué. ([2] [3] [4] [5]) + La desinstallation des compteurs de performance a échoué. ([2] [3] [4] [5]) + + La création des ACLs a échoué pour [3]\[4], erreur systeme: [2] + Le positionnement des ACLs pour l'objet [3] a échoué, erreur systeme: [2] + Type d'objet inconnu [3], erreur systeme: [2] + + Un problème est survenu lors de la configuration des fichiers XML. + Echec de l'ouverture des fichiers XML [3], erreur systeme: [2] + Echec de la recherche du noeud: [3] dans le fichier XML: [4], erreur systeme: [2] + Echec lors de la sauvegarde des modifications dans le fichier XML [3], erreur systeme: [2] + + Un problème est survenu lors de la configuration des fichiers XML. + Echec de l'ouverture des fichiers XML [3], erreur systeme: [2] + Echec de la recherche du noeud: [3] dans le fichier XML: [4], erreur systeme: [2] + Echec lors de la sauvegarde des modifications dans le fichier XML [3], erreur systeme: [2] + \ No newline at end of file diff --git a/src/ext/Util/wixlib/it-it.wxl b/src/ext/Util/wixlib/it-it.wxl new file mode 100644 index 00000000..8cea0a14 --- /dev/null +++ b/src/ext/Util/wixlib/it-it.wxl @@ -0,0 +1,32 @@ + + + + + Impossibile creare l'utente. ([2] [3] [4] [5]) + Impossibile creare l'utente perchè la password è errata. ([2] [3] [4] [5]) + Impossibile aggiungere l'utente al gruppo. ([2] [3] [4] [5]) + Impossibile creare l'utente perchè già esistente. ([2] [3] [4] [5]) + + Impossibile creare la risorsa di rete. ([2] [3] [4] [5]) + Impossibile eliminare la risorsa di rete. ([2] [3] [4] [5]) + + Impossibile registrare la DLL con PerfMon. ([2] [3] [4] [5]) + Impossibile rimuovere la registrazione della DLL con PerfMon. ([2] [3] [4] [5]) + + Impossibile installare i contatori delle prestazioni. ([2] [3] [4] [5]) + Impossibile rimuovere i contatori delle prestazioni. ([2] [3] [4] [5]) + + Impossibile creare i descrittori di sicurezza per [3]\[4], errore di sistema: [2] + Impossibile impostare i descrittori di sicurezza sull'oggetto [3], errore di sistema: [2] + Tipo di oggetto sconosciuto [3], errore di sistema: [2] + + Si è verificato un errore durante la configurazione dei file XML. + Impossibile aprire il file XML [3], errore di sistema: [2] + Impossibile trovare il nodo: [3] nel file XML: [4], errore di sistema: [2] + Impossible salvare le modifiche al file XML [3], errore di sistema: [2] + + Si è verificato un errore durante la configurazione dei file XML. + Impossibile aprire il file XML [3], errore di sistema: [2] + Impossibile trovare il nodo: [3] nel file XML: [4], errore di sistema: [2] + Impossibile salvare le modifiche al file XML [3], errore di sitema: [2] + diff --git a/src/ext/Util/wixlib/ja-jp.wxl b/src/ext/Util/wixlib/ja-jp.wxl new file mode 100644 index 00000000..5f5cf40d --- /dev/null +++ b/src/ext/Util/wixlib/ja-jp.wxl @@ -0,0 +1,32 @@ + + + + + ユーザー作成に失敗しました。 ([2] [3] [4] [5]) + パスワードが無効のためユーザー作成に失敗しました。 ([2] [3] [4] [5]) + ユーザーをグループに追加でいませんでした。 ([2] [3] [4] [5]) + ユーザーが既に存在するため作成できませんでした。 ([2] [3] [4] [5]) + + ネットワーク共有の作成に失敗しました。 ([2] [3] [4] [5]) + ネットワーク共有の削除に失敗しました。 ([2] [3] [4] [5]) + + DLL を PerfMon に登録でいませんでした。 ([2] [3] [4] [5]) + DLL を PerfMon より登録解除できませんでした。 ([2] [3] [4] [5]) + + パフォーマンス カウンタをインストールできませんでした。 ([2] [3] [4] [5]) + パフォーマンス カウンタをアンインストールできませんでした。 ([2] [3] [4] [5]) + + [3]\[4] 用セキュリティ ディスクリプターを作成できませんでした、システム エラー: [2] + オブジェクト [3] 上のセキュリティ ディスクリプターを設定できませんでした、システム エラー: [2] + 不明なオブジェクト種別 [3]、システム エラー: [2] + + XML ファイル構成中に失敗しました。 + XML ファイル [3] を開けませんでした、システム エラー: [2] + XML ファイル [4] 内にノード [3] が見つかりませんでした、システム エラー: [2] + XML ファイル [3] へ変更を保存できませんでした、システム エラー: [2] + + XML ファイル構成中に失敗しました。 + XML ファイル [3] を開けませんでした、システム エラー: [2] + XML ファイル [4] 内にノード [3] が見つかりませんでした、システム エラー: [2] + XML ファイル [3] へ変更を保存できませんでした、システム エラー: [2] + diff --git a/src/ext/Util/wixlib/pt-br.wxl b/src/ext/Util/wixlib/pt-br.wxl new file mode 100644 index 00000000..3ca27dda --- /dev/null +++ b/src/ext/Util/wixlib/pt-br.wxl @@ -0,0 +1,26 @@ + + + + + Falha ao criar usuário. ([2] [3] [4] [5]) + Falha ao criar usuário devido a senha inválida. ([2] [3] [4] [5]) + Falha ao adicionar o usuário ao grupo. ([2] [3] [4] [5]) + Falha ao criar o usuário, porque ele já existe. ([2] [3] [4] [5]) + Falha ao criar o compartilhamento de rede. ([2] [3] [4] [5]) + Falha ao cair compartilhamento de rede. ([2] [3] [4] [5]) + Falha ao registrar DLL com PerfMon. ([2] [3] [4] [5]) + Falha ao cancelar o registro de DLL com PerfMon. ([2] [3] [4] [5]) + Falha ao instalar contadores de desempenho. ([2] [3] [4] [5]) + Falha ao desinstalar contadores de desempenho. ([2] [3] [4] [5]) + Falha ao criar o descritor de segurança [3] \ [4], erro do sistema: [2] + Falha ao definir o descritor de segurança sobre o objeto [3], erro do sistema: [2] + Objeto Desconhecido Tipo [3], erro do sistema: [2] + Houve uma falha ao configurar arquivos XML. + Falha ao abrir o arquivo XML [3], erro do sistema: [2] + Falha ao localizar nó: [3] no arquivo XML: [4], erro do sistema: [2] + Falha ao salvar as alterações para o arquivo XML [3], erro do sistema: [2] + Houve uma falha ao configurar arquivos XML. + Falha ao abrir o arquivo XML [3], erro do sistema: [2] + Falha ao localizar nó: [3] no arquivo XML: [4], erro do sistema: [2] + Falha ao salvar as alterações para o arquivo XML [3], erro do sistema: [2] + diff --git a/src/ext/Util/wixlib/util.v3.ncrunchproject b/src/ext/Util/wixlib/util.v3.ncrunchproject new file mode 100644 index 00000000..319cd523 --- /dev/null +++ b/src/ext/Util/wixlib/util.v3.ncrunchproject @@ -0,0 +1,5 @@ + + + True + + \ No newline at end of file diff --git a/src/ext/Util/wixlib/util.wixproj b/src/ext/Util/wixlib/util.wixproj new file mode 100644 index 00000000..99dede7d --- /dev/null +++ b/src/ext/Util/wixlib/util.wixproj @@ -0,0 +1,27 @@ + + + + + Library + true + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ext/global.json b/src/ext/global.json new file mode 100644 index 00000000..697f5687 --- /dev/null +++ b/src/ext/global.json @@ -0,0 +1,8 @@ +{ + "msbuild-sdks": { + "WixToolset.Sdk": "4.0.0-build-0213" + }, + "sdk": { + "allowPrerelease": false + } +} diff --git a/src/test/WixToolsetTest.Util/TestData/.Data/burn.exe b/src/test/WixToolsetTest.Util/TestData/.Data/burn.exe deleted file mode 100644 index 2a4f423f..00000000 Binary files a/src/test/WixToolsetTest.Util/TestData/.Data/burn.exe and /dev/null differ diff --git a/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.en-us.wxl b/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.en-us.wxl deleted file mode 100644 index f50a5386..00000000 --- a/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.en-us.wxl +++ /dev/null @@ -1,8 +0,0 @@ - - - - ~TestBundle - - diff --git a/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.wxs b/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.wxs deleted file mode 100644 index 7fef0725..00000000 --- a/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.wxs +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/MsiPackage/Shared.dll b/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/MsiPackage/Shared.dll deleted file mode 100644 index 0e461ba8..00000000 --- a/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/MsiPackage/Shared.dll +++ /dev/null @@ -1 +0,0 @@ -This is Shared.dll. \ No newline at end of file diff --git a/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/MsiPackage/test.txt b/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/MsiPackage/test.txt deleted file mode 100644 index 8b986220..00000000 --- a/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/MsiPackage/test.txt +++ /dev/null @@ -1 +0,0 @@ -This is test.txt \ No newline at end of file diff --git a/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/fakeba.dll b/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/fakeba.dll deleted file mode 100644 index 970efdf0..00000000 --- a/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/fakeba.dll +++ /dev/null @@ -1 +0,0 @@ -This is a fakeba.dll \ No newline at end of file diff --git a/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/test.msi b/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/test.msi deleted file mode 100644 index 0722d60e..00000000 Binary files a/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/data/test.msi and /dev/null differ diff --git a/src/test/WixToolsetTest.Util/TestData/CloseApplication/Package.en-us.wxl b/src/test/WixToolsetTest.Util/TestData/CloseApplication/Package.en-us.wxl deleted file mode 100644 index 5301bb1a..00000000 --- a/src/test/WixToolsetTest.Util/TestData/CloseApplication/Package.en-us.wxl +++ /dev/null @@ -1,9 +0,0 @@ - - - - A newer version of [ProductName] is already installed. - MsiPackage - - diff --git a/src/test/WixToolsetTest.Util/TestData/CloseApplication/Package.wxs b/src/test/WixToolsetTest.Util/TestData/CloseApplication/Package.wxs deleted file mode 100644 index 8e054256..00000000 --- a/src/test/WixToolsetTest.Util/TestData/CloseApplication/Package.wxs +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/CloseApplication/PackageComponents.wxs b/src/test/WixToolsetTest.Util/TestData/CloseApplication/PackageComponents.wxs deleted file mode 100644 index e27b3c43..00000000 --- a/src/test/WixToolsetTest.Util/TestData/CloseApplication/PackageComponents.wxs +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/CloseApplication/example.txt b/src/test/WixToolsetTest.Util/TestData/CloseApplication/example.txt deleted file mode 100644 index 1b4ffe8a..00000000 --- a/src/test/WixToolsetTest.Util/TestData/CloseApplication/example.txt +++ /dev/null @@ -1 +0,0 @@ -This is example.txt. \ No newline at end of file diff --git a/src/test/WixToolsetTest.Util/TestData/EventManifest/Package.en-us.wxl b/src/test/WixToolsetTest.Util/TestData/EventManifest/Package.en-us.wxl deleted file mode 100644 index 5301bb1a..00000000 --- a/src/test/WixToolsetTest.Util/TestData/EventManifest/Package.en-us.wxl +++ /dev/null @@ -1,9 +0,0 @@ - - - - A newer version of [ProductName] is already installed. - MsiPackage - - diff --git a/src/test/WixToolsetTest.Util/TestData/EventManifest/Package.wxs b/src/test/WixToolsetTest.Util/TestData/EventManifest/Package.wxs deleted file mode 100644 index daae573a..00000000 --- a/src/test/WixToolsetTest.Util/TestData/EventManifest/Package.wxs +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/EventManifest/PackageComponents.wxs b/src/test/WixToolsetTest.Util/TestData/EventManifest/PackageComponents.wxs deleted file mode 100644 index 2ec8ce82..00000000 --- a/src/test/WixToolsetTest.Util/TestData/EventManifest/PackageComponents.wxs +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/EventManifest/example.txt b/src/test/WixToolsetTest.Util/TestData/EventManifest/example.txt deleted file mode 100644 index 1b4ffe8a..00000000 --- a/src/test/WixToolsetTest.Util/TestData/EventManifest/example.txt +++ /dev/null @@ -1 +0,0 @@ -This is example.txt. \ No newline at end of file diff --git a/src/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.en-us.wxl b/src/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.en-us.wxl deleted file mode 100644 index 5301bb1a..00000000 --- a/src/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.en-us.wxl +++ /dev/null @@ -1,9 +0,0 @@ - - - - A newer version of [ProductName] is already installed. - MsiPackage - - diff --git a/src/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.ico b/src/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.ico deleted file mode 100644 index 53134de7..00000000 Binary files a/src/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.ico and /dev/null differ diff --git a/src/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.wxs b/src/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.wxs deleted file mode 100644 index daae573a..00000000 --- a/src/test/WixToolsetTest.Util/TestData/InternetShortcut/Package.wxs +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/InternetShortcut/PackageComponents.wxs b/src/test/WixToolsetTest.Util/TestData/InternetShortcut/PackageComponents.wxs deleted file mode 100644 index 2a1b4347..00000000 --- a/src/test/WixToolsetTest.Util/TestData/InternetShortcut/PackageComponents.wxs +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/InternetShortcut/example.txt b/src/test/WixToolsetTest.Util/TestData/InternetShortcut/example.txt deleted file mode 100644 index 1b4ffe8a..00000000 --- a/src/test/WixToolsetTest.Util/TestData/InternetShortcut/example.txt +++ /dev/null @@ -1 +0,0 @@ -This is example.txt. \ No newline at end of file diff --git a/src/test/WixToolsetTest.Util/TestData/InternetShortcutModule/Module.wxs b/src/test/WixToolsetTest.Util/TestData/InternetShortcutModule/Module.wxs deleted file mode 100644 index 1355d42e..00000000 --- a/src/test/WixToolsetTest.Util/TestData/InternetShortcutModule/Module.wxs +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/InternetShortcutModule/ModuleComponents.wxs b/src/test/WixToolsetTest.Util/TestData/InternetShortcutModule/ModuleComponents.wxs deleted file mode 100644 index 2a1b4347..00000000 --- a/src/test/WixToolsetTest.Util/TestData/InternetShortcutModule/ModuleComponents.wxs +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/InternetShortcutModule/Package.ico b/src/test/WixToolsetTest.Util/TestData/InternetShortcutModule/Package.ico deleted file mode 100644 index 53134de7..00000000 Binary files a/src/test/WixToolsetTest.Util/TestData/InternetShortcutModule/Package.ico and /dev/null differ diff --git a/src/test/WixToolsetTest.Util/TestData/PermissionEx/Package.en-us.wxl b/src/test/WixToolsetTest.Util/TestData/PermissionEx/Package.en-us.wxl deleted file mode 100644 index 5301bb1a..00000000 --- a/src/test/WixToolsetTest.Util/TestData/PermissionEx/Package.en-us.wxl +++ /dev/null @@ -1,9 +0,0 @@ - - - - A newer version of [ProductName] is already installed. - MsiPackage - - diff --git a/src/test/WixToolsetTest.Util/TestData/PermissionEx/Package.wxs b/src/test/WixToolsetTest.Util/TestData/PermissionEx/Package.wxs deleted file mode 100644 index daae573a..00000000 --- a/src/test/WixToolsetTest.Util/TestData/PermissionEx/Package.wxs +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/PermissionEx/PackageComponents.wxs b/src/test/WixToolsetTest.Util/TestData/PermissionEx/PackageComponents.wxs deleted file mode 100644 index 0634d7d4..00000000 --- a/src/test/WixToolsetTest.Util/TestData/PermissionEx/PackageComponents.wxs +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/PermissionEx/example.txt b/src/test/WixToolsetTest.Util/TestData/PermissionEx/example.txt deleted file mode 100644 index 1b4ffe8a..00000000 --- a/src/test/WixToolsetTest.Util/TestData/PermissionEx/example.txt +++ /dev/null @@ -1 +0,0 @@ -This is example.txt. \ No newline at end of file diff --git a/src/test/WixToolsetTest.Util/TestData/Queries/Package.en-us.wxl b/src/test/WixToolsetTest.Util/TestData/Queries/Package.en-us.wxl deleted file mode 100644 index 5301bb1a..00000000 --- a/src/test/WixToolsetTest.Util/TestData/Queries/Package.en-us.wxl +++ /dev/null @@ -1,9 +0,0 @@ - - - - A newer version of [ProductName] is already installed. - MsiPackage - - diff --git a/src/test/WixToolsetTest.Util/TestData/Queries/Package.wxs b/src/test/WixToolsetTest.Util/TestData/Queries/Package.wxs deleted file mode 100644 index abf0dbb4..00000000 --- a/src/test/WixToolsetTest.Util/TestData/Queries/Package.wxs +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/Queries/PackageComponents.wxs b/src/test/WixToolsetTest.Util/TestData/Queries/PackageComponents.wxs deleted file mode 100644 index e27b3c43..00000000 --- a/src/test/WixToolsetTest.Util/TestData/Queries/PackageComponents.wxs +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/Queries/example.txt b/src/test/WixToolsetTest.Util/TestData/Queries/example.txt deleted file mode 100644 index 1b4ffe8a..00000000 --- a/src/test/WixToolsetTest.Util/TestData/Queries/example.txt +++ /dev/null @@ -1 +0,0 @@ -This is example.txt. \ No newline at end of file diff --git a/src/test/WixToolsetTest.Util/TestData/RemoveFolderEx/Module.wxs b/src/test/WixToolsetTest.Util/TestData/RemoveFolderEx/Module.wxs deleted file mode 100644 index 2c2be584..00000000 --- a/src/test/WixToolsetTest.Util/TestData/RemoveFolderEx/Module.wxs +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/RemoveFolderEx/ModuleComponents.wxs b/src/test/WixToolsetTest.Util/TestData/RemoveFolderEx/ModuleComponents.wxs deleted file mode 100644 index 236d9df0..00000000 --- a/src/test/WixToolsetTest.Util/TestData/RemoveFolderEx/ModuleComponents.wxs +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/RemoveRegistryKeyEx/Module.wxs b/src/test/WixToolsetTest.Util/TestData/RemoveRegistryKeyEx/Module.wxs deleted file mode 100644 index 32b246f4..00000000 --- a/src/test/WixToolsetTest.Util/TestData/RemoveRegistryKeyEx/Module.wxs +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/RemoveRegistryKeyEx/ModuleComponents.wxs b/src/test/WixToolsetTest.Util/TestData/RemoveRegistryKeyEx/ModuleComponents.wxs deleted file mode 100644 index 0a0c8cb6..00000000 --- a/src/test/WixToolsetTest.Util/TestData/RemoveRegistryKeyEx/ModuleComponents.wxs +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/UsingFileShare/Package.en-us.wxl b/src/test/WixToolsetTest.Util/TestData/UsingFileShare/Package.en-us.wxl deleted file mode 100644 index 5301bb1a..00000000 --- a/src/test/WixToolsetTest.Util/TestData/UsingFileShare/Package.en-us.wxl +++ /dev/null @@ -1,9 +0,0 @@ - - - - A newer version of [ProductName] is already installed. - MsiPackage - - diff --git a/src/test/WixToolsetTest.Util/TestData/UsingFileShare/Package.wxs b/src/test/WixToolsetTest.Util/TestData/UsingFileShare/Package.wxs deleted file mode 100644 index daae573a..00000000 --- a/src/test/WixToolsetTest.Util/TestData/UsingFileShare/Package.wxs +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/UsingFileShare/PackageComponents.wxs b/src/test/WixToolsetTest.Util/TestData/UsingFileShare/PackageComponents.wxs deleted file mode 100644 index 7cedbb30..00000000 --- a/src/test/WixToolsetTest.Util/TestData/UsingFileShare/PackageComponents.wxs +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/UsingFileShare/example.txt b/src/test/WixToolsetTest.Util/TestData/UsingFileShare/example.txt deleted file mode 100644 index 1b4ffe8a..00000000 --- a/src/test/WixToolsetTest.Util/TestData/UsingFileShare/example.txt +++ /dev/null @@ -1 +0,0 @@ -This is example.txt. \ No newline at end of file diff --git a/src/test/WixToolsetTest.Util/TestData/XmlConfig/Package.en-us.wxl b/src/test/WixToolsetTest.Util/TestData/XmlConfig/Package.en-us.wxl deleted file mode 100644 index 5301bb1a..00000000 --- a/src/test/WixToolsetTest.Util/TestData/XmlConfig/Package.en-us.wxl +++ /dev/null @@ -1,9 +0,0 @@ - - - - A newer version of [ProductName] is already installed. - MsiPackage - - diff --git a/src/test/WixToolsetTest.Util/TestData/XmlConfig/Package.wxs b/src/test/WixToolsetTest.Util/TestData/XmlConfig/Package.wxs deleted file mode 100644 index a2002634..00000000 --- a/src/test/WixToolsetTest.Util/TestData/XmlConfig/Package.wxs +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/XmlConfigModule/Module.wxs b/src/test/WixToolsetTest.Util/TestData/XmlConfigModule/Module.wxs deleted file mode 100644 index 29e8555b..00000000 --- a/src/test/WixToolsetTest.Util/TestData/XmlConfigModule/Module.wxs +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/TestData/XmlConfigModule/my.xml b/src/test/WixToolsetTest.Util/TestData/XmlConfigModule/my.xml deleted file mode 100644 index bad25217..00000000 --- a/src/test/WixToolsetTest.Util/TestData/XmlConfigModule/my.xml +++ /dev/null @@ -1 +0,0 @@ -This is my.xml file. diff --git a/src/test/WixToolsetTest.Util/UtilExtensionFixture.cs b/src/test/WixToolsetTest.Util/UtilExtensionFixture.cs deleted file mode 100644 index 883f9794..00000000 --- a/src/test/WixToolsetTest.Util/UtilExtensionFixture.cs +++ /dev/null @@ -1,317 +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.Util -{ - using System.IO; - using System.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Core.TestPackage; - using WixToolset.Data; - using WixToolset.Data.Symbols; - using WixToolset.Util; - using Xunit; - - public class UtilExtensionFixture - { - [Fact] - public void CanBuildUsingFileShare() - { - var folder = TestData.Get(@"TestData\UsingFileShare"); - var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); - - var results = build.BuildAndQuery(Build, "Binary", "CustomAction", "Wix4FileShare", "Wix4FileSharePermissions"); - WixAssert.CompareLineByLine(new[] - { - "Binary:Wix4UtilCA_X86\t[Binary data]", - "CustomAction:Wix4ConfigureSmbInstall_X86\t1\tWix4UtilCA_X86\tConfigureSmbInstall\t", - "CustomAction:Wix4ConfigureSmbUninstall_X86\t1\tWix4UtilCA_X86\tConfigureSmbUninstall\t", - "CustomAction:Wix4CreateSmb_X86\t11265\tWix4UtilCA_X86\tCreateSmb\t", - "CustomAction:Wix4CreateSmbRollback_X86\t11585\tWix4UtilCA_X86\tDropSmb\t", - "CustomAction:Wix4DropSmb_X86\t11265\tWix4UtilCA_X86\tDropSmb\t", - "CustomAction:Wix4DropSmbRollback_X86\t11585\tWix4UtilCA_X86\tCreateSmb\t", - "Wix4FileShare:ExampleFileShare\texample\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example file share\tINSTALLFOLDER", - "Wix4FileSharePermissions:ExampleFileShare\tEveryone\t1", - }, results.OrderBy(s => s).ToArray()); - } - - [Fact] - public void CanBuildUsingFileShareX64() - { - var folder = TestData.Get(@"TestData\UsingFileShare"); - var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); - - var results = build.BuildAndQuery(BuildX64, "Binary", "CustomAction", "Wix4FileShare", "Wix4FileSharePermissions"); - WixAssert.CompareLineByLine(new[] - { - "Binary:Wix4UtilCA_X64\t[Binary data]", - "CustomAction:Wix4ConfigureSmbInstall_X64\t1\tWix4UtilCA_X64\tConfigureSmbInstall\t", - "CustomAction:Wix4ConfigureSmbUninstall_X64\t1\tWix4UtilCA_X64\tConfigureSmbUninstall\t", - "CustomAction:Wix4CreateSmb_X64\t11265\tWix4UtilCA_X64\tCreateSmb\t", - "CustomAction:Wix4CreateSmbRollback_X64\t11585\tWix4UtilCA_X64\tDropSmb\t", - "CustomAction:Wix4DropSmb_X64\t11265\tWix4UtilCA_X64\tDropSmb\t", - "CustomAction:Wix4DropSmbRollback_X64\t11585\tWix4UtilCA_X64\tCreateSmb\t", - "Wix4FileShare:ExampleFileShare\texample\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example file share\tINSTALLFOLDER", - "Wix4FileSharePermissions:ExampleFileShare\tEveryone\t1", - }, results.OrderBy(s => s).ToArray()); - } - - [Fact] - public void CanBuildCloseApplication() - { - var folder = TestData.Get(@"TestData\CloseApplication"); - var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); - - var results = build.BuildAndQuery(BuildARM64, "Binary", "CustomAction", "Wix4CloseApplication"); - WixAssert.CompareLineByLine(new[] - { - "Binary:Wix4UtilCA_A64\t[Binary data]", - "CustomAction:Wix4CheckRebootRequired_A64\t65\tWix4UtilCA_A64\tWixCheckRebootRequired\t", - "CustomAction:Wix4CloseApplications_A64\t1\tWix4UtilCA_A64\tWixCloseApplications\t", - "CustomAction:Wix4CloseApplicationsDeferred_A64\t3073\tWix4UtilCA_A64\tWixCloseApplicationsDeferred\t", - "Wix4CloseApplication:CloseMyApp\texplorer.exe\t\t\t3\t\tMYAPPISRUNNING\t\t", - }, results.OrderBy(s => s).ToArray()); - } - - [Fact] - public void CanBuildInternetShortcutInProduct() - { - var folder = TestData.Get(@"TestData\InternetShortcut"); - var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); - - var results = build.BuildAndQuery(BuildX64, "Binary", "CustomAction", "RemoveFile", "Wix4InternetShortcut"); - WixAssert.CompareLineByLine(new[] - { - "Binary:Wix4UtilCA_X64\t[Binary data]", - "CustomAction:Wix4CreateInternetShortcuts_X64\t3073\tWix4UtilCA_X64\tWixCreateInternetShortcuts\t", - "CustomAction:Wix4RollbackInternetShortcuts_X64\t3329\tWix4UtilCA_X64\tWixRollbackInternetShortcuts\t", - "CustomAction:Wix4SchedInternetShortcuts_X64\t1\tWix4UtilCA_X64\tWixSchedInternetShortcuts\t", - "RemoveFile:uisdCsU32.1i4Hebrg1N7E194zJQ8Y\tPackage.ico\thoiptxrr.url|WiX Toolset (url).url\tINSTALLFOLDER\t2", - "RemoveFile:uisjV.q0ROZZYR3h_lkpbkZtLtPH0A\tPackage.ico\tjcxd1dwf.lnk|WiX Toolset (link).lnk\tINSTALLFOLDER\t2", - "Wix4InternetShortcut:uisdCsU32.1i4Hebrg1N7E194zJQ8Y\tPackage.ico\tINSTALLFOLDER\tWiX Toolset (url).url\thttps://wixtoolset.org\t1\t[#Package.ico]\t0", - "Wix4InternetShortcut:uisjV.q0ROZZYR3h_lkpbkZtLtPH0A\tPackage.ico\tINSTALLFOLDER\tWiX Toolset (link).lnk\thttps://wixtoolset.org\t0\t[#Package.ico]\t0", - }, results.OrderBy(s => s).ToArray()); - } - - [Fact] - public void CanBuildInternetShortcutInMergeModule() - { - var folder = TestData.Get(@"TestData\InternetShortcutModule"); - var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }, "test.msm"); - - var results = build.BuildAndQuery(BuildX64, "Binary", "CustomAction", "RemoveFile", "Wix4InternetShortcut"); - WixAssert.CompareLineByLine(new[] - { - "Binary:Wix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\t[Binary data]", - "CustomAction:Wix4CreateInternetShortcuts_X64\t3073\tWix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\tWixCreateInternetShortcuts\t", - "CustomAction:Wix4RollbackInternetShortcuts_X64\t3329\tWix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\tWixRollbackInternetShortcuts\t", - "CustomAction:Wix4SchedInternetShortcuts_X64\t1\tWix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\tWixSchedInternetShortcuts\t", - "RemoveFile:uisdCsU32.1i4Hebrg1N7E194zJQ8Y.047730A5_30FE_4A62_A520_DA9381B8226A\tPackage.ico.047730A5_30FE_4A62_A520_DA9381B8226A\thoiptxrr.url|WiX Toolset (url).url\tINSTALLFOLDER.047730A5_30FE_4A62_A520_DA9381B8226A\t2", - "RemoveFile:uisjV.q0ROZZYR3h_lkpbkZtLtPH0A.047730A5_30FE_4A62_A520_DA9381B8226A\tPackage.ico.047730A5_30FE_4A62_A520_DA9381B8226A\tjcxd1dwf.lnk|WiX Toolset (link).lnk\tINSTALLFOLDER.047730A5_30FE_4A62_A520_DA9381B8226A\t2", - "Wix4InternetShortcut:uisdCsU32.1i4Hebrg1N7E194zJQ8Y.047730A5_30FE_4A62_A520_DA9381B8226A\tPackage.ico.047730A5_30FE_4A62_A520_DA9381B8226A\tINSTALLFOLDER.047730A5_30FE_4A62_A520_DA9381B8226A\tWiX Toolset (url).url\thttps://wixtoolset.org\t1\t[#Package.ico.047730A5_30FE_4A62_A520_DA9381B8226A]\t0", - "Wix4InternetShortcut:uisjV.q0ROZZYR3h_lkpbkZtLtPH0A.047730A5_30FE_4A62_A520_DA9381B8226A\tPackage.ico.047730A5_30FE_4A62_A520_DA9381B8226A\tINSTALLFOLDER.047730A5_30FE_4A62_A520_DA9381B8226A\tWiX Toolset (link).lnk\thttps://wixtoolset.org\t0\t[#Package.ico.047730A5_30FE_4A62_A520_DA9381B8226A]\t0", - }, results.OrderBy(s => s).ToArray()); - } - - [Fact] - public void CanBuildWithPermissionEx() - { - var folder = TestData.Get(@"TestData\PermissionEx"); - var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); - - var results = build.BuildAndQuery(BuildX64, "Wix4SecureObject"); - WixAssert.CompareLineByLine(new[] - { - "Wix4SecureObject:ExampleRegistryKey\tRegistry\t\tEveryone\t1\t268435456\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo", - "Wix4SecureObject:filF5_pLhBuF5b4N9XEo52g_hUM5Lo\tFile\t\tEveryone\t1\t268435456\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo", - "Wix4SecureObject:INSTALLFOLDER\tCreateFolder\t\tEveryone\t1\t268435456\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo", - "Wix4SecureObject:regL6DnQ9yJpDJH5OdcVji4YXsdX2c\tRegistry\t\tEveryone\t1\t268435456\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo", - "Wix4SecureObject:testsvc\tServiceInstall\t\tEveryone\t1\t268435456\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo", - }, results.OrderBy(s => s).ToArray()); - } - - [Fact] - public void CanBuildRemoveRegistryKeyExInMergeModule() - { - var folder = TestData.Get(@"TestData", "RemoveRegistryKeyEx"); - var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }, "test.msm"); - - var results = build.BuildAndQuery(BuildX64, "Binary", "CustomAction", "RemoveRegistry", "Wix4RemoveRegistryKeyEx"); - WixAssert.CompareLineByLine(new[] - { - "Binary:Wix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\t[Binary data]", - "CustomAction:Wix4RemoveRegistryKeysEx_X64.047730A5_30FE_4A62_A520_DA9381B8226A\t65\tWix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\tWixRemoveRegistryKeysEx\t", - "Wix4RemoveRegistryKeyEx:rrxfcDhR4HhE3v3rYiQcNtQjyahQNg.047730A5_30FE_4A62_A520_DA9381B8226A\tfilh4juyUVjoUcWWtcQmd5L07FoON4.047730A5_30FE_4A62_A520_DA9381B8226A\t2\tSOFTWARE\\Example\t1\t", - }, results.OrderBy(s => s).ToArray()); - } - - [Fact] - public void CanBuildRemoveFolderExInMergeModule() - { - var folder = TestData.Get(@"TestData\RemoveFolderEx"); - var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }, "test.msm"); - - var results = build.BuildAndQuery(BuildX64, "Binary", "CustomAction", "RemoveFile", "Wix4RemoveFolderEx"); - WixAssert.CompareLineByLine(new[] - { - "Binary:Wix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\t[Binary data]", - "CustomAction:Wix4RemoveFoldersEx_X64.047730A5_30FE_4A62_A520_DA9381B8226A\t65\tWix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\tWixRemoveFoldersEx\t", - "Wix4RemoveFolderEx:wrf5qCm1SE.zp8djrlk78l1IYFXsEw.047730A5_30FE_4A62_A520_DA9381B8226A\tfilh4juyUVjoUcWWtcQmd5L07FoON4.047730A5_30FE_4A62_A520_DA9381B8226A\tRemoveProp.047730A5_30FE_4A62_A520_DA9381B8226A\t3\t", - }, results.OrderBy(s => s).ToArray()); - } - - [Fact] - public void CanBuildWithEventManifest() - { - var folder = TestData.Get(@"TestData\EventManifest"); - var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); - - var results = build.BuildAndQuery(BuildARM64, "Binary", "CustomAction", "Wix4EventManifest", "Wix4XmlFile"); - WixAssert.CompareLineByLine(new[] - { - "Binary:Wix4UtilCA_A64\t[Binary data]", - "CustomAction:Wix4ConfigureEventManifestRegister_A64\t1\tWix4UtilCA_A64\tConfigureEventManifestRegister\t", - "CustomAction:Wix4ConfigureEventManifestUnregister_A64\t1\tWix4UtilCA_A64\tConfigureEventManifestUnregister\t", - "CustomAction:Wix4ExecXmlFile_A64\t11265\tWix4UtilCA_A64\tExecXmlFile\t", - "CustomAction:Wix4ExecXmlFileRollback_A64\t11521\tWix4UtilCA_A64\tExecXmlFileRollback\t", - "CustomAction:Wix4RegisterEventManifest_A64\t3073\tWix4UtilCA_A64\tWixQuietExec\t", - "CustomAction:Wix4RollbackRegisterEventManifest_A64\t3393\tWix4UtilCA_A64\tWixQuietExec\t", - "CustomAction:Wix4RollbackUnregisterEventManifest_A64\t3329\tWix4UtilCA_A64\tWixQuietExec\t", - "CustomAction:Wix4SchedXmlFile_A64\t1\tWix4UtilCA_A64\tSchedXmlFile\t", - "CustomAction:Wix4UnregisterEventManifest_A64\t3137\tWix4UtilCA_A64\tWixQuietExec\t", - "Wix4EventManifest:Manifest.dll\t[#Manifest.dll]", - "Wix4XmlFile:Config_Manifest.dllMessageFile\t[#Manifest.dll]\t/*/*/*/*[\\[]@messageFileName[\\]]\tmessageFileName\t[Manifest.dll]\t4100\tManifest.dll\t", - "Wix4XmlFile:Config_Manifest.dllResourceFile\t[#Manifest.dll]\t/*/*/*/*[\\[]@resourceFileName[\\]]\tresourceFileName\t[Manifest.dll]\t4100\tManifest.dll\t", - }, results.OrderBy(s => s).ToArray()); - } - - [Fact] - public void CanBuildWithQueries() - { - var folder = TestData.Get(@"TestData\Queries"); - var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); - - var results = build.BuildAndQuery(BuildARM64, "Binary", "CustomAction"); - WixAssert.CompareLineByLine(new[] - { - "Binary:Wix4UtilCA_A64\t[Binary data]", - "CustomAction:Wix4BroadcastEnvironmentChange_A64\t65\tWix4UtilCA_A64\tWixBroadcastEnvironmentChange\t", - "CustomAction:Wix4BroadcastSettingChange_A64\t65\tWix4UtilCA_A64\tWixBroadcastSettingChange\t", - "CustomAction:Wix4CheckRebootRequired_A64\t65\tWix4UtilCA_A64\tWixCheckRebootRequired\t", - "CustomAction:Wix4QueryOsDriverInfo_A64\t257\tWix4UtilCA_A64\tWixQueryOsDriverInfo\t", - "CustomAction:Wix4QueryOsInfo_A64\t257\tWix4UtilCA_A64\tWixQueryOsInfo\t", - }, results.OrderBy(s => s).ToArray()); - } - - [Fact] - public void CanBuildWithXmlConfig() - { - var folder = TestData.Get(@"TestData", "XmlConfig"); - var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); - - var results = build.BuildAndQuery(BuildX64, "Wix4XmlConfig"); - WixAssert.CompareLineByLine(new[] - { - "Wix4XmlConfig:DelElement\t[INSTALLFOLDER]my.xml\t\t//root/sub\txxx\t\t\t289\tDel\t1", - }, results.OrderBy(s => s).ToArray()); - } - - [Fact] - public void CanBuildModuleWithXmlConfig() - { - var folder = TestData.Get(@"TestData", "XmlConfigModule"); - var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); - - var results = build.BuildAndQuery(BuildX64, "Wix4XmlConfig"); - WixAssert.CompareLineByLine(new[] - { - "Wix4XmlConfig:AddElement.047730A5_30FE_4A62_A520_DA9381B8226A\t[my.xml.047730A5_30FE_4A62_A520_DA9381B8226A]\t\t//root/sub\txxx\t\t\t273\tParent.047730A5_30FE_4A62_A520_DA9381B8226A\t1", - "Wix4XmlConfig:ChildElement.047730A5_30FE_4A62_A520_DA9381B8226A\t[my.xml.047730A5_30FE_4A62_A520_DA9381B8226A]\tAddElement.047730A5_30FE_4A62_A520_DA9381B8226A\t\txxx\t\t\t0\tChild.047730A5_30FE_4A62_A520_DA9381B8226A\t1", - }, results.OrderBy(s => s).ToArray()); - } - - [Fact] - public void CanBuildBundleWithSearches() - { - var burnStubPath = TestData.Get(@"TestData\.Data\burn.exe"); - var folder = TestData.Get(@"TestData\BundleWithSearches"); - var rootFolder = TestData.Get(); - var wixext = Path.Combine(rootFolder, "WixToolset.Util.wixext.dll"); - - using (var fs = new DisposableFileSystem()) - { - var baseFolder = fs.GetFolder(); - var intermediateFolder = Path.Combine(baseFolder, "obj"); - var bundlePath = Path.Combine(baseFolder, @"bin\test.exe"); - var baFolderPath = Path.Combine(baseFolder, "ba"); - var extractFolderPath = Path.Combine(baseFolder, "extract"); - - var result = WixRunner.Execute(new[] - { - "build", - Path.Combine(folder, "Bundle.wxs"), - "-ext", wixext, - "-loc", Path.Combine(folder, "Bundle.en-us.wxl"), - "-bindpath", Path.Combine(folder, "data"), - "-intermediateFolder", intermediateFolder, - "-o", bundlePath - }); - - result.AssertSuccess(); - - Assert.True(File.Exists(bundlePath)); -#if TODO - Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.wixpdb"))); -#endif - - var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath); - extractResult.AssertSuccess(); - - var bundleExtensionDatas = extractResult.SelectBundleExtensionDataNodes("/be:BundleExtensionData/be:BundleExtension[@Id='Wix4UtilBundleExtension_X86']"); - Assert.Equal(1, bundleExtensionDatas.Count); - Assert.Equal("" + - "" + - "", bundleExtensionDatas[0].GetTestXml()); - - var utilSearches = extractResult.SelectManifestNodes("/burn:BurnManifest/*[self::burn:ExtensionSearch or self::burn:FileSearch or self::burn:MsiProductSearch or self::burn:RegistrySearch]"); - Assert.Equal(5, utilSearches.Count); - Assert.Equal("", utilSearches[0].GetTestXml()); - Assert.Equal("", utilSearches[1].GetTestXml()); - Assert.Equal("", utilSearches[2].GetTestXml()); - Assert.Equal("", utilSearches[3].GetTestXml()); - Assert.Equal("", utilSearches[4].GetTestXml()); - } - } - - private static void Build(string[] args) - { - var result = WixRunner.Execute(args); - result.AssertSuccess(); - } - - private static void BuildX64(string[] args) - { - var newArgs = args.ToList(); - newArgs.Add("-platform"); - newArgs.Add("x64"); - newArgs.Add("-sw1072"); - - var result = WixRunner.Execute(newArgs.ToArray()); - result.AssertSuccess(); - } - - private static void BuildARM64(string[] args) - { - var newArgs = args.ToList(); - newArgs.Add("-platform"); - newArgs.Add("arm64"); - - var result = WixRunner.Execute(newArgs.ToArray()); - result.AssertSuccess(); - } - } -} diff --git a/src/test/WixToolsetTest.Util/WixToolsetTest.Util.csproj b/src/test/WixToolsetTest.Util/WixToolsetTest.Util.csproj deleted file mode 100644 index e77ecbed..00000000 --- a/src/test/WixToolsetTest.Util/WixToolsetTest.Util.csproj +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - netcoreapp3.1 - false - - - - NU1701 - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Util/WixToolsetTest.Util.v3.ncrunchproject b/src/test/WixToolsetTest.Util/WixToolsetTest.Util.v3.ncrunchproject deleted file mode 100644 index 7b5b2139..00000000 --- a/src/test/WixToolsetTest.Util/WixToolsetTest.Util.v3.ncrunchproject +++ /dev/null @@ -1,5 +0,0 @@ - - - True - - \ 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/PerformanceCounterType.cs b/src/wixext/PerformanceCounterType.cs deleted file mode 100644 index 1e06efd3..00000000 --- a/src/wixext/PerformanceCounterType.cs +++ /dev/null @@ -1,192 +0,0 @@ -// Captured from: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.dll - -namespace System.Diagnostics -{ - public enum PerformanceCounterType - { - // - // Summary: - // An instantaneous counter that shows the most recently observed value in hexadecimal - // format. Used, for example, to maintain a simple count of items or operations. - NumberOfItemsHEX32 = 0, - // - // Summary: - // An instantaneous counter that shows the most recently observed value. Used, for - // example, to maintain a simple count of a very large number of items or operations. - // It is the same as NumberOfItemsHEX32 except that it uses larger fields to accommodate - // larger values. - NumberOfItemsHEX64 = 256, - // - // Summary: - // An instantaneous counter that shows the most recently observed value. Used, for - // example, to maintain a simple count of items or operations. - NumberOfItems32 = 65536, - // - // Summary: - // An instantaneous counter that shows the most recently observed value. Used, for - // example, to maintain a simple count of a very large number of items or operations. - // It is the same as NumberOfItems32 except that it uses larger fields to accommodate - // larger values. - NumberOfItems64 = 65792, - // - // Summary: - // A difference counter that shows the change in the measured attribute between - // the two most recent sample intervals. - CounterDelta32 = 4195328, - // - // Summary: - // A difference counter that shows the change in the measured attribute between - // the two most recent sample intervals. It is the same as the CounterDelta32 counter - // type except that is uses larger fields to accomodate larger values. - CounterDelta64 = 4195584, - // - // Summary: - // An average counter that shows the average number of operations completed in one - // second. When a counter of this type samples the data, each sampling interrupt - // returns one or zero. The counter data is the number of ones that were sampled. - // It measures time in units of ticks of the system performance timer. - SampleCounter = 4260864, - // - // Summary: - // An average counter designed to monitor the average length of a queue to a resource - // over time. It shows the difference between the queue lengths observed during - // the last two sample intervals divided by the duration of the interval. This type - // of counter is typically used to track the number of items that are queued or - // waiting. - CountPerTimeInterval32 = 4523008, - // - // Summary: - // An average counter that monitors the average length of a queue to a resource - // over time. Counters of this type display the difference between the queue lengths - // observed during the last two sample intervals, divided by the duration of the - // interval. This counter type is the same as CountPerTimeInterval32 except that - // it uses larger fields to accommodate larger values. This type of counter is typically - // used to track a high-volume or very large number of items that are queued or - // waiting. - CountPerTimeInterval64 = 4523264, - // - // Summary: - // A difference counter that shows the average number of operations completed during - // each second of the sample interval. Counters of this type measure time in ticks - // of the system clock. - RateOfCountsPerSecond32 = 272696320, - // - // Summary: - // A difference counter that shows the average number of operations completed during - // each second of the sample interval. Counters of this type measure time in ticks - // of the system clock. This counter type is the same as the RateOfCountsPerSecond32 - // type, but it uses larger fields to accommodate larger values to track a high-volume - // number of items or operations per second, such as a byte-transmission rate. - RateOfCountsPerSecond64 = 272696576, - // - // Summary: - // An instantaneous percentage counter that shows the ratio of a subset to its set - // as a percentage. For example, it compares the number of bytes in use on a disk - // to the total number of bytes on the disk. Counters of this type display the current - // percentage only, not an average over time. - RawFraction = 537003008, - // - // Summary: - // A percentage counter that shows the average time that a component is active as - // a percentage of the total sample time. - CounterTimer = 541132032, - // - // Summary: - // A percentage counter that shows the active time of a component as a percentage - // of the total elapsed time of the sample interval. It measures time in units of - // 100 nanoseconds (ns). Counters of this type are designed to measure the activity - // of one component at a time. - Timer100Ns = 542180608, - // - // Summary: - // A percentage counter that shows the average ratio of hits to all operations during - // the last two sample intervals. - SampleFraction = 549585920, - // - // Summary: - // A percentage counter that displays the average percentage of active time observed - // during sample interval. The value of these counters is calculated by monitoring - // the percentage of time that the service was inactive and then subtracting that - // value from 100 percent. - CounterTimerInverse = 557909248, - // - // Summary: - // A percentage counter that shows the average percentage of active time observed - // during the sample interval. - Timer100NsInverse = 558957824, - // - // Summary: - // A percentage counter that displays the active time of one or more components - // as a percentage of the total time of the sample interval. Because the numerator - // records the active time of components operating simultaneously, the resulting - // percentage can exceed 100 percent. - CounterMultiTimer = 574686464, - // - // Summary: - // A percentage counter that shows the active time of one or more components as - // a percentage of the total time of the sample interval. It measures time in 100 - // nanosecond (ns) units. - CounterMultiTimer100Ns = 575735040, - // - // Summary: - // A percentage counter that shows the active time of one or more components as - // a percentage of the total time of the sample interval. It derives the active - // time by measuring the time that the components were not active and subtracting - // the result from 100 percent by the number of objects monitored. - CounterMultiTimerInverse = 591463680, - // - // Summary: - // A percentage counter that shows the active time of one or more components as - // a percentage of the total time of the sample interval. Counters of this type - // measure time in 100 nanosecond (ns) units. They derive the active time by measuring - // the time that the components were not active and subtracting the result from - // multiplying 100 percent by the number of objects monitored. - CounterMultiTimer100NsInverse = 592512256, - // - // Summary: - // An average counter that measures the time it takes, on average, to complete a - // process or operation. Counters of this type display a ratio of the total elapsed - // time of the sample interval to the number of processes or operations completed - // during that time. This counter type measures time in ticks of the system clock. - AverageTimer32 = 805438464, - // - // Summary: - // A difference timer that shows the total time between when the component or process - // started and the time when this value is calculated. - ElapsedTime = 807666944, - // - // Summary: - // An average counter that shows how many items are processed, on average, during - // an operation. Counters of this type display a ratio of the items processed to - // the number of operations completed. The ratio is calculated by comparing the - // number of items processed during the last interval to the number of operations - // completed during the last interval. - AverageCount64 = 1073874176, - // - // Summary: - // A base counter that stores the number of sampling interrupts taken and is used - // as a denominator in the sampling fraction. The sampling fraction is the number - // of samples that were 1 (or true) for a sample interrupt. Check that this value - // is greater than zero before using it as the denominator in a calculation of SampleFraction. - SampleBase = 1073939457, - // - // Summary: - // A base counter that is used in the calculation of time or count averages, such - // as AverageTimer32 and AverageCount64. Stores the denominator for calculating - // a counter to present "time per operation" or "count per operation". - AverageBase = 1073939458, - // - // Summary: - // A base counter that stores the denominator of a counter that presents a general - // arithmetic fraction. Check that this value is greater than zero before using - // it as the denominator in a RawFraction value calculation. - RawBase = 1073939459, - // - // Summary: - // A base counter that indicates the number of items sampled. It is used as the - // denominator in the calculations to get an average among the items sampled when - // taking timings of multiple, but similar items. Used with CounterMultiTimer, CounterMultiTimerInverse, - // CounterMultiTimer100Ns, and CounterMultiTimer100NsInverse. - CounterMultiBase = 1107494144 - } -} diff --git a/src/wixext/Symbols/EventManifestSymbol.cs b/src/wixext/Symbols/EventManifestSymbol.cs deleted file mode 100644 index ccd3c899..00000000 --- a/src/wixext/Symbols/EventManifestSymbol.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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition EventManifest = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.EventManifest.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(EventManifestSymbolFields.ComponentRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(EventManifestSymbolFields.File), IntermediateFieldType.String), - }, - typeof(EventManifestSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum EventManifestSymbolFields - { - ComponentRef, - File, - } - - public class EventManifestSymbol : IntermediateSymbol - { - public EventManifestSymbol() : base(UtilSymbolDefinitions.EventManifest, null, null) - { - } - - public EventManifestSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.EventManifest, sourceLineNumber, id) - { - } - - public IntermediateField this[EventManifestSymbolFields index] => this.Fields[(int)index]; - - public string ComponentRef - { - get => this.Fields[(int)EventManifestSymbolFields.ComponentRef].AsString(); - set => this.Set((int)EventManifestSymbolFields.ComponentRef, value); - } - - public string File - { - get => this.Fields[(int)EventManifestSymbolFields.File].AsString(); - set => this.Set((int)EventManifestSymbolFields.File, value); - } - } -} \ No newline at end of file diff --git a/src/wixext/Symbols/FileSharePermissionsSymbol.cs b/src/wixext/Symbols/FileSharePermissionsSymbol.cs deleted file mode 100644 index 3db92f22..00000000 --- a/src/wixext/Symbols/FileSharePermissionsSymbol.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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition FileSharePermissions = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.FileSharePermissions.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(FileSharePermissionsSymbolFields.FileShareRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(FileSharePermissionsSymbolFields.UserRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(FileSharePermissionsSymbolFields.Permissions), IntermediateFieldType.Number), - }, - typeof(FileSharePermissionsSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum FileSharePermissionsSymbolFields - { - FileShareRef, - UserRef, - Permissions, - } - - public class FileSharePermissionsSymbol : IntermediateSymbol - { - public FileSharePermissionsSymbol() : base(UtilSymbolDefinitions.FileSharePermissions, null, null) - { - } - - public FileSharePermissionsSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.FileSharePermissions, sourceLineNumber, id) - { - } - - public IntermediateField this[FileSharePermissionsSymbolFields index] => this.Fields[(int)index]; - - public string FileShareRef - { - get => this.Fields[(int)FileSharePermissionsSymbolFields.FileShareRef].AsString(); - set => this.Set((int)FileSharePermissionsSymbolFields.FileShareRef, value); - } - - public string UserRef - { - get => this.Fields[(int)FileSharePermissionsSymbolFields.UserRef].AsString(); - set => this.Set((int)FileSharePermissionsSymbolFields.UserRef, value); - } - - public int Permissions - { - get => this.Fields[(int)FileSharePermissionsSymbolFields.Permissions].AsNumber(); - set => this.Set((int)FileSharePermissionsSymbolFields.Permissions, value); - } - } -} \ No newline at end of file diff --git a/src/wixext/Symbols/FileShareSymbol.cs b/src/wixext/Symbols/FileShareSymbol.cs deleted file mode 100644 index c956ff42..00000000 --- a/src/wixext/Symbols/FileShareSymbol.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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition FileShare = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.FileShare.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(FileShareSymbolFields.ShareName), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(FileShareSymbolFields.ComponentRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(FileShareSymbolFields.Description), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(FileShareSymbolFields.DirectoryRef), IntermediateFieldType.String), - }, - typeof(FileShareSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum FileShareSymbolFields - { - ShareName, - ComponentRef, - Description, - DirectoryRef, - } - - public class FileShareSymbol : IntermediateSymbol - { - public FileShareSymbol() : base(UtilSymbolDefinitions.FileShare, null, null) - { - } - - public FileShareSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.FileShare, sourceLineNumber, id) - { - } - - public IntermediateField this[FileShareSymbolFields index] => this.Fields[(int)index]; - - public string ShareName - { - get => this.Fields[(int)FileShareSymbolFields.ShareName].AsString(); - set => this.Set((int)FileShareSymbolFields.ShareName, value); - } - - public string ComponentRef - { - get => this.Fields[(int)FileShareSymbolFields.ComponentRef].AsString(); - set => this.Set((int)FileShareSymbolFields.ComponentRef, value); - } - - public string Description - { - get => this.Fields[(int)FileShareSymbolFields.Description].AsString(); - set => this.Set((int)FileShareSymbolFields.Description, value); - } - - public string DirectoryRef - { - get => this.Fields[(int)FileShareSymbolFields.DirectoryRef].AsString(); - set => this.Set((int)FileShareSymbolFields.DirectoryRef, value); - } - } -} \ No newline at end of file diff --git a/src/wixext/Symbols/GroupSymbol.cs b/src/wixext/Symbols/GroupSymbol.cs deleted file mode 100644 index b378db44..00000000 --- a/src/wixext/Symbols/GroupSymbol.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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition Group = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.Group.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(GroupSymbolFields.ComponentRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(GroupSymbolFields.Name), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(GroupSymbolFields.Domain), IntermediateFieldType.String), - }, - typeof(GroupSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum GroupSymbolFields - { - ComponentRef, - Name, - Domain, - } - - public class GroupSymbol : IntermediateSymbol - { - public GroupSymbol() : base(UtilSymbolDefinitions.Group, null, null) - { - } - - public GroupSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.Group, sourceLineNumber, id) - { - } - - public IntermediateField this[GroupSymbolFields index] => this.Fields[(int)index]; - - public string ComponentRef - { - get => this.Fields[(int)GroupSymbolFields.ComponentRef].AsString(); - set => this.Set((int)GroupSymbolFields.ComponentRef, value); - } - - public string Name - { - get => this.Fields[(int)GroupSymbolFields.Name].AsString(); - set => this.Set((int)GroupSymbolFields.Name, value); - } - - public string Domain - { - get => this.Fields[(int)GroupSymbolFields.Domain].AsString(); - set => this.Set((int)GroupSymbolFields.Domain, value); - } - } -} \ No newline at end of file diff --git a/src/wixext/Symbols/PerfmonManifestSymbol.cs b/src/wixext/Symbols/PerfmonManifestSymbol.cs deleted file mode 100644 index 03fef14e..00000000 --- a/src/wixext/Symbols/PerfmonManifestSymbol.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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition PerfmonManifest = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.PerfmonManifest.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(PerfmonManifestSymbolFields.ComponentRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(PerfmonManifestSymbolFields.File), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(PerfmonManifestSymbolFields.ResourceFileDirectory), IntermediateFieldType.String), - }, - typeof(PerfmonManifestSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum PerfmonManifestSymbolFields - { - ComponentRef, - File, - ResourceFileDirectory, - } - - public class PerfmonManifestSymbol : IntermediateSymbol - { - public PerfmonManifestSymbol() : base(UtilSymbolDefinitions.PerfmonManifest, null, null) - { - } - - public PerfmonManifestSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.PerfmonManifest, sourceLineNumber, id) - { - } - - public IntermediateField this[PerfmonManifestSymbolFields index] => this.Fields[(int)index]; - - public string ComponentRef - { - get => this.Fields[(int)PerfmonManifestSymbolFields.ComponentRef].AsString(); - set => this.Set((int)PerfmonManifestSymbolFields.ComponentRef, value); - } - - public string File - { - get => this.Fields[(int)PerfmonManifestSymbolFields.File].AsString(); - set => this.Set((int)PerfmonManifestSymbolFields.File, value); - } - - public string ResourceFileDirectory - { - get => this.Fields[(int)PerfmonManifestSymbolFields.ResourceFileDirectory].AsString(); - set => this.Set((int)PerfmonManifestSymbolFields.ResourceFileDirectory, value); - } - } -} \ No newline at end of file diff --git a/src/wixext/Symbols/PerfmonSymbol.cs b/src/wixext/Symbols/PerfmonSymbol.cs deleted file mode 100644 index 6784ebd1..00000000 --- a/src/wixext/Symbols/PerfmonSymbol.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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition Perfmon = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.Perfmon.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(PerfmonSymbolFields.ComponentRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(PerfmonSymbolFields.File), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(PerfmonSymbolFields.Name), IntermediateFieldType.String), - }, - typeof(PerfmonSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum PerfmonSymbolFields - { - ComponentRef, - File, - Name, - } - - public class PerfmonSymbol : IntermediateSymbol - { - public PerfmonSymbol() : base(UtilSymbolDefinitions.Perfmon, null, null) - { - } - - public PerfmonSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.Perfmon, sourceLineNumber, id) - { - } - - public IntermediateField this[PerfmonSymbolFields index] => this.Fields[(int)index]; - - public string ComponentRef - { - get => this.Fields[(int)PerfmonSymbolFields.ComponentRef].AsString(); - set => this.Set((int)PerfmonSymbolFields.ComponentRef, value); - } - - public string File - { - get => this.Fields[(int)PerfmonSymbolFields.File].AsString(); - set => this.Set((int)PerfmonSymbolFields.File, value); - } - - public string Name - { - get => this.Fields[(int)PerfmonSymbolFields.Name].AsString(); - set => this.Set((int)PerfmonSymbolFields.Name, value); - } - } -} \ No newline at end of file diff --git a/src/wixext/Symbols/PerformanceCategorySymbol.cs b/src/wixext/Symbols/PerformanceCategorySymbol.cs deleted file mode 100644 index 5ecf388c..00000000 --- a/src/wixext/Symbols/PerformanceCategorySymbol.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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition PerformanceCategory = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.PerformanceCategory.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(PerformanceCategorySymbolFields.ComponentRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(PerformanceCategorySymbolFields.Name), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(PerformanceCategorySymbolFields.IniData), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(PerformanceCategorySymbolFields.ConstantData), IntermediateFieldType.String), - }, - typeof(PerformanceCategorySymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum PerformanceCategorySymbolFields - { - ComponentRef, - Name, - IniData, - ConstantData, - } - - public class PerformanceCategorySymbol : IntermediateSymbol - { - public PerformanceCategorySymbol() : base(UtilSymbolDefinitions.PerformanceCategory, null, null) - { - } - - public PerformanceCategorySymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.PerformanceCategory, sourceLineNumber, id) - { - } - - public IntermediateField this[PerformanceCategorySymbolFields index] => this.Fields[(int)index]; - - public string ComponentRef - { - get => this.Fields[(int)PerformanceCategorySymbolFields.ComponentRef].AsString(); - set => this.Set((int)PerformanceCategorySymbolFields.ComponentRef, value); - } - - public string Name - { - get => this.Fields[(int)PerformanceCategorySymbolFields.Name].AsString(); - set => this.Set((int)PerformanceCategorySymbolFields.Name, value); - } - - public string IniData - { - get => this.Fields[(int)PerformanceCategorySymbolFields.IniData].AsString(); - set => this.Set((int)PerformanceCategorySymbolFields.IniData, value); - } - - public string ConstantData - { - get => this.Fields[(int)PerformanceCategorySymbolFields.ConstantData].AsString(); - set => this.Set((int)PerformanceCategorySymbolFields.ConstantData, value); - } - } -} \ No newline at end of file diff --git a/src/wixext/Symbols/SecureObjectsSymbol.cs b/src/wixext/Symbols/SecureObjectsSymbol.cs deleted file mode 100644 index 25fc6dca..00000000 --- a/src/wixext/Symbols/SecureObjectsSymbol.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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition SecureObjects = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.SecureObjects.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.SecureObject), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.Table), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.Domain), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.User), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.Attributes), IntermediateFieldType.Number), - new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.Permission), IntermediateFieldType.Number), - new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.ComponentRef), IntermediateFieldType.String), - }, - typeof(SecureObjectsSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using System; - using WixToolset.Data; - - public enum SecureObjectsSymbolFields - { - SecureObject, - Table, - Domain, - User, - Attributes, - Permission, - ComponentRef, - } - - [Flags] - public enum WixPermissionExAttributes - { - None = 0x0, - Inheritable = 0x01 - } - - public class SecureObjectsSymbol : IntermediateSymbol - { - public SecureObjectsSymbol() : base(UtilSymbolDefinitions.SecureObjects, null, null) - { - } - - public SecureObjectsSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.SecureObjects, sourceLineNumber, id) - { - } - - public IntermediateField this[SecureObjectsSymbolFields index] => this.Fields[(int)index]; - - public string SecureObject - { - get => this.Fields[(int)SecureObjectsSymbolFields.SecureObject].AsString(); - set => this.Set((int)SecureObjectsSymbolFields.SecureObject, value); - } - - public string Table - { - get => this.Fields[(int)SecureObjectsSymbolFields.Table].AsString(); - set => this.Set((int)SecureObjectsSymbolFields.Table, value); - } - - public string Domain - { - get => this.Fields[(int)SecureObjectsSymbolFields.Domain].AsString(); - set => this.Set((int)SecureObjectsSymbolFields.Domain, value); - } - - public string User - { - get => this.Fields[(int)SecureObjectsSymbolFields.User].AsString(); - set => this.Set((int)SecureObjectsSymbolFields.User, value); - } - - public WixPermissionExAttributes Attributes - { - get => (WixPermissionExAttributes)this.Fields[(int)SecureObjectsSymbolFields.Attributes].AsNumber(); - set => this.Set((int)SecureObjectsSymbolFields.Attributes, (int)value); - } - - public int? Permission - { - get => this.Fields[(int)SecureObjectsSymbolFields.Permission].AsNullableNumber(); - set => this.Set((int)SecureObjectsSymbolFields.Permission, value); - } - - public string ComponentRef - { - get => this.Fields[(int)SecureObjectsSymbolFields.ComponentRef].AsString(); - set => this.Set((int)SecureObjectsSymbolFields.ComponentRef, value); - } - } -} \ No newline at end of file diff --git a/src/wixext/Symbols/ServiceConfigSymbol.cs b/src/wixext/Symbols/ServiceConfigSymbol.cs deleted file mode 100644 index 3a877f9b..00000000 --- a/src/wixext/Symbols/ServiceConfigSymbol.cs +++ /dev/null @@ -1,119 +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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition ServiceConfig = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.ServiceConfig.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.ServiceName), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.ComponentRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.NewService), IntermediateFieldType.Number), - new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.FirstFailureActionType), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.SecondFailureActionType), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.ThirdFailureActionType), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.ResetPeriodInDays), IntermediateFieldType.Number), - new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.RestartServiceDelayInSeconds), IntermediateFieldType.Number), - new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.ProgramCommandLine), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.RebootMessage), IntermediateFieldType.String), - }, - typeof(ServiceConfigSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum ServiceConfigSymbolFields - { - ServiceName, - ComponentRef, - NewService, - FirstFailureActionType, - SecondFailureActionType, - ThirdFailureActionType, - ResetPeriodInDays, - RestartServiceDelayInSeconds, - ProgramCommandLine, - RebootMessage, - } - - public class ServiceConfigSymbol : IntermediateSymbol - { - public ServiceConfigSymbol() : base(UtilSymbolDefinitions.ServiceConfig, null, null) - { - } - - public ServiceConfigSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.ServiceConfig, sourceLineNumber, id) - { - } - - public IntermediateField this[ServiceConfigSymbolFields index] => this.Fields[(int)index]; - - public string ServiceName - { - get => this.Fields[(int)ServiceConfigSymbolFields.ServiceName].AsString(); - set => this.Set((int)ServiceConfigSymbolFields.ServiceName, value); - } - - public string ComponentRef - { - get => this.Fields[(int)ServiceConfigSymbolFields.ComponentRef].AsString(); - set => this.Set((int)ServiceConfigSymbolFields.ComponentRef, value); - } - - public int NewService - { - get => this.Fields[(int)ServiceConfigSymbolFields.NewService].AsNumber(); - set => this.Set((int)ServiceConfigSymbolFields.NewService, value); - } - - public string FirstFailureActionType - { - get => this.Fields[(int)ServiceConfigSymbolFields.FirstFailureActionType].AsString(); - set => this.Set((int)ServiceConfigSymbolFields.FirstFailureActionType, value); - } - - public string SecondFailureActionType - { - get => this.Fields[(int)ServiceConfigSymbolFields.SecondFailureActionType].AsString(); - set => this.Set((int)ServiceConfigSymbolFields.SecondFailureActionType, value); - } - - public string ThirdFailureActionType - { - get => this.Fields[(int)ServiceConfigSymbolFields.ThirdFailureActionType].AsString(); - set => this.Set((int)ServiceConfigSymbolFields.ThirdFailureActionType, value); - } - - public int? ResetPeriodInDays - { - get => this.Fields[(int)ServiceConfigSymbolFields.ResetPeriodInDays].AsNullableNumber(); - set => this.Set((int)ServiceConfigSymbolFields.ResetPeriodInDays, value); - } - - public int? RestartServiceDelayInSeconds - { - get => this.Fields[(int)ServiceConfigSymbolFields.RestartServiceDelayInSeconds].AsNullableNumber(); - set => this.Set((int)ServiceConfigSymbolFields.RestartServiceDelayInSeconds, value); - } - - public string ProgramCommandLine - { - get => this.Fields[(int)ServiceConfigSymbolFields.ProgramCommandLine].AsString(); - set => this.Set((int)ServiceConfigSymbolFields.ProgramCommandLine, value); - } - - public string RebootMessage - { - get => this.Fields[(int)ServiceConfigSymbolFields.RebootMessage].AsString(); - set => this.Set((int)ServiceConfigSymbolFields.RebootMessage, value); - } - } -} \ No newline at end of file diff --git a/src/wixext/Symbols/UserGroupSymbol.cs b/src/wixext/Symbols/UserGroupSymbol.cs deleted file mode 100644 index c8f3998e..00000000 --- a/src/wixext/Symbols/UserGroupSymbol.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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition UserGroup = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.UserGroup.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(UserGroupSymbolFields.UserRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(UserGroupSymbolFields.GroupRef), IntermediateFieldType.String), - }, - typeof(UserGroupSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum UserGroupSymbolFields - { - UserRef, - GroupRef, - } - - public class UserGroupSymbol : IntermediateSymbol - { - public UserGroupSymbol() : base(UtilSymbolDefinitions.UserGroup, null, null) - { - } - - public UserGroupSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.UserGroup, sourceLineNumber, id) - { - } - - public IntermediateField this[UserGroupSymbolFields index] => this.Fields[(int)index]; - - public string UserRef - { - get => this.Fields[(int)UserGroupSymbolFields.UserRef].AsString(); - set => this.Set((int)UserGroupSymbolFields.UserRef, value); - } - - public string GroupRef - { - get => this.Fields[(int)UserGroupSymbolFields.GroupRef].AsString(); - set => this.Set((int)UserGroupSymbolFields.GroupRef, value); - } - } -} \ No newline at end of file diff --git a/src/wixext/Symbols/UserSymbol.cs b/src/wixext/Symbols/UserSymbol.cs deleted file mode 100644 index 5f00064b..00000000 --- a/src/wixext/Symbols/UserSymbol.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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition User = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.User.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(UserSymbolFields.ComponentRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(UserSymbolFields.Name), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(UserSymbolFields.Domain), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(UserSymbolFields.Password), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(UserSymbolFields.Attributes), IntermediateFieldType.Number), - }, - typeof(UserSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum UserSymbolFields - { - ComponentRef, - Name, - Domain, - Password, - Attributes, - } - - public class UserSymbol : IntermediateSymbol - { - public UserSymbol() : base(UtilSymbolDefinitions.User, null, null) - { - } - - public UserSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.User, sourceLineNumber, id) - { - } - - public IntermediateField this[UserSymbolFields index] => this.Fields[(int)index]; - - public string ComponentRef - { - get => this.Fields[(int)UserSymbolFields.ComponentRef].AsString(); - set => this.Set((int)UserSymbolFields.ComponentRef, value); - } - - public string Name - { - get => this.Fields[(int)UserSymbolFields.Name].AsString(); - set => this.Set((int)UserSymbolFields.Name, value); - } - - public string Domain - { - get => this.Fields[(int)UserSymbolFields.Domain].AsString(); - set => this.Set((int)UserSymbolFields.Domain, value); - } - - public string Password - { - get => this.Fields[(int)UserSymbolFields.Password].AsString(); - set => this.Set((int)UserSymbolFields.Password, value); - } - - public int Attributes - { - get => this.Fields[(int)UserSymbolFields.Attributes].AsNumber(); - set => this.Set((int)UserSymbolFields.Attributes, value); - } - } -} \ No newline at end of file diff --git a/src/wixext/Symbols/UtilSymbolDefinitions.cs b/src/wixext/Symbols/UtilSymbolDefinitions.cs deleted file mode 100644 index 72091c3b..00000000 --- a/src/wixext/Symbols/UtilSymbolDefinitions.cs +++ /dev/null @@ -1,125 +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.Util -{ - using System; - using WixToolset.Data; - using WixToolset.Data.Burn; - - public enum UtilSymbolDefinitionType - { - EventManifest, - FileShare, - FileSharePermissions, - Group, - Perfmon, - PerfmonManifest, - PerformanceCategory, - SecureObjects, - ServiceConfig, - User, - UserGroup, - WixCloseApplication, - WixFormatFiles, - WixInternetShortcut, - WixRemoveFolderEx, - WixRemoveRegistryKeyEx, - WixRestartResource, - WixTouchFile, - WixWindowsFeatureSearch, - XmlConfig, - XmlFile, - } - - public static partial class UtilSymbolDefinitions - { - public static readonly Version Version = new Version("4.0.0"); - - public static IntermediateSymbolDefinition ByName(string name) - { - if (!Enum.TryParse(name, out UtilSymbolDefinitionType type)) - { - return null; - } - - return ByType(type); - } - - public static IntermediateSymbolDefinition ByType(UtilSymbolDefinitionType type) - { - switch (type) - { - case UtilSymbolDefinitionType.EventManifest: - return UtilSymbolDefinitions.EventManifest; - - case UtilSymbolDefinitionType.FileShare: - return UtilSymbolDefinitions.FileShare; - - case UtilSymbolDefinitionType.FileSharePermissions: - return UtilSymbolDefinitions.FileSharePermissions; - - case UtilSymbolDefinitionType.Group: - return UtilSymbolDefinitions.Group; - - case UtilSymbolDefinitionType.Perfmon: - return UtilSymbolDefinitions.Perfmon; - - case UtilSymbolDefinitionType.PerfmonManifest: - return UtilSymbolDefinitions.PerfmonManifest; - - case UtilSymbolDefinitionType.PerformanceCategory: - return UtilSymbolDefinitions.PerformanceCategory; - - case UtilSymbolDefinitionType.SecureObjects: - return UtilSymbolDefinitions.SecureObjects; - - case UtilSymbolDefinitionType.ServiceConfig: - return UtilSymbolDefinitions.ServiceConfig; - - case UtilSymbolDefinitionType.User: - return UtilSymbolDefinitions.User; - - case UtilSymbolDefinitionType.UserGroup: - return UtilSymbolDefinitions.UserGroup; - - case UtilSymbolDefinitionType.WixCloseApplication: - return UtilSymbolDefinitions.WixCloseApplication; - - case UtilSymbolDefinitionType.WixFormatFiles: - return UtilSymbolDefinitions.WixFormatFiles; - - case UtilSymbolDefinitionType.WixInternetShortcut: - return UtilSymbolDefinitions.WixInternetShortcut; - - case UtilSymbolDefinitionType.WixRemoveFolderEx: - return UtilSymbolDefinitions.WixRemoveFolderEx; - - case UtilSymbolDefinitionType.WixRemoveRegistryKeyEx: - return UtilSymbolDefinitions.WixRemoveRegistryKeyEx; - - case UtilSymbolDefinitionType.WixRestartResource: - return UtilSymbolDefinitions.WixRestartResource; - - case UtilSymbolDefinitionType.WixTouchFile: - return UtilSymbolDefinitions.WixTouchFile; - - case UtilSymbolDefinitionType.WixWindowsFeatureSearch: - return UtilSymbolDefinitions.WixWindowsFeatureSearch; - - case UtilSymbolDefinitionType.XmlConfig: - return UtilSymbolDefinitions.XmlConfig; - - case UtilSymbolDefinitionType.XmlFile: - return UtilSymbolDefinitions.XmlFile; - - default: - throw new ArgumentOutOfRangeException(nameof(type)); - } - } - - static UtilSymbolDefinitions() - { - WixWindowsFeatureSearch.AddTag(BurnConstants.BundleExtensionSearchSymbolDefinitionTag); - } - } -} diff --git a/src/wixext/Symbols/WixCloseApplicationSymbol.cs b/src/wixext/Symbols/WixCloseApplicationSymbol.cs deleted file mode 100644 index 0738e3e4..00000000 --- a/src/wixext/Symbols/WixCloseApplicationSymbol.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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition WixCloseApplication = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.WixCloseApplication.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Target), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Description), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Condition), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Attributes), IntermediateFieldType.Number), - new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Sequence), IntermediateFieldType.Number), - new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Property), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.TerminateExitCode), IntermediateFieldType.Number), - new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Timeout), IntermediateFieldType.Number), - }, - typeof(WixCloseApplicationSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum WixCloseApplicationSymbolFields - { - Target, - Description, - Condition, - Attributes, - Sequence, - Property, - TerminateExitCode, - Timeout, - } - - public class WixCloseApplicationSymbol : IntermediateSymbol - { - public WixCloseApplicationSymbol() : base(UtilSymbolDefinitions.WixCloseApplication, null, null) - { - } - - public WixCloseApplicationSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixCloseApplication, sourceLineNumber, id) - { - } - - public IntermediateField this[WixCloseApplicationSymbolFields index] => this.Fields[(int)index]; - - public string Target - { - get => this.Fields[(int)WixCloseApplicationSymbolFields.Target].AsString(); - set => this.Set((int)WixCloseApplicationSymbolFields.Target, value); - } - - public string Description - { - get => this.Fields[(int)WixCloseApplicationSymbolFields.Description].AsString(); - set => this.Set((int)WixCloseApplicationSymbolFields.Description, value); - } - - public string Condition - { - get => this.Fields[(int)WixCloseApplicationSymbolFields.Condition].AsString(); - set => this.Set((int)WixCloseApplicationSymbolFields.Condition, value); - } - - public int Attributes - { - get => this.Fields[(int)WixCloseApplicationSymbolFields.Attributes].AsNumber(); - set => this.Set((int)WixCloseApplicationSymbolFields.Attributes, value); - } - - public int? Sequence - { - get => this.Fields[(int)WixCloseApplicationSymbolFields.Sequence].AsNullableNumber(); - set => this.Set((int)WixCloseApplicationSymbolFields.Sequence, value); - } - - public string Property - { - get => this.Fields[(int)WixCloseApplicationSymbolFields.Property].AsString(); - set => this.Set((int)WixCloseApplicationSymbolFields.Property, value); - } - - public int? TerminateExitCode - { - get => this.Fields[(int)WixCloseApplicationSymbolFields.TerminateExitCode].AsNullableNumber(); - set => this.Set((int)WixCloseApplicationSymbolFields.TerminateExitCode, value); - } - - public int? Timeout - { - get => this.Fields[(int)WixCloseApplicationSymbolFields.Timeout].AsNullableNumber(); - set => this.Set((int)WixCloseApplicationSymbolFields.Timeout, value); - } - } -} \ No newline at end of file diff --git a/src/wixext/Symbols/WixFormatFilesSymbol.cs b/src/wixext/Symbols/WixFormatFilesSymbol.cs deleted file mode 100644 index 38a9b8ff..00000000 --- a/src/wixext/Symbols/WixFormatFilesSymbol.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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition WixFormatFiles = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.WixFormatFiles.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(WixFormatFilesSymbolFields.BinaryRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixFormatFilesSymbolFields.FileRef), IntermediateFieldType.String), - }, - typeof(WixFormatFilesSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum WixFormatFilesSymbolFields - { - BinaryRef, - FileRef, - } - - public class WixFormatFilesSymbol : IntermediateSymbol - { - public WixFormatFilesSymbol() : base(UtilSymbolDefinitions.WixFormatFiles, null, null) - { - } - - public WixFormatFilesSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixFormatFiles, sourceLineNumber, id) - { - } - - public IntermediateField this[WixFormatFilesSymbolFields index] => this.Fields[(int)index]; - - public string BinaryRef - { - get => this.Fields[(int)WixFormatFilesSymbolFields.BinaryRef].AsString(); - set => this.Set((int)WixFormatFilesSymbolFields.BinaryRef, value); - } - - public string FileRef - { - get => this.Fields[(int)WixFormatFilesSymbolFields.FileRef].AsString(); - set => this.Set((int)WixFormatFilesSymbolFields.FileRef, value); - } - } -} \ No newline at end of file diff --git a/src/wixext/Symbols/WixInternetShortcutSymbol.cs b/src/wixext/Symbols/WixInternetShortcutSymbol.cs deleted file mode 100644 index e8265e02..00000000 --- a/src/wixext/Symbols/WixInternetShortcutSymbol.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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition WixInternetShortcut = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.WixInternetShortcut.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.ComponentRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.DirectoryRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.Name), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.Target), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.Attributes), IntermediateFieldType.Number), - new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.IconFile), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.IconIndex), IntermediateFieldType.Number), - }, - typeof(WixInternetShortcutSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum WixInternetShortcutSymbolFields - { - ComponentRef, - DirectoryRef, - Name, - Target, - Attributes, - IconFile, - IconIndex, - } - - public class WixInternetShortcutSymbol : IntermediateSymbol - { - public WixInternetShortcutSymbol() : base(UtilSymbolDefinitions.WixInternetShortcut, null, null) - { - } - - public WixInternetShortcutSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixInternetShortcut, sourceLineNumber, id) - { - } - - public IntermediateField this[WixInternetShortcutSymbolFields index] => this.Fields[(int)index]; - - public string ComponentRef - { - get => this.Fields[(int)WixInternetShortcutSymbolFields.ComponentRef].AsString(); - set => this.Set((int)WixInternetShortcutSymbolFields.ComponentRef, value); - } - - public string DirectoryRef - { - get => this.Fields[(int)WixInternetShortcutSymbolFields.DirectoryRef].AsString(); - set => this.Set((int)WixInternetShortcutSymbolFields.DirectoryRef, value); - } - - public string Name - { - get => this.Fields[(int)WixInternetShortcutSymbolFields.Name].AsString(); - set => this.Set((int)WixInternetShortcutSymbolFields.Name, value); - } - - public string Target - { - get => this.Fields[(int)WixInternetShortcutSymbolFields.Target].AsString(); - set => this.Set((int)WixInternetShortcutSymbolFields.Target, value); - } - - public int Attributes - { - get => this.Fields[(int)WixInternetShortcutSymbolFields.Attributes].AsNumber(); - set => this.Set((int)WixInternetShortcutSymbolFields.Attributes, value); - } - - public string IconFile - { - get => this.Fields[(int)WixInternetShortcutSymbolFields.IconFile].AsString(); - set => this.Set((int)WixInternetShortcutSymbolFields.IconFile, value); - } - - public int? IconIndex - { - get => this.Fields[(int)WixInternetShortcutSymbolFields.IconIndex].AsNullableNumber(); - set => this.Set((int)WixInternetShortcutSymbolFields.IconIndex, value); - } - } -} \ No newline at end of file diff --git a/src/wixext/Symbols/WixRemoveFolderExSymbol.cs b/src/wixext/Symbols/WixRemoveFolderExSymbol.cs deleted file mode 100644 index 86352b6c..00000000 --- a/src/wixext/Symbols/WixRemoveFolderExSymbol.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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition WixRemoveFolderEx = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.WixRemoveFolderEx.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.ComponentRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.Property), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.InstallMode), IntermediateFieldType.Number), - new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.Condition), IntermediateFieldType.String), - }, - typeof(WixRemoveFolderExSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum WixRemoveFolderExSymbolFields - { - ComponentRef, - Property, - InstallMode, - Condition, - } - - public enum WixRemoveFolderExInstallMode - { - Install = 1, - Uninstall = 2, - Both = 3, - } - - public class WixRemoveFolderExSymbol : IntermediateSymbol - { - public WixRemoveFolderExSymbol() : base(UtilSymbolDefinitions.WixRemoveFolderEx, null, null) - { - } - - public WixRemoveFolderExSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixRemoveFolderEx, sourceLineNumber, id) - { - } - - public IntermediateField this[WixRemoveFolderExSymbolFields index] => this.Fields[(int)index]; - - public string ComponentRef - { - get => this.Fields[(int)WixRemoveFolderExSymbolFields.ComponentRef].AsString(); - set => this.Set((int)WixRemoveFolderExSymbolFields.ComponentRef, value); - } - - public string Property - { - get => this.Fields[(int)WixRemoveFolderExSymbolFields.Property].AsString(); - set => this.Set((int)WixRemoveFolderExSymbolFields.Property, value); - } - - public WixRemoveFolderExInstallMode InstallMode - { - get => (WixRemoveFolderExInstallMode)this.Fields[(int)WixRemoveFolderExSymbolFields.InstallMode].AsNumber(); - set => this.Set((int)WixRemoveFolderExSymbolFields.InstallMode, (int)value); - } - - public string Condition - { - get => this.Fields[(int)WixRemoveFolderExSymbolFields.Condition].AsString(); - set => this.Set((int)WixRemoveFolderExSymbolFields.Condition, value); - } - } -} \ No newline at end of file diff --git a/src/wixext/Symbols/WixRemoveRegistryKeyExSymbol.cs b/src/wixext/Symbols/WixRemoveRegistryKeyExSymbol.cs deleted file mode 100644 index 8e4bd212..00000000 --- a/src/wixext/Symbols/WixRemoveRegistryKeyExSymbol.cs +++ /dev/null @@ -1,86 +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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition WixRemoveRegistryKeyEx = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.WixRemoveRegistryKeyEx.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(WixRemoveRegistryKeyExSymbolFields.ComponentRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixRemoveRegistryKeyExSymbolFields.Root), IntermediateFieldType.Number), - new IntermediateFieldDefinition(nameof(WixRemoveRegistryKeyExSymbolFields.Key), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixRemoveRegistryKeyExSymbolFields.InstallMode), IntermediateFieldType.Number), - new IntermediateFieldDefinition(nameof(WixRemoveRegistryKeyExSymbolFields.Condition), IntermediateFieldType.String), - }, - typeof(WixRemoveRegistryKeyExSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - using WixToolset.Data.Symbols; - - public enum WixRemoveRegistryKeyExSymbolFields - { - ComponentRef, - Root, - Key, - InstallMode, - Condition, - } - - public enum WixRemoveRegistryKeyExInstallMode - { - Install = 1, - Uninstall = 2, - } - - public class WixRemoveRegistryKeyExSymbol : IntermediateSymbol - { - public WixRemoveRegistryKeyExSymbol() : base(UtilSymbolDefinitions.WixRemoveRegistryKeyEx, null, null) - { - } - - public WixRemoveRegistryKeyExSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixRemoveRegistryKeyEx, sourceLineNumber, id) - { - } - - public IntermediateField this[WixRemoveRegistryKeyExSymbolFields index] => this.Fields[(int)index]; - - public string ComponentRef - { - get => this.Fields[(int)WixRemoveRegistryKeyExSymbolFields.ComponentRef].AsString(); - set => this.Set((int)WixRemoveRegistryKeyExSymbolFields.ComponentRef, value); - } - - public RegistryRootType Root - { - get => (RegistryRootType)this.Fields[(int)WixRemoveRegistryKeyExSymbolFields.Root].AsNumber(); - set => this.Set((int)WixRemoveRegistryKeyExSymbolFields.Root, (int)value); - } - - public string Key - { - get => (string)this.Fields[(int)WixRemoveRegistryKeyExSymbolFields.Key]; - set => this.Set((int)WixRemoveRegistryKeyExSymbolFields.Key, value); - } - - public WixRemoveRegistryKeyExInstallMode InstallMode - { - get => (WixRemoveRegistryKeyExInstallMode)this.Fields[(int)WixRemoveRegistryKeyExSymbolFields.InstallMode].AsNumber(); - set => this.Set((int)WixRemoveRegistryKeyExSymbolFields.InstallMode, (int)value); - } - - public string Condition - { - get => this.Fields[(int)WixRemoveRegistryKeyExSymbolFields.Condition].AsString(); - set => this.Set((int)WixRemoveRegistryKeyExSymbolFields.Condition, value); - } - } -} diff --git a/src/wixext/Symbols/WixRestartResourceSymbol.cs b/src/wixext/Symbols/WixRestartResourceSymbol.cs deleted file mode 100644 index 01b92b63..00000000 --- a/src/wixext/Symbols/WixRestartResourceSymbol.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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition WixRestartResource = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.WixRestartResource.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(WixRestartResourceSymbolFields.ComponentRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixRestartResourceSymbolFields.Resource), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixRestartResourceSymbolFields.Attributes), IntermediateFieldType.Number), - }, - typeof(WixRestartResourceSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum WixRestartResourceSymbolFields - { - ComponentRef, - Resource, - Attributes, - } - - public enum WixRestartResourceAttributes - { - Filename = 1, - ProcessName, - ServiceName, - TypeMask = 0xf, - } - - public class WixRestartResourceSymbol : IntermediateSymbol - { - public WixRestartResourceSymbol() : base(UtilSymbolDefinitions.WixRestartResource, null, null) - { - } - - public WixRestartResourceSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixRestartResource, sourceLineNumber, id) - { - } - - public IntermediateField this[WixRestartResourceSymbolFields index] => this.Fields[(int)index]; - - public string ComponentRef - { - get => this.Fields[(int)WixRestartResourceSymbolFields.ComponentRef].AsString(); - set => this.Set((int)WixRestartResourceSymbolFields.ComponentRef, value); - } - - public string Resource - { - get => this.Fields[(int)WixRestartResourceSymbolFields.Resource].AsString(); - set => this.Set((int)WixRestartResourceSymbolFields.Resource, value); - } - - public WixRestartResourceAttributes? Attributes - { - get => (WixRestartResourceAttributes?)this.Fields[(int)WixRestartResourceSymbolFields.Attributes].AsNullableNumber(); - set => this.Set((int)WixRestartResourceSymbolFields.Attributes, (int?)value); - } - } -} \ No newline at end of file diff --git a/src/wixext/Symbols/WixTouchFileSymbol.cs b/src/wixext/Symbols/WixTouchFileSymbol.cs deleted file mode 100644 index 447c21ba..00000000 --- a/src/wixext/Symbols/WixTouchFileSymbol.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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition WixTouchFile = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.WixTouchFile.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(WixTouchFileSymbolFields.ComponentRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixTouchFileSymbolFields.Path), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(WixTouchFileSymbolFields.Attributes), IntermediateFieldType.Number), - }, - typeof(WixTouchFileSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum WixTouchFileSymbolFields - { - ComponentRef, - Path, - Attributes, - } - - public class WixTouchFileSymbol : IntermediateSymbol - { - public WixTouchFileSymbol() : base(UtilSymbolDefinitions.WixTouchFile, null, null) - { - } - - public WixTouchFileSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixTouchFile, sourceLineNumber, id) - { - } - - public IntermediateField this[WixTouchFileSymbolFields index] => this.Fields[(int)index]; - - public string ComponentRef - { - get => this.Fields[(int)WixTouchFileSymbolFields.ComponentRef].AsString(); - set => this.Set((int)WixTouchFileSymbolFields.ComponentRef, value); - } - - public string Path - { - get => this.Fields[(int)WixTouchFileSymbolFields.Path].AsString(); - set => this.Set((int)WixTouchFileSymbolFields.Path, value); - } - - public int Attributes - { - get => this.Fields[(int)WixTouchFileSymbolFields.Attributes].AsNumber(); - set => this.Set((int)WixTouchFileSymbolFields.Attributes, value); - } - } -} \ No newline at end of file diff --git a/src/wixext/Symbols/WixWindowsFeatureSearchSymbol.cs b/src/wixext/Symbols/WixWindowsFeatureSearchSymbol.cs deleted file mode 100644 index 9a43692c..00000000 --- a/src/wixext/Symbols/WixWindowsFeatureSearchSymbol.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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition WixWindowsFeatureSearch = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.WixWindowsFeatureSearch.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(WixWindowsFeatureSearchSymbolFields.Type), IntermediateFieldType.String), - }, - typeof(WixWindowsFeatureSearchSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum WixWindowsFeatureSearchSymbolFields - { - Type, - } - - public class WixWindowsFeatureSearchSymbol : IntermediateSymbol - { - public WixWindowsFeatureSearchSymbol() : base(UtilSymbolDefinitions.WixWindowsFeatureSearch, null, null) - { - } - - public WixWindowsFeatureSearchSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixWindowsFeatureSearch, sourceLineNumber, id) - { - } - - public IntermediateField this[WixWindowsFeatureSearchSymbolFields index] => this.Fields[(int)index]; - - public string Type - { - get => this.Fields[(int)WixWindowsFeatureSearchSymbolFields.Type].AsString(); - set => this.Set((int)WixWindowsFeatureSearchSymbolFields.Type, value); - } - } -} diff --git a/src/wixext/Symbols/XmlConfigSymbol.cs b/src/wixext/Symbols/XmlConfigSymbol.cs deleted file mode 100644 index 6503a586..00000000 --- a/src/wixext/Symbols/XmlConfigSymbol.cs +++ /dev/null @@ -1,111 +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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition XmlConfig = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.XmlConfig.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.File), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.ElementId), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.ElementPath), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.VerifyPath), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.Name), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.Value), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.Flags), IntermediateFieldType.Number), - new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.ComponentRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.Sequence), IntermediateFieldType.Number), - }, - typeof(XmlConfigSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum XmlConfigSymbolFields - { - File, - ElementId, - ElementPath, - VerifyPath, - Name, - Value, - Flags, - ComponentRef, - Sequence, - } - - public class XmlConfigSymbol : IntermediateSymbol - { - public XmlConfigSymbol() : base(UtilSymbolDefinitions.XmlConfig, null, null) - { - } - - public XmlConfigSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.XmlConfig, sourceLineNumber, id) - { - } - - public IntermediateField this[XmlConfigSymbolFields index] => this.Fields[(int)index]; - - public string File - { - get => this.Fields[(int)XmlConfigSymbolFields.File].AsString(); - set => this.Set((int)XmlConfigSymbolFields.File, value); - } - - public string ElementId - { - get => this.Fields[(int)XmlConfigSymbolFields.ElementId].AsString(); - set => this.Set((int)XmlConfigSymbolFields.ElementId, value); - } - - public string ElementPath - { - get => this.Fields[(int)XmlConfigSymbolFields.ElementPath].AsString(); - set => this.Set((int)XmlConfigSymbolFields.ElementPath, value); - } - - public string VerifyPath - { - get => this.Fields[(int)XmlConfigSymbolFields.VerifyPath].AsString(); - set => this.Set((int)XmlConfigSymbolFields.VerifyPath, value); - } - - public string Name - { - get => this.Fields[(int)XmlConfigSymbolFields.Name].AsString(); - set => this.Set((int)XmlConfigSymbolFields.Name, value); - } - - public string Value - { - get => this.Fields[(int)XmlConfigSymbolFields.Value].AsString(); - set => this.Set((int)XmlConfigSymbolFields.Value, value); - } - - public int Flags - { - get => this.Fields[(int)XmlConfigSymbolFields.Flags].AsNumber(); - set => this.Set((int)XmlConfigSymbolFields.Flags, value); - } - - public string ComponentRef - { - get => this.Fields[(int)XmlConfigSymbolFields.ComponentRef].AsString(); - set => this.Set((int)XmlConfigSymbolFields.ComponentRef, value); - } - - public int? Sequence - { - get => this.Fields[(int)XmlConfigSymbolFields.Sequence].AsNullableNumber(); - set => this.Set((int)XmlConfigSymbolFields.Sequence, value); - } - } -} \ No newline at end of file diff --git a/src/wixext/Symbols/XmlFileSymbol.cs b/src/wixext/Symbols/XmlFileSymbol.cs deleted file mode 100644 index 7d5d991b..00000000 --- a/src/wixext/Symbols/XmlFileSymbol.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.Util -{ - using WixToolset.Data; - using WixToolset.Util.Symbols; - - public static partial class UtilSymbolDefinitions - { - public static readonly IntermediateSymbolDefinition XmlFile = new IntermediateSymbolDefinition( - UtilSymbolDefinitionType.XmlFile.ToString(), - new[] - { - new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.File), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.ElementPath), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.Name), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.Value), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.Flags), IntermediateFieldType.Number), - new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.ComponentRef), IntermediateFieldType.String), - new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.Sequence), IntermediateFieldType.Number), - }, - typeof(XmlFileSymbol)); - } -} - -namespace WixToolset.Util.Symbols -{ - using WixToolset.Data; - - public enum XmlFileSymbolFields - { - File, - ElementPath, - Name, - Value, - Flags, - ComponentRef, - Sequence, - } - - public class XmlFileSymbol : IntermediateSymbol - { - public XmlFileSymbol() : base(UtilSymbolDefinitions.XmlFile, null, null) - { - } - - public XmlFileSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.XmlFile, sourceLineNumber, id) - { - } - - public IntermediateField this[XmlFileSymbolFields index] => this.Fields[(int)index]; - - public string File - { - get => this.Fields[(int)XmlFileSymbolFields.File].AsString(); - set => this.Set((int)XmlFileSymbolFields.File, value); - } - - public string ElementPath - { - get => this.Fields[(int)XmlFileSymbolFields.ElementPath].AsString(); - set => this.Set((int)XmlFileSymbolFields.ElementPath, value); - } - - public string Name - { - get => this.Fields[(int)XmlFileSymbolFields.Name].AsString(); - set => this.Set((int)XmlFileSymbolFields.Name, value); - } - - public string Value - { - get => this.Fields[(int)XmlFileSymbolFields.Value].AsString(); - set => this.Set((int)XmlFileSymbolFields.Value, value); - } - - public int Flags - { - get => this.Fields[(int)XmlFileSymbolFields.Flags].AsNumber(); - set => this.Set((int)XmlFileSymbolFields.Flags, value); - } - - public string ComponentRef - { - get => this.Fields[(int)XmlFileSymbolFields.ComponentRef].AsString(); - set => this.Set((int)XmlFileSymbolFields.ComponentRef, value); - } - - public int? Sequence - { - get => this.Fields[(int)XmlFileSymbolFields.Sequence].AsNullableNumber(); - set => this.Set((int)XmlFileSymbolFields.Sequence, value); - } - } -} \ No newline at end of file diff --git a/src/wixext/UtilCompiler.cs b/src/wixext/UtilCompiler.cs deleted file mode 100644 index 45079150..00000000 --- a/src/wixext/UtilCompiler.cs +++ /dev/null @@ -1,3889 +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.Util -{ - using System; - using System.Collections; - using System.Collections.Generic; - using System.Globalization; - using System.Linq; - using System.Text; - using System.Text.RegularExpressions; - using System.Xml.Linq; - using WixToolset.Data; - using WixToolset.Data.Symbols; - using WixToolset.Extensibility; - using WixToolset.Extensibility.Data; - using WixToolset.Util.Symbols; - - /// - /// The compiler for the WiX Toolset Utility Extension. - /// - public sealed class UtilCompiler : BaseCompilerExtension - { - // user creation attributes definitions (from sca.h) - internal const int UserDontExpirePasswrd = 0x00000001; - internal const int UserPasswdCantChange = 0x00000002; - internal const int UserPasswdChangeReqdOnLogin = 0x00000004; - internal const int UserDisableAccount = 0x00000008; - internal const int UserFailIfExists = 0x00000010; - internal const int UserUpdateIfExists = 0x00000020; - internal const int UserLogonAsService = 0x00000040; - internal const int UserLogonAsBatchJob = 0x00000080; - - internal const int UserDontRemoveOnUninstall = 0x00000100; - internal const int UserDontCreateUser = 0x00000200; - internal const int UserNonVital = 0x00000400; - - private static readonly Regex FindPropertyBrackets = new Regex(@"\[(?!\\|\])|(? "http://wixtoolset.org/schemas/v4/wxs/util"; - - /// - /// Types of Internet shortcuts. - /// - public enum InternetShortcutType - { - /// Create a .lnk file. - Link = 0, - - /// Create a .url file. - Url, - } - - /// - /// Types of permission setting methods. - /// - private enum PermissionType - { - /// LockPermissions (normal) type permission setting. - LockPermissions, - - /// FileSharePermissions type permission setting. - FileSharePermissions, - - /// SecureObjects type permission setting. - SecureObjects, - } - - /// - /// Processes an element for the Compiler. - /// - /// Parent element of element to process. - /// Element to process. - /// Extra information about the context in which this element is being parsed. - public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary context) - { - this.ParsePossibleKeyPathElement(intermediate, section, parentElement, element, context); - } - - /// - /// Processes an element for the Compiler. - /// - /// Source line number for the parent element. - /// Parent element of element to process. - /// Element to process. - /// Extra information about the context in which this element is being parsed. - public override IComponentKeyPath ParsePossibleKeyPathElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary context) - { - IComponentKeyPath possibleKeyPath = null; - - switch (parentElement.Name.LocalName) - { - case "CreateFolder": - var createFolderId = context["DirectoryId"]; - var createFolderComponentId = context["ComponentId"]; - - // If this doesn't parse successfully, something really odd is going on, so let the exception get thrown - var createFolderWin64 = Boolean.Parse(context["Win64"]); - - switch (element.Name.LocalName) - { - case "PermissionEx": - this.ParsePermissionExElement(intermediate, section, element, createFolderId, createFolderComponentId, createFolderWin64, "CreateFolder"); - break; - default: - this.ParseHelper.UnexpectedElement(parentElement, element); - break; - } - break; - case "Component": - var componentId = context["ComponentId"]; - var directoryId = context["DirectoryId"]; - var componentWin64 = Boolean.Parse(context["Win64"]); - - switch (element.Name.LocalName) - { - case "EventSource": - possibleKeyPath = this.ParseEventSourceElement(intermediate, section, element, componentId); - break; - case "FileShare": - this.ParseFileShareElement(intermediate, section, element, componentId, directoryId); - break; - case "InternetShortcut": - this.ParseInternetShortcutElement(intermediate, section, element, componentId, directoryId); - break; - case "PerformanceCategory": - this.ParsePerformanceCategoryElement(intermediate, section, element, componentId); - break; - case "RemoveFolderEx": - this.ParseRemoveFolderExElement(intermediate, section, element, componentId); - break; - case "RemoveRegistryKey": - this.ParseRemoveRegistryKeyExElement(intermediate, section, element, componentId); - break; - case "RestartResource": - this.ParseRestartResourceElement(intermediate, section, element, componentId); - break; - case "ServiceConfig": - this.ParseServiceConfigElement(intermediate, section, element, componentId, "Component", null); - break; - case "TouchFile": - this.ParseTouchFileElement(intermediate, section, element, componentId, componentWin64); - break; - case "User": - this.ParseUserElement(intermediate, section, element, componentId); - break; - case "XmlFile": - this.ParseXmlFileElement(intermediate, section, element, componentId); - break; - case "XmlConfig": - this.ParseXmlConfigElement(intermediate, section, element, componentId, false); - break; - default: - this.ParseHelper.UnexpectedElement(parentElement, element); - break; - } - break; - case "File": - var fileId = context["FileId"]; - var fileComponentId = context["ComponentId"]; - - // If this doesn't parse successfully, something really odd is going on, so let the exception get thrown - var fileWin64 = Boolean.Parse(context["Win64"]); - - switch (element.Name.LocalName) - { - case "PerfCounter": - this.ParsePerfCounterElement(intermediate, section, element, fileComponentId, fileId); - break; - case "PermissionEx": - this.ParsePermissionExElement(intermediate, section, element, fileId, fileComponentId, fileWin64, "File"); - break; - case "PerfCounterManifest": - this.ParsePerfCounterManifestElement(intermediate, section, element, fileComponentId, fileId); - break; - case "EventManifest": - this.ParseEventManifestElement(intermediate, section, element, fileComponentId, fileId); - break; - case "FormatFile": - this.ParseFormatFileElement(intermediate, section, element, fileId, fileWin64); - break; - default: - this.ParseHelper.UnexpectedElement(parentElement, element); - break; - } - break; - case "Bundle": - case "Fragment": - case "Module": - case "Package": - switch (element.Name.LocalName) - { - case "CloseApplication": - this.ParseCloseApplicationElement(intermediate, section, element); - break; - case "Group": - this.ParseGroupElement(intermediate, section, element, null); - break; - case "RestartResource": - // Currently not supported for Bundles. - if (parentElement.Name.LocalName != "Bundle") - { - this.ParseRestartResourceElement(intermediate, section, element, null); - } - else - { - this.ParseHelper.UnexpectedElement(parentElement, element); - } - break; - case "User": - this.ParseUserElement(intermediate, section, element, null); - break; - case "BroadcastEnvironmentChange": - case "BroadcastSettingChange": - case "CheckRebootRequired": - case "ExitEarlyWithSuccess": - case "FailWhenDeferred": - case "QueryWindowsDirectories": - case "QueryWindowsDriverInfo": - case "QueryWindowsSuiteInfo": - case "QueryWindowsWellKnownSIDs": - case "WaitForEvent": - case "WaitForEventDeferred": - this.AddCustomActionReference(intermediate, section, element, parentElement); - break; - case "ComponentSearch": - case "ComponentSearchRef": - case "DirectorySearch": - case "DirectorySearchRef": - case "FileSearch": - case "FileSearchRef": - case "ProductSearch": - case "ProductSearchRef": - case "RegistrySearch": - case "RegistrySearchRef": - case "WindowsFeatureSearch": - case "WindowsFeatureSearchRef": - // These will eventually be supported under Module/Product, but are not yet. - if (parentElement.Name.LocalName == "Bundle" || parentElement.Name.LocalName == "Fragment") - { - // TODO: When these are supported by all section types, move - // these out of the nested switch and back into the surrounding one. - switch (element.Name.LocalName) - { - case "ComponentSearch": - this.ParseComponentSearchElement(intermediate, section, element); - break; - case "ComponentSearchRef": - this.ParseComponentSearchRefElement(intermediate, section, element); - break; - case "DirectorySearch": - this.ParseDirectorySearchElement(intermediate, section, element); - break; - case "DirectorySearchRef": - this.ParseWixSearchRefElement(intermediate, section, element); - break; - case "FileSearch": - this.ParseFileSearchElement(intermediate, section, element); - break; - case "FileSearchRef": - this.ParseWixSearchRefElement(intermediate, section, element); - break; - case "ProductSearch": - this.ParseProductSearchElement(intermediate, section, element); - break; - case "ProductSearchRef": - this.ParseWixSearchRefElement(intermediate, section, element); - break; - case "RegistrySearch": - this.ParseRegistrySearchElement(intermediate, section, element); - break; - case "RegistrySearchRef": - this.ParseWixSearchRefElement(intermediate, section, element); - break; - case "WindowsFeatureSearch": - this.ParseWindowsFeatureSearchElement(intermediate, section, element); - break; - case "WindowsFeatureSearchRef": - this.ParseWindowsFeatureSearchRefElement(intermediate, section, element); - break; - } - } - else - { - this.ParseHelper.UnexpectedElement(parentElement, element); - } - break; - default: - this.ParseHelper.UnexpectedElement(parentElement, element); - break; - } - break; - case "Registry": - case "RegistryKey": - case "RegistryValue": - var registryId = context["RegistryId"]; - var registryComponentId = context["ComponentId"]; - - // If this doesn't parse successfully, something really odd is going on, so let the exception get thrown - var registryWin64 = Boolean.Parse(context["Win64"]); - - switch (element.Name.LocalName) - { - case "PermissionEx": - this.ParsePermissionExElement(intermediate, section, element, registryId, registryComponentId, registryWin64, "Registry"); - break; - default: - this.ParseHelper.UnexpectedElement(parentElement, element); - break; - } - break; - case "ServiceInstall": - var serviceInstallId = context["ServiceInstallId"]; - var serviceInstallName = context["ServiceInstallName"]; - var serviceInstallComponentId = context["ServiceInstallComponentId"]; - - // If this doesn't parse successfully, something really odd is going on, so let the exception get thrown - var serviceInstallWin64 = Boolean.Parse(context["Win64"]); - - switch (element.Name.LocalName) - { - case "PermissionEx": - this.ParsePermissionExElement(intermediate, section, element, serviceInstallId, serviceInstallComponentId, serviceInstallWin64, "ServiceInstall"); - break; - case "ServiceConfig": - this.ParseServiceConfigElement(intermediate, section, element, serviceInstallComponentId, "ServiceInstall", serviceInstallName); - break; - default: - this.ParseHelper.UnexpectedElement(parentElement, element); - break; - } - break; - case "UI": - switch (element.Name.LocalName) - { - case "BroadcastEnvironmentChange": - case "BroadcastSettingChange": - case "CheckRebootRequired": - case "ExitEarlyWithSuccess": - case "FailWhenDeferred": - case "QueryWindowsDirectories": - case "QueryWindowsDriverInfo": - case "QueryWindowsSuiteInfo": - case "QueryWindowsWellKnownSIDs": - case "WaitForEvent": - case "WaitForEventDeferred": - this.AddCustomActionReference(intermediate, section, element, parentElement); - break; - } - break; - default: - this.ParseHelper.UnexpectedElement(parentElement, element); - break; - } - - return possibleKeyPath; - } - - private void AddCustomActionReference(Intermediate intermediate, IntermediateSection section, XElement element, XElement parentElement) - { - // These elements are not supported for bundles. - if (parentElement.Name.LocalName == "Bundle") - { - this.ParseHelper.UnexpectedElement(parentElement, element); - return; - } - - var customAction = element.Name.LocalName; - switch (element.Name.LocalName) - { - case "BroadcastEnvironmentChange": - case "BroadcastSettingChange": - case "CheckRebootRequired": - case "ExitEarlyWithSuccess": - case "FailWhenDeferred": - case "WaitForEvent": - case "WaitForEventDeferred": - //default: customAction = element.Name.LocalName; - break; - case "QueryWindowsDirectories": - customAction = "QueryOsDirs"; - break; - case "QueryWindowsDriverInfo": - customAction = "QueryOsDriverInfo"; - break; - case "QueryWindowsSuiteInfo": - customAction = "QueryOsInfo"; - break; - case "QueryWindowsWellKnownSIDs": - customAction = "QueryOsWellKnownSID"; - break; - } - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - // no attributes today - } - else - { - this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); - } - } - - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4" + customAction, this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - } - - /// - /// Parses the common search attributes shared across all searches. - /// - /// Source line number for the parent element. - /// Attribute to parse. - /// Value of the Id attribute. - /// Value of the Variable attribute. - /// Value of the Condition attribute. - /// Value of the After attribute. - private void ParseCommonSearchAttributes(SourceLineNumber sourceLineNumbers, XAttribute attrib, ref Identifier id, ref string variable, ref string condition, ref string after) - { - switch (attrib.Name.LocalName) - { - case "Id": - id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); - break; - case "Variable": - variable = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - // TODO: handle standard bundle variables - break; - case "Condition": - condition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "After": - after = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - default: - System.Diagnostics.Debug.Assert(false); - break; - } - } - - /// - /// Parses a ComponentSearch element. - /// - /// Element to parse. - private void ParseComponentSearchElement(Intermediate intermediate, IntermediateSection section, XElement element) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - Identifier id = null; - string variable = null; - string condition = null; - string after = null; - string guid = null; - string productCode = null; - var attributes = WixComponentSearchAttributes.KeyPath; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - case "Variable": - case "Condition": - case "After": - this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after); - break; - case "Guid": - guid = this.ParseHelper.GetAttributeGuidValue(sourceLineNumbers, attrib); - break; - case "ProductCode": - productCode = this.ParseHelper.GetAttributeGuidValue(sourceLineNumbers, attrib); - break; - case "Result": - var result = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - switch (result) - { - case "directory": - attributes = WixComponentSearchAttributes.WantDirectory; - break; - case "keyPath": - attributes = WixComponentSearchAttributes.KeyPath; - break; - case "state": - attributes = WixComponentSearchAttributes.State; - break; - default: - this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Parent.Name.LocalName, attrib.Name.LocalName, result, "directory", "keyPath", "state")); - break; - } - break; - default: - this.ParseHelper.UnexpectedAttribute(element, attrib); - break; - } - } - else - { - this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); - } - } - - if (null == guid) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Guid")); - } - - if (null == id) - { - id = this.ParseHelper.CreateIdentifier("wcs", variable, condition, after, guid, productCode, attributes.ToString()); - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, null); - - if (!this.Messaging.EncounteredError) - { - section.AddSymbol(new WixComponentSearchSymbol(sourceLineNumbers, id) - { - Guid = guid, - ProductCode = productCode, - Attributes = attributes, - }); - } - } - - /// - /// Parses a ComponentSearchRef element - /// - /// Element to parse. - private void ParseComponentSearchRefElement(Intermediate intermediate, IntermediateSection section, XElement element) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - string refId = null; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - refId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); - this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixComponentSearch, refId); - 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); - } - - /// - /// Parses a WindowsFeatureSearch element. - /// - /// Element to parse. - private void ParseWindowsFeatureSearchElement(Intermediate intermediate, IntermediateSection section, XElement element) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - Identifier id = null; - string variable = null; - string condition = null; - string after = null; - string feature = null; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - case "Variable": - case "Condition": - case "After": - this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after); - break; - case "Feature": - feature = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - switch (feature) - { - case "sha2CodeSigning": - break; - default: - this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Feature", feature, "sha2CodeSigning")); - break; - } - break; - default: - this.ParseHelper.UnexpectedAttribute(element, attrib); - break; - } - } - else - { - this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); - } - } - - if (id == null) - { - id = this.ParseHelper.CreateIdentifier("wwfs", variable, condition, after); - } - - if (feature == null) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Feature")); - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - var bundleExtensionId = this.ParseHelper.CreateIdentifierValueFromPlatform("Wix4UtilBundleExtension", this.Context.Platform, BurnPlatforms.X86 | BurnPlatforms.X64 | BurnPlatforms.ARM64); - if (bundleExtensionId == null) - { - this.Messaging.Write(ErrorMessages.UnsupportedPlatformForElement(sourceLineNumbers, this.Context.Platform.ToString(), element.Name.LocalName)); - } - - this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, bundleExtensionId); - - if (!this.Messaging.EncounteredError) - { - section.AddSymbol(new WixWindowsFeatureSearchSymbol(sourceLineNumbers, id) - { - Type = feature, - }); - } - } - - /// - /// Parses a WindowsFeatureSearchRef element - /// - /// Element to parse. - private void ParseWindowsFeatureSearchRefElement(Intermediate intermediate, IntermediateSection section, XElement element) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - var refId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); - this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, UtilSymbolDefinitions.WixWindowsFeatureSearch, refId); - 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); - } - - /// - /// Parses an event source element. - /// - /// Element to parse. - /// Identifier of parent component. - private IComponentKeyPath ParseEventSourceElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - string sourceName = null; - string logName = null; - string categoryMessageFile = null; - var categoryCount = CompilerConstants.IntegerNotSet; - string eventMessageFile = null; - string parameterMessageFile = null; - int typesSupported = 0; - var isKeyPath = false; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "CategoryCount": - categoryCount = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue); - break; - case "CategoryMessageFile": - categoryMessageFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "EventMessageFile": - eventMessageFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "KeyPath": - isKeyPath = YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); - break; - case "Log": - logName = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - if ("Security" == logName) - { - this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, logName, "Application", "System", "")); - } - break; - case "Name": - sourceName = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "ParameterMessageFile": - parameterMessageFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "SupportsErrors": - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - typesSupported |= 0x01; // EVENTLOG_ERROR_TYPE - } - break; - case "SupportsFailureAudits": - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - typesSupported |= 0x10; // EVENTLOG_AUDIT_FAILURE - } - break; - case "SupportsInformationals": - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - typesSupported |= 0x04; // EVENTLOG_INFORMATION_TYPE - } - break; - case "SupportsSuccessAudits": - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - typesSupported |= 0x08; // EVENTLOG_AUDIT_SUCCESS - } - break; - case "SupportsWarnings": - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - typesSupported |= 0x02; // EVENTLOG_WARNING_TYPE - } - break; - default: - this.ParseHelper.UnexpectedAttribute(element, attrib); - break; - } - } - else - { - this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); - } - } - - if (null == sourceName) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); - } - - if (null == logName) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "EventLog")); - } - - if (null == eventMessageFile) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "EventMessageFile")); - } - - if (null == categoryMessageFile && 0 < categoryCount) - { - this.Messaging.Write(ErrorMessages.IllegalAttributeWithoutOtherAttributes(sourceLineNumbers, element.Name.LocalName, "CategoryCount", "CategoryMessageFile")); - } - - if (null != categoryMessageFile && CompilerConstants.IntegerNotSet == categoryCount) - { - this.Messaging.Write(ErrorMessages.IllegalAttributeWithoutOtherAttributes(sourceLineNumbers, element.Name.LocalName, "CategoryMessageFile", "CategoryCount")); - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - string eventSourceKey = $@"SYSTEM\CurrentControlSet\Services\EventLog\{logName}\{sourceName}"; - var id = this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, eventSourceKey, "EventMessageFile", String.Concat("#%", eventMessageFile), componentId, false); - - if (null != categoryMessageFile) - { - this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, eventSourceKey, "CategoryMessageFile", String.Concat("#%", categoryMessageFile), componentId, false); - } - - if (CompilerConstants.IntegerNotSet != categoryCount) - { - this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, eventSourceKey, "CategoryCount", String.Concat("#", categoryCount), componentId, false); - } - - if (null != parameterMessageFile) - { - this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, eventSourceKey, "ParameterMessageFile", String.Concat("#%", parameterMessageFile), componentId, false); - } - - if (0 != typesSupported) - { - this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, eventSourceKey, "TypesSupported", String.Concat("#", typesSupported), componentId, false); - } - - var componentKeyPath = this.CreateComponentKeyPath(); - componentKeyPath.Id = id.Id; - componentKeyPath.Explicit = isKeyPath; - componentKeyPath.Type = PossibleKeyPathType.Registry; - return componentKeyPath; - } - - /// - /// Parses a close application element. - /// - /// Element to parse. - private void ParseCloseApplicationElement(Intermediate intermediate, IntermediateSection section, XElement element) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - string condition = null; - string description = null; - string target = null; - string property = null; - Identifier id = null; - int attributes = 2; // default to CLOSEAPP_ATTRIBUTE_REBOOTPROMPT enabled - var sequence = CompilerConstants.IntegerNotSet; - var terminateExitCode = CompilerConstants.IntegerNotSet; - var timeout = 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 "Condition": - condition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Description": - description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Property": - property = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); - break; - case "Sequence": - sequence = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue); - break; - case "Timeout": - timeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue); - break; - case "Target": - target = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "CloseMessage": - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= 1; // CLOSEAPP_ATTRIBUTE_CLOSEMESSAGE - } - else - { - attributes &= ~1; // CLOSEAPP_ATTRIBUTE_CLOSEMESSAGE - } - break; - case "EndSessionMessage": - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= 8; // CLOSEAPP_ATTRIBUTE_ENDSESSIONMESSAGE - } - else - { - attributes &= ~8; // CLOSEAPP_ATTRIBUTE_ENDSESSIONMESSAGE - } - break; - case "PromptToContinue": - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= 0x40; // CLOSEAPP_ATTRIBUTE_PROMPTTOCONTINUE - } - else - { - attributes &= ~0x40; // CLOSEAPP_ATTRIBUTE_PROMPTTOCONTINUE - } - break; - case "RebootPrompt": - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= 2; // CLOSEAPP_ATTRIBUTE_REBOOTPROMPT - } - else - { - attributes &= ~2; // CLOSEAPP_ATTRIBUTE_REBOOTPROMPT - } - break; - case "ElevatedCloseMessage": - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= 4; // CLOSEAPP_ATTRIBUTE_ELEVATEDCLOSEMESSAGE - } - else - { - attributes &= ~4; // CLOSEAPP_ATTRIBUTE_ELEVATEDCLOSEMESSAGE - } - break; - case "ElevatedEndSessionMessage": - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= 0x10; // CLOSEAPP_ATTRIBUTE_ELEVATEDENDSESSIONMESSAGE - } - else - { - attributes &= ~0x10; // CLOSEAPP_ATTRIBUTE_ELEVATEDENDSESSIONMESSAGE - } - break; - case "TerminateProcess": - terminateExitCode = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue); - attributes |= 0x20; // CLOSEAPP_ATTRIBUTE_TERMINATEPROCESS - break; - default: - this.ParseHelper.UnexpectedAttribute(element, attrib); - break; - } - } - else - { - this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); - } - } - - if (null == target) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Target")); - } - else if (null == id) - { - id = this.ParseHelper.CreateIdentifier("ca", target); - } - - if (String.IsNullOrEmpty(description) && 0x40 == (attributes & 0x40)) - { - this.Messaging.Write(ErrorMessages.IllegalAttributeValueWithoutOtherAttribute(sourceLineNumbers, element.Name.LocalName, "PromptToContinue", "yes", "Description")); - } - - if (0x22 == (attributes & 0x22)) - { - this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "TerminateProcess", "RebootPrompt", "yes")); - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4CloseApplications", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - - if (!this.Messaging.EncounteredError) - { - var symbol = section.AddSymbol(new WixCloseApplicationSymbol(sourceLineNumbers, id) - { - Target = target, - Description = description, - Condition = condition, - Attributes = attributes, - Property = property, - }); - if (CompilerConstants.IntegerNotSet != sequence) - { - symbol.Sequence = sequence; - } - if (CompilerConstants.IntegerNotSet != terminateExitCode) - { - symbol.TerminateExitCode = terminateExitCode; - } - if (CompilerConstants.IntegerNotSet != timeout) - { - symbol.Timeout = timeout * 1000; // make the timeout milliseconds in the table. - } - } - } - - /// - /// Parses a DirectorySearch element. - /// - /// Element to parse. - private void ParseDirectorySearchElement(Intermediate intermediate, IntermediateSection section, XElement element) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - Identifier id = null; - string variable = null; - string condition = null; - string after = null; - string path = null; - var attributes = WixFileSearchAttributes.IsDirectory; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - case "Variable": - case "Condition": - case "After": - this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after); - break; - case "Path": - path = this.ParseHelper.GetAttributeLongFilename(sourceLineNumbers, attrib, false, true); - break; - case "Result": - var result = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - switch (result) - { - case "exists": - attributes |= WixFileSearchAttributes.WantExists; - break; - default: - this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Parent.Name.LocalName, attrib.Name.LocalName, result, "exists")); - break; - } - break; - default: - this.ParseHelper.UnexpectedAttribute(element, attrib); - break; - } - } - else - { - this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); - } - } - - if (null == path) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Path")); - } - - if (null == id) - { - id = this.ParseHelper.CreateIdentifier("wds", variable, condition, after, path, attributes.ToString()); - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, null); - - if (!this.Messaging.EncounteredError) - { - this.CreateWixFileSearchRow(section, sourceLineNumbers, id, path, attributes); - } - } - - /// - /// Parses a DirectorySearchRef, FileSearchRef, ProductSearchRef, and RegistrySearchRef elements - /// - /// Element to parse. - private void ParseWixSearchRefElement(Intermediate intermediate, IntermediateSection section, XElement node) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(node); - - foreach (XAttribute attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - var refId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); - this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixSearch, refId); - break; - default: - this.ParseHelper.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, node, attrib); - } - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, node); - } - - /// - /// Parses a FileSearch element. - /// - /// Element to parse. - private void ParseFileSearchElement(Intermediate intermediate, IntermediateSection section, XElement node) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(node); - Identifier id = null; - string variable = null; - string condition = null; - string after = null; - string path = null; - var attributes = WixFileSearchAttributes.Default; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - case "Variable": - case "Condition": - case "After": - this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after); - break; - case "Path": - path = this.ParseHelper.GetAttributeLongFilename(sourceLineNumbers, attrib, false, true); - break; - case "Result": - string result = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - switch (result) - { - case "exists": - attributes |= WixFileSearchAttributes.WantExists; - break; - case "version": - attributes |= WixFileSearchAttributes.WantVersion; - break; - default: - this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Parent.Name.LocalName, attrib.Name.LocalName, result, "exists", "version")); - break; - } - break; - default: - this.ParseHelper.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, node, attrib); - } - } - - if (null == path) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Path")); - } - - if (null == id) - { - id = this.ParseHelper.CreateIdentifier("wfs", variable, condition, after, path, attributes.ToString()); - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, node); - - this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, node.Name.LocalName, id, variable, condition, after, null); - - if (!this.Messaging.EncounteredError) - { - this.CreateWixFileSearchRow(section, sourceLineNumbers, id, path, attributes); - } - } - - /// - /// Creates a row in the WixFileSearch table. - /// - /// Source line number for the parent element. - /// Identifier of the search (key into the WixSearch table) - /// File/directory path to search for. - /// - private void CreateWixFileSearchRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier id, string path, WixFileSearchAttributes attributes) - { - section.AddSymbol(new WixFileSearchSymbol(sourceLineNumbers, id) - { - Path = path, - Attributes = attributes, - }); - } - - /// - /// Parses a file share element. - /// - /// Element to parse. - /// Identifier of parent component. - /// Identifier of referred to directory. - private void ParseFileShareElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string directoryId) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - string description = null; - string name = null; - 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); - break; - case "Name": - name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Description": - description = 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("ufs", componentId, name); - } - - if (null == name) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); - } - - if (!element.Elements().Any()) - { - this.Messaging.Write(ErrorMessages.ExpectedElement(sourceLineNumbers, element.Name.LocalName, "FileSharePermission")); - } - - foreach (var child in element.Elements()) - { - if (this.Namespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "FileSharePermission": - this.ParseFileSharePermissionElement(intermediate, section, child, id); - break; - default: - this.ParseHelper.UnexpectedElement(element, child); - break; - } - } - else - { - this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child); - } - } - - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureSmbInstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureSmbUninstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - - if (!this.Messaging.EncounteredError) - { - section.AddSymbol(new FileShareSymbol(sourceLineNumbers, id) - { - ShareName = name, - ComponentRef = componentId, - Description = description, - DirectoryRef = directoryId, - }); - } - } - - /// - /// Parses a FileSharePermission element. - /// - /// Element to parse. - /// The identifier of the parent FileShare element. - private void ParseFileSharePermissionElement(Intermediate intermediate, IntermediateSection section, XElement element, Identifier fileShareId) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - var bits = new BitArray(32); - string user = null; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "User": - user = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); - this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, UtilSymbolDefinitions.User, user); - break; - default: - var attribValue = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); - if (!this.TrySetBitFromName(UtilConstants.StandardPermissions, attrib.Name.LocalName, attribValue, bits, 16)) - { - if (!this.TrySetBitFromName(UtilConstants.GenericPermissions, attrib.Name.LocalName, attribValue, bits, 28)) - { - if (!this.TrySetBitFromName(UtilConstants.FolderPermissions, attrib.Name.LocalName, attribValue, bits, 0)) - { - this.ParseHelper.UnexpectedAttribute(element, attrib); - break; - } - } - } - break; - } - } - else - { - this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); - } - } - - var permission = this.CreateIntegerFromBitArray(bits); - - if (null == user) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "User")); - } - - if (Int32.MinValue == permission) // just GENERIC_READ, which is MSI_NULL - { - this.Messaging.Write(ErrorMessages.GenericReadNotAllowed(sourceLineNumbers)); - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - if (!this.Messaging.EncounteredError) - { - section.AddSymbol(new FileSharePermissionsSymbol(sourceLineNumbers) - { - FileShareRef = fileShareId.Id, - UserRef = user, - Permissions = permission, - }); - } - } - - /// - /// Parses a group element. - /// - /// Node to be parsed. - /// Component Id of the parent component of this element. - private void ParseGroupElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - Identifier id = null; - string domain = null; - string name = 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": - name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Domain": - domain = 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("ugr", componentId, domain, name); - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - if (!this.Messaging.EncounteredError) - { - section.AddSymbol(new GroupSymbol(sourceLineNumbers, id) - { - ComponentRef = componentId, - Name = name, - Domain = domain, - }); - } - } - - /// - /// Parses a GroupRef element - /// - /// Element to parse. - /// Required user id to be joined to the group. - private void ParseGroupRefElement(Intermediate intermediate, IntermediateSection section, XElement element, string userId) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - string groupId = null; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - groupId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); - this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, UtilSymbolDefinitions.Group, groupId); - 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) - { - section.AddSymbol(new UserGroupSymbol(sourceLineNumbers) - { - UserRef = userId, - GroupRef = groupId, - }); - } - } - - /// - /// Parses an InternetShortcut element. - /// - /// Element to parse. - /// Identifier of parent component. - /// Default directory if none is specified on the InternetShortcut element. - private void ParseInternetShortcutElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string defaultTarget) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - Identifier id = null; - string name = null; - string target = null; - string directoryId = null; - string type = null; - string iconFile = null; - int iconIndex = 0; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Directory": - directoryId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); - break; - case "Id": - id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); - break; - case "Name": - name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Target": - target = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Type": - type = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "IconFile": - iconFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "IconIndex": - iconIndex = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue); - break; - default: - this.ParseHelper.UnexpectedAttribute(element, attrib); - break; - } - } - else - { - this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); - } - } - - // If there was no directoryId specified on the InternetShortcut element, default to the one on - // the parent component. - if (null == directoryId) - { - directoryId = defaultTarget; - } - - if (null == id) - { - id = this.ParseHelper.CreateIdentifier("uis", componentId, directoryId, name, target); - } - - // In theory this can never be the case, since InternetShortcut can only be under - // a component element, and if the Directory wasn't specified the default will come - // from the component. However, better safe than sorry, so here's a check to make sure - // it didn't wind up being null after setting it to the defaultTarget. - if (null == directoryId) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Directory")); - } - - if (null == name) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); - } - - if (null == target) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Target")); - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - var shortcutType = InternetShortcutType.Link; - if (String.Equals(type, "url", StringComparison.OrdinalIgnoreCase)) - { - shortcutType = InternetShortcutType.Url; - } - - if (!this.Messaging.EncounteredError) - { - this.CreateWixInternetShortcut(section, sourceLineNumbers, componentId, directoryId, id, name, target, shortcutType, iconFile, iconIndex); - } - } - - /// - /// Creates the rows needed for WixInternetShortcut to work. - /// - /// The CompilerCore object used to create rows. - /// Source line information about the owner element. - /// Identifier of parent component. - /// Identifier of directory containing shortcut. - /// Identifier of shortcut. - /// Name of shortcut without extension. - /// Target URL of shortcut. - private void CreateWixInternetShortcut(IntermediateSection section, SourceLineNumber sourceLineNumbers, string componentId, string directoryId, Identifier shortcutId, string name, string target, InternetShortcutType type, string iconFile, int iconIndex) - { - // add the appropriate extension based on type of shortcut - name = String.Concat(name, InternetShortcutType.Url == type ? ".url" : ".lnk"); - - section.AddSymbol(new WixInternetShortcutSymbol(sourceLineNumbers, shortcutId) - { - ComponentRef = componentId, - DirectoryRef = directoryId, - Name = name, - Target = target, - Attributes = (int)type, - IconFile = iconFile, - IconIndex = iconIndex, - }); - - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedInternetShortcuts", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - - // make sure we have a CreateFolder table so that the immediate CA can add temporary rows to handle installation and uninstallation - this.ParseHelper.EnsureTable(section, sourceLineNumbers, "CreateFolder"); - - // use built-in MSI functionality to remove the shortcuts rather than doing so via CA - section.AddSymbol(new RemoveFileSymbol(sourceLineNumbers, shortcutId) - { - ComponentRef = componentId, - DirPropertyRef = directoryId, - OnUninstall = true, - FileName = name, - }); - } - - /// - /// Parses a performance category element. - /// - /// Element to parse. - /// Identifier of parent component. - private void ParsePerformanceCategoryElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - Identifier id = null; - string name = null; - string help = null; - var multiInstance = YesNoType.No; - int defaultLanguage = 0x09; // default to "english" - - var parsedPerformanceCounters = new List(); - - // default to managed performance counter - var library = "netfxperf.dll"; - var openEntryPoint = "OpenPerformanceData"; - var collectEntryPoint = "CollectPerformanceData"; - var closeEntryPoint = "ClosePerformanceData"; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Close": - closeEntryPoint = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Collect": - collectEntryPoint = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "DefaultLanguage": - defaultLanguage = this.GetPerformanceCounterLanguage(sourceLineNumbers, attrib); - break; - case "Help": - help = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Id": - id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); - break; - case "Library": - library = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "MultiInstance": - multiInstance = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); - break; - case "Name": - name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Open": - openEntryPoint = 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 && null == name) - { - this.Messaging.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, element.Name.LocalName, "Id", "Name")); - } - else if (null == id) - { - id = this.ParseHelper.CreateIdentifier("upc", componentId, name); - } - else if (null == name) - { - name = id.Id; - } - - // Process the child counter elements. - foreach (var child in element.Elements()) - { - if (this.Namespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "PerformanceCounter": - var counter = this.ParsePerformanceCounterElement(intermediate, section, child, defaultLanguage); - if (null != counter) - { - parsedPerformanceCounters.Add(counter); - } - break; - default: - this.ParseHelper.UnexpectedElement(element, child); - break; - } - } - else - { - this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child); - } - } - - - if (!this.Messaging.EncounteredError) - { - // Calculate the ini and h file content. - var objectName = "OBJECT_1"; - var objectLanguage = defaultLanguage.ToString("D3", CultureInfo.InvariantCulture); - - var sbIniData = new StringBuilder(); - sbIniData.AppendFormat("[info]\r\ndrivername={0}\r\nsymbolfile=wixperf.h\r\n\r\n[objects]\r\n{1}_{2}_NAME=\r\n\r\n[languages]\r\n{2}=LANG{2}\r\n\r\n", name, objectName, objectLanguage); - sbIniData.AppendFormat("[text]\r\n{0}_{1}_NAME={2}\r\n", objectName, objectLanguage, name); - if (null != help) - { - sbIniData.AppendFormat("{0}_{1}_HELP={2}\r\n", objectName, objectLanguage, help); - } - - int symbolConstantsCounter = 0; - var sbSymbolicConstants = new StringBuilder(); - sbSymbolicConstants.AppendFormat("#define {0} {1}\r\n", objectName, symbolConstantsCounter); - - var sbCounterNames = new StringBuilder("[~]"); - var sbCounterTypes = new StringBuilder("[~]"); - for (int i = 0; i < parsedPerformanceCounters.Count; ++i) - { - var counter = parsedPerformanceCounters[i]; - var counterName = String.Concat("DEVICE_COUNTER_", i + 1); - - sbIniData.AppendFormat("{0}_{1}_NAME={2}\r\n", counterName, counter.Language, counter.Name); - if (null != counter.Help) - { - sbIniData.AppendFormat("{0}_{1}_HELP={2}\r\n", counterName, counter.Language, counter.Help); - } - - symbolConstantsCounter += 2; - sbSymbolicConstants.AppendFormat("#define {0} {1}\r\n", counterName, symbolConstantsCounter); - - sbCounterNames.Append(UtilCompiler.FindPropertyBrackets.Replace(counter.Name, this.EscapeProperties)); - sbCounterNames.Append("[~]"); - sbCounterTypes.Append(counter.Type); - sbCounterTypes.Append("[~]"); - } - - sbSymbolicConstants.AppendFormat("#define LAST_{0}_COUNTER_OFFSET {1}\r\n", objectName, symbolConstantsCounter); - - // Add the calculated INI and H strings to the PerformanceCategory table. - section.AddSymbol(new PerformanceCategorySymbol(sourceLineNumbers, id) - { - ComponentRef = componentId, - Name = name, - IniData = sbIniData.ToString(), - ConstantData = sbSymbolicConstants.ToString(), - }); - - // Set up the application's performance key. - var escapedName = UtilCompiler.FindPropertyBrackets.Replace(name, this.EscapeProperties); - var linkageKey = String.Format(@"SYSTEM\CurrentControlSet\Services\{0}\Linkage", escapedName); - var performanceKey = String.Format(@"SYSTEM\CurrentControlSet\Services\{0}\Performance", escapedName); - - this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, linkageKey, "Export", escapedName, componentId, false); - this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "-", null, componentId, false); - this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "Library", library, componentId, false); - this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "Open", openEntryPoint, componentId, false); - this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "Collect", collectEntryPoint, componentId, false); - this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "Close", closeEntryPoint, componentId, false); - this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "IsMultiInstance", YesNoType.Yes == multiInstance ? "#1" : "#0", componentId, false); - this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "Counter Names", sbCounterNames.ToString(), componentId, false); - this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "Counter Types", sbCounterTypes.ToString(), componentId, false); - } - - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4InstallPerfCounterData", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4UninstallPerfCounterData", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - } - - /// - /// Gets the performance counter language as a decimal number. - /// - /// Source line information about the owner element. - /// The attribute containing the value to get. - /// Numeric representation of the language as per WinNT.h. - private int GetPerformanceCounterLanguage(SourceLineNumber sourceLineNumbers, XAttribute attribute) - { - int language = 0; - if (String.Empty == attribute.Value) - { - this.Messaging.Write(ErrorMessages.IllegalEmptyAttributeValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName)); - } - else - { - switch (attribute.Value) - { - case "afrikaans": - language = 0x36; - break; - case "albanian": - language = 0x1c; - break; - case "arabic": - language = 0x01; - break; - case "armenian": - language = 0x2b; - break; - case "assamese": - language = 0x4d; - break; - case "azeri": - language = 0x2c; - break; - case "basque": - language = 0x2d; - break; - case "belarusian": - language = 0x23; - break; - case "bengali": - language = 0x45; - break; - case "bulgarian": - language = 0x02; - break; - case "catalan": - language = 0x03; - break; - case "chinese": - language = 0x04; - break; - case "croatian": - language = 0x1a; - break; - case "czech": - language = 0x05; - break; - case "danish": - language = 0x06; - break; - case "divehi": - language = 0x65; - break; - case "dutch": - language = 0x13; - break; - case "piglatin": - case "english": - language = 0x09; - break; - case "estonian": - language = 0x25; - break; - case "faeroese": - language = 0x38; - break; - case "farsi": - language = 0x29; - break; - case "finnish": - language = 0x0b; - break; - case "french": - language = 0x0c; - break; - case "galician": - language = 0x56; - break; - case "georgian": - language = 0x37; - break; - case "german": - language = 0x07; - break; - case "greek": - language = 0x08; - break; - case "gujarati": - language = 0x47; - break; - case "hebrew": - language = 0x0d; - break; - case "hindi": - language = 0x39; - break; - case "hungarian": - language = 0x0e; - break; - case "icelandic": - language = 0x0f; - break; - case "indonesian": - language = 0x21; - break; - case "italian": - language = 0x10; - break; - case "japanese": - language = 0x11; - break; - case "kannada": - language = 0x4b; - break; - case "kashmiri": - language = 0x60; - break; - case "kazak": - language = 0x3f; - break; - case "konkani": - language = 0x57; - break; - case "korean": - language = 0x12; - break; - case "kyrgyz": - language = 0x40; - break; - case "latvian": - language = 0x26; - break; - case "lithuanian": - language = 0x27; - break; - case "macedonian": - language = 0x2f; - break; - case "malay": - language = 0x3e; - break; - case "malayalam": - language = 0x4c; - break; - case "manipuri": - language = 0x58; - break; - case "marathi": - language = 0x4e; - break; - case "mongolian": - language = 0x50; - break; - case "nepali": - language = 0x61; - break; - case "norwegian": - language = 0x14; - break; - case "oriya": - language = 0x48; - break; - case "polish": - language = 0x15; - break; - case "portuguese": - language = 0x16; - break; - case "punjabi": - language = 0x46; - break; - case "romanian": - language = 0x18; - break; - case "russian": - language = 0x19; - break; - case "sanskrit": - language = 0x4f; - break; - case "serbian": - language = 0x1a; - break; - case "sindhi": - language = 0x59; - break; - case "slovak": - language = 0x1b; - break; - case "slovenian": - language = 0x24; - break; - case "spanish": - language = 0x0a; - break; - case "swahili": - language = 0x41; - break; - case "swedish": - language = 0x1d; - break; - case "syriac": - language = 0x5a; - break; - case "tamil": - language = 0x49; - break; - case "tatar": - language = 0x44; - break; - case "telugu": - language = 0x4a; - break; - case "thai": - language = 0x1e; - break; - case "turkish": - language = 0x1f; - break; - case "ukrainian": - language = 0x22; - break; - case "urdu": - language = 0x20; - break; - case "uzbek": - language = 0x43; - break; - case "vietnamese": - language = 0x2a; - break; - default: - this.Messaging.Write(ErrorMessages.IllegalEmptyAttributeValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName)); - break; - } - } - - return language; - } - - /// - /// Parses a performance counter element. - /// - /// Element to parse. - /// Default language for the performance counter. - private ParsedPerformanceCounter ParsePerformanceCounterElement(Intermediate intermediate, IntermediateSection section, XElement element, int defaultLanguage) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - ParsedPerformanceCounter parsedPerformanceCounter = null; - string name = null; - string help = null; - var type = System.Diagnostics.PerformanceCounterType.NumberOfItems32; - int language = defaultLanguage; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Help": - help = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Name": - name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Type": - type = this.GetPerformanceCounterType(sourceLineNumbers, attrib); - break; - case "Language": - language = this.GetPerformanceCounterLanguage(sourceLineNumbers, attrib); - break; - default: - this.ParseHelper.UnexpectedAttribute(element, attrib); - break; - } - } - else - { - this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); - } - } - - if (null == name) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); - } - - if (null == help) - { - this.Messaging.Write(UtilWarnings.RequiredAttributeForWindowsXP(sourceLineNumbers, element.Name.LocalName, "Help")); - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - if (!this.Messaging.EncounteredError) - { - parsedPerformanceCounter = new ParsedPerformanceCounter(name, help, type, language); - } - - return parsedPerformanceCounter; - } - - /// - /// Gets the performance counter type. - /// - /// Source line information about the owner element. - /// The attribute containing the value to get. - /// Numeric representation of the language as per WinNT.h. - private System.Diagnostics.PerformanceCounterType GetPerformanceCounterType(SourceLineNumber sourceLineNumbers, XAttribute attribute) - { - var type = System.Diagnostics.PerformanceCounterType.NumberOfItems32; - if (String.Empty == attribute.Value) - { - this.Messaging.Write(ErrorMessages.IllegalEmptyAttributeValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName)); - } - else - { - switch (attribute.Value) - { - case "averageBase": - type = System.Diagnostics.PerformanceCounterType.AverageBase; - break; - case "averageCount64": - type = System.Diagnostics.PerformanceCounterType.AverageCount64; - break; - case "averageTimer32": - type = System.Diagnostics.PerformanceCounterType.AverageTimer32; - break; - case "counterDelta32": - type = System.Diagnostics.PerformanceCounterType.CounterDelta32; - break; - case "counterTimerInverse": - type = System.Diagnostics.PerformanceCounterType.CounterTimerInverse; - break; - case "sampleFraction": - type = System.Diagnostics.PerformanceCounterType.SampleFraction; - break; - case "timer100Ns": - type = System.Diagnostics.PerformanceCounterType.Timer100Ns; - break; - case "counterTimer": - type = System.Diagnostics.PerformanceCounterType.CounterTimer; - break; - case "rawFraction": - type = System.Diagnostics.PerformanceCounterType.RawFraction; - break; - case "timer100NsInverse": - type = System.Diagnostics.PerformanceCounterType.Timer100NsInverse; - break; - case "counterMultiTimer": - type = System.Diagnostics.PerformanceCounterType.CounterMultiTimer; - break; - case "counterMultiTimer100Ns": - type = System.Diagnostics.PerformanceCounterType.CounterMultiTimer100Ns; - break; - case "counterMultiTimerInverse": - type = System.Diagnostics.PerformanceCounterType.CounterMultiTimerInverse; - break; - case "counterMultiTimer100NsInverse": - type = System.Diagnostics.PerformanceCounterType.CounterMultiTimer100NsInverse; - break; - case "elapsedTime": - type = System.Diagnostics.PerformanceCounterType.ElapsedTime; - break; - case "sampleBase": - type = System.Diagnostics.PerformanceCounterType.SampleBase; - break; - case "rawBase": - type = System.Diagnostics.PerformanceCounterType.RawBase; - break; - case "counterMultiBase": - type = System.Diagnostics.PerformanceCounterType.CounterMultiBase; - break; - case "rateOfCountsPerSecond64": - type = System.Diagnostics.PerformanceCounterType.RateOfCountsPerSecond64; - break; - case "rateOfCountsPerSecond32": - type = System.Diagnostics.PerformanceCounterType.RateOfCountsPerSecond32; - break; - case "countPerTimeInterval64": - type = System.Diagnostics.PerformanceCounterType.CountPerTimeInterval64; - break; - case "countPerTimeInterval32": - type = System.Diagnostics.PerformanceCounterType.CountPerTimeInterval32; - break; - case "sampleCounter": - type = System.Diagnostics.PerformanceCounterType.SampleCounter; - break; - case "counterDelta64": - type = System.Diagnostics.PerformanceCounterType.CounterDelta64; - break; - case "numberOfItems64": - type = System.Diagnostics.PerformanceCounterType.NumberOfItems64; - break; - case "numberOfItems32": - type = System.Diagnostics.PerformanceCounterType.NumberOfItems32; - break; - case "numberOfItemsHEX64": - type = System.Diagnostics.PerformanceCounterType.NumberOfItemsHEX64; - break; - case "numberOfItemsHEX32": - type = System.Diagnostics.PerformanceCounterType.NumberOfItemsHEX32; - break; - default: - this.Messaging.Write(ErrorMessages.IllegalEmptyAttributeValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName)); - break; - } - } - - return type; - } - - /// - /// Parses a perf counter element. - /// - /// Element to parse. - /// Identifier of parent component. - /// Identifier of referenced file. - private void ParsePerfCounterElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string fileId) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - string name = null; - - this.Messaging.Write(UtilWarnings.DeprecatedPerfCounterElement(sourceLineNumbers)); - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Name": - name = 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 == name) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - if (!this.Messaging.EncounteredError) - { - section.AddSymbol(new PerfmonSymbol(sourceLineNumbers) - { - ComponentRef = componentId, - File = $"[#{fileId}]", - Name = name, - }); - } - - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigurePerfmonInstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigurePerfmonUninstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - } - - - /// - /// Parses a perf manifest element. - /// - /// Element to parse. - /// Identifier of parent component. - /// Identifier of referenced file. - private void ParsePerfCounterManifestElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string fileId) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - string resourceFileDirectory = null; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "ResourceFileDirectory": - resourceFileDirectory = 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) - { - section.AddSymbol(new PerfmonManifestSymbol(sourceLineNumbers) - { - ComponentRef = componentId, - File = $"[#{fileId}]", - ResourceFileDirectory = resourceFileDirectory, - }); - } - - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigurePerfmonManifestRegister", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigurePerfmonManifestUnregister", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - } - - /// - /// Parses a format files element. - /// - /// Element to parse. - /// Identifier of referenced file. - /// Flag to determine whether the component is 64-bit. - private void ParseFormatFileElement(Intermediate intermediate, IntermediateSection section, XElement element, string fileId, bool win64) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - string binaryId = null; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "BinaryRef": - binaryId = 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 (null == binaryId) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "BinaryRef")); - } - - if (!this.Messaging.EncounteredError) - { - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedFormatFiles", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - - section.AddSymbol(new WixFormatFilesSymbol(sourceLineNumbers) - { - BinaryRef = binaryId, - FileRef = fileId, - }); - - this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Binary, binaryId); - } - } - - /// - /// Parses a event manifest element. - /// - /// Element to parse. - /// Identifier of parent component. - /// Identifier of referenced file. - private void ParseEventManifestElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string fileId) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - string messageFile = null; - string resourceFile = null; - string parameterFile = null; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "MessageFile": - messageFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "ResourceFile": - resourceFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "ParameterFile": - parameterFile = 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) - { - section.AddSymbol(new EventManifestSymbol(sourceLineNumbers) - { - ComponentRef = componentId, - File = $"[#{fileId}]", - }); - - if (null != messageFile) - { - section.AddSymbol(new XmlFileSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, $"Config_{fileId}MessageFile")) - { - File = $"[#{fileId}]", - ElementPath = "/*/*/*/*[\\[]@messageFileName[\\]]", - Name = "messageFileName", - Value = messageFile, - Flags = 4 | 0x00001000, //bulk write | preserve modified date - ComponentRef = componentId, - }); - } - if (null != parameterFile) - { - section.AddSymbol(new XmlFileSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, $"Config_{fileId}ParameterFile")) - { - File = $"[#{fileId}]", - ElementPath = "/*/*/*/*[\\[]@parameterFileName[\\]]", - Name = "parameterFileName", - Value = parameterFile, - Flags = 4 | 0x00001000, //bulk write | preserve modified date - ComponentRef = componentId, - }); - } - if (null != resourceFile) - { - section.AddSymbol(new XmlFileSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, $"Config_{fileId}ResourceFile")) - { - File = $"[#{fileId}]", - ElementPath = "/*/*/*/*[\\[]@resourceFileName[\\]]", - Name = "resourceFileName", - Value = resourceFile, - Flags = 4 | 0x00001000, //bulk write | preserve modified date - ComponentRef = componentId, - }); - } - - } - - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureEventManifestRegister", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureEventManifestUnregister", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - - if (null != messageFile || null != parameterFile || null != resourceFile) - { - this.AddReferenceToSchedXmlFile(sourceLineNumbers, section); - } - } - - /// - /// Parses a PermissionEx element. - /// - /// Element to parse. - /// Identifier of object to be secured. - /// Identifier of component, used to determine install state. - /// Flag to determine whether the component is 64-bit. - /// Name of table that contains objectId. - private void ParsePermissionExElement(Intermediate intermediate, IntermediateSection section, XElement element, string objectId, string componentId, bool win64, string tableName) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - var bits = new BitArray(32); - string domain = null; - string[] specialPermissions = null; - string user = null; - var attributes = WixPermissionExAttributes.Inheritable; // default to inheritable. - - var permissionType = PermissionType.SecureObjects; - - switch (tableName) - { - case "CreateFolder": - specialPermissions = UtilConstants.FolderPermissions; - break; - case "File": - specialPermissions = UtilConstants.FilePermissions; - break; - case "Registry": - specialPermissions = UtilConstants.RegistryPermissions; - if (String.IsNullOrEmpty(objectId)) - { - this.Messaging.Write(UtilErrors.InvalidRegistryObject(sourceLineNumbers, element.Parent.Name.LocalName)); - } - break; - case "ServiceInstall": - specialPermissions = UtilConstants.ServicePermissions; - permissionType = PermissionType.SecureObjects; - break; - default: - this.ParseHelper.UnexpectedElement(element.Parent, element); - break; - } - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Domain": - if (PermissionType.FileSharePermissions == permissionType) - { - this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, element.Parent.Name.LocalName)); - } - domain = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Inheritable": - if (this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib) == YesNoType.No) - { - attributes &= ~WixPermissionExAttributes.Inheritable; - } - break; - case "User": - user = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - default: - var attribValue = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); - if (!this.TrySetBitFromName(UtilConstants.StandardPermissions, attrib.Name.LocalName, attribValue, bits, 16)) - { - if (!this.TrySetBitFromName(UtilConstants.GenericPermissions, attrib.Name.LocalName, attribValue, bits, 28)) - { - if (!this.TrySetBitFromName(specialPermissions, attrib.Name.LocalName, attribValue, bits, 0)) - { - this.ParseHelper.UnexpectedAttribute(element, attrib); - break; - } - } - } - break; - } - } - else - { - this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); - } - } - - var permission = this.CreateIntegerFromBitArray(bits); - - if (null == user) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "User")); - } - - if (Int32.MinValue == permission) // just GENERIC_READ, which is MSI_NULL - { - this.Messaging.Write(ErrorMessages.GenericReadNotAllowed(sourceLineNumbers)); - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - if (!this.Messaging.EncounteredError) - { - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedSecureObjects", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - - var id = this.ParseHelper.CreateIdentifier("sec", objectId, tableName, domain, user); - section.AddSymbol(new SecureObjectsSymbol(sourceLineNumbers, id) - { - SecureObject = objectId, - Table = tableName, - Domain = domain, - User = user, - Attributes = attributes, - Permission = permission, - ComponentRef = componentId, - }); - } - } - - /// - /// Parses a ProductSearch element. - /// - /// Element to parse. - private void ParseProductSearchElement(Intermediate intermediate, IntermediateSection section, XElement element) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - Identifier id = null; - string variable = null; - string condition = null; - string after = null; - string productCode = null; - string upgradeCode = null; - var attributes = WixProductSearchAttributes.Version; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - case "Variable": - case "Condition": - case "After": - this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after); - break; - case "ProductCode": - productCode = this.ParseHelper.GetAttributeGuidValue(sourceLineNumbers, attrib, false); - break; - case "UpgradeCode": - upgradeCode = this.ParseHelper.GetAttributeGuidValue(sourceLineNumbers, attrib, false); - break; - case "Result": - var result = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - switch (result) - { - case "version": - attributes = WixProductSearchAttributes.Version; - break; - case "language": - attributes = WixProductSearchAttributes.Language; - break; - case "state": - attributes = WixProductSearchAttributes.State; - break; - case "assignment": - attributes = WixProductSearchAttributes.Assignment; - break; - default: - this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Parent.Name.LocalName, attrib.Name.LocalName, result, "version", "language", "state", "assignment")); - break; - } - break; - default: - this.ParseHelper.UnexpectedAttribute(element, attrib); - break; - } - } - else - { - this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); - } - } - - if (null == upgradeCode && null == productCode) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "ProductCode", "UpgradeCode", true)); - } - - if (null != upgradeCode && null != productCode) - { - this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "UpgradeCode", "ProductCode")); - } - - if (null == id) - { - id = this.ParseHelper.CreateIdentifier("wps", variable, condition, after, (productCode == null ? upgradeCode : productCode), attributes.ToString()); - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, null); - - if (!this.Messaging.EncounteredError) - { - // set an additional flag if this is an upgrade code - if (null != upgradeCode) - { - attributes |= WixProductSearchAttributes.UpgradeCode; - } - - section.AddSymbol(new WixProductSearchSymbol(sourceLineNumbers, id) - { - Guid = productCode ?? upgradeCode, - Attributes = attributes, - }); - } - } - - /// - /// Parses a RegistrySearch element. - /// - /// Element to parse. - private void ParseRegistrySearchElement(Intermediate intermediate, IntermediateSection section, XElement element) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - Identifier id = null; - string variable = null; - string condition = null; - string after = null; - RegistryRootType? root = null; - string key = null; - string value = null; - var expand = YesNoType.NotSet; - var win64 = this.Context.IsCurrentPlatform64Bit; - var attributes = WixRegistrySearchAttributes.Raw | WixRegistrySearchAttributes.WantValue; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - case "Variable": - case "Condition": - case "After": - this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after); - break; - case "Bitness": - var bitnessValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - switch (bitnessValue) - { - case "always32": - win64 = false; - break; - case "always64": - win64 = true; - break; - case "default": - case "": - break; - default: - this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Name.LocalName, attrib.Name.LocalName, bitnessValue, "default", "always32", "always64")); - break; - } - break; - case "Root": - root = this.ParseHelper.GetAttributeRegistryRootValue(sourceLineNumbers, attrib, false); - break; - case "Key": - key = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Value": - value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "ExpandEnvironmentVariables": - expand = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); - break; - case "Format": - string format = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - switch (format) - { - case "raw": - attributes |= WixRegistrySearchAttributes.Raw; - break; - case "compatible": - attributes |= WixRegistrySearchAttributes.Compatible; - break; - default: - this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Parent.Name.LocalName, attrib.Name.LocalName, format, "raw", "compatible")); - break; - } - break; - case "Result": - var result = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - switch (result) - { - case "exists": - attributes |= WixRegistrySearchAttributes.WantExists; - break; - case "value": - attributes |= WixRegistrySearchAttributes.WantValue; - break; - default: - this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Parent.Name.LocalName, attrib.Name.LocalName, result, "exists", "value")); - break; - } - break; - default: - this.ParseHelper.UnexpectedAttribute(element, attrib); - break; - } - } - else - { - this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); - } - } - - if (!root.HasValue) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Root")); - } - - if (null == key) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Key")); - } - - if (null == id) - { - id = this.ParseHelper.CreateIdentifier("wrs", variable, condition, after, root.ToString(), key, value, attributes.ToString()); - } - - if (expand == YesNoType.Yes) - { - if (0 != (attributes & WixRegistrySearchAttributes.WantExists)) - { - this.Messaging.Write(ErrorMessages.IllegalAttributeValueWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "ExpandEnvironmentVariables", expand.ToString(), "Result", "exists")); - } - - attributes |= WixRegistrySearchAttributes.ExpandEnvironmentVariables; - } - - if (win64) - { - attributes |= WixRegistrySearchAttributes.Win64; - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, null); - - if (!this.Messaging.EncounteredError) - { - section.AddSymbol(new WixRegistrySearchSymbol(sourceLineNumbers, id) - { - Root = root.Value, - Key = key, - Value = value, - Attributes = attributes, - }); - } - } - - /// - /// Parses a RemoveFolderEx element. - /// - /// Element to parse. - /// Identifier of parent component. - private void ParseRemoveFolderExElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - Identifier id = null; - var mode = WixRemoveFolderExInstallMode.Uninstall; - string property = null; - string condition = null; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Condition": - condition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Id": - id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); - break; - case "On": - var onValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - if (onValue.Length == 0) - { - } - else - { - switch (onValue) - { - case "install": - mode = WixRemoveFolderExInstallMode.Install; - break; - case "uninstall": - mode = WixRemoveFolderExInstallMode.Uninstall; - break; - case "both": - mode = WixRemoveFolderExInstallMode.Both; - break; - default: - this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "On", onValue, "install", "uninstall", "both")); - break; - } - } - break; - case "Property": - property = 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 (String.IsNullOrEmpty(property)) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Property")); - } - - if (id == null) - { - id = this.ParseHelper.CreateIdentifier("wrf", componentId, property, mode.ToString()); - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - if (!this.Messaging.EncounteredError) - { - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4RemoveFoldersEx", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - - section.AddSymbol(new WixRemoveFolderExSymbol(sourceLineNumbers, id) - { - ComponentRef = componentId, - Property = property, - InstallMode = mode, - Condition = condition - }); - - this.ParseHelper.EnsureTable(section, sourceLineNumbers, "RemoveFile"); - } - } - - /// - /// Parses a RemoveRegistryKeyEx element. - /// - /// Element to parse. - /// Identifier of parent component. - private void ParseRemoveRegistryKeyExElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - Identifier id = null; - var mode = WixRemoveRegistryKeyExInstallMode.Uninstall; - string condition = null; - RegistryRootType? root = null; - string key = null; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Condition": - condition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Id": - id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); - break; - case "On": - var actionValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - switch (actionValue) - { - case "": - break; - case "install": - mode = WixRemoveRegistryKeyExInstallMode.Install; - break; - case "uninstall": - mode = WixRemoveRegistryKeyExInstallMode.Uninstall; - break; - default: - this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "On", actionValue, "install", "uninstall")); - break; - } - break; - case "Root": - root = this.ParseHelper.GetAttributeRegistryRootValue(sourceLineNumbers, attrib, false); - break; - case "Key": - key = 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 (!root.HasValue) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Root")); - } - - if (key == null) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Key")); - } - - if (id == null) - { - id = this.ParseHelper.CreateIdentifier("rrx", componentId, condition, root.ToString(), key, mode.ToString()); - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - if (!this.Messaging.EncounteredError) - { - this.ParseHelper.EnsureTable(section, sourceLineNumbers, "Registry"); - this.ParseHelper.EnsureTable(section, sourceLineNumbers, "RemoveRegistry"); - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4RemoveRegistryKeysEx", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - - section.AddSymbol(new WixRemoveRegistryKeyExSymbol(sourceLineNumbers, id) - { - ComponentRef = componentId, - Root = root.Value, - Key = key, - InstallMode = mode, - Condition = condition - }); - } - } - - /// - /// Parses a RestartResource element. - /// - /// The element to parse. - /// The identity of the parent component. - private void ParseRestartResourceElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - Identifier id = null; - string resource = null; - WixRestartResourceAttributes? attributes = 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 "Path": - resource = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - attributes = WixRestartResourceAttributes.Filename; - break; - - case "ProcessName": - resource = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - attributes = WixRestartResourceAttributes.ProcessName; - break; - - case "ServiceName": - resource = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - attributes = WixRestartResourceAttributes.ServiceName; - break; - - default: - this.ParseHelper.UnexpectedAttribute(element, attrib); - break; - } - } - else - { - this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); - } - } - - // Validate the attribute. - if (id == null) - { - id = this.ParseHelper.CreateIdentifier("wrr", componentId, resource, attributes.ToString()); - } - - if (!attributes.HasValue) - { - this.Messaging.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, element.Name.LocalName, "Path", "ProcessName", "ServiceName")); - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - if (!this.Messaging.EncounteredError) - { - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4RegisterRestartResources", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - - section.AddSymbol(new WixRestartResourceSymbol(sourceLineNumbers, id) - { - ComponentRef = componentId, - Resource = resource, - Attributes = attributes, - }); - } - } - - /// - /// Parses a service configuration element. - /// - /// Element to parse. - /// Identifier of parent component. - /// Name of parent element. - /// Optional name of service - private void ParseServiceConfigElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string parentTableName, string parentTableServiceName) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - string firstFailureActionType = null; - var newService = false; - string programCommandLine = null; - string rebootMessage = null; - var resetPeriod = CompilerConstants.IntegerNotSet; - var restartServiceDelay = CompilerConstants.IntegerNotSet; - string secondFailureActionType = null; - string serviceName = null; - string thirdFailureActionType = null; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "FirstFailureActionType": - firstFailureActionType = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "ProgramCommandLine": - programCommandLine = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "RebootMessage": - rebootMessage = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "ResetPeriodInDays": - resetPeriod = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue); - break; - case "RestartServiceDelayInSeconds": - restartServiceDelay = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue); - break; - case "SecondFailureActionType": - secondFailureActionType = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "ServiceName": - serviceName = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "ThirdFailureActionType": - thirdFailureActionType = 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 this element is a child of ServiceInstall then ignore the service name provided. - if ("ServiceInstall" == parentTableName) - { - // TODO: the ServiceName attribute should not be allowed in this case (the overwriting behavior may confuse users) - serviceName = parentTableServiceName; - newService = true; - } - else - { - // not a child of ServiceInstall, so ServiceName must have been provided - if (null == serviceName) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "ServiceName")); - } - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - if (!this.Messaging.EncounteredError) - { - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedServiceConfig", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - - section.AddSymbol(new ServiceConfigSymbol(sourceLineNumbers) - { - ServiceName = serviceName, - ComponentRef = componentId, - NewService = newService ? 1 : 0, - FirstFailureActionType = firstFailureActionType, - SecondFailureActionType = secondFailureActionType, - ThirdFailureActionType = thirdFailureActionType, - ResetPeriodInDays = resetPeriod, - RestartServiceDelayInSeconds = restartServiceDelay, - ProgramCommandLine = programCommandLine, - RebootMessage = rebootMessage, - }); - } - } - - /// - /// Parses a touch file element. - /// - /// Element to parse. - /// Identifier of parent component. - /// Indicates whether the path is a 64-bit path. - private void ParseTouchFileElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, bool win64) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - Identifier id = null; - string path = null; - var onInstall = YesNoType.NotSet; - var onReinstall = YesNoType.NotSet; - var onUninstall = YesNoType.NotSet; - var nonvital = YesNoType.NotSet; - int attributes = 0; - - 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 "Path": - path = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "OnInstall": - onInstall = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); - break; - case "OnReinstall": - onReinstall = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); - break; - case "OnUninstall": - onUninstall = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); - break; - case "Nonvital": - nonvital = 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 == path) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Path")); - } - - // If none of the scheduling actions are set, default to touching on install and reinstall. - if (YesNoType.NotSet == onInstall && YesNoType.NotSet == onReinstall && YesNoType.NotSet == onUninstall) - { - onInstall = YesNoType.Yes; - onReinstall = YesNoType.Yes; - } - - attributes |= YesNoType.Yes == onInstall ? 0x1 : 0; - attributes |= YesNoType.Yes == onReinstall ? 0x2 : 0; - attributes |= YesNoType.Yes == onUninstall ? 0x4 : 0; - attributes |= win64 ? 0x10 : 0; - attributes |= YesNoType.Yes == nonvital ? 0 : 0x20; - - if (null == id) - { - id = this.ParseHelper.CreateIdentifier("tf", path, attributes.ToString()); - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - if (!this.Messaging.EncounteredError) - { - section.AddSymbol(new WixTouchFileSymbol(sourceLineNumbers, id) - { - ComponentRef = componentId, - Path = path, - Attributes = attributes, - }); - - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4TouchFileDuringInstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - } - } - - /// - /// Parses an user element. - /// - /// Element to parse. - /// Optional identifier of parent component. - private void ParseUserElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - Identifier id = null; - int attributes = 0; - string domain = null; - string name = null; - string password = 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 "CanNotChangePassword": - if (null == componentId) - { - this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); - } - - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= UserPasswdCantChange; - } - break; - case "CreateUser": - if (null == componentId) - { - this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); - } - - if (YesNoType.No == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= UserDontCreateUser; - } - break; - case "Disabled": - if (null == componentId) - { - this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); - } - - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= UserDisableAccount; - } - break; - case "Domain": - domain = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "FailIfExists": - if (null == componentId) - { - this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); - } - - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= UserFailIfExists; - } - break; - case "LogonAsService": - if (null == componentId) - { - this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); - } - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= UserLogonAsService; - } - break; - case "LogonAsBatchJob": - if (null == componentId) - { - this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); - } - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= UserLogonAsBatchJob; - } - break; - case "Name": - name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Password": - password = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "PasswordExpired": - if (null == componentId) - { - this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); - } - - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= UserPasswdChangeReqdOnLogin; - } - break; - case "PasswordNeverExpires": - if (null == componentId) - { - this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); - } - - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= UserDontExpirePasswrd; - } - break; - case "RemoveOnUninstall": - if (null == componentId) - { - this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); - } - - if (YesNoType.No == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= UserDontRemoveOnUninstall; - } - break; - case "UpdateIfExists": - if (null == componentId) - { - this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); - } - - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= UserUpdateIfExists; - } - break; - case "Vital": - if (null == componentId) - { - this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); - } - - if (YesNoType.No == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= UserNonVital; - } - 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("usr", componentId, name); - } - - if (null == name) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); - } - - foreach (var child in element.Elements()) - { - if (this.Namespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "GroupRef": - if (null == componentId) - { - var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child); - this.Messaging.Write(UtilErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); - } - - this.ParseGroupRefElement(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 (null != componentId) - { - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureUsers", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - } - - if (!this.Messaging.EncounteredError) - { - section.AddSymbol(new UserSymbol(sourceLineNumbers, id) - { - ComponentRef = componentId, - Name = name, - Domain = domain, - Password = password, - Attributes = attributes, - }); - } - } - - /// - /// Parses a XmlFile element. - /// - /// Element to parse. - /// Identifier of parent component. - private void ParseXmlFileElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - Identifier id = null; - string file = null; - string elementPath = null; - string name = null; - string value = null; - int sequence = -1; - int flags = 0; - - foreach (var attrib in element.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Action": - var actionValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - switch (actionValue) - { - case "createElement": - flags |= 0x00000001; // XMLFILE_CREATE_ELEMENT - break; - case "deleteValue": - flags |= 0x00000002; // XMLFILE_DELETE_VALUE - break; - case "bulkSetValue": - flags |= 0x00000004; // XMLFILE_BULKWRITE_VALUE - break; - case "setValue": - // no flag for set value since it's the default - break; - default: - this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Action", actionValue, "createElement", "deleteValue", "setValue", "bulkSetValue")); - break; - } - break; - case "SelectionLanguage": - string selectionLanguage = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - switch (selectionLanguage) - { - case "XPath": - flags |= 0x00000100; // XMLFILE_USE_XPATH - break; - case "XSLPattern": - // no flag for since it's the default - break; - default: - this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "SelectionLanguage", selectionLanguage, "XPath", "XSLPattern")); - break; - } - break; - case "Id": - id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); - break; - case "File": - file = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "ElementPath": - elementPath = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Name": - name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Permanent": - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - flags |= 0x00010000; // XMLFILE_DONT_UNINSTALL - } - break; - case "Sequence": - sequence = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, Int16.MaxValue); - break; - case "Value": - value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "PreserveModifiedDate": - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - flags |= 0x00001000; // XMLFILE_PRESERVE_MODIFIED - } - 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("uxf", componentId, file, elementPath, name); - } - - if (null == file) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "File")); - } - - if (null == elementPath) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "ElementPath")); - } - - if ((0x00000001 /*XMLFILE_CREATE_ELEMENT*/ & flags) != 0 && null == name) - { - this.Messaging.Write(ErrorMessages.IllegalAttributeWithoutOtherAttributes(sourceLineNumbers, element.Name.LocalName, "Action", "Name")); - } - - this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - - if (!this.Messaging.EncounteredError) - { - var symbol = section.AddSymbol(new XmlFileSymbol(sourceLineNumbers, id) - { - File = file, - ElementPath = elementPath, - Name = name, - Value = value, - Flags = flags, - ComponentRef = componentId, - }); - if (-1 != sequence) - { - symbol.Sequence = sequence; - } - } - - this.AddReferenceToSchedXmlFile(sourceLineNumbers, section); - } - - /// - /// Parses a XmlConfig element. - /// - /// Element to parse. - /// Identifier of parent component. - /// Whether or not the element is nested. - private void ParseXmlConfigElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, bool nested) - { - var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); - Identifier id = null; - string elementId = null; - string elementPath = null; - int flags = 0; - string file = null; - string name = null; - var sequence = CompilerConstants.IntegerNotSet; - string value = null; - string verifyPath = 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 "Action": - if (nested) - { - this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, element.Parent.Name.LocalName)); - } - else - { - string actionValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - switch (actionValue) - { - case "create": - flags |= 0x10; // XMLCONFIG_CREATE - break; - case "delete": - flags |= 0x20; // XMLCONFIG_DELETE - break; - default: - this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, actionValue, "create", "delete")); - break; - } - } - break; - case "ElementId": - elementId = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "ElementPath": - elementPath = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "File": - file = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Name": - name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Node": - if (nested) - { - this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, element.Parent.Name.LocalName)); - } - else - { - var nodeValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - switch (nodeValue) - { - case "element": - flags |= 0x1; // XMLCONFIG_ELEMENT - break; - case "value": - flags |= 0x2; // XMLCONFIG_VALUE - break; - case "document": - flags |= 0x4; // XMLCONFIG_DOCUMENT - break; - default: - this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, nodeValue, "element", "value", "document")); - break; - } - } - break; - case "On": - if (nested) - { - this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, element.Parent.Name.LocalName)); - } - else - { - var onValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - switch (onValue) - { - case "install": - flags |= 0x100; // XMLCONFIG_INSTALL - break; - case "uninstall": - flags |= 0x200; // XMLCONFIG_UNINSTALL - break; - default: - this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, onValue, "install", "uninstall")); - break; - } - } - break; - case "PreserveModifiedDate": - if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - flags |= 0x00001000; // XMLCONFIG_PRESERVE_MODIFIED - } - break; - case "Sequence": - sequence = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, Int16.MaxValue); - break; - case "Value": - value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "VerifyPath": - verifyPath = 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("uxc", componentId, file, elementId, elementPath); - } - - if (null == file) - { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "File")); - } - - if (null == elementId && null == elementPath) - { - this.Messaging.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, element.Name.LocalName, "ElementId", "ElementPath")); - } - else if (null != elementId) - { - if (null != elementPath) - { - this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "ElementId", "ElementPath")); - } - - if (0 != flags) - { - this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, "ElementId", "Action", "Node", "On")); - } - - this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, UtilSymbolDefinitions.XmlConfig, elementId); - } - - // find unexpected child elements - foreach (var child in element.Elements()) - { - if (this.Namespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "XmlConfig": - if (nested) - { - this.Messaging.Write(ErrorMessages.UnexpectedElement(sourceLineNumbers, element.Name.LocalName, child.Name.LocalName)); - } - else - { - this.ParseXmlConfigElement(intermediate, section, child, componentId, true); - } - 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 XmlConfigSymbol(sourceLineNumbers, id) - { - File = file, - ElementId = elementId, - ElementPath = elementPath, - VerifyPath = verifyPath, - Name = name, - Value = value, - Flags = flags, - ComponentRef = componentId, - }); - - if (CompilerConstants.IntegerNotSet != sequence) - { - symbol.Sequence = sequence; - } - } - - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedXmlConfig", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - } - - /// - /// Match evaluator to escape properties in a string. - /// - private string EscapeProperties(Match match) - { - string escape = null; - switch (match.Value) - { - case "[": - escape = @"[\[]"; - break; - case "]": - escape = @"[\]]"; - break; - } - - return escape; - } - - private int CreateIntegerFromBitArray(BitArray bits) - { - if (32 != bits.Length) - { - throw new ArgumentException(String.Format("Can only convert a bit array with 32-bits to integer. Actual number of bits in array: {0}", bits.Length), "bits"); - } - - var intArray = new int[1]; - bits.CopyTo(intArray, 0); - - return intArray[0]; - } - - private bool TrySetBitFromName(string[] attributeNames, string attributeName, YesNoType attributeValue, BitArray bits, int offset) - { - for (var i = 0; i < attributeNames.Length; i++) - { - if (attributeName.Equals(attributeNames[i], StringComparison.Ordinal)) - { - bits.Set(i + offset, YesNoType.Yes == attributeValue); - return true; - } - } - - return false; - } - - private void AddReferenceToSchedXmlFile(SourceLineNumber sourceLineNumbers, IntermediateSection section) - { - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedXmlFile", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); - } - - /// - /// Private class that stores the data from a parsed PerformanceCounter element. - /// - private class ParsedPerformanceCounter - { - internal ParsedPerformanceCounter(string name, string help, System.Diagnostics.PerformanceCounterType type, int language) - { - this.Name = name; - this.Help = help; - this.Type = (int)type; - this.Language = language.ToString("D3", CultureInfo.InvariantCulture); - } - - internal string Name { get; } - - internal string Help { get; } - - internal int Type { get; } - - internal string Language { get; } - } - } -} diff --git a/src/wixext/UtilConstants.cs b/src/wixext/UtilConstants.cs deleted file mode 100644 index 28ff368f..00000000 --- a/src/wixext/UtilConstants.cs +++ /dev/null @@ -1,17 +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.Util -{ - /// - /// Constants used by Utility Extension. - /// - internal static class UtilConstants - { - internal static readonly string[] FilePermissions = { "Read", "Write", "Append", "ReadExtendedAttributes", "WriteExtendedAttributes", "Execute", null, "ReadAttributes", "WriteAttributes" }; - internal static readonly string[] FolderPermissions = { "Read", "CreateFile", "CreateChild", "ReadExtendedAttributes", "WriteExtendedAttributes", "Traverse", "DeleteChild", "ReadAttributes", "WriteAttributes" }; - internal static readonly string[] GenericPermissions = { "GenericAll", "GenericExecute", "GenericWrite", "GenericRead" }; - internal static readonly string[] RegistryPermissions = { "Read", "Write", "CreateSubkeys", "EnumerateSubkeys", "Notify", "CreateLink" }; - internal static readonly string[] ServicePermissions = { "ServiceQueryConfig", "ServiceChangeConfig", "ServiceQueryStatus", "ServiceEnumerateDependents", "ServiceStart", "ServiceStop", "ServicePauseContinue", "ServiceInterrogate", "ServiceUserDefinedControl" }; - internal static readonly string[] StandardPermissions = { "Delete", "ReadPermission", "ChangePermission", "TakeOwnership", "Synchronize" }; - } -} diff --git a/src/wixext/UtilDecompiler.cs b/src/wixext/UtilDecompiler.cs deleted file mode 100644 index 9ef3390f..00000000 --- a/src/wixext/UtilDecompiler.cs +++ /dev/null @@ -1,1543 +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.Extensions -{ -#if TODO_CONSIDER_DECOMPILER - using System; - using System.IO; - using System.Text; - using System.Collections; - using System.Diagnostics; - using System.Globalization; - - using Util = WixToolset.Extensions.Serialize.Util; - using WixToolset.Data; - using WixToolset.Extensibility; - using Wix = WixToolset.Data.Serialize; - - /// - /// The decompiler for the WiX Toolset Utility Extension. - /// - public sealed class UtilDecompiler : DecompilerExtension - { - /// - /// Creates a decompiler for Utility Extension. - /// - public UtilDecompiler() - { - this.TableDefinitions = UtilExtensionData.GetExtensionTableDefinitions(); - } - - /// - /// Get the extensions library to be removed. - /// - /// Table definitions for library. - /// Library to remove from decompiled output. - public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions) - { - return UtilExtensionData.GetExtensionLibrary(tableDefinitions); - } - - /// - /// Called at the beginning of the decompilation of a database. - /// - /// The collection of all tables. - public override void Initialize(TableIndexedCollection tables) - { - this.CleanupSecureCustomProperties(tables); - this.CleanupInternetShortcutRemoveFileTables(tables); - } - - /// - /// Decompile the SecureCustomProperties field to PropertyRefs for known extension properties. - /// - /// - /// If we've referenced any of the suite or directory properties, add - /// a PropertyRef to refer to the Property (and associated custom action) - /// from the extension's library. Then remove the property from - /// SecureCustomExtensions property so later decompilation won't create - /// new Property elements. - /// - /// The collection of all tables. - private void CleanupSecureCustomProperties(TableIndexedCollection tables) - { - Table propertyTable = tables["Property"]; - - if (null != propertyTable) - { - foreach (Row row in propertyTable.Rows) - { - if ("SecureCustomProperties" == row[0].ToString()) - { - StringBuilder remainingProperties = new StringBuilder(); - string[] secureCustomProperties = row[1].ToString().Split(';'); - foreach (string property in secureCustomProperties) - { - if (property.StartsWith("WIX_SUITE_", StringComparison.Ordinal) || property.StartsWith("WIX_DIR_", StringComparison.Ordinal) - || property.StartsWith("WIX_ACCOUNT_", StringComparison.Ordinal)) - { - Wix.PropertyRef propertyRef = new Wix.PropertyRef(); - propertyRef.Id = property; - this.Core.RootElement.AddChild(propertyRef); - } - else - { - if (0 < remainingProperties.Length) - { - remainingProperties.Append(";"); - } - remainingProperties.Append(property); - } - } - - row[1] = remainingProperties.ToString(); - break; - } - } - } - } - - /// - /// Remove RemoveFile rows that the InternetShortcut compiler extension adds for us. - /// - /// The collection of all tables. - private void CleanupInternetShortcutRemoveFileTables(TableIndexedCollection tables) - { - // index the WixInternetShortcut table - Table wixInternetShortcutTable = tables["WixInternetShortcut"]; - Hashtable wixInternetShortcuts = new Hashtable(); - if (null != wixInternetShortcutTable) - { - foreach (Row row in wixInternetShortcutTable.Rows) - { - wixInternetShortcuts.Add(row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), row); - } - } - - // remove the RemoveFile rows with primary keys that match the WixInternetShortcut table's - Table removeFileTable = tables["RemoveFile"]; - if (null != removeFileTable) - { - for (int i = removeFileTable.Rows.Count - 1; 0 <= i; i--) - { - if (null != wixInternetShortcuts[removeFileTable.Rows[i][0]]) - { - removeFileTable.Rows.RemoveAt(i); - } - } - } - } - - /// - /// Decompiles an extension table. - /// - /// The table to decompile. - public override void DecompileTable(Table table) - { - switch (table.Name) - { - case "WixCloseApplication": - this.DecompileWixCloseApplicationTable(table); - break; - case "WixRemoveFolderEx": - this.DecompileWixRemoveFolderExTable(table); - break; - case "WixRestartResource": - this.DecompileWixRestartResourceTable(table); - break; - case "FileShare": - this.DecompileFileShareTable(table); - break; - case "FileSharePermissions": - this.DecompileFileSharePermissionsTable(table); - break; - case "WixInternetShortcut": - this.DecompileWixInternetShortcutTable(table); - break; - case "Group": - this.DecompileGroupTable(table); - break; - case "Perfmon": - this.DecompilePerfmonTable(table); - break; - case "PerfmonManifest": - this.DecompilePerfmonManifestTable(table); - break; - case "EventManifest": - this.DecompileEventManifestTable(table); - break; - case "SecureObjects": - this.DecompileSecureObjectsTable(table); - break; - case "ServiceConfig": - this.DecompileServiceConfigTable(table); - break; - case "User": - this.DecompileUserTable(table); - break; - case "UserGroup": - this.DecompileUserGroupTable(table); - break; - case "XmlConfig": - this.DecompileXmlConfigTable(table); - break; - case "XmlFile": - // XmlFile decompilation has been moved to FinalizeXmlFileTable function - break; - default: - base.DecompileTable(table); - break; - } - } - - /// - /// Finalize decompilation. - /// - /// The collection of all tables. - public override void Finish(TableIndexedCollection tables) - { - this.FinalizePerfmonTable(tables); - this.FinalizePerfmonManifestTable(tables); - this.FinalizeSecureObjectsTable(tables); - this.FinalizeServiceConfigTable(tables); - this.FinalizeXmlConfigTable(tables); - this.FinalizeXmlFileTable(tables); - this.FinalizeEventManifestTable(tables); - } - - /// - /// Decompile the WixCloseApplication table. - /// - /// The table to decompile. - private void DecompileWixCloseApplicationTable(Table table) - { - foreach (Row row in table.Rows) - { - Util.CloseApplication closeApplication = new Util.CloseApplication(); - - closeApplication.Id = (string)row[0]; - - closeApplication.Target = (string)row[1]; - - if (null != row[2]) - { - closeApplication.Description = (string)row[2]; - } - - if (null != row[3]) - { - closeApplication.Content = (string)row[3]; - } - - // set defaults - closeApplication.CloseMessage = Util.YesNoType.no; - closeApplication.RebootPrompt = Util.YesNoType.yes; - closeApplication.ElevatedCloseMessage = Util.YesNoType.no; - - if (null != row[4]) - { - int attribute = (int)row[4]; - - closeApplication.CloseMessage = (0x1 == (attribute & 0x1)) ? Util.YesNoType.yes : Util.YesNoType.no; - closeApplication.RebootPrompt = (0x2 == (attribute & 0x2)) ? Util.YesNoType.yes : Util.YesNoType.no; - closeApplication.ElevatedCloseMessage = (0x4 == (attribute & 0x4)) ? Util.YesNoType.yes : Util.YesNoType.no; - } - - if (null != row[5]) - { - closeApplication.Sequence = (int)row[5]; - } - - if (null != row[6]) - { - closeApplication.Property = (string)row[6]; - } - - this.Core.RootElement.AddChild(closeApplication); - } - } - - /// - /// Decompile the WixRemoveFolderEx table. - /// - /// The table to decompile. - private void DecompileWixRemoveFolderExTable(Table table) - { - foreach (Row row in table.Rows) - { - // Set the Id even if auto-generated previously. - Util.RemoveFolderEx removeFolder = new Util.RemoveFolderEx(); - removeFolder.Id = (string)row[0]; - removeFolder.Property = (string)row[2]; - - int installMode = (int)row[3]; - switch ((UtilCompiler.WixRemoveFolderExOn)installMode) - { - case UtilCompiler.WixRemoveFolderExOn.Install: - removeFolder.On = Util.RemoveFolderEx.OnType.install; - break; - - case UtilCompiler.WixRemoveFolderExOn.Uninstall: - removeFolder.On = Util.RemoveFolderEx.OnType.uninstall; - break; - - case UtilCompiler.WixRemoveFolderExOn.Both: - removeFolder.On = Util.RemoveFolderEx.OnType.both; - break; - - default: - this.Core.OnMessage(WixWarnings.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, "InstallMode", installMode)); - break; - } - - // Add to the appropriate Component or section element. - string componentId = (string)row[1]; - Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", componentId); - if (null != component) - { - component.AddChild(removeFolder); - } - else - { - this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", componentId, "Component")); - } - } - } - - /// - /// Decompile the WixRestartResource table. - /// - /// The table to decompile. - private void DecompileWixRestartResourceTable(Table table) - { - foreach (Row row in table.Rows) - { - // Set the Id even if auto-generated previously. - Util.RestartResource restartResource = new Util.RestartResource(); - restartResource.Id = (string)row[0]; - - // Determine the resource type and set accordingly. - string resource = (string)row[2]; - int attributes = (int)row[3]; - UtilCompiler.WixRestartResourceAttributes type = (UtilCompiler.WixRestartResourceAttributes)(attributes & (int)UtilCompiler.WixRestartResourceAttributes.TypeMask); - - switch (type) - { - case UtilCompiler.WixRestartResourceAttributes.Filename: - restartResource.Path = resource; - break; - - case UtilCompiler.WixRestartResourceAttributes.ProcessName: - restartResource.ProcessName = resource; - break; - - case UtilCompiler.WixRestartResourceAttributes.ServiceName: - restartResource.ServiceName = resource; - break; - - default: - this.Core.OnMessage(WixWarnings.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, "Attributes", attributes)); - break; - } - - // Add to the appropriate Component or section element. - string componentId = (string)row[1]; - if (!String.IsNullOrEmpty(componentId)) - { - Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", componentId); - if (null != component) - { - component.AddChild(restartResource); - } - else - { - this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", componentId, "Component")); - } - } - else - { - this.Core.RootElement.AddChild(restartResource); - } - } - } - - /// - /// Decompile the FileShare table. - /// - /// The table to decompile. - private void DecompileFileShareTable(Table table) - { - foreach (Row row in table.Rows) - { - Util.FileShare fileShare = new Util.FileShare(); - - fileShare.Id = (string)row[0]; - - fileShare.Name = (string)row[1]; - - if (null != row[3]) - { - fileShare.Description = (string)row[3]; - } - - // the Directory_ column is set by the parent Component - - // the User_ and Permissions columns are deprecated - - Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); - if (null != component) - { - component.AddChild(fileShare); - } - else - { - this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); - } - this.Core.IndexElement(row, fileShare); - } - } - - /// - /// Decompile the FileSharePermissions table. - /// - /// The table to decompile. - private void DecompileFileSharePermissionsTable(Table table) - { - foreach (Row row in table.Rows) - { - Util.FileSharePermission fileSharePermission = new Util.FileSharePermission(); - - fileSharePermission.User = (string)row[1]; - - string[] specialPermissions = UtilConstants.FolderPermissions; - int permissions = (int)row[2]; - for (int i = 0; i < 32; i++) - { - if (0 != ((permissions >> i) & 1)) - { - string name = null; - - if (16 > i && specialPermissions.Length > i) - { - name = specialPermissions[i]; - } - else if (28 > i && UtilConstants.StandardPermissions.Length > (i - 16)) - { - name = UtilConstants.StandardPermissions[i - 16]; - } - else if (0 <= (i - 28) && UtilConstants.GenericPermissions.Length > (i - 28)) - { - name = UtilConstants.GenericPermissions[i - 28]; - } - - if (null == name) - { - this.Core.OnMessage(WixWarnings.UnknownPermission(row.SourceLineNumbers, row.Table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), i)); - } - else - { - switch (name) - { - case "ChangePermission": - fileSharePermission.ChangePermission = Util.YesNoType.yes; - break; - case "CreateChild": - fileSharePermission.CreateChild = Util.YesNoType.yes; - break; - case "CreateFile": - fileSharePermission.CreateFile = Util.YesNoType.yes; - break; - case "Delete": - fileSharePermission.Delete = Util.YesNoType.yes; - break; - case "DeleteChild": - fileSharePermission.DeleteChild = Util.YesNoType.yes; - break; - case "GenericAll": - fileSharePermission.GenericAll = Util.YesNoType.yes; - break; - case "GenericExecute": - fileSharePermission.GenericExecute = Util.YesNoType.yes; - break; - case "GenericRead": - fileSharePermission.GenericRead = Util.YesNoType.yes; - break; - case "GenericWrite": - fileSharePermission.GenericWrite = Util.YesNoType.yes; - break; - case "Read": - fileSharePermission.Read = Util.YesNoType.yes; - break; - case "ReadAttributes": - fileSharePermission.ReadAttributes = Util.YesNoType.yes; - break; - case "ReadExtendedAttributes": - fileSharePermission.ReadExtendedAttributes = Util.YesNoType.yes; - break; - case "ReadPermission": - fileSharePermission.ReadPermission = Util.YesNoType.yes; - break; - case "Synchronize": - fileSharePermission.Synchronize = Util.YesNoType.yes; - break; - case "TakeOwnership": - fileSharePermission.TakeOwnership = Util.YesNoType.yes; - break; - case "Traverse": - fileSharePermission.Traverse = Util.YesNoType.yes; - break; - case "WriteAttributes": - fileSharePermission.WriteAttributes = Util.YesNoType.yes; - break; - case "WriteExtendedAttributes": - fileSharePermission.WriteExtendedAttributes = Util.YesNoType.yes; - break; - default: - Debug.Fail(String.Format("Unknown permission '{0}'.", name)); - break; - } - } - } - } - - Util.FileShare fileShare = (Util.FileShare)this.Core.GetIndexedElement("FileShare", (string)row[0]); - if (null != fileShare) - { - fileShare.AddChild(fileSharePermission); - } - else - { - this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "FileShare_", (string)row[0], "FileShare")); - } - } - } - - /// - /// Decompile the Group table. - /// - /// The table to decompile. - private void DecompileGroupTable(Table table) - { - foreach (Row row in table.Rows) - { - Util.Group group = new Util.Group(); - - group.Id = (string)row[0]; - - if (null != row[1]) - { - this.Core.OnMessage(WixWarnings.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, "Component_", (string)row[1])); - } - - group.Name = (string)row[2]; - - if (null != row[3]) - { - group.Domain = (string)row[3]; - } - - this.Core.RootElement.AddChild(group); - } - } - - /// - /// Decompile the WixInternetShortcut table. - /// - /// The table to decompile. - private void DecompileWixInternetShortcutTable(Table table) - { - foreach (Row row in table.Rows) - { - Util.InternetShortcut internetShortcut = new Util.InternetShortcut(); - internetShortcut.Id = (string)row[0]; - internetShortcut.Directory = (string)row[2]; - // remove .lnk/.url extension because compiler extension adds it back for us - internetShortcut.Name = Path.ChangeExtension((string)row[3], null); - internetShortcut.Target = (string)row[4]; - internetShortcut.IconFile = (string)row[6]; - internetShortcut.IconIndex = (int)row[7]; - - UtilCompiler.InternetShortcutType shortcutType = (UtilCompiler.InternetShortcutType)row[5]; - switch (shortcutType) - { - case UtilCompiler.InternetShortcutType.Link: - internetShortcut.Type = Util.InternetShortcut.TypeType.link; - break; - case UtilCompiler.InternetShortcutType.Url: - internetShortcut.Type = Util.InternetShortcut.TypeType.url; - break; - } - - Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]); - if (null != component) - { - component.AddChild(internetShortcut); - } - else - { - this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); - } - - this.Core.IndexElement(row, internetShortcut); - } - } - - /// - /// Decompile the Perfmon table. - /// - /// The table to decompile. - private void DecompilePerfmonTable(Table table) - { - foreach (Row row in table.Rows) - { - Util.PerfCounter perfCounter = new Util.PerfCounter(); - - perfCounter.Name = (string)row[2]; - - this.Core.IndexElement(row, perfCounter); - } - } - - /// - /// Decompile the PerfmonManifest table. - /// - /// The table to decompile. - private void DecompilePerfmonManifestTable(Table table) - { - foreach (Row row in table.Rows) - { - Util.PerfCounterManifest perfCounterManifest = new Util.PerfCounterManifest(); - - perfCounterManifest.ResourceFileDirectory = (string)row[2]; - - this.Core.IndexElement(row, perfCounterManifest); - } - } - - /// - /// Decompile the EventManifest table. - /// - /// The table to decompile. - private void DecompileEventManifestTable(Table table) - { - foreach (Row row in table.Rows) - { - Util.EventManifest eventManifest = new Util.EventManifest(); - this.Core.IndexElement(row, eventManifest); - } - } - - /// - /// Decompile the SecureObjects table. - /// - /// The table to decompile. - private void DecompileSecureObjectsTable(Table table) - { - foreach (Row row in table.Rows) - { - Util.PermissionEx permissionEx = new Util.PermissionEx(); - - string[] specialPermissions; - switch ((string)row[1]) - { - case "CreateFolder": - specialPermissions = UtilConstants.FolderPermissions; - break; - case "File": - specialPermissions = UtilConstants.FilePermissions; - break; - case "Registry": - specialPermissions = UtilConstants.RegistryPermissions; - break; - case "ServiceInstall": - specialPermissions = UtilConstants.ServicePermissions; - break; - default: - this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, row.Table.Name, row.Fields[1].Column.Name, row[1])); - return; - } - - int permissionBits = (int)row[4]; - for (int i = 0; i < 32; i++) - { - if (0 != ((permissionBits >> i) & 1)) - { - string name = null; - - if (16 > i && specialPermissions.Length > i) - { - name = specialPermissions[i]; - } - else if (28 > i && UtilConstants.StandardPermissions.Length > (i - 16)) - { - name = UtilConstants.StandardPermissions[i - 16]; - } - else if (0 <= (i - 28) && UtilConstants.GenericPermissions.Length > (i - 28)) - { - name = UtilConstants.GenericPermissions[i - 28]; - } - - if (null == name) - { - this.Core.OnMessage(WixWarnings.UnknownPermission(row.SourceLineNumbers, row.Table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), i)); - } - else - { - switch (name) - { - case "Append": - permissionEx.Append = Util.YesNoType.yes; - break; - case "ChangePermission": - permissionEx.ChangePermission = Util.YesNoType.yes; - break; - case "CreateChild": - permissionEx.CreateChild = Util.YesNoType.yes; - break; - case "CreateFile": - permissionEx.CreateFile = Util.YesNoType.yes; - break; - case "CreateLink": - permissionEx.CreateLink = Util.YesNoType.yes; - break; - case "CreateSubkeys": - permissionEx.CreateSubkeys = Util.YesNoType.yes; - break; - case "Delete": - permissionEx.Delete = Util.YesNoType.yes; - break; - case "DeleteChild": - permissionEx.DeleteChild = Util.YesNoType.yes; - break; - case "EnumerateSubkeys": - permissionEx.EnumerateSubkeys = Util.YesNoType.yes; - break; - case "Execute": - permissionEx.Execute = Util.YesNoType.yes; - break; - case "GenericAll": - permissionEx.GenericAll = Util.YesNoType.yes; - break; - case "GenericExecute": - permissionEx.GenericExecute = Util.YesNoType.yes; - break; - case "GenericRead": - permissionEx.GenericRead = Util.YesNoType.yes; - break; - case "GenericWrite": - permissionEx.GenericWrite = Util.YesNoType.yes; - break; - case "Notify": - permissionEx.Notify = Util.YesNoType.yes; - break; - case "Read": - permissionEx.Read = Util.YesNoType.yes; - break; - case "ReadAttributes": - permissionEx.ReadAttributes = Util.YesNoType.yes; - break; - case "ReadExtendedAttributes": - permissionEx.ReadExtendedAttributes = Util.YesNoType.yes; - break; - case "ReadPermission": - permissionEx.ReadPermission = Util.YesNoType.yes; - break; - case "ServiceChangeConfig": - permissionEx.ServiceChangeConfig = Util.YesNoType.yes; - break; - case "ServiceEnumerateDependents": - permissionEx.ServiceEnumerateDependents = Util.YesNoType.yes; - break; - case "ServiceInterrogate": - permissionEx.ServiceInterrogate = Util.YesNoType.yes; - break; - case "ServicePauseContinue": - permissionEx.ServicePauseContinue = Util.YesNoType.yes; - break; - case "ServiceQueryConfig": - permissionEx.ServiceQueryConfig = Util.YesNoType.yes; - break; - case "ServiceQueryStatus": - permissionEx.ServiceQueryStatus = Util.YesNoType.yes; - break; - case "ServiceStart": - permissionEx.ServiceStart = Util.YesNoType.yes; - break; - case "ServiceStop": - permissionEx.ServiceStop = Util.YesNoType.yes; - break; - case "ServiceUserDefinedControl": - permissionEx.ServiceUserDefinedControl = Util.YesNoType.yes; - break; - case "Synchronize": - permissionEx.Synchronize = Util.YesNoType.yes; - break; - case "TakeOwnership": - permissionEx.TakeOwnership = Util.YesNoType.yes; - break; - case "Traverse": - permissionEx.Traverse = Util.YesNoType.yes; - break; - case "Write": - permissionEx.Write = Util.YesNoType.yes; - break; - case "WriteAttributes": - permissionEx.WriteAttributes = Util.YesNoType.yes; - break; - case "WriteExtendedAttributes": - permissionEx.WriteExtendedAttributes = Util.YesNoType.yes; - break; - default: - throw new InvalidOperationException(String.Format("Unknown permission attribute '{0}'.", name)); - } - } - } - } - - if (null != row[2]) - { - permissionEx.Domain = (string)row[2]; - } - - permissionEx.User = (string)row[3]; - - this.Core.IndexElement(row, permissionEx); - } - } - - /// - /// Decompile the ServiceConfig table. - /// - /// The table to decompile. - private void DecompileServiceConfigTable(Table table) - { - foreach (Row row in table.Rows) - { - Util.ServiceConfig serviceConfig = new Util.ServiceConfig(); - - serviceConfig.ServiceName = (string)row[0]; - - switch ((string)row[3]) - { - case "none": - serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.none; - break; - case "reboot": - serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.reboot; - break; - case "restart": - serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.restart; - break; - case "runCommand": - serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.runCommand; - break; - default: - this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[3].Column.Name, row[3])); - break; - } - - switch ((string)row[4]) - { - case "none": - serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.none; - break; - case "reboot": - serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.reboot; - break; - case "restart": - serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.restart; - break; - case "runCommand": - serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.runCommand; - break; - default: - this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[4].Column.Name, row[4])); - break; - } - - switch ((string)row[5]) - { - case "none": - serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.none; - break; - case "reboot": - serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.reboot; - break; - case "restart": - serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.restart; - break; - case "runCommand": - serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.runCommand; - break; - default: - this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[5].Column.Name, row[5])); - break; - } - - if (null != row[6]) - { - serviceConfig.ResetPeriodInDays = (int)row[6]; - } - - if (null != row[7]) - { - serviceConfig.RestartServiceDelayInSeconds = (int)row[7]; - } - - if (null != row[8]) - { - serviceConfig.ProgramCommandLine = (string)row[8]; - } - - if (null != row[9]) - { - serviceConfig.RebootMessage = (string)row[9]; - } - - this.Core.IndexElement(row, serviceConfig); - } - } - - /// - /// Decompile the User table. - /// - /// The table to decompile. - private void DecompileUserTable(Table table) - { - foreach (Row row in table.Rows) - { - Util.User user = new Util.User(); - - user.Id = (string)row[0]; - - user.Name = (string)row[2]; - - if (null != row[3]) - { - user.Domain = (string)row[3]; - } - - if (null != row[4]) - { - user.Password = (string)row[4]; - } - - if (null != row[5]) - { - int attributes = (int)row[5]; - - if (UtilCompiler.UserDontExpirePasswrd == (attributes & UtilCompiler.UserDontExpirePasswrd)) - { - user.PasswordNeverExpires = Util.YesNoType.yes; - } - - if (UtilCompiler.UserPasswdCantChange == (attributes & UtilCompiler.UserPasswdCantChange)) - { - user.CanNotChangePassword = Util.YesNoType.yes; - } - - if (UtilCompiler.UserPasswdChangeReqdOnLogin == (attributes & UtilCompiler.UserPasswdChangeReqdOnLogin)) - { - user.PasswordExpired = Util.YesNoType.yes; - } - - if (UtilCompiler.UserDisableAccount == (attributes & UtilCompiler.UserDisableAccount)) - { - user.Disabled = Util.YesNoType.yes; - } - - if (UtilCompiler.UserFailIfExists == (attributes & UtilCompiler.UserFailIfExists)) - { - user.FailIfExists = Util.YesNoType.yes; - } - - if (UtilCompiler.UserUpdateIfExists == (attributes & UtilCompiler.UserUpdateIfExists)) - { - user.UpdateIfExists = Util.YesNoType.yes; - } - - if (UtilCompiler.UserLogonAsService == (attributes & UtilCompiler.UserLogonAsService)) - { - user.LogonAsService = Util.YesNoType.yes; - } - - if (UtilCompiler.UserDontRemoveOnUninstall == (attributes & UtilCompiler.UserDontRemoveOnUninstall)) - { - user.RemoveOnUninstall = Util.YesNoType.no; - } - - if (UtilCompiler.UserDontCreateUser == (attributes & UtilCompiler.UserDontCreateUser)) - { - user.CreateUser = Util.YesNoType.no; - } - - if (UtilCompiler.UserNonVital == (attributes & UtilCompiler.UserNonVital)) - { - user.Vital = Util.YesNoType.no; - } - } - - if (null != row[1]) - { - Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]); - - if (null != component) - { - component.AddChild(user); - } - else - { - this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); - } - } - else - { - this.Core.RootElement.AddChild(user); - } - this.Core.IndexElement(row, user); - } - } - - /// - /// Decompile the UserGroup table. - /// - /// The table to decompile. - private void DecompileUserGroupTable(Table table) - { - foreach (Row row in table.Rows) - { - Util.User user = (Util.User)this.Core.GetIndexedElement("User", (string)row[0]); - - if (null != user) - { - Util.GroupRef groupRef = new Util.GroupRef(); - - groupRef.Id = (string)row[1]; - - user.AddChild(groupRef); - } - else - { - this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Group_", (string)row[0], "Group")); - } - } - } - - /// - /// Decompile the XmlConfig table. - /// - /// The table to decompile. - private void DecompileXmlConfigTable(Table table) - { - foreach (Row row in table.Rows) - { - Util.XmlConfig xmlConfig = new Util.XmlConfig(); - - xmlConfig.Id = (string)row[0]; - - xmlConfig.File = (string)row[1]; - - xmlConfig.ElementPath = (string)row[2]; - - if (null != row[3]) - { - xmlConfig.VerifyPath = (string)row[3]; - } - - if (null != row[4]) - { - xmlConfig.Name = (string)row[4]; - } - - if (null != row[5]) - { - xmlConfig.Value = (string)row[5]; - } - - int flags = (int)row[6]; - - if (0x1 == (flags & 0x1)) - { - xmlConfig.Node = Util.XmlConfig.NodeType.element; - } - else if (0x2 == (flags & 0x2)) - { - xmlConfig.Node = Util.XmlConfig.NodeType.value; - } - else if (0x4 == (flags & 0x4)) - { - xmlConfig.Node = Util.XmlConfig.NodeType.document; - } - - if (0x10 == (flags & 0x10)) - { - xmlConfig.Action = Util.XmlConfig.ActionType.create; - } - else if (0x20 == (flags & 0x20)) - { - xmlConfig.Action = Util.XmlConfig.ActionType.delete; - } - - if (0x100 == (flags & 0x100)) - { - xmlConfig.On = Util.XmlConfig.OnType.install; - } - else if (0x200 == (flags & 0x200)) - { - xmlConfig.On = Util.XmlConfig.OnType.uninstall; - } - - if (0x00001000 == (flags & 0x00001000)) - { - xmlConfig.PreserveModifiedDate = Util.YesNoType.yes; - } - - if (null != row[8]) - { - xmlConfig.Sequence = (int)row[8]; - } - - this.Core.IndexElement(row, xmlConfig); - } - } - - /// - /// Finalize the Perfmon table. - /// - /// The collection of all tables. - /// - /// Since the PerfCounter element nests under a File element, but - /// the Perfmon table does not have a foreign key relationship with - /// the File table (instead it has a formatted string that usually - /// refers to a file row - but doesn't have to), the nesting must - /// be inferred during finalization. - /// - private void FinalizePerfmonTable(TableIndexedCollection tables) - { - Table perfmonTable = tables["Perfmon"]; - - if (null != perfmonTable) - { - foreach (Row row in perfmonTable.Rows) - { - string formattedFile = (string)row[1]; - Util.PerfCounter perfCounter = (Util.PerfCounter)this.Core.GetIndexedElement(row); - - // try to "de-format" the File column's value to determine the proper parent File element - if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal)) - && formattedFile.EndsWith("]", StringComparison.Ordinal)) - { - string fileId = formattedFile.Substring(2, formattedFile.Length - 3); - - Wix.File file = (Wix.File)this.Core.GetIndexedElement("File", fileId); - if (null != file) - { - file.AddChild(perfCounter); - } - else - { - this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, perfmonTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "File", formattedFile, "File")); - } - } - else - { - this.Core.OnMessage(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "Perfmon")); - } - } - } - } - - /// - /// Finalize the PerfmonManifest table. - /// - /// The collection of all tables. - private void FinalizePerfmonManifestTable(TableIndexedCollection tables) - { - Table perfmonManifestTable = tables["PerfmonManifest"]; - - if (null != perfmonManifestTable) - { - foreach (Row row in perfmonManifestTable.Rows) - { - string formattedFile = (string)row[1]; - Util.PerfCounterManifest perfCounterManifest = (Util.PerfCounterManifest)this.Core.GetIndexedElement(row); - - // try to "de-format" the File column's value to determine the proper parent File element - if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal)) - && formattedFile.EndsWith("]", StringComparison.Ordinal)) - { - string fileId = formattedFile.Substring(2, formattedFile.Length - 3); - - Wix.File file = (Wix.File)this.Core.GetIndexedElement("File", fileId); - if (null != file) - { - file.AddChild(perfCounterManifest); - } - else - { - this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, perfCounterManifest.ResourceFileDirectory, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "File", formattedFile, "File")); - } - } - else - { - this.Core.OnMessage(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "PerfmonManifest")); - } - } - } - } - - /// - /// Finalize the SecureObjects table. - /// - /// The collection of all tables. - /// - /// Nests the PermissionEx elements below their parent elements. There are no declared foreign - /// keys for the parents of the SecureObjects table. - /// - private void FinalizeSecureObjectsTable(TableIndexedCollection tables) - { - Table createFolderTable = tables["CreateFolder"]; - Table secureObjectsTable = tables["SecureObjects"]; - - Hashtable createFolders = new Hashtable(); - - // index the CreateFolder table because the foreign key to this table from the - // LockPermissions table is only part of the primary key of this table - if (null != createFolderTable) - { - foreach (Row row in createFolderTable.Rows) - { - Wix.CreateFolder createFolder = (Wix.CreateFolder)this.Core.GetIndexedElement(row); - string directoryId = (string)row[0]; - - if (!createFolders.Contains(directoryId)) - { - createFolders.Add(directoryId, new ArrayList()); - } - ((ArrayList)createFolders[directoryId]).Add(createFolder); - } - } - - if (null != secureObjectsTable) - { - foreach (Row row in secureObjectsTable.Rows) - { - string id = (string)row[0]; - string table = (string)row[1]; - - Util.PermissionEx permissionEx = (Util.PermissionEx)this.Core.GetIndexedElement(row); - - if ("CreateFolder" == table) - { - ArrayList createFolderElements = (ArrayList)createFolders[id]; - - if (null != createFolderElements) - { - foreach (Wix.CreateFolder createFolder in createFolderElements) - { - createFolder.AddChild(permissionEx); - } - } - else - { - this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "SecureObjects", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table)); - } - } - else - { - Wix.IParentElement parentElement = (Wix.IParentElement)this.Core.GetIndexedElement(table, id); - - if (null != parentElement) - { - parentElement.AddChild(permissionEx); - } - else - { - this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "SecureObjects", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table)); - } - } - } - } - } - - /// - /// Finalize the ServiceConfig table. - /// - /// The collection of all tables. - /// - /// Since there is no foreign key from the ServiceName column to the - /// ServiceInstall table, this relationship must be handled late. - /// - private void FinalizeServiceConfigTable(TableIndexedCollection tables) - { - Table serviceConfigTable = tables["ServiceConfig"]; - Table serviceInstallTable = tables["ServiceInstall"]; - - Hashtable serviceInstalls = new Hashtable(); - - // index the ServiceInstall table because the foreign key used by the ServiceConfig - // table is actually the ServiceInstall.Name, not the ServiceInstall.ServiceInstall - // this is unfortunate because the service Name is not guaranteed to be unique, so - // decompiler must assume there could be multiple matches and add the ServiceConfig to each - // TODO: the Component column information should be taken into acount to accurately identify - // the correct column to use - if (null != serviceInstallTable) - { - foreach (Row row in serviceInstallTable.Rows) - { - string name = (string)row[1]; - Wix.ServiceInstall serviceInstall = (Wix.ServiceInstall)this.Core.GetIndexedElement(row); - - if (!serviceInstalls.Contains(name)) - { - serviceInstalls.Add(name, new ArrayList()); - } - - ((ArrayList)serviceInstalls[name]).Add(serviceInstall); - } - } - - if (null != serviceConfigTable) - { - foreach (Row row in serviceConfigTable.Rows) - { - Util.ServiceConfig serviceConfig = (Util.ServiceConfig)this.Core.GetIndexedElement(row); - - if (0 == (int)row[2]) - { - Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]); - - if (null != component) - { - component.AddChild(serviceConfig); - } - else - { - this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, serviceConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); - } - } - else - { - ArrayList serviceInstallElements = (ArrayList)serviceInstalls[row[0]]; - - if (null != serviceInstallElements) - { - foreach (Wix.ServiceInstall serviceInstall in serviceInstallElements) - { - serviceInstall.AddChild(serviceConfig); - } - } - else - { - this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, serviceConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ServiceName", (string)row[0], "ServiceInstall")); - } - } - } - } - } - - /// - /// Finalize the XmlConfig table. - /// - /// Collection of all tables. - private void FinalizeXmlConfigTable(TableIndexedCollection tables) - { - Table xmlConfigTable = tables["XmlConfig"]; - - if (null != xmlConfigTable) - { - foreach (Row row in xmlConfigTable.Rows) - { - Util.XmlConfig xmlConfig = (Util.XmlConfig)this.Core.GetIndexedElement(row); - - if (null == row[6] || 0 == (int)row[6]) - { - Util.XmlConfig parentXmlConfig = (Util.XmlConfig)this.Core.GetIndexedElement("XmlConfig", (string)row[2]); - - if (null != parentXmlConfig) - { - parentXmlConfig.AddChild(xmlConfig); - } - else - { - this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, xmlConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ElementPath", (string)row[2], "XmlConfig")); - } - } - else - { - Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[7]); - - if (null != component) - { - component.AddChild(xmlConfig); - } - else - { - this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, xmlConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[7], "Component")); - } - } - } - } - } - - - /// - /// Finalize the XmlFile table. - /// - /// The collection of all tables. - /// - /// Some of the XmlFile table rows are compiler generated from util:EventManifest node - /// These rows should not be appended to component. - /// - private void FinalizeXmlFileTable(TableIndexedCollection tables) - { - Table xmlFileTable = tables["XmlFile"]; - Table eventManifestTable = tables["EventManifest"]; - - if (null != xmlFileTable) - { - foreach (Row row in xmlFileTable.Rows) - { - bool bManifestGenerated = false; - string xmlFileConfigId = (string)row[0]; - if (null != eventManifestTable) - { - foreach (Row emrow in eventManifestTable.Rows) - { - string formattedFile = (string)emrow[1]; - if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal)) - && formattedFile.EndsWith("]", StringComparison.Ordinal)) - { - string fileId = formattedFile.Substring(2, formattedFile.Length - 3); - if (String.Equals(String.Concat("Config_", fileId, "ResourceFile"), xmlFileConfigId)) - { - Util.EventManifest eventManifest = (Util.EventManifest)this.Core.GetIndexedElement(emrow); - if (null != eventManifest) - { - eventManifest.ResourceFile = (string)row[4]; - } - bManifestGenerated = true; - } - - else if (String.Equals(String.Concat("Config_", fileId, "MessageFile"), xmlFileConfigId)) - { - Util.EventManifest eventManifest = (Util.EventManifest)this.Core.GetIndexedElement(emrow); - if (null != eventManifest) - { - eventManifest.MessageFile = (string)row[4]; - } - bManifestGenerated = true; - } - } - } - } - - if (true == bManifestGenerated) - continue; - - Util.XmlFile xmlFile = new Util.XmlFile(); - - xmlFile.Id = (string)row[0]; - xmlFile.File = (string)row[1]; - xmlFile.ElementPath = (string)row[2]; - - if (null != row[3]) - { - xmlFile.Name = (string)row[3]; - } - - if (null != row[4]) - { - xmlFile.Value = (string)row[4]; - } - - int flags = (int)row[5]; - if (0x1 == (flags & 0x1) && 0x2 == (flags & 0x2)) - { - this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, xmlFileTable.Name, row.Fields[5].Column.Name, row[5])); - } - else if (0x1 == (flags & 0x1)) - { - xmlFile.Action = Util.XmlFile.ActionType.createElement; - } - else if (0x2 == (flags & 0x2)) - { - xmlFile.Action = Util.XmlFile.ActionType.deleteValue; - } - else - { - xmlFile.Action = Util.XmlFile.ActionType.setValue; - } - - if (0x100 == (flags & 0x100)) - { - xmlFile.SelectionLanguage = Util.XmlFile.SelectionLanguageType.XPath; - } - - if (0x00001000 == (flags & 0x00001000)) - { - xmlFile.PreserveModifiedDate = Util.YesNoType.yes; - } - - if (0x00010000 == (flags & 0x00010000)) - { - xmlFile.Permanent = Util.YesNoType.yes; - } - - if (null != row[7]) - { - xmlFile.Sequence = (int)row[7]; - } - - Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[6]); - - if (null != component) - { - component.AddChild(xmlFile); - } - else - { - this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, xmlFileTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[6], "Component")); - } - } - } - } - - /// - /// Finalize the eventManifest table. - /// This function must be called after FinalizeXmlFileTable - /// - /// The collection of all tables. - private void FinalizeEventManifestTable(TableIndexedCollection tables) - { - Table eventManifestTable = tables["EventManifest"]; - - if (null != eventManifestTable) - { - foreach (Row row in eventManifestTable.Rows) - { - string formattedFile = (string)row[1]; - Util.EventManifest eventManifest = (Util.EventManifest)this.Core.GetIndexedElement(row); - - // try to "de-format" the File column's value to determine the proper parent File element - if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal)) - && formattedFile.EndsWith("]", StringComparison.Ordinal)) - { - string fileId = formattedFile.Substring(2, formattedFile.Length - 3); - - Wix.File file = (Wix.File)this.Core.GetIndexedElement("File", fileId); - if (null != file) - { - file.AddChild(eventManifest); - } - } - else - { - this.Core.OnMessage(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "EventManifest")); - } - } - } - } - } -#endif -} diff --git a/src/wixext/UtilErrors.cs b/src/wixext/UtilErrors.cs deleted file mode 100644 index b9ce1688..00000000 --- a/src/wixext/UtilErrors.cs +++ /dev/null @@ -1,49 +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.Util -{ - using System; - using System.Resources; - using WixToolset.Data; - - public static class UtilErrors - { - 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 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 IllegalFileValueInPerfmonOrManifest(string file, string table) - { - return Message(null, Ids.IllegalFileValueInPerfmonOrManifest, "The value '{0}' in the File column, {1} table is invalid. It should be in the form of '[#file]' or '[!file]'.", file, table); - } - - public static Message InvalidRegistryObject(SourceLineNumber sourceLineNumbers, string registryElementName) - { - return Message(sourceLineNumbers, Ids.InvalidRegistryObject, "The {0} element has no id and cannot have its permissions set. If you want to set permissions on a 'placeholder' registry key, force its creation by setting the ForceCreateOnInstall attribute to yes.", registryElementName); - } - - 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 - { - IllegalAttributeWithoutComponent = 5050, - IllegalElementWithoutComponent = 5051, - IllegalFileValueInPerfmonOrManifest = 5054, - InvalidRegistryObject = 5063, - } - } -} diff --git a/src/wixext/UtilExtensionData.cs b/src/wixext/UtilExtensionData.cs deleted file mode 100644 index d3ca3358..00000000 --- a/src/wixext/UtilExtensionData.cs +++ /dev/null @@ -1,23 +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.Util -{ - using WixToolset.Data; - using WixToolset.Extensibility; - - public sealed class UtilExtensionData : BaseExtensionData - { - public override string DefaultCulture => "en-US"; - - public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition) - { - symbolDefinition = UtilSymbolDefinitions.ByName(name); - return symbolDefinition != null; - } - - public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions) - { - return Intermediate.Load(typeof(UtilExtensionData).Assembly, "WixToolset.Util.util.wixlib", symbolDefinitions); - } - } -} diff --git a/src/wixext/UtilExtensionFactory.cs b/src/wixext/UtilExtensionFactory.cs deleted file mode 100644 index 08352813..00000000 --- a/src/wixext/UtilExtensionFactory.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.Util -{ - using System; - using System.Collections.Generic; - using WixToolset.Extensibility; - - public class UtilExtensionFactory : BaseExtensionFactory - { - protected override IReadOnlyCollection ExtensionTypes => new[] - { - typeof(UtilCompiler), - typeof(UtilExtensionData), - typeof(UtilWindowsInstallerBackendBinderExtension), - }; - } -} diff --git a/src/wixext/UtilTableDefinitions.cs b/src/wixext/UtilTableDefinitions.cs deleted file mode 100644 index 12f423cc..00000000 --- a/src/wixext/UtilTableDefinitions.cs +++ /dev/null @@ -1,319 +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.Util -{ - using WixToolset.Data.WindowsInstaller; - - public static class UtilTableDefinitions - { - public static readonly TableDefinition Wix4CloseApplication = new TableDefinition( - "Wix4CloseApplication", - UtilSymbolDefinitions.WixCloseApplication, - new[] - { - new ColumnDefinition("Wix4CloseApplication", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token in table.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Target", ColumnType.Localized, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Name of executable to ensure is closed.", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("Description", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Description string displayed to user when executable is in use.", modularizeType: ColumnModularizeType.Property, forceLocalizable: true), - new ColumnDefinition("Condition", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Condition, description: "Optional expression which skips the closing.", modularizeType: ColumnModularizeType.Condition, forceLocalizable: true), - new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 2147483647, description: "A 32-bit word that specifies the attribute flags to be applied."), - new ColumnDefinition("Sequence", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, minValue: 1, maxValue: 2147483647, description: "Sequence to order the closings by."), - new ColumnDefinition("Property", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, description: "Optional property that is set to the number of running instances of the app.", modularizeType: ColumnModularizeType.Property, forceLocalizable: true), - new ColumnDefinition("TerminateExitCode", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, minValue: 0, maxValue: 2147483647, description: "Exit code to return from a terminated application."), - new ColumnDefinition("Timeout", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, minValue: 1, maxValue: 2147483647, description: "Timeout in milliseconds before scheduling restart or terminating application."), - }, - symbolIdIsPrimaryKey: true - ); - - public static readonly TableDefinition Wix4RemoveFolderEx = new TableDefinition( - "Wix4RemoveFolderEx", - UtilSymbolDefinitions.WixRemoveFolderEx, - new[] - { - new ColumnDefinition("Wix4RemoveFolderEx", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Identifier for the WixRemoveFolderEx row in the package.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Property", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, description: "Name of Property that contains the root of the directory tree to remove.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("InstallMode", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 1, maxValue: 3, description: "1 == Remove only when the associated component is being installed (msiInstallStateLocal or msiInstallStateSource), 2 == Remove only when the associated component is being removed (msiInstallStateAbsent), 3 = Remove in either of the above cases."), - new ColumnDefinition("Condition", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Condition, description: "Optional expression which skips the removing of folders.", modularizeType: ColumnModularizeType.Condition, forceLocalizable: true), - }, - symbolIdIsPrimaryKey: true - ); - - public static readonly TableDefinition Wix4RemoveRegistryKeyEx = new TableDefinition( - "Wix4RemoveRegistryKeyEx", - UtilSymbolDefinitions.WixRemoveRegistryKeyEx, - new[] - { - new ColumnDefinition("Wix4RemoveRegistryKeyEx", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Identifier for the Wix4RemoveRegistryKeyEx row in the package.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Root", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: -1, maxValue: 3, description: "The predefined root key for the registry value, one of rrkEnum."), - new ColumnDefinition("Key", ColumnType.Localized, 255, primaryKey: false, nullable: false, ColumnCategory.RegPath, description: "The key for the registry value.", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("InstallMode", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 1, maxValue: 3, description: "1 == Remove only when the associated component is being installed (msiInstallStateLocal or msiInstallStateSource), 2 == Remove only when the associated component is being removed (msiInstallStateAbsent), 3 = Remove in either of the above cases."), - new ColumnDefinition("Condition", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Condition, description: "Optional expression to control whether the registry key is removed.", modularizeType: ColumnModularizeType.Condition, forceLocalizable: true), - }, - symbolIdIsPrimaryKey: true - ); - - public static readonly TableDefinition Wix4RestartResource = new TableDefinition( - "Wix4RestartResource", - UtilSymbolDefinitions.WixRestartResource, - new[] - { - new ColumnDefinition("Wix4RestartResource", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized identifier.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Resource", ColumnType.String, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "The resource to be registered with the Restart Manager.", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 2147483647, description: "A 32-bit word that specifies the type of resource and flags used for processing."), - }, - symbolIdIsPrimaryKey: true - ); - - public static readonly TableDefinition Wix4FileShare = new TableDefinition( - "Wix4FileShare", - UtilSymbolDefinitions.FileShare, - new[] - { - new ColumnDefinition("Wix4FileShare", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized identifier", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("ShareName", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "The actual share name used"), - new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Description", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Description string displayed for the file share"), - new ColumnDefinition("Directory_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Directory", keyColumn: 1, description: "Foreign key referencing directory that the share is created on", modularizeType: ColumnModularizeType.Column), - }, - symbolIdIsPrimaryKey: true - ); - - public static readonly TableDefinition Wix4FileSharePermissions = new TableDefinition( - "Wix4FileSharePermissions", - UtilSymbolDefinitions.FileSharePermissions, - new[] - { - new ColumnDefinition("Wix4FileShare_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "FileShare", keyColumn: 1, description: "FileShare that these premissions are to be applied to.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Wix4User_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Wix4User", description: "User that these premissions are to apply to.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Permissions", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, description: "Permissions int, as in EXPLICIT_ACCESS.grfAccessPermissions in MSDN"), - }, - symbolIdIsPrimaryKey: false - ); - - public static readonly TableDefinition Wix4Group = new TableDefinition( - "Wix4Group", - UtilSymbolDefinitions.Group, - new[] - { - new ColumnDefinition("Wix4Group", 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.Text, keyTable: "Component", keyColumn: 1, description: "Foreign key, Component used to determine install state", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Name", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Group name", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("Domain", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Group domain", modularizeType: ColumnModularizeType.Property), - }, - symbolIdIsPrimaryKey: true - ); - - public static readonly TableDefinition Wix4InternetShortcut = new TableDefinition( - "Wix4InternetShortcut", - UtilSymbolDefinitions.WixInternetShortcut, - new[] - { - new ColumnDefinition("Wix4InternetShortcut", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token in table.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Text, keyTable: "Component", keyColumn: 1, description: "Foreign key, Component used to determine install state", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Directory_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Directory", keyColumn: 1, description: "Foreign key referencing directory that the shortcut is created in", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Name", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Name used for shortcut.", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("Target", ColumnType.Localized, 0, primaryKey: false, nullable: false, ColumnCategory.Text, description: "URL target."), - new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, description: "Attribute flags that control how the shortcut is created."), - new ColumnDefinition("IconFile", ColumnType.Localized, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Icon file for shortcut", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("IconIndex", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Index of the icon being referenced."), - }, - symbolIdIsPrimaryKey: true - ); - - public static readonly TableDefinition Wix4PerformanceCategory = new TableDefinition( - "Wix4PerformanceCategory", - UtilSymbolDefinitions.PerformanceCategory, - new[] - { - new ColumnDefinition("Wix4PerformanceCategory", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token in table.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Component used to determine install state", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Name", ColumnType.String, 80, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Name of the performance counter category."), - new ColumnDefinition("IniData", ColumnType.Localized, 0, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Data that goes into the performance counter .ini file."), - new ColumnDefinition("ConstantData", ColumnType.Localized, 0, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Data that goes into the performance counter .h file."), - }, - symbolIdIsPrimaryKey: true - ); - - public static readonly TableDefinition Wix4Perfmon = new TableDefinition( - "Wix4Perfmon", - UtilSymbolDefinitions.Perfmon, - new[] - { - new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Component used to determine install state", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("File", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Formatted, description: "Name of .INI file", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("Name", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Text, description: "Service name in registry"), - }, - symbolIdIsPrimaryKey: false - ); - - public static readonly TableDefinition Wix4PerfmonManifest = new TableDefinition( - "Wix4PerfmonManifest", - UtilSymbolDefinitions.PerfmonManifest, - new[] - { - new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Component used to determine install state", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("File", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Formatted, description: "Name of perfmon manifest file", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("ResourceFileDirectory", ColumnType.String, 255, primaryKey: true, nullable: false, ColumnCategory.Formatted, description: "The path of the Resource File Directory"), - }, - symbolIdIsPrimaryKey: false - ); - - public static readonly TableDefinition Wix4EventManifest = new TableDefinition( - "Wix4EventManifest", - UtilSymbolDefinitions.EventManifest, - new[] - { - new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Component used to determine install state", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("File", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Formatted, description: "Name of event manifest file", modularizeType: ColumnModularizeType.Property), - }, - symbolIdIsPrimaryKey: false - ); - - public static readonly TableDefinition Wix4SecureObject = new TableDefinition( - "Wix4SecureObject", - UtilSymbolDefinitions.SecureObjects, - new[] - { - new ColumnDefinition("Wix4SecureObject", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token in Table", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Table", ColumnType.String, 32, primaryKey: true, nullable: false, ColumnCategory.Text, description: "Table SecureObject should be securing"), - new ColumnDefinition("Domain", ColumnType.String, 255, primaryKey: true, nullable: true, ColumnCategory.Text, description: "Domain half of user account to secure", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("User", ColumnType.String, 255, primaryKey: true, nullable: false, ColumnCategory.Text, description: "User name half of user account to secure", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Integer, minValue: 0, maxValue: 2147483647, description: "A 32-bit word that specifies the attribute flags to be applied."), - new ColumnDefinition("Permission", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, minValue: -2147483647, maxValue: 2147483647, description: "Permissions to grant to User"), - new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state", modularizeType: ColumnModularizeType.Column), - }, - symbolIdIsPrimaryKey: false - ); - - public static readonly TableDefinition Wix4ServiceConfig = new TableDefinition( - "Wix4ServiceConfig", - UtilSymbolDefinitions.ServiceConfig, - new[] - { - new ColumnDefinition("ServiceName", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Formatted, description: "Primary key, non-localized token"), - new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key, Component used to determine install state ", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("NewService", ColumnType.Number, 1, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 1, description: "Whether the affected service is being installed or already exists."), - new ColumnDefinition("FirstFailureActionType", ColumnType.String, 32, primaryKey: false, nullable: false, ColumnCategory.Text, description: "First failure action type for configured service to take."), - new ColumnDefinition("SecondFailureActionType", ColumnType.String, 32, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Second failure action type for configured service to take."), - new ColumnDefinition("ThirdFailureActionType", ColumnType.String, 32, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Third failure action type for configured service to take."), - new ColumnDefinition("ResetPeriodInDays", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Integer, minValue: 0, description: "Period after which to reset the failure count for the service."), - new ColumnDefinition("RestartServiceDelayInSeconds", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Integer, minValue: 0, description: "Period after which to restart the service after a given failure."), - new ColumnDefinition("ProgramCommandLine", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Command line for program to run if failure action is RUN_COMMAND."), - new ColumnDefinition("RebootMessage", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Message to show to users when rebooting if failure action is REBOOT."), - }, - symbolIdIsPrimaryKey: false - ); - - public static readonly TableDefinition Wix4TouchFile = new TableDefinition( - "Wix4TouchFile", - UtilSymbolDefinitions.WixTouchFile, - new[] - { - new ColumnDefinition("Wix4TouchFile", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Identifier for the Wix4TouchFile row in the package.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Path", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Formatted column that resolves to the path to touch.", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 1, maxValue: 63, description: "1 == Touch only when the associated component is being installed, 2 == Touch only when the associated component is being repaired , 4 == Touch only when the associated component is being removed, 16 = path is in 64-bit location, 32 = touching the file is vital."), - }, - symbolIdIsPrimaryKey: true - ); - - public static readonly TableDefinition Wix4User = new TableDefinition( - "Wix4User", - UtilSymbolDefinitions.User, - new[] - { - new ColumnDefinition("Wix4User", 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.Text, keyTable: "Component", keyColumn: 1, description: "Foreign key, Component used to determine install state", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Name", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "User name", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("Domain", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "User domain", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("Password", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "User password", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, minValue: 0, maxValue: 65535, description: "Attributes describing how to create the user"), - }, - symbolIdIsPrimaryKey: true - ); - - public static readonly TableDefinition Wix4UserGroup = new TableDefinition( - "Wix4UserGroup", - UtilSymbolDefinitions.UserGroup, - new[] - { - new ColumnDefinition("Wix4User_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Wix4User", keyColumn: 1, description: "User to be joined to a Group.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Wix4Group_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Wix4Group", keyColumn: 1, description: "Group to join User to.", modularizeType: ColumnModularizeType.Column), - }, - symbolIdIsPrimaryKey: false - ); - - public static readonly TableDefinition Wix4XmlFile = new TableDefinition( - "Wix4XmlFile", - UtilSymbolDefinitions.XmlFile, - new[] - { - new ColumnDefinition("Wix4XmlFile", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("File", ColumnType.Localized, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "The .XML file in which to write the information", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("ElementPath", ColumnType.Localized, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "The .XML file element to modify.", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("Name", ColumnType.Localized, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The .XML file node to set/add in the element.", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("Value", ColumnType.Localized, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The value to be written.", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("Flags", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 70143, description: "Flags"), - new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table referencing component that controls the installing of the .XML value.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Sequence", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Order to execute the XML modifications."), - }, - symbolIdIsPrimaryKey: true - ); - - public static readonly TableDefinition Wix4XmlConfig = new TableDefinition( - "Wix4XmlConfig", - UtilSymbolDefinitions.XmlConfig, - new[] - { - new ColumnDefinition("Wix4XmlConfig", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("File", ColumnType.Localized, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "The .XML file in which to write the information", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("ElementId", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "Wix4XmlConfig", keyColumn: 1, description: "A foreign key reference to another Wix4XmlConfig row if no attributes are set and the row referenced is a create element row.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("ElementPath", ColumnType.Localized, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The XPATH query for an element to modify or add children to. Must be null if ElementId is provided", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("VerifyPath", ColumnType.Localized, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The XPATH query run from ElementPath to verify whether a repair is necessary. Also used to uninstall.", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("Name", ColumnType.Localized, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The .XML file node to set/add in the element.", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("Value", ColumnType.Localized, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The value to be written.", modularizeType: ColumnModularizeType.Property), - new ColumnDefinition("Flags", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 65536, description: "Element=1,Value=2,Document=4,Create=16,Delete=32,Install=256,Uninstall=512"), - new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table referencing component that controls the installing of the .XML value.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("Sequence", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Order to execute the XML modifications."), - }, - symbolIdIsPrimaryKey: true - ); - - public static readonly TableDefinition Wix4FormatFile = new TableDefinition( - "Wix4FormatFile", - UtilSymbolDefinitions.WixFormatFiles, - new[] - { - new ColumnDefinition("Binary_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Binary", keyColumn: 1, description: "Binary data to be formatted.", modularizeType: ColumnModularizeType.Column), - new ColumnDefinition("File_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "File", keyColumn: 1, description: "File whose component controls the custom action and where the formatted data is written.", modularizeType: ColumnModularizeType.Column), - }, - symbolIdIsPrimaryKey: false - ); - - public static readonly TableDefinition[] All = new[] - { - Wix4CloseApplication, - Wix4RemoveFolderEx, - Wix4RemoveRegistryKeyEx, - Wix4RestartResource, - Wix4FileShare, - Wix4FileSharePermissions, - Wix4Group, - Wix4InternetShortcut, - Wix4PerformanceCategory, - Wix4Perfmon, - Wix4PerfmonManifest, - Wix4EventManifest, - Wix4SecureObject, - Wix4ServiceConfig, - Wix4TouchFile, - Wix4User, - Wix4UserGroup, - Wix4XmlFile, - Wix4XmlConfig, - Wix4FormatFile, - }; - } -} diff --git a/src/wixext/UtilWarnings.cs b/src/wixext/UtilWarnings.cs deleted file mode 100644 index b65abe45..00000000 --- a/src/wixext/UtilWarnings.cs +++ /dev/null @@ -1,37 +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.Util -{ - using System; - using System.Resources; - using WixToolset.Data; - - public static class UtilWarnings - { - public static Message DeprecatedPerfCounterElement(SourceLineNumber sourceLineNumbers) - { - return Message(sourceLineNumbers, Ids.DeprecatedPerfCounterElement, "The PerfCounter element has been deprecated. Please use the PerformanceCounter element instead."); - } - - public static Message RequiredAttributeForWindowsXP(SourceLineNumber sourceLineNumbers, string elementName, string attributeName) - { - return Message(sourceLineNumbers, Ids.RequiredAttributeForWindowsXP, "The {0}/@{1} attribute must be specified to successfully install on Windows XP. You can ignore this warning if this installation does not install on Windows XP.", elementName, attributeName); - } - - private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) - { - return new Message(sourceLineNumber, MessageLevel.Warning, (int)id, format, args); - } - - private static Message Message(SourceLineNumber sourceLineNumber, Ids id, ResourceManager resourceManager, string resourceName, params object[] args) - { - return new Message(sourceLineNumber, MessageLevel.Warning, (int)id, resourceManager, resourceName, args); - } - - public enum Ids - { - DeprecatedPerfCounterElement = 5153, - RequiredAttributeForWindowsXP = 5154, - } - } -} diff --git a/src/wixext/UtilWindowsInstallerBackendExtension.cs b/src/wixext/UtilWindowsInstallerBackendExtension.cs deleted file mode 100644 index bca7c700..00000000 --- a/src/wixext/UtilWindowsInstallerBackendExtension.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.Util -{ - using System.Collections.Generic; - using WixToolset.Data.WindowsInstaller; - using WixToolset.Extensibility; - - public class UtilWindowsInstallerBackendBinderExtension : BaseWindowsInstallerBackendBinderExtension - { - public override IReadOnlyCollection TableDefinitions => UtilTableDefinitions.All; - } -} diff --git a/src/wixext/WixToolset.Util.wixext.csproj b/src/wixext/WixToolset.Util.wixext.csproj deleted file mode 100644 index 10fc569e..00000000 --- a/src/wixext/WixToolset.Util.wixext.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - netstandard2.0 - WixToolset.Util - WiX Toolset Utility Extension - WiX Toolset Util Extension - embedded - true - - - - - - - - - - - - - - - - - - - - diff --git a/src/wixext/WixToolset.Util.wixext.nuspec b/src/wixext/WixToolset.Util.wixext.nuspec deleted file mode 100644 index ba3eaade..00000000 --- a/src/wixext/WixToolset.Util.wixext.nuspec +++ /dev/null @@ -1,25 +0,0 @@ - - - - $id$ - $version$ - $title$ - $description$ - $authors$ - MS-RL - false - $copyright$ - $projectUrl$ - - - - - - - - - - - - - diff --git a/src/wixext/WixToolset.Util.wixext.targets b/src/wixext/WixToolset.Util.wixext.targets deleted file mode 100644 index 64dff429..00000000 --- a/src/wixext/WixToolset.Util.wixext.targets +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - $(MSBuildThisFileDirectory)..\tools\WixToolset.Util.wixext.dll - - - - - diff --git a/src/wixext/WixToolset.Util.wixext.v3.ncrunchproject b/src/wixext/WixToolset.Util.wixext.v3.ncrunchproject deleted file mode 100644 index d75e7ab3..00000000 --- a/src/wixext/WixToolset.Util.wixext.v3.ncrunchproject +++ /dev/null @@ -1,7 +0,0 @@ - - - - ..\..\build\Debug\util.wixlib - - - \ No newline at end of file diff --git a/src/wixlib/UtilBundleExtension_Platform.wxi b/src/wixlib/UtilBundleExtension_Platform.wxi deleted file mode 100644 index 379c8f57..00000000 --- a/src/wixlib/UtilBundleExtension_Platform.wxi +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/src/wixlib/UtilBundleExtension_arm64.wxs b/src/wixlib/UtilBundleExtension_arm64.wxs deleted file mode 100644 index b17be031..00000000 --- a/src/wixlib/UtilBundleExtension_arm64.wxs +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/wixlib/UtilBundleExtension_x64.wxs b/src/wixlib/UtilBundleExtension_x64.wxs deleted file mode 100644 index 96c85a5b..00000000 --- a/src/wixlib/UtilBundleExtension_x64.wxs +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/wixlib/UtilBundleExtension_x86.wxs b/src/wixlib/UtilBundleExtension_x86.wxs deleted file mode 100644 index 3b458687..00000000 --- a/src/wixlib/UtilBundleExtension_x86.wxs +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/wixlib/UtilExtension.wxs b/src/wixlib/UtilExtension.wxs deleted file mode 100644 index 0f445ab4..00000000 --- a/src/wixlib/UtilExtension.wxs +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/wixlib/UtilExtension_Platform.wxi b/src/wixlib/UtilExtension_Platform.wxi deleted file mode 100644 index 913c01b9..00000000 --- a/src/wixlib/UtilExtension_Platform.wxi +++ /dev/null @@ -1,360 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/wixlib/UtilExtension_arm64.wxs b/src/wixlib/UtilExtension_arm64.wxs deleted file mode 100644 index b9dc73b8..00000000 --- a/src/wixlib/UtilExtension_arm64.wxs +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/wixlib/UtilExtension_x64.wxs b/src/wixlib/UtilExtension_x64.wxs deleted file mode 100644 index 40cdf306..00000000 --- a/src/wixlib/UtilExtension_x64.wxs +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/wixlib/UtilExtension_x86.wxs b/src/wixlib/UtilExtension_x86.wxs deleted file mode 100644 index bd0fa562..00000000 --- a/src/wixlib/UtilExtension_x86.wxs +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - 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 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ 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 65785a3b..00000000 --- a/src/wixlib/de-de.wxl +++ /dev/null @@ -1,32 +0,0 @@ - - - - - Konnte den Benutzer nicht anlegen. ([2] [3] [4] [5]) - Konnte den Benutzer auf Grund eines falschen Passwortes nicht anlegen. ([2] [3] [4] [5]) - Konnte Benutzer nicht zur Gruppe hinzufügen. ([2] [3] [4] [5]) - Konnte den Benutzer nicht anlegen, da er bereits existierte. ([2] [3] [4] [5]) - - Konnte Netzwerkfreigabe nicht anlegen. ([2] [3] [4] [5]) - Konnte Netzwerkfreigabe nicht entfernen. ([2] [3] [4] [5]) - - Konnte die DLL nicht für PerfMon registrieren. ([2] [3] [4] [5]) - Konnte die DLL nicht für PerfMon deregistrieren. ([2] [3] [4] [5]) - - Konnte die Daten der Leistungsüberwachung (performance counters) nicht installieren. ([2] [3] [4] [5]) - Konnte die Daten der Leistungsüberwachung (performance counters) nicht deinstallieren. ([2] [3] [4] [5]) - - Konnte keinen Security Descriptor für [3]\[4] erstellen, System Fehler: [2] - Konnte keinen Security Descriptor für das Objekt [3] erstellen, System Fehler: [2] - Unbekannter Objekt Typ [3], System Fehler: [2] - - Beim Lesen der XML Dateien trat ein Fehler auf. - Konnte XML Datei [3] nicht öffnen, System Fehler: [2] - Konnte Knoten [3] in der XML Datei [4] nicht finden, System Fehler: [2] - Beim Speichern der Änderungen an der XML Datei [3] trat ein Fehler auf, System Fehler: [2] - - Bei der Konfiguration der XML Dateien trat ein Fehler auf. - Konnte XML Datei [3] nicht öffnen, System Fehler: [2] - Konnte Knoten [3] in der XML Datei [4] nicht finden, System Fehler: [2] - Beim Speichern der Änderungen an der XML Datei [3] trat ein Fehler auf, System Fehler: [2] - diff --git a/src/wixlib/en-us.wxl b/src/wixlib/en-us.wxl deleted file mode 100644 index e8b146a4..00000000 --- a/src/wixlib/en-us.wxl +++ /dev/null @@ -1,32 +0,0 @@ - - - - - Failed to create user. ([2] [3] [4] [5]) - Failed to create user due to invalid password. ([2] [3] [4] [5]) - Failed to add user to group. ([2] [3] [4] [5]) - Failed to create user because it already exists. ([2] [3] [4] [5]) - - Failed to create network share. ([2] [3] [4] [5]) - Failed to drop network share. ([2] [3] [4] [5]) - - Failed to register DLL with PerfMon. ([2] [3] [4] [5]) - Failed to unregister DLL with PerfMon. ([2] [3] [4] [5]) - - Failed to install performance counters. ([2] [3] [4] [5]) - Failed to uninstall performance counters. ([2] [3] [4] [5]) - - Failed to create security descriptor for [3]\[4], system error: [2] - Failed to set security descriptor on object [3], system error: [2] - Unknown Object Type [3], system error: [2] - - There was a failure while configuring XML files. - Failed to open XML file [3], system error: [2] - Failed to find node: [3] in XML file: [4], system error: [2] - Failed to save changes to XML file [3], system error: [2] - - There was a failure while configuring XML files. - Failed to open XML file [3], system error: [2] - Failed to find node: [3] in XML file: [4], system error: [2] - Failed to save changes to XML file [3], system error: [2] - diff --git a/src/wixlib/es-es.wxl b/src/wixlib/es-es.wxl deleted file mode 100644 index ca5ab8bb..00000000 --- a/src/wixlib/es-es.wxl +++ /dev/null @@ -1,31 +0,0 @@ - - - - La creación del usuario ha fracasado. ([2] [3] [4] [5]) - La creación del usuario ha fracasado porque la contraseña es incorrecta. ([2] [3] [4] [5]) - El aditamento del usuario al grupo ha fracasado. ([2] [3] [4] [5]) - La creación del usuario ha fracasado porque ya existe. ([2] [3] [4] [5]) - - La creación de la red compartida ha fracasado. ([2] [3] [4] [5]) - La eliminación de la red compartida ha fracasado. ([2] [3] [4] [5]) - - La inscripción al registro de la DLL con PerfMon ha fracasado. ([2] [3] [4] [5]) - La cancelación de la inscripción al registro de la DLL con PerfMon ha fracasado. ([2] [3] [4] [5]) - - La instalación de los contadores de rendimiento ha fracasado. ([2] [3] [4] [5]) - La desinstalación de los contadores de rendimiento ha fracasado. ([2] [3] [4] [5]) - - La creación de los ACLs ha fracasado por [3]\[4], error del sistema : [2] - El posicionamiento de los ACLs por el objecto [3] ha fracasado, error del sistema: [2] - Tipo de objecto no conocido [3], error del sistema: [2] - - Un problema ha aparecido durante la configuración de los ficheros XML. - Fracaso de la apertura de los ficheros XML [3], error del sistema: [2] - Fracaso de la búsqueda del nodo: [3] en el fichero XML: [4], error del sistema: [2] - Fracaso durante la salvaguardia de las modificaciones en el fichero XML [3], error del sistema: [2] - - Un problema ha aparecido durante la configuración de los ficheros XML. - Fracaso de la apertura de los ficheros XML [3], error del sistema: [2] - Fracaso de la búsqueda del nodo: [3] en el fichero XML: [4], error del sistema: [2] - Fracaso durante la salvaguardia de las modificaciones en el fichero XML [3], error del sistema: [2] - \ No newline at end of file diff --git a/src/wixlib/fr-fr.wxl b/src/wixlib/fr-fr.wxl deleted file mode 100644 index ad34b56a..00000000 --- a/src/wixlib/fr-fr.wxl +++ /dev/null @@ -1,31 +0,0 @@ - - - - La création de l'utilisateur a échoué. ([2] [3] [4] [5]) - La création de l'utilisateur a échoué car le mot de passe est invalide. ([2] [3] [4] [5]) - L'ajout de l'utilisateur au groupe a échoué. ([2] [3] [4] [5]) - La création de l'utilisateur a échoué car il existe dejà. ([2] [3] [4] [5]) - - La création du partage reseau a échoué. ([2] [3] [4] [5]) - La suppression du partage reseau a échoué. ([2] [3] [4] [5]) - - L'inscription au registre de la DLL avec PerfMon a échoué. ([2] [3] [4] [5]) - La desinscription au registre de la DLL avec PerfMon a échoué. ([2] [3] [4] [5]) - - L'installation des compteurs de performance a échoué. ([2] [3] [4] [5]) - La desinstallation des compteurs de performance a échoué. ([2] [3] [4] [5]) - - La création des ACLs a échoué pour [3]\[4], erreur systeme: [2] - Le positionnement des ACLs pour l'objet [3] a échoué, erreur systeme: [2] - Type d'objet inconnu [3], erreur systeme: [2] - - Un problème est survenu lors de la configuration des fichiers XML. - Echec de l'ouverture des fichiers XML [3], erreur systeme: [2] - Echec de la recherche du noeud: [3] dans le fichier XML: [4], erreur systeme: [2] - Echec lors de la sauvegarde des modifications dans le fichier XML [3], erreur systeme: [2] - - Un problème est survenu lors de la configuration des fichiers XML. - Echec de l'ouverture des fichiers XML [3], erreur systeme: [2] - Echec de la recherche du noeud: [3] dans le fichier XML: [4], erreur systeme: [2] - Echec lors de la sauvegarde des modifications dans le fichier XML [3], erreur systeme: [2] - \ No newline at end of file diff --git a/src/wixlib/it-it.wxl b/src/wixlib/it-it.wxl deleted file mode 100644 index 8cea0a14..00000000 --- a/src/wixlib/it-it.wxl +++ /dev/null @@ -1,32 +0,0 @@ - - - - - Impossibile creare l'utente. ([2] [3] [4] [5]) - Impossibile creare l'utente perchè la password è errata. ([2] [3] [4] [5]) - Impossibile aggiungere l'utente al gruppo. ([2] [3] [4] [5]) - Impossibile creare l'utente perchè già esistente. ([2] [3] [4] [5]) - - Impossibile creare la risorsa di rete. ([2] [3] [4] [5]) - Impossibile eliminare la risorsa di rete. ([2] [3] [4] [5]) - - Impossibile registrare la DLL con PerfMon. ([2] [3] [4] [5]) - Impossibile rimuovere la registrazione della DLL con PerfMon. ([2] [3] [4] [5]) - - Impossibile installare i contatori delle prestazioni. ([2] [3] [4] [5]) - Impossibile rimuovere i contatori delle prestazioni. ([2] [3] [4] [5]) - - Impossibile creare i descrittori di sicurezza per [3]\[4], errore di sistema: [2] - Impossibile impostare i descrittori di sicurezza sull'oggetto [3], errore di sistema: [2] - Tipo di oggetto sconosciuto [3], errore di sistema: [2] - - Si è verificato un errore durante la configurazione dei file XML. - Impossibile aprire il file XML [3], errore di sistema: [2] - Impossibile trovare il nodo: [3] nel file XML: [4], errore di sistema: [2] - Impossible salvare le modifiche al file XML [3], errore di sistema: [2] - - Si è verificato un errore durante la configurazione dei file XML. - Impossibile aprire il file XML [3], errore di sistema: [2] - Impossibile trovare il nodo: [3] nel file XML: [4], errore di sistema: [2] - Impossibile salvare le modifiche al file XML [3], errore di sitema: [2] - diff --git a/src/wixlib/ja-jp.wxl b/src/wixlib/ja-jp.wxl deleted file mode 100644 index 5f5cf40d..00000000 --- a/src/wixlib/ja-jp.wxl +++ /dev/null @@ -1,32 +0,0 @@ - - - - - ユーザー作成に失敗しました。 ([2] [3] [4] [5]) - パスワードが無効のためユーザー作成に失敗しました。 ([2] [3] [4] [5]) - ユーザーをグループに追加でいませんでした。 ([2] [3] [4] [5]) - ユーザーが既に存在するため作成できませんでした。 ([2] [3] [4] [5]) - - ネットワーク共有の作成に失敗しました。 ([2] [3] [4] [5]) - ネットワーク共有の削除に失敗しました。 ([2] [3] [4] [5]) - - DLL を PerfMon に登録でいませんでした。 ([2] [3] [4] [5]) - DLL を PerfMon より登録解除できませんでした。 ([2] [3] [4] [5]) - - パフォーマンス カウンタをインストールできませんでした。 ([2] [3] [4] [5]) - パフォーマンス カウンタをアンインストールできませんでした。 ([2] [3] [4] [5]) - - [3]\[4] 用セキュリティ ディスクリプターを作成できませんでした、システム エラー: [2] - オブジェクト [3] 上のセキュリティ ディスクリプターを設定できませんでした、システム エラー: [2] - 不明なオブジェクト種別 [3]、システム エラー: [2] - - XML ファイル構成中に失敗しました。 - XML ファイル [3] を開けませんでした、システム エラー: [2] - XML ファイル [4] 内にノード [3] が見つかりませんでした、システム エラー: [2] - XML ファイル [3] へ変更を保存できませんでした、システム エラー: [2] - - XML ファイル構成中に失敗しました。 - XML ファイル [3] を開けませんでした、システム エラー: [2] - XML ファイル [4] 内にノード [3] が見つかりませんでした、システム エラー: [2] - XML ファイル [3] へ変更を保存できませんでした、システム エラー: [2] - diff --git a/src/wixlib/pt-br.wxl b/src/wixlib/pt-br.wxl deleted file mode 100644 index 3ca27dda..00000000 --- a/src/wixlib/pt-br.wxl +++ /dev/null @@ -1,26 +0,0 @@ - - - - - Falha ao criar usuário. ([2] [3] [4] [5]) - Falha ao criar usuário devido a senha inválida. ([2] [3] [4] [5]) - Falha ao adicionar o usuário ao grupo. ([2] [3] [4] [5]) - Falha ao criar o usuário, porque ele já existe. ([2] [3] [4] [5]) - Falha ao criar o compartilhamento de rede. ([2] [3] [4] [5]) - Falha ao cair compartilhamento de rede. ([2] [3] [4] [5]) - Falha ao registrar DLL com PerfMon. ([2] [3] [4] [5]) - Falha ao cancelar o registro de DLL com PerfMon. ([2] [3] [4] [5]) - Falha ao instalar contadores de desempenho. ([2] [3] [4] [5]) - Falha ao desinstalar contadores de desempenho. ([2] [3] [4] [5]) - Falha ao criar o descritor de segurança [3] \ [4], erro do sistema: [2] - Falha ao definir o descritor de segurança sobre o objeto [3], erro do sistema: [2] - Objeto Desconhecido Tipo [3], erro do sistema: [2] - Houve uma falha ao configurar arquivos XML. - Falha ao abrir o arquivo XML [3], erro do sistema: [2] - Falha ao localizar nó: [3] no arquivo XML: [4], erro do sistema: [2] - Falha ao salvar as alterações para o arquivo XML [3], erro do sistema: [2] - Houve uma falha ao configurar arquivos XML. - Falha ao abrir o arquivo XML [3], erro do sistema: [2] - Falha ao localizar nó: [3] no arquivo XML: [4], erro do sistema: [2] - Falha ao salvar as alterações para o arquivo XML [3], erro do sistema: [2] - diff --git a/src/wixlib/util.v3.ncrunchproject b/src/wixlib/util.v3.ncrunchproject deleted file mode 100644 index 319cd523..00000000 --- a/src/wixlib/util.v3.ncrunchproject +++ /dev/null @@ -1,5 +0,0 @@ - - - True - - \ No newline at end of file diff --git a/src/wixlib/util.wixproj b/src/wixlib/util.wixproj deleted file mode 100644 index 99dede7d..00000000 --- a/src/wixlib/util.wixproj +++ /dev/null @@ -1,27 +0,0 @@ - - - - - Library - true - - - - - - - - - - - - - - - - - - - - - diff --git a/version.json b/version.json deleted file mode 100644 index 5f857771..00000000 --- a/version.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "version": "4.0", - "publicReleaseRefSpec": [ - "^refs/heads/master$" - ], - "cloudBuild": { - "buildNumber": { - "enabled": true - } - } -} -- cgit v1.2.3-55-g6feb