diff options
author | Rob Mensching <rob@firegiant.com> | 2021-05-04 22:50:16 -0700 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2021-05-04 22:50:16 -0700 |
commit | e713e6695bd531d1021482d454401b86c84f3f2d (patch) | |
tree | bf76f3a6a411edd1c4b47f3a54625f7f1023e95b /src/ext | |
parent | 2977d0ffabcd6d68790e711736d2edd1fe0cc0af (diff) | |
download | wix-e713e6695bd531d1021482d454401b86c84f3f2d.tar.gz wix-e713e6695bd531d1021482d454401b86c84f3f2d.tar.bz2 wix-e713e6695bd531d1021482d454401b86c84f3f2d.zip |
Move Sql.wixext into ext
Diffstat (limited to 'src/ext')
67 files changed, 5098 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> | ||
diff --git a/src/ext/global.json b/src/ext/global.json new file mode 100644 index 00000000..23dd3fa6 --- /dev/null +++ b/src/ext/global.json | |||
@@ -0,0 +1,5 @@ | |||
1 | { | ||
2 | "msbuild-sdks": { | ||
3 | "WixToolset.Sdk": "4.0.0-build-0211" | ||
4 | } | ||
5 | } | ||