diff options
Diffstat (limited to 'src')
66 files changed, 5093 insertions, 0 deletions
diff --git a/src/ext/Sql/Directory.Build.props b/src/ext/Sql/Directory.Build.props new file mode 100644 index 00000000..b3c6287c --- /dev/null +++ b/src/ext/Sql/Directory.Build.props | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | <!-- | ||
| 4 | Do NOT modify this file. Update the canonical version in Home\repo-template\src\Directory.Build.props | ||
| 5 | then update all of the repos. | ||
| 6 | --> | ||
| 7 | <Project> | ||
| 8 | <PropertyGroup> | ||
| 9 | <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | ||
| 10 | <EnableSourceLink Condition=" '$(NCrunch)' == '1' ">false</EnableSourceLink> | ||
| 11 | <MSBuildWarningsAsMessages>MSB3246</MSBuildWarningsAsMessages> | ||
| 12 | |||
| 13 | <ProjectName Condition=" '$(ProjectName)' == '' ">$(MSBuildProjectName)</ProjectName> | ||
| 14 | <BaseOutputPath>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\build\))</BaseOutputPath> | ||
| 15 | <BaseIntermediateOutputPath>$(BaseOutputPath)obj\$(ProjectName)\</BaseIntermediateOutputPath> | ||
| 16 | <OutputPath>$(BaseOutputPath)$(Configuration)\</OutputPath> | ||
| 17 | |||
| 18 | <Authors>WiX Toolset Team</Authors> | ||
| 19 | <Company>WiX Toolset</Company> | ||
| 20 | <Copyright>Copyright (c) .NET Foundation and contributors. All rights reserved.</Copyright> | ||
| 21 | <PackageLicenseExpression>MS-RL</PackageLicenseExpression> | ||
| 22 | <Product>WiX Toolset</Product> | ||
| 23 | </PropertyGroup> | ||
| 24 | |||
| 25 | <Import Project="Directory$(MSBuildProjectExtension).props" Condition=" Exists('Directory$(MSBuildProjectExtension).props') " /> | ||
| 26 | <Import Project="Custom.Build.props" Condition=" Exists('Custom.Build.props') " /> | ||
| 27 | </Project> | ||
diff --git a/src/ext/Sql/Directory.Build.targets b/src/ext/Sql/Directory.Build.targets new file mode 100644 index 00000000..2fcc765a --- /dev/null +++ b/src/ext/Sql/Directory.Build.targets | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | <!-- | ||
| 4 | Do NOT modify this file. Update the canonical version in Home\repo-template\src\Directory.Build.targets | ||
| 5 | then update all of the repos. | ||
| 6 | --> | ||
| 7 | <!-- | ||
| 8 | Replace PackageReferences with ProjectReferences when the projects can be found in .sln. | ||
| 9 | See the original here: https://github.com/dotnet/sdk/issues/1151#issuecomment-385133284 | ||
| 10 | --> | ||
| 11 | <Project> | ||
| 12 | <PropertyGroup> | ||
| 13 | <ReplacePackageReferences>true</ReplacePackageReferences> | ||
| 14 | <TheSolutionPath Condition=" '$(NCrunch)'=='' ">$(SolutionPath)</TheSolutionPath> | ||
| 15 | <TheSolutionPath Condition=" '$(NCrunch)'=='1' ">$(NCrunchOriginalSolutionPath)</TheSolutionPath> | ||
| 16 | </PropertyGroup> | ||
| 17 | |||
| 18 | <Choose> | ||
| 19 | <When Condition="$(ReplacePackageReferences) AND '$(TheSolutionPath)' != '' AND '$(TheSolutionPath)' != '*undefined*' AND Exists('$(TheSolutionPath)')"> | ||
| 20 | |||
| 21 | <PropertyGroup> | ||
| 22 | <SolutionFileContent>$([System.IO.File]::ReadAllText($(TheSolutionPath)))</SolutionFileContent> | ||
| 23 | <SmartSolutionDir>$([System.IO.Path]::GetDirectoryName( $(TheSolutionPath) ))</SmartSolutionDir> | ||
| 24 | <RegexPattern>(?<="[PackageName]", ")(.*)(?=", ")</RegexPattern> | ||
| 25 | </PropertyGroup> | ||
| 26 | |||
| 27 | <ItemGroup> | ||
| 28 | <!-- Keep the identity of the PackageReference --> | ||
| 29 | <SmartPackageReference Include="@(PackageReference)"> | ||
| 30 | <PackageName>%(Identity)</PackageName> | ||
| 31 | <InSolution>$(SolutionFileContent.Contains('\%(Identity).csproj'))</InSolution> | ||
| 32 | </SmartPackageReference> | ||
| 33 | |||
| 34 | <!-- Filter them by mapping them to another ItemGroup using the WithMetadataValue item function --> | ||
| 35 | <PackageInSolution Include="@(SmartPackageReference->WithMetadataValue('InSolution', True))"> | ||
| 36 | <Pattern>$(RegexPattern.Replace('[PackageName]','%(PackageName)') )</Pattern> | ||
| 37 | <SmartPath>$([System.Text.RegularExpressions.Regex]::Match('$(SolutionFileContent)', '%(Pattern)'))</SmartPath> | ||
| 38 | </PackageInSolution> | ||
| 39 | |||
| 40 | <ProjectReference Include="@(PackageInSolution->'$(SmartSolutionDir)\%(SmartPath)' )"/> | ||
| 41 | |||
| 42 | <!-- Remove the package references that are now referenced as projects --> | ||
| 43 | <PackageReference Remove="@(PackageInSolution->'%(PackageName)')"/> | ||
| 44 | </ItemGroup> | ||
| 45 | |||
| 46 | </When> | ||
| 47 | </Choose> | ||
| 48 | |||
| 49 | <Import Project="Directory$(MSBuildProjectExtension).targets" Condition=" Exists('Directory$(MSBuildProjectExtension).targets') " /> | ||
| 50 | <Import Project="Custom.Build.targets" Condition=" Exists('Custom.Build.targets') " /> | ||
| 51 | </Project> | ||
diff --git a/src/ext/Sql/Directory.csproj.props b/src/ext/Sql/Directory.csproj.props new file mode 100644 index 00000000..81d24ad1 --- /dev/null +++ b/src/ext/Sql/Directory.csproj.props | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | <!-- | ||
| 3 | Do NOT modify this file. Update the canonical version in Home\repo-template\src\CSharp.Build.props | ||
| 4 | then update all of the repos. | ||
| 5 | --> | ||
| 6 | <Project> | ||
| 7 | <PropertyGroup> | ||
| 8 | <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow> | ||
| 9 | <SignAssembly>true</SignAssembly> | ||
| 10 | <AssemblyOriginatorKeyFile>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)wix.snk))</AssemblyOriginatorKeyFile> | ||
| 11 | <NBGV_EmitThisAssemblyClass>false</NBGV_EmitThisAssemblyClass> | ||
| 12 | </PropertyGroup> | ||
| 13 | </Project> | ||
diff --git a/src/ext/Sql/Directory.csproj.targets b/src/ext/Sql/Directory.csproj.targets new file mode 100644 index 00000000..c3270426 --- /dev/null +++ b/src/ext/Sql/Directory.csproj.targets | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | <!-- | ||
| 3 | Do NOT modify this file. Update the canonical version in Home\repo-template\src\Directory.csproj.targets | ||
| 4 | then update all of the repos. | ||
| 5 | --> | ||
| 6 | <Project> | ||
| 7 | <PropertyGroup> | ||
| 8 | <CreateDocumentation Condition=" '$(CreateDocumentationFile)'!='true' ">false</CreateDocumentation> | ||
| 9 | <DocumentationFile Condition=" '$(CreateDocumentationFile)'=='true' ">$(OutputPath)\$(AssemblyName).xml</DocumentationFile> | ||
| 10 | </PropertyGroup> | ||
| 11 | |||
| 12 | <Target Name="SetNuspecProperties" DependsOnTargets="InitializeSourceControlInformation" AfterTargets="GetBuildVersion" | ||
| 13 | Condition=" Exists('$(MSBuildProjectName).nuspec') "> | ||
| 14 | <PropertyGroup> | ||
| 15 | <ProjectUrl Condition=" '$(ProjectUrl)'=='' and '$(PrivateRepositoryUrl)'!='' ">$(PrivateRepositoryUrl.Replace('.git',''))</ProjectUrl> | ||
| 16 | |||
| 17 | <NuspecFile>$(MSBuildProjectName).nuspec</NuspecFile> | ||
| 18 | <NuspecBasePath Condition=" '$(NuspecBasePath)'=='' ">$(OutputPath)..\</NuspecBasePath> | ||
| 19 | <NuspecProperties>$(NuspecProperties);Id=$(PackageId);Authors=$(Authors);Copyright=$(Copyright);Description=$(Description);Title=$(Title)</NuspecProperties> | ||
| 20 | <NuspecProperties>$(NuspecProperties);Version=$(PackageVersion);RepositoryCommit=$(SourceRevisionId);RepositoryType=$(RepositoryType);RepositoryUrl=$(PrivateRepositoryUrl);ProjectFolder=$(MSBuildProjectDirectory)\;ProjectUrl=$(ProjectUrl)</NuspecProperties> | ||
| 21 | <PublishRepositoryUrl>true</PublishRepositoryUrl> | ||
| 22 | <SymbolPackageFormat>snupkg</SymbolPackageFormat> | ||
| 23 | </PropertyGroup> | ||
| 24 | </Target> | ||
| 25 | |||
| 26 | </Project> | ||
diff --git a/src/ext/Sql/Directory.vcxproj.props b/src/ext/Sql/Directory.vcxproj.props new file mode 100644 index 00000000..bcf26c57 --- /dev/null +++ b/src/ext/Sql/Directory.vcxproj.props | |||
| @@ -0,0 +1,111 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | |||
| 4 | <Project> | ||
| 5 | <PropertyGroup> | ||
| 6 | <Platform Condition=" '$(Platform)' == '' OR '$(Platform)' == 'AnyCPU' ">Win32</Platform> | ||
| 7 | <IntDir>$(BaseIntermediateOutputPath)$(Configuration)\$(Platform)\</IntDir> | ||
| 8 | <OutDir>$(OutputPath)$(Platform)\</OutDir> | ||
| 9 | |||
| 10 | <!-- NBGV properties --> | ||
| 11 | <AssemblyCompany>$(Company)</AssemblyCompany> | ||
| 12 | <AssemblyCopyright>$(Copyright)</AssemblyCopyright> | ||
| 13 | |||
| 14 | <RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers> | ||
| 15 | <NuGetTargetMoniker>native,Version=v0.0</NuGetTargetMoniker> | ||
| 16 | </PropertyGroup> | ||
| 17 | |||
| 18 | <PropertyGroup Condition="'$(WindowsTargetPlatformVersion)'=='' AND '$(VisualStudioVersion)'>='15.0'"> | ||
| 19 | <WindowsTargetPlatformVersion>$([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0'))</WindowsTargetPlatformVersion> | ||
| 20 | </PropertyGroup> | ||
| 21 | |||
| 22 | <ItemDefinitionGroup> | ||
| 23 | <ClCompile> | ||
| 24 | <DisableSpecificWarnings>$(DisableSpecificCompilerWarnings)</DisableSpecificWarnings> | ||
| 25 | <WarningLevel>Level4</WarningLevel> | ||
| 26 | <AdditionalIncludeDirectories>$(ProjectDir)inc;$(MSBuildProjectDirectory);$(IntDir);$(SqlCESdkIncludePath);$(ProjectAdditionalIncludeDirectories);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | ||
| 27 | <PreprocessorDefinitions>WIN32;_WINDOWS;_WIN32_MSI=500;_WIN32_WINNT=0x0501;$(ArmPreprocessorDefinitions);$(UnicodePreprocessorDefinitions);_CRT_STDIO_LEGACY_WIDE_SPECIFIERS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||
| 28 | <PrecompiledHeader>Use</PrecompiledHeader> | ||
| 29 | <PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile> | ||
| 30 | <CallingConvention Condition="'$(Platform)'=='Win32'">StdCall</CallingConvention> | ||
| 31 | <TreatWarningAsError>true</TreatWarningAsError> | ||
| 32 | <ExceptionHandling>false</ExceptionHandling> | ||
| 33 | <AdditionalOptions>-YlprecompDefine</AdditionalOptions> | ||
| 34 | <AdditionalOptions Condition=" $(PlatformToolset.StartsWith('v14')) ">/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions> | ||
| 35 | <MultiProcessorCompilation Condition=" $(NUMBER_OF_PROCESSORS) > 4 ">true</MultiProcessorCompilation> | ||
| 36 | </ClCompile> | ||
| 37 | <ResourceCompile> | ||
| 38 | <PreprocessorDefinitions>$(ArmPreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||
| 39 | <AdditionalIncludeDirectories>$(ProjectAdditionalResourceIncludeDirectories);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | ||
| 40 | </ResourceCompile> | ||
| 41 | <Lib> | ||
| 42 | <AdditionalLibraryDirectories>$(OutDir);$(AdditionalMultiTargetLibraryPath);$(ProjectAdditionalLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> | ||
| 43 | </Lib> | ||
| 44 | <Link> | ||
| 45 | <SubSystem>$(ProjectSubSystem)</SubSystem> | ||
| 46 | <ModuleDefinitionFile>$(ProjectModuleDefinitionFile)</ModuleDefinitionFile> | ||
| 47 | <NoEntryPoint>$(ResourceOnlyDll)</NoEntryPoint> | ||
| 48 | <GenerateDebugInformation>true</GenerateDebugInformation> | ||
| 49 | <AdditionalDependencies>$(ProjectAdditionalLinkLibraries);advapi32.lib;comdlg32.lib;user32.lib;oleaut32.lib;gdi32.lib;shell32.lib;ole32.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies> | ||
| 50 | <AdditionalLibraryDirectories>$(OutDir);$(AdditionalMultiTargetLibraryPath);$(ArmLibraryDirectories);$(ProjectAdditionalLinkLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> | ||
| 51 | <AdditionalOptions Condition=" $(PlatformToolset.StartsWith('v14')) ">/IGNORE:4099 %(AdditionalOptions)</AdditionalOptions> | ||
| 52 | </Link> | ||
| 53 | </ItemDefinitionGroup> | ||
| 54 | |||
| 55 | <ItemDefinitionGroup Condition=" '$(Platform)'=='Win32' and '$(PlatformToolset)'!='v100'"> | ||
| 56 | <ClCompile> | ||
| 57 | <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet> | ||
| 58 | </ClCompile> | ||
| 59 | </ItemDefinitionGroup> | ||
| 60 | <ItemDefinitionGroup Condition=" '$(Platform)'=='arm' "> | ||
| 61 | <ClCompile> | ||
| 62 | <CallingConvention>CDecl</CallingConvention> | ||
| 63 | </ClCompile> | ||
| 64 | </ItemDefinitionGroup> | ||
| 65 | <ItemDefinitionGroup Condition=" '$(ConfigurationType)'=='StaticLibrary' "> | ||
| 66 | <ClCompile> | ||
| 67 | <DebugInformationFormat>OldStyle</DebugInformationFormat> | ||
| 68 | <OmitDefaultLibName>true</OmitDefaultLibName> | ||
| 69 | <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries> | ||
| 70 | </ClCompile> | ||
| 71 | </ItemDefinitionGroup> | ||
| 72 | <ItemDefinitionGroup Condition=" '$(Configuration)'=='Debug' "> | ||
| 73 | <ClCompile> | ||
| 74 | <Optimization>Disabled</Optimization> | ||
| 75 | <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> | ||
| 76 | <PreprocessorDefinitions>_DEBUG;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||
| 77 | <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> | ||
| 78 | </ClCompile> | ||
| 79 | </ItemDefinitionGroup> | ||
| 80 | <ItemDefinitionGroup Condition=" '$(Configuration)'=='Debug' and '$(CLRSupport)'=='true' "> | ||
| 81 | <ClCompile> | ||
| 82 | <BasicRuntimeChecks></BasicRuntimeChecks> | ||
| 83 | <RuntimeLibrary>MultiThreadedDebugDll</RuntimeLibrary> | ||
| 84 | </ClCompile> | ||
| 85 | </ItemDefinitionGroup> | ||
| 86 | <ItemDefinitionGroup Condition=" '$(Configuration)'=='Release' "> | ||
| 87 | <ClCompile> | ||
| 88 | <Optimization>MinSpace</Optimization> | ||
| 89 | <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||
| 90 | <FunctionLevelLinking>true</FunctionLevelLinking> | ||
| 91 | <IntrinsicFunctions>true</IntrinsicFunctions> | ||
| 92 | <RuntimeLibrary>MultiThreaded</RuntimeLibrary> | ||
| 93 | </ClCompile> | ||
| 94 | <Link> | ||
| 95 | <EnableCOMDATFolding>true</EnableCOMDATFolding> | ||
| 96 | <OptimizeReferences>true</OptimizeReferences> | ||
| 97 | </Link> | ||
| 98 | </ItemDefinitionGroup> | ||
| 99 | <ItemDefinitionGroup Condition=" '$(Configuration)'=='Release' and '$(CLRSupport)'=='true' "> | ||
| 100 | <ClCompile> | ||
| 101 | <BasicRuntimeChecks></BasicRuntimeChecks> | ||
| 102 | <RuntimeLibrary>MultiThreadedDll</RuntimeLibrary> | ||
| 103 | </ClCompile> | ||
| 104 | </ItemDefinitionGroup> | ||
| 105 | <ItemDefinitionGroup Condition=" '$(CLRSupport)'=='true' "> | ||
| 106 | <Link> | ||
| 107 | <KeyFile>$(LinkKeyFile)</KeyFile> | ||
| 108 | <DelaySign>$(LinkDelaySign)</DelaySign> | ||
| 109 | </Link> | ||
| 110 | </ItemDefinitionGroup> | ||
| 111 | </Project> | ||
diff --git a/src/ext/Sql/README.md b/src/ext/Sql/README.md new file mode 100644 index 00000000..377c9032 --- /dev/null +++ b/src/ext/Sql/README.md | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | # Sql.wixext | ||
| 2 | WixToolset.Sql.wixext - Sql WiX Toolset Extension | ||
diff --git a/src/ext/Sql/Sql.wixext.sln b/src/ext/Sql/Sql.wixext.sln new file mode 100644 index 00000000..cfa9ad4f --- /dev/null +++ b/src/ext/Sql/Sql.wixext.sln | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | | ||
| 2 | Microsoft Visual Studio Solution File, Format Version 12.00 | ||
| 3 | # Visual Studio Version 16 | ||
| 4 | VisualStudioVersion = 16.0.30204.135 | ||
| 5 | MinimumVisualStudioVersion = 10.0.40219.1 | ||
| 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sqlca", "src\ca\sqlca.vcxproj", "{4DCA6E4B-A1F1-4450-BC2D-94AC20F31935}" | ||
| 7 | EndProject | ||
| 8 | Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "sql", "src\wixlib\sql.wixproj", "{9ACF1A20-D801-45CC-A463-F9D13E506AA3}" | ||
| 9 | EndProject | ||
| 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Sql.wixext", "src\wixext\WixToolset.Sql.wixext.csproj", "{0E05519A-0045-4AEC-BD0C-D9205FF1468F}" | ||
| 11 | EndProject | ||
| 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.Sql", "src\test\WixToolsetTest.Sql\WixToolsetTest.Sql.csproj", "{FE72A369-03CA-4EBC-BC7B-A8BBF5BBD3E0}" | ||
| 13 | EndProject | ||
| 14 | Global | ||
| 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
| 16 | Debug|Any CPU = Debug|Any CPU | ||
| 17 | Debug|x86 = Debug|x86 | ||
| 18 | Release|Any CPU = Release|Any CPU | ||
| 19 | Release|x86 = Release|x86 | ||
| 20 | EndGlobalSection | ||
| 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
| 22 | {4DCA6E4B-A1F1-4450-BC2D-94AC20F31935}.Debug|Any CPU.ActiveCfg = Debug|Win32 | ||
| 23 | {4DCA6E4B-A1F1-4450-BC2D-94AC20F31935}.Debug|Any CPU.Build.0 = Debug|Win32 | ||
| 24 | {4DCA6E4B-A1F1-4450-BC2D-94AC20F31935}.Debug|x86.ActiveCfg = Debug|Win32 | ||
| 25 | {4DCA6E4B-A1F1-4450-BC2D-94AC20F31935}.Debug|x86.Build.0 = Debug|Win32 | ||
| 26 | {4DCA6E4B-A1F1-4450-BC2D-94AC20F31935}.Release|Any CPU.ActiveCfg = Release|Win32 | ||
| 27 | {4DCA6E4B-A1F1-4450-BC2D-94AC20F31935}.Release|x86.ActiveCfg = Release|Win32 | ||
| 28 | {4DCA6E4B-A1F1-4450-BC2D-94AC20F31935}.Release|x86.Build.0 = Release|Win32 | ||
| 29 | {9ACF1A20-D801-45CC-A463-F9D13E506AA3}.Debug|Any CPU.ActiveCfg = Debug|x86 | ||
| 30 | {9ACF1A20-D801-45CC-A463-F9D13E506AA3}.Debug|Any CPU.Build.0 = Debug|x86 | ||
| 31 | {9ACF1A20-D801-45CC-A463-F9D13E506AA3}.Debug|x86.ActiveCfg = Debug|x86 | ||
| 32 | {9ACF1A20-D801-45CC-A463-F9D13E506AA3}.Debug|x86.Build.0 = Debug|x86 | ||
| 33 | {9ACF1A20-D801-45CC-A463-F9D13E506AA3}.Release|Any CPU.ActiveCfg = Release|x86 | ||
| 34 | {9ACF1A20-D801-45CC-A463-F9D13E506AA3}.Release|x86.ActiveCfg = Release|x86 | ||
| 35 | {9ACF1A20-D801-45CC-A463-F9D13E506AA3}.Release|x86.Build.0 = Release|x86 | ||
| 36 | {0E05519A-0045-4AEC-BD0C-D9205FF1468F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| 37 | {0E05519A-0045-4AEC-BD0C-D9205FF1468F}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| 38 | {0E05519A-0045-4AEC-BD0C-D9205FF1468F}.Debug|x86.ActiveCfg = Debug|Any CPU | ||
| 39 | {0E05519A-0045-4AEC-BD0C-D9205FF1468F}.Debug|x86.Build.0 = Debug|Any CPU | ||
| 40 | {0E05519A-0045-4AEC-BD0C-D9205FF1468F}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| 41 | {0E05519A-0045-4AEC-BD0C-D9205FF1468F}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| 42 | {0E05519A-0045-4AEC-BD0C-D9205FF1468F}.Release|x86.ActiveCfg = Release|Any CPU | ||
| 43 | {0E05519A-0045-4AEC-BD0C-D9205FF1468F}.Release|x86.Build.0 = Release|Any CPU | ||
| 44 | {FE72A369-03CA-4EBC-BC7B-A8BBF5BBD3E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| 45 | {FE72A369-03CA-4EBC-BC7B-A8BBF5BBD3E0}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| 46 | {FE72A369-03CA-4EBC-BC7B-A8BBF5BBD3E0}.Debug|x86.ActiveCfg = Debug|Any CPU | ||
| 47 | {FE72A369-03CA-4EBC-BC7B-A8BBF5BBD3E0}.Debug|x86.Build.0 = Debug|Any CPU | ||
| 48 | {FE72A369-03CA-4EBC-BC7B-A8BBF5BBD3E0}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| 49 | {FE72A369-03CA-4EBC-BC7B-A8BBF5BBD3E0}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| 50 | {FE72A369-03CA-4EBC-BC7B-A8BBF5BBD3E0}.Release|x86.ActiveCfg = Release|Any CPU | ||
| 51 | {FE72A369-03CA-4EBC-BC7B-A8BBF5BBD3E0}.Release|x86.Build.0 = Release|Any CPU | ||
| 52 | EndGlobalSection | ||
| 53 | GlobalSection(SolutionProperties) = preSolution | ||
| 54 | HideSolutionNode = FALSE | ||
| 55 | EndGlobalSection | ||
| 56 | GlobalSection(ExtensibilityGlobals) = postSolution | ||
| 57 | SolutionGuid = {DEFEE3BB-E557-4B77-A85C-ECA19D6F5DF5} | ||
| 58 | EndGlobalSection | ||
| 59 | EndGlobal | ||
diff --git a/src/ext/Sql/appveyor.cmd b/src/ext/Sql/appveyor.cmd new file mode 100644 index 00000000..f21449d2 --- /dev/null +++ b/src/ext/Sql/appveyor.cmd | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | @setlocal | ||
| 2 | @pushd %~dp0 | ||
| 3 | @set _C=Release | ||
| 4 | @if /i "%1"=="debug" set _C=Debug | ||
| 5 | |||
| 6 | :: Restore | ||
| 7 | msbuild -p:Configuration=%_C% -t:Restore || exit /b | ||
| 8 | |||
| 9 | :: Build | ||
| 10 | msbuild -p:Configuration=%_C% src\test\WixToolsetTest.Sql\WixToolsetTest.Sql.csproj || exit /b | ||
| 11 | |||
| 12 | :: Test | ||
| 13 | dotnet test -c %_C% --no-build src\test\WixToolsetTest.Sql || exit /b | ||
| 14 | |||
| 15 | :: Pack | ||
| 16 | msbuild -p:Configuration=%_C% -p:NoBuild=true -t:Pack src\wixext\WixToolset.Sql.wixext.csproj || exit /b | ||
| 17 | |||
| 18 | @popd | ||
| 19 | @endlocal | ||
diff --git a/src/ext/Sql/appveyor.yml b/src/ext/Sql/appveyor.yml new file mode 100644 index 00000000..7c686b04 --- /dev/null +++ b/src/ext/Sql/appveyor.yml | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | # Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | # | ||
| 3 | # Do NOT modify this file. Update the canonical version in Home\repo-template\src\appveyor.yml | ||
| 4 | # then update all of the repos. | ||
| 5 | |||
| 6 | branches: | ||
| 7 | only: | ||
| 8 | - master | ||
| 9 | - develop | ||
| 10 | |||
| 11 | image: Visual Studio 2019 | ||
| 12 | |||
| 13 | version: 0.0.0.{build} | ||
| 14 | configuration: Release | ||
| 15 | |||
| 16 | environment: | ||
| 17 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true | ||
| 18 | DOTNET_CLI_TELEMETRY_OPTOUT: 1 | ||
| 19 | NUGET_XMLDOC_MODE: skip | ||
| 20 | |||
| 21 | build_script: | ||
| 22 | - appveyor.cmd | ||
| 23 | |||
| 24 | pull_requests: | ||
| 25 | do_not_increment_build_number: true | ||
| 26 | |||
| 27 | nuget: | ||
| 28 | disable_publish_on_pr: true | ||
| 29 | |||
| 30 | skip_branch_with_pr: true | ||
| 31 | skip_tags: true | ||
| 32 | |||
| 33 | artifacts: | ||
| 34 | - path: build\Release\**\*.nupkg | ||
| 35 | name: nuget | ||
| 36 | |||
| 37 | notifications: | ||
| 38 | - provider: Slack | ||
| 39 | incoming_webhook: | ||
| 40 | secure: p5xuu+4x2JHfwGDMDe5KcG1k7gZxqYc4jWVwvyNZv5cvkubPD2waJs5yXMAXZNN7Z63/3PWHb7q4KoY/99AjauYa1nZ4c5qYqRPFRBKTHfA= | ||
diff --git a/src/ext/Sql/ca/CustomMsiErrors.h b/src/ext/Sql/ca/CustomMsiErrors.h new file mode 100644 index 00000000..b568d01c --- /dev/null +++ b/src/ext/Sql/ca/CustomMsiErrors.h | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | #define msierrSQLFailedCreateDatabase 26201 | ||
| 5 | #define msierrSQLFailedDropDatabase 26202 | ||
| 6 | #define msierrSQLFailedConnectDatabase 26203 | ||
| 7 | #define msierrSQLFailedExecString 26204 | ||
| 8 | #define msierrSQLDatabaseAlreadyExists 26205 | ||
| 9 | |||
| 10 | //Last available is 26250 \ No newline at end of file | ||
diff --git a/src/ext/Sql/ca/caDecor.h b/src/ext/Sql/ca/caDecor.h new file mode 100644 index 00000000..da274650 --- /dev/null +++ b/src/ext/Sql/ca/caDecor.h | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #if defined(_M_ARM64) | ||
| 6 | #define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_A64" | ||
| 7 | #elif defined(_M_AMD64) | ||
| 8 | #define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_X64" | ||
| 9 | #elif defined(_M_ARM) | ||
| 10 | #define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_ARM" | ||
| 11 | #else | ||
| 12 | #define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_X86" | ||
| 13 | #endif | ||
diff --git a/src/ext/Sql/ca/dllmain.cpp b/src/ext/Sql/ca/dllmain.cpp new file mode 100644 index 00000000..35ae6d1c --- /dev/null +++ b/src/ext/Sql/ca/dllmain.cpp | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | /******************************************************************** | ||
| 6 | DllMain - standard entry point for all WiX custom actions | ||
| 7 | |||
| 8 | ********************************************************************/ | ||
| 9 | extern "C" BOOL WINAPI DllMain( | ||
| 10 | IN HINSTANCE hInst, | ||
| 11 | IN ULONG ulReason, | ||
| 12 | IN LPVOID) | ||
| 13 | { | ||
| 14 | switch(ulReason) | ||
| 15 | { | ||
| 16 | case DLL_PROCESS_ATTACH: | ||
| 17 | WcaGlobalInitialize(hInst); | ||
| 18 | break; | ||
| 19 | |||
| 20 | case DLL_PROCESS_DETACH: | ||
| 21 | WcaGlobalFinalize(); | ||
| 22 | break; | ||
| 23 | } | ||
| 24 | |||
| 25 | return TRUE; | ||
| 26 | } | ||
diff --git a/src/ext/Sql/ca/precomp.h b/src/ext/Sql/ca/precomp.h new file mode 100644 index 00000000..266d543c --- /dev/null +++ b/src/ext/Sql/ca/precomp.h | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #if _WIN32_MSI < 150 | ||
| 6 | #define _WIN32_MSI 150 | ||
| 7 | #endif | ||
| 8 | |||
| 9 | #include <windows.h> | ||
| 10 | #include <msiquery.h> | ||
| 11 | |||
| 12 | #include <strsafe.h> | ||
| 13 | |||
| 14 | #define MAXUINT USHRT_MAX | ||
| 15 | |||
| 16 | #include "wcautil.h" | ||
| 17 | #include "fileutil.h" | ||
| 18 | #include "memutil.h" | ||
| 19 | #include "strutil.h" | ||
| 20 | #include "wiutil.h" | ||
| 21 | |||
| 22 | #include "CustomMsiErrors.h" | ||
| 23 | |||
| 24 | #include "sca.h" | ||
| 25 | #include "scacost.h" | ||
| 26 | #include "scasqlstr.h" | ||
| 27 | |||
| 28 | #include "caDecor.h" | ||
diff --git a/src/ext/Sql/ca/sca.h b/src/ext/Sql/ca/sca.h new file mode 100644 index 00000000..bc36344e --- /dev/null +++ b/src/ext/Sql/ca/sca.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | // Generic action enum. | ||
| 5 | enum SCA_ACTION | ||
| 6 | { | ||
| 7 | SCA_ACTION_NONE, | ||
| 8 | SCA_ACTION_INSTALL, | ||
| 9 | SCA_ACTION_UNINSTALL | ||
| 10 | }; | ||
| 11 | |||
| 12 | // sql database attributes definitions | ||
| 13 | enum SCADB_ATTRIBUTES | ||
| 14 | { | ||
| 15 | SCADB_CREATE_ON_INSTALL = 0x00000001, | ||
| 16 | SCADB_DROP_ON_UNINSTALL = 0x00000002, | ||
| 17 | SCADB_CONTINUE_ON_ERROR = 0x00000004, | ||
| 18 | SCADB_DROP_ON_INSTALL = 0x00000008, | ||
| 19 | SCADB_CREATE_ON_UNINSTALL = 0x00000010, | ||
| 20 | SCADB_CONFIRM_OVERWRITE = 0x00000020, | ||
| 21 | SCADB_CREATE_ON_REINSTALL = 0x00000040, | ||
| 22 | SCADB_DROP_ON_REINSTALL = 0x00000080, | ||
| 23 | }; | ||
| 24 | |||
| 25 | // sql string/script attributes definitions | ||
| 26 | enum SCASQL_ATTRIBUTES | ||
| 27 | { | ||
| 28 | SCASQL_EXECUTE_ON_INSTALL = 0x00000001, | ||
| 29 | SCASQL_EXECUTE_ON_UNINSTALL = 0x00000002, | ||
| 30 | SCASQL_CONTINUE_ON_ERROR = 0x00000004, | ||
| 31 | SCASQL_ROLLBACK = 0x00000008, | ||
| 32 | SCASQL_EXECUTE_ON_REINSTALL = 0x00000010, | ||
| 33 | }; | ||
diff --git a/src/ext/Sql/ca/scacost.h b/src/ext/Sql/ca/scacost.h new file mode 100644 index 00000000..6ea7e465 --- /dev/null +++ b/src/ext/Sql/ca/scacost.h | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | const UINT COST_SQL_CREATEDB = 10000; | ||
| 5 | const UINT COST_SQL_DROPDB = 5000; | ||
| 6 | const UINT COST_SQL_CONNECTDB = 5000; | ||
| 7 | const UINT COST_SQL_STRING = 5000; | ||
diff --git a/src/ext/Sql/ca/scadb.cpp b/src/ext/Sql/ca/scadb.cpp new file mode 100644 index 00000000..288b9efe --- /dev/null +++ b/src/ext/Sql/ca/scadb.cpp | |||
| @@ -0,0 +1,588 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | // sql queries | ||
| 6 | LPCWSTR vcsSqlDatabaseQuery = L"SELECT `SqlDb`, `Server`, `Instance`, `Database`, " | ||
| 7 | L"`Component_`, `User_`, `FileSpec_`, `FileSpec_Log`, `Attributes` " | ||
| 8 | L"FROM `Wix4SqlDatabase`"; | ||
| 9 | enum eSqlDatabaseQuery { sdqSqlDb = 1, sdqServer, sdqInstance, sdqDatabase, | ||
| 10 | sdqComponent, sdqUser, sdqDbFileSpec, sdqLogFileSpec, sdqAttributes }; | ||
| 11 | |||
| 12 | LPCWSTR vcsSqlFileSpecQuery = L"SELECT `FileSpec`, `Name`, `Filename`, `Size`, " | ||
| 13 | L"`MaxSize`, `GrowthSize` FROM `Wix4SqlFileSpec` WHERE `FileSpec`=?"; | ||
| 14 | enum eSqlFileSpecQuery { sfsqFileSpec = 1, sfsqName, sfsqFilename, sfsqSize, | ||
| 15 | sfsqMaxSize, sfsqGrowth }; | ||
| 16 | |||
| 17 | |||
| 18 | // prototypes for private helper functions | ||
| 19 | static HRESULT NewDb( | ||
| 20 | __out SCA_DB** ppsd | ||
| 21 | ); | ||
| 22 | |||
| 23 | static SCA_DB* AddDbToList( | ||
| 24 | __in SCA_DB* psdList, | ||
| 25 | __in SCA_DB* psd | ||
| 26 | ); | ||
| 27 | |||
| 28 | static HRESULT SchedCreateDatabase( | ||
| 29 | __in SCA_DB* psd | ||
| 30 | ); | ||
| 31 | |||
| 32 | static HRESULT SchedDropDatabase( | ||
| 33 | __in LPCWSTR wzKey, LPCWSTR wzServer, | ||
| 34 | __in LPCWSTR wzInstance, | ||
| 35 | __in LPCWSTR wzDatabase, | ||
| 36 | __in int iAttributes, | ||
| 37 | __in BOOL fIntegratedAuth, | ||
| 38 | __in LPCWSTR wzUser, | ||
| 39 | __in LPCWSTR wzPassword | ||
| 40 | ); | ||
| 41 | |||
| 42 | static HRESULT GetFileSpec( | ||
| 43 | __in MSIHANDLE hViewFileSpec, | ||
| 44 | __in LPCWSTR wzKey, | ||
| 45 | __in SQL_FILESPEC* psf | ||
| 46 | ); | ||
| 47 | |||
| 48 | |||
| 49 | HRESULT ScaDbsRead( | ||
| 50 | __inout SCA_DB** ppsdList, | ||
| 51 | __in SCA_ACTION saAction | ||
| 52 | ) | ||
| 53 | { | ||
| 54 | HRESULT hr = S_OK; | ||
| 55 | UINT er = ERROR_SUCCESS; | ||
| 56 | PMSIHANDLE hView; | ||
| 57 | PMSIHANDLE hRec; | ||
| 58 | PMSIHANDLE hViewFileSpec = NULL; | ||
| 59 | |||
| 60 | LPWSTR pwzData = NULL; | ||
| 61 | LPWSTR pwzId = NULL; | ||
| 62 | LPWSTR pwzComponent = NULL; | ||
| 63 | |||
| 64 | SCA_DB* psd = NULL; | ||
| 65 | |||
| 66 | if (S_OK != WcaTableExists(L"Wix4SqlDatabase")) | ||
| 67 | { | ||
| 68 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaCreateDatabase() - Wix4SqlDatabase table not present"); | ||
| 69 | ExitFunction1(hr = S_FALSE); | ||
| 70 | } | ||
| 71 | |||
| 72 | if (S_OK == WcaTableExists(L"Wix4SqlFileSpec")) | ||
| 73 | { | ||
| 74 | hr = WcaOpenView(vcsSqlFileSpecQuery, &hViewFileSpec); | ||
| 75 | ExitOnFailure(hr, "failed to open view on Wix4SqlFileSpec table"); | ||
| 76 | } | ||
| 77 | |||
| 78 | // loop through all the sql databases | ||
| 79 | hr = WcaOpenExecuteView(vcsSqlDatabaseQuery, &hView); | ||
| 80 | ExitOnFailure(hr, "Failed to open view on Wix4SqlDatabase table"); | ||
| 81 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 82 | { | ||
| 83 | BOOL fHasComponent = FALSE; | ||
| 84 | INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN; | ||
| 85 | INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN; | ||
| 86 | |||
| 87 | hr = WcaGetRecordString(hRec, sdqSqlDb, &pwzId); | ||
| 88 | ExitOnFailure(hr, "Failed to get Wix4SqlDatabase.SqlDb"); | ||
| 89 | |||
| 90 | hr = WcaGetRecordString(hRec, sdqComponent, &pwzComponent); | ||
| 91 | ExitOnFailure(hr, "Failed to get Component for database: '%ls'", psd->wzKey); | ||
| 92 | if (pwzComponent && *pwzComponent) | ||
| 93 | { | ||
| 94 | fHasComponent = TRUE; | ||
| 95 | |||
| 96 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzComponent, &isInstalled, &isAction); | ||
| 97 | hr = HRESULT_FROM_WIN32(er); | ||
| 98 | ExitOnFailure(hr, "Failed to get state for component: %ls", pwzComponent); | ||
| 99 | |||
| 100 | // If we're doing install but the Component is not being installed or we're doing | ||
| 101 | // uninstall but the Component is not being uninstalled, skip it. | ||
| 102 | if ((WcaIsInstalling(isInstalled, isAction) && SCA_ACTION_INSTALL != saAction) || | ||
| 103 | (WcaIsUninstalling(isInstalled, isAction) && SCA_ACTION_UNINSTALL != saAction)) | ||
| 104 | { | ||
| 105 | continue; | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | hr = NewDb(&psd); | ||
| 110 | ExitOnFailure(hr, "Failed to allocate memory for new database: %D", pwzId); | ||
| 111 | |||
| 112 | hr = ::StringCchCopyW(psd->wzKey, countof(psd->wzKey), pwzId); | ||
| 113 | ExitOnFailure(hr, "Failed to copy Wix4SqlDatabase.SqlDbL: %ls", pwzId); | ||
| 114 | |||
| 115 | hr = ::StringCchCopyW(psd->wzComponent, countof(psd->wzComponent), pwzComponent); | ||
| 116 | ExitOnFailure(hr, "Failed to copy Wix4SqlDatabase.Component_: %ls", pwzComponent); | ||
| 117 | |||
| 118 | psd->fHasComponent = fHasComponent; | ||
| 119 | psd->isInstalled = isInstalled; | ||
| 120 | psd->isAction = isAction; | ||
| 121 | |||
| 122 | hr = WcaGetRecordFormattedString(hRec, sdqServer, &pwzData); | ||
| 123 | ExitOnFailure(hr, "Failed to get Server for database: '%ls'", psd->wzKey); | ||
| 124 | hr = ::StringCchCopyW(psd->wzServer, countof(psd->wzServer), pwzData); | ||
| 125 | ExitOnFailure(hr, "Failed to copy server string to database object:%ls", pwzData); | ||
| 126 | |||
| 127 | hr = WcaGetRecordFormattedString(hRec, sdqInstance, &pwzData); | ||
| 128 | ExitOnFailure(hr, "Failed to get Instance for database: '%ls'", psd->wzKey); | ||
| 129 | hr = ::StringCchCopyW(psd->wzInstance, countof(psd->wzInstance), pwzData); | ||
| 130 | ExitOnFailure(hr, "Failed to copy instance string to database object:%ls", pwzData); | ||
| 131 | |||
| 132 | hr = WcaGetRecordFormattedString(hRec, sdqDatabase, &pwzData); | ||
| 133 | ExitOnFailure(hr, "Failed to get Database for database: '%ls'", psd->wzKey); | ||
| 134 | hr = ::StringCchCopyW(psd->wzDatabase, countof(psd->wzDatabase), pwzData); | ||
| 135 | ExitOnFailure(hr, "Failed to copy database string to database object:%ls", pwzData); | ||
| 136 | |||
| 137 | hr = WcaGetRecordInteger(hRec, sdqAttributes, &psd->iAttributes); | ||
| 138 | ExitOnFailure(hr, "Failed to get Wix4SqlDatabase.Attributes"); | ||
| 139 | |||
| 140 | hr = WcaGetRecordFormattedString(hRec, sdqUser, &pwzData); | ||
| 141 | ExitOnFailure(hr, "Failed to get User record for database: '%ls'", psd->wzKey); | ||
| 142 | |||
| 143 | // if a user was specified | ||
| 144 | if (*pwzData) | ||
| 145 | { | ||
| 146 | psd->fUseIntegratedAuth = FALSE; | ||
| 147 | hr = ScaGetUser(pwzData, &psd->scau); | ||
| 148 | ExitOnFailure(hr, "Failed to get user information for database: '%ls'", psd->wzKey); | ||
| 149 | } | ||
| 150 | else | ||
| 151 | { | ||
| 152 | psd->fUseIntegratedAuth = TRUE; | ||
| 153 | // integrated authorization doesn't have a User record | ||
| 154 | } | ||
| 155 | |||
| 156 | hr = WcaGetRecordString(hRec, sdqDbFileSpec, &pwzData); | ||
| 157 | ExitOnFailure(hr, "Failed to get Database FileSpec for database: '%ls'", psd->wzKey); | ||
| 158 | |||
| 159 | // if a database filespec was specified | ||
| 160 | if (*pwzData) | ||
| 161 | { | ||
| 162 | hr = GetFileSpec(hViewFileSpec, pwzData, &psd->sfDb); | ||
| 163 | ExitOnFailure(hr, "failed to get FileSpec for: %ls", pwzData); | ||
| 164 | if (S_OK == hr) | ||
| 165 | { | ||
| 166 | psd->fHasDbSpec = TRUE; | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | hr = WcaGetRecordString(hRec, sdqLogFileSpec, &pwzData); | ||
| 171 | ExitOnFailure(hr, "Failed to get Log FileSpec for database: '%ls'", psd->wzKey); | ||
| 172 | |||
| 173 | // if a log filespec was specified | ||
| 174 | if (*pwzData) | ||
| 175 | { | ||
| 176 | hr = GetFileSpec(hViewFileSpec, pwzData, &psd->sfLog); | ||
| 177 | ExitOnFailure(hr, "failed to get FileSpec for: %ls", pwzData); | ||
| 178 | if (S_OK == hr) | ||
| 179 | { | ||
| 180 | psd->fHasLogSpec = TRUE; | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | *ppsdList = AddDbToList(*ppsdList, psd); | ||
| 185 | psd = NULL; // set the db NULL so it doesn't accidentally get freed below | ||
| 186 | } | ||
| 187 | |||
| 188 | if (E_NOMOREITEMS == hr) | ||
| 189 | { | ||
| 190 | hr = S_OK; | ||
| 191 | } | ||
| 192 | ExitOnFailure(hr, "Failure occured while processing Wix4SqlDatabase table"); | ||
| 193 | |||
| 194 | LExit: | ||
| 195 | if (psd) | ||
| 196 | { | ||
| 197 | ScaDbsFreeList(psd); | ||
| 198 | } | ||
| 199 | |||
| 200 | ReleaseStr(pwzComponent); | ||
| 201 | ReleaseStr(pwzId); | ||
| 202 | ReleaseStr(pwzData); | ||
| 203 | return hr; | ||
| 204 | } | ||
| 205 | |||
| 206 | |||
| 207 | SCA_DB* ScaDbsFindDatabase( | ||
| 208 | __in LPCWSTR wzSqlDb, | ||
| 209 | __in SCA_DB* psdList | ||
| 210 | ) | ||
| 211 | { | ||
| 212 | SCA_DB* psd = NULL; | ||
| 213 | |||
| 214 | for (psd = psdList; psd; psd = psd->psdNext) | ||
| 215 | { | ||
| 216 | if (0 == lstrcmpW(wzSqlDb, psd->wzKey)) | ||
| 217 | { | ||
| 218 | break; | ||
| 219 | } | ||
| 220 | } | ||
| 221 | |||
| 222 | return psd; | ||
| 223 | } | ||
| 224 | |||
| 225 | |||
| 226 | HRESULT ScaDbsInstall( | ||
| 227 | __in SCA_DB* psdList | ||
| 228 | ) | ||
| 229 | { | ||
| 230 | HRESULT hr = S_FALSE; // assume nothing will be done | ||
| 231 | SCA_DB* psd = NULL; | ||
| 232 | |||
| 233 | for (psd = psdList; psd; psd = psd->psdNext) | ||
| 234 | { | ||
| 235 | if (psd->fHasComponent) | ||
| 236 | { | ||
| 237 | // if we need to drop, do that first | ||
| 238 | if (((psd->iAttributes & SCADB_DROP_ON_INSTALL) && WcaIsInstalling(psd->isInstalled, psd->isAction) && !WcaIsReInstalling(psd->isInstalled, psd->isAction)) || | ||
| 239 | ((psd->iAttributes & SCADB_DROP_ON_REINSTALL) && WcaIsReInstalling(psd->isInstalled, psd->isAction))) | ||
| 240 | { | ||
| 241 | hr = SchedDropDatabase(psd->wzKey, psd->wzServer, psd->wzInstance, psd->wzDatabase, psd->iAttributes, psd->fUseIntegratedAuth, psd->scau.wzName, psd->scau.wzPassword); | ||
| 242 | ExitOnFailure(hr, "Failed to drop database %ls", psd->wzKey); | ||
| 243 | } | ||
| 244 | |||
| 245 | // if installing this component | ||
| 246 | if (((psd->iAttributes & SCADB_CREATE_ON_INSTALL) && WcaIsInstalling(psd->isInstalled, psd->isAction) && !WcaIsReInstalling(psd->isInstalled, psd->isAction)) || | ||
| 247 | ((psd->iAttributes & SCADB_CREATE_ON_REINSTALL) && WcaIsReInstalling(psd->isInstalled, psd->isAction))) | ||
| 248 | { | ||
| 249 | hr = SchedCreateDatabase(psd); | ||
| 250 | ExitOnFailure(hr, "Failed to ensure database %ls exists", psd->wzKey); | ||
| 251 | } | ||
| 252 | } | ||
| 253 | } | ||
| 254 | |||
| 255 | LExit: | ||
| 256 | return hr; | ||
| 257 | } | ||
| 258 | |||
| 259 | |||
| 260 | HRESULT ScaDbsUninstall( | ||
| 261 | __in SCA_DB* psdList | ||
| 262 | ) | ||
| 263 | { | ||
| 264 | HRESULT hr = S_FALSE; // assume nothing will be done | ||
| 265 | SCA_DB* psd = NULL; | ||
| 266 | |||
| 267 | for (psd = psdList; psd; psd = psd->psdNext) | ||
| 268 | { | ||
| 269 | if (psd->fHasComponent) | ||
| 270 | { | ||
| 271 | // if we need to drop do that first | ||
| 272 | if ((psd->iAttributes & SCADB_DROP_ON_UNINSTALL) && WcaIsUninstalling(psd->isInstalled, psd->isAction)) | ||
| 273 | { | ||
| 274 | hr = SchedDropDatabase(psd->wzKey, psd->wzServer, psd->wzInstance, psd->wzDatabase, psd->iAttributes, psd->fUseIntegratedAuth, psd->scau.wzName, psd->scau.wzPassword); | ||
| 275 | ExitOnFailure(hr, "Failed to drop database %ls", psd->wzKey); | ||
| 276 | } | ||
| 277 | |||
| 278 | // install the db | ||
| 279 | if ((psd->iAttributes & SCADB_CREATE_ON_UNINSTALL) && WcaIsUninstalling(psd->isInstalled, psd->isAction)) | ||
| 280 | { | ||
| 281 | hr = SchedCreateDatabase(psd); | ||
| 282 | ExitOnFailure(hr, "Failed to ensure database %ls exists", psd->wzKey); | ||
| 283 | } | ||
| 284 | } | ||
| 285 | } | ||
| 286 | |||
| 287 | LExit: | ||
| 288 | return hr; | ||
| 289 | } | ||
| 290 | |||
| 291 | |||
| 292 | void ScaDbsFreeList( | ||
| 293 | __in SCA_DB* psdList | ||
| 294 | ) | ||
| 295 | { | ||
| 296 | SCA_DB* psdDelete = psdList; | ||
| 297 | while (psdList) | ||
| 298 | { | ||
| 299 | psdDelete = psdList; | ||
| 300 | psdList = psdList->psdNext; | ||
| 301 | |||
| 302 | MemFree(psdDelete); | ||
| 303 | } | ||
| 304 | } | ||
| 305 | |||
| 306 | |||
| 307 | // private helper functions | ||
| 308 | |||
| 309 | static HRESULT NewDb( | ||
| 310 | __out SCA_DB** ppsd | ||
| 311 | ) | ||
| 312 | { | ||
| 313 | HRESULT hr = S_OK; | ||
| 314 | SCA_DB* psd = static_cast<SCA_DB*>(MemAlloc(sizeof(SCA_DB), TRUE)); | ||
| 315 | ExitOnNull(psd, hr, E_OUTOFMEMORY, "failed to allocate memory for new database element"); | ||
| 316 | |||
| 317 | *ppsd = psd; | ||
| 318 | |||
| 319 | LExit: | ||
| 320 | return hr; | ||
| 321 | } | ||
| 322 | |||
| 323 | |||
| 324 | static SCA_DB* AddDbToList( | ||
| 325 | __in SCA_DB* psdList, | ||
| 326 | __in SCA_DB* psd | ||
| 327 | ) | ||
| 328 | { | ||
| 329 | if (psdList) | ||
| 330 | { | ||
| 331 | SCA_DB* psdT = psdList; | ||
| 332 | while (psdT->psdNext) | ||
| 333 | { | ||
| 334 | psdT = psdT->psdNext; | ||
| 335 | } | ||
| 336 | |||
| 337 | psdT->psdNext = psd; | ||
| 338 | } | ||
| 339 | else | ||
| 340 | { | ||
| 341 | psdList = psd; | ||
| 342 | } | ||
| 343 | |||
| 344 | return psdList; | ||
| 345 | } | ||
| 346 | |||
| 347 | |||
| 348 | static HRESULT SchedCreateDatabase( | ||
| 349 | __in SCA_DB* psd | ||
| 350 | ) | ||
| 351 | { | ||
| 352 | HRESULT hr = S_OK; | ||
| 353 | WCHAR* pwzCustomActionData = NULL; | ||
| 354 | |||
| 355 | hr = WcaWriteStringToCaData(psd->wzKey, &pwzCustomActionData); | ||
| 356 | ExitOnFailure(hr, "failed to add DBKey to CustomActionData"); | ||
| 357 | |||
| 358 | hr = WcaWriteStringToCaData(psd->wzServer, &pwzCustomActionData); | ||
| 359 | ExitOnFailure(hr, "Failed to add server name to CustomActionData"); | ||
| 360 | |||
| 361 | hr = WcaWriteStringToCaData(psd->wzInstance, &pwzCustomActionData); | ||
| 362 | ExitOnFailure(hr, "Failed to add server instance to CustomActionData"); | ||
| 363 | |||
| 364 | hr = WcaWriteStringToCaData(psd->wzDatabase, &pwzCustomActionData); | ||
| 365 | ExitOnFailure(hr, "Failed to add database name to CustomActionData"); | ||
| 366 | |||
| 367 | hr = WcaWriteIntegerToCaData(psd->iAttributes, &pwzCustomActionData); | ||
| 368 | ExitOnFailure(hr, "Failed to add Sql attributes to CustomActionData"); | ||
| 369 | |||
| 370 | hr = WcaWriteStringToCaData(psd->fUseIntegratedAuth ? L"1" : L"0", &pwzCustomActionData); | ||
| 371 | ExitOnFailure(hr, "Failed to add if integrated connection to CustomActionData"); | ||
| 372 | |||
| 373 | hr = WcaWriteStringToCaData(psd->scau.wzName, &pwzCustomActionData); | ||
| 374 | ExitOnFailure(hr, "Failed to add server user to CustomActionData"); | ||
| 375 | |||
| 376 | hr = WcaWriteStringToCaData(psd->scau.wzPassword, &pwzCustomActionData); | ||
| 377 | ExitOnFailure(hr, "Failed to add user password to CustomActionData"); | ||
| 378 | |||
| 379 | // Check to see if the database exists, if it does not then schedule a rollback | ||
| 380 | // so we clean up after ourselves if the creation of the database fails or is | ||
| 381 | // aborted. It is interesting to note that we can do this check here because the | ||
| 382 | // deferred CustomActions are Impersonated. That means this scheduling action and | ||
| 383 | // the execution actions all run with the same user context, so it is safe to | ||
| 384 | // to do the check. | ||
| 385 | hr = SqlDatabaseExists(psd->wzServer, psd->wzInstance, psd->wzDatabase, psd->fUseIntegratedAuth, psd->scau.wzName, psd->scau.wzPassword, NULL); | ||
| 386 | if (S_FALSE == hr) | ||
| 387 | { | ||
| 388 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackCreateDatabase"), pwzCustomActionData, COST_SQL_CREATEDB); | ||
| 389 | ExitOnFailure(hr, "Failed to schedule RollbackCreateDatabase action"); | ||
| 390 | } | ||
| 391 | |||
| 392 | // database filespec | ||
| 393 | if (psd->fHasDbSpec) | ||
| 394 | { | ||
| 395 | hr = WcaWriteStringToCaData(L"1", &pwzCustomActionData); | ||
| 396 | ExitOnFailure(hr, "failed to specify that do have db.filespec to CustomActionData"); | ||
| 397 | |||
| 398 | hr = WcaWriteStringToCaData(psd->sfDb.wzName, &pwzCustomActionData); | ||
| 399 | ExitOnFailure(hr, "failed to add FileSpec.Name to CustomActionData"); | ||
| 400 | |||
| 401 | hr = WcaWriteStringToCaData(psd->sfDb.wzFilename, &pwzCustomActionData); | ||
| 402 | ExitOnFailure(hr, "failed to add FileSpec.Filename to CustomActionData"); | ||
| 403 | |||
| 404 | hr = WcaWriteStringToCaData(psd->sfDb.wzSize, &pwzCustomActionData); | ||
| 405 | ExitOnFailure(hr, "Failed to add FileSpec.Size to CustomActionData"); | ||
| 406 | |||
| 407 | hr = WcaWriteStringToCaData(psd->sfDb.wzMaxSize, &pwzCustomActionData); | ||
| 408 | ExitOnFailure(hr, "Failed to add FileSpec.MaxSize to CustomActionData"); | ||
| 409 | |||
| 410 | hr = WcaWriteStringToCaData(psd->sfDb.wzGrow, &pwzCustomActionData); | ||
| 411 | ExitOnFailure(hr, "Failed to add FileSpec.GrowthSize to CustomActionData"); | ||
| 412 | } | ||
| 413 | else | ||
| 414 | { | ||
| 415 | hr = WcaWriteStringToCaData(L"0", &pwzCustomActionData); | ||
| 416 | ExitOnFailure(hr, "failed to specify that do not have db.filespec to CustomActionData"); | ||
| 417 | } | ||
| 418 | |||
| 419 | // log filespec | ||
| 420 | if (psd->fHasLogSpec) | ||
| 421 | { | ||
| 422 | hr = WcaWriteStringToCaData(L"1", &pwzCustomActionData); | ||
| 423 | ExitOnFailure(hr, "failed to specify that do have log.filespec to CustomActionData"); | ||
| 424 | |||
| 425 | hr = WcaWriteStringToCaData(psd->sfLog.wzName, &pwzCustomActionData); | ||
| 426 | ExitOnFailure(hr, "failed to add FileSpec.Name to CustomActionData"); | ||
| 427 | |||
| 428 | hr = WcaWriteStringToCaData(psd->sfLog.wzFilename, &pwzCustomActionData); | ||
| 429 | ExitOnFailure(hr, "failed to add FileSpec.Filename to CustomActionData"); | ||
| 430 | |||
| 431 | hr = WcaWriteStringToCaData(psd->sfLog.wzSize, &pwzCustomActionData); | ||
| 432 | ExitOnFailure(hr, "Failed to add FileSpec.Size to CustomActionData"); | ||
| 433 | |||
| 434 | hr = WcaWriteStringToCaData(psd->sfLog.wzMaxSize, &pwzCustomActionData); | ||
| 435 | ExitOnFailure(hr, "Failed to add FileSpec.MaxSize to CustomActionData"); | ||
| 436 | |||
| 437 | hr = WcaWriteStringToCaData(psd->sfLog.wzGrow, &pwzCustomActionData); | ||
| 438 | ExitOnFailure(hr, "Failed to add FileSpec.GrowthSize to CustomActionData"); | ||
| 439 | } | ||
| 440 | else | ||
| 441 | { | ||
| 442 | hr = WcaWriteStringToCaData(L"0", &pwzCustomActionData); | ||
| 443 | ExitOnFailure(hr, "failed to specify that do not have log.filespec to CustomActionData"); | ||
| 444 | } | ||
| 445 | |||
| 446 | // schedule the CreateDatabase action | ||
| 447 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CreateDatabase"), pwzCustomActionData, COST_SQL_CREATEDB); | ||
| 448 | ExitOnFailure(hr, "Failed to schedule CreateDatabase action"); | ||
| 449 | |||
| 450 | LExit: | ||
| 451 | ReleaseStr(pwzCustomActionData); | ||
| 452 | return hr; | ||
| 453 | } | ||
| 454 | |||
| 455 | |||
| 456 | HRESULT SchedDropDatabase( | ||
| 457 | __in LPCWSTR wzKey, | ||
| 458 | __in LPCWSTR wzServer, | ||
| 459 | __in LPCWSTR wzInstance, | ||
| 460 | __in LPCWSTR wzDatabase, | ||
| 461 | __in int iAttributes, | ||
| 462 | __in BOOL fIntegratedAuth, | ||
| 463 | __in LPCWSTR wzUser, | ||
| 464 | __in LPCWSTR wzPassword | ||
| 465 | ) | ||
| 466 | { | ||
| 467 | HRESULT hr = S_OK; | ||
| 468 | WCHAR* pwzCustomActionData = NULL; | ||
| 469 | |||
| 470 | hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData); | ||
| 471 | ExitOnFailure(hr, "failed to add DBKey to CustomActionData"); | ||
| 472 | |||
| 473 | hr = WcaWriteStringToCaData(wzServer, &pwzCustomActionData); | ||
| 474 | ExitOnFailure(hr, "Failed to add server name to CustomActionData"); | ||
| 475 | |||
| 476 | hr = WcaWriteStringToCaData(wzInstance, &pwzCustomActionData); | ||
| 477 | ExitOnFailure(hr, "Failed to add server instance to CustomActionData"); | ||
| 478 | |||
| 479 | hr = WcaWriteStringToCaData(wzDatabase, &pwzCustomActionData); | ||
| 480 | ExitOnFailure(hr, "Failed to add database name to CustomActionData"); | ||
| 481 | |||
| 482 | hr = WcaWriteIntegerToCaData(iAttributes, &pwzCustomActionData); | ||
| 483 | ExitOnFailure(hr, "Failed to add server name to CustomActionData"); | ||
| 484 | |||
| 485 | hr = WcaWriteStringToCaData(fIntegratedAuth ? L"1" : L"0", &pwzCustomActionData); | ||
| 486 | ExitOnFailure(hr, "Failed to add server name to CustomActionData"); | ||
| 487 | |||
| 488 | hr = WcaWriteStringToCaData(wzUser, &pwzCustomActionData); | ||
| 489 | ExitOnFailure(hr, "Failed to add server user to CustomActionData"); | ||
| 490 | |||
| 491 | hr = WcaWriteStringToCaData(wzPassword, &pwzCustomActionData); | ||
| 492 | ExitOnFailure(hr, "Failed to add user password to CustomActionData"); | ||
| 493 | |||
| 494 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"DropDatabase"), pwzCustomActionData, COST_SQL_DROPDB); | ||
| 495 | ExitOnFailure(hr, "Failed to schedule DropDatabase action"); | ||
| 496 | |||
| 497 | LExit: | ||
| 498 | ReleaseStr(pwzCustomActionData); | ||
| 499 | return hr; | ||
| 500 | } | ||
| 501 | |||
| 502 | |||
| 503 | HRESULT GetFileSpec( | ||
| 504 | __in MSIHANDLE hViewFileSpec, | ||
| 505 | __in LPCWSTR wzKey, | ||
| 506 | __in SQL_FILESPEC* psf | ||
| 507 | ) | ||
| 508 | { | ||
| 509 | HRESULT hr = S_OK; | ||
| 510 | PMSIHANDLE hRecFileSpec, hRec; | ||
| 511 | LPWSTR pwzData = NULL; | ||
| 512 | |||
| 513 | // create a record to do the fetch | ||
| 514 | hRecFileSpec = ::MsiCreateRecord(1); | ||
| 515 | if (!hRecFileSpec) | ||
| 516 | { | ||
| 517 | ExitOnFailure(hr = E_UNEXPECTED, "failed to create record for filespec: %ls", wzKey); | ||
| 518 | } | ||
| 519 | hr = WcaSetRecordString(hRecFileSpec, 1, wzKey); | ||
| 520 | ExitOnFailure(hr, "failed to set record string for filespec: %ls", wzKey); | ||
| 521 | |||
| 522 | // get the FileSpec record | ||
| 523 | hr = WcaExecuteView(hViewFileSpec, hRecFileSpec); | ||
| 524 | ExitOnFailure(hr, "failed to execute view on Wix4SqlFileSpec table for filespec: %ls", wzKey); | ||
| 525 | hr = WcaFetchSingleRecord(hViewFileSpec, &hRec); | ||
| 526 | ExitOnFailure(hr, "failed to get record for filespec: %ls", wzKey); | ||
| 527 | |||
| 528 | // read the data out of the filespec record | ||
| 529 | hr = WcaGetRecordFormattedString(hRec, sfsqName, &pwzData); | ||
| 530 | ExitOnFailure(hr, "Failed to get Wix4SqlFileSpec.Name for filespec: %ls", wzKey); | ||
| 531 | hr = ::StringCchCopyW(psf->wzName, countof(psf->wzName), pwzData); | ||
| 532 | ExitOnFailure(hr, "Failed to copy Wix4SqlFileSpec.Name string: %ls", pwzData); | ||
| 533 | |||
| 534 | hr = WcaGetRecordFormattedString(hRec, sfsqFilename, &pwzData); | ||
| 535 | ExitOnFailure(hr, "Failed to get Wix4SqlFileSpec.Filename for filespec: %ls", wzKey); | ||
| 536 | if (*pwzData) | ||
| 537 | { | ||
| 538 | hr = ::StringCchCopyW(psf->wzFilename, countof(psf->wzFilename), pwzData); | ||
| 539 | ExitOnFailure(hr, "Failed to copy filename to filespec object: %ls", pwzData); | ||
| 540 | } | ||
| 541 | else // if there is no file, skip this FILESPEC | ||
| 542 | { | ||
| 543 | WcaLog(LOGMSG_VERBOSE, "No filename specified, skipping FileSpec: %ls", psf->wzName); | ||
| 544 | ExitFunction1(hr = S_FALSE); | ||
| 545 | } | ||
| 546 | |||
| 547 | hr = WcaGetRecordFormattedString(hRec, sfsqSize, &pwzData); | ||
| 548 | ExitOnFailure(hr, "Failed to get Wix4SqlFileSpec.Size for filespec: %ls", wzKey); | ||
| 549 | if (*pwzData) | ||
| 550 | { | ||
| 551 | hr = ::StringCchCopyW(psf->wzSize, countof(psf->wzSize), pwzData); | ||
| 552 | ExitOnFailure(hr, "Failed to copy size to filespec object: %ls", pwzData); | ||
| 553 | } | ||
| 554 | else | ||
| 555 | { | ||
| 556 | psf->wzSize[0] = 0; | ||
| 557 | } | ||
| 558 | |||
| 559 | hr = WcaGetRecordFormattedString(hRec, sfsqMaxSize, &pwzData); | ||
| 560 | ExitOnFailure(hr, "Failed to get Wix4SqlFileSpec.MaxSize for filespec: %ls", wzKey); | ||
| 561 | if (*pwzData) | ||
| 562 | { | ||
| 563 | hr = ::StringCchCopyW(psf->wzMaxSize, countof(psf->wzMaxSize), pwzData); | ||
| 564 | ExitOnFailure(hr, "Failed to copy max size to filespec object: %ls", pwzData); | ||
| 565 | } | ||
| 566 | else | ||
| 567 | { | ||
| 568 | psf->wzMaxSize[0] = 0; | ||
| 569 | } | ||
| 570 | |||
| 571 | hr = WcaGetRecordFormattedString(hRec, sfsqGrowth, &pwzData); | ||
| 572 | ExitOnFailure(hr, "Failed to get Wix4SqlFileSpec.GrowthSize for filespec: %ls", wzKey); | ||
| 573 | if (*pwzData) | ||
| 574 | { | ||
| 575 | hr = ::StringCchCopyW(psf->wzGrow, countof(psf->wzGrow), pwzData); | ||
| 576 | ExitOnFailure(hr, "Failed to copy growth size to filespec object: %ls", pwzData); | ||
| 577 | } | ||
| 578 | else | ||
| 579 | { | ||
| 580 | psf->wzGrow[0] = 0; | ||
| 581 | } | ||
| 582 | |||
| 583 | hr = S_OK; | ||
| 584 | |||
| 585 | LExit: | ||
| 586 | ReleaseStr(pwzData); | ||
| 587 | return hr; | ||
| 588 | } | ||
diff --git a/src/ext/Sql/ca/scadb.h b/src/ext/Sql/ca/scadb.h new file mode 100644 index 00000000..885e84c2 --- /dev/null +++ b/src/ext/Sql/ca/scadb.h | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #include "scauser.h" | ||
| 6 | #include "sqlutil.h" | ||
| 7 | |||
| 8 | struct SCA_DB | ||
| 9 | { | ||
| 10 | // darwin information | ||
| 11 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 12 | BOOL fHasComponent; | ||
| 13 | WCHAR wzComponent[MAX_DARWIN_KEY + 1]; | ||
| 14 | INSTALLSTATE isInstalled, isAction; | ||
| 15 | |||
| 16 | WCHAR wzServer[MAX_DARWIN_COLUMN + 1]; | ||
| 17 | WCHAR wzInstance[MAX_DARWIN_COLUMN + 1]; | ||
| 18 | WCHAR wzDatabase[MAX_DARWIN_COLUMN + 1]; | ||
| 19 | |||
| 20 | int iAttributes; | ||
| 21 | |||
| 22 | BOOL fUseIntegratedAuth; | ||
| 23 | SCA_USER scau; | ||
| 24 | |||
| 25 | BOOL fHasDbSpec; | ||
| 26 | SQL_FILESPEC sfDb; | ||
| 27 | BOOL fHasLogSpec; | ||
| 28 | SQL_FILESPEC sfLog; | ||
| 29 | |||
| 30 | SCA_DB* psdNext; | ||
| 31 | }; | ||
| 32 | |||
| 33 | |||
| 34 | // prototypes | ||
| 35 | HRESULT ScaDbsRead( | ||
| 36 | __inout SCA_DB** ppsdList, | ||
| 37 | __in SCA_ACTION saAction | ||
| 38 | ); | ||
| 39 | |||
| 40 | SCA_DB* ScaDbsFindDatabase( | ||
| 41 | __in LPCWSTR wzSqlDb, | ||
| 42 | __in SCA_DB* psdList | ||
| 43 | ); | ||
| 44 | |||
| 45 | HRESULT ScaDbsInstall( | ||
| 46 | __in SCA_DB* psdList | ||
| 47 | ); | ||
| 48 | |||
| 49 | HRESULT ScaDbsUninstall( | ||
| 50 | __in SCA_DB* psdList | ||
| 51 | ); | ||
| 52 | |||
| 53 | void ScaDbsFreeList( | ||
| 54 | __in SCA_DB* psdList | ||
| 55 | ); | ||
diff --git a/src/ext/Sql/ca/scaexec.cpp b/src/ext/Sql/ca/scaexec.cpp new file mode 100644 index 00000000..b2648361 --- /dev/null +++ b/src/ext/Sql/ca/scaexec.cpp | |||
| @@ -0,0 +1,393 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | /******************************************************************** | ||
| 7 | * CreateDatabase - CUSTOM ACTION ENTRY POINT for creating databases | ||
| 8 | * | ||
| 9 | * Input: deferred CustomActionData - DbKey\tServer\tInstance\tDatabase\tAttributes\tIntegratedAuth\tUser\tPassword | ||
| 10 | * ****************************************************************/ | ||
| 11 | extern "C" UINT __stdcall CreateDatabase(MSIHANDLE hInstall) | ||
| 12 | { | ||
| 13 | //AssertSz(FALSE, "debug CreateDatabase here"); | ||
| 14 | UINT er = ERROR_SUCCESS; | ||
| 15 | HRESULT hr = S_OK; | ||
| 16 | |||
| 17 | LPWSTR pwzData = NULL; | ||
| 18 | IDBCreateSession* pidbSession = NULL; | ||
| 19 | BSTR bstrErrorDescription = NULL; | ||
| 20 | LPWSTR pwz = NULL; | ||
| 21 | LPWSTR pwzDatabaseKey = NULL; | ||
| 22 | LPWSTR pwzServer = NULL; | ||
| 23 | LPWSTR pwzInstance = NULL; | ||
| 24 | LPWSTR pwzDatabase = NULL; | ||
| 25 | LPWSTR pwzTemp = NULL; | ||
| 26 | int iAttributes; | ||
| 27 | BOOL fIntegratedAuth; | ||
| 28 | LPWSTR pwzUser = NULL; | ||
| 29 | LPWSTR pwzPassword = NULL; | ||
| 30 | BOOL fHaveDbFileSpec = FALSE; | ||
| 31 | SQL_FILESPEC sfDb; | ||
| 32 | BOOL fHaveLogFileSpec = FALSE; | ||
| 33 | SQL_FILESPEC sfLog; | ||
| 34 | BOOL fInitializedCom = FALSE; | ||
| 35 | |||
| 36 | memset(&sfDb, 0, sizeof(sfDb)); | ||
| 37 | memset(&sfLog, 0, sizeof(sfLog)); | ||
| 38 | |||
| 39 | hr = WcaInitialize(hInstall, "CreateDatabase"); | ||
| 40 | ExitOnFailure(hr, "failed to initialize"); | ||
| 41 | |||
| 42 | hr = ::CoInitialize(NULL); | ||
| 43 | ExitOnFailure(hr, "failed to intialize COM"); | ||
| 44 | fInitializedCom = TRUE; | ||
| 45 | |||
| 46 | hr = WcaGetProperty( L"CustomActionData", &pwzData); | ||
| 47 | ExitOnFailure(hr, "failed to get CustomActionData"); | ||
| 48 | |||
| 49 | WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); | ||
| 50 | |||
| 51 | pwz = pwzData; | ||
| 52 | hr = WcaReadStringFromCaData(&pwz, &pwzDatabaseKey); // SQL Server | ||
| 53 | ExitOnFailure(hr, "failed to read database key from custom action data: %ls", pwz); | ||
| 54 | hr = WcaReadStringFromCaData(&pwz, &pwzServer); // SQL Server | ||
| 55 | ExitOnFailure(hr, "failed to read server from custom action data: %ls", pwz); | ||
| 56 | hr = WcaReadStringFromCaData(&pwz, &pwzInstance); // SQL Server Instance | ||
| 57 | ExitOnFailure(hr, "failed to read server instance from custom action data: %ls", pwz); | ||
| 58 | hr = WcaReadStringFromCaData(&pwz, &pwzDatabase); // SQL Database | ||
| 59 | ExitOnFailure(hr, "failed to read server instance from custom action data: %ls", pwz); | ||
| 60 | hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); | ||
| 61 | ExitOnFailure(hr, "failed to read attributes from custom action data: %ls", pwz); | ||
| 62 | hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int *>(&fIntegratedAuth)); // Integrated Windows Authentication? | ||
| 63 | ExitOnFailure(hr, "failed to read integrated auth flag from custom action data: %ls", pwz); | ||
| 64 | hr = WcaReadStringFromCaData(&pwz, &pwzUser); // SQL User | ||
| 65 | ExitOnFailure(hr, "failed to read user from custom action data: %ls", pwz); | ||
| 66 | hr = WcaReadStringFromCaData(&pwz, &pwzPassword); // SQL User Password | ||
| 67 | ExitOnFailure(hr, "failed to read user from custom action data: %ls", pwz); | ||
| 68 | |||
| 69 | // db file spec | ||
| 70 | hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int *>(&fHaveDbFileSpec)); | ||
| 71 | ExitOnFailure(hr, "failed to read db file spec from custom action data: %ls", pwz); | ||
| 72 | |||
| 73 | if (fHaveDbFileSpec) | ||
| 74 | { | ||
| 75 | hr = WcaReadStringFromCaData(&pwz, &pwzTemp); | ||
| 76 | ExitOnFailure(hr, "failed to read db file spec name from custom action data: %ls", pwz); | ||
| 77 | hr = ::StringCchCopyW(sfDb.wzName, countof(sfDb.wzName), pwzTemp); | ||
| 78 | ExitOnFailure(hr, "failed to copy db file spec name: %ls", pwzTemp); | ||
| 79 | |||
| 80 | hr = WcaReadStringFromCaData(&pwz, &pwzTemp); | ||
| 81 | ExitOnFailure(hr, "failed to read db file spec filename from custom action data: %ls", pwz); | ||
| 82 | hr = ::StringCchCopyW(sfDb.wzFilename, countof(sfDb.wzFilename), pwzTemp); | ||
| 83 | ExitOnFailure(hr, "failed to copy db file spec filename: %ls", pwzTemp); | ||
| 84 | |||
| 85 | hr = WcaReadStringFromCaData(&pwz, &pwzTemp); | ||
| 86 | ExitOnFailure(hr, "failed to read db file spec size from custom action data: %ls", pwz); | ||
| 87 | hr = ::StringCchCopyW(sfDb.wzSize, countof(sfDb.wzSize), pwzTemp); | ||
| 88 | ExitOnFailure(hr, "failed to copy db file spec size value: %ls", pwzTemp); | ||
| 89 | |||
| 90 | hr = WcaReadStringFromCaData(&pwz, &pwzTemp); | ||
| 91 | ExitOnFailure(hr, "failed to read db file spec max size from custom action data: %ls", pwz); | ||
| 92 | hr = ::StringCchCopyW(sfDb.wzMaxSize, countof(sfDb.wzMaxSize), pwzTemp); | ||
| 93 | ExitOnFailure(hr, "failed to copy db file spec max size: %ls", pwzTemp); | ||
| 94 | |||
| 95 | hr = WcaReadStringFromCaData(&pwz, &pwzTemp); | ||
| 96 | ExitOnFailure(hr, "failed to read db file spec grow from custom action data: %ls", pwz); | ||
| 97 | hr = ::StringCchCopyW(sfDb.wzGrow, countof(sfDb.wzGrow), pwzTemp); | ||
| 98 | ExitOnFailure(hr, "failed to copy db file spec grow value: %ls", pwzTemp); | ||
| 99 | } | ||
| 100 | |||
| 101 | // log file spec | ||
| 102 | hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int *>(&fHaveLogFileSpec)); | ||
| 103 | ExitOnFailure(hr, "failed to read log file spec from custom action data: %ls", pwz); | ||
| 104 | if (fHaveLogFileSpec) | ||
| 105 | { | ||
| 106 | hr = WcaReadStringFromCaData(&pwz, &pwzTemp); | ||
| 107 | ExitOnFailure(hr, "failed to read log file spec name from custom action data: %ls", pwz); | ||
| 108 | hr = ::StringCchCopyW(sfLog.wzName, countof(sfDb.wzName), pwzTemp); | ||
| 109 | ExitOnFailure(hr, "failed to copy log file spec name: %ls", pwzTemp); | ||
| 110 | |||
| 111 | hr = WcaReadStringFromCaData(&pwz, &pwzTemp); | ||
| 112 | ExitOnFailure(hr, "failed to read log file spec filename from custom action data: %ls", pwz); | ||
| 113 | hr = ::StringCchCopyW(sfLog.wzFilename, countof(sfDb.wzFilename), pwzTemp); | ||
| 114 | ExitOnFailure(hr, "failed to copy log file spec filename: %ls", pwzTemp); | ||
| 115 | |||
| 116 | hr = WcaReadStringFromCaData(&pwz, &pwzTemp); | ||
| 117 | ExitOnFailure(hr, "failed to read log file spec size from custom action data: %ls", pwz); | ||
| 118 | hr = ::StringCchCopyW(sfLog.wzSize, countof(sfDb.wzSize), pwzTemp); | ||
| 119 | ExitOnFailure(hr, "failed to copy log file spec size value: %ls", pwzTemp); | ||
| 120 | |||
| 121 | hr = WcaReadStringFromCaData(&pwz, &pwzTemp); | ||
| 122 | ExitOnFailure(hr, "failed to read log file spec max size from custom action data: %ls", pwz); | ||
| 123 | hr = ::StringCchCopyW(sfLog.wzMaxSize, countof(sfDb.wzMaxSize), pwzTemp); | ||
| 124 | ExitOnFailure(hr, "failed to copy log file spec max size: %ls", pwzTemp); | ||
| 125 | |||
| 126 | hr = WcaReadStringFromCaData(&pwz, &pwzTemp); | ||
| 127 | ExitOnFailure(hr, "failed to read log file spec grow from custom action data: %ls", pwz); | ||
| 128 | hr = ::StringCchCopyW(sfLog.wzGrow, countof(sfDb.wzGrow), pwzTemp); | ||
| 129 | ExitOnFailure(hr, "failed to copy log file spec grow value: %ls", pwzTemp); | ||
| 130 | } | ||
| 131 | |||
| 132 | if (iAttributes & SCADB_CONFIRM_OVERWRITE) | ||
| 133 | { | ||
| 134 | // Check if the database already exists | ||
| 135 | hr = SqlDatabaseExists(pwzServer, pwzInstance, pwzDatabase, fIntegratedAuth, pwzUser, pwzPassword, &bstrErrorDescription); | ||
| 136 | MessageExitOnFailure(hr, msierrSQLFailedCreateDatabase, "failed to check if database exists: '%ls', error: %ls", pwzDatabase, NULL == bstrErrorDescription ? L"unknown error" : bstrErrorDescription); | ||
| 137 | |||
| 138 | if (S_OK == hr) // found an existing database, confirm that they don't want to stop before it gets trampled, in no UI case just continue anyways | ||
| 139 | { | ||
| 140 | hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS); | ||
| 141 | if (IDNO == WcaErrorMessage(msierrSQLDatabaseAlreadyExists, hr, MB_YESNO, 1, pwzDatabase)) | ||
| 142 | ExitOnFailure(hr, "failed to initialize"); | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | hr = SqlDatabaseEnsureExists(pwzServer, pwzInstance, pwzDatabase, fIntegratedAuth, pwzUser, pwzPassword, fHaveDbFileSpec ? &sfDb : NULL, fHaveLogFileSpec ? &sfLog : NULL, &bstrErrorDescription); | ||
| 147 | if ((iAttributes & SCADB_CONTINUE_ON_ERROR) && FAILED(hr)) | ||
| 148 | { | ||
| 149 | WcaLog(LOGMSG_STANDARD, "Error 0x%x: failed to create SQL database but continuing, error: %ls, Database: %ls", hr, NULL == bstrErrorDescription ? L"unknown error" : bstrErrorDescription, pwzDatabase); | ||
| 150 | hr = S_OK; | ||
| 151 | } | ||
| 152 | MessageExitOnFailure(hr, msierrSQLFailedCreateDatabase, "failed to create to database: '%ls', error: %ls", pwzDatabase, NULL == bstrErrorDescription ? L"unknown error" : bstrErrorDescription); | ||
| 153 | |||
| 154 | hr = WcaProgressMessage(COST_SQL_CONNECTDB, FALSE); | ||
| 155 | LExit: | ||
| 156 | ReleaseStr(pwzDatabaseKey); | ||
| 157 | ReleaseStr(pwzServer); | ||
| 158 | ReleaseStr(pwzInstance); | ||
| 159 | ReleaseStr(pwzDatabase); | ||
| 160 | ReleaseStr(pwzUser); | ||
| 161 | ReleaseStr(pwzPassword); | ||
| 162 | ReleaseObject(pidbSession); | ||
| 163 | ReleaseBSTR(bstrErrorDescription); | ||
| 164 | |||
| 165 | if (fInitializedCom) | ||
| 166 | { | ||
| 167 | ::CoUninitialize(); | ||
| 168 | } | ||
| 169 | |||
| 170 | if (FAILED(hr)) | ||
| 171 | { | ||
| 172 | er = ERROR_INSTALL_FAILURE; | ||
| 173 | } | ||
| 174 | return WcaFinalize(er); | ||
| 175 | } | ||
| 176 | |||
| 177 | |||
| 178 | /******************************************************************** | ||
| 179 | DropDatabase - CUSTOM ACTION ENTRY POINT for removing databases | ||
| 180 | |||
| 181 | Input: deferred CustomActionData - DbKey\tServer\tInstance\tDatabase\tAttributes\tIntegratedAuth\tUser\tPassword | ||
| 182 | * ****************************************************************/ | ||
| 183 | extern "C" UINT __stdcall DropDatabase(MSIHANDLE hInstall) | ||
| 184 | { | ||
| 185 | //Assert(FALSE); | ||
| 186 | UINT er = ERROR_SUCCESS; | ||
| 187 | HRESULT hr = S_OK; | ||
| 188 | |||
| 189 | LPWSTR pwzData = NULL; | ||
| 190 | IDBCreateSession* pidbSession = NULL; | ||
| 191 | BSTR bstrErrorDescription = NULL; | ||
| 192 | LPWSTR pwz = NULL; | ||
| 193 | LPWSTR pwzDatabaseKey = NULL; | ||
| 194 | LPWSTR pwzServer = NULL; | ||
| 195 | LPWSTR pwzInstance = NULL; | ||
| 196 | LPWSTR pwzDatabase = NULL; | ||
| 197 | long lAttributes; | ||
| 198 | BOOL fIntegratedAuth; | ||
| 199 | LPWSTR pwzUser = NULL; | ||
| 200 | LPWSTR pwzPassword = NULL; | ||
| 201 | BOOL fInitializedCom = TRUE; | ||
| 202 | |||
| 203 | hr = WcaInitialize(hInstall, "DropDatabase"); | ||
| 204 | ExitOnFailure(hr, "failed to initialize"); | ||
| 205 | |||
| 206 | hr = ::CoInitialize(NULL); | ||
| 207 | ExitOnFailure(hr, "failed to intialize COM"); | ||
| 208 | fInitializedCom = TRUE; | ||
| 209 | |||
| 210 | hr = WcaGetProperty( L"CustomActionData", &pwzData); | ||
| 211 | ExitOnFailure(hr, "failed to get CustomActionData"); | ||
| 212 | |||
| 213 | WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); | ||
| 214 | |||
| 215 | pwz = pwzData; | ||
| 216 | hr = WcaReadStringFromCaData(&pwz, &pwzDatabaseKey); | ||
| 217 | ExitOnFailure(hr, "failed to read database key"); | ||
| 218 | hr = WcaReadStringFromCaData(&pwz, &pwzServer); | ||
| 219 | ExitOnFailure(hr, "failed to read server"); | ||
| 220 | hr = WcaReadStringFromCaData(&pwz, &pwzInstance); | ||
| 221 | ExitOnFailure(hr, "failed to read instance"); | ||
| 222 | hr = WcaReadStringFromCaData(&pwz, &pwzDatabase); | ||
| 223 | ExitOnFailure(hr, "failed to read database"); | ||
| 224 | hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int *>(&lAttributes)); | ||
| 225 | ExitOnFailure(hr, "failed to read attributes"); | ||
| 226 | hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int *>(&fIntegratedAuth)); // Integrated Windows Authentication? | ||
| 227 | ExitOnFailure(hr, "failed to read integrated auth flag"); | ||
| 228 | hr = WcaReadStringFromCaData(&pwz, &pwzUser); | ||
| 229 | ExitOnFailure(hr, "failed to read user"); | ||
| 230 | hr = WcaReadStringFromCaData(&pwz, &pwzPassword); | ||
| 231 | ExitOnFailure(hr, "failed to read password"); | ||
| 232 | |||
| 233 | hr = SqlDropDatabase(pwzServer, pwzInstance, pwzDatabase, fIntegratedAuth, pwzUser, pwzPassword, &bstrErrorDescription); | ||
| 234 | if ((lAttributes & SCADB_CONTINUE_ON_ERROR) && FAILED(hr)) | ||
| 235 | { | ||
| 236 | WcaLog(LOGMSG_STANDARD, "Error 0x%x: failed to drop SQL database but continuing, error: %ls, Database: %ls", hr, NULL == bstrErrorDescription ? L"unknown error" : bstrErrorDescription, pwzDatabase); | ||
| 237 | hr = S_OK; | ||
| 238 | } | ||
| 239 | MessageExitOnFailure(hr, msierrSQLFailedDropDatabase, "failed to drop to database: '%ls', error: %ls", pwzDatabase, NULL == bstrErrorDescription ? L"unknown error" : bstrErrorDescription); | ||
| 240 | |||
| 241 | hr = WcaProgressMessage(COST_SQL_CONNECTDB, FALSE); | ||
| 242 | |||
| 243 | LExit: | ||
| 244 | ReleaseStr(pwzDatabaseKey); | ||
| 245 | ReleaseStr(pwzServer); | ||
| 246 | ReleaseStr(pwzInstance); | ||
| 247 | ReleaseStr(pwzDatabase); | ||
| 248 | ReleaseStr(pwzUser); | ||
| 249 | ReleaseStr(pwzPassword); | ||
| 250 | ReleaseStr(pwzData); | ||
| 251 | ReleaseObject(pidbSession); | ||
| 252 | ReleaseBSTR(bstrErrorDescription); | ||
| 253 | |||
| 254 | if (fInitializedCom) | ||
| 255 | { | ||
| 256 | ::CoUninitialize(); | ||
| 257 | } | ||
| 258 | |||
| 259 | if (FAILED(hr)) | ||
| 260 | { | ||
| 261 | er = ERROR_INSTALL_FAILURE; | ||
| 262 | } | ||
| 263 | return WcaFinalize(er); | ||
| 264 | } | ||
| 265 | |||
| 266 | |||
| 267 | /******************************************************************** | ||
| 268 | ExecuteSqlStrings - CUSTOM ACTION ENTRY POINT for running SQL strings | ||
| 269 | |||
| 270 | Input: deferred CustomActionData - DbKey\tServer\tInstance\tDatabase\tAttributes\tIntegratedAuth\tUser\tPassword\tSQLKey1\tSQLString1\tSQLKey2\tSQLString2\tSQLKey3\tSQLString3\t... | ||
| 271 | rollback CustomActionData - same as above | ||
| 272 | * ****************************************************************/ | ||
| 273 | extern "C" UINT __stdcall ExecuteSqlStrings(MSIHANDLE hInstall) | ||
| 274 | { | ||
| 275 | //Assert(FALSE); | ||
| 276 | UINT er = ERROR_SUCCESS; | ||
| 277 | HRESULT hr = S_OK; | ||
| 278 | HRESULT hrDB = S_OK; | ||
| 279 | |||
| 280 | LPWSTR pwzData = NULL; | ||
| 281 | IDBCreateSession* pidbSession = NULL; | ||
| 282 | BSTR bstrErrorDescription = NULL; | ||
| 283 | |||
| 284 | LPWSTR pwz = NULL; | ||
| 285 | LPWSTR pwzDatabaseKey = NULL; | ||
| 286 | LPWSTR pwzServer = NULL; | ||
| 287 | LPWSTR pwzInstance = NULL; | ||
| 288 | LPWSTR pwzDatabase = NULL; | ||
| 289 | int iAttributesDB; | ||
| 290 | int iAttributesSQL; | ||
| 291 | BOOL fIntegratedAuth; | ||
| 292 | LPWSTR pwzUser = NULL; | ||
| 293 | LPWSTR pwzPassword = NULL; | ||
| 294 | LPWSTR pwzSqlKey = NULL; | ||
| 295 | LPWSTR pwzSql = NULL; | ||
| 296 | BOOL fInitializedCom = FALSE; | ||
| 297 | |||
| 298 | hr = WcaInitialize(hInstall, "ExecuteSqlStrings"); | ||
| 299 | ExitOnFailure(hr, "failed to initialize"); | ||
| 300 | |||
| 301 | hr = ::CoInitialize(NULL); | ||
| 302 | ExitOnFailure(hr, "failed to intialize COM"); | ||
| 303 | fInitializedCom = TRUE; | ||
| 304 | |||
| 305 | hr = WcaGetProperty( L"CustomActionData", &pwzData); | ||
| 306 | ExitOnFailure(hr, "failed to get CustomActionData"); | ||
| 307 | |||
| 308 | WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); | ||
| 309 | |||
| 310 | pwz = pwzData; | ||
| 311 | hr = WcaReadStringFromCaData(&pwz, &pwzDatabaseKey); | ||
| 312 | ExitOnFailure(hr, "failed to read database key"); | ||
| 313 | hr = WcaReadStringFromCaData(&pwz, &pwzServer); | ||
| 314 | ExitOnFailure(hr, "failed to read server"); | ||
| 315 | hr = WcaReadStringFromCaData(&pwz, &pwzInstance); | ||
| 316 | ExitOnFailure(hr, "failed to read instance"); | ||
| 317 | hr = WcaReadStringFromCaData(&pwz, &pwzDatabase); | ||
| 318 | ExitOnFailure(hr, "failed to read database"); | ||
| 319 | hr = WcaReadIntegerFromCaData(&pwz, &iAttributesDB); | ||
| 320 | ExitOnFailure(hr, "failed to read attributes"); | ||
| 321 | hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int *>(&fIntegratedAuth)); // Integrated Windows Authentication? | ||
| 322 | ExitOnFailure(hr, "failed to read integrated auth flag"); | ||
| 323 | hr = WcaReadStringFromCaData(&pwz, &pwzUser); | ||
| 324 | ExitOnFailure(hr, "failed to read user"); | ||
| 325 | hr = WcaReadStringFromCaData(&pwz, &pwzPassword); | ||
| 326 | ExitOnFailure(hr, "failed to read password"); | ||
| 327 | |||
| 328 | // Store off the result of the connect, only exit if we don't care if the database connection succeeds | ||
| 329 | // Wait to fail until later to see if we actually have work to do that is not set to continue on error | ||
| 330 | hrDB = SqlConnectDatabase(pwzServer, pwzInstance, pwzDatabase, fIntegratedAuth, pwzUser, pwzPassword, &pidbSession); | ||
| 331 | if ((iAttributesDB & SCADB_CONTINUE_ON_ERROR) && FAILED(hrDB)) | ||
| 332 | { | ||
| 333 | WcaLog(LOGMSG_STANDARD, "Error 0x%x: continuing after failure to connect to database: %ls", hrDB, pwzDatabase); | ||
| 334 | ExitFunction1(hr = S_OK); | ||
| 335 | } | ||
| 336 | |||
| 337 | while (S_OK == hr && S_OK == (hr = WcaReadStringFromCaData(&pwz, &pwzSqlKey))) | ||
| 338 | { | ||
| 339 | hr = WcaReadIntegerFromCaData(&pwz, &iAttributesSQL); | ||
| 340 | ExitOnFailure(hr, "failed to read attributes for SQL string: %ls", pwzSqlKey); | ||
| 341 | |||
| 342 | hr = WcaReadStringFromCaData(&pwz, &pwzSql); | ||
| 343 | ExitOnFailure(hr, "failed to read SQL string for key: %ls", pwzSqlKey); | ||
| 344 | |||
| 345 | // If the Wix4SqlString row is set to continue on error and the DB connection failed, skip attempting to execute | ||
| 346 | if ((iAttributesSQL & SCASQL_CONTINUE_ON_ERROR) && FAILED(hrDB)) | ||
| 347 | { | ||
| 348 | WcaLog(LOGMSG_STANDARD, "Error 0x%x: continuing after failure to connect to database: %ls", hrDB, pwzDatabase); | ||
| 349 | continue; | ||
| 350 | } | ||
| 351 | |||
| 352 | // Now check if the DB connection succeeded | ||
| 353 | MessageExitOnFailure(hr = hrDB, msierrSQLFailedConnectDatabase, "failed to connect to database: '%ls'", pwzDatabase); | ||
| 354 | |||
| 355 | WcaLog(LOGMSG_VERBOSE, "Executing SQL string: %ls", pwzSql); | ||
| 356 | hr = SqlSessionExecuteQuery(pidbSession, pwzSql, NULL, NULL, &bstrErrorDescription); | ||
| 357 | if ((iAttributesSQL & SCASQL_CONTINUE_ON_ERROR) && FAILED(hr)) | ||
| 358 | { | ||
| 359 | WcaLog(LOGMSG_STANDARD, "Error 0x%x: failed to execute SQL string but continuing, error: %ls, SQL key: %ls SQL string: %ls", hr, NULL == bstrErrorDescription ? L"unknown error" : bstrErrorDescription, pwzSqlKey, pwzSql); | ||
| 360 | hr = S_OK; | ||
| 361 | } | ||
| 362 | MessageExitOnFailure(hr, msierrSQLFailedExecString, "failed to execute SQL string, error: %ls, SQL key: %ls SQL string: %ls", NULL == bstrErrorDescription ? L"unknown error" : bstrErrorDescription, pwzSqlKey, pwzSql); | ||
| 363 | |||
| 364 | WcaProgressMessage(COST_SQL_STRING, FALSE); | ||
| 365 | } | ||
| 366 | if (E_NOMOREITEMS == hr) | ||
| 367 | { | ||
| 368 | hr = S_OK; | ||
| 369 | } | ||
| 370 | |||
| 371 | LExit: | ||
| 372 | ReleaseStr(pwzDatabaseKey); | ||
| 373 | ReleaseStr(pwzServer); | ||
| 374 | ReleaseStr(pwzInstance); | ||
| 375 | ReleaseStr(pwzDatabase); | ||
| 376 | ReleaseStr(pwzUser); | ||
| 377 | ReleaseStr(pwzPassword); | ||
| 378 | ReleaseStr(pwzData); | ||
| 379 | |||
| 380 | ReleaseBSTR(bstrErrorDescription); | ||
| 381 | ReleaseObject(pidbSession); | ||
| 382 | |||
| 383 | if (fInitializedCom) | ||
| 384 | { | ||
| 385 | ::CoUninitialize(); | ||
| 386 | } | ||
| 387 | |||
| 388 | if (FAILED(hr)) | ||
| 389 | { | ||
| 390 | er = ERROR_INSTALL_FAILURE; | ||
| 391 | } | ||
| 392 | return WcaFinalize(er); | ||
| 393 | } | ||
diff --git a/src/ext/Sql/ca/scasql.cpp b/src/ext/Sql/ca/scasql.cpp new file mode 100644 index 00000000..b0216950 --- /dev/null +++ b/src/ext/Sql/ca/scasql.cpp | |||
| @@ -0,0 +1,113 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | // prototypes | ||
| 6 | static HRESULT ConfigureSqlData( | ||
| 7 | __in SCA_ACTION saAction | ||
| 8 | ); | ||
| 9 | |||
| 10 | |||
| 11 | /******************************************************************** | ||
| 12 | InstallSqlData - CUSTOM ACTION ENTRY POINT for installing | ||
| 13 | SQL data | ||
| 14 | |||
| 15 | ********************************************************************/ | ||
| 16 | extern "C" UINT __stdcall InstallSqlData( | ||
| 17 | __in MSIHANDLE hInstall | ||
| 18 | ) | ||
| 19 | { | ||
| 20 | HRESULT hr = S_OK; | ||
| 21 | UINT er = ERROR_SUCCESS; | ||
| 22 | |||
| 23 | // initialize | ||
| 24 | hr = WcaInitialize(hInstall, "InstallSqlData"); | ||
| 25 | ExitOnFailure(hr, "Failed to initialize"); | ||
| 26 | |||
| 27 | hr = ConfigureSqlData(SCA_ACTION_INSTALL); | ||
| 28 | |||
| 29 | LExit: | ||
| 30 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 31 | return WcaFinalize(er); | ||
| 32 | } | ||
| 33 | |||
| 34 | |||
| 35 | /******************************************************************** | ||
| 36 | UninstallSqlData - CUSTOM ACTION ENTRY POINT for uninstalling | ||
| 37 | SQL data | ||
| 38 | |||
| 39 | ********************************************************************/ | ||
| 40 | extern "C" UINT __stdcall UninstallSqlData( | ||
| 41 | __in MSIHANDLE hInstall | ||
| 42 | ) | ||
| 43 | { | ||
| 44 | HRESULT hr = S_OK; | ||
| 45 | UINT er = ERROR_SUCCESS; | ||
| 46 | |||
| 47 | // initialize | ||
| 48 | hr = WcaInitialize(hInstall, "UninstallCertificates"); | ||
| 49 | ExitOnFailure(hr, "Failed to initialize"); | ||
| 50 | |||
| 51 | hr = ConfigureSqlData(SCA_ACTION_UNINSTALL); | ||
| 52 | |||
| 53 | LExit: | ||
| 54 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 55 | return WcaFinalize(er); | ||
| 56 | } | ||
| 57 | |||
| 58 | |||
| 59 | static HRESULT ConfigureSqlData( | ||
| 60 | __in SCA_ACTION saAction | ||
| 61 | ) | ||
| 62 | { | ||
| 63 | //AssertSz(FALSE, "debug ConfigureSqlData()"); | ||
| 64 | HRESULT hr = S_OK; | ||
| 65 | |||
| 66 | SCA_DB* psdList = NULL; | ||
| 67 | SCA_SQLSTR* psssList = NULL; | ||
| 68 | |||
| 69 | // check for the prerequsite tables | ||
| 70 | if (S_OK != WcaTableExists(L"Wix4SqlDatabase")) | ||
| 71 | { | ||
| 72 | WcaLog(LOGMSG_VERBOSE, "skipping SQL CustomAction, no Wix4SqlDatabase table"); | ||
| 73 | ExitFunction1(hr = S_FALSE); | ||
| 74 | } | ||
| 75 | |||
| 76 | // read tables | ||
| 77 | hr = ScaDbsRead(&psdList, saAction); | ||
| 78 | ExitOnFailure(hr, "failed to read Wix4SqlDatabase table"); | ||
| 79 | |||
| 80 | hr = ScaSqlStrsRead(&psssList, saAction); | ||
| 81 | ExitOnFailure(hr, "failed to read Wix4SqlString table"); | ||
| 82 | |||
| 83 | hr = ScaSqlStrsReadScripts(&psssList, saAction); | ||
| 84 | ExitOnFailure(hr, "failed to read Wix4SqlScript table"); | ||
| 85 | |||
| 86 | if (SCA_ACTION_UNINSTALL == saAction) | ||
| 87 | { | ||
| 88 | // do uninstall actions (order is important!) | ||
| 89 | hr = ScaSqlStrsUninstall(psdList, psssList); | ||
| 90 | ExitOnFailure(hr, "failed to execute uninstall SQL strings"); | ||
| 91 | |||
| 92 | hr = ScaDbsUninstall(psdList); | ||
| 93 | ExitOnFailure(hr, "failed to uninstall databases"); | ||
| 94 | } | ||
| 95 | else | ||
| 96 | { | ||
| 97 | // do install actions (order is important!) | ||
| 98 | hr = ScaDbsInstall(psdList); | ||
| 99 | ExitOnFailure(hr, "failed to install databases"); | ||
| 100 | |||
| 101 | hr = ScaSqlStrsInstall(psdList, psssList); | ||
| 102 | ExitOnFailure(hr, "failed to execute install SQL strings, length may be too long, try add GO to break up"); | ||
| 103 | } | ||
| 104 | |||
| 105 | LExit: | ||
| 106 | if (psssList) | ||
| 107 | ScaSqlStrsFreeList(psssList); | ||
| 108 | |||
| 109 | if (psdList) | ||
| 110 | ScaDbsFreeList(psdList); | ||
| 111 | |||
| 112 | return hr; | ||
| 113 | } | ||
diff --git a/src/ext/Sql/ca/scasqlstr.cpp b/src/ext/Sql/ca/scasqlstr.cpp new file mode 100644 index 00000000..c3ebd43d --- /dev/null +++ b/src/ext/Sql/ca/scasqlstr.cpp | |||
| @@ -0,0 +1,728 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | // sql queries | ||
| 6 | LPCWSTR vcsSqlStringQuery = L"SELECT `String`, `SqlDb_`, `Component_`,`SQL`,`User_`,`Attributes`,`Sequence` " | ||
| 7 | L"FROM `Wix4SqlString` ORDER BY `SqlDb_`,`Sequence`"; | ||
| 8 | enum eSqlStringQuery { ssqSqlString = 1, ssqSqlDb, ssqComponent, ssqSQL, ssqUser, ssqAttributes, ssqSequence }; | ||
| 9 | |||
| 10 | LPCWSTR vcsSqlScriptQuery = L"SELECT `ScriptBinary_`,`Script`, `SqlDb_`, `Component_`,`User_`,`Attributes`,`Sequence` " | ||
| 11 | L"FROM `Wix4SqlScript` ORDER BY `SqlDb_`,`Sequence`"; | ||
| 12 | enum eSqlScriptQuery { sscrqScriptBinary=1, sscrqSqlScript, sscrqSqlDb, sscrqComponent, sscrqUser, sscrqAttributes, sscrqSequence }; | ||
| 13 | |||
| 14 | LPCWSTR vcsSqlBinaryScriptQuery = L"SELECT `Data` FROM `Binary` WHERE `Name`=?"; | ||
| 15 | enum eSqlBinaryScriptQuery { ssbsqData = 1 }; | ||
| 16 | |||
| 17 | |||
| 18 | // prototypes for private helper functions | ||
| 19 | static HRESULT NewSqlStr( | ||
| 20 | __out SCA_SQLSTR** ppsss | ||
| 21 | ); | ||
| 22 | static SCA_SQLSTR* AddSqlStrToList( | ||
| 23 | __in SCA_SQLSTR* psssList, | ||
| 24 | __in SCA_SQLSTR* psss | ||
| 25 | ); | ||
| 26 | static HRESULT ExecuteStrings( | ||
| 27 | __in SCA_DB* psdList, | ||
| 28 | __in SCA_SQLSTR* psssList, | ||
| 29 | __in BOOL fInstall | ||
| 30 | ); | ||
| 31 | |||
| 32 | HRESULT ScaSqlStrsRead( | ||
| 33 | __inout SCA_SQLSTR** ppsssList, | ||
| 34 | __in SCA_ACTION saAction | ||
| 35 | ) | ||
| 36 | { | ||
| 37 | HRESULT hr = S_OK; | ||
| 38 | UINT er = ERROR_SUCCESS; | ||
| 39 | PMSIHANDLE hView, hRec; | ||
| 40 | PMSIHANDLE hViewUser, hRecUser; | ||
| 41 | |||
| 42 | LPWSTR pwzComponent = NULL; | ||
| 43 | LPWSTR pwzData = NULL; | ||
| 44 | |||
| 45 | SCA_SQLSTR* psss = NULL; | ||
| 46 | |||
| 47 | if (S_OK != WcaTableExists(L"Wix4SqlString") || S_OK != WcaTableExists(L"Wix4SqlDatabase")) | ||
| 48 | { | ||
| 49 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaSqlStrsRead() - Wix4SqlString and/or Wix4SqlDatabase table not present"); | ||
| 50 | ExitFunction1(hr = S_FALSE); | ||
| 51 | } | ||
| 52 | |||
| 53 | // loop through all the sql strings | ||
| 54 | hr = WcaOpenExecuteView(vcsSqlStringQuery, &hView); | ||
| 55 | ExitOnFailure(hr, "Failed to open view on Wix4SqlString table"); | ||
| 56 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 57 | { | ||
| 58 | INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN; | ||
| 59 | INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN; | ||
| 60 | |||
| 61 | hr = WcaGetRecordString(hRec, ssqComponent, &pwzComponent); | ||
| 62 | ExitOnFailure(hr, "Failed to get Component for SQL String."); | ||
| 63 | |||
| 64 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzComponent, &isInstalled, &isAction); | ||
| 65 | hr = HRESULT_FROM_WIN32(er); | ||
| 66 | ExitOnFailure(hr, "Failed to get state for component: %ls", pwzComponent); | ||
| 67 | |||
| 68 | // If we're doing install but the Component is not being installed or we're doing | ||
| 69 | // uninstall but the Component is not being uninstalled, skip it. | ||
| 70 | if ((WcaIsInstalling(isInstalled, isAction) && SCA_ACTION_INSTALL != saAction) || | ||
| 71 | (WcaIsUninstalling(isInstalled, isAction) && SCA_ACTION_UNINSTALL != saAction)) | ||
| 72 | { | ||
| 73 | continue; | ||
| 74 | } | ||
| 75 | |||
| 76 | hr = NewSqlStr(&psss); | ||
| 77 | ExitOnFailure(hr, "failed to allocation new sql string element"); | ||
| 78 | |||
| 79 | psss->isInstalled = isInstalled; | ||
| 80 | psss->isAction = isAction; | ||
| 81 | |||
| 82 | hr = WcaGetRecordString(hRec, ssqSqlString, &pwzData); | ||
| 83 | ExitOnFailure(hr, "Failed to get Wix4SqlString.String"); | ||
| 84 | hr = ::StringCchCopyW(psss->wzKey, countof(psss->wzKey), pwzData); | ||
| 85 | ExitOnFailure(hr, "Failed to copy Wix4SqlString.String: %ls", pwzData); | ||
| 86 | |||
| 87 | // find the database information for this string | ||
| 88 | hr = WcaGetRecordString(hRec, ssqSqlDb, &pwzData); | ||
| 89 | ExitOnFailure(hr, "Failed to get Wix4SqlString.SqlDb_ for SqlString '%ls'", psss->wzKey); | ||
| 90 | hr = ::StringCchCopyW(psss->wzSqlDb, countof(psss->wzSqlDb), pwzData); | ||
| 91 | ExitOnFailure(hr, "Failed to copy Wix4SqlString.SqlDb_: %ls", pwzData); | ||
| 92 | |||
| 93 | hr = WcaGetRecordInteger(hRec, ssqAttributes, &psss->iAttributes); | ||
| 94 | ExitOnFailure(hr, "Failed to get Wix4SqlString.Attributes for SqlString '%ls'", psss->wzKey); | ||
| 95 | |||
| 96 | //get the sequence number for the string (note that this will be sequenced with scripts too) | ||
| 97 | hr = WcaGetRecordInteger(hRec, ssqSequence, &psss->iSequence); | ||
| 98 | ExitOnFailure(hr, "Failed to get Wix4SqlString.Sequence for SqlString '%ls'", psss->wzKey); | ||
| 99 | |||
| 100 | // execute SQL | ||
| 101 | hr = WcaGetRecordFormattedString(hRec, ssqSQL, &pwzData); | ||
| 102 | ExitOnFailure(hr, "Failed to get Wix4SqlString.SQL for SQL string '%ls'", psss->wzKey); | ||
| 103 | |||
| 104 | Assert(!psss->pwzSql); | ||
| 105 | hr = StrAllocString(&psss->pwzSql, pwzData, 0); | ||
| 106 | ExitOnFailure(hr, "Failed to alloc string for SQL string '%ls'", psss->wzKey); | ||
| 107 | |||
| 108 | *ppsssList = AddSqlStrToList(*ppsssList, psss); | ||
| 109 | psss = NULL; // set the sss to NULL so it doesn't get freed below | ||
| 110 | } | ||
| 111 | |||
| 112 | if (E_NOMOREITEMS == hr) | ||
| 113 | { | ||
| 114 | hr = S_OK; | ||
| 115 | } | ||
| 116 | ExitOnFailure(hr, "Failure occured while reading Wix4SqlString table"); | ||
| 117 | |||
| 118 | LExit: | ||
| 119 | // if anything was left over after an error clean it all up | ||
| 120 | if (psss) | ||
| 121 | { | ||
| 122 | ScaSqlStrsFreeList(psss); | ||
| 123 | } | ||
| 124 | |||
| 125 | ReleaseStr(pwzData); | ||
| 126 | ReleaseStr(pwzComponent); | ||
| 127 | |||
| 128 | return hr; | ||
| 129 | } | ||
| 130 | |||
| 131 | |||
| 132 | HRESULT ScaSqlStrsReadScripts( | ||
| 133 | __inout SCA_SQLSTR** ppsssList, | ||
| 134 | __in SCA_ACTION saAction | ||
| 135 | ) | ||
| 136 | { | ||
| 137 | HRESULT hr = S_OK; | ||
| 138 | UINT er = ERROR_SUCCESS; | ||
| 139 | |||
| 140 | PMSIHANDLE hView, hRec; | ||
| 141 | PMSIHANDLE hViewBinary, hRecBinary; | ||
| 142 | PMSIHANDLE hViewUser, hRecUser; | ||
| 143 | |||
| 144 | LPWSTR pwzComponent = NULL; | ||
| 145 | LPWSTR pwzData = NULL; | ||
| 146 | |||
| 147 | BYTE* pbScript = NULL; | ||
| 148 | DWORD cbRead = 0; | ||
| 149 | DWORD cbScript = 0; | ||
| 150 | DWORD cchScript = 0; | ||
| 151 | |||
| 152 | LPWSTR pwzScriptBuffer = NULL; | ||
| 153 | WCHAR* pwzScript = NULL; | ||
| 154 | WCHAR* pwz; | ||
| 155 | DWORD cch = 0; | ||
| 156 | |||
| 157 | SCA_SQLSTR sss; | ||
| 158 | SCA_SQLSTR* psss = NULL; | ||
| 159 | |||
| 160 | if (S_OK != WcaTableExists(L"Wix4SqlScript") || S_OK != WcaTableExists(L"Wix4SqlDatabase") || S_OK != WcaTableExists(L"Binary")) | ||
| 161 | { | ||
| 162 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaSqlStrsReadScripts() - Wix4SqlScript and/or Wix4SqlDatabase table not present"); | ||
| 163 | ExitFunction1(hr = S_FALSE); | ||
| 164 | } | ||
| 165 | |||
| 166 | // open a view on the binary table | ||
| 167 | hr = WcaOpenView(vcsSqlBinaryScriptQuery, &hViewBinary); | ||
| 168 | ExitOnFailure(hr, "Failed to open view on Binary table for SQL scripts"); | ||
| 169 | |||
| 170 | // loop through all the sql scripts | ||
| 171 | hr = WcaOpenExecuteView(vcsSqlScriptQuery, &hView); | ||
| 172 | ExitOnFailure(hr, "Failed to open view on Wix4SqlScript table"); | ||
| 173 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 174 | { | ||
| 175 | INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN; | ||
| 176 | INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN; | ||
| 177 | |||
| 178 | hr = WcaGetRecordString(hRec, sscrqComponent, &pwzComponent); | ||
| 179 | ExitOnFailure(hr, "Failed to get Component for SQL Script."); | ||
| 180 | |||
| 181 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzComponent, &isInstalled, &isAction); | ||
| 182 | hr = HRESULT_FROM_WIN32(er); | ||
| 183 | ExitOnFailure(hr, "Failed to get state for component: %ls", pwzComponent); | ||
| 184 | |||
| 185 | // If we're doing install but the Component is not being installed or we're doing | ||
| 186 | // uninstall but the Component is not being uninstalled, skip it. | ||
| 187 | if ((WcaIsInstalling(isInstalled, isAction) && SCA_ACTION_INSTALL != saAction) || | ||
| 188 | (WcaIsUninstalling(isInstalled, isAction) && SCA_ACTION_UNINSTALL != saAction)) | ||
| 189 | { | ||
| 190 | continue; | ||
| 191 | } | ||
| 192 | |||
| 193 | ::ZeroMemory(&sss, sizeof(sss)); | ||
| 194 | |||
| 195 | sss.isInstalled = isInstalled; | ||
| 196 | sss.isAction = isAction; | ||
| 197 | |||
| 198 | hr = WcaGetRecordString(hRec, sscrqSqlScript, &pwzData); | ||
| 199 | ExitOnFailure(hr, "Failed to get Wix4SqlScript.Script"); | ||
| 200 | hr = ::StringCchCopyW(sss.wzKey, countof(sss.wzKey), pwzData); | ||
| 201 | ExitOnFailure(hr, "Failed to copy Wix4SqlScript.Script: %ls", pwzData); | ||
| 202 | |||
| 203 | // find the database information for this string | ||
| 204 | hr = WcaGetRecordString(hRec, sscrqSqlDb, &pwzData); | ||
| 205 | ExitOnFailure(hr, "Failed to get Wix4SqlScript.SqlDb_ for SqlScript '%ls'", sss.wzKey); | ||
| 206 | hr = ::StringCchCopyW(sss.wzSqlDb, countof(sss.wzSqlDb), pwzData); | ||
| 207 | ExitOnFailure(hr, "Failed to copy Wix4SqlScript.SqlDbb: %ls", pwzData); | ||
| 208 | |||
| 209 | hr = WcaGetRecordInteger(hRec, sscrqAttributes, &sss.iAttributes); | ||
| 210 | ExitOnFailure(hr, "Failed to get Wix4SqlScript.Attributes for SqlScript '%ls'", sss.wzKey); | ||
| 211 | |||
| 212 | hr = WcaGetRecordInteger(hRec, sscrqSequence, &sss.iSequence); | ||
| 213 | ExitOnFailure(hr, "Failed to get Wix4SqlScript.Sequence for SqlScript '%ls'", sss.wzKey); | ||
| 214 | |||
| 215 | // get the sql script out of the binary stream | ||
| 216 | hr = WcaExecuteView(hViewBinary, hRec); | ||
| 217 | ExitOnFailure(hr, "Failed to open Wix4SqlScript.BinaryScript_ for SqlScript '%ls'", sss.wzKey); | ||
| 218 | hr = WcaFetchSingleRecord(hViewBinary, &hRecBinary); | ||
| 219 | ExitOnFailure(hr, "Failed to fetch Wix4SqlScript.BinaryScript_ for SqlScript '%ls'", sss.wzKey); | ||
| 220 | |||
| 221 | // Note: We need to allocate an extra character on the stream to NULL terminate the SQL script. | ||
| 222 | // The WcaGetRecordStream() function won't let us add extra space on the end of the stream | ||
| 223 | // so we'll read the stream "the old fashioned way". | ||
| 224 | //hr = WcaGetRecordStream(hRecBinary, ssbsqData, (BYTE**)&pbScript, &cbScript); | ||
| 225 | //ExitOnFailure(hr, "Failed to read Wix4SqlScript.BinaryScript_ for SqlScript '%ls'", sss.wzKey); | ||
| 226 | er = ::MsiRecordReadStream(hRecBinary, ssbsqData, NULL, &cbRead); | ||
| 227 | hr = HRESULT_FROM_WIN32(er); | ||
| 228 | ExitOnFailure(hr, "failed to get size of stream"); | ||
| 229 | |||
| 230 | cbScript = cbRead + sizeof(WCHAR); // we may have an ANSI SQL script but leave enough to even NULL terminate a WCHAR string | ||
| 231 | hr = WcaAllocStream(&pbScript, cbScript); // this will allocate a fully zeroed out buffer so our string will be NULL terminated | ||
| 232 | ExitOnFailure(hr, "failed to allocate data for stream"); | ||
| 233 | |||
| 234 | er = ::MsiRecordReadStream(hRecBinary, ssbsqData, reinterpret_cast<char*>(pbScript), &cbRead); //read the buffer but leave the space for the NULL terminator | ||
| 235 | hr = HRESULT_FROM_WIN32(er); | ||
| 236 | ExitOnFailure(hr, "failed to read from stream"); | ||
| 237 | |||
| 238 | Assert(cbRead + sizeof(WCHAR) == cbScript); | ||
| 239 | |||
| 240 | // Check for the UNICODE BOM file marker. | ||
| 241 | if ((0xFF == *pbScript) && (0xFE == *(pbScript + 1))) | ||
| 242 | { | ||
| 243 | // Copy the UNICODE string after the BOM marker (subtract one because we'll skip the BOM marker). | ||
| 244 | cchScript = (cbScript / sizeof(WCHAR)) - 1; | ||
| 245 | |||
| 246 | hr = StrAllocString(&pwzScriptBuffer, reinterpret_cast<LPWSTR>(pbScript) + 1, 0); | ||
| 247 | ExitOnFailure(hr, "Failed to allocate WCHAR string of size '%d'", cchScript); | ||
| 248 | } | ||
| 249 | else | ||
| 250 | { | ||
| 251 | // We have an ANSI string so convert it to UNICODE. | ||
| 252 | cchScript = cbScript; | ||
| 253 | |||
| 254 | hr = StrAllocStringAnsi(&pwzScriptBuffer, reinterpret_cast<LPCSTR>(pbScript), 0, CP_ACP); | ||
| 255 | ExitOnFailure(hr, "Failed to allocate WCHAR string of size '%d'", cchScript); | ||
| 256 | } | ||
| 257 | |||
| 258 | // Free the byte buffer since it has been converted to a new UNICODE string, one way or another. | ||
| 259 | if (pbScript) | ||
| 260 | { | ||
| 261 | WcaFreeStream(pbScript); | ||
| 262 | pbScript = NULL; | ||
| 263 | } | ||
| 264 | |||
| 265 | // Process the SQL script stripping out unnecessary stuff (like comments) and looking for "GO" statements. | ||
| 266 | pwzScript = pwzScriptBuffer; | ||
| 267 | while (cchScript && pwzScript && *pwzScript) | ||
| 268 | { | ||
| 269 | // strip off leading whitespace | ||
| 270 | while (cchScript && *pwzScript && iswspace(*pwzScript)) | ||
| 271 | { | ||
| 272 | ++pwzScript; | ||
| 273 | --cchScript; | ||
| 274 | } | ||
| 275 | |||
| 276 | Assert(0 <= cchScript); | ||
| 277 | |||
| 278 | // if there is a SQL comment remove it | ||
| 279 | while (cchScript && L'/' == *pwzScript && L'*' == *(pwzScript + 1)) | ||
| 280 | { | ||
| 281 | // go until end of comment | ||
| 282 | while (cchScript && *pwzScript && *(pwzScript + 1) && !(L'*' == *pwzScript && L'/' == *(pwzScript + 1))) | ||
| 283 | { | ||
| 284 | ++pwzScript; | ||
| 285 | --cchScript; | ||
| 286 | } | ||
| 287 | |||
| 288 | Assert(2 <= cchScript); | ||
| 289 | |||
| 290 | if (2 <= cchScript) | ||
| 291 | { | ||
| 292 | // to account for */ at end | ||
| 293 | pwzScript+=2; | ||
| 294 | cchScript-=2; | ||
| 295 | } | ||
| 296 | |||
| 297 | Assert(0 <= cchScript); | ||
| 298 | |||
| 299 | // strip off any new leading whitespace | ||
| 300 | while (cchScript && *pwzScript && iswspace(*pwzScript)) | ||
| 301 | { | ||
| 302 | ++pwzScript; | ||
| 303 | --cchScript; | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | while (cchScript && L'-' == *pwzScript && L'-' == *(pwzScript + 1)) | ||
| 308 | { | ||
| 309 | // go past the new line character | ||
| 310 | while (cchScript && *pwzScript && L'\n' != *pwzScript) | ||
| 311 | { | ||
| 312 | ++pwzScript; | ||
| 313 | --cchScript; | ||
| 314 | } | ||
| 315 | |||
| 316 | Assert(0 <= cchScript); | ||
| 317 | |||
| 318 | if (cchScript && L'\n' == *pwzScript) | ||
| 319 | { | ||
| 320 | ++pwzScript; | ||
| 321 | --cchScript; | ||
| 322 | } | ||
| 323 | |||
| 324 | Assert(0 <= cchScript); | ||
| 325 | |||
| 326 | // strip off any new leading whitespace | ||
| 327 | while (cchScript && *pwzScript && iswspace(*pwzScript)) | ||
| 328 | { | ||
| 329 | ++pwzScript; | ||
| 330 | --cchScript; | ||
| 331 | } | ||
| 332 | } | ||
| 333 | |||
| 334 | Assert(0 <= cchScript); | ||
| 335 | |||
| 336 | // try to isolate a "GO" keyword and count the characters in the SQL string | ||
| 337 | pwz = pwzScript; | ||
| 338 | cch = 0; | ||
| 339 | while (cchScript && *pwz) | ||
| 340 | { | ||
| 341 | //skip past comment lines that might have "go" in them | ||
| 342 | //note that these comments are "in the middle" of our function, | ||
| 343 | //or possibly at the end of a line | ||
| 344 | if (cchScript && L'-' == *pwz && L'-' == *(pwz + 1)) | ||
| 345 | { | ||
| 346 | // skip past chars until the new line character | ||
| 347 | while (cchScript && *pwz && (L'\n' != *pwz)) | ||
| 348 | { | ||
| 349 | ++pwz; | ||
| 350 | ++cch; | ||
| 351 | --cchScript; | ||
| 352 | } | ||
| 353 | } | ||
| 354 | |||
| 355 | //skip past comment lines of form /* to */ that might have "go" in them | ||
| 356 | //note that these comments are "in the middle" of our function, | ||
| 357 | //or possibly at the end of a line | ||
| 358 | if (cchScript && L'/' == *pwz && L'*' == *(pwz + 1)) | ||
| 359 | { | ||
| 360 | // skip past chars until the new line character | ||
| 361 | while (cchScript && *pwz && *(pwz + 1) && !((L'*' == *pwz) && (L'/' == *(pwz + 1)))) | ||
| 362 | { | ||
| 363 | ++pwz; | ||
| 364 | ++cch; | ||
| 365 | --cchScript; | ||
| 366 | } | ||
| 367 | |||
| 368 | if (2 <= cchScript) | ||
| 369 | { | ||
| 370 | // to account for */ at end | ||
| 371 | pwz+=2; | ||
| 372 | cch+=2; | ||
| 373 | cchScript-=2; | ||
| 374 | } | ||
| 375 | } | ||
| 376 | |||
| 377 | // Skip past strings that may be part of the SQL statement that might have a "go" in them | ||
| 378 | if ( cchScript && L'\'' == *pwz ) | ||
| 379 | { | ||
| 380 | ++pwz; | ||
| 381 | ++cch; | ||
| 382 | --cchScript; | ||
| 383 | |||
| 384 | // Skip past chars until the end of the string | ||
| 385 | while ( cchScript && *pwz && !(L'\'' == *pwz) ) | ||
| 386 | { | ||
| 387 | ++pwz; | ||
| 388 | ++cch; | ||
| 389 | --cchScript; | ||
| 390 | } | ||
| 391 | } | ||
| 392 | |||
| 393 | // Skip past strings that may be part of the SQL statement that might have a "go" in them | ||
| 394 | if ( cchScript && L'\"' == *pwz ) | ||
| 395 | { | ||
| 396 | ++pwz; | ||
| 397 | ++cch; | ||
| 398 | --cchScript; | ||
| 399 | |||
| 400 | // Skip past chars until the end of the string | ||
| 401 | while ( cchScript && *pwz && !(L'\"' == *pwz) ) | ||
| 402 | { | ||
| 403 | ++pwz; | ||
| 404 | ++cch; | ||
| 405 | --cchScript; | ||
| 406 | } | ||
| 407 | } | ||
| 408 | |||
| 409 | // if "GO" is isolated | ||
| 410 | if ((pwzScript == pwz || iswspace(*(pwz - 1))) && | ||
| 411 | (L'G' == *pwz || L'g' == *pwz) && | ||
| 412 | (L'O' == *(pwz + 1) || L'o' == *(pwz + 1)) && | ||
| 413 | (0 == *(pwz + 2) || iswspace(*(pwz + 2)))) | ||
| 414 | { | ||
| 415 | *pwz = 0; // null terminate the SQL string on the "G" | ||
| 416 | pwz += 2; | ||
| 417 | cchScript -= 2; | ||
| 418 | break; // found "GO" now add SQL string to list | ||
| 419 | } | ||
| 420 | |||
| 421 | ++pwz; | ||
| 422 | ++cch; | ||
| 423 | --cchScript; | ||
| 424 | } | ||
| 425 | |||
| 426 | Assert(0 <= cchScript); | ||
| 427 | |||
| 428 | if (0 < cch) //don't process if there's nothing to process | ||
| 429 | { | ||
| 430 | // replace tabs with spaces | ||
| 431 | for (LPWSTR pwzTab = wcsstr(pwzScript, L"\t"); pwzTab; pwzTab = wcsstr(pwzTab, L"\t")) | ||
| 432 | *pwzTab = ' '; | ||
| 433 | |||
| 434 | // strip off whitespace at the end of the script string | ||
| 435 | for (LPWSTR pwzErase = pwzScript + cch - 1; pwzScript < pwzErase && iswspace(*pwzErase); pwzErase--) | ||
| 436 | { | ||
| 437 | *(pwzErase) = 0; | ||
| 438 | cch--; | ||
| 439 | } | ||
| 440 | } | ||
| 441 | |||
| 442 | if (0 < cch) | ||
| 443 | { | ||
| 444 | hr = NewSqlStr(&psss); | ||
| 445 | ExitOnFailure(hr, "failed to allocate new sql string element"); | ||
| 446 | |||
| 447 | // copy everything over | ||
| 448 | hr = ::StringCchCopyW(psss->wzKey, countof(psss->wzKey), sss.wzKey); | ||
| 449 | ExitOnFailure(hr, "Failed to copy key string to sqlstr object"); | ||
| 450 | hr = ::StringCchCopyW(psss->wzSqlDb, countof(psss->wzSqlDb), sss.wzSqlDb); | ||
| 451 | ExitOnFailure(hr, "Failed to copy DB string to sqlstr object"); | ||
| 452 | hr = ::StringCchCopyW(psss->wzComponent, countof(psss->wzComponent), sss.wzComponent); | ||
| 453 | ExitOnFailure(hr, "Failed to copy component string to sqlstr object"); | ||
| 454 | psss->isInstalled = sss.isInstalled; | ||
| 455 | psss->isAction = sss.isAction; | ||
| 456 | psss->iAttributes = sss.iAttributes; | ||
| 457 | psss->iSequence = sss.iSequence; | ||
| 458 | |||
| 459 | // cchRequired includes the NULL terminating char | ||
| 460 | hr = StrAllocString(&psss->pwzSql, pwzScript, 0); | ||
| 461 | ExitOnFailure(hr, "Failed to allocate string for SQL script: '%ls'", psss->wzKey); | ||
| 462 | |||
| 463 | *ppsssList = AddSqlStrToList(*ppsssList, psss); | ||
| 464 | psss = NULL; // set the db NULL so it doesn't accidentally get freed below | ||
| 465 | } | ||
| 466 | |||
| 467 | pwzScript = pwz; | ||
| 468 | } | ||
| 469 | } | ||
| 470 | |||
| 471 | if (E_NOMOREITEMS == hr) | ||
| 472 | { | ||
| 473 | hr = S_OK; | ||
| 474 | } | ||
| 475 | ExitOnFailure(hr, "Failure occured while reading Wix4SqlScript table"); | ||
| 476 | |||
| 477 | LExit: | ||
| 478 | // if anything was left over after an error clean it all up | ||
| 479 | if (psss) | ||
| 480 | { | ||
| 481 | ScaSqlStrsFreeList(psss); | ||
| 482 | } | ||
| 483 | |||
| 484 | if (pbScript) | ||
| 485 | { | ||
| 486 | WcaFreeStream(pbScript); | ||
| 487 | } | ||
| 488 | |||
| 489 | ReleaseStr(pwzScriptBuffer); | ||
| 490 | ReleaseStr(pwzData); | ||
| 491 | ReleaseStr(pwzComponent); | ||
| 492 | |||
| 493 | return hr; | ||
| 494 | } | ||
| 495 | |||
| 496 | |||
| 497 | HRESULT ScaSqlStrsInstall( | ||
| 498 | __in SCA_DB* psdList, | ||
| 499 | __in SCA_SQLSTR* psssList | ||
| 500 | ) | ||
| 501 | { | ||
| 502 | HRESULT hr = ExecuteStrings(psdList, psssList, TRUE); | ||
| 503 | |||
| 504 | return hr; | ||
| 505 | } | ||
| 506 | |||
| 507 | |||
| 508 | HRESULT ScaSqlStrsUninstall( | ||
| 509 | __in SCA_DB* psdList, | ||
| 510 | __in SCA_SQLSTR* psssList | ||
| 511 | ) | ||
| 512 | { | ||
| 513 | HRESULT hr = ExecuteStrings(psdList, psssList, FALSE); | ||
| 514 | |||
| 515 | return hr; | ||
| 516 | } | ||
| 517 | |||
| 518 | |||
| 519 | void ScaSqlStrsFreeList( | ||
| 520 | __in SCA_SQLSTR* psssList | ||
| 521 | ) | ||
| 522 | { | ||
| 523 | SCA_SQLSTR* psssDelete = psssList; | ||
| 524 | while (psssList) | ||
| 525 | { | ||
| 526 | psssDelete = psssList; | ||
| 527 | psssList = psssList->psssNext; | ||
| 528 | |||
| 529 | if (psssDelete->pwzSql) | ||
| 530 | { | ||
| 531 | ReleaseStr(psssDelete->pwzSql); | ||
| 532 | } | ||
| 533 | |||
| 534 | MemFree(psssDelete); | ||
| 535 | } | ||
| 536 | } | ||
| 537 | |||
| 538 | |||
| 539 | // private helper functions | ||
| 540 | |||
| 541 | static HRESULT NewSqlStr( | ||
| 542 | __out SCA_SQLSTR** ppsss | ||
| 543 | ) | ||
| 544 | { | ||
| 545 | HRESULT hr = S_OK; | ||
| 546 | SCA_SQLSTR* psss = static_cast<SCA_SQLSTR*>(MemAlloc(sizeof(SCA_SQLSTR), TRUE)); | ||
| 547 | ExitOnNull(psss, hr, E_OUTOFMEMORY, "failed to allocate memory for new sql string element"); | ||
| 548 | |||
| 549 | *ppsss = psss; | ||
| 550 | |||
| 551 | LExit: | ||
| 552 | return hr; | ||
| 553 | } | ||
| 554 | |||
| 555 | |||
| 556 | static SCA_SQLSTR* AddSqlStrToList( | ||
| 557 | __in SCA_SQLSTR* psssList, | ||
| 558 | __in SCA_SQLSTR* psss | ||
| 559 | ) | ||
| 560 | { | ||
| 561 | Assert(psss); //just checking | ||
| 562 | |||
| 563 | //make certain we have a valid sequence number; note that negatives are technically valid | ||
| 564 | if (MSI_NULL_INTEGER == psss->iSequence) | ||
| 565 | { | ||
| 566 | psss->iSequence = 0; | ||
| 567 | } | ||
| 568 | |||
| 569 | if (psssList) | ||
| 570 | { | ||
| 571 | //list already exists, so insert psss into the list in Sequence order | ||
| 572 | |||
| 573 | //see if we need to change the head, otherwise figure out where in the order it fits | ||
| 574 | if (psss->iSequence < psssList->iSequence) | ||
| 575 | { | ||
| 576 | psss->psssNext = psssList; | ||
| 577 | psssList = psss; | ||
| 578 | } | ||
| 579 | else | ||
| 580 | { | ||
| 581 | SCA_SQLSTR* psssT = psssList; | ||
| 582 | //note that if Sequence numbers are duplicated, as in the case of a sqlscript, | ||
| 583 | //we need to insert them "at the end" of the group so the sqlfile stays in order | ||
| 584 | while (psssT->psssNext && (psssT->psssNext->iSequence <= psss->iSequence)) | ||
| 585 | { | ||
| 586 | psssT = psssT->psssNext; | ||
| 587 | } | ||
| 588 | |||
| 589 | //insert our new psss AFTER psssT | ||
| 590 | psss->psssNext = psssT->psssNext; | ||
| 591 | psssT->psssNext = psss; | ||
| 592 | } | ||
| 593 | } | ||
| 594 | else | ||
| 595 | { | ||
| 596 | psssList = psss; | ||
| 597 | } | ||
| 598 | |||
| 599 | return psssList; | ||
| 600 | } | ||
| 601 | |||
| 602 | |||
| 603 | static HRESULT ExecuteStrings( | ||
| 604 | __in SCA_DB* psdList, | ||
| 605 | __in SCA_SQLSTR* psssList, | ||
| 606 | __in BOOL fInstall | ||
| 607 | ) | ||
| 608 | { | ||
| 609 | HRESULT hr = S_FALSE; // assume nothing will be done | ||
| 610 | |||
| 611 | int iRollback = -1; | ||
| 612 | int iOldRollback = iRollback; | ||
| 613 | |||
| 614 | LPCWSTR wzOldDb = NULL; | ||
| 615 | UINT uiCost = 0; | ||
| 616 | WCHAR* pwzCustomActionData = NULL; | ||
| 617 | WCHAR wzNumber[64]; | ||
| 618 | |||
| 619 | // loop through all sql strings | ||
| 620 | for (SCA_SQLSTR* psss = psssList; psss; psss = psss->psssNext) | ||
| 621 | { | ||
| 622 | // if installing this component | ||
| 623 | if ((fInstall && (psss->iAttributes & SCASQL_EXECUTE_ON_INSTALL) && WcaIsInstalling(psss->isInstalled, psss->isAction) && !WcaIsReInstalling(psss->isInstalled, psss->isAction)) || | ||
| 624 | (fInstall && (psss->iAttributes & SCASQL_EXECUTE_ON_REINSTALL) && WcaIsReInstalling(psss->isInstalled, psss->isAction)) || | ||
| 625 | (!fInstall && (psss->iAttributes & SCASQL_EXECUTE_ON_UNINSTALL) && WcaIsUninstalling(psss->isInstalled, psss->isAction))) | ||
| 626 | { | ||
| 627 | // determine if this is a rollback scheduling or normal deferred scheduling | ||
| 628 | if (psss->iAttributes & SCASQL_ROLLBACK) | ||
| 629 | { | ||
| 630 | iRollback = 1; | ||
| 631 | } | ||
| 632 | else | ||
| 633 | { | ||
| 634 | iRollback = 0; | ||
| 635 | } | ||
| 636 | |||
| 637 | // if we need to create a connection to a new server\database | ||
| 638 | if (!wzOldDb || 0 != lstrcmpW(wzOldDb, psss->wzSqlDb) || iOldRollback != iRollback) | ||
| 639 | { | ||
| 640 | const SCA_DB* psd = ScaDbsFindDatabase(psss->wzSqlDb, psdList); | ||
| 641 | if (!psd) | ||
| 642 | { | ||
| 643 | ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "failed to find data for Database: %ls", psss->wzSqlDb); | ||
| 644 | } | ||
| 645 | |||
| 646 | if (-1 == iOldRollback) | ||
| 647 | { | ||
| 648 | iOldRollback = iRollback; | ||
| 649 | } | ||
| 650 | Assert(0 == iOldRollback || 1 == iOldRollback); | ||
| 651 | |||
| 652 | // if there was custom action data before, schedule the action to write it | ||
| 653 | if (pwzCustomActionData && *pwzCustomActionData) | ||
| 654 | { | ||
| 655 | Assert(pwzCustomActionData && *pwzCustomActionData && uiCost); | ||
| 656 | |||
| 657 | hr = WcaDoDeferredAction(1 == iOldRollback ? CUSTOM_ACTION_DECORATION(L"RollbackExecuteSqlStrings") : CUSTOM_ACTION_DECORATION(L"ExecuteSqlStrings"), pwzCustomActionData, uiCost); | ||
| 658 | ExitOnFailure(hr, "failed to schedule ExecuteSqlStrings action, rollback: %d", iOldRollback); | ||
| 659 | iOldRollback = iRollback; | ||
| 660 | |||
| 661 | *pwzCustomActionData = L'\0'; | ||
| 662 | uiCost = 0; | ||
| 663 | } | ||
| 664 | |||
| 665 | Assert(!pwzCustomActionData || (pwzCustomActionData && 0 == *pwzCustomActionData) && 0 == uiCost); | ||
| 666 | |||
| 667 | hr = WcaWriteStringToCaData(psd->wzKey, &pwzCustomActionData); | ||
| 668 | ExitOnFailure(hr, "Failed to add SQL Server Database String to CustomActionData for Database String: %ls", psd->wzKey); | ||
| 669 | |||
| 670 | hr = WcaWriteStringToCaData(psd->wzServer, &pwzCustomActionData); | ||
| 671 | ExitOnFailure(hr, "Failed to add SQL Server to CustomActionData for Database String: %ls", psd->wzKey); | ||
| 672 | |||
| 673 | hr = WcaWriteStringToCaData(psd->wzInstance, &pwzCustomActionData); | ||
| 674 | ExitOnFailure(hr, "Failed to add SQL Instance to CustomActionData for Database String: %ls", psd->wzKey); | ||
| 675 | |||
| 676 | hr = WcaWriteStringToCaData(psd->wzDatabase, &pwzCustomActionData); | ||
| 677 | ExitOnFailure(hr, "Failed to add SQL Database to CustomActionData for Database String: %ls", psd->wzKey); | ||
| 678 | |||
| 679 | hr = ::StringCchPrintfW(wzNumber, countof(wzNumber), L"%d", psd->iAttributes); | ||
| 680 | ExitOnFailure(hr, "Failed to format attributes integer value to string"); | ||
| 681 | hr = WcaWriteStringToCaData(wzNumber, &pwzCustomActionData); | ||
| 682 | ExitOnFailure(hr, "Failed to add SQL Attributes to CustomActionData for Database String: %ls", psd->wzKey); | ||
| 683 | |||
| 684 | hr = ::StringCchPrintfW(wzNumber, countof(wzNumber), L"%d", psd->fUseIntegratedAuth); | ||
| 685 | ExitOnFailure(hr, "Failed to format UseIntegratedAuth integer value to string"); | ||
| 686 | hr = WcaWriteStringToCaData(wzNumber, &pwzCustomActionData); | ||
| 687 | ExitOnFailure(hr, "Failed to add SQL IntegratedAuth flag to CustomActionData for Database String: %ls", psd->wzKey); | ||
| 688 | |||
| 689 | hr = WcaWriteStringToCaData(psd->scau.wzName, &pwzCustomActionData); | ||
| 690 | ExitOnFailure(hr, "Failed to add SQL UserName to CustomActionData for Database String: %ls", psd->wzKey); | ||
| 691 | |||
| 692 | hr = WcaWriteStringToCaData(psd->scau.wzPassword, &pwzCustomActionData); | ||
| 693 | ExitOnFailure(hr, "Failed to add SQL Password to CustomActionData for Database String: %ls", psd->wzKey); | ||
| 694 | |||
| 695 | uiCost += COST_SQL_CONNECTDB; | ||
| 696 | |||
| 697 | wzOldDb = psss->wzSqlDb; | ||
| 698 | } | ||
| 699 | |||
| 700 | WcaLog(LOGMSG_VERBOSE, "Scheduling SQL string: %ls", psss->pwzSql); | ||
| 701 | |||
| 702 | hr = WcaWriteStringToCaData(psss->wzKey, &pwzCustomActionData); | ||
| 703 | ExitOnFailure(hr, "Failed to add SQL Key to CustomActionData for SQL string: %ls", psss->wzKey); | ||
| 704 | |||
| 705 | hr = WcaWriteIntegerToCaData(psss->iAttributes, &pwzCustomActionData); | ||
| 706 | ExitOnFailure(hr, "failed to add attributes to CustomActionData for SQL string: %ls", psss->wzKey); | ||
| 707 | |||
| 708 | hr = WcaWriteStringToCaData(psss->pwzSql, &pwzCustomActionData); | ||
| 709 | ExitOnFailure(hr, "Failed to to add SQL Query to CustomActionData for SQL string: %ls", psss->wzKey); | ||
| 710 | uiCost += COST_SQL_STRING; | ||
| 711 | } | ||
| 712 | } | ||
| 713 | |||
| 714 | if (pwzCustomActionData && *pwzCustomActionData) | ||
| 715 | { | ||
| 716 | Assert(pwzCustomActionData && *pwzCustomActionData && uiCost); | ||
| 717 | hr = WcaDoDeferredAction(1 == iRollback ? CUSTOM_ACTION_DECORATION(L"RollbackExecuteSqlStrings") : CUSTOM_ACTION_DECORATION(L"ExecuteSqlStrings"), pwzCustomActionData, uiCost); | ||
| 718 | ExitOnFailure(hr, "Failed to schedule ExecuteSqlStrings action"); | ||
| 719 | |||
| 720 | *pwzCustomActionData = L'\0'; | ||
| 721 | uiCost = 0; | ||
| 722 | } | ||
| 723 | |||
| 724 | LExit: | ||
| 725 | ReleaseStr(pwzCustomActionData); | ||
| 726 | |||
| 727 | return hr; | ||
| 728 | } | ||
diff --git a/src/ext/Sql/ca/scasqlstr.h b/src/ext/Sql/ca/scasqlstr.h new file mode 100644 index 00000000..72c1d770 --- /dev/null +++ b/src/ext/Sql/ca/scasqlstr.h | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #include "scadb.h" | ||
| 6 | |||
| 7 | struct SCA_SQLSTR | ||
| 8 | { | ||
| 9 | // darwin information | ||
| 10 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 11 | WCHAR wzComponent[MAX_DARWIN_KEY + 1]; | ||
| 12 | INSTALLSTATE isInstalled, isAction; | ||
| 13 | |||
| 14 | WCHAR wzSqlDb[MAX_DARWIN_COLUMN + 1]; | ||
| 15 | |||
| 16 | BOOL fHasUser; | ||
| 17 | SCA_USER scau; | ||
| 18 | |||
| 19 | LPWSTR pwzSql; | ||
| 20 | int iAttributes; | ||
| 21 | int iSequence; //used to sequence Wix4SqlString and Wix4SqlScript tables together | ||
| 22 | |||
| 23 | SCA_SQLSTR* psssNext; | ||
| 24 | }; | ||
| 25 | |||
| 26 | |||
| 27 | // prototypes | ||
| 28 | HRESULT ScaSqlStrsRead( | ||
| 29 | __inout SCA_SQLSTR** ppsssList, | ||
| 30 | __in SCA_ACTION saAction | ||
| 31 | ); | ||
| 32 | |||
| 33 | HRESULT ScaSqlStrsReadScripts( | ||
| 34 | __inout SCA_SQLSTR** ppsssList, | ||
| 35 | __in SCA_ACTION saAction | ||
| 36 | ); | ||
| 37 | |||
| 38 | HRESULT ScaSqlStrsInstall( | ||
| 39 | __in SCA_DB* psdList, | ||
| 40 | __in SCA_SQLSTR* psssList | ||
| 41 | ); | ||
| 42 | |||
| 43 | HRESULT ScaSqlStrsUninstall( | ||
| 44 | __in SCA_DB* psdList, | ||
| 45 | __in SCA_SQLSTR* psssList | ||
| 46 | ); | ||
| 47 | |||
| 48 | void ScaSqlStrsFreeList( | ||
| 49 | __in SCA_SQLSTR* psssList | ||
| 50 | ); | ||
| 51 | |||
diff --git a/src/ext/Sql/ca/scauser.cpp b/src/ext/Sql/ca/scauser.cpp new file mode 100644 index 00000000..4d74e4d4 --- /dev/null +++ b/src/ext/Sql/ca/scauser.cpp | |||
| @@ -0,0 +1,82 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | LPCWSTR vcsUserQuery = L"SELECT `User`, `Component_`, `Name`, `Domain`, `Password` FROM `User` WHERE `User`=?"; | ||
| 6 | enum eUserQuery { vuqUser = 1, vuqComponent, vuqName, vuqDomain, vuqPassword }; | ||
| 7 | |||
| 8 | |||
| 9 | HRESULT __stdcall ScaGetUser( | ||
| 10 | __in LPCWSTR wzUser, | ||
| 11 | __out SCA_USER* pscau | ||
| 12 | ) | ||
| 13 | { | ||
| 14 | if (!wzUser || !pscau) | ||
| 15 | { | ||
| 16 | return E_INVALIDARG; | ||
| 17 | } | ||
| 18 | |||
| 19 | HRESULT hr = S_OK; | ||
| 20 | PMSIHANDLE hView, hRec; | ||
| 21 | |||
| 22 | LPWSTR pwzData = NULL; | ||
| 23 | |||
| 24 | // clear struct and bail right away if no user key was passed to search for | ||
| 25 | ::ZeroMemory(pscau, sizeof(*pscau)); | ||
| 26 | if (!*wzUser) | ||
| 27 | { | ||
| 28 | ExitFunction1(hr = S_OK); | ||
| 29 | } | ||
| 30 | |||
| 31 | hRec = ::MsiCreateRecord(1); | ||
| 32 | hr = WcaSetRecordString(hRec, 1, wzUser); | ||
| 33 | ExitOnFailure(hr, "Failed to look up User"); | ||
| 34 | |||
| 35 | hr = WcaOpenView(vcsUserQuery, &hView); | ||
| 36 | ExitOnFailure(hr, "Failed to open view on User table"); | ||
| 37 | hr = WcaExecuteView(hView, hRec); | ||
| 38 | ExitOnFailure(hr, "Failed to execute view on User table"); | ||
| 39 | |||
| 40 | hr = WcaFetchSingleRecord(hView, &hRec); | ||
| 41 | if (S_OK == hr) | ||
| 42 | { | ||
| 43 | hr = WcaGetRecordString(hRec, vuqUser, &pwzData); | ||
| 44 | ExitOnFailure(hr, "Failed to get User.User"); | ||
| 45 | hr = ::StringCchCopyW(pscau->wzKey, countof(pscau->wzKey), pwzData); | ||
| 46 | ExitOnFailure(hr, "Failed to copy key string to user object"); | ||
| 47 | |||
| 48 | hr = WcaGetRecordString(hRec, vuqComponent, &pwzData); | ||
| 49 | ExitOnFailure(hr, "Failed to get User.Component_"); | ||
| 50 | hr = ::StringCchCopyW(pscau->wzComponent, countof(pscau->wzComponent), pwzData); | ||
| 51 | ExitOnFailure(hr, "Failed to copy component string to user object"); | ||
| 52 | |||
| 53 | hr = WcaGetRecordFormattedString(hRec, vuqName, &pwzData); | ||
| 54 | ExitOnFailure(hr, "Failed to get User.Name"); | ||
| 55 | hr = ::StringCchCopyW(pscau->wzName, countof(pscau->wzName), pwzData); | ||
| 56 | ExitOnFailure(hr, "Failed to copy name string to user object"); | ||
| 57 | |||
| 58 | hr = WcaGetRecordFormattedString(hRec, vuqDomain, &pwzData); | ||
| 59 | ExitOnFailure(hr, "Failed to get User.Domain"); | ||
| 60 | hr = ::StringCchCopyW(pscau->wzDomain, countof(pscau->wzDomain), pwzData); | ||
| 61 | ExitOnFailure(hr, "Failed to copy domain string to user object"); | ||
| 62 | |||
| 63 | hr = WcaGetRecordFormattedString(hRec, vuqPassword, &pwzData); | ||
| 64 | ExitOnFailure(hr, "Failed to get User.Password"); | ||
| 65 | hr = ::StringCchCopyW(pscau->wzPassword, countof(pscau->wzPassword), pwzData); | ||
| 66 | ExitOnFailure(hr, "Failed to copy password string to user object"); | ||
| 67 | } | ||
| 68 | else if (E_NOMOREITEMS == hr) | ||
| 69 | { | ||
| 70 | WcaLog(LOGMSG_STANDARD, "Error: Cannot locate User.User='%ls'", wzUser); | ||
| 71 | hr = E_FAIL; | ||
| 72 | } | ||
| 73 | else | ||
| 74 | { | ||
| 75 | ExitOnFailure(hr, "Error or found multiple matching User rows"); | ||
| 76 | } | ||
| 77 | |||
| 78 | LExit: | ||
| 79 | ReleaseStr(pwzData); | ||
| 80 | |||
| 81 | return hr; | ||
| 82 | } | ||
diff --git a/src/ext/Sql/ca/scauser.h b/src/ext/Sql/ca/scauser.h new file mode 100644 index 00000000..20e561f2 --- /dev/null +++ b/src/ext/Sql/ca/scauser.h | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | |||
| 6 | // structs | ||
| 7 | struct SCA_GROUP | ||
| 8 | { | ||
| 9 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 10 | WCHAR wzComponent[MAX_DARWIN_KEY + 1]; | ||
| 11 | |||
| 12 | WCHAR wzDomain[MAX_DARWIN_COLUMN + 1]; | ||
| 13 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
| 14 | |||
| 15 | SCA_GROUP *psgNext; | ||
| 16 | }; | ||
| 17 | |||
| 18 | struct SCA_USER | ||
| 19 | { | ||
| 20 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 21 | WCHAR wzComponent[MAX_DARWIN_KEY + 1]; | ||
| 22 | INSTALLSTATE isInstalled; | ||
| 23 | INSTALLSTATE isAction; | ||
| 24 | |||
| 25 | WCHAR wzDomain[MAX_DARWIN_COLUMN + 1]; | ||
| 26 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
| 27 | WCHAR wzPassword[MAX_DARWIN_COLUMN + 1]; | ||
| 28 | INT iAttributes; | ||
| 29 | |||
| 30 | SCA_GROUP *psgGroups; | ||
| 31 | |||
| 32 | SCA_USER *psuNext; | ||
| 33 | }; | ||
| 34 | |||
| 35 | |||
| 36 | // prototypes | ||
| 37 | HRESULT __stdcall ScaGetUser( | ||
| 38 | __in LPCWSTR wzUser, | ||
| 39 | __out SCA_USER* pscau | ||
| 40 | ); | ||
diff --git a/src/ext/Sql/ca/sqlca.cpp b/src/ext/Sql/ca/sqlca.cpp new file mode 100644 index 00000000..37664a1c --- /dev/null +++ b/src/ext/Sql/ca/sqlca.cpp | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
diff --git a/src/ext/Sql/ca/sqlca.def b/src/ext/Sql/ca/sqlca.def new file mode 100644 index 00000000..e899d560 --- /dev/null +++ b/src/ext/Sql/ca/sqlca.def | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | ; Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | |||
| 4 | LIBRARY "sqlca" | ||
| 5 | |||
| 6 | EXPORTS | ||
| 7 | ;scaexec.cpp | ||
| 8 | CreateDatabase | ||
| 9 | DropDatabase | ||
| 10 | ExecuteSqlStrings | ||
| 11 | ;scasql.cpp | ||
| 12 | InstallSqlData | ||
| 13 | UninstallSqlData | ||
diff --git a/src/ext/Sql/ca/sqlca.vcxproj b/src/ext/Sql/ca/sqlca.vcxproj new file mode 100644 index 00000000..18becc5f --- /dev/null +++ b/src/ext/Sql/ca/sqlca.vcxproj | |||
| @@ -0,0 +1,83 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | |||
| 4 | <Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
| 5 | <ItemGroup Label="ProjectConfigurations"> | ||
| 6 | <ProjectConfiguration Include="Debug|Win32"> | ||
| 7 | <Configuration>Debug</Configuration> | ||
| 8 | <Platform>Win32</Platform> | ||
| 9 | </ProjectConfiguration> | ||
| 10 | <ProjectConfiguration Include="Release|Win32"> | ||
| 11 | <Configuration>Release</Configuration> | ||
| 12 | <Platform>Win32</Platform> | ||
| 13 | </ProjectConfiguration> | ||
| 14 | <ProjectConfiguration Include="Debug|x64"> | ||
| 15 | <Configuration>Debug</Configuration> | ||
| 16 | <Platform>x64</Platform> | ||
| 17 | </ProjectConfiguration> | ||
| 18 | <ProjectConfiguration Include="Release|x64"> | ||
| 19 | <Configuration>Release</Configuration> | ||
| 20 | <Platform>x64</Platform> | ||
| 21 | </ProjectConfiguration> | ||
| 22 | <ProjectConfiguration Include="Debug|ARM64"> | ||
| 23 | <Configuration>Debug</Configuration> | ||
| 24 | <Platform>ARM64</Platform> | ||
| 25 | </ProjectConfiguration> | ||
| 26 | <ProjectConfiguration Include="Release|ARM64"> | ||
| 27 | <Configuration>Release</Configuration> | ||
| 28 | <Platform>ARM64</Platform> | ||
| 29 | </ProjectConfiguration> | ||
| 30 | </ItemGroup> | ||
| 31 | |||
| 32 | <PropertyGroup Label="Globals"> | ||
| 33 | <ProjectGuid>{4DCA6E4B-A1F1-4450-BC2D-94AC20F31935}</ProjectGuid> | ||
| 34 | <ConfigurationType>DynamicLibrary</ConfigurationType> | ||
| 35 | <TargetName>sqlca</TargetName> | ||
| 36 | <PlatformToolset>v142</PlatformToolset> | ||
| 37 | <CharacterSet>Unicode</CharacterSet> | ||
| 38 | <ProjectModuleDefinitionFile>sqlca.def</ProjectModuleDefinitionFile> | ||
| 39 | <Description>WiX Toolset Sql CustomAction</Description> | ||
| 40 | </PropertyGroup> | ||
| 41 | |||
| 42 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> | ||
| 43 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> | ||
| 44 | |||
| 45 | <PropertyGroup> | ||
| 46 | <ProjectAdditionalLinkLibraries>msi.lib</ProjectAdditionalLinkLibraries> | ||
| 47 | </PropertyGroup> | ||
| 48 | |||
| 49 | <ItemGroup> | ||
| 50 | <ClCompile Include="dllmain.cpp"> | ||
| 51 | <PrecompiledHeader>Create</PrecompiledHeader> | ||
| 52 | </ClCompile> | ||
| 53 | <ClCompile Include="scadb.cpp" /> | ||
| 54 | <ClCompile Include="scaexec.cpp" /> | ||
| 55 | <ClCompile Include="scasql.cpp" /> | ||
| 56 | <ClCompile Include="scasqlstr.cpp" /> | ||
| 57 | <ClCompile Include="scauser.cpp" /> | ||
| 58 | <ClCompile Include="sqlca.cpp" /> | ||
| 59 | </ItemGroup> | ||
| 60 | |||
| 61 | <ItemGroup> | ||
| 62 | <ClInclude Include="CustomMsiErrors.h" /> | ||
| 63 | <ClInclude Include="precomp.h" /> | ||
| 64 | <ClInclude Include="sca.h" /> | ||
| 65 | <ClInclude Include="scacost.h" /> | ||
| 66 | <ClInclude Include="scadb.h" /> | ||
| 67 | <ClInclude Include="scasqlstr.h" /> | ||
| 68 | <ClInclude Include="scauser.h" /> | ||
| 69 | </ItemGroup> | ||
| 70 | |||
| 71 | <ItemGroup> | ||
| 72 | <None Include="sqlca.def" /> | ||
| 73 | </ItemGroup> | ||
| 74 | |||
| 75 | <ItemGroup> | ||
| 76 | <PackageReference Include="WixToolset.Dutil" Version="4.0.65" /> | ||
| 77 | <PackageReference Include="WixToolset.WcaUtil" Version="4.0.18" /> | ||
| 78 | <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" /> | ||
| 79 | <PackageReference Include="Nerdbank.GitVersioning" Version="3.3.37" /> | ||
| 80 | </ItemGroup> | ||
| 81 | |||
| 82 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | ||
| 83 | </Project> | ||
diff --git a/src/ext/Sql/nuget.config b/src/ext/Sql/nuget.config new file mode 100644 index 00000000..db7aba29 --- /dev/null +++ b/src/ext/Sql/nuget.config | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <configuration> | ||
| 3 | <packageSources> | ||
| 4 | <clear /> | ||
| 5 | <add key="wixtoolset-burn" value="https://ci.appveyor.com/nuget/wixtoolset-burn" /> | ||
| 6 | <add key="wixtoolset-data" value="https://ci.appveyor.com/nuget/wixtoolset-data" /> | ||
| 7 | <add key="wixtoolset-extensibility" value="https://ci.appveyor.com/nuget/wixtoolset-extensibility" /> | ||
| 8 | <add key="wixtoolset-core" value="https://ci.appveyor.com/nuget/wixtoolset-core" /> | ||
| 9 | <add key="wixtoolset-core-native" value="https://ci.appveyor.com/nuget/wixtoolset-core-native" /> | ||
| 10 | <add key="wixtoolset-dtf" value="https://ci.appveyor.com/nuget/wixtoolset-dtf" /> | ||
| 11 | <add key="wixtoolset-dutil" value="https://ci.appveyor.com/nuget/wixtoolset-dutil" /> | ||
| 12 | <add key="wixtoolset-wcautil" value="https://ci.appveyor.com/nuget/wixtoolset-wcautil" /> | ||
| 13 | <add key="wixtoolset-tools" value="https://ci.appveyor.com/nuget/wixtoolset-tools" /> | ||
| 14 | <add key="wixbuildtools" value="https://ci.appveyor.com/nuget/wixbuildtools" /> | ||
| 15 | <add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" /> | ||
| 16 | </packageSources> | ||
| 17 | </configuration> \ No newline at end of file | ||
diff --git a/src/ext/Sql/test/WixToolsetTest.Sql/SqlExtensionFixture.cs b/src/ext/Sql/test/WixToolsetTest.Sql/SqlExtensionFixture.cs new file mode 100644 index 00000000..aa9d7a1f --- /dev/null +++ b/src/ext/Sql/test/WixToolsetTest.Sql/SqlExtensionFixture.cs | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolsetTest.Sql | ||
| 4 | { | ||
| 5 | using System.Linq; | ||
| 6 | using WixBuildTools.TestSupport; | ||
| 7 | using WixToolset.Core.TestPackage; | ||
| 8 | using WixToolset.Sql; | ||
| 9 | using Xunit; | ||
| 10 | |||
| 11 | public class SqlExtensionFixture | ||
| 12 | { | ||
| 13 | [Fact] | ||
| 14 | public void CanBuildUsingSqlStuff() | ||
| 15 | { | ||
| 16 | var folder = TestData.Get(@"TestData\UsingSql"); | ||
| 17 | var build = new Builder(folder, typeof(SqlExtensionFactory), new[] { folder }); | ||
| 18 | |||
| 19 | var results = build.BuildAndQuery(Build, "Wix4SqlDatabase", "Wix4SqlFileSpec", "Wix4SqlScript", "Wix4SqlString"); | ||
| 20 | WixAssert.CompareLineByLine(new[] | ||
| 21 | { | ||
| 22 | "Wix4SqlDatabase:TestDB\tMySQLHostName\tMyInstanceName\tMyDB\tDatabaseComponent\t\tTestFileSpecId\tTestLogFileSpecId\t35", | ||
| 23 | "Wix4SqlFileSpec:TestFileSpecId\tTestFileSpecLogicalName\tTestFileSpec\t10MB\t100MB\t10%", | ||
| 24 | "Wix4SqlFileSpec:TestLogFileSpecId\tTestLogFileSpecLogicalName\tTestLogFileSpec\t1MB\t10MB\t1%", | ||
| 25 | "Wix4SqlScript:TestScript\tTestDB\tDatabaseComponent\tScriptBinary\t\t1\t", | ||
| 26 | "Wix4SqlString:TestString\tTestDB\tDatabaseComponent\tCREATE TABLE TestTable1(name varchar(20), value varchar(20))\t\t1\t", | ||
| 27 | }, results.ToArray()); | ||
| 28 | } | ||
| 29 | |||
| 30 | private static void Build(string[] args) | ||
| 31 | { | ||
| 32 | var result = WixRunner.Execute(args) | ||
| 33 | .AssertSuccess(); | ||
| 34 | } | ||
| 35 | } | ||
| 36 | } | ||
diff --git a/src/ext/Sql/test/WixToolsetTest.Sql/TestData/UsingSql/Package.en-us.wxl b/src/ext/Sql/test/WixToolsetTest.Sql/TestData/UsingSql/Package.en-us.wxl new file mode 100644 index 00000000..38c12ac1 --- /dev/null +++ b/src/ext/Sql/test/WixToolsetTest.Sql/TestData/UsingSql/Package.en-us.wxl | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | |||
| 3 | <!-- | ||
| 4 | This file contains the declaration of all the localizable strings. | ||
| 5 | --> | ||
| 6 | <WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US"> | ||
| 7 | |||
| 8 | <String Id="DowngradeError">A newer version of [ProductName] is already installed.</String> | ||
| 9 | <String Id="FeatureTitle">MsiPackage</String> | ||
| 10 | |||
| 11 | </WixLocalization> | ||
diff --git a/src/ext/Sql/test/WixToolsetTest.Sql/TestData/UsingSql/Package.wxs b/src/ext/Sql/test/WixToolsetTest.Sql/TestData/UsingSql/Package.wxs new file mode 100644 index 00000000..ee3bc921 --- /dev/null +++ b/src/ext/Sql/test/WixToolsetTest.Sql/TestData/UsingSql/Package.wxs | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 2 | <Package Name="MsiPackage" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a" InstallerVersion="200"> | ||
| 3 | |||
| 4 | |||
| 5 | <MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" /> | ||
| 6 | |||
| 7 | |||
| 8 | <Feature Id="ProductFeature" Title="!(loc.FeatureTitle)"> | ||
| 9 | <ComponentGroupRef Id="ProductComponents" /> | ||
| 10 | </Feature> | ||
| 11 | |||
| 12 | </Package> | ||
| 13 | |||
| 14 | <Fragment> | ||
| 15 | <StandardDirectory Id="ProgramFilesFolder"> | ||
| 16 | <Directory Id="INSTALLFOLDER" Name="MsiPackage" /> | ||
| 17 | </StandardDirectory> | ||
| 18 | </Fragment> | ||
| 19 | </Wix> | ||
diff --git a/src/ext/Sql/test/WixToolsetTest.Sql/TestData/UsingSql/PackageComponents.wxs b/src/ext/Sql/test/WixToolsetTest.Sql/TestData/UsingSql/PackageComponents.wxs new file mode 100644 index 00000000..f7626926 --- /dev/null +++ b/src/ext/Sql/test/WixToolsetTest.Sql/TestData/UsingSql/PackageComponents.wxs | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" | ||
| 3 | xmlns:sql="http://wixtoolset.org/schemas/v4/wxs/sql"> | ||
| 4 | <Fragment> | ||
| 5 | <Binary Id="ScriptBinary" SourceFile="example.txt" /> | ||
| 6 | |||
| 7 | <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER"> | ||
| 8 | <Component Id="DatabaseComponent" Guid="{322802E7-D65E-4C91-924F-FC6D30FEEB34}"> | ||
| 9 | <File Id="TestFileSpec" Source="example.txt" /> | ||
| 10 | <File Id="TestLogFileSpec" Source="example.txt" /> | ||
| 11 | |||
| 12 | <sql:SqlDatabase Id="TestDB" Database="MyDB" Server="MySQLHostName" Instance="MyInstanceName" CreateOnInstall="yes" DropOnUninstall="yes" ConfirmOverwrite="yes"> | ||
| 13 | <sql:SqlString Id="TestString" SQL="CREATE TABLE TestTable1(name varchar(20), value varchar(20))" ExecuteOnInstall="yes" /> | ||
| 14 | <sql:SqlFileSpec Id="TestFileSpecId" Filename="TestFileSpec" Name="TestFileSpecLogicalName" Size="10MB" GrowthSize="10%" MaxSize="100MB" /> | ||
| 15 | <sql:SqlLogFileSpec Id="TestLogFileSpecId" Filename="TestLogFileSpec" Name="TestLogFileSpecLogicalName" Size="1MB" GrowthSize="1%" MaxSize="10MB" /> | ||
| 16 | </sql:SqlDatabase> | ||
| 17 | |||
| 18 | <sql:SqlScript Id="TestScript" BinaryRef="ScriptBinary" SqlDb="TestDB" ExecuteOnInstall="yes" /> | ||
| 19 | </Component> | ||
| 20 | </ComponentGroup> | ||
| 21 | </Fragment> | ||
| 22 | </Wix> | ||
diff --git a/src/ext/Sql/test/WixToolsetTest.Sql/TestData/UsingSql/example.txt b/src/ext/Sql/test/WixToolsetTest.Sql/TestData/UsingSql/example.txt new file mode 100644 index 00000000..1b4ffe8a --- /dev/null +++ b/src/ext/Sql/test/WixToolsetTest.Sql/TestData/UsingSql/example.txt | |||
| @@ -0,0 +1 @@ | |||
| This is example.txt. \ No newline at end of file | |||
diff --git a/src/ext/Sql/test/WixToolsetTest.Sql/WixToolsetTest.Sql.csproj b/src/ext/Sql/test/WixToolsetTest.Sql/WixToolsetTest.Sql.csproj new file mode 100644 index 00000000..bbf3041d --- /dev/null +++ b/src/ext/Sql/test/WixToolsetTest.Sql/WixToolsetTest.Sql.csproj | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | |||
| 4 | <Project Sdk="Microsoft.NET.Sdk"> | ||
| 5 | <PropertyGroup> | ||
| 6 | <TargetFramework>netcoreapp3.1</TargetFramework> | ||
| 7 | <IsPackable>false</IsPackable> | ||
| 8 | </PropertyGroup> | ||
| 9 | |||
| 10 | <PropertyGroup> | ||
| 11 | <NoWarn>NU1701</NoWarn> | ||
| 12 | </PropertyGroup> | ||
| 13 | |||
| 14 | <ItemGroup> | ||
| 15 | <Content Include="TestData\**" CopyToOutputDirectory="PreserveNewest" /> | ||
| 16 | </ItemGroup> | ||
| 17 | |||
| 18 | <ItemGroup> | ||
| 19 | <ProjectReference Include="..\..\wixext\WixToolset.Sql.wixext.csproj" /> | ||
| 20 | </ItemGroup> | ||
| 21 | |||
| 22 | <ItemGroup> | ||
| 23 | <PackageReference Include="WixToolset.Core" Version="4.0.*" /> | ||
| 24 | <PackageReference Include="WixToolset.Core.Burn" Version="4.0.*" /> | ||
| 25 | <PackageReference Include="WixToolset.Core.WindowsInstaller" Version="4.0.*" /> | ||
| 26 | <PackageReference Include="WixToolset.Core.TestPackage" Version="4.0.*" /> | ||
| 27 | </ItemGroup> | ||
| 28 | |||
| 29 | <ItemGroup> | ||
| 30 | <PackageReference Include="WixBuildTools.TestSupport" Version="4.0.*" /> | ||
| 31 | </ItemGroup> | ||
| 32 | |||
| 33 | <ItemGroup> | ||
| 34 | <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" /> | ||
| 35 | <PackageReference Include="xunit" Version="2.4.1" /> | ||
| 36 | <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" PrivateAssets="All" /> | ||
| 37 | </ItemGroup> | ||
| 38 | </Project> | ||
diff --git a/src/ext/Sql/test/WixToolsetTest.Sql/WixToolsetTest.Sql.v3.ncrunchproject b/src/ext/Sql/test/WixToolsetTest.Sql/WixToolsetTest.Sql.v3.ncrunchproject new file mode 100644 index 00000000..7b5b2139 --- /dev/null +++ b/src/ext/Sql/test/WixToolsetTest.Sql/WixToolsetTest.Sql.v3.ncrunchproject | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | <ProjectConfiguration> | ||
| 2 | <Settings> | ||
| 3 | <CopyReferencedAssembliesToWorkspace>True</CopyReferencedAssembliesToWorkspace> | ||
| 4 | </Settings> | ||
| 5 | </ProjectConfiguration> \ No newline at end of file | ||
diff --git a/src/ext/Sql/wix.snk b/src/ext/Sql/wix.snk new file mode 100644 index 00000000..3908a66a --- /dev/null +++ b/src/ext/Sql/wix.snk | |||
| Binary files differ | |||
diff --git a/src/ext/Sql/wixext/SqlCompiler.cs b/src/ext/Sql/wixext/SqlCompiler.cs new file mode 100644 index 00000000..46196e95 --- /dev/null +++ b/src/ext/Sql/wixext/SqlCompiler.cs | |||
| @@ -0,0 +1,804 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Sql | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Collections.Generic; | ||
| 7 | using System.Xml.Linq; | ||
| 8 | using WixToolset.Data; | ||
| 9 | using WixToolset.Extensibility; | ||
| 10 | using WixToolset.Extensibility.Data; | ||
| 11 | using WixToolset.Sql.Symbols; | ||
| 12 | |||
| 13 | /// <summary> | ||
| 14 | /// The compiler for the WiX Toolset SQL Server Extension. | ||
| 15 | /// </summary> | ||
| 16 | public sealed class SqlCompiler : BaseCompilerExtension | ||
| 17 | { | ||
| 18 | // sql database attributes definitions (from sca.h) | ||
| 19 | internal const int DbCreateOnInstall = 0x00000001; | ||
| 20 | internal const int DbDropOnUninstall = 0x00000002; | ||
| 21 | internal const int DbContinueOnError = 0x00000004; | ||
| 22 | internal const int DbDropOnInstall = 0x00000008; | ||
| 23 | internal const int DbCreateOnUninstall = 0x00000010; | ||
| 24 | internal const int DbConfirmOverwrite = 0x00000020; | ||
| 25 | internal const int DbCreateOnReinstall = 0x00000040; | ||
| 26 | internal const int DbDropOnReinstall = 0x00000080; | ||
| 27 | |||
| 28 | // sql string/script attributes definitions (from sca.h) | ||
| 29 | internal const int SqlExecuteOnInstall = 0x00000001; | ||
| 30 | internal const int SqlExecuteOnUninstall = 0x00000002; | ||
| 31 | internal const int SqlContinueOnError = 0x00000004; | ||
| 32 | internal const int SqlRollback = 0x00000008; | ||
| 33 | internal const int SqlExecuteOnReinstall = 0x00000010; | ||
| 34 | |||
| 35 | public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/sql"; | ||
| 36 | |||
| 37 | /// <summary> | ||
| 38 | /// Processes an element for the Compiler. | ||
| 39 | /// </summary> | ||
| 40 | /// <param name="intermediate"></param> | ||
| 41 | /// <param name="section"></param> | ||
| 42 | /// <param name="parentElement">Parent element of element to process.</param> | ||
| 43 | /// <param name="element">Element to process.</param> | ||
| 44 | /// <param name="context">Extra information about the context in which this element is being parsed.</param> | ||
| 45 | public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary<string, string> context) | ||
| 46 | { | ||
| 47 | switch (parentElement.Name.LocalName) | ||
| 48 | { | ||
| 49 | case "Component": | ||
| 50 | var componentId = context["ComponentId"]; | ||
| 51 | |||
| 52 | switch (element.Name.LocalName) | ||
| 53 | { | ||
| 54 | case "SqlDatabase": | ||
| 55 | this.ParseSqlDatabaseElement(intermediate, section, element, componentId); | ||
| 56 | break; | ||
| 57 | case "SqlScript": | ||
| 58 | this.ParseSqlScriptElement(intermediate, section, element, componentId, null); | ||
| 59 | break; | ||
| 60 | case "SqlString": | ||
| 61 | this.ParseSqlStringElement(intermediate, section, element, componentId, null); | ||
| 62 | break; | ||
| 63 | default: | ||
| 64 | this.ParseHelper.UnexpectedElement(parentElement, element); | ||
| 65 | break; | ||
| 66 | } | ||
| 67 | break; | ||
| 68 | case "Fragment": | ||
| 69 | case "Module": | ||
| 70 | case "Package": | ||
| 71 | switch (element.Name.LocalName) | ||
| 72 | { | ||
| 73 | case "SqlDatabase": | ||
| 74 | this.ParseSqlDatabaseElement(intermediate, section, element, null); | ||
| 75 | break; | ||
| 76 | default: | ||
| 77 | this.ParseHelper.UnexpectedElement(parentElement, element); | ||
| 78 | break; | ||
| 79 | } | ||
| 80 | break; | ||
| 81 | default: | ||
| 82 | this.ParseHelper.UnexpectedElement(parentElement, element); | ||
| 83 | break; | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | /// <summary> | ||
| 88 | /// Parses a sql database element | ||
| 89 | /// </summary> | ||
| 90 | /// <param name="intermediate"></param> | ||
| 91 | /// <param name="section"></param> | ||
| 92 | /// <param name="element">Element to parse.</param> | ||
| 93 | /// <param name="componentId">Identifier for parent component.</param> | ||
| 94 | private void ParseSqlDatabaseElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId) | ||
| 95 | { | ||
| 96 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 97 | Identifier id = null; | ||
| 98 | int attributes = 0; | ||
| 99 | string database = null; | ||
| 100 | Identifier fileSpec = null; | ||
| 101 | string instance = null; | ||
| 102 | Identifier logFileSpec = null; | ||
| 103 | string server = null; | ||
| 104 | string user = null; | ||
| 105 | |||
| 106 | foreach (var attrib in element.Attributes()) | ||
| 107 | { | ||
| 108 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 109 | { | ||
| 110 | switch (attrib.Name.LocalName) | ||
| 111 | { | ||
| 112 | case "Id": | ||
| 113 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 114 | break; | ||
| 115 | case "ConfirmOverwrite": | ||
| 116 | if (null == componentId) | ||
| 117 | { | ||
| 118 | this.Messaging.Write(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 119 | } | ||
| 120 | |||
| 121 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 122 | { | ||
| 123 | attributes |= DbConfirmOverwrite; | ||
| 124 | } | ||
| 125 | break; | ||
| 126 | case "ContinueOnError": | ||
| 127 | if (null == componentId) | ||
| 128 | { | ||
| 129 | this.Messaging.Write(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 130 | } | ||
| 131 | |||
| 132 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 133 | { | ||
| 134 | attributes |= DbContinueOnError; | ||
| 135 | } | ||
| 136 | break; | ||
| 137 | case "CreateOnInstall": | ||
| 138 | if (null == componentId) | ||
| 139 | { | ||
| 140 | this.Messaging.Write(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 141 | } | ||
| 142 | |||
| 143 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 144 | { | ||
| 145 | attributes |= DbCreateOnInstall; | ||
| 146 | } | ||
| 147 | break; | ||
| 148 | case "CreateOnReinstall": | ||
| 149 | if (null == componentId) | ||
| 150 | { | ||
| 151 | this.Messaging.Write(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 152 | } | ||
| 153 | |||
| 154 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 155 | { | ||
| 156 | attributes |= DbCreateOnReinstall; | ||
| 157 | } | ||
| 158 | break; | ||
| 159 | case "CreateOnUninstall": | ||
| 160 | if (null == componentId) | ||
| 161 | { | ||
| 162 | this.Messaging.Write(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 163 | } | ||
| 164 | |||
| 165 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 166 | { | ||
| 167 | attributes |= DbCreateOnUninstall; | ||
| 168 | } | ||
| 169 | break; | ||
| 170 | case "Database": | ||
| 171 | database = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 172 | break; | ||
| 173 | case "DropOnInstall": | ||
| 174 | if (null == componentId) | ||
| 175 | { | ||
| 176 | this.Messaging.Write(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 177 | } | ||
| 178 | |||
| 179 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 180 | { | ||
| 181 | attributes |= DbDropOnInstall; | ||
| 182 | } | ||
| 183 | break; | ||
| 184 | case "DropOnReinstall": | ||
| 185 | if (null == componentId) | ||
| 186 | { | ||
| 187 | this.Messaging.Write(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 188 | } | ||
| 189 | |||
| 190 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 191 | { | ||
| 192 | attributes |= DbDropOnReinstall; | ||
| 193 | } | ||
| 194 | break; | ||
| 195 | |||
| 196 | case "DropOnUninstall": | ||
| 197 | if (null == componentId) | ||
| 198 | { | ||
| 199 | this.Messaging.Write(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName)); | ||
| 200 | } | ||
| 201 | |||
| 202 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 203 | { | ||
| 204 | attributes |= DbDropOnUninstall; | ||
| 205 | } | ||
| 206 | break; | ||
| 207 | case "Instance": | ||
| 208 | instance = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 209 | break; | ||
| 210 | case "Server": | ||
| 211 | server = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 212 | break; | ||
| 213 | case "User": | ||
| 214 | user = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 215 | if (!this.ParseHelper.ContainsProperty(user)) | ||
| 216 | { | ||
| 217 | user = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 218 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "User", user); | ||
| 219 | } | ||
| 220 | break; | ||
| 221 | default: | ||
| 222 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 223 | break; | ||
| 224 | } | ||
| 225 | } | ||
| 226 | else | ||
| 227 | { | ||
| 228 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 229 | } | ||
| 230 | } | ||
| 231 | |||
| 232 | if (null == id) | ||
| 233 | { | ||
| 234 | id = this.ParseHelper.CreateIdentifier("sdb", componentId, server, database); | ||
| 235 | } | ||
| 236 | |||
| 237 | if (null == database) | ||
| 238 | { | ||
| 239 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Database")); | ||
| 240 | } | ||
| 241 | else if (128 < database.Length) | ||
| 242 | { | ||
| 243 | this.Messaging.Write(ErrorMessages.IdentifierTooLongError(sourceLineNumbers, element.Name.LocalName, "Database", database, 128)); | ||
| 244 | } | ||
| 245 | |||
| 246 | if (null == server) | ||
| 247 | { | ||
| 248 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Server")); | ||
| 249 | } | ||
| 250 | |||
| 251 | if (0 == attributes && null != componentId) | ||
| 252 | { | ||
| 253 | this.Messaging.Write(SqlErrors.OneOfAttributesRequiredUnderComponent(sourceLineNumbers, element.Name.LocalName, "CreateOnInstall", "CreateOnUninstall", "DropOnInstall", "DropOnUninstall")); | ||
| 254 | } | ||
| 255 | |||
| 256 | foreach (var child in element.Elements()) | ||
| 257 | { | ||
| 258 | if (this.Namespace == child.Name.Namespace) | ||
| 259 | { | ||
| 260 | var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child); | ||
| 261 | switch (child.Name.LocalName) | ||
| 262 | { | ||
| 263 | case "SqlScript": | ||
| 264 | if (null == componentId) | ||
| 265 | { | ||
| 266 | this.Messaging.Write(SqlErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); | ||
| 267 | } | ||
| 268 | |||
| 269 | this.ParseSqlScriptElement(intermediate, section, child, componentId, id?.Id); | ||
| 270 | break; | ||
| 271 | case "SqlString": | ||
| 272 | if (null == componentId) | ||
| 273 | { | ||
| 274 | this.Messaging.Write(SqlErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); | ||
| 275 | } | ||
| 276 | |||
| 277 | this.ParseSqlStringElement(intermediate, section, child, componentId, id?.Id); | ||
| 278 | break; | ||
| 279 | case "SqlFileSpec": | ||
| 280 | if (null == componentId) | ||
| 281 | { | ||
| 282 | this.Messaging.Write(SqlErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); | ||
| 283 | } | ||
| 284 | else if (null != fileSpec) | ||
| 285 | { | ||
| 286 | this.Messaging.Write(ErrorMessages.TooManyElements(sourceLineNumbers, element.Name.LocalName, child.Name.LocalName, 1)); | ||
| 287 | } | ||
| 288 | |||
| 289 | fileSpec = this.ParseSqlFileSpecElement(intermediate, section, child, id?.Id); | ||
| 290 | break; | ||
| 291 | case "SqlLogFileSpec": | ||
| 292 | if (null == componentId) | ||
| 293 | { | ||
| 294 | this.Messaging.Write(SqlErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); | ||
| 295 | } | ||
| 296 | else if (null != logFileSpec) | ||
| 297 | { | ||
| 298 | this.Messaging.Write(ErrorMessages.TooManyElements(sourceLineNumbers, element.Name.LocalName, child.Name.LocalName, 1)); | ||
| 299 | } | ||
| 300 | |||
| 301 | logFileSpec = this.ParseSqlFileSpecElement(intermediate, section, child, id?.Id); | ||
| 302 | break; | ||
| 303 | default: | ||
| 304 | this.ParseHelper.UnexpectedElement(element, child); | ||
| 305 | break; | ||
| 306 | } | ||
| 307 | } | ||
| 308 | else | ||
| 309 | { | ||
| 310 | this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child); | ||
| 311 | } | ||
| 312 | } | ||
| 313 | |||
| 314 | if (null != componentId) | ||
| 315 | { | ||
| 316 | // Reference InstallSqlData and UninstallSqlData since nothing will happen without it | ||
| 317 | this.AddReferenceToInstallSqlData(section, sourceLineNumbers); | ||
| 318 | } | ||
| 319 | |||
| 320 | if (!this.Messaging.EncounteredError) | ||
| 321 | { | ||
| 322 | var symbol = section.AddSymbol(new SqlDatabaseSymbol(sourceLineNumbers, id) | ||
| 323 | { | ||
| 324 | Server = server, | ||
| 325 | Instance = instance, | ||
| 326 | Database = database, | ||
| 327 | ComponentRef = componentId, | ||
| 328 | UserRef = user, | ||
| 329 | FileSpecRef = fileSpec?.Id, | ||
| 330 | LogFileSpecRef = logFileSpec?.Id, | ||
| 331 | }); | ||
| 332 | |||
| 333 | if (0 != attributes) | ||
| 334 | { | ||
| 335 | symbol.Attributes = attributes; | ||
| 336 | } | ||
| 337 | } | ||
| 338 | } | ||
| 339 | |||
| 340 | /// <summary> | ||
| 341 | /// Parses a sql file specification element. | ||
| 342 | /// </summary> | ||
| 343 | /// <param name="intermediate"></param> | ||
| 344 | /// <param name="section"></param> | ||
| 345 | /// <param name="element">Element to parse.</param> | ||
| 346 | /// <returns>Identifier of sql file specification.</returns> | ||
| 347 | private Identifier ParseSqlFileSpecElement(Intermediate intermediate, IntermediateSection section, XElement element, string parentId) | ||
| 348 | { | ||
| 349 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 350 | Identifier id = null; | ||
| 351 | string fileName = null; | ||
| 352 | string growthSize = null; | ||
| 353 | string maxSize = null; | ||
| 354 | string name = null; | ||
| 355 | string size = null; | ||
| 356 | |||
| 357 | foreach (var attrib in element.Attributes()) | ||
| 358 | { | ||
| 359 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 360 | { | ||
| 361 | switch (attrib.Name.LocalName) | ||
| 362 | { | ||
| 363 | case "Id": | ||
| 364 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 365 | break; | ||
| 366 | case "Name": | ||
| 367 | name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 368 | break; | ||
| 369 | case "Filename": | ||
| 370 | fileName = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 371 | break; | ||
| 372 | case "Size": | ||
| 373 | size = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 374 | break; | ||
| 375 | case "MaxSize": | ||
| 376 | maxSize = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 377 | break; | ||
| 378 | case "GrowthSize": | ||
| 379 | growthSize = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 380 | break; | ||
| 381 | default: | ||
| 382 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 383 | break; | ||
| 384 | } | ||
| 385 | } | ||
| 386 | else | ||
| 387 | { | ||
| 388 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 389 | } | ||
| 390 | } | ||
| 391 | |||
| 392 | if (null == id) | ||
| 393 | { | ||
| 394 | id = this.ParseHelper.CreateIdentifier("sfs", parentId, name, fileName); | ||
| 395 | } | ||
| 396 | |||
| 397 | if (null == name) | ||
| 398 | { | ||
| 399 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); | ||
| 400 | } | ||
| 401 | |||
| 402 | if (null == fileName) | ||
| 403 | { | ||
| 404 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Filename")); | ||
| 405 | } | ||
| 406 | |||
| 407 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | ||
| 408 | |||
| 409 | if (!this.Messaging.EncounteredError) | ||
| 410 | { | ||
| 411 | var symbol = section.AddSymbol(new SqlFileSpecSymbol(sourceLineNumbers, id) | ||
| 412 | { | ||
| 413 | Name = name, | ||
| 414 | Filename = fileName, | ||
| 415 | }); | ||
| 416 | |||
| 417 | if (null != size) | ||
| 418 | { | ||
| 419 | symbol.Size = size; | ||
| 420 | } | ||
| 421 | |||
| 422 | if (null != maxSize) | ||
| 423 | { | ||
| 424 | symbol.MaxSize = maxSize; | ||
| 425 | } | ||
| 426 | |||
| 427 | if (null != growthSize) | ||
| 428 | { | ||
| 429 | symbol.GrowthSize = growthSize; | ||
| 430 | } | ||
| 431 | } | ||
| 432 | |||
| 433 | return id; | ||
| 434 | } | ||
| 435 | |||
| 436 | /// <summary> | ||
| 437 | /// Parses a sql script element. | ||
| 438 | /// </summary> | ||
| 439 | /// <param name="element">Element to parse.</param> | ||
| 440 | /// <param name="componentId">Identifier for parent component.</param> | ||
| 441 | /// <param name="sqlDb">Optional database to execute script against.</param> | ||
| 442 | private void ParseSqlScriptElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string sqlDb) | ||
| 443 | { | ||
| 444 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 445 | Identifier id = null; | ||
| 446 | int attributes = 0; | ||
| 447 | var rollbackAttribute = false; | ||
| 448 | var nonRollbackAttribute = false; | ||
| 449 | string binaryRef = null; | ||
| 450 | var sequence = CompilerConstants.IntegerNotSet; | ||
| 451 | string user = null; | ||
| 452 | |||
| 453 | foreach (var attrib in element.Attributes()) | ||
| 454 | { | ||
| 455 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 456 | { | ||
| 457 | switch (attrib.Name.LocalName) | ||
| 458 | { | ||
| 459 | case "Id": | ||
| 460 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 461 | break; | ||
| 462 | case "BinaryRef": | ||
| 463 | binaryRef = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 464 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Binary, binaryRef); | ||
| 465 | break; | ||
| 466 | case "Sequence": | ||
| 467 | sequence = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, short.MaxValue); | ||
| 468 | break; | ||
| 469 | case "SqlDb": | ||
| 470 | if (null != sqlDb) | ||
| 471 | { | ||
| 472 | this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, element.Parent.Name.LocalName)); | ||
| 473 | } | ||
| 474 | sqlDb = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 475 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SqlSymbolDefinitions.SqlDatabase, sqlDb); | ||
| 476 | break; | ||
| 477 | case "User": | ||
| 478 | user = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 479 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "User", user); | ||
| 480 | break; | ||
| 481 | |||
| 482 | // Flag-setting attributes | ||
| 483 | case "ContinueOnError": | ||
| 484 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 485 | { | ||
| 486 | attributes |= SqlContinueOnError; | ||
| 487 | } | ||
| 488 | break; | ||
| 489 | case "ExecuteOnInstall": | ||
| 490 | if (rollbackAttribute) | ||
| 491 | { | ||
| 492 | this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall")); | ||
| 493 | } | ||
| 494 | nonRollbackAttribute = true; | ||
| 495 | |||
| 496 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 497 | { | ||
| 498 | attributes |= SqlExecuteOnInstall; | ||
| 499 | } | ||
| 500 | break; | ||
| 501 | case "ExecuteOnReinstall": | ||
| 502 | if (rollbackAttribute) | ||
| 503 | { | ||
| 504 | this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall")); | ||
| 505 | } | ||
| 506 | nonRollbackAttribute = true; | ||
| 507 | |||
| 508 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 509 | { | ||
| 510 | attributes |= SqlExecuteOnReinstall; | ||
| 511 | } | ||
| 512 | break; | ||
| 513 | case "ExecuteOnUninstall": | ||
| 514 | if (rollbackAttribute) | ||
| 515 | { | ||
| 516 | this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall")); | ||
| 517 | } | ||
| 518 | nonRollbackAttribute = true; | ||
| 519 | |||
| 520 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 521 | { | ||
| 522 | attributes |= SqlExecuteOnUninstall; | ||
| 523 | } | ||
| 524 | break; | ||
| 525 | case "RollbackOnInstall": | ||
| 526 | if (nonRollbackAttribute) | ||
| 527 | { | ||
| 528 | this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall")); | ||
| 529 | } | ||
| 530 | rollbackAttribute = true; | ||
| 531 | |||
| 532 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 533 | { | ||
| 534 | attributes |= SqlExecuteOnInstall; | ||
| 535 | attributes |= SqlRollback; | ||
| 536 | } | ||
| 537 | break; | ||
| 538 | case "RollbackOnReinstall": | ||
| 539 | if (nonRollbackAttribute) | ||
| 540 | { | ||
| 541 | this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall")); | ||
| 542 | } | ||
| 543 | rollbackAttribute = true; | ||
| 544 | |||
| 545 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 546 | { | ||
| 547 | attributes |= SqlExecuteOnReinstall; | ||
| 548 | attributes |= SqlRollback; | ||
| 549 | } | ||
| 550 | break; | ||
| 551 | case "RollbackOnUninstall": | ||
| 552 | if (nonRollbackAttribute) | ||
| 553 | { | ||
| 554 | this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall")); | ||
| 555 | } | ||
| 556 | rollbackAttribute = true; | ||
| 557 | |||
| 558 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 559 | { | ||
| 560 | attributes |= SqlExecuteOnUninstall; | ||
| 561 | attributes |= SqlRollback; | ||
| 562 | } | ||
| 563 | break; | ||
| 564 | default: | ||
| 565 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 566 | break; | ||
| 567 | } | ||
| 568 | } | ||
| 569 | else | ||
| 570 | { | ||
| 571 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 572 | } | ||
| 573 | } | ||
| 574 | |||
| 575 | if (null == id) | ||
| 576 | { | ||
| 577 | id = this.ParseHelper.CreateIdentifier("ssc", componentId, binaryRef, sqlDb); | ||
| 578 | } | ||
| 579 | |||
| 580 | if (null == binaryRef) | ||
| 581 | { | ||
| 582 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "BinaryRef")); | ||
| 583 | } | ||
| 584 | |||
| 585 | if (null == sqlDb) | ||
| 586 | { | ||
| 587 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "SqlDb")); | ||
| 588 | } | ||
| 589 | |||
| 590 | if (0 == attributes) | ||
| 591 | { | ||
| 592 | this.Messaging.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, element.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall", "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall")); | ||
| 593 | } | ||
| 594 | |||
| 595 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | ||
| 596 | |||
| 597 | // Reference InstallSqlData and UninstallSqlData since nothing will happen without it | ||
| 598 | this.AddReferenceToInstallSqlData(section, sourceLineNumbers); | ||
| 599 | |||
| 600 | if (!this.Messaging.EncounteredError) | ||
| 601 | { | ||
| 602 | var symbol = section.AddSymbol(new SqlScriptSymbol(sourceLineNumbers, id) | ||
| 603 | { | ||
| 604 | SqlDbRef = sqlDb, | ||
| 605 | ComponentRef = componentId, | ||
| 606 | ScriptBinaryRef = binaryRef, | ||
| 607 | UserRef = user, | ||
| 608 | Attributes = attributes, | ||
| 609 | }); | ||
| 610 | |||
| 611 | if (CompilerConstants.IntegerNotSet != sequence) | ||
| 612 | { | ||
| 613 | symbol.Sequence = sequence; | ||
| 614 | } | ||
| 615 | } | ||
| 616 | } | ||
| 617 | |||
| 618 | /// <summary> | ||
| 619 | /// Parses a sql string element. | ||
| 620 | /// </summary> | ||
| 621 | /// <param name="element">Element to parse.</param> | ||
| 622 | /// <param name="componentId">Identifier for parent component.</param> | ||
| 623 | /// <param name="sqlDb">Optional database to execute string against.</param> | ||
| 624 | private void ParseSqlStringElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string sqlDb) | ||
| 625 | { | ||
| 626 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 627 | Identifier id = null; | ||
| 628 | int attributes = 0; | ||
| 629 | var rollbackAttribute = false; | ||
| 630 | var nonRollbackAttribute = false; | ||
| 631 | var sequence = CompilerConstants.IntegerNotSet; | ||
| 632 | string sql = null; | ||
| 633 | string user = null; | ||
| 634 | |||
| 635 | foreach (var attrib in element.Attributes()) | ||
| 636 | { | ||
| 637 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 638 | { | ||
| 639 | switch (attrib.Name.LocalName) | ||
| 640 | { | ||
| 641 | case "Id": | ||
| 642 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
| 643 | break; | ||
| 644 | case "ContinueOnError": | ||
| 645 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 646 | { | ||
| 647 | attributes |= SqlContinueOnError; | ||
| 648 | } | ||
| 649 | break; | ||
| 650 | case "ExecuteOnInstall": | ||
| 651 | if (rollbackAttribute) | ||
| 652 | { | ||
| 653 | this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall")); | ||
| 654 | } | ||
| 655 | nonRollbackAttribute = true; | ||
| 656 | |||
| 657 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 658 | { | ||
| 659 | attributes |= SqlExecuteOnInstall; | ||
| 660 | } | ||
| 661 | break; | ||
| 662 | case "ExecuteOnReinstall": | ||
| 663 | if (rollbackAttribute) | ||
| 664 | { | ||
| 665 | this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall")); | ||
| 666 | } | ||
| 667 | nonRollbackAttribute = true; | ||
| 668 | |||
| 669 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 670 | { | ||
| 671 | attributes |= SqlExecuteOnReinstall; | ||
| 672 | } | ||
| 673 | break; | ||
| 674 | case "ExecuteOnUninstall": | ||
| 675 | if (rollbackAttribute) | ||
| 676 | { | ||
| 677 | this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall")); | ||
| 678 | } | ||
| 679 | nonRollbackAttribute = true; | ||
| 680 | |||
| 681 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 682 | { | ||
| 683 | attributes |= SqlExecuteOnUninstall; | ||
| 684 | } | ||
| 685 | break; | ||
| 686 | case "RollbackOnInstall": | ||
| 687 | if (nonRollbackAttribute) | ||
| 688 | { | ||
| 689 | this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall")); | ||
| 690 | } | ||
| 691 | rollbackAttribute = true; | ||
| 692 | |||
| 693 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 694 | { | ||
| 695 | attributes |= SqlExecuteOnInstall; | ||
| 696 | attributes |= SqlRollback; | ||
| 697 | } | ||
| 698 | break; | ||
| 699 | case "RollbackOnReinstall": | ||
| 700 | if (nonRollbackAttribute) | ||
| 701 | { | ||
| 702 | this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall")); | ||
| 703 | } | ||
| 704 | rollbackAttribute = true; | ||
| 705 | |||
| 706 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 707 | { | ||
| 708 | attributes |= SqlExecuteOnReinstall; | ||
| 709 | attributes |= SqlRollback; | ||
| 710 | } | ||
| 711 | break; | ||
| 712 | case "RollbackOnUninstall": | ||
| 713 | if (nonRollbackAttribute) | ||
| 714 | { | ||
| 715 | this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall")); | ||
| 716 | } | ||
| 717 | rollbackAttribute = true; | ||
| 718 | |||
| 719 | if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 720 | { | ||
| 721 | attributes |= SqlExecuteOnUninstall; | ||
| 722 | attributes |= SqlRollback; | ||
| 723 | } | ||
| 724 | break; | ||
| 725 | case "Sequence": | ||
| 726 | sequence = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, short.MaxValue); | ||
| 727 | break; | ||
| 728 | case "SQL": | ||
| 729 | sql = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 730 | break; | ||
| 731 | case "SqlDb": | ||
| 732 | if (null != sqlDb) | ||
| 733 | { | ||
| 734 | this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "SqlDb", "SqlDatabase")); | ||
| 735 | } | ||
| 736 | |||
| 737 | sqlDb = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 738 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SqlSymbolDefinitions.SqlDatabase, sqlDb); | ||
| 739 | break; | ||
| 740 | case "User": | ||
| 741 | user = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 742 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "User", user); | ||
| 743 | break; | ||
| 744 | default: | ||
| 745 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 746 | break; | ||
| 747 | } | ||
| 748 | } | ||
| 749 | else | ||
| 750 | { | ||
| 751 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 752 | } | ||
| 753 | } | ||
| 754 | |||
| 755 | if (null == id) | ||
| 756 | { | ||
| 757 | id = this.ParseHelper.CreateIdentifier("sst", componentId, sql, sqlDb); | ||
| 758 | } | ||
| 759 | |||
| 760 | if (null == sql) | ||
| 761 | { | ||
| 762 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "SQL")); | ||
| 763 | } | ||
| 764 | |||
| 765 | if (null == sqlDb) | ||
| 766 | { | ||
| 767 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "SqlDb")); | ||
| 768 | } | ||
| 769 | |||
| 770 | if (0 == attributes) | ||
| 771 | { | ||
| 772 | this.Messaging.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, element.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall", "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall")); | ||
| 773 | } | ||
| 774 | |||
| 775 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | ||
| 776 | |||
| 777 | // Reference InstallSqlData and UninstallSqlData since nothing will happen without it | ||
| 778 | this.AddReferenceToInstallSqlData(section, sourceLineNumbers); | ||
| 779 | |||
| 780 | if (!this.Messaging.EncounteredError) | ||
| 781 | { | ||
| 782 | var symbol = section.AddSymbol(new SqlStringSymbol(sourceLineNumbers, id) | ||
| 783 | { | ||
| 784 | SqlDbRef = sqlDb, | ||
| 785 | ComponentRef = componentId, | ||
| 786 | SQL = sql, | ||
| 787 | UserRef = user, | ||
| 788 | Attributes = attributes, | ||
| 789 | }); | ||
| 790 | |||
| 791 | if (CompilerConstants.IntegerNotSet != sequence) | ||
| 792 | { | ||
| 793 | symbol.Sequence = sequence; | ||
| 794 | } | ||
| 795 | } | ||
| 796 | } | ||
| 797 | |||
| 798 | private void AddReferenceToInstallSqlData(IntermediateSection section, SourceLineNumber sourceLineNumbers) | ||
| 799 | { | ||
| 800 | this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4InstallSqlData", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); | ||
| 801 | this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4UninstallSqlData", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); | ||
| 802 | } | ||
| 803 | } | ||
| 804 | } | ||
diff --git a/src/ext/Sql/wixext/SqlDecompiler.cs b/src/ext/Sql/wixext/SqlDecompiler.cs new file mode 100644 index 00000000..52436b87 --- /dev/null +++ b/src/ext/Sql/wixext/SqlDecompiler.cs | |||
| @@ -0,0 +1,514 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Sql | ||
| 4 | { | ||
| 5 | #if TODO_CONSIDER_DECOMPILER | ||
| 6 | using System.Collections; | ||
| 7 | using WixToolset.Data; | ||
| 8 | using WixToolset.Extensibility; | ||
| 9 | using Sql = WixToolset.Extensions.Serialize.Sql; | ||
| 10 | using Wix = WixToolset.Data.Serialize; | ||
| 11 | |||
| 12 | /// <summary> | ||
| 13 | /// The decompiler for the WiX Toolset SQL Server Extension. | ||
| 14 | /// </summary> | ||
| 15 | public sealed class SqlDecompiler : DecompilerExtension | ||
| 16 | { | ||
| 17 | /// <summary> | ||
| 18 | /// Creates a decompiler for SQL Extension. | ||
| 19 | /// </summary> | ||
| 20 | public SqlDecompiler() | ||
| 21 | { | ||
| 22 | this.TableDefinitions = SqlExtensionData.GetExtensionTableDefinitions(); | ||
| 23 | } | ||
| 24 | |||
| 25 | /// <summary> | ||
| 26 | /// Get the extensions library to be removed. | ||
| 27 | /// </summary> | ||
| 28 | /// <param name="tableDefinitions">Table definitions for library.</param> | ||
| 29 | /// <returns>Library to remove from decompiled output.</returns> | ||
| 30 | public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions) | ||
| 31 | { | ||
| 32 | return SqlExtensionData.GetExtensionLibrary(tableDefinitions); | ||
| 33 | } | ||
| 34 | |||
| 35 | /// <summary> | ||
| 36 | /// Decompiles an extension table. | ||
| 37 | /// </summary> | ||
| 38 | /// <param name="table">The table to decompile.</param> | ||
| 39 | public override void DecompileTable(Table table) | ||
| 40 | { | ||
| 41 | switch (table.Name) | ||
| 42 | { | ||
| 43 | case "SqlDatabase": | ||
| 44 | this.DecompileSqlDatabaseTable(table); | ||
| 45 | break; | ||
| 46 | case "SqlFileSpec": | ||
| 47 | // handled in FinalizeSqlFileSpecTable | ||
| 48 | break; | ||
| 49 | case "SqlScript": | ||
| 50 | this.DecompileSqlScriptTable(table); | ||
| 51 | break; | ||
| 52 | case "SqlString": | ||
| 53 | this.DecompileSqlStringTable(table); | ||
| 54 | break; | ||
| 55 | default: | ||
| 56 | base.DecompileTable(table); | ||
| 57 | break; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | /// <summary> | ||
| 62 | /// Finalize decompilation. | ||
| 63 | /// </summary> | ||
| 64 | /// <param name="tables">The collection of all tables.</param> | ||
| 65 | public override void Finish(TableIndexedCollection tables) | ||
| 66 | { | ||
| 67 | this.FinalizeSqlFileSpecTable(tables); | ||
| 68 | this.FinalizeSqlScriptAndSqlStringTables(tables); | ||
| 69 | } | ||
| 70 | |||
| 71 | /// <summary> | ||
| 72 | /// Decompile the SqlDatabase table. | ||
| 73 | /// </summary> | ||
| 74 | /// <param name="table">The table to decompile.</param> | ||
| 75 | private void DecompileSqlDatabaseTable(Table table) | ||
| 76 | { | ||
| 77 | foreach (Row row in table.Rows) | ||
| 78 | { | ||
| 79 | Sql.SqlDatabase sqlDatabase = new Sql.SqlDatabase(); | ||
| 80 | |||
| 81 | sqlDatabase.Id = (string)row[0]; | ||
| 82 | |||
| 83 | if (null != row[1]) | ||
| 84 | { | ||
| 85 | sqlDatabase.Server = (string)row[1]; | ||
| 86 | } | ||
| 87 | |||
| 88 | if (null != row[2]) | ||
| 89 | { | ||
| 90 | sqlDatabase.Instance = (string)row[2]; | ||
| 91 | } | ||
| 92 | |||
| 93 | sqlDatabase.Database = (string)row[3]; | ||
| 94 | |||
| 95 | if (null != row[5]) | ||
| 96 | { | ||
| 97 | sqlDatabase.User = (string)row[5]; | ||
| 98 | } | ||
| 99 | |||
| 100 | // the FileSpec_ and FileSpec_Log columns will be handled in FinalizeSqlFileSpecTable | ||
| 101 | |||
| 102 | if (null != row[8]) | ||
| 103 | { | ||
| 104 | int attributes = (int)row[8]; | ||
| 105 | |||
| 106 | if (SqlCompiler.DbCreateOnInstall == (attributes & SqlCompiler.DbCreateOnInstall)) | ||
| 107 | { | ||
| 108 | sqlDatabase.CreateOnInstall = Sql.YesNoType.yes; | ||
| 109 | } | ||
| 110 | |||
| 111 | if (SqlCompiler.DbDropOnUninstall == (attributes & SqlCompiler.DbDropOnUninstall)) | ||
| 112 | { | ||
| 113 | sqlDatabase.DropOnUninstall = Sql.YesNoType.yes; | ||
| 114 | } | ||
| 115 | |||
| 116 | if (SqlCompiler.DbContinueOnError == (attributes & SqlCompiler.DbContinueOnError)) | ||
| 117 | { | ||
| 118 | sqlDatabase.ContinueOnError = Sql.YesNoType.yes; | ||
| 119 | } | ||
| 120 | |||
| 121 | if (SqlCompiler.DbDropOnInstall == (attributes & SqlCompiler.DbDropOnInstall)) | ||
| 122 | { | ||
| 123 | sqlDatabase.DropOnInstall = Sql.YesNoType.yes; | ||
| 124 | } | ||
| 125 | |||
| 126 | if (SqlCompiler.DbCreateOnUninstall == (attributes & SqlCompiler.DbCreateOnUninstall)) | ||
| 127 | { | ||
| 128 | sqlDatabase.CreateOnUninstall = Sql.YesNoType.yes; | ||
| 129 | } | ||
| 130 | |||
| 131 | if (SqlCompiler.DbConfirmOverwrite == (attributes & SqlCompiler.DbConfirmOverwrite)) | ||
| 132 | { | ||
| 133 | sqlDatabase.ConfirmOverwrite = Sql.YesNoType.yes; | ||
| 134 | } | ||
| 135 | |||
| 136 | if (SqlCompiler.DbCreateOnReinstall == (attributes & SqlCompiler.DbCreateOnReinstall)) | ||
| 137 | { | ||
| 138 | sqlDatabase.CreateOnReinstall = Sql.YesNoType.yes; | ||
| 139 | } | ||
| 140 | |||
| 141 | if (SqlCompiler.DbDropOnReinstall == (attributes & SqlCompiler.DbDropOnReinstall)) | ||
| 142 | { | ||
| 143 | sqlDatabase.DropOnReinstall = Sql.YesNoType.yes; | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 147 | if (null != row[4]) | ||
| 148 | { | ||
| 149 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[4]); | ||
| 150 | |||
| 151 | if (null != component) | ||
| 152 | { | ||
| 153 | component.AddChild(sqlDatabase); | ||
| 154 | } | ||
| 155 | else | ||
| 156 | { | ||
| 157 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[4], "Component")); | ||
| 158 | } | ||
| 159 | } | ||
| 160 | else | ||
| 161 | { | ||
| 162 | this.Core.RootElement.AddChild(sqlDatabase); | ||
| 163 | } | ||
| 164 | this.Core.IndexElement(row, sqlDatabase); | ||
| 165 | } | ||
| 166 | } | ||
| 167 | |||
| 168 | /// <summary> | ||
| 169 | /// Decompile the SqlScript table. | ||
| 170 | /// </summary> | ||
| 171 | /// <param name="table">The table to decompile.</param> | ||
| 172 | private void DecompileSqlScriptTable(Table table) | ||
| 173 | { | ||
| 174 | foreach (Row row in table.Rows) | ||
| 175 | { | ||
| 176 | Sql.SqlScript sqlScript = new Sql.SqlScript(); | ||
| 177 | |||
| 178 | sqlScript.Id = (string)row[0]; | ||
| 179 | |||
| 180 | // the Db_ and Component_ columns are handled in FinalizeSqlScriptAndSqlStringTables | ||
| 181 | |||
| 182 | sqlScript.BinaryKey = (string)row[3]; | ||
| 183 | |||
| 184 | if (null != row[4]) | ||
| 185 | { | ||
| 186 | sqlScript.User = (string)row[4]; | ||
| 187 | } | ||
| 188 | |||
| 189 | int attributes = (int)row[5]; | ||
| 190 | |||
| 191 | if (SqlCompiler.SqlContinueOnError == (attributes & SqlCompiler.SqlContinueOnError)) | ||
| 192 | { | ||
| 193 | sqlScript.ContinueOnError = Sql.YesNoType.yes; | ||
| 194 | } | ||
| 195 | |||
| 196 | if (SqlCompiler.SqlExecuteOnInstall == (attributes & SqlCompiler.SqlExecuteOnInstall)) | ||
| 197 | { | ||
| 198 | sqlScript.ExecuteOnInstall = Sql.YesNoType.yes; | ||
| 199 | } | ||
| 200 | |||
| 201 | if (SqlCompiler.SqlExecuteOnReinstall == (attributes & SqlCompiler.SqlExecuteOnReinstall)) | ||
| 202 | { | ||
| 203 | sqlScript.ExecuteOnReinstall = Sql.YesNoType.yes; | ||
| 204 | } | ||
| 205 | |||
| 206 | if (SqlCompiler.SqlExecuteOnUninstall == (attributes & SqlCompiler.SqlExecuteOnUninstall)) | ||
| 207 | { | ||
| 208 | sqlScript.ExecuteOnUninstall = Sql.YesNoType.yes; | ||
| 209 | } | ||
| 210 | |||
| 211 | if ((SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnInstall) == (attributes & (SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnInstall))) | ||
| 212 | { | ||
| 213 | sqlScript.RollbackOnInstall = Sql.YesNoType.yes; | ||
| 214 | } | ||
| 215 | |||
| 216 | if ((SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnReinstall) == (attributes & (SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnReinstall))) | ||
| 217 | { | ||
| 218 | sqlScript.RollbackOnReinstall = Sql.YesNoType.yes; | ||
| 219 | } | ||
| 220 | |||
| 221 | if ((SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnUninstall) == (attributes & (SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnUninstall))) | ||
| 222 | { | ||
| 223 | sqlScript.RollbackOnUninstall = Sql.YesNoType.yes; | ||
| 224 | } | ||
| 225 | |||
| 226 | if (null != row[6]) | ||
| 227 | { | ||
| 228 | sqlScript.Sequence = (int)row[6]; | ||
| 229 | } | ||
| 230 | |||
| 231 | this.Core.IndexElement(row, sqlScript); | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | /// <summary> | ||
| 236 | /// Decompile the SqlString table. | ||
| 237 | /// </summary> | ||
| 238 | /// <param name="table">The table to decompile.</param> | ||
| 239 | private void DecompileSqlStringTable(Table table) | ||
| 240 | { | ||
| 241 | foreach (Row row in table.Rows) | ||
| 242 | { | ||
| 243 | Sql.SqlString sqlString = new Sql.SqlString(); | ||
| 244 | |||
| 245 | sqlString.Id = (string)row[0]; | ||
| 246 | |||
| 247 | // the Db_ and Component_ columns are handled in FinalizeSqlScriptAndSqlStringTables | ||
| 248 | |||
| 249 | sqlString.SQL = (string)row[3]; | ||
| 250 | |||
| 251 | if (null != row[4]) | ||
| 252 | { | ||
| 253 | sqlString.User = (string)row[4]; | ||
| 254 | } | ||
| 255 | |||
| 256 | int attributes = (int)row[5]; | ||
| 257 | |||
| 258 | if (SqlCompiler.SqlContinueOnError == (attributes & SqlCompiler.SqlContinueOnError)) | ||
| 259 | { | ||
| 260 | sqlString.ContinueOnError = Sql.YesNoType.yes; | ||
| 261 | } | ||
| 262 | |||
| 263 | if (SqlCompiler.SqlExecuteOnInstall == (attributes & SqlCompiler.SqlExecuteOnInstall)) | ||
| 264 | { | ||
| 265 | sqlString.ExecuteOnInstall = Sql.YesNoType.yes; | ||
| 266 | } | ||
| 267 | |||
| 268 | if (SqlCompiler.SqlExecuteOnReinstall == (attributes & SqlCompiler.SqlExecuteOnReinstall)) | ||
| 269 | { | ||
| 270 | sqlString.ExecuteOnReinstall = Sql.YesNoType.yes; | ||
| 271 | } | ||
| 272 | |||
| 273 | if (SqlCompiler.SqlExecuteOnUninstall == (attributes & SqlCompiler.SqlExecuteOnUninstall)) | ||
| 274 | { | ||
| 275 | sqlString.ExecuteOnUninstall = Sql.YesNoType.yes; | ||
| 276 | } | ||
| 277 | |||
| 278 | if ((SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnInstall) == (attributes & (SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnInstall))) | ||
| 279 | { | ||
| 280 | sqlString.RollbackOnInstall = Sql.YesNoType.yes; | ||
| 281 | } | ||
| 282 | |||
| 283 | if ((SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnReinstall) == (attributes & (SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnReinstall))) | ||
| 284 | { | ||
| 285 | sqlString.RollbackOnReinstall = Sql.YesNoType.yes; | ||
| 286 | } | ||
| 287 | |||
| 288 | if ((SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnUninstall) == (attributes & (SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnUninstall))) | ||
| 289 | { | ||
| 290 | sqlString.RollbackOnUninstall = Sql.YesNoType.yes; | ||
| 291 | } | ||
| 292 | |||
| 293 | if (null != row[6]) | ||
| 294 | { | ||
| 295 | sqlString.Sequence = (int)row[6]; | ||
| 296 | } | ||
| 297 | |||
| 298 | this.Core.IndexElement(row, sqlString); | ||
| 299 | } | ||
| 300 | } | ||
| 301 | |||
| 302 | /// <summary> | ||
| 303 | /// Finalize the SqlFileSpec table. | ||
| 304 | /// </summary> | ||
| 305 | /// <param name="tables">The collection of all tables.</param> | ||
| 306 | /// <remarks> | ||
| 307 | /// Since rows of the SqlFileSpec table are represented by either | ||
| 308 | /// the SqlFileSpec or SqlLogFileSpec depending upon the context in | ||
| 309 | /// which they are used in the SqlDatabase table, decompilation of this | ||
| 310 | /// table must occur after the SqlDatbase parents are decompiled. | ||
| 311 | /// </remarks> | ||
| 312 | private void FinalizeSqlFileSpecTable(TableIndexedCollection tables) | ||
| 313 | { | ||
| 314 | Table sqlDatabaseTable = tables["SqlDatabase"]; | ||
| 315 | Table sqlFileSpecTable = tables["SqlFileSpec"]; | ||
| 316 | |||
| 317 | if (null != sqlDatabaseTable && null != sqlFileSpecTable) | ||
| 318 | { | ||
| 319 | Hashtable sqlFileSpecRows = new Hashtable(); | ||
| 320 | |||
| 321 | // index each SqlFileSpec row by its primary key | ||
| 322 | foreach (Row row in sqlFileSpecTable.Rows) | ||
| 323 | { | ||
| 324 | sqlFileSpecRows.Add(row[0], row); | ||
| 325 | } | ||
| 326 | |||
| 327 | // create the necessary SqlFileSpec and SqlLogFileSpec elements for each row | ||
| 328 | foreach (Row row in sqlDatabaseTable.Rows) | ||
| 329 | { | ||
| 330 | Sql.SqlDatabase sqlDatabase = (Sql.SqlDatabase)this.Core.GetIndexedElement(row); | ||
| 331 | |||
| 332 | if (null != row[6]) | ||
| 333 | { | ||
| 334 | Row sqlFileSpecRow = (Row)sqlFileSpecRows[row[6]]; | ||
| 335 | |||
| 336 | if (null != sqlFileSpecRow) | ||
| 337 | { | ||
| 338 | Sql.SqlFileSpec sqlFileSpec = new Sql.SqlFileSpec(); | ||
| 339 | |||
| 340 | sqlFileSpec.Id = (string)sqlFileSpecRow[0]; | ||
| 341 | |||
| 342 | if (null != sqlFileSpecRow[1]) | ||
| 343 | { | ||
| 344 | sqlFileSpec.Name = (string)sqlFileSpecRow[1]; | ||
| 345 | } | ||
| 346 | |||
| 347 | sqlFileSpec.Filename = (string)sqlFileSpecRow[2]; | ||
| 348 | |||
| 349 | if (null != sqlFileSpecRow[3]) | ||
| 350 | { | ||
| 351 | sqlFileSpec.Size = (string)sqlFileSpecRow[3]; | ||
| 352 | } | ||
| 353 | |||
| 354 | if (null != sqlFileSpecRow[4]) | ||
| 355 | { | ||
| 356 | sqlFileSpec.MaxSize = (string)sqlFileSpecRow[4]; | ||
| 357 | } | ||
| 358 | |||
| 359 | if (null != sqlFileSpecRow[5]) | ||
| 360 | { | ||
| 361 | sqlFileSpec.GrowthSize = (string)sqlFileSpecRow[5]; | ||
| 362 | } | ||
| 363 | |||
| 364 | sqlDatabase.AddChild(sqlFileSpec); | ||
| 365 | } | ||
| 366 | else | ||
| 367 | { | ||
| 368 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, sqlDatabaseTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "FileSpec_", (string)row[6], "SqlFileSpec")); | ||
| 369 | } | ||
| 370 | } | ||
| 371 | |||
| 372 | if (null != row[7]) | ||
| 373 | { | ||
| 374 | Row sqlFileSpecRow = (Row)sqlFileSpecRows[row[7]]; | ||
| 375 | |||
| 376 | if (null != sqlFileSpecRow) | ||
| 377 | { | ||
| 378 | Sql.SqlLogFileSpec sqlLogFileSpec = new Sql.SqlLogFileSpec(); | ||
| 379 | |||
| 380 | sqlLogFileSpec.Id = (string)sqlFileSpecRow[0]; | ||
| 381 | |||
| 382 | if (null != sqlFileSpecRow[1]) | ||
| 383 | { | ||
| 384 | sqlLogFileSpec.Name = (string)sqlFileSpecRow[1]; | ||
| 385 | } | ||
| 386 | |||
| 387 | sqlLogFileSpec.Filename = (string)sqlFileSpecRow[2]; | ||
| 388 | |||
| 389 | if (null != sqlFileSpecRow[3]) | ||
| 390 | { | ||
| 391 | sqlLogFileSpec.Size = (string)sqlFileSpecRow[3]; | ||
| 392 | } | ||
| 393 | |||
| 394 | if (null != sqlFileSpecRow[4]) | ||
| 395 | { | ||
| 396 | sqlLogFileSpec.MaxSize = (string)sqlFileSpecRow[4]; | ||
| 397 | } | ||
| 398 | |||
| 399 | if (null != sqlFileSpecRow[5]) | ||
| 400 | { | ||
| 401 | sqlLogFileSpec.GrowthSize = (string)sqlFileSpecRow[5]; | ||
| 402 | } | ||
| 403 | |||
| 404 | sqlDatabase.AddChild(sqlLogFileSpec); | ||
| 405 | } | ||
| 406 | else | ||
| 407 | { | ||
| 408 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, sqlDatabaseTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "FileSpec_Log", (string)row[7], "SqlFileSpec")); | ||
| 409 | } | ||
| 410 | } | ||
| 411 | } | ||
| 412 | } | ||
| 413 | } | ||
| 414 | |||
| 415 | /// <summary> | ||
| 416 | /// Finalize the SqlScript table. | ||
| 417 | /// </summary> | ||
| 418 | /// <param name="tables">The collection of all tables.</param> | ||
| 419 | /// <remarks> | ||
| 420 | /// The SqlScript and SqlString tables contain a foreign key into the SqlDatabase | ||
| 421 | /// and Component tables. Depending upon the parent of the SqlDatabase | ||
| 422 | /// element, the SqlScript and SqlString elements are nested under either the | ||
| 423 | /// SqlDatabase or the Component element. | ||
| 424 | /// </remarks> | ||
| 425 | private void FinalizeSqlScriptAndSqlStringTables(TableIndexedCollection tables) | ||
| 426 | { | ||
| 427 | Table sqlDatabaseTable = tables["SqlDatabase"]; | ||
| 428 | Table sqlScriptTable = tables["SqlScript"]; | ||
| 429 | Table sqlStringTable = tables["SqlString"]; | ||
| 430 | |||
| 431 | Hashtable sqlDatabaseRows = new Hashtable(); | ||
| 432 | |||
| 433 | // index each SqlDatabase row by its primary key | ||
| 434 | if (null != sqlDatabaseTable) | ||
| 435 | { | ||
| 436 | foreach (Row row in sqlDatabaseTable.Rows) | ||
| 437 | { | ||
| 438 | sqlDatabaseRows.Add(row[0], row); | ||
| 439 | } | ||
| 440 | } | ||
| 441 | |||
| 442 | if (null != sqlScriptTable) | ||
| 443 | { | ||
| 444 | foreach (Row row in sqlScriptTable.Rows) | ||
| 445 | { | ||
| 446 | Sql.SqlScript sqlScript = (Sql.SqlScript)this.Core.GetIndexedElement(row); | ||
| 447 | |||
| 448 | Row sqlDatabaseRow = (Row)sqlDatabaseRows[row[1]]; | ||
| 449 | string databaseComponent = (string)sqlDatabaseRow[4]; | ||
| 450 | |||
| 451 | // determine if the SqlScript element should be nested under the database or another component | ||
| 452 | if (null != databaseComponent && databaseComponent == (string)row[2]) | ||
| 453 | { | ||
| 454 | Sql.SqlDatabase sqlDatabase = (Sql.SqlDatabase)this.Core.GetIndexedElement(sqlDatabaseRow); | ||
| 455 | |||
| 456 | sqlDatabase.AddChild(sqlScript); | ||
| 457 | } | ||
| 458 | else // nest under the component of the SqlDatabase row | ||
| 459 | { | ||
| 460 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
| 461 | |||
| 462 | // set the Database value | ||
| 463 | sqlScript.SqlDb = (string)row[1]; | ||
| 464 | |||
| 465 | if (null != component) | ||
| 466 | { | ||
| 467 | component.AddChild(sqlScript); | ||
| 468 | } | ||
| 469 | else | ||
| 470 | { | ||
| 471 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, sqlScriptTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
| 472 | } | ||
| 473 | } | ||
| 474 | } | ||
| 475 | } | ||
| 476 | |||
| 477 | if (null != sqlStringTable) | ||
| 478 | { | ||
| 479 | foreach (Row row in sqlStringTable.Rows) | ||
| 480 | { | ||
| 481 | Sql.SqlString sqlString = (Sql.SqlString)this.Core.GetIndexedElement(row); | ||
| 482 | |||
| 483 | Row sqlDatabaseRow = (Row)sqlDatabaseRows[row[1]]; | ||
| 484 | string databaseComponent = (string)sqlDatabaseRow[4]; | ||
| 485 | |||
| 486 | // determine if the SqlScript element should be nested under the database or another component | ||
| 487 | if (null != databaseComponent && databaseComponent == (string)row[2]) | ||
| 488 | { | ||
| 489 | Sql.SqlDatabase sqlDatabase = (Sql.SqlDatabase)this.Core.GetIndexedElement(sqlDatabaseRow); | ||
| 490 | |||
| 491 | sqlDatabase.AddChild(sqlString); | ||
| 492 | } | ||
| 493 | else // nest under the component of the SqlDatabase row | ||
| 494 | { | ||
| 495 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
| 496 | |||
| 497 | // set the Database value | ||
| 498 | sqlString.SqlDb = (string)row[1]; | ||
| 499 | |||
| 500 | if (null != component) | ||
| 501 | { | ||
| 502 | component.AddChild(sqlString); | ||
| 503 | } | ||
| 504 | else | ||
| 505 | { | ||
| 506 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, sqlStringTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
| 507 | } | ||
| 508 | } | ||
| 509 | } | ||
| 510 | } | ||
| 511 | } | ||
| 512 | } | ||
| 513 | #endif | ||
| 514 | } | ||
diff --git a/src/ext/Sql/wixext/SqlErrors.cs b/src/ext/Sql/wixext/SqlErrors.cs new file mode 100644 index 00000000..f25728bd --- /dev/null +++ b/src/ext/Sql/wixext/SqlErrors.cs | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Sql | ||
| 4 | { | ||
| 5 | using System.Resources; | ||
| 6 | using WixToolset.Data; | ||
| 7 | |||
| 8 | public static class SqlErrors | ||
| 9 | { | ||
| 10 | public static Message IllegalAttributeWithoutComponent(SourceLineNumber sourceLineNumbers, string elementName, string attributeName) | ||
| 11 | { | ||
| 12 | 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); | ||
| 13 | } | ||
| 14 | |||
| 15 | public static Message IllegalElementWithoutComponent(SourceLineNumber sourceLineNumbers, string elementName) | ||
| 16 | { | ||
| 17 | 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); | ||
| 18 | } | ||
| 19 | |||
| 20 | public static Message OneOfAttributesRequiredUnderComponent(SourceLineNumber sourceLineNumbers, string elementName, string attributeName1, string attributeName2, string attributeName3, string attributeName4) | ||
| 21 | { | ||
| 22 | return Message(sourceLineNumbers, Ids.OneOfAttributesRequiredUnderComponent, "When nested under a Component, the {0} element must have one of the following attributes specified: {1}, {2}, {3} or {4}.", elementName, attributeName1, attributeName2, attributeName3, attributeName4); | ||
| 23 | } | ||
| 24 | |||
| 25 | public static Message DeprecatedBinaryChildElement(SourceLineNumber sourceLineNumbers, string elementName) | ||
| 26 | { | ||
| 27 | return Message(sourceLineNumbers, Ids.DeprecatedBinaryChildElement, "The {0} element contains a deprecated child Binary element. Please move the Binary element under a Fragment, Module, or Product element and set the {0}/@BinaryKey attribute to the value of the Binary/@Id attribute.", elementName); | ||
| 28 | } | ||
| 29 | |||
| 30 | private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) | ||
| 31 | { | ||
| 32 | return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args); | ||
| 33 | } | ||
| 34 | |||
| 35 | private static Message Message(SourceLineNumber sourceLineNumber, Ids id, ResourceManager resourceManager, string resourceName, params object[] args) | ||
| 36 | { | ||
| 37 | return new Message(sourceLineNumber, MessageLevel.Error, (int)id, resourceManager, resourceName, args); | ||
| 38 | } | ||
| 39 | |||
| 40 | public enum Ids | ||
| 41 | { | ||
| 42 | IllegalAttributeWithoutComponent = 5100, | ||
| 43 | IllegalElementWithoutComponent = 5101, | ||
| 44 | OneOfAttributesRequiredUnderComponent = 5102, | ||
| 45 | DeprecatedBinaryChildElement = 5103, | ||
| 46 | } | ||
| 47 | } | ||
| 48 | } \ No newline at end of file | ||
diff --git a/src/ext/Sql/wixext/SqlExtensionData.cs b/src/ext/Sql/wixext/SqlExtensionData.cs new file mode 100644 index 00000000..60de94fe --- /dev/null +++ b/src/ext/Sql/wixext/SqlExtensionData.cs | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Sql | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Extensibility; | ||
| 7 | |||
| 8 | /// <summary> | ||
| 9 | /// The WiX Toolset SQL Server Extension. | ||
| 10 | /// </summary> | ||
| 11 | public sealed class SqlExtensionData : BaseExtensionData | ||
| 12 | { | ||
| 13 | /// <summary> | ||
| 14 | /// Gets the default culture. | ||
| 15 | /// </summary> | ||
| 16 | /// <value>The default culture.</value> | ||
| 17 | public override string DefaultCulture => "en-US"; | ||
| 18 | |||
| 19 | public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition) | ||
| 20 | { | ||
| 21 | symbolDefinition = SqlSymbolDefinitions.ByName(name); | ||
| 22 | return symbolDefinition != null; | ||
| 23 | } | ||
| 24 | |||
| 25 | public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions) | ||
| 26 | { | ||
| 27 | return Intermediate.Load(typeof(SqlExtensionData).Assembly, "WixToolset.Sql.sql.wixlib", symbolDefinitions); | ||
| 28 | } | ||
| 29 | } | ||
| 30 | } | ||
diff --git a/src/ext/Sql/wixext/SqlExtensionFactory.cs b/src/ext/Sql/wixext/SqlExtensionFactory.cs new file mode 100644 index 00000000..279106d3 --- /dev/null +++ b/src/ext/Sql/wixext/SqlExtensionFactory.cs | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Sql | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Collections.Generic; | ||
| 7 | using WixToolset.Extensibility; | ||
| 8 | |||
| 9 | public class SqlExtensionFactory : BaseExtensionFactory | ||
| 10 | { | ||
| 11 | protected override IReadOnlyCollection<Type> ExtensionTypes => new[] | ||
| 12 | { | ||
| 13 | typeof(SqlCompiler), | ||
| 14 | typeof(SqlExtensionData), | ||
| 15 | typeof(SqlWindowsInstallerBackendBinderExtension), | ||
| 16 | }; | ||
| 17 | } | ||
| 18 | } | ||
diff --git a/src/ext/Sql/wixext/SqlTableDefinitions.cs b/src/ext/Sql/wixext/SqlTableDefinitions.cs new file mode 100644 index 00000000..029a092e --- /dev/null +++ b/src/ext/Sql/wixext/SqlTableDefinitions.cs | |||
| @@ -0,0 +1,82 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Sql | ||
| 4 | { | ||
| 5 | using WixToolset.Data.WindowsInstaller; | ||
| 6 | |||
| 7 | public static class SqlTableDefinitions | ||
| 8 | { | ||
| 9 | public static readonly TableDefinition SqlDatabase = new TableDefinition( | ||
| 10 | "Wix4SqlDatabase", | ||
| 11 | SqlSymbolDefinitions.SqlDatabase, | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new ColumnDefinition("SqlDb", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column), | ||
| 15 | new ColumnDefinition("Server", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Primary key, name of server running SQL Server"), | ||
| 16 | new ColumnDefinition("Instance", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Primary key, name of SQL Server instance"), | ||
| 17 | new ColumnDefinition("Database", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Primary key, name of database in a SQL Server"), | ||
| 18 | new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key, Component used to determine install state ", modularizeType: ColumnModularizeType.Column), | ||
| 19 | new ColumnDefinition("User_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "User", keyColumn: 1, description: "Foreign key, User used to log into database", modularizeType: ColumnModularizeType.Column), | ||
| 20 | new ColumnDefinition("FileSpec_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "Wix4SqlFileSpec", keyColumn: 1, description: "Foreign key referencing SqlFileSpec.", modularizeType: ColumnModularizeType.Column), | ||
| 21 | new ColumnDefinition("FileSpec_Log", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "Wix4SqlFileSpec", keyColumn: 1, description: "Foreign key referencing SqlFileSpec.", modularizeType: ColumnModularizeType.Column), | ||
| 22 | new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, minValue: 0, maxValue: 255, description: "1 == create on install, 2 == drop on uninstall, 4 == continue on error, 8 == drop on install, 16 == create on uninstall, 32 == confirm update existing table, 64 == create on reinstall, 128 == drop on reinstall"), | ||
| 23 | }, | ||
| 24 | symbolIdIsPrimaryKey: true | ||
| 25 | ); | ||
| 26 | |||
| 27 | public static readonly TableDefinition SqlFileSpec = new TableDefinition( | ||
| 28 | "Wix4SqlFileSpec", | ||
| 29 | SqlSymbolDefinitions.SqlFileSpec, | ||
| 30 | new[] | ||
| 31 | { | ||
| 32 | new ColumnDefinition("FileSpec", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column), | ||
| 33 | new ColumnDefinition("Name", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Logical name of filespec", modularizeType: ColumnModularizeType.Property), | ||
| 34 | new ColumnDefinition("Filename", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Filename to use (path must exist)", modularizeType: ColumnModularizeType.Property), | ||
| 35 | new ColumnDefinition("Size", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Initial size for file", modularizeType: ColumnModularizeType.Property), | ||
| 36 | new ColumnDefinition("MaxSize", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Maximum size for file", modularizeType: ColumnModularizeType.Property), | ||
| 37 | new ColumnDefinition("GrowthSize", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Size file should grow when necessary", modularizeType: ColumnModularizeType.Property), | ||
| 38 | }, | ||
| 39 | symbolIdIsPrimaryKey: true | ||
| 40 | ); | ||
| 41 | |||
| 42 | public static readonly TableDefinition SqlScript = new TableDefinition( | ||
| 43 | "Wix4SqlScript", | ||
| 44 | SqlSymbolDefinitions.SqlScript, | ||
| 45 | new[] | ||
| 46 | { | ||
| 47 | new ColumnDefinition("Script", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token"), | ||
| 48 | new ColumnDefinition("SqlDb_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Wix4SqlDatabase", keyColumn: 1, description: "Foreign key, SQL Server key", modularizeType: ColumnModularizeType.Column), | ||
| 49 | 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), | ||
| 50 | new ColumnDefinition("ScriptBinary_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Binary", keyColumn: 1, description: "Foreign key, Binary stream that contains SQL Script to execute", modularizeType: ColumnModularizeType.Column), | ||
| 51 | new ColumnDefinition("User_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "User", keyColumn: 1, description: "Foreign key, User used to log into database", modularizeType: ColumnModularizeType.Column), | ||
| 52 | new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, possibilities: "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31", description: "1 == execute on install, 2 == execute on uninstall, 4 == continue on error, 8 == rollback on install, 16 == rollback on uninstall"), | ||
| 53 | new ColumnDefinition("Sequence", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Order to execute SQL Queries in"), | ||
| 54 | }, | ||
| 55 | symbolIdIsPrimaryKey: true | ||
| 56 | ); | ||
| 57 | |||
| 58 | public static readonly TableDefinition SqlString = new TableDefinition( | ||
| 59 | "Wix4SqlString", | ||
| 60 | SqlSymbolDefinitions.SqlString, | ||
| 61 | new[] | ||
| 62 | { | ||
| 63 | new ColumnDefinition("String", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Id for the Wix4SqlString", modularizeType: ColumnModularizeType.Column), | ||
| 64 | new ColumnDefinition("SqlDb_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Wix4SqlDatabase", keyColumn: 1, description: "Foreign key, SQL Server key", modularizeType: ColumnModularizeType.Column), | ||
| 65 | 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), | ||
| 66 | new ColumnDefinition("SQL", ColumnType.String, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "SQL query to execute"), | ||
| 67 | new ColumnDefinition("User_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "User", keyColumn: 1, description: "Foreign key, User used to log into database", modularizeType: ColumnModularizeType.Column), | ||
| 68 | new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, possibilities: "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31", description: "1 == execute on install, 2 == execute on uninstall, 4 == continue on error, 8 == rollback on install, 16 == rollback on uninstall"), | ||
| 69 | new ColumnDefinition("Sequence", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Order to execute SQL Queries in"), | ||
| 70 | }, | ||
| 71 | symbolIdIsPrimaryKey: true | ||
| 72 | ); | ||
| 73 | |||
| 74 | public static readonly TableDefinition[] All = new[] | ||
| 75 | { | ||
| 76 | SqlDatabase, | ||
| 77 | SqlFileSpec, | ||
| 78 | SqlScript, | ||
| 79 | SqlString, | ||
| 80 | }; | ||
| 81 | } | ||
| 82 | } | ||
diff --git a/src/ext/Sql/wixext/SqlWindowsInstallerBackendExtension.cs b/src/ext/Sql/wixext/SqlWindowsInstallerBackendExtension.cs new file mode 100644 index 00000000..2ccdcc56 --- /dev/null +++ b/src/ext/Sql/wixext/SqlWindowsInstallerBackendExtension.cs | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Sql | ||
| 4 | { | ||
| 5 | using System.Collections.Generic; | ||
| 6 | using WixToolset.Data.WindowsInstaller; | ||
| 7 | using WixToolset.Extensibility; | ||
| 8 | |||
| 9 | public class SqlWindowsInstallerBackendBinderExtension : BaseWindowsInstallerBackendBinderExtension | ||
| 10 | { | ||
| 11 | public override IReadOnlyCollection<TableDefinition> TableDefinitions => SqlTableDefinitions.All; | ||
| 12 | } | ||
| 13 | } | ||
diff --git a/src/ext/Sql/wixext/Symbols/SqlDatabaseSymbol.cs b/src/ext/Sql/wixext/Symbols/SqlDatabaseSymbol.cs new file mode 100644 index 00000000..6f0820ac --- /dev/null +++ b/src/ext/Sql/wixext/Symbols/SqlDatabaseSymbol.cs | |||
| @@ -0,0 +1,103 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Sql | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Sql.Symbols; | ||
| 7 | |||
| 8 | public static partial class SqlSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition SqlDatabase = new IntermediateSymbolDefinition( | ||
| 11 | SqlSymbolDefinitionType.SqlDatabase.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(SqlDatabaseSymbolFields.Server), IntermediateFieldType.String), | ||
| 15 | new IntermediateFieldDefinition(nameof(SqlDatabaseSymbolFields.Instance), IntermediateFieldType.String), | ||
| 16 | new IntermediateFieldDefinition(nameof(SqlDatabaseSymbolFields.Database), IntermediateFieldType.String), | ||
| 17 | new IntermediateFieldDefinition(nameof(SqlDatabaseSymbolFields.ComponentRef), IntermediateFieldType.String), | ||
| 18 | new IntermediateFieldDefinition(nameof(SqlDatabaseSymbolFields.UserRef), IntermediateFieldType.String), | ||
| 19 | new IntermediateFieldDefinition(nameof(SqlDatabaseSymbolFields.FileSpecRef), IntermediateFieldType.String), | ||
| 20 | new IntermediateFieldDefinition(nameof(SqlDatabaseSymbolFields.LogFileSpecRef), IntermediateFieldType.String), | ||
| 21 | new IntermediateFieldDefinition(nameof(SqlDatabaseSymbolFields.Attributes), IntermediateFieldType.Number), | ||
| 22 | }, | ||
| 23 | typeof(SqlDatabaseSymbol)); | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | namespace WixToolset.Sql.Symbols | ||
| 28 | { | ||
| 29 | using WixToolset.Data; | ||
| 30 | |||
| 31 | public enum SqlDatabaseSymbolFields | ||
| 32 | { | ||
| 33 | Server, | ||
| 34 | Instance, | ||
| 35 | Database, | ||
| 36 | ComponentRef, | ||
| 37 | UserRef, | ||
| 38 | FileSpecRef, | ||
| 39 | LogFileSpecRef, | ||
| 40 | Attributes, | ||
| 41 | } | ||
| 42 | |||
| 43 | public class SqlDatabaseSymbol : IntermediateSymbol | ||
| 44 | { | ||
| 45 | public SqlDatabaseSymbol() : base(SqlSymbolDefinitions.SqlDatabase, null, null) | ||
| 46 | { | ||
| 47 | } | ||
| 48 | |||
| 49 | public SqlDatabaseSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(SqlSymbolDefinitions.SqlDatabase, sourceLineNumber, id) | ||
| 50 | { | ||
| 51 | } | ||
| 52 | |||
| 53 | public IntermediateField this[SqlDatabaseSymbolFields index] => this.Fields[(int)index]; | ||
| 54 | |||
| 55 | public string Server | ||
| 56 | { | ||
| 57 | get => this.Fields[(int)SqlDatabaseSymbolFields.Server].AsString(); | ||
| 58 | set => this.Set((int)SqlDatabaseSymbolFields.Server, value); | ||
| 59 | } | ||
| 60 | |||
| 61 | public string Instance | ||
| 62 | { | ||
| 63 | get => this.Fields[(int)SqlDatabaseSymbolFields.Instance].AsString(); | ||
| 64 | set => this.Set((int)SqlDatabaseSymbolFields.Instance, value); | ||
| 65 | } | ||
| 66 | |||
| 67 | public string Database | ||
| 68 | { | ||
| 69 | get => this.Fields[(int)SqlDatabaseSymbolFields.Database].AsString(); | ||
| 70 | set => this.Set((int)SqlDatabaseSymbolFields.Database, value); | ||
| 71 | } | ||
| 72 | |||
| 73 | public string ComponentRef | ||
| 74 | { | ||
| 75 | get => this.Fields[(int)SqlDatabaseSymbolFields.ComponentRef].AsString(); | ||
| 76 | set => this.Set((int)SqlDatabaseSymbolFields.ComponentRef, value); | ||
| 77 | } | ||
| 78 | |||
| 79 | public string UserRef | ||
| 80 | { | ||
| 81 | get => this.Fields[(int)SqlDatabaseSymbolFields.UserRef].AsString(); | ||
| 82 | set => this.Set((int)SqlDatabaseSymbolFields.UserRef, value); | ||
| 83 | } | ||
| 84 | |||
| 85 | public string FileSpecRef | ||
| 86 | { | ||
| 87 | get => this.Fields[(int)SqlDatabaseSymbolFields.FileSpecRef].AsString(); | ||
| 88 | set => this.Set((int)SqlDatabaseSymbolFields.FileSpecRef, value); | ||
| 89 | } | ||
| 90 | |||
| 91 | public string LogFileSpecRef | ||
| 92 | { | ||
| 93 | get => this.Fields[(int)SqlDatabaseSymbolFields.LogFileSpecRef].AsString(); | ||
| 94 | set => this.Set((int)SqlDatabaseSymbolFields.LogFileSpecRef, value); | ||
| 95 | } | ||
| 96 | |||
| 97 | public int Attributes | ||
| 98 | { | ||
| 99 | get => this.Fields[(int)SqlDatabaseSymbolFields.Attributes].AsNumber(); | ||
| 100 | set => this.Set((int)SqlDatabaseSymbolFields.Attributes, value); | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } \ No newline at end of file | ||
diff --git a/src/ext/Sql/wixext/Symbols/SqlFileSpecSymbol.cs b/src/ext/Sql/wixext/Symbols/SqlFileSpecSymbol.cs new file mode 100644 index 00000000..d9eecc62 --- /dev/null +++ b/src/ext/Sql/wixext/Symbols/SqlFileSpecSymbol.cs | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Sql | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Sql.Symbols; | ||
| 7 | |||
| 8 | public static partial class SqlSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition SqlFileSpec = new IntermediateSymbolDefinition( | ||
| 11 | SqlSymbolDefinitionType.SqlFileSpec.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(SqlFileSpecSymbolFields.Name), IntermediateFieldType.String), | ||
| 15 | new IntermediateFieldDefinition(nameof(SqlFileSpecSymbolFields.Filename), IntermediateFieldType.String), | ||
| 16 | new IntermediateFieldDefinition(nameof(SqlFileSpecSymbolFields.Size), IntermediateFieldType.String), | ||
| 17 | new IntermediateFieldDefinition(nameof(SqlFileSpecSymbolFields.MaxSize), IntermediateFieldType.String), | ||
| 18 | new IntermediateFieldDefinition(nameof(SqlFileSpecSymbolFields.GrowthSize), IntermediateFieldType.String), | ||
| 19 | }, | ||
| 20 | typeof(SqlFileSpecSymbol)); | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | namespace WixToolset.Sql.Symbols | ||
| 25 | { | ||
| 26 | using WixToolset.Data; | ||
| 27 | |||
| 28 | public enum SqlFileSpecSymbolFields | ||
| 29 | { | ||
| 30 | Name, | ||
| 31 | Filename, | ||
| 32 | Size, | ||
| 33 | MaxSize, | ||
| 34 | GrowthSize, | ||
| 35 | } | ||
| 36 | |||
| 37 | public class SqlFileSpecSymbol : IntermediateSymbol | ||
| 38 | { | ||
| 39 | public SqlFileSpecSymbol() : base(SqlSymbolDefinitions.SqlFileSpec, null, null) | ||
| 40 | { | ||
| 41 | } | ||
| 42 | |||
| 43 | public SqlFileSpecSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(SqlSymbolDefinitions.SqlFileSpec, sourceLineNumber, id) | ||
| 44 | { | ||
| 45 | } | ||
| 46 | |||
| 47 | public IntermediateField this[SqlFileSpecSymbolFields index] => this.Fields[(int)index]; | ||
| 48 | |||
| 49 | public string Name | ||
| 50 | { | ||
| 51 | get => this.Fields[(int)SqlFileSpecSymbolFields.Name].AsString(); | ||
| 52 | set => this.Set((int)SqlFileSpecSymbolFields.Name, value); | ||
| 53 | } | ||
| 54 | |||
| 55 | public string Filename | ||
| 56 | { | ||
| 57 | get => this.Fields[(int)SqlFileSpecSymbolFields.Filename].AsString(); | ||
| 58 | set => this.Set((int)SqlFileSpecSymbolFields.Filename, value); | ||
| 59 | } | ||
| 60 | |||
| 61 | public string Size | ||
| 62 | { | ||
| 63 | get => this.Fields[(int)SqlFileSpecSymbolFields.Size].AsString(); | ||
| 64 | set => this.Set((int)SqlFileSpecSymbolFields.Size, value); | ||
| 65 | } | ||
| 66 | |||
| 67 | public string MaxSize | ||
| 68 | { | ||
| 69 | get => this.Fields[(int)SqlFileSpecSymbolFields.MaxSize].AsString(); | ||
| 70 | set => this.Set((int)SqlFileSpecSymbolFields.MaxSize, value); | ||
| 71 | } | ||
| 72 | |||
| 73 | public string GrowthSize | ||
| 74 | { | ||
| 75 | get => this.Fields[(int)SqlFileSpecSymbolFields.GrowthSize].AsString(); | ||
| 76 | set => this.Set((int)SqlFileSpecSymbolFields.GrowthSize, value); | ||
| 77 | } | ||
| 78 | } | ||
| 79 | } \ No newline at end of file | ||
diff --git a/src/ext/Sql/wixext/Symbols/SqlScriptSymbol.cs b/src/ext/Sql/wixext/Symbols/SqlScriptSymbol.cs new file mode 100644 index 00000000..94c70390 --- /dev/null +++ b/src/ext/Sql/wixext/Symbols/SqlScriptSymbol.cs | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Sql | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Sql.Symbols; | ||
| 7 | |||
| 8 | public static partial class SqlSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition SqlScript = new IntermediateSymbolDefinition( | ||
| 11 | SqlSymbolDefinitionType.SqlScript.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(SqlScriptSymbolFields.SqlDbRef), IntermediateFieldType.String), | ||
| 15 | new IntermediateFieldDefinition(nameof(SqlScriptSymbolFields.ComponentRef), IntermediateFieldType.String), | ||
| 16 | new IntermediateFieldDefinition(nameof(SqlScriptSymbolFields.ScriptBinaryRef), IntermediateFieldType.String), | ||
| 17 | new IntermediateFieldDefinition(nameof(SqlScriptSymbolFields.UserRef), IntermediateFieldType.String), | ||
| 18 | new IntermediateFieldDefinition(nameof(SqlScriptSymbolFields.Attributes), IntermediateFieldType.Number), | ||
| 19 | new IntermediateFieldDefinition(nameof(SqlScriptSymbolFields.Sequence), IntermediateFieldType.Number), | ||
| 20 | }, | ||
| 21 | typeof(SqlScriptSymbol)); | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | namespace WixToolset.Sql.Symbols | ||
| 26 | { | ||
| 27 | using WixToolset.Data; | ||
| 28 | |||
| 29 | public enum SqlScriptSymbolFields | ||
| 30 | { | ||
| 31 | SqlDbRef, | ||
| 32 | ComponentRef, | ||
| 33 | ScriptBinaryRef, | ||
| 34 | UserRef, | ||
| 35 | Attributes, | ||
| 36 | Sequence, | ||
| 37 | } | ||
| 38 | |||
| 39 | public class SqlScriptSymbol : IntermediateSymbol | ||
| 40 | { | ||
| 41 | public SqlScriptSymbol() : base(SqlSymbolDefinitions.SqlScript, null, null) | ||
| 42 | { | ||
| 43 | } | ||
| 44 | |||
| 45 | public SqlScriptSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(SqlSymbolDefinitions.SqlScript, sourceLineNumber, id) | ||
| 46 | { | ||
| 47 | } | ||
| 48 | |||
| 49 | public IntermediateField this[SqlScriptSymbolFields index] => this.Fields[(int)index]; | ||
| 50 | |||
| 51 | public string SqlDbRef | ||
| 52 | { | ||
| 53 | get => this.Fields[(int)SqlScriptSymbolFields.SqlDbRef].AsString(); | ||
| 54 | set => this.Set((int)SqlScriptSymbolFields.SqlDbRef, value); | ||
| 55 | } | ||
| 56 | |||
| 57 | public string ComponentRef | ||
| 58 | { | ||
| 59 | get => this.Fields[(int)SqlScriptSymbolFields.ComponentRef].AsString(); | ||
| 60 | set => this.Set((int)SqlScriptSymbolFields.ComponentRef, value); | ||
| 61 | } | ||
| 62 | |||
| 63 | public string ScriptBinaryRef | ||
| 64 | { | ||
| 65 | get => this.Fields[(int)SqlScriptSymbolFields.ScriptBinaryRef].AsString(); | ||
| 66 | set => this.Set((int)SqlScriptSymbolFields.ScriptBinaryRef, value); | ||
| 67 | } | ||
| 68 | |||
| 69 | public string UserRef | ||
| 70 | { | ||
| 71 | get => this.Fields[(int)SqlScriptSymbolFields.UserRef].AsString(); | ||
| 72 | set => this.Set((int)SqlScriptSymbolFields.UserRef, value); | ||
| 73 | } | ||
| 74 | |||
| 75 | public int Attributes | ||
| 76 | { | ||
| 77 | get => this.Fields[(int)SqlScriptSymbolFields.Attributes].AsNumber(); | ||
| 78 | set => this.Set((int)SqlScriptSymbolFields.Attributes, value); | ||
| 79 | } | ||
| 80 | |||
| 81 | public int? Sequence | ||
| 82 | { | ||
| 83 | get => this.Fields[(int)SqlScriptSymbolFields.Sequence].AsNullableNumber(); | ||
| 84 | set => this.Set((int)SqlScriptSymbolFields.Sequence, value); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | } \ No newline at end of file | ||
diff --git a/src/ext/Sql/wixext/Symbols/SqlStringSymbol.cs b/src/ext/Sql/wixext/Symbols/SqlStringSymbol.cs new file mode 100644 index 00000000..73a8206e --- /dev/null +++ b/src/ext/Sql/wixext/Symbols/SqlStringSymbol.cs | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Sql | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Sql.Symbols; | ||
| 7 | |||
| 8 | public static partial class SqlSymbolDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateSymbolDefinition SqlString = new IntermediateSymbolDefinition( | ||
| 11 | SqlSymbolDefinitionType.SqlString.ToString(), | ||
| 12 | new[] | ||
| 13 | { | ||
| 14 | new IntermediateFieldDefinition(nameof(SqlStringSymbolFields.SqlDbRef), IntermediateFieldType.String), | ||
| 15 | new IntermediateFieldDefinition(nameof(SqlStringSymbolFields.ComponentRef), IntermediateFieldType.String), | ||
| 16 | new IntermediateFieldDefinition(nameof(SqlStringSymbolFields.SQL), IntermediateFieldType.String), | ||
| 17 | new IntermediateFieldDefinition(nameof(SqlStringSymbolFields.UserRef), IntermediateFieldType.String), | ||
| 18 | new IntermediateFieldDefinition(nameof(SqlStringSymbolFields.Attributes), IntermediateFieldType.Number), | ||
| 19 | new IntermediateFieldDefinition(nameof(SqlStringSymbolFields.Sequence), IntermediateFieldType.Number), | ||
| 20 | }, | ||
| 21 | typeof(SqlStringSymbol)); | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | namespace WixToolset.Sql.Symbols | ||
| 26 | { | ||
| 27 | using WixToolset.Data; | ||
| 28 | |||
| 29 | public enum SqlStringSymbolFields | ||
| 30 | { | ||
| 31 | SqlDbRef, | ||
| 32 | ComponentRef, | ||
| 33 | SQL, | ||
| 34 | UserRef, | ||
| 35 | Attributes, | ||
| 36 | Sequence, | ||
| 37 | } | ||
| 38 | |||
| 39 | public class SqlStringSymbol : IntermediateSymbol | ||
| 40 | { | ||
| 41 | public SqlStringSymbol() : base(SqlSymbolDefinitions.SqlString, null, null) | ||
| 42 | { | ||
| 43 | } | ||
| 44 | |||
| 45 | public SqlStringSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(SqlSymbolDefinitions.SqlString, sourceLineNumber, id) | ||
| 46 | { | ||
| 47 | } | ||
| 48 | |||
| 49 | public IntermediateField this[SqlStringSymbolFields index] => this.Fields[(int)index]; | ||
| 50 | |||
| 51 | public string SqlDbRef | ||
| 52 | { | ||
| 53 | get => this.Fields[(int)SqlStringSymbolFields.SqlDbRef].AsString(); | ||
| 54 | set => this.Set((int)SqlStringSymbolFields.SqlDbRef, value); | ||
| 55 | } | ||
| 56 | |||
| 57 | public string ComponentRef | ||
| 58 | { | ||
| 59 | get => this.Fields[(int)SqlStringSymbolFields.ComponentRef].AsString(); | ||
| 60 | set => this.Set((int)SqlStringSymbolFields.ComponentRef, value); | ||
| 61 | } | ||
| 62 | |||
| 63 | public string SQL | ||
| 64 | { | ||
| 65 | get => this.Fields[(int)SqlStringSymbolFields.SQL].AsString(); | ||
| 66 | set => this.Set((int)SqlStringSymbolFields.SQL, value); | ||
| 67 | } | ||
| 68 | |||
| 69 | public string UserRef | ||
| 70 | { | ||
| 71 | get => this.Fields[(int)SqlStringSymbolFields.UserRef].AsString(); | ||
| 72 | set => this.Set((int)SqlStringSymbolFields.UserRef, value); | ||
| 73 | } | ||
| 74 | |||
| 75 | public int Attributes | ||
| 76 | { | ||
| 77 | get => this.Fields[(int)SqlStringSymbolFields.Attributes].AsNumber(); | ||
| 78 | set => this.Set((int)SqlStringSymbolFields.Attributes, value); | ||
| 79 | } | ||
| 80 | |||
| 81 | public int? Sequence | ||
| 82 | { | ||
| 83 | get => this.Fields[(int)SqlStringSymbolFields.Sequence].AsNullableNumber(); | ||
| 84 | set => this.Set((int)SqlStringSymbolFields.Sequence, value); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | } \ No newline at end of file | ||
diff --git a/src/ext/Sql/wixext/Symbols/SqlSymbolDefinitions.cs b/src/ext/Sql/wixext/Symbols/SqlSymbolDefinitions.cs new file mode 100644 index 00000000..336f1546 --- /dev/null +++ b/src/ext/Sql/wixext/Symbols/SqlSymbolDefinitions.cs | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Sql | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using WixToolset.Data; | ||
| 7 | |||
| 8 | public enum SqlSymbolDefinitionType | ||
| 9 | { | ||
| 10 | SqlDatabase, | ||
| 11 | SqlFileSpec, | ||
| 12 | SqlScript, | ||
| 13 | SqlString, | ||
| 14 | } | ||
| 15 | |||
| 16 | public static partial class SqlSymbolDefinitions | ||
| 17 | { | ||
| 18 | public static readonly Version Version = new Version("4.0.0"); | ||
| 19 | |||
| 20 | public static IntermediateSymbolDefinition ByName(string name) | ||
| 21 | { | ||
| 22 | if (!Enum.TryParse(name, out SqlSymbolDefinitionType type)) | ||
| 23 | { | ||
| 24 | return null; | ||
| 25 | } | ||
| 26 | |||
| 27 | return ByType(type); | ||
| 28 | } | ||
| 29 | |||
| 30 | public static IntermediateSymbolDefinition ByType(SqlSymbolDefinitionType type) | ||
| 31 | { | ||
| 32 | switch (type) | ||
| 33 | { | ||
| 34 | case SqlSymbolDefinitionType.SqlDatabase: | ||
| 35 | return SqlSymbolDefinitions.SqlDatabase; | ||
| 36 | |||
| 37 | case SqlSymbolDefinitionType.SqlFileSpec: | ||
| 38 | return SqlSymbolDefinitions.SqlFileSpec; | ||
| 39 | |||
| 40 | case SqlSymbolDefinitionType.SqlScript: | ||
| 41 | return SqlSymbolDefinitions.SqlScript; | ||
| 42 | |||
| 43 | case SqlSymbolDefinitionType.SqlString: | ||
| 44 | return SqlSymbolDefinitions.SqlString; | ||
| 45 | |||
| 46 | default: | ||
| 47 | throw new ArgumentOutOfRangeException(nameof(type)); | ||
| 48 | } | ||
| 49 | } | ||
| 50 | } | ||
| 51 | } | ||
diff --git a/src/ext/Sql/wixext/WixToolset.Sql.wixext.csproj b/src/ext/Sql/wixext/WixToolset.Sql.wixext.csproj new file mode 100644 index 00000000..5a1ebeb0 --- /dev/null +++ b/src/ext/Sql/wixext/WixToolset.Sql.wixext.csproj | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | |||
| 4 | <Project Sdk="Microsoft.NET.Sdk"> | ||
| 5 | <PropertyGroup> | ||
| 6 | <TargetFramework>netstandard2.0</TargetFramework> | ||
| 7 | <RootNamespace>WixToolset.Sql</RootNamespace> | ||
| 8 | <Description>WiX Toolset Sql Extension</Description> | ||
| 9 | <Title>WiX Toolset Sql Extension</Title> | ||
| 10 | <DebugType>embedded</DebugType> | ||
| 11 | <IncludeSymbols>true</IncludeSymbols> | ||
| 12 | </PropertyGroup> | ||
| 13 | |||
| 14 | <ItemGroup> | ||
| 15 | <EmbeddedResource Include="$(OutputPath)..\sql.wixlib" /> | ||
| 16 | </ItemGroup> | ||
| 17 | |||
| 18 | <ItemGroup> | ||
| 19 | <ProjectReference Include="..\wixlib\sql.wixproj" ReferenceOutputAssembly="false" Condition=" '$(NCrunch)'=='' " /> | ||
| 20 | </ItemGroup> | ||
| 21 | |||
| 22 | <ItemGroup> | ||
| 23 | <PackageReference Include="WixToolset.Extensibility" Version="4.0.*" PrivateAssets="All" /> | ||
| 24 | </ItemGroup> | ||
| 25 | |||
| 26 | <ItemGroup> | ||
| 27 | <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> | ||
| 28 | <PackageReference Include="Nerdbank.GitVersioning" Version="3.3.37" PrivateAssets="All" /> | ||
| 29 | </ItemGroup> | ||
| 30 | </Project> | ||
diff --git a/src/ext/Sql/wixext/WixToolset.Sql.wixext.nuspec b/src/ext/Sql/wixext/WixToolset.Sql.wixext.nuspec new file mode 100644 index 00000000..ba3eaade --- /dev/null +++ b/src/ext/Sql/wixext/WixToolset.Sql.wixext.nuspec | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | <?xml version="1.0"?> | ||
| 2 | <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> | ||
| 3 | <metadata minClientVersion="4.0"> | ||
| 4 | <id>$id$</id> | ||
| 5 | <version>$version$</version> | ||
| 6 | <title>$title$</title> | ||
| 7 | <description>$description$</description> | ||
| 8 | <authors>$authors$</authors> | ||
| 9 | <license type="expression">MS-RL</license> | ||
| 10 | <requireLicenseAcceptance>false</requireLicenseAcceptance> | ||
| 11 | <copyright>$copyright$</copyright> | ||
| 12 | <projectUrl>$projectUrl$</projectUrl> | ||
| 13 | <repository type="$repositorytype$" url="$repositoryurl$" commit="$repositorycommit$" /> | ||
| 14 | </metadata> | ||
| 15 | |||
| 16 | <files> | ||
| 17 | <file src="$projectFolder$$id$.targets" target="build" /> | ||
| 18 | |||
| 19 | <file src="netstandard2.0\$id$.dll" target="tools" /> | ||
| 20 | |||
| 21 | <file src="ARM64\*.pdb" target="pdbs\ARM64" /> | ||
| 22 | <file src="x86\*.pdb" target="pdbs\x86" /> | ||
| 23 | <file src="x64\*.pdb" target="pdbs\x64" /> | ||
| 24 | </files> | ||
| 25 | </package> | ||
diff --git a/src/ext/Sql/wixext/WixToolset.Sql.wixext.targets b/src/ext/Sql/wixext/WixToolset.Sql.wixext.targets new file mode 100644 index 00000000..4950e119 --- /dev/null +++ b/src/ext/Sql/wixext/WixToolset.Sql.wixext.targets | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | |||
| 4 | <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> | ||
| 5 | <PropertyGroup> | ||
| 6 | <WixToolsetSqlWixextPath Condition=" '$(WixToolsetSqlWixextPath)' == '' ">$(MSBuildThisFileDirectory)..\tools\WixToolset.Sql.wixext.dll</WixToolsetSqlWixextPath> | ||
| 7 | </PropertyGroup> | ||
| 8 | <ItemGroup> | ||
| 9 | <WixExtension Include="$(WixToolsetSqlWixextPath)" /> | ||
| 10 | </ItemGroup> | ||
| 11 | </Project> | ||
diff --git a/src/ext/Sql/wixlib/SqlExtension.wxi b/src/ext/Sql/wixlib/SqlExtension.wxi new file mode 100644 index 00000000..c9261f1d --- /dev/null +++ b/src/ext/Sql/wixlib/SqlExtension.wxi | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | <Include xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 4 | <?include caDecor.wxi ?> | ||
| 5 | |||
| 6 | <Fragment> | ||
| 7 | <UI> | ||
| 8 | <ProgressText Action="$(var.Prefix)InstallSqlData$(var.Suffix)" Message="!(loc.ConfigureSql)" /> | ||
| 9 | <ProgressText Action="$(var.Prefix)UninstallSqlData$(var.Suffix)" Message="!(loc.ConfigureSql)" /> | ||
| 10 | <ProgressText Action="$(var.Prefix)CreateDatabase$(var.Suffix)" Message="!(loc.CreateDatabase)" /> | ||
| 11 | <ProgressText Action="$(var.Prefix)DropDatabase$(var.Suffix)" Message="!(loc.DropDatabase)" /> | ||
| 12 | <ProgressText Action="$(var.Prefix)ExecuteSqlStrings$(var.Suffix)" Message="!(loc.ExecuteSqlStrings)" /> | ||
| 13 | <ProgressText Action="$(var.Prefix)RollbackExecuteSqlStrings$(var.Suffix)" Message="!(loc.RollbackExecuteSqlStrings)" /> | ||
| 14 | </UI> | ||
| 15 | |||
| 16 | <!-- The SQL custom actions impersonate the user because the user's credentials are used when connecting to the database if none are provided. --> | ||
| 17 | <CustomAction Id="$(var.Prefix)InstallSqlData$(var.Suffix)" DllEntry="InstallSqlData" Execute="immediate" Return="check" BinaryRef="SqlCA$(var.Suffix)" /> | ||
| 18 | <CustomAction Id="$(var.Prefix)UninstallSqlData$(var.Suffix)" DllEntry="UninstallSqlData" Execute="immediate" Return="check" BinaryRef="SqlCA$(var.Suffix)" /> | ||
| 19 | <CustomAction Id="$(var.Prefix)CreateDatabase$(var.Suffix)" DllEntry="CreateDatabase" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" TerminalServerAware="yes" BinaryRef="SqlCA$(var.Suffix)" /> | ||
| 20 | <CustomAction Id="$(var.Prefix)RollbackCreateDatabase$(var.Suffix)" DllEntry="DropDatabase" Execute="rollback" Return="check" HideTarget="yes" SuppressModularization="yes" TerminalServerAware="yes" BinaryRef="SqlCA$(var.Suffix)" /> | ||
| 21 | <CustomAction Id="$(var.Prefix)DropDatabase$(var.Suffix)" DllEntry="DropDatabase" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" TerminalServerAware="yes" BinaryRef="SqlCA$(var.Suffix)" /> | ||
| 22 | <CustomAction Id="$(var.Prefix)ExecuteSqlStrings$(var.Suffix)" DllEntry="ExecuteSqlStrings" Execute="deferred" Return="check" HideTarget="yes" SuppressModularization="yes" TerminalServerAware="yes" BinaryRef="SqlCA$(var.Suffix)" /> | ||
| 23 | <CustomAction Id="$(var.Prefix)RollbackExecuteSqlStrings$(var.Suffix)" DllEntry="ExecuteSqlStrings" Execute="rollback" Return="check" HideTarget="yes" SuppressModularization="yes" TerminalServerAware="yes" BinaryRef="SqlCA$(var.Suffix)" /> | ||
| 24 | |||
| 25 | <InstallExecuteSequence> | ||
| 26 | <Custom Action="$(var.Prefix)UninstallSqlData$(var.Suffix)" Before="RemoveFiles" Overridable="yes" Condition="NOT SKIPUNINSTALLSQLDATA AND VersionNT > 400" /> | ||
| 27 | <Custom Action="$(var.Prefix)InstallSqlData$(var.Suffix)" After="InstallFiles" Overridable="yes" Condition="NOT SKIPINSTALLSQLDATA AND VersionNT > 400" /> | ||
| 28 | </InstallExecuteSequence> | ||
| 29 | </Fragment> | ||
| 30 | |||
| 31 | <!-- Server Custom Action DLL Definitions --> | ||
| 32 | <Fragment> | ||
| 33 | <Binary Id="SqlCA$(var.Suffix)" SourceFile="!(bindpath.$(var.platform))sqlca.dll" /> | ||
| 34 | </Fragment> | ||
| 35 | </Include> | ||
diff --git a/src/ext/Sql/wixlib/SqlExtension.wxs b/src/ext/Sql/wixlib/SqlExtension.wxs new file mode 100644 index 00000000..8b5320fa --- /dev/null +++ b/src/ext/Sql/wixlib/SqlExtension.wxs | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 4 | <?include caerr.wxi ?> | ||
| 5 | |||
| 6 | <Fragment> | ||
| 7 | <UI> | ||
| 8 | <Error Id="$(var.msierrSQLFailedCreateDatabase)" Message="!(loc.msierrSQLFailedCreateDatabase)" /> | ||
| 9 | <Error Id="$(var.msierrSQLFailedDropDatabase)" Message="!(loc.msierrSQLFailedDropDatabase)" /> | ||
| 10 | <Error Id="$(var.msierrSQLFailedConnectDatabase)" Message="!(loc.msierrSQLFailedConnectDatabase)" /> | ||
| 11 | <Error Id="$(var.msierrSQLFailedExecString)" Message="!(loc.msierrSQLFailedExecString)" /> | ||
| 12 | <Error Id="$(var.msierrSQLDatabaseAlreadyExists)" Message="!(loc.msierrSQLDatabaseAlreadyExists)" /> | ||
| 13 | </UI> | ||
| 14 | </Fragment> | ||
| 15 | </Wix> | ||
diff --git a/src/ext/Sql/wixlib/SqlExtension_arm64.wxs b/src/ext/Sql/wixlib/SqlExtension_arm64.wxs new file mode 100644 index 00000000..e8d22f69 --- /dev/null +++ b/src/ext/Sql/wixlib/SqlExtension_arm64.wxs | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 5 | <?define platform=arm64 ?> | ||
| 6 | <?include SqlExtension.wxi ?> | ||
| 7 | </Wix> | ||
diff --git a/src/ext/Sql/wixlib/SqlExtension_x64.wxs b/src/ext/Sql/wixlib/SqlExtension_x64.wxs new file mode 100644 index 00000000..e55a14e4 --- /dev/null +++ b/src/ext/Sql/wixlib/SqlExtension_x64.wxs | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 5 | <?define platform=x64 ?> | ||
| 6 | <?include SqlExtension.wxi ?> | ||
| 7 | </Wix> | ||
diff --git a/src/ext/Sql/wixlib/SqlExtension_x86.wxs b/src/ext/Sql/wixlib/SqlExtension_x86.wxs new file mode 100644 index 00000000..1a51ed91 --- /dev/null +++ b/src/ext/Sql/wixlib/SqlExtension_x86.wxs | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 5 | <?define platform=x86 ?> | ||
| 6 | <?include SqlExtension.wxi ?> | ||
| 7 | </Wix> | ||
diff --git a/src/ext/Sql/wixlib/caDecor.wxi b/src/ext/Sql/wixlib/caDecor.wxi new file mode 100644 index 00000000..b1711518 --- /dev/null +++ b/src/ext/Sql/wixlib/caDecor.wxi | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <Include xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 5 | <?ifdef Prefix ?> | ||
| 6 | <?undef Prefix ?> | ||
| 7 | <?endif?> | ||
| 8 | |||
| 9 | <?define Prefix="Wix4" ?> | ||
| 10 | |||
| 11 | <?ifndef platform ?> | ||
| 12 | <?define platform="x86" ?> | ||
| 13 | <?endif?> | ||
| 14 | |||
| 15 | <?if $(var.platform)="" ?> | ||
| 16 | <?undef platform ?> | ||
| 17 | <?define platform="x86" ?> | ||
| 18 | <?endif?> | ||
| 19 | |||
| 20 | <?ifdef Suffix ?> | ||
| 21 | <?undef Suffix ?> | ||
| 22 | <?endif?> | ||
| 23 | |||
| 24 | <?if $(var.platform)~="x86" ?> | ||
| 25 | <?define Suffix="_X86" ?> | ||
| 26 | <?endif?> | ||
| 27 | |||
| 28 | <?if $(var.platform)~="x64" ?> | ||
| 29 | <?define Suffix="_X64" ?> | ||
| 30 | <?endif?> | ||
| 31 | |||
| 32 | <?if $(var.platform)~="arm" ?> | ||
| 33 | <?define Suffix="_A32" ?> | ||
| 34 | <?endif?> | ||
| 35 | |||
| 36 | <?if $(var.platform)~="arm64" ?> | ||
| 37 | <?define Suffix="_A64" ?> | ||
| 38 | <?endif?> | ||
| 39 | </Include> | ||
diff --git a/src/ext/Sql/wixlib/caerr.wxi b/src/ext/Sql/wixlib/caerr.wxi new file mode 100644 index 00000000..ff7ec121 --- /dev/null +++ b/src/ext/Sql/wixlib/caerr.wxi | |||
| @@ -0,0 +1,96 @@ | |||
| 1 | <Include xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 2 | <?define msierrSecureObjectsFailedCreateSD = 25520?> | ||
| 3 | <?define msierrSecureObjectsFailedSet = 25521?> | ||
| 4 | <?define msierrSecureObjectsUnknownType = 25522?> | ||
| 5 | <?define msierrXmlFileFailedRead = 25530?> | ||
| 6 | <?define msierrXmlFileFailedOpen = 25531?> | ||
| 7 | <?define msierrXmlFileFailedSelect = 25532?> | ||
| 8 | <?define msierrXmlFileFailedSave = 25533?> | ||
| 9 | <?define msierrXmlConfigFailedRead = 25540?> | ||
| 10 | <?define msierrXmlConfigFailedOpen = 25541?> | ||
| 11 | <?define msierrXmlConfigFailedSelect = 25542?> | ||
| 12 | <?define msierrXmlConfigFailedSave = 25543?> | ||
| 13 | <?define msierrFirewallCannotConnect = 25580?> | ||
| 14 | <?define msierrIISCannotConnect = 26001?> | ||
| 15 | <?define msierrIISFailedReadWebSite = 26002?> | ||
| 16 | <?define msierrIISFailedReadWebDirs = 26003?> | ||
| 17 | <?define msierrIISFailedReadVDirs = 26004?> | ||
| 18 | <?define msierrIISFailedReadFilters = 26005?> | ||
| 19 | <?define msierrIISFailedReadAppPool = 26006?> | ||
| 20 | <?define msierrIISFailedReadMimeMap = 26007?> | ||
| 21 | <?define msierrIISFailedReadProp = 26008?> | ||
| 22 | <?define msierrIISFailedReadWebSvcExt = 26009?> | ||
| 23 | <?define msierrIISFailedReadWebError = 26010?> | ||
| 24 | <?define msierrIISFailedReadHttpHeader = 26011?> | ||
| 25 | <?define msierrIISFailedSchedTransaction = 26031?> | ||
| 26 | <?define msierrIISFailedSchedInstallWebs = 26032?> | ||
| 27 | <?define msierrIISFailedSchedInstallWebDirs = 26033?> | ||
| 28 | <?define msierrIISFailedSchedInstallVDirs = 26034?> | ||
| 29 | <?define msierrIISFailedSchedInstallFilters = 26035?> | ||
| 30 | <?define msierrIISFailedSchedInstallAppPool = 26036?> | ||
| 31 | <?define msierrIISFailedSchedInstallProp = 26037?> | ||
| 32 | <?define msierrIISFailedSchedInstallWebSvcExt = 26038?> | ||
| 33 | <?define msierrIISFailedSchedUninstallWebs = 26051?> | ||
| 34 | <?define msierrIISFailedSchedUninstallWebDirs = 26052?> | ||
| 35 | <?define msierrIISFailedSchedUninstallVDirs = 26053?> | ||
| 36 | <?define msierrIISFailedSchedUninstallFilters = 26054?> | ||
| 37 | <?define msierrIISFailedSchedUninstallAppPool = 26055?> | ||
| 38 | <?define msierrIISFailedSchedUninstallProp = 26056?> | ||
| 39 | <?define msierrIISFailedSchedUninstallWebSvcExt = 26057?> | ||
| 40 | <?define msierrIISFailedStartTransaction = 26101?> | ||
| 41 | <?define msierrIISFailedOpenKey = 26102?> | ||
| 42 | <?define msierrIISFailedCreateKey = 26103?> | ||
| 43 | <?define msierrIISFailedWriteData = 26104?> | ||
| 44 | <?define msierrIISFailedCreateApp = 26105?> | ||
| 45 | <?define msierrIISFailedDeleteKey = 26106?> | ||
| 46 | <?define msierrIISFailedDeleteApp = 26107?> | ||
| 47 | <?define msierrIISFailedDeleteValue = 26108?> | ||
| 48 | <?define msierrIISFailedCommitInUse = 26109?> | ||
| 49 | <?define msierrSQLFailedCreateDatabase = 26201?> | ||
| 50 | <?define msierrSQLFailedDropDatabase = 26202?> | ||
| 51 | <?define msierrSQLFailedConnectDatabase = 26203?> | ||
| 52 | <?define msierrSQLFailedExecString = 26204?> | ||
| 53 | <?define msierrSQLDatabaseAlreadyExists = 26205?> | ||
| 54 | <?define msierrPERFMONFailedRegisterDLL = 26251?> | ||
| 55 | <?define msierrPERFMONFailedUnregisterDLL = 26252?> | ||
| 56 | <?define msierrInstallPerfCounterData = 26253?> | ||
| 57 | <?define msierrUninstallPerfCounterData = 26254?> | ||
| 58 | <?define msierrSMBFailedCreate = 26301?> | ||
| 59 | <?define msierrSMBFailedDrop = 26302?> | ||
| 60 | <?define msierrCERTFailedOpen = 26351?> | ||
| 61 | <?define msierrCERTFailedAdd = 26352?> | ||
| 62 | <?define msierrUSRFailedUserCreate = 26401?> | ||
| 63 | <?define msierrUSRFailedUserCreatePswd = 26402?> | ||
| 64 | <?define msierrUSRFailedUserGroupAdd = 26403?> | ||
| 65 | <?define msierrUSRFailedUserCreateExists = 26404?> | ||
| 66 | <?define msierrUSRFailedGrantLogonAsService = 26405?> | ||
| 67 | <?define msierrDependencyMissingDependencies = 26451?> | ||
| 68 | <?define msierrDependencyHasDependents = 26452?> | ||
| 69 | <?define msierrDotNetRuntimeRequired = 27000?> | ||
| 70 | <?define msierrComPlusCannotConnect = 28001?> | ||
| 71 | <?define msierrComPlusPartitionReadFailed = 28002?> | ||
| 72 | <?define msierrComPlusPartitionRoleReadFailed = 28003?> | ||
| 73 | <?define msierrComPlusUserInPartitionRoleReadFailed = 28004?> | ||
| 74 | <?define msierrComPlusPartitionUserReadFailed = 28005?> | ||
| 75 | <?define msierrComPlusApplicationReadFailed = 28006?> | ||
| 76 | <?define msierrComPlusApplicationRoleReadFailed = 28007?> | ||
| 77 | <?define msierrComPlusUserInApplicationRoleReadFailed = 28008?> | ||
| 78 | <?define msierrComPlusAssembliesReadFailed = 28009?> | ||
| 79 | <?define msierrComPlusSubscriptionReadFailed = 28010?> | ||
| 80 | <?define msierrComPlusPartitionDependency = 28011?> | ||
| 81 | <?define msierrComPlusPartitionNotFound = 28012?> | ||
| 82 | <?define msierrComPlusPartitionIdConflict = 28013?> | ||
| 83 | <?define msierrComPlusPartitionNameConflict = 28014?> | ||
| 84 | <?define msierrComPlusApplicationDependency = 28015?> | ||
| 85 | <?define msierrComPlusApplicationNotFound = 28016?> | ||
| 86 | <?define msierrComPlusApplicationIdConflict = 28017?> | ||
| 87 | <?define msierrComPlusApplicationNameConflict = 28018?> | ||
| 88 | <?define msierrComPlusApplicationRoleDependency = 28019?> | ||
| 89 | <?define msierrComPlusApplicationRoleNotFound = 28020?> | ||
| 90 | <?define msierrComPlusApplicationRoleConflict = 28021?> | ||
| 91 | <?define msierrComPlusAssemblyDependency = 28022?> | ||
| 92 | <?define msierrComPlusSubscriptionIdConflict = 28023?> | ||
| 93 | <?define msierrComPlusSubscriptionNameConflict = 28024?> | ||
| 94 | <?define msierrComPlusFailedLookupNames = 28025?> | ||
| 95 | <?define msierrMsmqCannotConnect = 28101?> | ||
| 96 | </Include> \ No newline at end of file | ||
diff --git a/src/ext/Sql/wixlib/de-de.wxl b/src/ext/Sql/wixlib/de-de.wxl new file mode 100644 index 00000000..ed2313a4 --- /dev/null +++ b/src/ext/Sql/wixlib/de-de.wxl | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <WixLocalization Culture="en-us" xmlns="http://wixtoolset.org/schemas/v4/wxl"> | ||
| 5 | <String Id="msierrSQLFailedCreateDatabase" Overridable="yes">Fehler [2]: Erstellen der SQL-Datenbank fehlgeschlagen: [3], Fehlerbeschreibung: [4].</String> | ||
| 6 | <String Id="msierrSQLFailedDropDatabase" Overridable="yes">Fehler [2]: Löschen der SQL-Datenbank fehlgeschlagen: [3], Fehlerbeschreibung: [4].</String> | ||
| 7 | <String Id="msierrSQLFailedConnectDatabase" Overridable="yes">Verbinden mit der SQL-Datenbank fehlgeschlagen. ([2] [3] [4] [5])</String> | ||
| 8 | <String Id="msierrSQLFailedExecString" Overridable="yes">Fehler [2]: Das Erstellen der SQL Zeichenfolge ist fehlgeschlagen, Fehlerbeschreibung: [3], SQL-Schlüssel: [4] SQL-Zeichenfolge: [5]</String> | ||
| 9 | <String Id="msierrSQLDatabaseAlreadyExists" Overridable="yes">Die Datenbank [3] existiert bereits. Wollen Sie fortfahren?</String> | ||
| 10 | |||
| 11 | <String Id="ConfigureSql" Overridable="yes">Konfiguriere SQL Server</String> | ||
| 12 | <String Id="CreateDatabase" Overridable="yes">Erstelle Datenbanken</String> | ||
| 13 | <String Id="DropDatabase" Overridable="yes">Lösche Datenbanken</String> | ||
| 14 | <String Id="ExecuteSqlStrings" Overridable="yes">SQL-Zeichenfolgen werden erstellt</String> | ||
| 15 | <String Id="RollbackExecuteSqlStrings" Overridable="yes">SQL-Zeichenfolgen werden zurückgesetzt</String> | ||
| 16 | </WixLocalization> | ||
diff --git a/src/ext/Sql/wixlib/en-us.wxl b/src/ext/Sql/wixlib/en-us.wxl new file mode 100644 index 00000000..d3ffd5eb --- /dev/null +++ b/src/ext/Sql/wixlib/en-us.wxl | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <WixLocalization Culture="en-us" xmlns="http://wixtoolset.org/schemas/v4/wxl"> | ||
| 5 | <String Id="msierrSQLFailedCreateDatabase" Overridable="yes">Error [2]: failed to create SQL database: [3], error detail: [4].</String> | ||
| 6 | <String Id="msierrSQLFailedDropDatabase" Overridable="yes">Error [2]: failed to drop SQL database: [3], error detail: [4].</String> | ||
| 7 | <String Id="msierrSQLFailedConnectDatabase" Overridable="yes">Failed to connect to SQL database. ([2] [3] [4] [5])</String> | ||
| 8 | <String Id="msierrSQLFailedExecString" Overridable="yes">Error [2]: failed to execute SQL string, error detail: [3], SQL key: [4] SQL string: [5]</String> | ||
| 9 | <String Id="msierrSQLDatabaseAlreadyExists" Overridable="yes">The database [3] already exists. Do you want to continue?</String> | ||
| 10 | |||
| 11 | <String Id="ConfigureSql" Overridable="yes">Configuring SQL Server</String> | ||
| 12 | <String Id="CreateDatabase" Overridable="yes">Creating Databases</String> | ||
| 13 | <String Id="DropDatabase" Overridable="yes">Dropping Databases</String> | ||
| 14 | <String Id="ExecuteSqlStrings" Overridable="yes">Executing SQL Strings</String> | ||
| 15 | <String Id="RollbackExecuteSqlStrings" Overridable="yes">Rolling back SQL Strings</String> | ||
| 16 | </WixLocalization> | ||
diff --git a/src/ext/Sql/wixlib/es-es.wxl b/src/ext/Sql/wixlib/es-es.wxl new file mode 100644 index 00000000..b2e5d499 --- /dev/null +++ b/src/ext/Sql/wixlib/es-es.wxl | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <WixLocalization Culture="es-es" xmlns="http://wixtoolset.org/schemas/v4/wxl"> | ||
| 5 | <String Id="msierrSQLFailedCreateDatabase" Overridable="yes">Error [2]: falla al crear la base de datos SQL: [3], detalle del error: [4].</String> | ||
| 6 | <String Id="msierrSQLFailedDropDatabase" Overridable="yes">Error [2]: falla al poner la base de datos SQL: [3], detalle del error: [4].</String> | ||
| 7 | <String Id="msierrSQLFailedConnectDatabase" Overridable="yes">Falla al conectarse con la base de datos SQL. ([2] [3] [4] [5])</String> | ||
| 8 | <String Id="msierrSQLFailedExecString" Overridable="yes">Error [2]: falla al ejecutar la cadena SQL, detalle del error: [3], Clave SQL: [4] Cadena SQL: [5]</String> | ||
| 9 | <String Id="msierrSQLDatabaseAlreadyExists" Overridable="yes">La base de datos [3] ya existe. ¿Desea continuar?</String> | ||
| 10 | |||
| 11 | <String Id="ConfigureSql" Overridable="yes">Configurando SQL Server</String> | ||
| 12 | <String Id="CreateDatabase" Overridable="yes">Creando Bases de Datos</String> | ||
| 13 | <String Id="DropDatabase" Overridable="yes">Colocando Bases de Datos</String> | ||
| 14 | <String Id="ExecuteSqlStrings" Overridable="yes">Ejecutando cadenas SQL</String> | ||
| 15 | <String Id="RollbackExecuteSqlStrings" Overridable="yes">Revirtiendo cadenas SQL</String> | ||
| 16 | </WixLocalization> | ||
| 17 | |||
diff --git a/src/ext/Sql/wixlib/ja-jp.wxl b/src/ext/Sql/wixlib/ja-jp.wxl new file mode 100644 index 00000000..6e35fd17 --- /dev/null +++ b/src/ext/Sql/wixlib/ja-jp.wxl | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <WixLocalization Culture="ja-jp" xmlns="http://wixtoolset.org/schemas/v4/wxl"> | ||
| 5 | <String Id="msierrSQLFailedCreateDatabase" Overridable="yes">エラー [2]: SQL データベース [3] 作成に失敗しました、エラー詳細: [4]。</String> | ||
| 6 | <String Id="msierrSQLFailedDropDatabase" Overridable="yes">エラー [2]: SQL データベース [3] の削除に失敗しました、エラー詳細: [4]。</String> | ||
| 7 | <String Id="msierrSQLFailedConnectDatabase" Overridable="yes">SQL データベースへ接続できませんでした。 ([2] [3] [4] [5])</String> | ||
| 8 | <String Id="msierrSQLFailedExecString" Overridable="yes">エラー [2]: SQL ストリングの実行に失敗しました、エラー詳細: [3]、 SQL キー: [4] SQL ストリング: [5]</String> | ||
| 9 | <String Id="msierrSQLDatabaseAlreadyExists" Overridable="yes">データベース [3] は既に存在します。続行しますか?</String> | ||
| 10 | |||
| 11 | <String Id="ConfigureSql" Overridable="yes">SQL サーバーを構成しています</String> | ||
| 12 | <String Id="CreateDatabase" Overridable="yes">データベースを作成しています</String> | ||
| 13 | <String Id="DropDatabase" Overridable="yes">データベースを削除しています</String> | ||
| 14 | <String Id="ExecuteSqlStrings" Overridable="yes">SQL ストリングを実行しています</String> | ||
| 15 | <String Id="RollbackExecuteSqlStrings" Overridable="yes">SQL ストリングをロールバックしています</String> | ||
| 16 | </WixLocalization> | ||
diff --git a/src/ext/Sql/wixlib/pl-pl.wxl b/src/ext/Sql/wixlib/pl-pl.wxl new file mode 100644 index 00000000..6200e0e9 --- /dev/null +++ b/src/ext/Sql/wixlib/pl-pl.wxl | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <WixLocalization Culture="pl-pl" xmlns="http://wixtoolset.org/schemas/v4/wxl"> | ||
| 5 | <String Id="msierrSQLFailedCreateDatabase" Overridable="yes">Błąd [2]: nie udało się utworzyć bazy danych: [3]. Szczegóły błędu: [4].</String> | ||
| 6 | <String Id="msierrSQLFailedDropDatabase" Overridable="yes">Błąd [2]: nie udało się usunąć bazy danych: [3]. Szczegóły błędu: [4].</String> | ||
| 7 | <String Id="msierrSQLFailedConnectDatabase" Overridable="yes">Nie udało się połączyć z bazą danych. ([2] [3] [4] [5])</String> | ||
| 8 | <String Id="msierrSQLFailedExecString" Overridable="yes">Błąd [2]: nie udało się wykonać zapytania SQL. Szczegóły błędu: [3], klucz: [4] zapytanie SQL: [5]</String> | ||
| 9 | <String Id="msierrSQLDatabaseAlreadyExists" Overridable="yes">Baza danych [3] już istnieje. Czy chcesz kontynuować?</String> | ||
| 10 | |||
| 11 | <String Id="ConfigureSql" Overridable="yes">Konfigurowanie programu SQL Server</String> | ||
| 12 | <String Id="CreateDatabase" Overridable="yes">Tworzenie baz danych</String> | ||
| 13 | <String Id="DropDatabase" Overridable="yes">Usuwanie baz danych</String> | ||
| 14 | <String Id="ExecuteSqlStrings" Overridable="yes">Wykonywanie zapytań SQL</String> | ||
| 15 | <String Id="RollbackExecuteSqlStrings" Overridable="yes">Cofanie zapytań SQL</String> | ||
| 16 | </WixLocalization> | ||
diff --git a/src/ext/Sql/wixlib/pt-br.wxl b/src/ext/Sql/wixlib/pt-br.wxl new file mode 100644 index 00000000..74c53313 --- /dev/null +++ b/src/ext/Sql/wixlib/pt-br.wxl | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <WixLocalization Culture="pt-br" xmlns="http://wixtoolset.org/schemas/v4/wxl"> | ||
| 5 | <String Id="msierrSQLFailedCreateDatabase" Overridable="yes">Error [2]: falha ao criar o Banco de Dados: [3], detalhes: [4].</String> | ||
| 6 | <String Id="msierrSQLFailedDropDatabase" Overridable="yes">Error [2]: falha ao remover o Banco de Dados: [3], detalhes: [4].</String> | ||
| 7 | <String Id="msierrSQLFailedConnectDatabase" Overridable="yes">Falhou a ligação ao Banco de Dados. ([2] [3] [4] [5])</String> | ||
| 8 | <String Id="msierrSQLFailedExecString" Overridable="yes">Erro [2]: falha ao executar o comando de SQL, detalhes: [3], Comando: [4] Conteúdo: [5]</String> | ||
| 9 | <String Id="msierrSQLDatabaseAlreadyExists" Overridable="yes">O Banco de Dados [3] já existe. Deseja continuar?</String> | ||
| 10 | |||
| 11 | <String Id="ConfigureSql" Overridable="yes">Configurando o Servidor de SQL</String> | ||
| 12 | <String Id="CreateDatabase" Overridable="yes">Criando os Bancos de Dados</String> | ||
| 13 | <String Id="DropDatabase" Overridable="yes">Removendo os Bancos de Dados</String> | ||
| 14 | <String Id="ExecuteSqlStrings" Overridable="yes">Executando comandos de SQL</String> | ||
| 15 | <String Id="RollbackExecuteSqlStrings" Overridable="yes">Revertendo os comandos de SQL</String> | ||
| 16 | </WixLocalization> | ||
diff --git a/src/ext/Sql/wixlib/pt-pt.wxl b/src/ext/Sql/wixlib/pt-pt.wxl new file mode 100644 index 00000000..90d9df4f --- /dev/null +++ b/src/ext/Sql/wixlib/pt-pt.wxl | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | |||
| 4 | <WixLocalization Culture="pt-pt" xmlns="http://wixtoolset.org/schemas/v4/wxl"> | ||
| 5 | <String Id="msierrSQLFailedCreateDatabase" Overridable="yes">Error [2]: falha ao criar a Base de Dados: [3], detalhes: [4].</String> | ||
| 6 | <String Id="msierrSQLFailedDropDatabase" Overridable="yes">Error [2]: falha ao remover a Base de Dados: [3], detalhes: [4].</String> | ||
| 7 | <String Id="msierrSQLFailedConnectDatabase" Overridable="yes">Falhou a ligação à Base de Dados. ([2] [3] [4] [5])</String> | ||
| 8 | <String Id="msierrSQLFailedExecString" Overridable="yes">Erro [2]: falha ao executar o comando de SQL, detalhes: [3], Comando: [4] Conteúdo: [5]</String> | ||
| 9 | <String Id="msierrSQLDatabaseAlreadyExists" Overridable="yes">A Base de Dados [3] já existe. Deseja continuar?</String> | ||
| 10 | |||
| 11 | <String Id="ConfigureSql" Overridable="yes">Configurar o Servidor de SQL</String> | ||
| 12 | <String Id="CreateDatabase" Overridable="yes">Criar as Bases de Dados</String> | ||
| 13 | <String Id="DropDatabase" Overridable="yes">Remover as Bases de Dados</String> | ||
| 14 | <String Id="ExecuteSqlStrings" Overridable="yes">Executar comandos de SQL</String> | ||
| 15 | <String Id="RollbackExecuteSqlStrings" Overridable="yes">Reverter os comandos de SQL</String> | ||
| 16 | </WixLocalization> | ||
diff --git a/src/ext/Sql/wixlib/sql.v3.ncrunchproject b/src/ext/Sql/wixlib/sql.v3.ncrunchproject new file mode 100644 index 00000000..319cd523 --- /dev/null +++ b/src/ext/Sql/wixlib/sql.v3.ncrunchproject | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | <ProjectConfiguration> | ||
| 2 | <Settings> | ||
| 3 | <IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely> | ||
| 4 | </Settings> | ||
| 5 | </ProjectConfiguration> \ No newline at end of file | ||
diff --git a/src/ext/Sql/wixlib/sql.wixproj b/src/ext/Sql/wixlib/sql.wixproj new file mode 100644 index 00000000..ac994e6b --- /dev/null +++ b/src/ext/Sql/wixlib/sql.wixproj | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | <Project Sdk="WixToolset.Sdk"> | ||
| 3 | |||
| 4 | <PropertyGroup> | ||
| 5 | <OutputType>Library</OutputType> | ||
| 6 | <BindFiles>true</BindFiles> | ||
| 7 | </PropertyGroup> | ||
| 8 | |||
| 9 | <ItemGroup> | ||
| 10 | <BindInputPaths Include="$(OutputPath)x86" BindName='x86' /> | ||
| 11 | <BindInputPaths Include="$(OutputPath)x64" BindName='x64' /> | ||
| 12 | <BindInputPaths Include="$(OutputPath)arm64" BindName='arm64' /> | ||
| 13 | </ItemGroup> | ||
| 14 | |||
| 15 | <ItemGroup> | ||
| 16 | <ProjectReference Include="..\ca\sqlca.vcxproj" Properties="Platform=ARM64" ReferenceOutputAssembly="false" /> | ||
| 17 | <ProjectReference Include="..\ca\sqlca.vcxproj" Properties="Platform=x86" ReferenceOutputAssembly="false" /> | ||
| 18 | <ProjectReference Include="..\ca\sqlca.vcxproj" Properties="Platform=x64" ReferenceOutputAssembly="false" /> | ||
| 19 | </ItemGroup> | ||
| 20 | |||
| 21 | <ItemGroup> | ||
| 22 | <PackageReference Include="Nerdbank.GitVersioning" Version="3.3.37" PrivateAssets="All" /> | ||
| 23 | </ItemGroup> | ||
| 24 | </Project> | ||
