commit 58324fbbccabef700fe337f3bc28f32dddb04d6b Author: Chris Kaczor Date: Wed Nov 12 19:36:56 2014 -0500 Initial commit diff --git a/BalExtensionExt.sln b/BalExtensionExt.sln new file mode 100644 index 0000000..0031fd9 --- /dev/null +++ b/BalExtensionExt.sln @@ -0,0 +1,82 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wixextba", "wixstdba\wixstdba.vcxproj", "{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}" +EndProject +Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "BalExtension", "wixlib\BalExtension.wixproj", "{3444D952-F21C-496F-AB6B-56435BFD0787}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WixBalExtensionExt", "wixext\WixBalExtensionExt.csproj", "{6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}" + ProjectSection(ProjectDependencies) = postProject + {3444D952-F21C-496F-AB6B-56435BFD0787} = {3444D952-F21C-496F-AB6B-56435BFD0787} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bafunctions", "bafunctions\bafunctions.vcxproj", "{EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|Win32 = Debug|Win32 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|Win32 = Release|Win32 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Any CPU.Build.0 = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Win32.ActiveCfg = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Win32.Build.0 = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|x86.ActiveCfg = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Any CPU.ActiveCfg = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Mixed Platforms.Build.0 = Release|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Win32.ActiveCfg = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Win32.Build.0 = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|x86.ActiveCfg = Debug|Win32 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|Any CPU.ActiveCfg = Debug|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|Win32.ActiveCfg = Debug|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|x86.ActiveCfg = Debug|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|x86.Build.0 = Debug|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Release|Any CPU.ActiveCfg = Release|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Release|Mixed Platforms.Build.0 = Release|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Release|Win32.ActiveCfg = Release|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Release|x86.ActiveCfg = Release|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Release|x86.Build.0 = Release|x86 + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Win32.ActiveCfg = Debug|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|x86.ActiveCfg = Debug|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Any CPU.Build.0 = Release|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Win32.ActiveCfg = Release|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|x86.ActiveCfg = Release|Any CPU + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Debug|Win32.ActiveCfg = Debug|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Debug|Win32.Build.0 = Debug|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Debug|x86.ActiveCfg = Debug|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Debug|x86.Build.0 = Debug|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Release|Any CPU.ActiveCfg = Release|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Release|Mixed Platforms.Build.0 = Release|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Release|Win32.ActiveCfg = Release|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Release|Win32.Build.0 = Release|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Release|x86.ActiveCfg = Release|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Examples/Build.bat b/Examples/Build.bat new file mode 100644 index 0000000..b5c4758 --- /dev/null +++ b/Examples/Build.bat @@ -0,0 +1,63 @@ +@echo off + +path=%wix%\bin;%path% + +rd obj /q/s 2>nul 1>nul +md obj 1>nul 2>nul + +echo Building examples... + +Call :build Setup msi +Call :build Bundle1 exe +Call :build Setup msi +Call :build Bundle2 exe +Call :build Setup msi +Call :build Bundle3 exe +Call :build Setup msi +Call :build Bundle4 exe +Call :build Setup msi +Call :build Bundle5 exe +Call :build Setup msi +Call :build Bundle6 exe +Call :build Setup msi +Call :build Bundle7 exe +Call :build Setup msi +Call :build Bundle8 exe +Call :build Setup msi +Call :build Bundle9 exe +Call :build Setup msi +Call :build Bundle11 exe +Call :build Setup msi +Call :build Bundle10 exe + +echo. +echo Build complete +echo. + +goto :EOF +REM ***************************************************************** +REM End of Main +REM ***************************************************************** + + +REM ***************************************************************** +REM Build WiX code +REM ***************************************************************** +:build +candle -nologo -ext WixUtilExtension -ext WixNetFxExtension -ext ..\build\WixBalExtensionExt.dll -out obj\ %1.wxs +if %errorlevel% neq 0 ( + echo Candle error: %errorlevel% + pause + goto :EOF +) + +light -nologo -spdb -ext WixUtilExtension -ext WixNetFxExtension -ext ..\build\WixBalExtensionExt.dll obj\%1.wixobj -o %1.%2 +if %errorlevel% neq 0 ( + echo Light error: %errorlevel% + pause + goto :EOF +) + +rd obj /q/s 2>nul 1>nul +goto :EOF +REM ***************************************************************** diff --git a/Examples/Bundle1.wxs b/Examples/Bundle1.wxs new file mode 100644 index 0000000..3e64582 --- /dev/null +++ b/Examples/Bundle1.wxs @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Bundle10.wxs b/Examples/Bundle10.wxs new file mode 100644 index 0000000..1eba28a --- /dev/null +++ b/Examples/Bundle10.wxs @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Bundle11.wxs b/Examples/Bundle11.wxs new file mode 100644 index 0000000..ea8b67d --- /dev/null +++ b/Examples/Bundle11.wxs @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Bundle2.wxs b/Examples/Bundle2.wxs new file mode 100644 index 0000000..d5ec53c --- /dev/null +++ b/Examples/Bundle2.wxs @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Bundle3.wxs b/Examples/Bundle3.wxs new file mode 100644 index 0000000..f3d862f --- /dev/null +++ b/Examples/Bundle3.wxs @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Bundle4.wxs b/Examples/Bundle4.wxs new file mode 100644 index 0000000..2ccf287 --- /dev/null +++ b/Examples/Bundle4.wxs @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Bundle5.wxs b/Examples/Bundle5.wxs new file mode 100644 index 0000000..fb5c776 --- /dev/null +++ b/Examples/Bundle5.wxs @@ -0,0 +1,33 @@ + + + + + + + + + diff --git a/Examples/Bundle6.wxs b/Examples/Bundle6.wxs new file mode 100644 index 0000000..a0b0582 --- /dev/null +++ b/Examples/Bundle6.wxs @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Bundle7.wxs b/Examples/Bundle7.wxs new file mode 100644 index 0000000..d9cf7f4 --- /dev/null +++ b/Examples/Bundle7.wxs @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Bundle8.wxs b/Examples/Bundle8.wxs new file mode 100644 index 0000000..e262a3b --- /dev/null +++ b/Examples/Bundle8.wxs @@ -0,0 +1,35 @@ + + + + + + + + + + + diff --git a/Examples/Bundle9.wxs b/Examples/Bundle9.wxs new file mode 100644 index 0000000..e939f38 --- /dev/null +++ b/Examples/Bundle9.wxs @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Resource/1031/HyperlinkTheme.wxl b/Examples/Resource/1031/HyperlinkTheme.wxl new file mode 100644 index 0000000..fd66dfa --- /dev/null +++ b/Examples/Resource/1031/HyperlinkTheme.wxl @@ -0,0 +1,49 @@ + + + [WixBundleName] Setup + [WixBundleName] + Welcome (de-de [UserLanguageID]) + Setup will install [WixBundleName] on your computer. Click install to continue, options to set the install directory or Close to exit. + Version [WixBundleVersion] + Are you sure you want to cancel? + Setup Help + /install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or creates a complete local copy of the bundle in directory. Install is the default. + +/passive | /quiet - displays minimal UI with no prompts or displays no UI and no prompts. By default UI and all prompts are displayed. + +/norestart - suppress any attempts to restart. By default UI will prompt before restart. + +/log log.txt - logs to a specific file. By default a log file is created in %TEMP%. + &Close + [WixBundleName] <a href="#">license terms</a>. + I &agree to the license terms and conditions + &Options + &Install + &Close + Version [WixBundleVersion] <a href="#">upgrade available</a> + Setup Options + Install location: + &Browse... + Database location: + B&rowse... + &OK + &Cancel + Setup Progress + Processing: + Initializing... + &Cancel + Modify Setup + &Repair + &Uninstall + &Close + Setup Successful + &Launch + You must restart your computer before you can use the software. + &Restart + &Close + Setup Failed + One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. + You must restart your computer to complete the rollback of the software. + &Restart + &Close + \ No newline at end of file diff --git a/Examples/Resource/2057/HyperlinkTheme.wxl b/Examples/Resource/2057/HyperlinkTheme.wxl new file mode 100644 index 0000000..704cad1 --- /dev/null +++ b/Examples/Resource/2057/HyperlinkTheme.wxl @@ -0,0 +1,49 @@ + + + [WixBundleName] Setup + [WixBundleName] + Welcome (en-GB [UserLanguageID]) + Setup will install [WixBundleName] on your computer. Click install to continue, options to set the install directory or Close to exit. + Version [WixBundleVersion] + Are you sure you want to cancel? + Setup Help + /install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or creates a complete local copy of the bundle in directory. Install is the default. + +/passive | /quiet - displays minimal UI with no prompts or displays no UI and no prompts. By default UI and all prompts are displayed. + +/norestart - suppress any attempts to restart. By default UI will prompt before restart. + +/log log.txt - logs to a specific file. By default a log file is created in %TEMP%. + &Close + [WixBundleName] <a href="#">license terms</a>. + I &agree to the license terms and conditions + &Options + &Install + &Close + Version [WixBundleVersion] <a href="#">upgrade available</a> + Setup Options + Install location: + &Browse... + Database location: + B&rowse... + &OK + &Cancel + Setup Progress + Processing: + Initializing... + &Cancel + Modify Setup + &Repair + &Uninstall + &Close + Setup Successful + &Launch + You must restart your computer before you can use the software. + &Restart + &Close + Setup Failed + One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. + You must restart your computer to complete the rollback of the software. + &Restart + &Close + \ No newline at end of file diff --git a/Examples/Resource/Bundle2Theme.xml b/Examples/Resource/Bundle2Theme.xml new file mode 100644 index 0000000..8788f2b --- /dev/null +++ b/Examples/Resource/Bundle2Theme.xml @@ -0,0 +1,89 @@ + + + #(loc.Caption) + Segoe UI + Segoe UI + Segoe UI + Segoe UI + Segoe UI + + + #(loc.InstallUpgradeLinkText) + + + #(loc.Title) + + #(loc.HelpHeader) + #(loc.HelpText) + + + + #(loc.Title) + + #(loc.InstallHeader) + #(loc.InstallMessage) + #(loc.InstallLicenseLinkText) + #(loc.InstallVersion) + + #(loc.InstallAcceptCheckbox) + + + + + + #(loc.Title) + + #(loc.OptionsHeader) + #(loc.OptionsLocationLabel) + + + #(loc.OptionsLocationLabel2) + + + + Select option + + + + + + + + + + #(loc.Title) + + #(loc.ProgressHeader) + #(loc.ProgressLabel) + #(loc.OverallProgressPackageText) + + + + + #(loc.Title) + + #(loc.ModifyHeader) + + + + + + #(loc.Title) + + #(loc.SuccessHeader) + + #(loc.SuccessRestartText) + + + + + #(loc.Title) + + #(loc.FailureHeader) + #(loc.FailureHyperlinkLogText) + + #(loc.FailureRestartText) + + + + \ No newline at end of file diff --git a/Examples/Resource/Bundle3Theme.xml b/Examples/Resource/Bundle3Theme.xml new file mode 100644 index 0000000..a0ba158 --- /dev/null +++ b/Examples/Resource/Bundle3Theme.xml @@ -0,0 +1,87 @@ + + + #(loc.Caption) + Segoe UI + Segoe UI + Segoe UI + Segoe UI + Segoe UI + + + #(loc.Title) + + #(loc.HelpHeader) + #(loc.HelpText) + + + + #(loc.Title) + + #(loc.InstallHeader) + #(loc.InstallMessage) + + Select option + + + + + + + #(loc.InstallLicenseLinkText) + #(loc.InstallVersion) + #(loc.InstallAcceptCheckbox) + + + + + + #(loc.Title) + + #(loc.OptionsHeader) + #(loc.OptionsLocationLabel) + + + + Textbox + [Username] + + + + + + #(loc.Title) + + #(loc.ProgressHeader) + #(loc.ProgressLabel) + #(loc.OverallProgressPackageText) + + + + + #(loc.Title) + + #(loc.ModifyHeader) + + + + + + #(loc.Title) + + #(loc.SuccessHeader) + + #(loc.SuccessRestartText) + + + + + #(loc.Title) + + #(loc.FailureHeader) + #(loc.FailureHyperlinkLogText) + + #(loc.FailureRestartText) + + + + \ No newline at end of file diff --git a/Examples/Resource/Bundle4Theme.xml b/Examples/Resource/Bundle4Theme.xml new file mode 100644 index 0000000..517d7ff --- /dev/null +++ b/Examples/Resource/Bundle4Theme.xml @@ -0,0 +1,88 @@ + + + #(loc.Caption) + Segoe UI + Segoe UI + Segoe UI + Segoe UI + Segoe UI + + + #(loc.Title) + + #(loc.HelpHeader) + #(loc.HelpText) + + + + #(loc.Title) + + #(loc.InstallHeader) + #(loc.InstallMessage) + + Checkbox Option 1 + Checkbox Option 2 + + #(loc.InstallLicenseLinkText) + #(loc.InstallVersion) + #(loc.InstallAcceptCheckbox) + + + + + + #(loc.Title) + + #(loc.OptionsHeader) + #(loc.OptionsLocationLabel) + + + #(loc.OptionsLocationLabel2) + + + + Textbox + Useful Text + + Checkbox Option 3 + + + + + + #(loc.Title) + + #(loc.ProgressHeader) + #(loc.ProgressLabel) + #(loc.OverallProgressPackageText) + + + + + #(loc.Title) + + #(loc.ModifyHeader) + + + + + + #(loc.Title) + + #(loc.SuccessHeader) + + #(loc.SuccessRestartText) + + + + + #(loc.Title) + + #(loc.FailureHeader) + #(loc.FailureHyperlinkLogText) + + #(loc.FailureRestartText) + + + + \ No newline at end of file diff --git a/Examples/Resource/HyperlinkLocaleTheme.wxl b/Examples/Resource/HyperlinkLocaleTheme.wxl new file mode 100644 index 0000000..5bfb902 --- /dev/null +++ b/Examples/Resource/HyperlinkLocaleTheme.wxl @@ -0,0 +1,49 @@ + + + [WixBundleName] Setup + [WixBundleName] + Welcome ([UserLanguageID]) + Setup will install [WixBundleName] on your computer. Click install to continue, options to set the install directory or Close to exit. + Version [WixBundleVersion] + Are you sure you want to cancel? + Setup Help + /install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or creates a complete local copy of the bundle in directory. Install is the default. + +/passive | /quiet - displays minimal UI with no prompts or displays no UI and no prompts. By default UI and all prompts are displayed. + +/norestart - suppress any attempts to restart. By default UI will prompt before restart. + +/log log.txt - logs to a specific file. By default a log file is created in %TEMP%. + &Close + [WixBundleName] <a href="#">license terms</a>. + I &agree to the license terms and conditions + &Options + &Install + &Close + Version [WixBundleVersion] <a href="#">upgrade available</a> + Setup Options + Install location: + &Browse... + Database location: + B&rowse... + &OK + &Cancel + Setup Progress + Processing: + Initializing... + &Cancel + Modify Setup + &Repair + &Uninstall + &Close + Setup Successful + &Launch + You must restart your computer before you can use the software. + &Restart + &Close + Setup Failed + One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. + You must restart your computer to complete the rollback of the software. + &Restart + &Close + \ No newline at end of file diff --git a/Examples/Resource/HyperlinkTheme.wxl b/Examples/Resource/HyperlinkTheme.wxl new file mode 100644 index 0000000..955ba61 --- /dev/null +++ b/Examples/Resource/HyperlinkTheme.wxl @@ -0,0 +1,49 @@ + + + [WixBundleName] Setup + [WixBundleName] + Welcome + Setup will install [WixBundleName] on your computer. Click install to continue, options to set the install directory or Close to exit. + Version [WixBundleVersion] + Are you sure you want to cancel? + Setup Help + /install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or creates a complete local copy of the bundle in directory. Install is the default. + +/passive | /quiet - displays minimal UI with no prompts or displays no UI and no prompts. By default UI and all prompts are displayed. + +/norestart - suppress any attempts to restart. By default UI will prompt before restart. + +/log log.txt - logs to a specific file. By default a log file is created in %TEMP%. + &Close + [WixBundleName] <a href="#">license terms</a>. + I &agree to the license terms and conditions + &Options + &Install + &Close + Version [WixBundleVersion] <a href="#">upgrade available</a> + Setup Options + Install location: + &Browse... + Database location: + B&rowse... + &OK + &Cancel + Setup Progress + Processing: + Initializing... + &Cancel + Modify Setup + &Repair + &Uninstall + &Close + Setup Successful + &Launch + You must restart your computer before you can use the software. + &Restart + &Close + Setup Failed + One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. + You must restart your computer to complete the rollback of the software. + &Restart + &Close + \ No newline at end of file diff --git a/Examples/Resource/License.htm b/Examples/Resource/License.htm new file mode 100644 index 0000000..e15530b --- /dev/null +++ b/Examples/Resource/License.htm @@ -0,0 +1,127 @@ + + + + + + + + + + + +
+ +

[Put Your License Agreement Here]

+ +

Lorem +ipsum dolor sit amet, consectetur adipiscing elit. Donec ultricies ultricies +arcu id commodo. Ut dignissim ante nec urna elementum imperdiet. Praesent +pretium condimentum orci sit amet laoreet. Fusce condimentum tempor leo, vitae +tempor quam interdum et. Nulla ante dui, tincidunt sed porta nec, pulvinar in +felis. Pellentesque pellentesque ornare nibh id accumsan. In eu arcu nibh. +Aenean ut vulputate nisl. Proin at nibh lacinia urna elementum commodo. Donec semper +lorem quis neque fringilla quis facilisis dolor dignissim. Suspendisse a massa +in odio viverra vehicula. Curabitur id lectus purus, non bibendum arcu. Cras +dictum, turpis eget gravida condimentum, turpis ante varius leo, molestie +pulvinar mauris libero ut leo. Morbi libero diam, sollicitudin id interdum sit +amet, rhoncus eget turpis.

+ +

Vestibulum arcu dui, suscipit +vitae suscipit laoreet, posuere eget risus. Sed vitae massa in justo vehicula +elementum sed at arcu. Pellentesque arcu ante, accumsan sed lacinia sed, +lacinia vel urna. Vivamus at ligula nulla, lobortis ultricies tortor. Vivamus +suscipit dolor non velit adipiscing venenatis. Nullam adipiscing accumsan +condimentum. Nullam ut lorem neque, et iaculis felis. Donec sed massa diam, et +feugiat velit. Pellentesque facilisis mi a odio ultrices facilisis. Nam porta, +lorem feugiat aliquet placerat, ipsum risus accumsan sem, euismod bibendum +velit dolor sed turpis. Suspendisse tincidunt, lectus congue rhoncus +sollicitudin, magna erat porttitor ante, eget sodales ante sem eu augue. Aenean +risus risus, mattis vitae pretium at, venenatis dictum est. Vestibulum +consectetur euismod magna vel sodales.

+ +

Quisque eu urna lacus. Nunc eget +dictum odio. Pellentesque vel dolor leo. Praesent aliquet, erat vel fringilla +lobortis, ante nibh dapibus augue, sed semper ligula odio vitae nulla. Nullam +dictum gravida lectus nec lacinia. Vivamus fermentum ultricies lobortis. In +quis magna massa, ut commodo lectus. Donec nunc velit, gravida id euismod +luctus, luctus sed ante. Nunc elementum mollis sapien, ac interdum quam +fringilla eu. Pellentesque habitant morbi tristique senectus et netus et +malesuada fames ac turpis egestas. Aliquam dui enim, tempus vel aliquam sed, +pretium sed nisi. Fusce vitae magna nec nibh aliquam suscipit vel a felis. +Etiam gravida, lorem id laoreet gravida, nisl leo hendrerit dolor, quis porta +mauris enim vitae justo. Maecenas congue, felis at rhoncus vestibulum, nisl +urna pellentesque urna, id iaculis augue metus eget neque. Curabitur pretium +risus nec tortor vulputate et rhoncus ipsum gravida.

+ +

Maecenas elementum volutpat arcu, +nec ultricies velit faucibus facilisis. Etiam sem lacus, mattis eget gravida +ut, rhoncus porta lorem. Vivamus volutpat dui sit amet risus mollis venenatis. +Quisque velit velit, condimentum id pharetra sed, varius vitae lectus. Praesent +nisi turpis, porttitor nec accumsan a, aliquam sit amet augue. Quisque +facilisis enim sed enim pretium tristique. Aliquam commodo varius mi, ut +iaculis nunc tempus non. Vivamus velit nunc, dictum a dignissim vitae, commodo +id metus. Integer volutpat, neque at ultrices dignissim, felis nulla commodo +orci, at auctor nisl quam nec sem. Pellentesque interdum pellentesque nulla, ac +fermentum tortor porttitor a. Etiam condimentum aliquet sapien vel adipiscing. Quisque +est velit, vulputate a iaculis ut, tempus in nibh. Cras consectetur quam nibh, +vel lobortis justo. Aenean a elit leo. Aenean mollis dolor a odio accumsan +mollis. Proin blandit neque erat. Integer lectus urna, volutpat quis vulputate +et, fermentum et ante. Maecenas vitae ultricies dui.

+ +

Mauris accumsan varius luctus. In +hac habitasse platea dictumst. Mauris malesuada tempus nibh, porta accumsan +tortor tincidunt eu. Proin orci mauris, commodo id malesuada nec, adipiscing ut +sapien. Phasellus at dui vel nisi adipiscing auctor quis vel sem. Phasellus +fermentum, enim id sodales ullamcorper, magna sapien facilisis urna, ac +lobortis nunc augue ut ligula. Quisque vulputate nibh sed velit pharetra +dictum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque +mi metus, vestibulum vitae dapibus vel, ultrices at tellus. Vivamus iaculis dui +a nisl faucibus eget congue velit gravida. Donec vel quam ligula. Nam magna +ante, vulputate id pharetra ac, dapibus commodo velit. Cras nisl nulla, congue +sit amet laoreet eget, cursus et lorem. Mauris diam tortor, porttitor vitae +fringilla id, iaculis sit amet eros. Donec sed enim eget felis fermentum +posuere. Pellentesque sodales feugiat dolor, vel molestie est adipiscing non. +Morbi tincidunt viverra felis ut hendrerit.

+ +
+ + + + diff --git a/Examples/Resource/License.rtf b/Examples/Resource/License.rtf new file mode 100644 index 0000000..1a18323 Binary files /dev/null and b/Examples/Resource/License.rtf differ diff --git a/Examples/Resource/Logo.png b/Examples/Resource/Logo.png new file mode 100644 index 0000000..8bc70e8 Binary files /dev/null and b/Examples/Resource/Logo.png differ diff --git a/Examples/Resource/LogoSide.png b/Examples/Resource/LogoSide.png new file mode 100644 index 0000000..e7dc183 Binary files /dev/null and b/Examples/Resource/LogoSide.png differ diff --git a/Examples/Resource/SplashScreen.bmp b/Examples/Resource/SplashScreen.bmp new file mode 100644 index 0000000..1d9b1e4 Binary files /dev/null and b/Examples/Resource/SplashScreen.bmp differ diff --git a/Examples/Setup.wxs b/Examples/Setup.wxs new file mode 100644 index 0000000..946a98a --- /dev/null +++ b/Examples/Setup.wxs @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Template bafunctions/IBootstrapperBAFunction.h b/Examples/Template bafunctions/IBootstrapperBAFunction.h new file mode 100644 index 0000000..c0c9b3b --- /dev/null +++ b/Examples/Template bafunctions/IBootstrapperBAFunction.h @@ -0,0 +1,29 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +//------------------------------------------------------------------------------------------------- + +#pragma once + +#include + +#include "IBootstrapperEngine.h" + +interface IBootstrapperBAFunction +{ + STDMETHOD(OnDetect)() = 0; + STDMETHOD(OnDetectComplete)() = 0; + STDMETHOD(OnPlan)() = 0; + STDMETHOD(OnPlanComplete)() = 0; +}; + +extern "C" typedef HRESULT (WINAPI *PFN_BOOTSTRAPPER_BA_FUNCTION_CREATE)( + __in IBootstrapperEngine* pEngine, + __in HMODULE hModule, + __out IBootstrapperBAFunction** ppBAFunction + ); + diff --git a/Examples/Template bafunctions/Readme.txt b/Examples/Template bafunctions/Readme.txt new file mode 100644 index 0000000..c94074a --- /dev/null +++ b/Examples/Template bafunctions/Readme.txt @@ -0,0 +1,85 @@ + +This is a sample project showing how to create a BA function assembly. + +The four interfaces are in the WixBootstrapperBAFunction.cpp file. + + +Example code: +~~~~~~~~~~~~~ + + + HRESULT hr = S_OK; + HKEY hkKey = NULL; + LPWSTR sczValue = NULL; + LPWSTR sczFormatedValue = NULL; + + + //--------------------------------------------------------------------------------------------- + // Example of BA function failure + hr = E_NOTIMPL; + BalExitOnFailure(hr, "Test failure."); + //--------------------------------------------------------------------------------------------- + + //--------------------------------------------------------------------------------------------- + // Example of setting a variables + hr = m_pEngine->SetVariableString(L"Variable1", L"String value"); + BalExitOnFailure(hr, "Failed to set variable."); + hr = m_pEngine->SetVariableNumeric(L"Variable2", 1234); + BalExitOnFailure(hr, "Failed to set variable."); + //--------------------------------------------------------------------------------------------- + + //--------------------------------------------------------------------------------------------- + // Example of reading burn variable. + BalGetStringVariable(L"WixBundleName", &sczValue); + BalExitOnFailure(hr, "Failed to get variable."); + + hr = m_pEngine->SetVariableString(L"Variable4", sczValue); + BalExitOnFailure(hr, "Failed to set variable."); + //--------------------------------------------------------------------------------------------- + + ReleaseNullStr(sczValue); // Release string so it can be re-used + + //--------------------------------------------------------------------------------------------- + // Examples of reading burn variable and formatting it. + BalGetStringVariable(L"InstallFolder", &sczValue); + BalExitOnFailure(hr, "Failed to get variable."); + + hr = m_pEngine->SetVariableString(L"Variable5", sczValue); + BalExitOnFailure(hr, "Failed to set variable."); + + BalFormatString(sczValue, &sczFormatedValue); + BalExitOnFailure(hr, "Failed to format variable."); + + hr = m_pEngine->SetVariableString(L"Variable6", sczFormatedValue); + BalExitOnFailure(hr, "Failed to set variable."); + //--------------------------------------------------------------------------------------------- + + ReleaseNullStr(sczValue); // Release string so it can be re-used + + //--------------------------------------------------------------------------------------------- + // Example of reading 64 bit registry and setting the InstallFolder variable to the value read. + hr = RegOpen(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.5", KEY_READ | KEY_WOW64_64KEY, &hkKey); + BalExitOnFailure(hr, "Failed to open registry key."); + + hr = RegReadString(hkKey, L"InstallPath", &sczValue); + BalExitOnFailure(hr, "Failed to read registry value."); + + // Example of function call + PathBackslashTerminate(&sczValue); + + hr = m_pEngine->SetVariableString(L"InstallFolder", sczValue); + BalExitOnFailure(hr, "Failed to set variable."); + //--------------------------------------------------------------------------------------------- + + ReleaseNullStr(sczValue); // Release string so it can be re-used + + //--------------------------------------------------------------------------------------------- + // Example of calling a function that return HRESULT + hr = GetFileVersion(); + BalExitOnFailure(hr, "Failed to get version."); + //--------------------------------------------------------------------------------------------- + + LExit: + ReleaseRegKey(hkKey); + ReleaseStr(sczValue); + ReleaseStr(sczFormatedValue); diff --git a/Examples/Template bafunctions/Version.proj b/Examples/Template bafunctions/Version.proj new file mode 100644 index 0000000..109f83f --- /dev/null +++ b/Examples/Template bafunctions/Version.proj @@ -0,0 +1,72 @@ + + + + 1 + 0 + + .\bafunctionsver.h + + + + $([System.DateTime]::new(2000, 1, 1)) + $([System.Convert]::ToInt32($([System.DateTime]::Now.ToUniversalTime().Subtract($(Base)).TotalDays))) + $([System.Convert]::ToInt32($([MSBuild]::Divide($([System.Convert]::ToInt32($([System.DateTime]::Now.ToUniversalTime().TimeOfDay.TotalSeconds))), 2)))) + + $(MajorBuildNumber).$(MinorBuildNumber).$(BuildNumber).$(BuildRevision) + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Template bafunctions/WixBootstrapperBAFunction.cpp b/Examples/Template bafunctions/WixBootstrapperBAFunction.cpp new file mode 100644 index 0000000..34baaa7 --- /dev/null +++ b/Examples/Template bafunctions/WixBootstrapperBAFunction.cpp @@ -0,0 +1,134 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +//------------------------------------------------------------------------------------------------- + + +#include "precomp.h" + +class CWixBootstrapperBAFunction : IBootstrapperBAFunction +{ +public: + STDMETHODIMP OnDetect() + { + HRESULT hr = S_OK; + + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Running detect BA function"); + + //------------------------------------------------------------------------------------------------- + // YOUR CODE GOES HERE + BalExitOnFailure(hr, "Change this message to represent real error handling."); + //------------------------------------------------------------------------------------------------- + + LExit: + return hr; + } + + + STDMETHODIMP OnDetectComplete() { return S_OK; } + STDMETHODIMP OnPlan() { return S_OK; } + STDMETHODIMP OnPlanComplete() { return S_OK; } + +/* + STDMETHODIMP OnDetectComplete() + { + HRESULT hr = S_OK; + + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Running detect complete BA function"); + + //------------------------------------------------------------------------------------------------- + // YOUR CODE GOES HERE + BalExitOnFailure(hr, "Change this message to represent real error handling."); + //------------------------------------------------------------------------------------------------- + + LExit: + return hr; + } + + + STDMETHODIMP OnPlan() + { + HRESULT hr = S_OK; + + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Running plan BA function"); + + //------------------------------------------------------------------------------------------------- + // YOUR CODE GOES HERE + BalExitOnFailure(hr, "Change this message to represent real error handling."); + //------------------------------------------------------------------------------------------------- + + LExit: + return hr; + } + + + STDMETHODIMP OnPlanComplete() + { + HRESULT hr = S_OK; + + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Running plan complete BA function"); + + //------------------------------------------------------------------------------------------------- + // YOUR CODE GOES HERE + BalExitOnFailure(hr, "Change this message to represent real error handling."); + //------------------------------------------------------------------------------------------------- + + LExit: + return hr; + } +*/ + + +private: + HMODULE m_hModule; + IBootstrapperEngine* m_pEngine; + + +public: + // + // Constructor - initialize member variables. + // + CWixBootstrapperBAFunction( + __in IBootstrapperEngine* pEngine, + __in HMODULE hModule + ) + { + m_hModule = hModule; + m_pEngine = pEngine; + } + + // + // Destructor - release member variables. + // + ~CWixBootstrapperBAFunction() + { + } +}; + + +extern "C" HRESULT WINAPI CreateBootstrapperBAFunction( + __in IBootstrapperEngine* pEngine, + __in HMODULE hModule, + __out CWixBootstrapperBAFunction** ppBAFunction + ) +{ + HRESULT hr = S_OK; + CWixBootstrapperBAFunction* pBAFunction = NULL; + + // This is required to enable logging functions + BalInitialize(pEngine); + + pBAFunction = new CWixBootstrapperBAFunction(pEngine, hModule); + ExitOnNull(pBAFunction, hr, E_OUTOFMEMORY, "Failed to create new bootstrapper BA function object."); + + *ppBAFunction = pBAFunction; + pBAFunction = NULL; + +LExit: + delete pBAFunction; + return hr; +} diff --git a/Examples/Template bafunctions/bafunctions.cpp b/Examples/Template bafunctions/bafunctions.cpp new file mode 100644 index 0000000..16b6543 --- /dev/null +++ b/Examples/Template bafunctions/bafunctions.cpp @@ -0,0 +1,37 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +// +// +// Entry point for bootstrapper BA function DLL. +// +//------------------------------------------------------------------------------------------------- + +#include "precomp.h" + +static HINSTANCE vhInstance = NULL; + +extern "C" BOOL WINAPI DllMain( + IN HINSTANCE hInstance, + IN DWORD dwReason, + IN LPVOID /* pvReserved */ + ) +{ + switch(dwReason) + { + case DLL_PROCESS_ATTACH: + ::DisableThreadLibraryCalls(hInstance); + vhInstance = hInstance; + break; + + case DLL_PROCESS_DETACH: + vhInstance = NULL; + break; + } + + return TRUE; +} diff --git a/Examples/Template bafunctions/bafunctions.def b/Examples/Template bafunctions/bafunctions.def new file mode 100644 index 0000000..6e721f1 --- /dev/null +++ b/Examples/Template bafunctions/bafunctions.def @@ -0,0 +1,16 @@ +;------------------------------------------------------------------------------------------------- +; +; Copyright (c) 2004, Outercurve Foundation. +; This software is released under Microsoft Reciprocal License (MS-RL). +; The license and further copyright text can be found in the file +; LICENSE.TXT at the root directory of the distribution. +; +; +; +; Bootstrapper Application function DLL entry points. +; +;------------------------------------------------------------------------------------------------- + +EXPORTS + CreateBootstrapperBAFunction + diff --git a/Examples/Template bafunctions/bafunctions.rc b/Examples/Template bafunctions/bafunctions.rc new file mode 100644 index 0000000..d3fcf9f --- /dev/null +++ b/Examples/Template bafunctions/bafunctions.rc @@ -0,0 +1,129 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +// +// +// WiX Extendend Bootstrapper BA function resource file. +// +//------------------------------------------------------------------------------------------------- + +#include +#include +#include "bafunctionsver.h" + +#define VER_APP +#define VER_ORIGINAL_FILENAME "bafunctions.dll" +#define VER_INTERNAL_NAME "bafunctions" +#define VER_PRODUCT_NAME "WiX Bootstrapper functions" +#define VER_FILE_DESCRIPTION "WiX Bootstrapper functions" + +#ifdef DEBUG + #define VER_DEBUG VS_FF_DEBUG + #define VER_PRIVATE_BUILD VS_FF_PRIVATEBUILD + #define VER_PRE_RELEASE (VS_FF_PRERELEASE | VS_FF_SPECIALBUILD) +#else + #define VER_DEBUG 0 + #define VER_PRIVATE_BUILD 0 + #define VER_PRE_RELEASE 0 +#endif + +#if defined(VER_APP) + #define VER_FILE_TYPE VFT_APP +#elif defined(VER_DLL) + #define VER_FILE_TYPE VFT_DLL +#elif defined(VER_TYPELIB) + #define VER_FILE_TYPE VFT_UNKNOWN +#else + #define VER_FILE_TYPE VFT_UNKNOWN +#endif + +#if defined(VER_LANG_NEUTRAL) + #ifndef VER_LANG + #define VER_LANG 0x0000 + #endif + #ifndef VER_CP + #define VER_CP 0x04E4 + #endif + #ifndef VER_BLOCK + #define VER_BLOCK "000004E4" + #endif +#else + #ifndef VER_LANG + #define VER_LANG 0x0409 + #endif + #ifndef VER_CP + #define VER_CP 0x04E4 + #endif + #ifndef VER_BLOCK + #define VER_BLOCK "040904E4" + #endif +#endif + +#define VER_FILE_VERSION rmj, rmm, rbd, rev +#define VER_PRODUCT_VERSION rmj, rmm, rbd, rev +#define VER_FILE_VERSION_STRING szVerMajorMinorBuildRev +#define VER_PRODUCT_VERSION_STRING VER_FILE_VERSION_STRING +#define VER_FILE_FLAGS_MASK VS_FFI_FILEFLAGSMASK +#define VER_FILE_FLAGS (VER_DEBUG | VER_PRIVATE_BUILD | VER_PRE_RELEASE) + +#define VER_FILE_OS VOS__WINDOWS32 + +#define VER_COMPANY_NAME "Outercurve Foundation" +#ifndef VER_PRODUCT_NAME + #define VER_PRODUCT_NAME "Windows Installer XML (WiX)" +#endif +#ifndef VER_FILE_DESCRIPTION + #define VER_FILE_DESCRIPTION "Windows Installer XML (WiX) component" +#endif + +#if defined(VER_LEGAL_COPYRIGHT) + #error +#endif +#define VER_LEGAL_COPYRIGHT "Copyright (c) Outercurve Foundation.\240 All rights reserved." + +#if !defined(VER_FILE_SUBTYPE) + #define VER_FILE_SUBTYPE 0 +#endif + +#ifdef RC_INVOKED + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILE_VERSION +PRODUCTVERSION VER_PRODUCT_VERSION +FILEFLAGSMASK VER_FILE_FLAGS_MASK +FILEFLAGS VER_FILE_FLAGS +FILEOS VER_FILE_OS +FILETYPE VER_FILE_TYPE +FILESUBTYPE VER_FILE_SUBTYPE +BEGIN +BLOCK "StringFileInfo" + BEGIN + BLOCK VER_BLOCK + BEGIN + VALUE "CompanyName", VER_COMPANY_NAME + VALUE "FileDescription", VER_FILE_DESCRIPTION + VALUE "FileVersion", VER_FILE_VERSION_STRING + VALUE "InternalName", VER_INTERNAL_NAME + + VALUE "LegalCopyright", VER_LEGAL_COPYRIGHT + + VALUE "OriginalFilename", VER_ORIGINAL_FILENAME + VALUE "ProductName", VER_PRODUCT_NAME + VALUE "ProductVersion", VER_FILE_VERSION_STRING +#if defined(DEBUG) + VALUE "WiX Common Resource Format", "Debug Only" +#endif + END + END + +BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", VER_LANG, VER_CP + END +END + +#endif diff --git a/Examples/Template bafunctions/bafunctions.vcxproj b/Examples/Template bafunctions/bafunctions.vcxproj new file mode 100644 index 0000000..02b4cf9 --- /dev/null +++ b/Examples/Template bafunctions/bafunctions.vcxproj @@ -0,0 +1,134 @@ + + + + + + Debug + Win32 + + + Release + Win32 + + + + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02} + BaFunctions + Win32Proj + DynamicLibrary + MultiByte + bafunctions + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(Configuration)\ + $(Configuration)\ + true + AllRules.ruleset + + + $(Configuration)\ + $(Configuration)\ + true + AllRules.ruleset + + + + + + + + + + Disabled + $(WiX)SDK\VS2010\inc;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;DEBUG;%(PreprocessorDefinitions);$(ExtraDefinitions) + true + EnableFastChecks + MultiThreadedDebug + Use + precomp.h + $(IntDir)$(ProjectName).pdb + Level4 + ProgramDatabase + StdCall + true + + + %(AdditionalIncludeDirectories) + + + dutil.lib;balutil.lib;comctl32.lib;gdiplus.lib;shlwapi.lib;wininet.lib;version.lib;%(AdditionalDependencies) + $(WiX)SDK\VS2010\lib\x86;%(AdditionalLibraryDirectories) + bafunctions.def + true + Windows + + + + + Disabled + $(WiX)SDK\VS2010\inc;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);$(ExtraDefinitions) + true + EnableFastChecks + MultiThreaded + Use + precomp.h + $(IntDir)$(ProjectName).pdb + Level4 + ProgramDatabase + StdCall + true + + + %(AdditionalIncludeDirectories) + + + dutil.lib;balutil.lib;comctl32.lib;gdiplus.lib;shlwapi.lib;wininet.lib;version.lib;%(AdditionalDependencies) + $(WiX)SDK\VS2010\lib\x86;%(AdditionalLibraryDirectories) + bafunctions.def + false + Windows + + + + + + Create + Create + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Examples/Template bafunctions/bafunctions.vcxproj.filters b/Examples/Template bafunctions/bafunctions.vcxproj.filters new file mode 100644 index 0000000..2212a5f --- /dev/null +++ b/Examples/Template bafunctions/bafunctions.vcxproj.filters @@ -0,0 +1,47 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + + + + Resource Files + + + \ No newline at end of file diff --git a/Examples/Template bafunctions/bafunctionsver.h b/Examples/Template bafunctions/bafunctionsver.h new file mode 100644 index 0000000..2046f30 --- /dev/null +++ b/Examples/Template bafunctions/bafunctionsver.h @@ -0,0 +1,12 @@ +// +#ifndef _VERSION_FILE_H_ +#define _VERSION_FILE_H_ + +#define szVerMajorMinor "1.0" +#define szVerMajorMinorBuildRev "1.0.0.0" +#define rmj 1 +#define rmm 0 +#define rbd 0 +#define rev 0 + +#endif diff --git a/Examples/Template bafunctions/build.bat b/Examples/Template bafunctions/build.bat new file mode 100644 index 0000000..9356ca1 --- /dev/null +++ b/Examples/Template bafunctions/build.bat @@ -0,0 +1,23 @@ +@echo off + +echo Configuring environment... +set MSBUILD="%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe" +echo. + +set outdir=%~dp0build + +rem %MSBUILD% Version.proj +%MSBUILD% bafunctions.vcxproj /t:Rebuild /p:Configuration=Release,Platform=Win32 /p:RunCodeAnalysis=false /p:DefineConstants="TRACE" /p:OutDir="%outdir%\\" /l:FileLogger,Microsoft.Build.Engine;logfile=build.log +if %errorlevel% neq 0 ( + echo Build failed + pause + goto :EOF +) + +echo. + +goto :EOF + +REM ***************************************************************** +REM End of Main +REM ***************************************************************** diff --git a/Examples/Template bafunctions/precomp.h b/Examples/Template bafunctions/precomp.h new file mode 100644 index 0000000..a90e2a4 --- /dev/null +++ b/Examples/Template bafunctions/precomp.h @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +// +// +// Precompiled header for standard bootstrapper application. +// +//------------------------------------------------------------------------------------------------- + +#pragma once + + +#include +#include +#include +#include +#include +#include +#include +#include + +// Standard WiX header files, include as required +#include "dutil.h" +//#include "memutil.h" +//#include "dictutil.h" +//#include "dirutil.h" +#include "fileutil.h" +//#include "locutil.h" +//#include "logutil.h" +#include "pathutil.h" +//#include "resrutil.h" +//#include "shelutil.h" +#include "strutil.h" +//#include "thmutil.h" +//#include "uriutil.h" +//#include "xmlutil.h" +#include "regutil.h" + +//#include "IBootstrapperEngine.h" +//#include "IBootstrapperApplication.h" + +#include "BalBaseBootstrapperApplication.h" +//#include "balinfo.h" +//#include "balcondition.h" +#include "balutil.h" + +#include "IBootstrapperBAFunction.h" + diff --git a/Examples/Template bafunctions/resource.h b/Examples/Template bafunctions/resource.h new file mode 100644 index 0000000..53c03c3 --- /dev/null +++ b/Examples/Template bafunctions/resource.h @@ -0,0 +1,25 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +//------------------------------------------------------------------------------------------------- + +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// +#define IDC_STATIC -1 + + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1003 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Examples/bafunctions.dll b/Examples/bafunctions.dll new file mode 100644 index 0000000..ae079bb Binary files /dev/null and b/Examples/bafunctions.dll differ diff --git a/LICENSE.TXT b/LICENSE.TXT new file mode 100644 index 0000000..9e34401 --- /dev/null +++ b/LICENSE.TXT @@ -0,0 +1,28 @@ +Copyright (c) 2004, Outercurve Foundation. +This software is released under the Microsoft Reciprocal License (MS-RL) (the "License"); you may not use the software except in compliance with the License. + +The text of the Microsoft Reciprocal License (MS-RL) can be found online at: + http://opensource.org/licenses/ms-rl + + +Microsoft Reciprocal License (MS-RL) + +This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. + +1. Definitions + The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. + A "contribution" is the original software, or any additions or changes to the software. + A "contributor" is any person that distributes its contribution under this license. + "Licensed patents" are a contributor's patent claims that read directly on its contribution. + +2. Grant of Rights + (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. + (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. + +3. Conditions and Limitations + (A) Reciprocal Grants- For any file you distribute that contains code from the software (in source code or binary format), you must provide recipients the source code to that file along with a copy of this license, which license will govern that file. You may license other files that are entirely your own work and do not contain code from the software under any terms you choose. + (B) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. + (C) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. + (D) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. + (E) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. + (F) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. diff --git a/bafunctions/IBootstrapperBAFunction.h b/bafunctions/IBootstrapperBAFunction.h new file mode 100644 index 0000000..c0c9b3b --- /dev/null +++ b/bafunctions/IBootstrapperBAFunction.h @@ -0,0 +1,29 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +//------------------------------------------------------------------------------------------------- + +#pragma once + +#include + +#include "IBootstrapperEngine.h" + +interface IBootstrapperBAFunction +{ + STDMETHOD(OnDetect)() = 0; + STDMETHOD(OnDetectComplete)() = 0; + STDMETHOD(OnPlan)() = 0; + STDMETHOD(OnPlanComplete)() = 0; +}; + +extern "C" typedef HRESULT (WINAPI *PFN_BOOTSTRAPPER_BA_FUNCTION_CREATE)( + __in IBootstrapperEngine* pEngine, + __in HMODULE hModule, + __out IBootstrapperBAFunction** ppBAFunction + ); + diff --git a/bafunctions/Version.proj b/bafunctions/Version.proj new file mode 100644 index 0000000..109f83f --- /dev/null +++ b/bafunctions/Version.proj @@ -0,0 +1,72 @@ + + + + 1 + 0 + + .\bafunctionsver.h + + + + $([System.DateTime]::new(2000, 1, 1)) + $([System.Convert]::ToInt32($([System.DateTime]::Now.ToUniversalTime().Subtract($(Base)).TotalDays))) + $([System.Convert]::ToInt32($([MSBuild]::Divide($([System.Convert]::ToInt32($([System.DateTime]::Now.ToUniversalTime().TimeOfDay.TotalSeconds))), 2)))) + + $(MajorBuildNumber).$(MinorBuildNumber).$(BuildNumber).$(BuildRevision) + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bafunctions/WixBootstrapperBAFunction.cpp b/bafunctions/WixBootstrapperBAFunction.cpp new file mode 100644 index 0000000..f4739a0 --- /dev/null +++ b/bafunctions/WixBootstrapperBAFunction.cpp @@ -0,0 +1,278 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +//------------------------------------------------------------------------------------------------- + + +#include "precomp.h" + +class CWixBootstrapperBAFunction : IBootstrapperBAFunction +{ +public: + STDMETHODIMP OnDetect() + { + HRESULT hr = S_OK; + HKEY hkKey = NULL; + LPWSTR sczValue = NULL; + LPWSTR sczFormatedValue = NULL; + + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Running detect BA function"); + + //--------------------------------------------------------------------------------------------- + // Example of BA function failure + //hr = E_NOTIMPL; + //BalExitOnFailure(hr, "Test failure."); + //--------------------------------------------------------------------------------------------- + + //--------------------------------------------------------------------------------------------- + // Example of setting a variables + hr = m_pEngine->SetVariableString(L"Variable1", L"String value"); + BalExitOnFailure(hr, "Failed to set variable."); + hr = m_pEngine->SetVariableNumeric(L"Variable2", 1234); + BalExitOnFailure(hr, "Failed to set variable."); + //--------------------------------------------------------------------------------------------- + + //--------------------------------------------------------------------------------------------- + // Example of reading burn variable. + BalGetStringVariable(L"WixBundleName", &sczValue); + BalExitOnFailure(hr, "Failed to get variable."); + + hr = m_pEngine->SetVariableString(L"Variable4", sczValue); + BalExitOnFailure(hr, "Failed to set variable."); + //--------------------------------------------------------------------------------------------- + + ReleaseNullStr(sczValue); // Release string so it can be re-used + + //--------------------------------------------------------------------------------------------- + // Examples of reading burn variable and formatting it. + BalGetStringVariable(L"InstallFolder", &sczValue); + BalExitOnFailure(hr, "Failed to get variable."); + + hr = m_pEngine->SetVariableString(L"Variable5", sczValue); + BalExitOnFailure(hr, "Failed to set variable."); + + BalFormatString(sczValue, &sczFormatedValue); + BalExitOnFailure(hr, "Failed to format variable."); + + hr = m_pEngine->SetVariableString(L"Variable6", sczFormatedValue); + BalExitOnFailure(hr, "Failed to set variable."); + //--------------------------------------------------------------------------------------------- + + ReleaseNullStr(sczValue); // Release string so it can be re-used + + //--------------------------------------------------------------------------------------------- + BalFormatString(L"WixBundleVersion=[WixBundleVersion]", &sczValue); + BalExitOnFailure(hr, "Failed to format variable."); + + hr = m_pEngine->SetVariableString(L"Variable7", sczValue); + BalExitOnFailure(hr, "Failed to set variable."); + //--------------------------------------------------------------------------------------------- + + ReleaseNullStr(sczValue); // Release string so it can be re-used + + //--------------------------------------------------------------------------------------------- + // Example of reading 64 bit registry and setting the InstallFolder variable to the value read. + hr = RegOpen(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.5", KEY_READ | KEY_WOW64_64KEY, &hkKey); + BalExitOnFailure(hr, "Failed to open registry key."); + + hr = RegReadString(hkKey, L"InstallPath", &sczValue); + BalExitOnFailure(hr, "Failed to read registry value."); + + // Example of function call + PathBackslashTerminate(&sczValue); + + hr = m_pEngine->SetVariableString(L"InstallFolder", sczValue); + BalExitOnFailure(hr, "Failed to set variable."); + //--------------------------------------------------------------------------------------------- + + ReleaseNullStr(sczValue); // Release string so it can be re-used + + //--------------------------------------------------------------------------------------------- + hr = PathRelativeToModule(&sczValue, NULL, m_hModule); + hr = m_pEngine->SetVariableString(L"ModulePath", sczValue); + //--------------------------------------------------------------------------------------------- + + ReleaseNullStr(sczValue); // Release string so it can be re-used + + //--------------------------------------------------------------------------------------------- + hr = GetFileVersion(); + BalExitOnFailure(hr, "Failed to get version."); + //--------------------------------------------------------------------------------------------- + + //--------------------------------------------------------------------------------------------- + // Delay start to show splashscreen handling + Delay(); + //--------------------------------------------------------------------------------------------- + + LExit: + ReleaseRegKey(hkKey); + ReleaseStr(sczValue); + ReleaseStr(sczFormatedValue); + + return hr; + } + + + STDMETHODIMP OnDetectComplete() { return S_OK; } + + +/* + STDMETHODIMP OnDetectComplete() + { + HRESULT hr = S_OK; + + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Running detect complete BA function"); + + //------------------------------------------------------------------------------------------------- + // YOUR CODE GOES HERE + BalExitOnFailure(hr, "Change this message to represent real error handling."); + //------------------------------------------------------------------------------------------------- + + LExit: + return hr; + } +*/ + + + STDMETHODIMP OnPlan() + { + HRESULT hr = S_OK; + + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Running plan BA function"); + + //--------------------------------------------------------------------------------------------- + // Example of converting 4 radio button values in to 1 + LONGLONG llValue = 0; + if (SUCCEEDED(BalGetNumericVariable(L"RadioButton1", &llValue)) && llValue) + { + m_pEngine->SetVariableNumeric(L"RadioButton", 1); + BalExitOnFailure(hr, "Failed to set variable."); + } + else if (SUCCEEDED(BalGetNumericVariable(L"RadioButton2", &llValue)) && llValue) + { + m_pEngine->SetVariableNumeric(L"RadioButton", 2); + BalExitOnFailure(hr, "Failed to set variable."); + } + else if (SUCCEEDED(BalGetNumericVariable(L"RadioButton3", &llValue)) && llValue) + { + m_pEngine->SetVariableNumeric(L"RadioButton", 3); + BalExitOnFailure(hr, "Failed to set variable."); + } + else if (SUCCEEDED(BalGetNumericVariable(L"RadioButton4", &llValue)) && llValue) + { + m_pEngine->SetVariableNumeric(L"RadioButton", 4); + BalExitOnFailure(hr, "Failed to set variable."); + } + else + { + m_pEngine->SetVariableNumeric(L"RadioButton", 0); + BalExitOnFailure(hr, "Failed to set variable."); + } + //--------------------------------------------------------------------------------------------- + + LExit: + return hr; + } + + + STDMETHODIMP OnPlanComplete() + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Running plan complete BA function"); + return S_OK; + } + +private: + //--------------------------------------------------------------------------------------------- + // Example of function call to get the file version of this bundle + //--------------------------------------------------------------------------------------------- + HRESULT GetFileVersion() + { + HRESULT hr = S_OK; + LPWSTR sczValue = NULL; + ULARGE_INTEGER uliVersion = { }; + + BalFormatString(L"[WixBundleOriginalSource]", &sczValue); + BalExitOnFailure(hr, "Failed to format variable."); + + FileVersion(sczValue, &uliVersion.HighPart, &uliVersion.LowPart); + BalExitOnFailure(hr, "Failed to get file version."); + + hr = m_pEngine->SetVariableVersion(L"FileVersion", uliVersion.QuadPart); + BalExitOnFailure(hr, "Failed to set variable."); + + LExit: + ReleaseStr(sczValue); + + return hr; + } + + + HRESULT Delay() + { + HRESULT hr = S_OK; + LONGLONG llDelay = 0; + + BalGetNumericVariable(L"DelayStart", &llDelay); + if (llDelay) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Delay for %dms", (DWORD)llDelay); + ::Sleep((DWORD)llDelay); + } + + return hr; + } + + +private: + HMODULE m_hModule; + IBootstrapperEngine* m_pEngine; + + +public: + // + // Constructor - initialize member variables. + // + CWixBootstrapperBAFunction( + __in IBootstrapperEngine* pEngine, + __in HMODULE hModule + ) + { + m_hModule = hModule; + m_pEngine = pEngine; + } + + // + // Destructor - release member variables. + // + ~CWixBootstrapperBAFunction() + { + } +}; + + +extern "C" HRESULT WINAPI CreateBootstrapperBAFunction( + __in IBootstrapperEngine* pEngine, + __in HMODULE hModule, + __out CWixBootstrapperBAFunction** ppBAFunction + ) +{ + HRESULT hr = S_OK; + CWixBootstrapperBAFunction* pBAFunction = NULL; + + // This is required to enable logging functions + BalInitialize(pEngine); + + pBAFunction = new CWixBootstrapperBAFunction(pEngine, hModule); + ExitOnNull(pBAFunction, hr, E_OUTOFMEMORY, "Failed to create new bootstrapper BA function object."); + + *ppBAFunction = pBAFunction; + pBAFunction = NULL; + +LExit: + delete pBAFunction; + return hr; +} diff --git a/bafunctions/bafunctions.cpp b/bafunctions/bafunctions.cpp new file mode 100644 index 0000000..16b6543 --- /dev/null +++ b/bafunctions/bafunctions.cpp @@ -0,0 +1,37 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +// +// +// Entry point for bootstrapper BA function DLL. +// +//------------------------------------------------------------------------------------------------- + +#include "precomp.h" + +static HINSTANCE vhInstance = NULL; + +extern "C" BOOL WINAPI DllMain( + IN HINSTANCE hInstance, + IN DWORD dwReason, + IN LPVOID /* pvReserved */ + ) +{ + switch(dwReason) + { + case DLL_PROCESS_ATTACH: + ::DisableThreadLibraryCalls(hInstance); + vhInstance = hInstance; + break; + + case DLL_PROCESS_DETACH: + vhInstance = NULL; + break; + } + + return TRUE; +} diff --git a/bafunctions/bafunctions.def b/bafunctions/bafunctions.def new file mode 100644 index 0000000..6e721f1 --- /dev/null +++ b/bafunctions/bafunctions.def @@ -0,0 +1,16 @@ +;------------------------------------------------------------------------------------------------- +; +; Copyright (c) 2004, Outercurve Foundation. +; This software is released under Microsoft Reciprocal License (MS-RL). +; The license and further copyright text can be found in the file +; LICENSE.TXT at the root directory of the distribution. +; +; +; +; Bootstrapper Application function DLL entry points. +; +;------------------------------------------------------------------------------------------------- + +EXPORTS + CreateBootstrapperBAFunction + diff --git a/bafunctions/bafunctions.rc b/bafunctions/bafunctions.rc new file mode 100644 index 0000000..d3fcf9f --- /dev/null +++ b/bafunctions/bafunctions.rc @@ -0,0 +1,129 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +// +// +// WiX Extendend Bootstrapper BA function resource file. +// +//------------------------------------------------------------------------------------------------- + +#include +#include +#include "bafunctionsver.h" + +#define VER_APP +#define VER_ORIGINAL_FILENAME "bafunctions.dll" +#define VER_INTERNAL_NAME "bafunctions" +#define VER_PRODUCT_NAME "WiX Bootstrapper functions" +#define VER_FILE_DESCRIPTION "WiX Bootstrapper functions" + +#ifdef DEBUG + #define VER_DEBUG VS_FF_DEBUG + #define VER_PRIVATE_BUILD VS_FF_PRIVATEBUILD + #define VER_PRE_RELEASE (VS_FF_PRERELEASE | VS_FF_SPECIALBUILD) +#else + #define VER_DEBUG 0 + #define VER_PRIVATE_BUILD 0 + #define VER_PRE_RELEASE 0 +#endif + +#if defined(VER_APP) + #define VER_FILE_TYPE VFT_APP +#elif defined(VER_DLL) + #define VER_FILE_TYPE VFT_DLL +#elif defined(VER_TYPELIB) + #define VER_FILE_TYPE VFT_UNKNOWN +#else + #define VER_FILE_TYPE VFT_UNKNOWN +#endif + +#if defined(VER_LANG_NEUTRAL) + #ifndef VER_LANG + #define VER_LANG 0x0000 + #endif + #ifndef VER_CP + #define VER_CP 0x04E4 + #endif + #ifndef VER_BLOCK + #define VER_BLOCK "000004E4" + #endif +#else + #ifndef VER_LANG + #define VER_LANG 0x0409 + #endif + #ifndef VER_CP + #define VER_CP 0x04E4 + #endif + #ifndef VER_BLOCK + #define VER_BLOCK "040904E4" + #endif +#endif + +#define VER_FILE_VERSION rmj, rmm, rbd, rev +#define VER_PRODUCT_VERSION rmj, rmm, rbd, rev +#define VER_FILE_VERSION_STRING szVerMajorMinorBuildRev +#define VER_PRODUCT_VERSION_STRING VER_FILE_VERSION_STRING +#define VER_FILE_FLAGS_MASK VS_FFI_FILEFLAGSMASK +#define VER_FILE_FLAGS (VER_DEBUG | VER_PRIVATE_BUILD | VER_PRE_RELEASE) + +#define VER_FILE_OS VOS__WINDOWS32 + +#define VER_COMPANY_NAME "Outercurve Foundation" +#ifndef VER_PRODUCT_NAME + #define VER_PRODUCT_NAME "Windows Installer XML (WiX)" +#endif +#ifndef VER_FILE_DESCRIPTION + #define VER_FILE_DESCRIPTION "Windows Installer XML (WiX) component" +#endif + +#if defined(VER_LEGAL_COPYRIGHT) + #error +#endif +#define VER_LEGAL_COPYRIGHT "Copyright (c) Outercurve Foundation.\240 All rights reserved." + +#if !defined(VER_FILE_SUBTYPE) + #define VER_FILE_SUBTYPE 0 +#endif + +#ifdef RC_INVOKED + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILE_VERSION +PRODUCTVERSION VER_PRODUCT_VERSION +FILEFLAGSMASK VER_FILE_FLAGS_MASK +FILEFLAGS VER_FILE_FLAGS +FILEOS VER_FILE_OS +FILETYPE VER_FILE_TYPE +FILESUBTYPE VER_FILE_SUBTYPE +BEGIN +BLOCK "StringFileInfo" + BEGIN + BLOCK VER_BLOCK + BEGIN + VALUE "CompanyName", VER_COMPANY_NAME + VALUE "FileDescription", VER_FILE_DESCRIPTION + VALUE "FileVersion", VER_FILE_VERSION_STRING + VALUE "InternalName", VER_INTERNAL_NAME + + VALUE "LegalCopyright", VER_LEGAL_COPYRIGHT + + VALUE "OriginalFilename", VER_ORIGINAL_FILENAME + VALUE "ProductName", VER_PRODUCT_NAME + VALUE "ProductVersion", VER_FILE_VERSION_STRING +#if defined(DEBUG) + VALUE "WiX Common Resource Format", "Debug Only" +#endif + END + END + +BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", VER_LANG, VER_CP + END +END + +#endif diff --git a/bafunctions/bafunctions.vcxproj b/bafunctions/bafunctions.vcxproj new file mode 100644 index 0000000..83d9607 --- /dev/null +++ b/bafunctions/bafunctions.vcxproj @@ -0,0 +1,137 @@ + + + + + + Debug + Win32 + + + Release + Win32 + + + + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02} + BaFunctions + Win32Proj + DynamicLibrary + MultiByte + bafunctions + + + + v120 + + + v120 + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(Configuration)\ + $(Configuration)\ + true + AllRules.ruleset + + + $(Configuration)\ + $(Configuration)\ + true + AllRules.ruleset + + + + + + + + + + Disabled + $(WiX)SDK\VS2010\inc;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;DEBUG;%(PreprocessorDefinitions);$(ExtraDefinitions) + true + EnableFastChecks + MultiThreadedDebug + Use + precomp.h + $(IntDir)$(ProjectName).pdb + Level4 + ProgramDatabase + StdCall + true + + + %(AdditionalIncludeDirectories) + + + dutil.lib;balutil.lib;comctl32.lib;gdiplus.lib;shlwapi.lib;wininet.lib;version.lib;%(AdditionalDependencies) + $(WiX)SDK\VS2010\lib\x86;%(AdditionalLibraryDirectories) + bafunctions.def + true + Windows + + + + + Disabled + $(WiX)SDK\VS2010\inc;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);$(ExtraDefinitions) + true + EnableFastChecks + MultiThreaded + Use + precomp.h + $(IntDir)$(ProjectName).pdb + Level4 + ProgramDatabase + StdCall + true + + + %(AdditionalIncludeDirectories) + + + dutil.lib;balutil.lib;comctl32.lib;gdiplus.lib;shlwapi.lib;wininet.lib;version.lib;%(AdditionalDependencies) + $(WiX)SDK\VS2010\lib\x86;%(AdditionalLibraryDirectories) + bafunctions.def + false + Windows + + + + + + Create + Create + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bafunctions/bafunctions.vcxproj.filters b/bafunctions/bafunctions.vcxproj.filters new file mode 100644 index 0000000..b77f5c3 --- /dev/null +++ b/bafunctions/bafunctions.vcxproj.filters @@ -0,0 +1,46 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + Source Files + + + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/bafunctions/bafunctionsver.h b/bafunctions/bafunctionsver.h new file mode 100644 index 0000000..7b0d107 --- /dev/null +++ b/bafunctions/bafunctionsver.h @@ -0,0 +1,12 @@ +// +#ifndef _VERSION_FILE_H_ +#define _VERSION_FILE_H_ + +#define szVerMajorMinor "1.0" +#define szVerMajorMinorBuildRev "1.0.5260.23891" +#define rmj 1 +#define rmm 0 +#define rbd 5260 +#define rev 23891 + +#endif diff --git a/bafunctions/build.bat b/bafunctions/build.bat new file mode 100644 index 0000000..c6578de --- /dev/null +++ b/bafunctions/build.bat @@ -0,0 +1,25 @@ +@echo off + +echo Configuring environment... +set MSBUILD="%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe" +echo. + +set outdir=%~dp0build + +%MSBUILD% Version.proj +%MSBUILD% bafunctions.vcxproj /t:Rebuild /p:Configuration=Release,Platform=Win32 /p:RunCodeAnalysis=false /p:DefineConstants="TRACE" /p:OutDir="%outdir%\\" /l:FileLogger,Microsoft.Build.Engine;logfile=build.log +if %errorlevel% neq 0 ( + echo Build failed + pause + goto :EOF +) + +copy build\bafunctions.dll ..\Examples /y + +echo. + +goto :EOF + +REM ***************************************************************** +REM End of Main +REM ***************************************************************** diff --git a/bafunctions/precomp.h b/bafunctions/precomp.h new file mode 100644 index 0000000..a90e2a4 --- /dev/null +++ b/bafunctions/precomp.h @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +// +// +// Precompiled header for standard bootstrapper application. +// +//------------------------------------------------------------------------------------------------- + +#pragma once + + +#include +#include +#include +#include +#include +#include +#include +#include + +// Standard WiX header files, include as required +#include "dutil.h" +//#include "memutil.h" +//#include "dictutil.h" +//#include "dirutil.h" +#include "fileutil.h" +//#include "locutil.h" +//#include "logutil.h" +#include "pathutil.h" +//#include "resrutil.h" +//#include "shelutil.h" +#include "strutil.h" +//#include "thmutil.h" +//#include "uriutil.h" +//#include "xmlutil.h" +#include "regutil.h" + +//#include "IBootstrapperEngine.h" +//#include "IBootstrapperApplication.h" + +#include "BalBaseBootstrapperApplication.h" +//#include "balinfo.h" +//#include "balcondition.h" +#include "balutil.h" + +#include "IBootstrapperBAFunction.h" + diff --git a/bafunctions/resource.h b/bafunctions/resource.h new file mode 100644 index 0000000..53c03c3 --- /dev/null +++ b/bafunctions/resource.h @@ -0,0 +1,25 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +//------------------------------------------------------------------------------------------------- + +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// +#define IDC_STATIC -1 + + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1003 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..90d8beb --- /dev/null +++ b/build.bat @@ -0,0 +1,44 @@ +@echo off + +echo Configuring environment... +set MSBUILD="%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe" +echo. + +set outdir=%~dp0build + +echo Removing release folder... +Call :DeleteDir "%outdir%" +Call :DeleteDir "ipch" + +%MSBUILD% inc\Version.proj +%MSBUILD% bafunctions\Version.proj +%MSBUILD% BalExtensionExt.sln /t:Rebuild /p:Configuration=Release /p:Platform="Mixed Platforms" /p:RunCodeAnalysis=false /p:DefineConstants="TRACE" /p:OutDir="%outdir%\\" /l:FileLogger,Microsoft.Build.Engine;logfile=build.log +if %errorlevel% neq 0 ( + echo Build failed + pause + goto :EOF +) + +copy build\bafunctions.dll Examples /y + +pushd Examples +Call Build +popd + +echo. + +pause + +goto :EOF + +REM ***************************************************************** +REM End of Main +REM ***************************************************************** + + +REM ***************************************************************** +REM Delete/create directory +REM ***************************************************************** +:DeleteDir +rd %1% /q/s 2>nul 1>nul +goto :EOF diff --git a/build/WixBalExtensionExt.dll b/build/WixBalExtensionExt.dll new file mode 100644 index 0000000..5ab6898 Binary files /dev/null and b/build/WixBalExtensionExt.dll differ diff --git a/build/balExt.wixlib b/build/balExt.wixlib new file mode 100644 index 0000000..38368c2 Binary files /dev/null and b/build/balExt.wixlib differ diff --git a/inc/Version.proj b/inc/Version.proj new file mode 100644 index 0000000..42ab9c5 --- /dev/null +++ b/inc/Version.proj @@ -0,0 +1,100 @@ + + + + 3 + 8 + + .\wixver.h + .\wixver.cs + + + + $([System.DateTime]::new(2000, 1, 1)) + $([System.Convert]::ToInt32($([System.DateTime]::Now.ToUniversalTime().Subtract($(Base)).TotalDays))) + $([System.Convert]::ToInt32($([MSBuild]::Divide($([System.Convert]::ToInt32($([System.DateTime]::Now.ToUniversalTime().TimeOfDay.TotalSeconds))), 2)))) + + $(MajorBuildNumber).$(MinorBuildNumber).$(BuildNumber).$(BuildRevision) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inc/WixDistribution.cs b/inc/WixDistribution.cs new file mode 100644 index 0000000..54e7d1d --- /dev/null +++ b/inc/WixDistribution.cs @@ -0,0 +1,13 @@ +using System.Reflection; +using System.Resources; + +[assembly: AssemblyCompany("Outercurve Foundation")] +[assembly: AssemblyCopyright("Copyright © Outercurve Foundation. All rights reserved.")] +[assembly: AssemblyTrademark("")] +#if DEBUG + [assembly: AssemblyConfiguration("DEBUG")] +#else + [assembly: AssemblyConfiguration("")] +#endif +[assembly: NeutralResourcesLanguage("en-US")] +[assembly: AssemblyProduct("Windows Installer XML")] diff --git a/inc/WixDistribution.h b/inc/WixDistribution.h new file mode 100644 index 0000000..4151907 --- /dev/null +++ b/inc/WixDistribution.h @@ -0,0 +1,17 @@ +/* ************************************************************************** + * WixDistribution.h file contains disribution specific items, such as + * Product Name. + * + * **************************************************************************/ + +#pragma once + +#ifndef __WIXDISTRIBUTION_FILE_H_ +#define __WIXDISTRIBUTION_FILE_H_ + +#ifdef VER_PRODUCT_NAME + #undef VER_PRODUCT_NAME +#endif +#define VER_PRODUCT_NAME "Windows Installer XML" + +#endif // __WIXDISTRIBUTION_FILE_H_ diff --git a/inc/wix.rc b/inc/wix.rc new file mode 100644 index 0000000..8c418b4 --- /dev/null +++ b/inc/wix.rc @@ -0,0 +1,140 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +// +// +// Common resource file for any native wix resources. +// +// +// Usage: +// #define VER_APP (VER_DLL, VER_TYPELIB, none) +// #define VER_LANG_NEUTRAL (optional) +// #define VER_ORIGINAL_FILENAME "FooBar.Exe" +// #define VER_INTERNAL_NAME "FooBar" +// #define VER_PRODUCT_NAME +// #define VER_FILE_DESCRIPTION +// #include "wix.rc" +// +// Optional to add before the #include (must add as a group and VER_BLOCK must match to VER_LANG and VER_CP) +// You should not have to do this except for some extreme cases. +// #define VER_LANG 0x0000 +// #define VER_CP 0x04E4 +// #define VER_BLOCK "000004E4" +// +//------------------------------------------------------------------------------------------------- + +#include +#include +#include "wixver.h" +#include "WixDistribution.h" + +#ifdef DEBUG + #define VER_DEBUG VS_FF_DEBUG + #define VER_PRIVATE_BUILD VS_FF_PRIVATEBUILD + #define VER_PRE_RELEASE (VS_FF_PRERELEASE | VS_FF_SPECIALBUILD) +#else + #define VER_DEBUG 0 + #define VER_PRIVATE_BUILD 0 + #define VER_PRE_RELEASE 0 +#endif + +#if defined(VER_APP) + #define VER_FILE_TYPE VFT_APP +#elif defined(VER_DLL) + #define VER_FILE_TYPE VFT_DLL +#elif defined(VER_TYPELIB) + #define VER_FILE_TYPE VFT_UNKNOWN +#else + #define VER_FILE_TYPE VFT_UNKNOWN +#endif + +#if defined(VER_LANG_NEUTRAL) + #ifndef VER_LANG + #define VER_LANG 0x0000 + #endif + #ifndef VER_CP + #define VER_CP 0x04E4 + #endif + #ifndef VER_BLOCK + #define VER_BLOCK "000004E4" + #endif +#else + #ifndef VER_LANG + #define VER_LANG 0x0409 + #endif + #ifndef VER_CP + #define VER_CP 0x04E4 + #endif + #ifndef VER_BLOCK + #define VER_BLOCK "040904E4" + #endif +#endif + +#define VER_FILE_VERSION rmj, rmm, rbd, rev +#define VER_PRODUCT_VERSION rmj, rmm, rbd, rev +#define VER_FILE_VERSION_STRING szVerMajorMinorBuildRev +#define VER_PRODUCT_VERSION_STRING VER_FILE_VERSION_STRING +#define VER_FILE_FLAGS_MASK VS_FFI_FILEFLAGSMASK +#define VER_FILE_FLAGS (VER_DEBUG | VER_PRIVATE_BUILD | VER_PRE_RELEASE) + +#define VER_FILE_OS VOS__WINDOWS32 + +#define VER_COMPANY_NAME "Outercurve Foundation" +#ifndef VER_PRODUCT_NAME + #define VER_PRODUCT_NAME "Windows Installer XML (WiX)" +#endif +#ifndef VER_FILE_DESCRIPTION + #define VER_FILE_DESCRIPTION "Windows Installer XML (WiX) component" +#endif + +#if defined(VER_LEGAL_COPYRIGHT) + #error +#endif +#define VER_LEGAL_COPYRIGHT "Copyright (c) Outercurve Foundation.\240 All rights reserved." + +#if !defined(VER_FILE_SUBTYPE) + #define VER_FILE_SUBTYPE 0 +#endif + +#ifdef RC_INVOKED + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILE_VERSION +PRODUCTVERSION VER_PRODUCT_VERSION +FILEFLAGSMASK VER_FILE_FLAGS_MASK +FILEFLAGS VER_FILE_FLAGS +FILEOS VER_FILE_OS +FILETYPE VER_FILE_TYPE +FILESUBTYPE VER_FILE_SUBTYPE +BEGIN +BLOCK "StringFileInfo" + BEGIN + BLOCK VER_BLOCK + BEGIN + VALUE "CompanyName", VER_COMPANY_NAME + VALUE "FileDescription", VER_FILE_DESCRIPTION + VALUE "FileVersion", VER_FILE_VERSION_STRING + VALUE "InternalName", VER_INTERNAL_NAME + + VALUE "LegalCopyright", VER_LEGAL_COPYRIGHT + + VALUE "OriginalFilename", VER_ORIGINAL_FILENAME + VALUE "ProductName", VER_PRODUCT_NAME + VALUE "ProductVersion", VER_FILE_VERSION_STRING +#if defined(DEBUG) + VALUE "WiX Common Resource Format", "Debug Only" +#endif + END + END + +BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", VER_LANG, VER_CP + END +END + +#endif diff --git a/inc/wixver.cs b/inc/wixver.cs new file mode 100644 index 0000000..e82ef78 --- /dev/null +++ b/inc/wixver.cs @@ -0,0 +1,4 @@ +// +using System.Reflection; +[assembly:AssemblyVersion("3.0.0.0")] +[assembly:AssemblyFileVersion("3.8.5260.23891")] diff --git a/inc/wixver.h b/inc/wixver.h new file mode 100644 index 0000000..ba6381f --- /dev/null +++ b/inc/wixver.h @@ -0,0 +1,13 @@ +// +#ifndef _VERSION_FILE_H_ +#define _VERSION_FILE_H_ + +#define szVerMajorMinor "3.8" +#define szVerMajorMinorBuildRev "3.8.5260.23891" +#define rmj 3 +#define rmm 8 +#define rbd 5260 +#define rev 23891 +#define szVerName "BalExtensionExt Release" + +#endif diff --git a/wixext/BalCompiler.cs b/wixext/BalCompiler.cs new file mode 100644 index 0000000..b2b77e5 --- /dev/null +++ b/wixext/BalCompiler.cs @@ -0,0 +1,373 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +// +// +// The compiler for the Windows Installer XML Toolset Bal Extension. +// +//------------------------------------------------------------------------------------------------- + +namespace Microsoft.Tools.WindowsInstallerXml.Extensions +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Globalization; + using System.IO; + using System.Reflection; + using System.Xml; + using System.Xml.Schema; + using Microsoft.Tools.WindowsInstallerXml; + + /// + /// The compiler for the Windows Installer XML Toolset Bal Extension. + /// + public sealed class BalCompiler : CompilerExtension + { + private SourceLineNumberCollection addedConditionLineNumber; + private XmlSchema schema; + + /// + /// Instantiate a new BalCompiler. + /// + public BalCompiler() + { + this.addedConditionLineNumber = null; + this.schema = LoadXmlSchemaHelper(Assembly.GetExecutingAssembly(), "Microsoft.Tools.WindowsInstallerXml.Extensions.Xsd.bal.xsd"); + } + + /// + /// Gets the schema for this extension. + /// + /// Schema for this extension. + public override XmlSchema Schema + { + get { return this.schema; } + } + + /// + /// Processes an element for the Compiler. + /// + /// Source line number for the parent element. + /// Parent element of element to process. + /// Element to process. + /// Extra information about the context in which this element is being parsed. + public override void ParseElement(SourceLineNumberCollection sourceLineNumbers, XmlElement parentElement, XmlElement element, params string[] contextValues) + { + switch (parentElement.LocalName) + { + case "Bundle": + case "Fragment": + switch (element.LocalName) + { + case "Condition": + this.ParseConditionElement(element); + break; + default: + this.Core.UnexpectedElement(parentElement, element); + break; + } + break; + case "BootstrapperApplicationRef": + switch (element.LocalName) + { + case "WixExtendedBootstrapperApplication": + this.ParseWixExtendedBootstrapperApplicationElement(element); + break; + default: + this.Core.UnexpectedElement(parentElement, element); + break; + } + break; + default: + this.Core.UnexpectedElement(parentElement, element); + break; + } + } + + /// + /// Processes an attribute for the Compiler. + /// + /// Source line number for the parent element. + /// Parent element of element to process. + /// Attribute to process. + /// Extra information about the context in which this element is being parsed. + public override void ParseAttribute(SourceLineNumberCollection sourceLineNumbers, XmlElement parentElement, XmlAttribute attribute, Dictionary contextValues) + { + switch (parentElement.LocalName) + { + case "Variable": + // at the time the extension attribute is parsed, the compiler might not yet have + // parsed the Name attribute, so we need to get it directly from the parent element. + string variableName = parentElement.GetAttribute("Name"); + if (String.IsNullOrEmpty(variableName)) + { + this.Core.OnMessage(WixErrors.ExpectedParentWithAttribute(sourceLineNumbers, "Variable", "Overridable", "Name")); + } + else + { + switch (attribute.LocalName) + { + case "Overridable": + if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attribute)) + { + Row row = this.Core.CreateRow(sourceLineNumbers, "WixStdbaOverridableVariable"); + row[0] = variableName; + } + break; + default: + this.Core.UnexpectedAttribute(sourceLineNumbers, attribute); + break; + } + } + break; + default: + this.Core.UnexpectedAttribute(sourceLineNumbers, attribute); + break; + } + } + + /// + /// Parses a Condition element for Bundles. + /// + /// The element to parse. + private void ParseConditionElement(XmlNode node) + { + SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + string condition = CompilerCore.GetConditionInnerText(node); // condition is the inner text of the element. + string message = null; + + foreach (XmlAttribute attrib in node.Attributes) + { + if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace) + { + switch (attrib.LocalName) + { + case "Message": + message = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); + break; + default: + this.Core.UnexpectedAttribute(sourceLineNumbers, attrib); + break; + } + } + else + { + this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib); + } + } + + foreach (XmlNode child in node.ChildNodes) + { + if (XmlNodeType.Element == child.NodeType) + { + if (child.NamespaceURI == this.schema.TargetNamespace) + { + this.Core.UnexpectedElement(node, child); + } + else + { + this.Core.UnsupportedExtensionElement(node, child); + } + } + } + + // Error check the values. + if (String.IsNullOrEmpty(condition)) + { + this.Core.OnMessage(WixErrors.ConditionExpected(sourceLineNumbers, node.Name)); + } + + if (null == message) + { + this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Message")); + } + + if (!this.Core.EncounteredError) + { + Row row = this.Core.CreateRow(sourceLineNumbers, "WixBalCondition"); + row[0] = condition; + row[1] = message; + + if (null == this.addedConditionLineNumber) + { + this.addedConditionLineNumber = sourceLineNumbers; + } + } + } + + /// + /// Parses a WixExtendedBootstrapperApplication element for Bundles. + /// + /// The element to parse. + private void ParseWixExtendedBootstrapperApplicationElement(XmlNode node) + { + SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + string launchTarget = null; + string licenseFile = null; + string licenseUrl = null; + string logoFile = null; + string logoSideFile = null; + string themeFile = null; + string localizationFile = null; + YesNoType suppressOptionsUI = YesNoType.NotSet; + YesNoType suppressDowngradeFailure = YesNoType.NotSet; + YesNoType suppressRepair = YesNoType.NotSet; + YesNoType showVersion = YesNoType.NotSet; + YesNoType launchPassive = YesNoType.NotSet; + YesNoType launchQuiet = YesNoType.NotSet; + + foreach (XmlAttribute attrib in node.Attributes) + { + if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace) + { + switch (attrib.LocalName) + { + case "LaunchTarget": + launchTarget = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); + break; + case "LicenseFile": + licenseFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); + break; + case "LicenseUrl": + licenseUrl = this.Core.GetAttributeValue(sourceLineNumbers, attrib, true); + break; + case "LogoFile": + logoFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); + break; + case "LogoSideFile": + logoSideFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); + break; + case "ThemeFile": + themeFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); + break; + case "LocalizationFile": + localizationFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib, false); + break; + case "SuppressOptionsUI": + suppressOptionsUI = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "LaunchPassive": + launchPassive = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "LaunchQuiet": + launchQuiet = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "SuppressDowngradeFailure": + suppressDowngradeFailure = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "SuppressRepair": + suppressRepair = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "ShowVersion": + showVersion = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + default: + this.Core.UnexpectedAttribute(sourceLineNumbers, attrib); + break; + } + } + else + { + this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib); + } + } + + foreach (XmlNode child in node.ChildNodes) + { + if (XmlNodeType.Element == child.NodeType) + { + if (child.NamespaceURI == this.schema.TargetNamespace) + { + this.Core.UnexpectedElement(node, child); + } + else + { + this.Core.UnsupportedExtensionElement(node, child); + } + } + } + + if (String.IsNullOrEmpty(licenseFile) && null == licenseUrl) + { + this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "LicenseFile", "LicenseUrl", true)); + } + + if (!this.Core.EncounteredError) + { + if (!String.IsNullOrEmpty(launchTarget)) + { + this.Core.CreateVariableRow(sourceLineNumbers, "LaunchTarget", launchTarget, "string", false, false); + } + + if (!String.IsNullOrEmpty(licenseFile)) + { + this.Core.CreateWixVariableRow(sourceLineNumbers, "WixExtbaLicenseRtf", licenseFile, false); + } + + if (null != licenseUrl) + { + this.Core.CreateWixVariableRow(sourceLineNumbers, "WixExtbaLicenseUrl", licenseUrl, false); + } + + if (!String.IsNullOrEmpty(logoFile)) + { + this.Core.CreateWixVariableRow(sourceLineNumbers, "WixExtbaLogo", logoFile, false); + } + + if (!String.IsNullOrEmpty(logoSideFile)) + { + this.Core.CreateWixVariableRow(sourceLineNumbers, "WixExtbaLogoSide", logoSideFile, false); + } + + if (!String.IsNullOrEmpty(themeFile)) + { + this.Core.CreateWixVariableRow(sourceLineNumbers, "WixExtbaThemeXml", themeFile, false); + } + + if (!String.IsNullOrEmpty(localizationFile)) + { + this.Core.CreateWixVariableRow(sourceLineNumbers, "WixExtbaThemeWxl", localizationFile, false); + } + + if (YesNoType.Yes == suppressOptionsUI || YesNoType.Yes == suppressDowngradeFailure || YesNoType.Yes == suppressRepair) + { + Row row = this.Core.CreateRow(sourceLineNumbers, "WixExtbaOptions"); + if (YesNoType.Yes == suppressOptionsUI) + { + row[0] = 1; + } + + if (YesNoType.Yes == suppressDowngradeFailure) + { + row[1] = 1; + } + + if (YesNoType.Yes == suppressRepair) + { + row[2] = 1; + } + + if (YesNoType.Yes == showVersion) + { + row[3] = 1; + } + + if (YesNoType.Yes == launchPassive) + { + row[4] = 1; + } + + if (YesNoType.Yes == launchQuiet) + { + row[5] = 1; + } + } + } + } + } +} diff --git a/wixext/BalExtension.cs b/wixext/BalExtension.cs new file mode 100644 index 0000000..ae0ba2c --- /dev/null +++ b/wixext/BalExtension.cs @@ -0,0 +1,96 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +// +// +// The Windows Installer XML Toolset Bal extension. +// +//------------------------------------------------------------------------------------------------- + +namespace Microsoft.Tools.WindowsInstallerXml.Extensions +{ + using System; + using System.Reflection; + + /// + /// The Windows Installer XML Toolset Bal Extension. + /// + public sealed class BalExtension : WixExtension + { + private BalCompiler compilerExtension; + private Library library; + private TableDefinitionCollection tableDefinitions; + + private BalPreprocessorExtension preprocessorExtension; + + /// + /// Gets the optional compiler extension. + /// + /// The optional compiler extension. + public override CompilerExtension CompilerExtension + { + get + { + if (null == this.compilerExtension) + { + this.compilerExtension = new BalCompiler(); + } + + return this.compilerExtension; + } + } + + /// + /// Gets the optional table definitions for this extension. + /// + /// The optional table definitions for this extension. + public override TableDefinitionCollection TableDefinitions + { + get + { + if (null == this.tableDefinitions) + { + this.tableDefinitions = LoadTableDefinitionHelper(Assembly.GetExecutingAssembly(), "Microsoft.Tools.WindowsInstallerXml.Extensions.Data.tables.xml"); + } + + return this.tableDefinitions; + } + } + + /// + /// Gets the library associated with this extension. + /// + /// The table definitions to use while loading the library. + /// The loaded library. + public override Library GetLibrary(TableDefinitionCollection tableDefinitions) + { + if (null == this.library) + { + this.library = LoadLibraryHelper(Assembly.GetExecutingAssembly(), "Microsoft.Tools.WindowsInstallerXml.Extensions.Data.balExt.wixlib", tableDefinitions); + } + + return this.library; + } + + /// + /// Gets the optional preprocessor extension. + /// + /// The optional preprocessor extension. + public override PreprocessorExtension PreprocessorExtension + { + get + { + if (null == this.preprocessorExtension) + { + this.preprocessorExtension = new BalPreprocessorExtension(); + } + + return this.preprocessorExtension; + } + } + } +} diff --git a/wixext/BalPreprocessorExtension.cs b/wixext/BalPreprocessorExtension.cs new file mode 100644 index 0000000..bd84548 --- /dev/null +++ b/wixext/BalPreprocessorExtension.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------------------------- +// +// +// +// +// A WiX preprocessor extension. +// +//------------------------------------------------------------------------------------------------- + +namespace Microsoft.Tools.WindowsInstallerXml.Extensions +{ + using System; + using Microsoft.Tools.WindowsInstallerXml; + + /// + /// The preprocessor extension. + /// + public sealed class BalPreprocessorExtension : PreprocessorExtension + { + private static readonly string[] prefixes = {"bal"}; + + /// + /// Gets the variable prefixes for this extension. + /// + /// The variable prefixes for this extension. + public override string[] Prefixes + { + get { return prefixes; } + } + + public override string EvaluateFunction(string prefix, string function, string[] args) + { + string result = null; + + switch (prefix) + { + case "bal": + switch (function) + { + case "Version": + // Make sure the base version is specified + if (args.Length == 0 || args[0].Length == 0) + { + throw new ArgumentException("Version template not specified"); + } + + // Build = days since 1/1/2000; Revision = seconds since midnight / 2 + DateTime now = DateTime.Now.ToUniversalTime(); + double build = (now - new DateTime(2000, 1, 1)).TotalDays; + double revision = now.TimeOfDay.TotalSeconds / 2; + + result = String.Format("{0}.{1}.{2}", args[0], (int)build, (int)revision); + + break; + } + + break; + } + + return result; + } + } +} diff --git a/wixext/Properties/AssemblyInfo.cs b/wixext/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..5081dc3 --- /dev/null +++ b/wixext/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file LICENSE.TXT +// LICENSE.TXT at the root directory of the distribution. +// +// +// +// The assembly information for the Windows Installer XML Toolset Bootstrapper Application Layer Extension. +// +//------------------------------------------------------------------------------------------------- + +using System; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using Microsoft.Tools.WindowsInstallerXml; +using Microsoft.Tools.WindowsInstallerXml.Extensions; + +[assembly: AssemblyTitle("WiX Toolset Bootstrapper Application Layer Extension")] +[assembly: AssemblyDescription("Windows Installer XML Toolset Bootstrapper Application Layer Extension")] +[assembly: AssemblyCulture("")] +[assembly: CLSCompliant(true)] +[assembly: ComVisible(false)] +[assembly: AssemblyDefaultWixExtension(typeof(BalExtension))] diff --git a/wixext/WixBalExtensionExt.csproj b/wixext/WixBalExtensionExt.csproj new file mode 100644 index 0000000..e693763 --- /dev/null +++ b/wixext/WixBalExtensionExt.csproj @@ -0,0 +1,88 @@ + + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05} + Library + Properties + Microsoft.Tools.WindowsInstallerXml.Extensions + WixBalExtensionExt + v2.0 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + False + $(WIX)bin\wix.dll + False + + + + + Properties\WixDistribution.cs + + + Properties\wixver.cs + + + + + + + $(RootNamespace).Data.Messages.resources + + + $(RootNamespace).Data.tables.xml + + + $(RootNamespace).Xsd.bal.xsd + PreserveNewest + + + Microsoft.Tools.WindowsInstallerXml.Serialize + Microsoft.Tools.WindowsInstallerXml.Extensions.Serialize.Bal + + + Data\balExt.wixlib + + + + + \ No newline at end of file diff --git a/wixext/Xsd/bal.xsd b/wixext/Xsd/bal.xsd new file mode 100644 index 0000000..152ae5e --- /dev/null +++ b/wixext/Xsd/bal.xsd @@ -0,0 +1,154 @@ + + + + + + The source code schema for the Windows Installer XML Toolset Burn User Experience Extension. + + + + + + + + + Conditions for a bundle. The condition is specified in the inner text of the element. + + + + + + + + + + + + The condition that must evaluate to true for the installation to continue. + + + + + + Set the value to the text to display when the condition fails and the installation must be terminated. + + + + + + + + + + + + Configures WixExtendedBootstrapperApplication for a Bundle. + + + + + + + + + If set, the success page will show a Launch button the user can use to launch the application being installed. The string value can be formatted using Burn variables enclosed in brackets, to refer to installation directories and so forth. + + + + + Source file of the RTF license file. Cannot be used simultaneously with LicenseUrl. + + + + + URL target of the license link. Cannot be used simultaneously with LicenseFile. This attribute can be empty to hide the license link completely. + + + + + Source file of the logo graphic. + + + + + Source file of the side logo graphic. + + + + + Source file of the theme XML. + + + + + Source file of the theme localization .wxl file. + + + + + If set to "yes", the Options button will not be shown and the user will not be able to choose an installation directory. + + + + + If set to "yes", the LaunchTarget option will be executed automatically at the end of a passive install. + + + + + If set to "yes", the LaunchTarget option will be executed automatically at the end of a quiet install. + + + + + If set to "yes", attempting to installer a downgraded version of a bundle will be treated as a successful do-nothing operation. + The default behavior (or when explicitly set to "no") is to treat downgrade attempts as failures. + + + + + If set to "yes", the Repair button will not be shown in the maintenance-mode UI. + + + + + If set to "yes", the application version will be displayed on the UI. + + + + + + + + + When set to "yes", lets the user override the variable's default value by specifying another value on the command line, + in the form Variable=Value. Otherwise, WixStdBA won't overwrite the default value and will log + "Ignoring attempt to set non-overridable variable: 'BAR'." + + + + + + + + + + Values of this type will either be "yes" or "no". + + + + + + + diff --git a/wixext/data/messages.xml b/wixext/data/messages.xml new file mode 100644 index 0000000..a902dc9 --- /dev/null +++ b/wixext/data/messages.xml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/wixext/data/tables.xml b/wixext/data/tables.xml new file mode 100644 index 0000000..7216e89 --- /dev/null +++ b/wixext/data/tables.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/wixlib/BalExtension.wixproj b/wixlib/BalExtension.wixproj new file mode 100644 index 0000000..c0d8c9c --- /dev/null +++ b/wixlib/BalExtension.wixproj @@ -0,0 +1,48 @@ + + + + + {3444d952-f21c-496f-ab6b-56435bfd0787} + balExt + Library + True + True + True + en-us + $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets + $(Configuration)\$(Platform) + True + + + ..\build\ + + + ..\build\ + + + + + + + + + + + + wixextba + {41085a22-e6aa-4e8b-ab1b-ddee0dc89dfa} + True + True + Binaries;Content;Satellites + INSTALLFOLDER + + + + \ No newline at end of file diff --git a/wixlib/BalExtension.wxs b/wixlib/BalExtension.wxs new file mode 100644 index 0000000..83f8203 --- /dev/null +++ b/wixlib/BalExtension.wxs @@ -0,0 +1,13 @@ + + + + + + diff --git a/wixlib/wixstdba.wxs b/wixlib/wixstdba.wxs new file mode 100644 index 0000000..5632880 --- /dev/null +++ b/wixlib/wixstdba.wxs @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + !(wix.WixExtbaLicenseRtfName=license.rtf) + + + + + + + + + + + + + + + !(wix.WixExtbaLicenseUrl) + + + + + + + + + + + + + + + + !(wix.WixExtbaLicenseUrl) + + + + + + + + + + + + diff --git a/wixlib/wixstdba_platform.wxi b/wixlib/wixstdba_platform.wxi new file mode 100644 index 0000000..46bc723 --- /dev/null +++ b/wixlib/wixstdba_platform.wxi @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wixlib/wixstdba_x86.wxs b/wixlib/wixstdba_x86.wxs new file mode 100644 index 0000000..988f466 --- /dev/null +++ b/wixlib/wixstdba_x86.wxs @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/wixstdba/Resources/Hyperlink2Theme.xml b/wixstdba/Resources/Hyperlink2Theme.xml new file mode 100644 index 0000000..c4f0f1e --- /dev/null +++ b/wixstdba/Resources/Hyperlink2Theme.xml @@ -0,0 +1,77 @@ + + + #(loc.Caption) + Segoe UI + Segoe UI + Segoe UI + Segoe UI + Segoe UI + + + #(loc.Title) + + #(loc.HelpHeader) + #(loc.HelpText) + + + + #(loc.Title) + + #(loc.InstallHeader) + #(loc.InstallMessage) + #(loc.InstallLicenseLinkText) + #(loc.InstallVersion) + #(loc.InstallUpgradeLinkText) + #(loc.InstallAcceptCheckbox) + + + + + + #(loc.Title) + + #(loc.OptionsHeader) + #(loc.OptionsLocationLabel) + + + + + + + + #(loc.Title) + + #(loc.ProgressHeader) + #(loc.ProgressLabel) + #(loc.OverallProgressPackageText) + + + + + #(loc.Title) + + #(loc.ModifyHeader) + + + + + + #(loc.Title) + + #(loc.SuccessHeader) + + #(loc.SuccessRestartText) + + + + + #(loc.Title) + + #(loc.FailureHeader) + #(loc.FailureHyperlinkLogText) + + #(loc.FailureRestartText) + + + + \ No newline at end of file diff --git a/wixstdba/Resources/HyperlinkTheme.wxl b/wixstdba/Resources/HyperlinkTheme.wxl new file mode 100644 index 0000000..41910b6 --- /dev/null +++ b/wixstdba/Resources/HyperlinkTheme.wxl @@ -0,0 +1,48 @@ + + + [WixBundleName] Setup + [WixBundleName] + Welcome + Setup will install [WixBundleName] on your computer. Click install to continue, options to set the install directory or Close to exit. + Version [WixBundleVersion] + Version [WixBundleVersion] <a href="#">upgrade available</a> + Are you sure you want to cancel? + Setup Help + /install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or + creates a complete local copy of the bundle in directory. Install is the default. + +/passive | /quiet - displays minimal UI with no prompts or displays no UI and + no prompts. By default UI and all prompts are displayed. + +/norestart - suppress any attempts to restart. By default UI will prompt before restart. +/log log.txt - logs to a specific file. By default a log file is created in %TEMP%. + &Close + [WixBundleName] <a href="#">license terms</a>. + I &agree to the license terms and conditions + &Options + &Install + &Close + Setup Options + Install location: + &Browse + &OK + &Cancel + Setup Progress + Processing: + Initializing... + &Cancel + Modify Setup + &Repair + &Uninstall + &Close + Setup Successful + &Launch + You must restart your computer before you can use the software. + &Restart + &Close + Setup Failed + One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. + You must restart your computer to complete the rollback of the software. + &Restart + &Close + \ No newline at end of file diff --git a/wixstdba/Resources/HyperlinkTheme.xml b/wixstdba/Resources/HyperlinkTheme.xml new file mode 100644 index 0000000..34aca2c --- /dev/null +++ b/wixstdba/Resources/HyperlinkTheme.xml @@ -0,0 +1,66 @@ + + + #(loc.Caption) + Segoe UI + Segoe UI + Segoe UI + Segoe UI + Segoe UI + + + #(loc.Title) + + + #(loc.HelpHeader) + #(loc.HelpText) + + + + #(loc.InstallHeader) + #(loc.InstallMessage) + + #(loc.InstallLicenseLinkText) + #(loc.InstallVersion) + #(loc.InstallUpgradeLinkText) + #(loc.InstallAcceptCheckbox) + + + + + + #(loc.OptionsHeader) + #(loc.OptionsLocationLabel) + + + + + + + #(loc.ProgressHeader) + #(loc.ProgressLabel) + #(loc.OverallProgressPackageText) + + + + + #(loc.ModifyHeader) + + + + + + #(loc.SuccessHeader) + + #(loc.SuccessRestartText) + + + + + #(loc.FailureHeader) + #(loc.FailureHyperlinkLogText) + + #(loc.FailureRestartText) + + + + \ No newline at end of file diff --git a/wixstdba/Resources/LogoSide.png b/wixstdba/Resources/LogoSide.png new file mode 100644 index 0000000..3d7af32 Binary files /dev/null and b/wixstdba/Resources/LogoSide.png differ diff --git a/wixstdba/Resources/LoremIpsumLicense.rtf b/wixstdba/Resources/LoremIpsumLicense.rtf new file mode 100644 index 0000000..1a18323 Binary files /dev/null and b/wixstdba/Resources/LoremIpsumLicense.rtf differ diff --git a/wixstdba/Resources/RtfTheme.wxl b/wixstdba/Resources/RtfTheme.wxl new file mode 100644 index 0000000..67b5ee0 --- /dev/null +++ b/wixstdba/Resources/RtfTheme.wxl @@ -0,0 +1,43 @@ + + + [WixBundleName] Setup + [WixBundleName] + Are you sure you want to cancel? + Setup Help + /install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or + creates a complete local copy of the bundle in directory. Install is the default. + +/passive | /quiet - displays minimal UI with no prompts or displays no UI and + no prompts. By default UI and all prompts are displayed. + +/norestart - suppress any attempts to restart. By default UI will prompt before restart. +/log log.txt - logs to a specific file. By default a log file is created in %TEMP%. + &Close + I &agree to the license terms and conditions + &Options + &Install + &Close + Setup Options + Install location: + &Browse + &OK + &Cancel + Setup Progress + Processing: + Initializing... + &Cancel + Modify Setup + &Repair + &Uninstall + &Close + Setup Successful + &Launch + You must restart your computer before you can use the software. + &Restart + &Close + Setup Failed + One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. + You must restart your computer to complete the rollback of the software. + &Restart + &Close + diff --git a/wixstdba/Resources/RtfTheme.xml b/wixstdba/Resources/RtfTheme.xml new file mode 100644 index 0000000..af724a8 --- /dev/null +++ b/wixstdba/Resources/RtfTheme.xml @@ -0,0 +1,62 @@ + + + #(loc.Caption) + Segoe UI + Segoe UI + Segoe UI + Segoe UI + Segoe UI + + + #(loc.Title) + + + #(loc.HelpHeader) + #(loc.HelpText) + + + + + + #(loc.InstallAcceptCheckbox) + + + + + + #(loc.OptionsHeader) + #(loc.OptionsLocationLabel) + + + + + + + #(loc.ProgressHeader) + #(loc.ProgressLabel) + #(loc.OverallProgressPackageText) + + + + + #(loc.ModifyHeader) + + + + + + #(loc.SuccessHeader) + + #(loc.SuccessRestartText) + + + + + #(loc.FailureHeader) + #(loc.FailureHyperlinkLogText) + + #(loc.FailureRestartText) + + + + \ No newline at end of file diff --git a/wixstdba/Resources/logo.png b/wixstdba/Resources/logo.png new file mode 100644 index 0000000..6df52d5 Binary files /dev/null and b/wixstdba/Resources/logo.png differ diff --git a/wixstdba/WixStandardBootstrapperApplication.cpp b/wixstdba/WixStandardBootstrapperApplication.cpp new file mode 100644 index 0000000..d3a609e --- /dev/null +++ b/wixstdba/WixStandardBootstrapperApplication.cpp @@ -0,0 +1,2975 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +//------------------------------------------------------------------------------------------------- + + +#include "precomp.h" + +static const LPCWSTR WIXBUNDLE_VARIABLE_ELEVATED = L"WixBundleElevated"; + +static const LPCWSTR WIXSTDBA_WINDOW_CLASS = L"WixExtBA"; +static const LPCWSTR WIXSTDBA_VARIABLE_INSTALL_FOLDER = L"InstallFolder"; +static const LPCWSTR WIXSTDBA_VARIABLE_INSTALL_FOLDER2 = L"InstallFolder2"; +static const LPCWSTR WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH = L"LaunchTarget"; +static const LPCWSTR WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS = L"LaunchArguments"; +static const LPCWSTR WIXSTDBA_VARIABLE_LAUNCH_HIDDEN = L"LaunchHidden"; +static const DWORD WIXSTDBA_ACQUIRE_PERCENTAGE = 30; + +enum WIXSTDBA_STATE +{ + WIXSTDBA_STATE_OPTIONS, + WIXSTDBA_STATE_INITIALIZING, + WIXSTDBA_STATE_INITIALIZED, + WIXSTDBA_STATE_HELP, + WIXSTDBA_STATE_DETECTING, + WIXSTDBA_STATE_DETECTED, + WIXSTDBA_STATE_PLANNING, + WIXSTDBA_STATE_PLANNED, + WIXSTDBA_STATE_APPLYING, + WIXSTDBA_STATE_CACHING, + WIXSTDBA_STATE_CACHED, + WIXSTDBA_STATE_EXECUTING, + WIXSTDBA_STATE_EXECUTED, + WIXSTDBA_STATE_APPLIED, + WIXSTDBA_STATE_FAILED, +}; + +enum WM_WIXSTDBA +{ + WM_WIXSTDBA_SHOW_HELP = WM_APP + 100, + WM_WIXSTDBA_DETECT_PACKAGES, + WM_WIXSTDBA_PLAN_PACKAGES, + WM_WIXSTDBA_APPLY_PACKAGES, + WM_WIXSTDBA_CHANGE_STATE, +}; + +// This enum must be kept in the same order as the vrgwzPageNames array. +enum WIXSTDBA_PAGE +{ + WIXSTDBA_PAGE_LOADING, + WIXSTDBA_PAGE_HELP, + WIXSTDBA_PAGE_INSTALL, + WIXSTDBA_PAGE_OPTIONS, + WIXSTDBA_PAGE_MODIFY, + WIXSTDBA_PAGE_PROGRESS, + WIXSTDBA_PAGE_PROGRESS_PASSIVE, + WIXSTDBA_PAGE_SUCCESS, + WIXSTDBA_PAGE_FAILURE, + COUNT_WIXSTDBA_PAGE, +}; + +// This array must be kept in the same order as the WIXSTDBA_PAGE enum. +static LPCWSTR vrgwzPageNames[] = { + L"Loading", + L"Help", + L"Install", + L"Options", + L"Modify", + L"Progress", + L"ProgressPassive", + L"Success", + L"Failure", +}; + +enum WIXSTDBA_CONTROL +{ + // Non-paged controls + WIXSTDBA_CONTROL_CLOSE_BUTTON = THEME_FIRST_ASSIGN_CONTROL_ID, + WIXSTDBA_CONTROL_MINIMIZE_BUTTON, + + // Help page + WIXSTDBA_CONTROL_HELP_CANCEL_BUTTON, + + // Welcome page + WIXSTDBA_CONTROL_INSTALL_BUTTON, + WIXSTDBA_CONTROL_OPTIONS_BUTTON, + WIXSTDBA_CONTROL_EULA_RICHEDIT, + WIXSTDBA_CONTROL_EULA_LINK, + WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX, + WIXSTDBA_CONTROL_WELCOME_CANCEL_BUTTON, + WIXSTDBA_CONTROL_VERSION_LABEL, + WIXSTDBA_CONTROL_UPGRADE_LINK, + + // Options page + WIXSTDBA_CONTROL_FOLDER_EDITBOX, + WIXSTDBA_CONTROL_BROWSE_BUTTON, + WIXSTDBA_CONTROL_FOLDER_EDITBOX2, + WIXSTDBA_CONTROL_BROWSE_BUTTON2, + WIXSTDBA_CONTROL_OK_BUTTON, + WIXSTDBA_CONTROL_CANCEL_BUTTON, + + // Modify page + WIXSTDBA_CONTROL_REPAIR_BUTTON, + WIXSTDBA_CONTROL_UNINSTALL_BUTTON, + WIXSTDBA_CONTROL_MODIFY_CANCEL_BUTTON, + + // Progress page + WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, + WIXSTDBA_CONTROL_CACHE_PROGRESS_BAR, + WIXSTDBA_CONTROL_CACHE_PROGRESS_TEXT, + + WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, + WIXSTDBA_CONTROL_EXECUTE_PROGRESS_BAR, + WIXSTDBA_CONTROL_EXECUTE_PROGRESS_TEXT, + WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, + + WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, + WIXSTDBA_CONTROL_OVERALL_PROGRESS_BAR, + WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, + WIXSTDBA_CONTROL_OVERALL_PROGRESS_TEXT, + + WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, + + // Success page + WIXSTDBA_CONTROL_LAUNCH_BUTTON, + WIXSTDBA_CONTROL_SUCCESS_RESTART_TEXT, + WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON, + WIXSTDBA_CONTROL_SUCCESS_CANCEL_BUTTON, + + // Failure page + WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK, + WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, + WIXSTDBA_CONTROL_FAILURE_RESTART_TEXT, + WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON, + WIXSTDBA_CONTROL_FAILURE_CANCEL_BUTTON, +}; + +static THEME_ASSIGN_CONTROL_ID vrgInitControls[] = { + { WIXSTDBA_CONTROL_CLOSE_BUTTON, L"CloseButton" }, + { WIXSTDBA_CONTROL_MINIMIZE_BUTTON, L"MinimizeButton" }, + + { WIXSTDBA_CONTROL_HELP_CANCEL_BUTTON, L"HelpCancelButton" }, + + { WIXSTDBA_CONTROL_INSTALL_BUTTON, L"InstallButton" }, + { WIXSTDBA_CONTROL_OPTIONS_BUTTON, L"OptionsButton" }, + { WIXSTDBA_CONTROL_EULA_RICHEDIT, L"EulaRichedit" }, + { WIXSTDBA_CONTROL_EULA_LINK, L"EulaHyperlink" }, + { WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX, L"EulaAcceptCheckbox" }, + { WIXSTDBA_CONTROL_WELCOME_CANCEL_BUTTON, L"WelcomeCancelButton" }, + { WIXSTDBA_CONTROL_VERSION_LABEL, L"InstallVersion" }, + { WIXSTDBA_CONTROL_UPGRADE_LINK, L"UpgradeHyperlink" }, + + { WIXSTDBA_CONTROL_FOLDER_EDITBOX, L"FolderEditbox" }, + { WIXSTDBA_CONTROL_BROWSE_BUTTON, L"BrowseButton" }, + { WIXSTDBA_CONTROL_FOLDER_EDITBOX2, L"FolderEditbox2" }, + { WIXSTDBA_CONTROL_BROWSE_BUTTON2, L"BrowseButton2" }, + { WIXSTDBA_CONTROL_OK_BUTTON, L"OptionsOkButton" }, + { WIXSTDBA_CONTROL_CANCEL_BUTTON, L"OptionsCancelButton" }, + + { WIXSTDBA_CONTROL_REPAIR_BUTTON, L"RepairButton" }, + { WIXSTDBA_CONTROL_UNINSTALL_BUTTON, L"UninstallButton" }, + { WIXSTDBA_CONTROL_MODIFY_CANCEL_BUTTON, L"ModifyCancelButton" }, + + { WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, L"CacheProgressPackageText" }, + { WIXSTDBA_CONTROL_CACHE_PROGRESS_BAR, L"CacheProgressbar" }, + { WIXSTDBA_CONTROL_CACHE_PROGRESS_TEXT, L"CacheProgressText" }, + { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, L"ExecuteProgressPackageText" }, + { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_BAR, L"ExecuteProgressbar" }, + { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_TEXT, L"ExecuteProgressText" }, + { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, L"ExecuteProgressActionDataText" }, + { WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, L"OverallProgressPackageText" }, + { WIXSTDBA_CONTROL_OVERALL_PROGRESS_BAR, L"OverallProgressbar" }, + { WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, L"OverallCalculatedProgressbar" }, + { WIXSTDBA_CONTROL_OVERALL_PROGRESS_TEXT, L"OverallProgressText" }, + { WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, L"ProgressCancelButton" }, + + { WIXSTDBA_CONTROL_LAUNCH_BUTTON, L"LaunchButton" }, + { WIXSTDBA_CONTROL_SUCCESS_RESTART_TEXT, L"SuccessRestartText" }, + { WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON, L"SuccessRestartButton" }, + { WIXSTDBA_CONTROL_SUCCESS_CANCEL_BUTTON, L"SuccessCancelButton" }, + + { WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK, L"FailureLogFileLink" }, + { WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, L"FailureMessageText" }, + { WIXSTDBA_CONTROL_FAILURE_RESTART_TEXT, L"FailureRestartText" }, + { WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON, L"FailureRestartButton" }, + { WIXSTDBA_CONTROL_FAILURE_CANCEL_BUTTON, L"FailureCloseButton" }, +}; + +class CWixStandardBootstrapperApplication : public CBalBaseBootstrapperApplication +{ +public: // IBootstrapperApplication + virtual STDMETHODIMP OnStartup() + { + HRESULT hr = S_OK; + DWORD dwUIThreadId = 0; + + // create UI thread + m_hUiThread = ::CreateThread(NULL, 0, UiThreadProc, this, 0, &dwUIThreadId); + if (!m_hUiThread) + { + ExitWithLastError(hr, "Failed to create UI thread."); + } + + LExit: + return hr; + } + + + virtual STDMETHODIMP_(int) OnShutdown() + { + int nResult = IDNOACTION; + + // wait for UI thread to terminate + if (m_hUiThread) + { + ::WaitForSingleObject(m_hUiThread, INFINITE); + ReleaseHandle(m_hUiThread); + } + + // If a restart was required. + if (m_fRestartRequired) + { + if (m_fAllowRestart) + { + nResult = IDRESTART; + } + + if (m_sczPrereqPackage) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, m_fAllowRestart ? "The prerequisites scheduled a restart. The bootstrapper application will be reloaded after the computer is restarted." + : "A restart is required by the prerequisites but the user delayed it. The bootstrapper application will be reloaded after the computer is restarted."); + } + } + else if (m_fPrereqInstalled) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were successfully installed. The bootstrapper application will be reloaded."); + nResult = IDRELOAD_BOOTSTRAPPER; + } + else if (m_fPrereqAlreadyInstalled) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were already installed. The bootstrapper application will not be reloaded to prevent an infinite loop."); + } + else if (m_fPrereq) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were not successfully installed, error: 0x%x. The bootstrapper application will be not reloaded.", m_hrFinal); + } + + return nResult; + } + + + virtual STDMETHODIMP_(int) OnDetectRelatedBundle( + __in LPCWSTR wzBundleId, + __in BOOTSTRAPPER_RELATION_TYPE relationType, + __in LPCWSTR /*wzBundleTag*/, + __in BOOL fPerMachine, + __in DWORD64 /*dw64Version*/, + __in BOOTSTRAPPER_RELATED_OPERATION operation + ) + { + BalInfoAddRelatedBundleAsPackage(&m_Bundle.packages, wzBundleId, relationType, fPerMachine); + + // If we're not doing a pre-req install, remember when our bundle would cause a downgrade. + if (!m_sczPrereqPackage && BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE == operation) + { + m_fDowngrading = TRUE; + } + + return CheckCanceled() ? IDCANCEL : IDOK; + } + + + virtual STDMETHODIMP_(void) OnDetectPackageComplete( + __in LPCWSTR wzPackageId, + __in HRESULT /*hrStatus*/, + __in BOOTSTRAPPER_PACKAGE_STATE state + ) + { + // If the prereq package is already installed, remember that. + if (m_sczPrereqPackage && BOOTSTRAPPER_PACKAGE_STATE_PRESENT == state && + CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, m_sczPrereqPackage, -1)) + { + m_fPrereqAlreadyInstalled = TRUE; + } + } + + + // OnDetectUpdateBegin - called when the engine begins detection for bundle update. + virtual STDMETHODIMP_(int) OnDetectUpdateBegin( + __in_z LPCWSTR wzUpdateLocation, + __in int nRecommendation + ) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Update location: %ls.", wzUpdateLocation); + + m_wzUpdateLocation = wzUpdateLocation; + // If there is an upgrade link, check for update on a background thread + if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK)) + { + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK, FALSE); + ::CreateThread(NULL, 0, ThreadProc, this, 0, NULL); + } + + return nRecommendation; + } + + + virtual STDMETHODIMP_(int) OnDetectBegin( + __in BOOL /*fInstalled*/, + __in DWORD /*cPackages*/ + ) + { + return IDNOACTION; + } + + + virtual STDMETHODIMP_(void) OnDetectComplete( + __in HRESULT hrStatus + ) + { + if (SUCCEEDED(hrStatus) && m_pBAFunction) + { + m_pBAFunction->OnDetectComplete(); + } + + if (SUCCEEDED(hrStatus)) + { + hrStatus = EvaluateConditions(); + } + + SetState(WIXSTDBA_STATE_DETECTED, hrStatus); + + // If we're not interacting with the user or we're doing a layout or we're just after a force restart + // then automatically start planning. + if (BOOTSTRAPPER_DISPLAY_FULL > m_command.display || BOOTSTRAPPER_ACTION_LAYOUT == m_command.action || BOOTSTRAPPER_RESUME_TYPE_REBOOT == m_command.resumeType) + { + if (SUCCEEDED(hrStatus)) + { + ::PostMessageW(m_hWnd, WM_WIXSTDBA_PLAN_PACKAGES, 0, m_command.action); + } + } + } + + + virtual STDMETHODIMP_(int) OnPlanRelatedBundle( + __in_z LPCWSTR /*wzBundleId*/, + __inout_z BOOTSTRAPPER_REQUEST_STATE* pRequestedState + ) + { + // If we're only installing prereq, do not touch related bundles. + if (m_sczPrereqPackage) + { + *pRequestedState = BOOTSTRAPPER_REQUEST_STATE_NONE; + } + + return CheckCanceled() ? IDCANCEL : IDOK; + } + + + virtual STDMETHODIMP_(int) OnPlanPackageBegin( + __in_z LPCWSTR wzPackageId, + __inout BOOTSTRAPPER_REQUEST_STATE *pRequestState + ) + { + // If we're planning to install a pre-req, install it. The pre-req needs to be installed + // in all cases (even uninstall!) so the BA can load next. + if (m_sczPrereqPackage) + { + if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, m_sczPrereqPackage, -1)) + { + *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT; + } + else // skip everything else. + { + *pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; + } + } + else if (m_sczAfterForcedRestartPackage) // after force restart skip packages until after the package that caused the restart. + { + // After restart we need to finish the dependency registration for our package so allow the package + // to go present. + if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, m_sczAfterForcedRestartPackage, -1)) + { + // Do not allow a repair because that could put us in a perpetual restart loop. + if (BOOTSTRAPPER_REQUEST_STATE_REPAIR == *pRequestState) + { + *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT; + } + + ReleaseNullStr(m_sczAfterForcedRestartPackage); // no more skipping now. + } + else // not the matching package, so skip it. + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Skipping package: %ls, after restart because it was applied before the restart.", wzPackageId); + + *pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; + } + } + + return CheckCanceled() ? IDCANCEL : IDOK; + } + + + virtual STDMETHODIMP_(void) OnPlanComplete( + __in HRESULT hrStatus + ) + { + if (SUCCEEDED(hrStatus) && m_pBAFunction) + { + m_pBAFunction->OnPlanComplete(); + } + + SetState(WIXSTDBA_STATE_PLANNED, hrStatus); + + if (SUCCEEDED(hrStatus)) + { + ::PostMessageW(m_hWnd, WM_WIXSTDBA_APPLY_PACKAGES, 0, 0); + } + + m_dwCalculatedCacheProgress = 0; + m_dwCalculatedExecuteProgress = 0; + } + + + virtual STDMETHODIMP_(int) OnCachePackageBegin( + __in_z LPCWSTR wzPackageId, + __in DWORD cCachePayloads, + __in DWORD64 dw64PackageCacheSize + ) + { + if (wzPackageId && *wzPackageId) + { + BAL_INFO_PACKAGE* pPackage = NULL; + HRESULT hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage); + LPCWSTR wz = (SUCCEEDED(hr) && pPackage->sczDisplayName) ? pPackage->sczDisplayName : wzPackageId; + + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, wz); + + // If something started executing, leave it in the overall progress text. + if (!m_fStartedExecution) + { + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wz); + } + } + + return __super::OnCachePackageBegin(wzPackageId, cCachePayloads, dw64PackageCacheSize); + } + + + virtual STDMETHODIMP_(int) OnCacheAcquireProgress( + __in_z LPCWSTR wzPackageOrContainerId, + __in_z_opt LPCWSTR wzPayloadId, + __in DWORD64 dw64Progress, + __in DWORD64 dw64Total, + __in DWORD dwOverallPercentage + ) + { + WCHAR wzProgress[5] = {}; + +#ifdef DEBUG + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnCacheAcquireProgress() - container/package: %ls, payload: %ls, progress: %I64u, total: %I64u, overall progress: %u%%", wzPackageOrContainerId, wzPayloadId, dw64Progress, dw64Total, dwOverallPercentage); +#endif + + ::StringCchPrintfW(wzProgress, countof(wzProgress), L"%u%%", dwOverallPercentage); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_TEXT, wzProgress); + + ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_BAR, dwOverallPercentage); + + // Restrict progress to 100% to hide burn engine progress bug. + m_dwCalculatedCacheProgress = min(dwOverallPercentage, 100) * WIXSTDBA_ACQUIRE_PERCENTAGE / 100; +#ifdef DEBUG + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnCacheAcquireProgress() - calculated progress: %u%%, displayed progress: %u%%", m_dwCalculatedCacheProgress, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress); +#endif + ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress); + + SetTaskbarButtonProgress(m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress); + + return __super::OnCacheAcquireProgress(wzPackageOrContainerId, wzPayloadId, dw64Progress, dw64Total, dwOverallPercentage); + } + + + virtual STDMETHODIMP_(int) OnCacheAcquireComplete( + __in_z LPCWSTR wzPackageOrContainerId, + __in_z_opt LPCWSTR wzPayloadId, + __in HRESULT hrStatus, + __in int nRecommendation + ) + { + SetProgressState(hrStatus); + return __super::OnCacheAcquireComplete(wzPackageOrContainerId, wzPayloadId, hrStatus, nRecommendation); + } + + + virtual STDMETHODIMP_(int) OnCacheVerifyComplete( + __in_z LPCWSTR wzPackageId, + __in_z LPCWSTR wzPayloadId, + __in HRESULT hrStatus, + __in int nRecommendation + ) + { + SetProgressState(hrStatus); + return __super::OnCacheVerifyComplete(wzPackageId, wzPayloadId, hrStatus, nRecommendation); + } + + + virtual STDMETHODIMP_(void) OnCacheComplete( + __in HRESULT /*hrStatus*/ + ) + { + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, L""); + SetState(WIXSTDBA_STATE_CACHED, S_OK); // we always return success here and let OnApplyComplete() deal with the error. + } + + + virtual STDMETHODIMP_(int) OnError( + __in BOOTSTRAPPER_ERROR_TYPE errorType, + __in LPCWSTR wzPackageId, + __in DWORD dwCode, + __in_z LPCWSTR wzError, + __in DWORD dwUIHint, + __in DWORD /*cData*/, + __in_ecount_z_opt(cData) LPCWSTR* /*rgwzData*/, + __in int nRecommendation + ) + { + int nResult = nRecommendation; + LPWSTR sczError = NULL; + + if (BOOTSTRAPPER_DISPLAY_EMBEDDED == m_command.display) + { + HRESULT hr = m_pEngine->SendEmbeddedError(dwCode, wzError, dwUIHint, &nResult); + if (FAILED(hr)) + { + nResult = IDERROR; + } + } + else if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display) + { + // If this is an authentication failure, let the engine try to handle it for us. + if (BOOTSTRAPPER_ERROR_TYPE_HTTP_AUTH_SERVER == errorType || BOOTSTRAPPER_ERROR_TYPE_HTTP_AUTH_PROXY == errorType) + { + nResult = IDTRYAGAIN; + } + else // show a generic error message box. + { + BalRetryErrorOccurred(wzPackageId, dwCode); + + if (!m_fShowingInternalUiThisPackage) + { + // If no error message was provided, use the error code to try and get an error message. + if (!wzError || !*wzError || BOOTSTRAPPER_ERROR_TYPE_WINDOWS_INSTALLER != errorType) + { + HRESULT hr = StrAllocFromError(&sczError, dwCode, NULL); + if (FAILED(hr) || !sczError || !*sczError) + { + StrAllocFormatted(&sczError, L"0x%x", dwCode); + } + } + + nResult = ::MessageBoxW(m_hWnd, sczError ? sczError : wzError, m_pTheme->sczCaption, dwUIHint); + } + } + + SetProgressState(HRESULT_FROM_WIN32(dwCode)); + } + else // just take note of the error code and let things continue. + { + BalRetryErrorOccurred(wzPackageId, dwCode); + } + + ReleaseStr(sczError); + return nResult; + } + + + virtual STDMETHODIMP_(int) OnExecuteMsiMessage( + __in_z LPCWSTR wzPackageId, + __in INSTALLMESSAGE mt, + __in UINT uiFlags, + __in_z LPCWSTR wzMessage, + __in DWORD cData, + __in_ecount_z_opt(cData) LPCWSTR* rgwzData, + __in int nRecommendation + ) + { +#ifdef DEBUG + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnExecuteMsiMessage() - package: %ls, message: %ls", wzPackageId, wzMessage); +#endif + if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display && (INSTALLMESSAGE_WARNING == mt || INSTALLMESSAGE_USER == mt)) + { + int nResult = ::MessageBoxW(m_hWnd, wzMessage, m_pTheme->sczCaption, uiFlags); + return nResult; + } + + if (INSTALLMESSAGE_ACTIONSTART == mt) + { + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, wzMessage); + } + + return __super::OnExecuteMsiMessage(wzPackageId, mt, uiFlags, wzMessage, cData, rgwzData, nRecommendation); + } + + + virtual STDMETHODIMP_(int) OnProgress( + __in DWORD dwProgressPercentage, + __in DWORD dwOverallProgressPercentage + ) + { + WCHAR wzProgress[5] = {}; + +#ifdef DEBUG + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnProgress() - progress: %u%%, overall progress: %u%%", dwProgressPercentage, dwOverallProgressPercentage); +#endif + + ::StringCchPrintfW(wzProgress, countof(wzProgress), L"%u%%", dwOverallProgressPercentage); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_TEXT, wzProgress); + + ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_BAR, dwOverallProgressPercentage); + SetTaskbarButtonProgress(dwOverallProgressPercentage); + + return __super::OnProgress(dwProgressPercentage, dwOverallProgressPercentage); + } + + + virtual STDMETHODIMP_(int) OnExecutePackageBegin( + __in_z LPCWSTR wzPackageId, + __in BOOL fExecute + ) + { + LPWSTR sczFormattedString = NULL; + + m_fStartedExecution = TRUE; + + if (wzPackageId && *wzPackageId) + { + BAL_INFO_PACKAGE* pPackage = NULL; + BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage); + + LPCWSTR wz = wzPackageId; + if (pPackage) + { + LOC_STRING* pLocString = NULL; + + switch (pPackage->type) + { + case BAL_INFO_PACKAGE_TYPE_BUNDLE_ADDON: + LocGetString(m_pWixLoc, L"#(loc.ExecuteAddonRelatedBundleMessage)", &pLocString); + break; + + case BAL_INFO_PACKAGE_TYPE_BUNDLE_PATCH: + LocGetString(m_pWixLoc, L"#(loc.ExecutePatchRelatedBundleMessage)", &pLocString); + break; + + case BAL_INFO_PACKAGE_TYPE_BUNDLE_UPGRADE: + LocGetString(m_pWixLoc, L"#(loc.ExecuteUpgradeRelatedBundleMessage)", &pLocString); + break; + } + + if (pLocString) + { + BalFormatString(pLocString->wzText, &sczFormattedString); + } + + wz = sczFormattedString ? sczFormattedString : pPackage->sczDisplayName ? pPackage->sczDisplayName : wzPackageId; + } + + m_fShowingInternalUiThisPackage = pPackage && pPackage->fDisplayInternalUI; + + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, wz); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wz); + } + else + { + m_fShowingInternalUiThisPackage = FALSE; + } + + ReleaseStr(sczFormattedString); + return __super::OnExecutePackageBegin(wzPackageId, fExecute); + } + + + virtual int __stdcall OnExecuteProgress( + __in_z LPCWSTR wzPackageId, + __in DWORD dwProgressPercentage, + __in DWORD dwOverallProgressPercentage + ) + { + WCHAR wzProgress[5] = {}; + +#ifdef DEBUG + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnExecuteProgress() - package: %ls, progress: %u%%, overall progress: %u%%", wzPackageId, dwProgressPercentage, dwOverallProgressPercentage); +#endif + + ::StringCchPrintfW(wzProgress, countof(wzProgress), L"%u%%", dwOverallProgressPercentage); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_TEXT, wzProgress); + + ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_BAR, dwOverallProgressPercentage); + + m_dwCalculatedExecuteProgress = dwOverallProgressPercentage * (100 - WIXSTDBA_ACQUIRE_PERCENTAGE) / 100; +#ifdef DEBUG + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnExecuteProgress() - calculated progress: %u%%, displayed progress: %u%%", m_dwCalculatedExecuteProgress, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress); +#endif + ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress); + + SetTaskbarButtonProgress(m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress); + + return __super::OnExecuteProgress(wzPackageId, dwProgressPercentage, dwOverallProgressPercentage); + } + + + virtual STDMETHODIMP_(int) OnExecutePackageComplete( + __in_z LPCWSTR wzPackageId, + __in HRESULT hrExitCode, + __in BOOTSTRAPPER_APPLY_RESTART restart, + __in int nRecommendation + ) + { + SetProgressState(hrExitCode); + + int nResult = __super::OnExecutePackageComplete(wzPackageId, hrExitCode, restart, nRecommendation); + + if (m_sczPrereqPackage && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, m_sczPrereqPackage, -1)) + { + m_fPrereqInstalled = SUCCEEDED(hrExitCode); + + // If the pre-req required a restart (any restart) then do an immediate + // restart to ensure that the bundle will get launched again post reboot. + if (BOOTSTRAPPER_APPLY_RESTART_NONE != restart) + { + nResult = IDRESTART; + } + } + + return nResult; + } + + + virtual STDMETHODIMP_(void) OnExecuteComplete( + __in HRESULT hrStatus + ) + { + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, L""); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, L""); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, L""); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, FALSE); // no more cancel. + + SetState(WIXSTDBA_STATE_EXECUTED, S_OK); // we always return success here and let OnApplyComplete() deal with the error. + SetProgressState(hrStatus); + } + + + virtual STDMETHODIMP_(int) OnResolveSource( + __in_z LPCWSTR wzPackageOrContainerId, + __in_z_opt LPCWSTR wzPayloadId, + __in_z LPCWSTR wzLocalSource, + __in_z_opt LPCWSTR wzDownloadSource + ) + { + int nResult = IDERROR; // assume we won't resolve source and that is unexpected. + + if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display) + { + if (wzDownloadSource) + { + nResult = IDDOWNLOAD; + } + else // prompt to change the source location. + { + OPENFILENAMEW ofn = {}; + WCHAR wzFile[MAX_PATH] = {}; + + ::StringCchCopyW(wzFile, countof(wzFile), wzLocalSource); + + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = m_hWnd; + ofn.lpstrFile = wzFile; + ofn.nMaxFile = countof(wzFile); + ofn.lpstrFilter = L"All Files\0*.*\0"; + ofn.nFilterIndex = 1; + ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; + ofn.lpstrTitle = m_pTheme->sczCaption; + + if (::GetOpenFileNameW(&ofn)) + { + HRESULT hr = m_pEngine->SetLocalSource(wzPackageOrContainerId, wzPayloadId, ofn.lpstrFile); + nResult = SUCCEEDED(hr) ? IDRETRY : IDERROR; + } + else + { + nResult = IDCANCEL; + } + } + } + else if (wzDownloadSource) + { + // If doing a non-interactive install and download source is available, let's try downloading the package silently + nResult = IDDOWNLOAD; + } + // else there's nothing more we can do in non-interactive mode + + return CheckCanceled() ? IDCANCEL : nResult; + } + + + virtual STDMETHODIMP_(int) OnApplyComplete( + __in HRESULT hrStatus, + __in BOOTSTRAPPER_APPLY_RESTART restart + ) + { + m_restartResult = restart; // remember the restart result so we return the correct error code no matter what the user chooses to do in the UI. + + // If a restart was encountered and we are not suppressing restarts, then restart is required. + m_fRestartRequired = (BOOTSTRAPPER_APPLY_RESTART_NONE != restart && BOOTSTRAPPER_RESTART_NEVER < m_command.restart); + // If a restart is required and we're not displaying a UI or we are not supposed to prompt for restart then allow the restart. + m_fAllowRestart = m_fRestartRequired && (BOOTSTRAPPER_DISPLAY_FULL > m_command.display || BOOTSTRAPPER_RESTART_PROMPT < m_command.restart); + + // If we are showing UI, wait a beat before moving to the final screen. + if (BOOTSTRAPPER_DISPLAY_NONE < m_command.display) + { + ::Sleep(250); + } + + SetState(WIXSTDBA_STATE_APPLIED, hrStatus); + SetTaskbarButtonProgress(100); // show full progress bar, green, yellow, or red + + // If we successfully applied an update close the window since the new Bundle should be running now. + if (SUCCEEDED(hrStatus) && m_fUpdating) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Update downloaded, close bundle."); + ::PostMessageW(m_hWnd, WM_CLOSE, 0, 0); + } + + return IDNOACTION; + } + + +private: // privates + // + // UiThreadProc - entrypoint for UI thread. + // + static DWORD WINAPI UiThreadProc( + __in LPVOID pvContext + ) + { + HRESULT hr = S_OK; + CWixStandardBootstrapperApplication* pThis = (CWixStandardBootstrapperApplication*)pvContext; + BOOL fComInitialized = FALSE; + BOOL fRet = FALSE; + MSG msg = {}; + + // Initialize COM and theme. + hr = ::CoInitialize(NULL); + BalExitOnFailure(hr, "Failed to initialize COM."); + fComInitialized = TRUE; + + hr = ThemeInitialize(pThis->m_hModule); + BalExitOnFailure(hr, "Failed to initialize theme manager."); + + hr = pThis->InitializeData(); + BalExitOnFailure(hr, "Failed to initialize data in bootstrapper application."); + + // Create main window. + pThis->InitializeTaskbarButton(); + hr = pThis->CreateMainWindow(); + BalExitOnFailure(hr, "Failed to create main window."); + + // Okay, we're ready for packages now. + pThis->SetState(WIXSTDBA_STATE_INITIALIZED, hr); + ::PostMessageW(pThis->m_hWnd, BOOTSTRAPPER_ACTION_HELP == pThis->m_command.action ? WM_WIXSTDBA_SHOW_HELP : WM_WIXSTDBA_DETECT_PACKAGES, 0, 0); + + // message pump + while (0 != (fRet = ::GetMessageW(&msg, NULL, 0, 0))) + { + if (-1 == fRet) + { + hr = E_UNEXPECTED; + BalExitOnFailure(hr, "Unexpected return value from message pump."); + } + else if (!ThemeHandleKeyboardMessage(pThis->m_pTheme, msg.hwnd, &msg)) + { + ::TranslateMessage(&msg); + ::DispatchMessageW(&msg); + } + } + + // Succeeded thus far, check to see if anything went wrong while actually + // executing changes. + if (FAILED(pThis->m_hrFinal)) + { + hr = pThis->m_hrFinal; + } + else if (pThis->CheckCanceled()) + { + hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); + } + + LExit: + // destroy main window + pThis->DestroyMainWindow(); + + // initiate engine shutdown + DWORD dwQuit = HRESULT_CODE(hr); + if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == pThis->m_restartResult) + { + dwQuit = ERROR_SUCCESS_REBOOT_INITIATED; + } + else if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == pThis->m_restartResult) + { + dwQuit = ERROR_SUCCESS_REBOOT_REQUIRED; + } + pThis->m_pEngine->Quit(dwQuit); + + ReleaseTheme(pThis->m_pTheme); + ThemeUninitialize(); + + // uninitialize COM + if (fComInitialized) + { + ::CoUninitialize(); + } + + return hr; + } + + + static DWORD WINAPI ThreadProc( + __in LPVOID pvContext + ) + { + CWixStandardBootstrapperApplication* pThis = static_cast(pvContext);; + + HRESULT hr = S_OK; + IXMLDOMDocument *pixd = NULL; + IXMLDOMNode* pNode = NULL; + LPWSTR sczUpdateUrl = NULL; + DWORD64 qwSize = 0; + + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Checking for update."); + + // Load the update XML from a location url and parse it for an update. + // + // + // + // + // + + hr = XmlLoadDocumentFromFile(pThis->m_wzUpdateLocation, &pixd); + BalExitOnFailure(hr, "Failed to load version check XML document."); + + hr = XmlSelectSingleNode(pixd, L"/Setup/Upgrade", &pNode); + BalExitOnFailure(hr, "Failed to select upgrade node."); + + if (S_OK == hr) + { + hr = XmlGetAttributeEx(pNode, L"Url", &sczUpdateUrl); + BalExitOnFailure(hr, "Failed to get url attribute."); + + hr = XmlGetAttributeLargeNumber(pNode, L"Size", &qwSize); + } + + if (sczUpdateUrl && *sczUpdateUrl) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Update available, url: %ls; size: %I64u.", sczUpdateUrl, qwSize); + // Show upgrade on install and modify pages + if (pThis->m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == pThis->m_dwCurrentPage || + pThis->m_rgdwPageIds[WIXSTDBA_PAGE_MODIFY] == pThis->m_dwCurrentPage) + { + pThis->m_pEngine->SetUpdate(NULL, sczUpdateUrl, qwSize, BOOTSTRAPPER_UPDATE_HASH_TYPE_NONE, NULL, 0); + ThemeControlEnable(pThis->m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK, TRUE); + } + } + else + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "No update available."); + } + + LExit: + ReleaseObject(pixd); + ReleaseObject(pNode); + ReleaseStr(sczUpdateUrl); + + return 0; + } + + + // + // InitializeData - initializes all the package and prereq information. + // + HRESULT InitializeData() + { + HRESULT hr = S_OK; + LPWSTR sczModulePath = NULL; + IXMLDOMDocument *pixdManifest = NULL; + + hr = BalManifestLoad(m_hModule, &pixdManifest); + BalExitOnFailure(hr, "Failed to load bootstrapper application manifest."); + + hr = ParseOverridableVariablesFromXml(pixdManifest); + BalExitOnFailure(hr, "Failed to read overridable variables."); + + hr = ProcessCommandLine(&m_sczLanguage); + ExitOnFailure(hr, "Unknown commandline parameters."); + + hr = PathRelativeToModule(&sczModulePath, NULL, m_hModule); + BalExitOnFailure(hr, "Failed to get module path."); + + hr = LoadLocalization(sczModulePath, m_sczLanguage); + ExitOnFailure(hr, "Failed to load localization."); + + hr = LoadTheme(sczModulePath, m_sczLanguage); + ExitOnFailure(hr, "Failed to load theme."); + + hr = BalInfoParseFromXml(&m_Bundle, pixdManifest); + BalExitOnFailure(hr, "Failed to load bundle information."); + + hr = BalConditionsParseFromXml(&m_Conditions, pixdManifest, m_pWixLoc); + BalExitOnFailure(hr, "Failed to load conditions from XML."); + + LoadBootstrapperBAFunctions(); + + hr = ParseBootrapperApplicationDataFromXml(pixdManifest); + BalExitOnFailure(hr, "Failed to read bootstrapper application data."); + + LExit: + ReleaseObject(pixdManifest); + ReleaseStr(sczModulePath); + + return hr; + } + + + // + // ProcessCommandLine - process the provided command line arguments. + // + HRESULT ProcessCommandLine( + __inout LPWSTR* psczLanguage + ) + { + HRESULT hr = S_OK; + int argc = 0; + LPWSTR* argv = NULL; + LPWSTR sczVariableName = NULL; + LPWSTR sczVariableValue = NULL; + + if (m_command.wzCommandLine && *m_command.wzCommandLine) + { + argv = ::CommandLineToArgvW(m_command.wzCommandLine, &argc); + ExitOnNullWithLastError(argv, hr, "Failed to get command line."); + + for (int i = 0; i < argc; ++i) + { + if (argv[i][0] == L'-' || argv[i][0] == L'/') + { + if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"lang", -1)) + { + if (i + 1 >= argc) + { + hr = E_INVALIDARG; + BalExitOnFailure(hr, "Must specify a language."); + } + + ++i; + + hr = StrAllocString(psczLanguage, &argv[i][0], 0); + BalExitOnFailure(hr, "Failed to copy language."); + } + } + else if (m_sdOverridableVariables) + { + const wchar_t* pwc = wcschr(argv[i], L'='); + if (pwc) + { + hr = StrAllocString(&sczVariableName, argv[i], pwc - argv[i]); + BalExitOnFailure(hr, "Failed to copy variable name."); + + hr = DictKeyExists(m_sdOverridableVariables, sczVariableName); + if (E_NOTFOUND == hr) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Ignoring attempt to set non-overridable variable: '%ls'.", sczVariableName); + hr = S_OK; + continue; + } + ExitOnFailure(hr, "Failed to check the dictionary of overridable variables."); + + hr = StrAllocString(&sczVariableValue, ++pwc, 0); + BalExitOnFailure(hr, "Failed to copy variable value."); + + hr = m_pEngine->SetVariableString(sczVariableName, sczVariableValue); + BalExitOnFailure(hr, "Failed to set variable."); + } + else + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Ignoring unknown argument: %ls", argv[i]); + } + } + } + } + + LExit: + if (argv) + { + ::LocalFree(argv); + } + + ReleaseStr(sczVariableName); + ReleaseStr(sczVariableValue); + + return hr; + } + + HRESULT LoadLocalization( + __in_z LPCWSTR wzModulePath, + __in_z_opt LPCWSTR wzLanguage + ) + { + HRESULT hr = S_OK; + LPWSTR sczLocPath = NULL; + LPCWSTR wzLocFileName = L"thm.wxl"; + + hr = LocProbeForFile(wzModulePath, wzLocFileName, wzLanguage, &sczLocPath); + BalExitOnFailure2(hr, "Failed to probe for loc file: %ls in path: %ls", wzLocFileName, wzModulePath); + + hr = LocLoadFromFile(sczLocPath, &m_pWixLoc); + BalExitOnFailure1(hr, "Failed to load loc file from path: %ls", sczLocPath); + + if (WIX_LOCALIZATION_LANGUAGE_NOT_SET != m_pWixLoc->dwLangId) + { + ::SetThreadLocale(m_pWixLoc->dwLangId); + } + + hr = StrAllocString(&m_sczConfirmCloseMessage, L"#(loc.ConfirmCancelMessage)", 0); + ExitOnFailure(hr, "Failed to initialize confirm message loc identifier."); + + hr = LocLocalizeString(m_pWixLoc, &m_sczConfirmCloseMessage); + BalExitOnFailure1(hr, "Failed to localize confirm close message: %ls", m_sczConfirmCloseMessage); + + LExit: + ReleaseStr(sczLocPath); + + return hr; + } + + + HRESULT LoadTheme( + __in_z LPCWSTR wzModulePath, + __in_z_opt LPCWSTR wzLanguage + ) + { + HRESULT hr = S_OK; + LPWSTR sczThemePath = NULL; + LPCWSTR wzThemeFileName = L"thm.xml"; + LPWSTR sczCaption = NULL; + + hr = LocProbeForFile(wzModulePath, wzThemeFileName, wzLanguage, &sczThemePath); + BalExitOnFailure2(hr, "Failed to probe for theme file: %ls in path: %ls", wzThemeFileName, wzModulePath); + + hr = ThemeLoadFromFile(sczThemePath, &m_pTheme); + BalExitOnFailure1(hr, "Failed to load theme from path: %ls", sczThemePath); + + hr = ThemeLocalize(m_pTheme, m_pWixLoc); + BalExitOnFailure1(hr, "Failed to localize theme: %ls", sczThemePath); + + // Update the caption if there are any formatted strings in it. + hr = BalFormatString(m_pTheme->sczCaption, &sczCaption); + if (SUCCEEDED(hr)) + { + ThemeUpdateCaption(m_pTheme, sczCaption); + } + + LExit: + ReleaseStr(sczCaption); + ReleaseStr(sczThemePath); + + return hr; + } + + + HRESULT ParseOverridableVariablesFromXml( + __in IXMLDOMDocument* pixdManifest + ) + { + HRESULT hr = S_OK; + IXMLDOMNode* pNode = NULL; + IXMLDOMNodeList* pNodes = NULL; + DWORD cNodes = 0; + LPWSTR scz = NULL; + + // get the list of variables users can override on the command line + hr = XmlSelectNodes(pixdManifest, L"/BootstrapperApplicationData/WixStdbaOverridableVariable", &pNodes); + if (S_FALSE == hr) + { + ExitFunction1(hr = S_OK); + } + ExitOnFailure(hr, "Failed to select overridable variable nodes."); + + hr = pNodes->get_length((long*)&cNodes); + ExitOnFailure(hr, "Failed to get overridable variable node count."); + + if (cNodes) + { + hr = DictCreateStringList(&m_sdOverridableVariables, 32, DICT_FLAG_NONE); + ExitOnFailure(hr, "Failed to create the string dictionary."); + + for (DWORD i = 0; i < cNodes; ++i) + { + hr = XmlNextElement(pNodes, &pNode, NULL); + ExitOnFailure(hr, "Failed to get next node."); + + // @Name + hr = XmlGetAttributeEx(pNode, L"Name", &scz); + ExitOnFailure(hr, "Failed to get @Name."); + + hr = DictAddKey(m_sdOverridableVariables, scz); + ExitOnFailure1(hr, "Failed to add \"%ls\" to the string dictionary.", scz); + + // prepare next iteration + ReleaseNullObject(pNode); + } + } + + LExit: + ReleaseObject(pNode); + ReleaseObject(pNodes); + ReleaseStr(scz); + return hr; + } + + + HRESULT ParsePrerequisiteInformationFromXml( + __in IXMLDOMDocument* pixdManifest + ) + { + HRESULT hr = S_OK; + IXMLDOMNode* pNode = NULL; + + hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixMbaPrereqInformation", &pNode); + if (S_FALSE == hr) + { + hr = E_INVALIDARG; + } + BalExitOnFailure(hr, "BootstrapperApplication.xml manifest is missing prerequisite information."); + + hr = XmlGetAttributeEx(pNode, L"PackageId", &m_sczPrereqPackage); + BalExitOnFailure(hr, "Failed to get prerequisite package identifier."); + + hr = XmlGetAttributeEx(pNode, L"LicenseUrl", &m_sczLicenseUrl); + if (E_NOTFOUND == hr) + { + hr = S_OK; + } + BalExitOnFailure(hr, "Failed to get prerequisite license URL."); + + hr = XmlGetAttributeEx(pNode, L"LicenseFile", &m_sczLicenseFile); + if (E_NOTFOUND == hr) + { + hr = S_OK; + } + BalExitOnFailure(hr, "Failed to get prerequisite license file."); + + LExit: + ReleaseObject(pNode); + return hr; + } + + + HRESULT ParseBootrapperApplicationDataFromXml( + __in IXMLDOMDocument* pixdManifest + ) + { + HRESULT hr = S_OK; + IXMLDOMNode* pNode = NULL; + DWORD dwBool = 0; + + hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixExtbaInformation", &pNode); + if (S_FALSE == hr) + { + hr = E_INVALIDARG; + } + BalExitOnFailure(hr, "BootstrapperApplication.xml manifest is missing wixextba information."); + + hr = XmlGetAttributeEx(pNode, L"LicenseFile", &m_sczLicenseFile); + if (E_NOTFOUND == hr) + { + hr = S_OK; + } + BalExitOnFailure(hr, "Failed to get license file."); + + hr = XmlGetAttributeEx(pNode, L"LicenseUrl", &m_sczLicenseUrl); + if (E_NOTFOUND == hr) + { + hr = S_OK; + } + BalExitOnFailure(hr, "Failed to get license URL."); + + ReleaseObject(pNode); + + hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixExtbaOptions", &pNode); + if (S_FALSE == hr) + { + ExitFunction1(hr = S_OK); + } + BalExitOnFailure(hr, "Failed to read wixextba options from BootstrapperApplication.xml manifest."); + + hr = XmlGetAttributeNumber(pNode, L"SuppressOptionsUI", &dwBool); + if (E_NOTFOUND == hr) + { + hr = S_OK; + } + else if (SUCCEEDED(hr)) + { + m_fSuppressOptionsUI = 0 < dwBool; + } + BalExitOnFailure(hr, "Failed to get SuppressOptionsUI value."); + + dwBool = 0; + hr = XmlGetAttributeNumber(pNode, L"SuppressDowngradeFailure", &dwBool); + if (E_NOTFOUND == hr) + { + hr = S_OK; + } + else if (SUCCEEDED(hr)) + { + m_fSuppressDowngradeFailure = 0 < dwBool; + } + BalExitOnFailure(hr, "Failed to get SuppressDowngradeFailure value."); + + dwBool = 0; + hr = XmlGetAttributeNumber(pNode, L"SuppressRepair", &dwBool); + if (E_NOTFOUND == hr) + { + hr = S_OK; + } + else if (SUCCEEDED(hr)) + { + m_fSuppressRepair = 0 < dwBool; + } + BalExitOnFailure(hr, "Failed to get SuppressRepair value."); + + hr = XmlGetAttributeNumber(pNode, L"ShowVersion", &dwBool); + if (E_NOTFOUND == hr) + { + hr = S_OK; + } + else if (SUCCEEDED(hr)) + { + m_fShowVersion = 0 < dwBool; + } + BalExitOnFailure(hr, "Failed to get ShowVersion value."); + + dwBool = 0; + hr = XmlGetAttributeNumber(pNode, L"LaunchPassive", &dwBool); + if (E_NOTFOUND == hr) + { + hr = S_OK; + } + else if (SUCCEEDED(hr)) + { + m_fLaunchPassive = 0 < dwBool; + } + BalExitOnFailure(hr, "Failed to get LaunchPassive value."); + + dwBool = 0; + hr = XmlGetAttributeNumber(pNode, L"LaunchQuiet", &dwBool); + if (E_NOTFOUND == hr) + { + hr = S_OK; + } + else if (SUCCEEDED(hr)) + { + m_fLaunchQuiet = 0 < dwBool; + } + BalExitOnFailure(hr, "Failed to get LaunchQuiet value."); + + LExit: + ReleaseObject(pNode); + return hr; + } + + + // + // CreateMainWindow - creates the main install window. + // + HRESULT CreateMainWindow() + { + HRESULT hr = S_OK; + HICON hIcon = reinterpret_cast(m_pTheme->hIcon); + WNDCLASSW wc = {}; + DWORD dwWindowStyle = 0; + int x = CW_USEDEFAULT; + int y = CW_USEDEFAULT; + POINT ptCursor = {}; + HMONITOR hMonitor = NULL; + MONITORINFO mi = {}; + + // If the theme did not provide an icon, try using the icon from the bundle engine. + if (!hIcon) + { + HMODULE hBootstrapperEngine = ::GetModuleHandleW(NULL); + if (hBootstrapperEngine) + { + hIcon = ::LoadIconW(hBootstrapperEngine, MAKEINTRESOURCEW(1)); + } + } + + // Register the window class and create the window. + wc.lpfnWndProc = CWixStandardBootstrapperApplication::WndProc; + wc.hInstance = m_hModule; + wc.hIcon = hIcon; + wc.hCursor = ::LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); + wc.hbrBackground = m_pTheme->rgFonts[m_pTheme->dwFontId].hBackground; + wc.lpszMenuName = NULL; + wc.lpszClassName = WIXSTDBA_WINDOW_CLASS; + if (!::RegisterClassW(&wc)) + { + ExitWithLastError(hr, "Failed to register window."); + } + + m_fRegistered = TRUE; + + // Calculate the window style based on the theme style and command display value. + dwWindowStyle = m_pTheme->dwStyle; + if (BOOTSTRAPPER_DISPLAY_NONE >= m_command.display) + { + dwWindowStyle &= ~WS_VISIBLE; + } + + // Don't show the window if there is a splash screen (it will be made visible when the splash screen is hidden) + if (::IsWindow(m_command.hwndSplashScreen)) + { + dwWindowStyle &= ~WS_VISIBLE; + } + + // Center the window on the monitor with the mouse. + if (::GetCursorPos(&ptCursor)) + { + hMonitor = ::MonitorFromPoint(ptCursor, MONITOR_DEFAULTTONEAREST); + if (hMonitor) + { + mi.cbSize = sizeof(mi); + if (::GetMonitorInfoW(hMonitor, &mi)) + { + x = mi.rcWork.left + (mi.rcWork.right - mi.rcWork.left - m_pTheme->nWidth) / 2; + y = mi.rcWork.top + (mi.rcWork.bottom - mi.rcWork.top - m_pTheme->nHeight) / 2; + } + } + } + + m_hWnd = ::CreateWindowExW(0, wc.lpszClassName, m_pTheme->sczCaption, dwWindowStyle, x, y, m_pTheme->nWidth, m_pTheme->nHeight, HWND_DESKTOP, NULL, m_hModule, this); + ExitOnNullWithLastError(m_hWnd, hr, "Failed to create window."); + + hr = S_OK; + + LExit: + return hr; + } + + + // + // InitializeTaskbarButton - initializes taskbar button for progress. + // + void InitializeTaskbarButton() + { + HRESULT hr = S_OK; + + hr = ::CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_ALL, __uuidof(ITaskbarList3), reinterpret_cast(&m_pTaskbarList)); + if (REGDB_E_CLASSNOTREG == hr) // not supported before Windows 7 + { + ExitFunction1(hr = S_OK); + } + BalExitOnFailure(hr, "Failed to create ITaskbarList3. Continuing."); + + m_uTaskbarButtonCreatedMessage = ::RegisterWindowMessageW(L"TaskbarButtonCreated"); + BalExitOnNullWithLastError(m_uTaskbarButtonCreatedMessage, hr, "Failed to get TaskbarButtonCreated message. Continuing."); + + LExit: + return; + } + + // + // DestroyMainWindow - clean up all the window registration. + // + void DestroyMainWindow() + { + if (::IsWindow(m_hWnd)) + { + ::DestroyWindow(m_hWnd); + m_hWnd = NULL; + m_fTaskbarButtonOK = FALSE; + } + + if (m_fRegistered) + { + ::UnregisterClassW(WIXSTDBA_WINDOW_CLASS, m_hModule); + m_fRegistered = FALSE; + } + } + + + // + // WndProc - standard windows message handler. + // + static LRESULT CALLBACK WndProc( + __in HWND hWnd, + __in UINT uMsg, + __in WPARAM wParam, + __in LPARAM lParam + ) + { +#pragma warning(suppress:4312) + CWixStandardBootstrapperApplication* pBA = reinterpret_cast(::GetWindowLongPtrW(hWnd, GWLP_USERDATA)); + + switch (uMsg) + { + case WM_NCCREATE: + { + LPCREATESTRUCT lpcs = reinterpret_cast(lParam); + pBA = reinterpret_cast(lpcs->lpCreateParams); +#pragma warning(suppress:4244) + ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast(pBA)); + } + break; + + case WM_NCDESTROY: + { + LRESULT lres = ThemeDefWindowProc(pBA ? pBA->m_pTheme : NULL, hWnd, uMsg, wParam, lParam); + ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, 0); + return lres; + } + + case WM_CREATE: + if (!pBA->OnCreate(hWnd)) + { + return -1; + } + break; + + case WM_QUERYENDSESSION: + return IDCANCEL != pBA->OnSystemShutdown(static_cast(lParam), IDCANCEL); + + case WM_CLOSE: + // If the user chose not to close, do *not* let the default window proc handle the message. + if (!pBA->OnClose()) + { + return 0; + } + break; + + case WM_DESTROY: + ::PostQuitMessage(0); + break; + + case WM_WIXSTDBA_SHOW_HELP: + pBA->OnShowHelp(); + return 0; + + case WM_WIXSTDBA_DETECT_PACKAGES: + pBA->OnDetect(); + return 0; + + case WM_WIXSTDBA_PLAN_PACKAGES: + pBA->OnPlan(static_cast(lParam)); + return 0; + + case WM_WIXSTDBA_APPLY_PACKAGES: + pBA->OnApply(); + return 0; + + case WM_WIXSTDBA_CHANGE_STATE: + pBA->OnChangeState(static_cast(lParam)); + return 0; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX: + pBA->OnClickAcceptCheckbox(); + return 0; + + case WIXSTDBA_CONTROL_OPTIONS_BUTTON: + pBA->OnClickOptionsButton(); + return 0; + + case WIXSTDBA_CONTROL_BROWSE_BUTTON: + pBA->OnClickOptionsBrowseButton(WIXSTDBA_CONTROL_BROWSE_BUTTON); + return 0; + + case WIXSTDBA_CONTROL_BROWSE_BUTTON2: + pBA->OnClickOptionsBrowseButton(WIXSTDBA_CONTROL_BROWSE_BUTTON2); + return 0; + + case WIXSTDBA_CONTROL_OK_BUTTON: + pBA->OnClickOptionsOkButton(); + return 0; + + case WIXSTDBA_CONTROL_CANCEL_BUTTON: + pBA->OnClickOptionsCancelButton(); + return 0; + + case WIXSTDBA_CONTROL_INSTALL_BUTTON: + pBA->OnClickInstallButton(); + return 0; + + case WIXSTDBA_CONTROL_REPAIR_BUTTON: + pBA->OnClickRepairButton(); + return 0; + + case WIXSTDBA_CONTROL_UNINSTALL_BUTTON: + pBA->OnClickUninstallButton(); + return 0; + + case WIXSTDBA_CONTROL_LAUNCH_BUTTON: + pBA->OnClickLaunchButton(); + return 0; + + case WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON: __fallthrough; + case WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON: + pBA->OnClickRestartButton(); + return 0; + + case WIXSTDBA_CONTROL_HELP_CANCEL_BUTTON: __fallthrough; + + case WIXSTDBA_CONTROL_WELCOME_CANCEL_BUTTON: __fallthrough; + case WIXSTDBA_CONTROL_MODIFY_CANCEL_BUTTON: __fallthrough; + case WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON: __fallthrough; + case WIXSTDBA_CONTROL_SUCCESS_CANCEL_BUTTON: __fallthrough; + case WIXSTDBA_CONTROL_FAILURE_CANCEL_BUTTON: __fallthrough; + case WIXSTDBA_CONTROL_CLOSE_BUTTON: + pBA->OnClickCloseButton(); + return 0; + } + break; + + case WM_NOTIFY: + if (lParam) + { + LPNMHDR pnmhdr = reinterpret_cast(lParam); + switch (pnmhdr->code) + { + case NM_CLICK: __fallthrough; + case NM_RETURN: + switch (static_cast(pnmhdr->idFrom)) + { + case WIXSTDBA_CONTROL_EULA_LINK: + pBA->OnClickEulaLink(); + return 1; + case WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK: + pBA->OnClickLogFileLink(); + return 1; + case WIXSTDBA_CONTROL_UPGRADE_LINK: + pBA->OnClickUpgradeLink(); + return 1; + } + } + } + break; + } + + if (pBA && pBA->m_pTaskbarList && uMsg == pBA->m_uTaskbarButtonCreatedMessage) + { + pBA->m_fTaskbarButtonOK = TRUE; + return 0; + } + + return ThemeDefWindowProc(pBA ? pBA->m_pTheme : NULL, hWnd, uMsg, wParam, lParam); + } + + + // + // OnCreate - finishes loading the theme. + // + BOOL OnCreate( + __in HWND hWnd + ) + { + HRESULT hr = S_OK; + LPWSTR sczText = NULL; + LPWSTR sczLicenseFormatted = NULL; + LPWSTR sczLicensePath = NULL; + LPWSTR sczLicenseDirectory = NULL; + LPWSTR sczLicenseFilename = NULL; + + hr = ThemeLoadControls(m_pTheme, hWnd, vrgInitControls, countof(vrgInitControls)); + BalExitOnFailure(hr, "Failed to load theme controls."); + + C_ASSERT(COUNT_WIXSTDBA_PAGE == countof(vrgwzPageNames)); + C_ASSERT(countof(m_rgdwPageIds) == countof(vrgwzPageNames)); + + ThemeGetPageIds(m_pTheme, vrgwzPageNames, m_rgdwPageIds, countof(m_rgdwPageIds)); + + // Initialize the text on all "application" (non-page) controls. + for (DWORD i = 0; i < m_pTheme->cControls; ++i) + { + THEME_CONTROL* pControl = m_pTheme->rgControls + i; + if (!pControl->wPageId && pControl->sczText && *pControl->sczText) + { + HRESULT hrFormat = BalFormatString(pControl->sczText, &sczText); + if (SUCCEEDED(hrFormat)) + { + ThemeSetTextControl(m_pTheme, pControl->wId, sczText); + } + } + } + + // Load the RTF EULA control with text if the control exists. + if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_RICHEDIT)) + { + hr = (m_sczLicenseFile && *m_sczLicenseFile) ? S_OK : E_INVALIDDATA; + if (SUCCEEDED(hr)) + { + hr = StrAllocString(&sczLicenseFormatted, m_sczLicenseFile, 0); + if (SUCCEEDED(hr)) + { + hr = LocLocalizeString(m_pWixLoc, &sczLicenseFormatted); + if (SUCCEEDED(hr)) + { + hr = BalFormatString(sczLicenseFormatted, &sczLicenseFormatted); + if (SUCCEEDED(hr)) + { + hr = PathRelativeToModule(&sczLicensePath, sczLicenseFormatted, m_hModule); + if (SUCCEEDED(hr)) + { + hr = PathGetDirectory(sczLicensePath, &sczLicenseDirectory); + if (SUCCEEDED(hr)) + { + hr = StrAllocString(&sczLicenseFilename, PathFile(sczLicenseFormatted), 0); + if (SUCCEEDED(hr)) + { + hr = LocProbeForFile(sczLicenseDirectory, sczLicenseFilename, m_sczLanguage, &sczLicensePath); + if (SUCCEEDED(hr)) + { + hr = ThemeLoadRichEditFromFile(m_pTheme, WIXSTDBA_CONTROL_EULA_RICHEDIT, sczLicensePath, m_hModule); + } + } + } + } + } + } + } + } + + if (FAILED(hr)) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Failed to load file into license richedit control from path '%ls' manifest value: %ls", sczLicensePath, m_sczLicenseFile); + hr = S_OK; + } + } + + LExit: + ReleaseStr(sczLicenseFilename); + ReleaseStr(sczLicenseDirectory); + ReleaseStr(sczLicensePath); + ReleaseStr(sczLicenseFormatted); + ReleaseStr(sczText); + + return SUCCEEDED(hr); + } + + + // + // OnShowHelp - display the help page. + // + void OnShowHelp() + { + SetState(WIXSTDBA_STATE_HELP, S_OK); + + // If the UI should be visible, display it now and hide the splash screen + if (BOOTSTRAPPER_DISPLAY_NONE < m_command.display) + { + ::ShowWindow(m_pTheme->hwndParent, SW_SHOW); + } + + m_pEngine->CloseSplashScreen(); + + return; + } + + + // + // OnDetect - start the processing of packages. + // + void OnDetect() + { + HRESULT hr = S_OK; + + if (m_pBAFunction) + { + hr = m_pBAFunction->OnDetect(); + BalExitOnFailure(hr, "Failed calling detect BA function."); + } + + SetState(WIXSTDBA_STATE_DETECTING, hr); + + // If the UI should be visible, display it now and hide the splash screen + if (BOOTSTRAPPER_DISPLAY_NONE < m_command.display) + { + ::ShowWindow(m_pTheme->hwndParent, SW_SHOW); + } + + m_pEngine->CloseSplashScreen(); + + // Tell the core we're ready for the packages to be processed now. + hr = m_pEngine->Detect(); + BalExitOnFailure(hr, "Failed to start detecting chain."); + + LExit: + if (FAILED(hr)) + { + SetState(WIXSTDBA_STATE_DETECTING, hr); + } + + return; + } + + + // + // OnPlan - plan the detected changes. + // + void OnPlan( + __in BOOTSTRAPPER_ACTION action + ) + { + HRESULT hr = S_OK; + + m_plannedAction = action; + + // If we are going to apply a downgrade, bail. + if (m_fDowngrading && BOOTSTRAPPER_ACTION_UNINSTALL < action) + { + if (m_fSuppressDowngradeFailure) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "A newer version of this product is installed but downgrade failure has been suppressed; continuing..."); + } + else + { + hr = HRESULT_FROM_WIN32(ERROR_PRODUCT_VERSION); + BalExitOnFailure(hr, "Cannot install a product when a newer version is installed."); + } + } + + SetState(WIXSTDBA_STATE_PLANNING, hr); + + if (m_pBAFunction) + { + m_pBAFunction->OnPlan(); + } + + hr = m_pEngine->Plan(action); + BalExitOnFailure(hr, "Failed to start planning packages."); + + LExit: + if (FAILED(hr)) + { + SetState(WIXSTDBA_STATE_PLANNING, hr); + } + + return; + } + + + // + // OnApply - apply the packages. + // + void OnApply() + { + HRESULT hr = S_OK; + + SetState(WIXSTDBA_STATE_APPLYING, hr); + SetProgressState(hr); + SetTaskbarButtonProgress(0); + + hr = m_pEngine->Apply(m_hWnd); + BalExitOnFailure(hr, "Failed to start applying packages."); + + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, TRUE); // ensure the cancel button is enabled before starting. + + LExit: + if (FAILED(hr)) + { + SetState(WIXSTDBA_STATE_APPLYING, hr); + } + + return; + } + + + // + // OnChangeState - change state. + // + void OnChangeState( + __in WIXSTDBA_STATE state + ) + { + WIXSTDBA_STATE stateOld = m_state; + DWORD dwOldPageId = 0; + DWORD dwNewPageId = 0; + LPWSTR sczText = NULL; + LPWSTR sczUnformattedText = NULL; + LPWSTR sczControlState = NULL; + LPWSTR sczControlName = NULL; + + m_state = state; + + // If our install is at the end (success or failure) and we're not showing full UI or + // we successfully installed the prerequisite then exit (prompt for restart if required). + if ((WIXSTDBA_STATE_APPLIED <= m_state && BOOTSTRAPPER_DISPLAY_FULL > m_command.display) || + (WIXSTDBA_STATE_APPLIED == m_state && m_fPrereq)) + { + // If a restart was required but we were not automatically allowed to + // accept the reboot then do the prompt. + if (m_fRestartRequired && !m_fAllowRestart) + { + StrAllocFromError(&sczUnformattedText, HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED), NULL); + + int nResult = ::MessageBoxW(m_hWnd, sczUnformattedText ? sczUnformattedText : L"The requested operation is successful. Changes will not be effective until the system is rebooted.", m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OKCANCEL); + m_fAllowRestart = (IDOK == nResult); + } + + if ((BOOTSTRAPPER_DISPLAY_PASSIVE == m_command.display && m_fLaunchPassive) || (m_command.display == BOOTSTRAPPER_DISPLAY_NONE && m_fLaunchQuiet)) + { + BOOL fLaunchTargetExists = BalStringVariableExists(WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH); + if (fLaunchTargetExists) + OnClickLaunchButton(); + } + + // Quietly exit. + ::PostMessageW(m_hWnd, WM_CLOSE, 0, 0); + } + else // try to change the pages. + { + DeterminePageId(stateOld, &dwOldPageId); + DeterminePageId(m_state, &dwNewPageId); + + if (dwOldPageId != dwNewPageId) + { + // Enable disable controls per-page. + if (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == dwNewPageId) // on the "Install" page, ensure the install button is enabled/disabled correctly. + { + LONGLONG llElevated = 0; + if (m_Bundle.fPerMachine) + { + BalGetNumericVariable(WIXBUNDLE_VARIABLE_ELEVATED, &llElevated); + } + ThemeControlElevates(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, (m_Bundle.fPerMachine && !llElevated)); + + // If the EULA control exists, show it only if a license URL is provided as well. + if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_LINK)) + { + BOOL fEulaLink = (m_sczLicenseUrl && *m_sczLicenseUrl); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_EULA_LINK, fEulaLink); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX, fEulaLink); + } + + BOOL fAcceptedLicense = !ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX) || !ThemeControlEnabled(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX) || ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAcceptedLicense); + + // If there is an "Options" page, the "Options" button exists, and it hasn't been suppressed, then enable the button. + BOOL fOptionsEnabled = m_rgdwPageIds[WIXSTDBA_PAGE_OPTIONS] && ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_OPTIONS_BUTTON) && !m_fSuppressOptionsUI; + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_OPTIONS_BUTTON, fOptionsEnabled); + + // Show/Hide the version label if it exists. + if (m_rgdwPageIds[WIXSTDBA_PAGE_OPTIONS] && ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_VERSION_LABEL) && !m_fShowVersion) + { + ThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_VERSION_LABEL, SW_HIDE); + } + } + else if (m_rgdwPageIds[WIXSTDBA_PAGE_MODIFY] == dwNewPageId) + { + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_REPAIR_BUTTON, !m_fSuppressRepair); + } + else if (m_rgdwPageIds[WIXSTDBA_PAGE_OPTIONS] == dwNewPageId) + { + HRESULT hr = BalGetStringVariable(WIXSTDBA_VARIABLE_INSTALL_FOLDER, &sczUnformattedText); + if (SUCCEEDED(hr)) + { + BalFormatString(sczUnformattedText, &sczText); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_FOLDER_EDITBOX, sczText); + } + + hr = BalGetStringVariable(WIXSTDBA_VARIABLE_INSTALL_FOLDER2, &sczUnformattedText); + if (SUCCEEDED(hr)) + { + BalFormatString(sczUnformattedText, &sczText); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_FOLDER_EDITBOX2, sczText); + } + } + else if (m_rgdwPageIds[WIXSTDBA_PAGE_SUCCESS] == dwNewPageId) // on the "Success" page, check if the restart or launch button should be enabled. + { + BOOL fShowRestartButton = FALSE; + BOOL fLaunchTargetExists = FALSE; + if (m_fRestartRequired) + { + if (BOOTSTRAPPER_RESTART_PROMPT == m_command.restart) + { + fShowRestartButton = TRUE; + } + } + else if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_LAUNCH_BUTTON)) + { + fLaunchTargetExists = BalStringVariableExists(WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH); + } + + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_LAUNCH_BUTTON, fLaunchTargetExists && BOOTSTRAPPER_ACTION_UNINSTALL < m_plannedAction); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_SUCCESS_RESTART_TEXT, fShowRestartButton); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON, fShowRestartButton); + } + else if (m_rgdwPageIds[WIXSTDBA_PAGE_FAILURE] == dwNewPageId) // on the "Failure" page, show error message and check if the restart button should be enabled. + { + BOOL fShowLogLink = (m_Bundle.sczLogVariable && *m_Bundle.sczLogVariable); // if there is a log file variable then we'll assume the log file exists. + BOOL fShowErrorMessage = FALSE; + BOOL fShowRestartButton = FALSE; + + if (FAILED(m_hrFinal)) + { + // If we know the failure message, use that. + if (m_sczFailedMessage && *m_sczFailedMessage) + { + StrAllocString(&sczUnformattedText, m_sczFailedMessage, 0); + } + else // try to get the error message from the error code. + { + StrAllocFromError(&sczUnformattedText, m_hrFinal, NULL); + if (!sczUnformattedText || !*sczUnformattedText) + { + StrAllocFromError(&sczUnformattedText, E_FAIL, NULL); + } + } + + StrAllocFormatted(&sczText, L"0x%08x - %ls", m_hrFinal, sczUnformattedText); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, sczText); + fShowErrorMessage = TRUE; + } + + if (m_fRestartRequired) + { + if (BOOTSTRAPPER_RESTART_PROMPT == m_command.restart) + { + fShowRestartButton = TRUE; + } + } + + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK, fShowLogLink); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, fShowErrorMessage); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_RESTART_TEXT, fShowRestartButton); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON, fShowRestartButton); + } + + // Hide the upgrade link + if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK)) + { + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK, FALSE); + } + + // Process each control for special handling in the new page. + THEME_PAGE* pPage = ThemeGetPage(m_pTheme, dwNewPageId); + if (pPage) + { + for (DWORD i = 0; i < pPage->cControlIndices; ++i) + { + THEME_CONTROL* pControl = m_pTheme->rgControls + pPage->rgdwControlIndices[i]; + + // If we are on the install, options or modify pages and this is a named control, try to set its default state. + if ((m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == dwNewPageId || + m_rgdwPageIds[WIXSTDBA_PAGE_OPTIONS] == dwNewPageId || + m_rgdwPageIds[WIXSTDBA_PAGE_MODIFY] == dwNewPageId) && + pControl->sczName && *pControl->sczName) + { + // If this is a checkbox control, try to set its default state to the state of a matching named Burn variable. + if (THEME_CONTROL_TYPE_CHECKBOX == pControl->type && WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX != pControl->wId) + { + LONGLONG llValue = 0; + HRESULT hr = BalGetNumericVariable(pControl->sczName, &llValue); + + ThemeSendControlMessage(m_pTheme, pControl->wId, BM_SETCHECK, SUCCEEDED(hr) && llValue ? BST_CHECKED : BST_UNCHECKED, 0); + } + + // If this is a button control with the BS_AUTORADIOBUTTON style, try to set its default + // state to the state of a matching named Burn variable. + if (THEME_CONTROL_TYPE_BUTTON == pControl->type && (BS_AUTORADIOBUTTON == (BS_AUTORADIOBUTTON & pControl->dwStyle))) + { + LONGLONG llValue = 0; + HRESULT hr = BalGetNumericVariable(pControl->sczName, &llValue); + + // If the control value isn't set then disable it. + if (!SUCCEEDED(hr)) + { + ThemeControlEnable(m_pTheme, pControl->wId, FALSE); + } + else + { + ThemeSendControlMessage(m_pTheme, pControl->wId, BM_SETCHECK, SUCCEEDED(hr) && llValue ? BST_CHECKED : BST_UNCHECKED, 0); + } + } + + // Hide or disable controls based on the control name with 'State' appended + HRESULT hr = StrAllocFormatted(&sczControlName, L"%lsState", pControl->sczName); + if (SUCCEEDED(hr)) + { + hr = BalGetStringVariable(sczControlName, &sczControlState); + if (SUCCEEDED(hr) && sczControlState && *sczControlState) + { + if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, sczControlState, -1, L"disable", -1)) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Disable control %ls", pControl->sczName); + ThemeControlEnable(m_pTheme, pControl->wId, FALSE); + } + else if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, sczControlState, -1, L"hide", -1)) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Hide control %ls", pControl->sczName); + // TODO: This doesn't work + ThemeShowControl(m_pTheme, pControl->wId, SW_HIDE); + } + } + } + } + + // Format the text in each of the new page's controls (if they have any text). + if (pControl->sczText && *pControl->sczText) + { + HRESULT hr = BalFormatString(pControl->sczText, &sczText); + if (SUCCEEDED(hr)) + { + ThemeSetTextControl(m_pTheme, pControl->wId, sczText); + } + } + } + } + + ThemeShowPage(m_pTheme, dwOldPageId, SW_HIDE); + ThemeShowPage(m_pTheme, dwNewPageId, SW_SHOW); + + // Remember current page + m_dwCurrentPage = dwNewPageId; + + // On the install page set the focus to the install button or the next enabled control if install is disabled + if (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == dwNewPageId) + { + HWND hwndFocus = ::GetDlgItem(m_pTheme->hwndParent, WIXSTDBA_CONTROL_INSTALL_BUTTON); + if (hwndFocus && !ThemeControlEnabled(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON)) + { + hwndFocus = ::GetNextDlgTabItem(m_pTheme->hwndParent, hwndFocus, FALSE); + } + + if (hwndFocus) + { + ::SetFocus(hwndFocus); + } + } + } + } + + ReleaseStr(sczText); + ReleaseStr(sczUnformattedText); + ReleaseStr(sczControlState); + ReleaseStr(sczControlName); + } + + + // + // OnClose - called when the window is trying to be closed. + // + BOOL OnClose() + { + BOOL fClose = FALSE; + + // If we've already succeeded or failed or showing the help page, just close (prompts are annoying if the bootstrapper is done). + if (WIXSTDBA_STATE_APPLIED <= m_state || WIXSTDBA_STATE_HELP == m_state) + { + fClose = TRUE; + } + else // prompt the user or force the cancel if there is no UI. + { + fClose = PromptCancel(m_hWnd, BOOTSTRAPPER_DISPLAY_FULL != m_command.display, m_sczConfirmCloseMessage ? m_sczConfirmCloseMessage : L"Are you sure you want to cancel?", m_pTheme->sczCaption); + } + + // If we're doing progress then we never close, we just cancel to let rollback occur. + if (WIXSTDBA_STATE_APPLYING <= m_state && WIXSTDBA_STATE_APPLIED > m_state) + { + // If we canceled disable cancel button since clicking it again is silly. + if (fClose) + { + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, FALSE); + } + + fClose = FALSE; + } + + return fClose; + } + + + // + // OnClickAcceptCheckbox - allow the install to continue. + // + void OnClickAcceptCheckbox() + { + BOOL fAcceptedLicense = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAcceptedLicense); + } + + + // + // OnClickOptionsButton - show the options page. + // + void OnClickOptionsButton() + { + SavePageSettings(WIXSTDBA_PAGE_INSTALL); + m_stateBeforeOptions = m_state; + SetState(WIXSTDBA_STATE_OPTIONS, S_OK); + } + + + // + // OnClickOptionsBrowseButton - browse for install folder on the options page. + // + void OnClickOptionsBrowseButton(DWORD dwControl) + { + WCHAR wzPath[MAX_PATH] = {}; + BROWSEINFOW browseInfo = {}; + PIDLIST_ABSOLUTE pidl = NULL; + PIDLIST_ABSOLUTE pidlRoot = NULL; + + ::SHGetFolderLocation(m_hWnd, CSIDL_DRIVES, NULL, 0, &pidlRoot); + + browseInfo.hwndOwner = m_hWnd; + browseInfo.pszDisplayName = wzPath; + browseInfo.lpszTitle = m_pTheme->sczCaption; + browseInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI; + browseInfo.pidlRoot = pidlRoot; + pidl = ::SHBrowseForFolderW(&browseInfo); + if (pidl && ::SHGetPathFromIDListW(pidl, wzPath)) + { + switch (dwControl) + { + case WIXSTDBA_CONTROL_BROWSE_BUTTON: + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_FOLDER_EDITBOX, wzPath); + break; + + case WIXSTDBA_CONTROL_BROWSE_BUTTON2: + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_FOLDER_EDITBOX2, wzPath); + break; + } + } + + if (pidl) + { + ::CoTaskMemFree(pidl); + } + + return; + } + + // + // OnClickOptionsOkButton - accept the changes made by the options page. + // + void OnClickOptionsOkButton() + { + HRESULT hr = S_OK; + LPWSTR sczPath = NULL; + + if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_FOLDER_EDITBOX)) + { + hr = ThemeGetTextControl(m_pTheme, WIXSTDBA_CONTROL_FOLDER_EDITBOX, &sczPath); + ExitOnFailure(hr, "Failed to get text from folder edit box."); + + // TODO: verify the path is valid. + + hr = m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_INSTALL_FOLDER, sczPath); + ExitOnFailure(hr, "Failed to set the install folder."); + } + + if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_FOLDER_EDITBOX2)) + { + hr = ThemeGetTextControl(m_pTheme, WIXSTDBA_CONTROL_FOLDER_EDITBOX2, &sczPath); + ExitOnFailure(hr, "Failed to get text from folder edit box2."); + + // TODO: verify the path is valid. + + hr = m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_INSTALL_FOLDER2, sczPath); + ExitOnFailure(hr, "Failed to set the install folder2."); + } + + SavePageSettings(WIXSTDBA_PAGE_OPTIONS); + + LExit: + SetState(m_stateBeforeOptions, S_OK); + return; + } + + + // + // OnClickOptionsCancelButton - discard the changes made by the options page. + // + void OnClickOptionsCancelButton() + { + SetState(m_stateBeforeOptions, S_OK); + } + + + // + // OnClickInstallButton - start the install by planning the packages. + // + void OnClickInstallButton() + { + SavePageSettings(WIXSTDBA_PAGE_INSTALL); + + this->OnPlan(BOOTSTRAPPER_ACTION_INSTALL); + } + + + // + // OnClickRepairButton - start the repair. + // + void OnClickRepairButton() + { + this->OnPlan(BOOTSTRAPPER_ACTION_REPAIR); + } + + + // + // OnClickUninstallButton - start the uninstall. + // + void OnClickUninstallButton() + { + this->OnPlan(BOOTSTRAPPER_ACTION_UNINSTALL); + } + + + // + // OnClickCloseButton - close the application. + // + void OnClickCloseButton() + { + ::SendMessageW(m_hWnd, WM_CLOSE, 0, 0); + } + + + // + // OnClickEulaLink - show the end user license agreement. + // + void OnClickEulaLink() + { + HRESULT hr = S_OK; + LPWSTR sczLicenseUrl = NULL; + LPWSTR sczLicensePath = NULL; + LPWSTR sczLicenseDirectory = NULL; + URI_PROTOCOL protocol = URI_PROTOCOL_UNKNOWN; + + hr = StrAllocString(&sczLicenseUrl, m_sczLicenseUrl, 0); + BalExitOnFailure1(hr, "Failed to copy license URL: %ls", m_sczLicenseUrl); + + hr = LocLocalizeString(m_pWixLoc, &sczLicenseUrl); + BalExitOnFailure1(hr, "Failed to localize license URL: %ls", m_sczLicenseUrl); + + hr = BalFormatString(sczLicenseUrl, &sczLicenseUrl); + BalExitOnFailure1(hr, "Failed to get formatted license URL: %ls", m_sczLicenseUrl); + + hr = UriProtocol(sczLicenseUrl, &protocol); + if (FAILED(hr) || URI_PROTOCOL_UNKNOWN == protocol) + { + // Probe for localised license file + hr = PathRelativeToModule(&sczLicensePath, sczLicenseUrl, m_hModule); + if (SUCCEEDED(hr)) + { + hr = PathGetDirectory(sczLicensePath, &sczLicenseDirectory); + if (SUCCEEDED(hr)) + { + hr = LocProbeForFile(sczLicenseDirectory, PathFile(sczLicenseUrl), m_sczLanguage, &sczLicensePath); + } + } + } + + hr = ShelExec(sczLicensePath ? sczLicensePath : sczLicenseUrl, NULL, L"open", NULL, SW_SHOWDEFAULT, m_hWnd, NULL); + BalExitOnFailure(hr, "Failed to launch URL to EULA."); + + LExit: + ReleaseStr(sczLicensePath); + ReleaseStr(sczLicenseUrl); + ReleaseStr(sczLicenseDirectory); + + return; + } + + + // + // OnClickUpgradeLink - download the upgrade. + // + void OnClickUpgradeLink() + { + this->OnPlan(BOOTSTRAPPER_ACTION_UPDATE_REPLACE); + + m_fUpdating = TRUE; + + return; + } + + + // + // OnClickLaunchButton - launch the app from the success page. + // + void OnClickLaunchButton() + { + HRESULT hr = S_OK; + LPWSTR sczUnformattedLaunchTarget = NULL; + LPWSTR sczLaunchTarget = NULL; + LPWSTR sczUnformattedArguments = NULL; + LPWSTR sczArguments = NULL; + int nCmdShow = SW_SHOWNORMAL; + + hr = BalGetStringVariable(WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH, &sczUnformattedLaunchTarget); + BalExitOnFailure1(hr, "Failed to get launch target variable '%ls'.", WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH); + + hr = BalFormatString(sczUnformattedLaunchTarget, &sczLaunchTarget); + BalExitOnFailure1(hr, "Failed to format launch target variable: %ls", sczUnformattedLaunchTarget); + + if (BalStringVariableExists(WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS)) + { + hr = BalGetStringVariable(WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS, &sczUnformattedArguments); + BalExitOnFailure1(hr, "Failed to get launch arguments '%ls'.", WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS); + + hr = BalFormatString(sczUnformattedArguments, &sczArguments); + BalExitOnFailure1(hr, "Failed to format launch arguments variable: %ls", sczUnformattedArguments); + } + + if (BalStringVariableExists(WIXSTDBA_VARIABLE_LAUNCH_HIDDEN)) + { + nCmdShow = SW_HIDE; + } + + hr = ShelExec(sczLaunchTarget, sczArguments, L"open", NULL, nCmdShow, m_hWnd, NULL); + BalExitOnFailure1(hr, "Failed to launch target: %ls", sczLaunchTarget); + + ::PostMessageW(m_hWnd, WM_CLOSE, 0, 0); + + LExit: + ReleaseStr(sczArguments); + ReleaseStr(sczUnformattedArguments); + ReleaseStr(sczLaunchTarget); + ReleaseStr(sczUnformattedLaunchTarget); + + return; + } + + + // + // OnClickRestartButton - allows the restart and closes the app. + // + void OnClickRestartButton() + { + AssertSz(m_fRestartRequired, "Restart must be requested to be able to click on the restart button."); + + m_fAllowRestart = TRUE; + ::SendMessageW(m_hWnd, WM_CLOSE, 0, 0); + + return; + } + + + // + // OnClickLogFileLink - show the log file. + // + void OnClickLogFileLink() + { + HRESULT hr = S_OK; + LPWSTR sczLogFile = NULL; + + hr = BalGetStringVariable(m_Bundle.sczLogVariable, &sczLogFile); + BalExitOnFailure1(hr, "Failed to get log file variable '%ls'.", m_Bundle.sczLogVariable); + + hr = ShelExec(L"notepad.exe", sczLogFile, L"open", NULL, SW_SHOWDEFAULT, m_hWnd, NULL); + BalExitOnFailure1(hr, "Failed to open log file target: %ls", sczLogFile); + + LExit: + ReleaseStr(sczLogFile); + + return; + } + + + // + // SetState + // + void SetState( + __in WIXSTDBA_STATE state, + __in HRESULT hrStatus + ) + { + if (FAILED(hrStatus)) + { + m_hrFinal = hrStatus; + } + + if (FAILED(m_hrFinal)) + { + state = WIXSTDBA_STATE_FAILED; + } + + if (WIXSTDBA_STATE_OPTIONS == state || m_state < state) + { + ::PostMessageW(m_hWnd, WM_WIXSTDBA_CHANGE_STATE, 0, state); + } + } + + + void DeterminePageId( + __in WIXSTDBA_STATE state, + __out DWORD* pdwPageId + ) + { + if (BOOTSTRAPPER_DISPLAY_PASSIVE == m_command.display) + { + switch (state) + { + case WIXSTDBA_STATE_INITIALIZED: + *pdwPageId = BOOTSTRAPPER_ACTION_HELP == m_command.action ? m_rgdwPageIds[WIXSTDBA_PAGE_HELP] : m_rgdwPageIds[WIXSTDBA_PAGE_LOADING]; + break; + + case WIXSTDBA_STATE_HELP: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_HELP]; + break; + + case WIXSTDBA_STATE_DETECTING: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_LOADING] ? m_rgdwPageIds[WIXSTDBA_PAGE_LOADING] : m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS_PASSIVE] ? m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS_PASSIVE] : m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS]; + break; + + case WIXSTDBA_STATE_DETECTED: __fallthrough; + case WIXSTDBA_STATE_PLANNING: __fallthrough; + case WIXSTDBA_STATE_PLANNED: __fallthrough; + case WIXSTDBA_STATE_APPLYING: __fallthrough; + case WIXSTDBA_STATE_CACHING: __fallthrough; + case WIXSTDBA_STATE_CACHED: __fallthrough; + case WIXSTDBA_STATE_EXECUTING: __fallthrough; + case WIXSTDBA_STATE_EXECUTED: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS_PASSIVE] ? m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS_PASSIVE] : m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS]; + break; + + default: + *pdwPageId = 0; + break; + } + } + else if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display) + { + switch (state) + { + case WIXSTDBA_STATE_INITIALIZING: + *pdwPageId = 0; + break; + + case WIXSTDBA_STATE_INITIALIZED: + *pdwPageId = BOOTSTRAPPER_ACTION_HELP == m_command.action ? m_rgdwPageIds[WIXSTDBA_PAGE_HELP] : m_rgdwPageIds[WIXSTDBA_PAGE_LOADING]; + break; + + case WIXSTDBA_STATE_HELP: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_HELP]; + break; + + case WIXSTDBA_STATE_DETECTING: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_LOADING]; + break; + + case WIXSTDBA_STATE_DETECTED: + switch (m_command.action) + { + case BOOTSTRAPPER_ACTION_INSTALL: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL]; + break; + + case BOOTSTRAPPER_ACTION_MODIFY: __fallthrough; + case BOOTSTRAPPER_ACTION_REPAIR: __fallthrough; + case BOOTSTRAPPER_ACTION_UNINSTALL: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_MODIFY]; + break; + } + break; + + case WIXSTDBA_STATE_OPTIONS: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_OPTIONS]; + break; + + case WIXSTDBA_STATE_PLANNING: __fallthrough; + case WIXSTDBA_STATE_PLANNED: __fallthrough; + case WIXSTDBA_STATE_APPLYING: __fallthrough; + case WIXSTDBA_STATE_CACHING: __fallthrough; + case WIXSTDBA_STATE_CACHED: __fallthrough; + case WIXSTDBA_STATE_EXECUTING: __fallthrough; + case WIXSTDBA_STATE_EXECUTED: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS]; + break; + + case WIXSTDBA_STATE_APPLIED: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_SUCCESS]; + break; + + case WIXSTDBA_STATE_FAILED: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_FAILURE]; + break; + } + } + } + + + HRESULT EvaluateConditions() + { + HRESULT hr = S_OK; + BOOL fResult = FALSE; + + for (DWORD i = 0; i < m_Conditions.cConditions; ++i) + { + BAL_CONDITION* pCondition = m_Conditions.rgConditions + i; + + hr = BalConditionEvaluate(pCondition, m_pEngine, &fResult, &m_sczFailedMessage); + BalExitOnFailure(hr, "Failed to evaluate condition."); + + if (!fResult) + { + hr = E_WIXSTDBA_CONDITION_FAILED; + BalExitOnFailure1(hr, "Bundle condition evaluated to false: %ls", pCondition->sczCondition); + } + } + + ReleaseNullStr(m_sczFailedMessage); + + LExit: + return hr; + } + + + void SetTaskbarButtonProgress( + __in DWORD dwOverallPercentage + ) + { + HRESULT hr = S_OK; + + if (m_fTaskbarButtonOK) + { + hr = m_pTaskbarList->SetProgressValue(m_hWnd, dwOverallPercentage, 100UL); + BalExitOnFailure1(hr, "Failed to set taskbar button progress to: %d%%.", dwOverallPercentage); + } + + LExit: + return; + } + + + void SetTaskbarButtonState( + __in TBPFLAG tbpFlags + ) + { + HRESULT hr = S_OK; + + if (m_fTaskbarButtonOK) + { + hr = m_pTaskbarList->SetProgressState(m_hWnd, tbpFlags); + BalExitOnFailure1(hr, "Failed to set taskbar button state.", tbpFlags); + } + + LExit: + return; + } + + + void SetProgressState( + __in HRESULT hrStatus + ) + { + TBPFLAG flag = TBPF_NORMAL; + + if (IsCanceled() || HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) == hrStatus) + { + flag = TBPF_PAUSED; + } + else if (IsRollingBack() || FAILED(hrStatus)) + { + flag = TBPF_ERROR; + } + + SetTaskbarButtonState(flag); + } + + + HRESULT LoadBootstrapperBAFunctions() + { + HRESULT hr = S_OK; + LPWSTR sczBafPath = NULL; + + hr = PathRelativeToModule(&sczBafPath, L"bafunctions.dll", m_hModule); + BalExitOnFailure(hr, "Failed to get path to BA function DLL."); + +#ifdef DEBUG + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXEXTBA: LoadBootstrapperBAFunctions() - BA function DLL '%ls'", sczBafPath); +#endif + + m_hBAFModule = ::LoadLibraryW(sczBafPath); + if (m_hBAFModule) + { + PFN_BOOTSTRAPPER_BA_FUNCTION_CREATE pfnBAFunctionCreate = reinterpret_cast(::GetProcAddress(m_hBAFModule, "CreateBootstrapperBAFunction")); + BalExitOnNullWithLastError1(pfnBAFunctionCreate, hr, "Failed to get CreateBootstrapperBAFunction entry-point from: %ls", sczBafPath); + + hr = pfnBAFunctionCreate(m_pEngine, m_hBAFModule, &m_pBAFunction); + BalExitOnFailure(hr, "Failed to create BA function."); + } +#ifdef DEBUG + else + { + BalLogError(HRESULT_FROM_WIN32(::GetLastError()), "WIXEXTBA: LoadBootstrapperBAFunctions() - Failed to load DLL %ls", sczBafPath); + } +#endif + + LExit: + if (m_hBAFModule && !m_pBAFunction) + { + ::FreeLibrary(m_hBAFModule); + m_hBAFModule = NULL; + } + ReleaseStr(sczBafPath); + + return hr; + } + + + void SavePageSettings( + __in WIXSTDBA_PAGE page + ) + { + THEME_PAGE* pPage = NULL; + + pPage = ThemeGetPage(m_pTheme, m_rgdwPageIds[page]); + if (pPage) + { + for (DWORD i = 0; i < pPage->cControlIndices; ++i) + { + // Loop through all the checkbox controls (or buttons with BS_AUTORADIOBUTTON) with names and set a Burn variable with that name to true or false. + THEME_CONTROL* pControl = m_pTheme->rgControls + pPage->rgdwControlIndices[i]; + if ((THEME_CONTROL_TYPE_CHECKBOX == pControl->type) || + (THEME_CONTROL_TYPE_BUTTON == pControl->type && (BS_AUTORADIOBUTTON == (BS_AUTORADIOBUTTON & pControl->dwStyle)) && + pControl->sczName && *pControl->sczName)) + { + BOOL bChecked = ThemeIsControlChecked(m_pTheme, pControl->wId); + m_pEngine->SetVariableNumeric(pControl->sczName, bChecked ? 1 : 0); + } + + // Loop through all the editbox controls with names and set a Burn variable with that name to the contents. + if (THEME_CONTROL_TYPE_EDITBOX == pControl->type && pControl->sczName && *pControl->sczName && + (WIXSTDBA_CONTROL_FOLDER_EDITBOX != pControl->wId && WIXSTDBA_CONTROL_FOLDER_EDITBOX2 != pControl->wId)) + { + LPWSTR sczValue = NULL; + ThemeGetTextControl(m_pTheme, pControl->wId, &sczValue); + m_pEngine->SetVariableString(pControl->sczName, sczValue); + } + } + } + } + + +public: + // + // Constructor - intitialize member variables. + // + CWixStandardBootstrapperApplication( + __in HMODULE hModule, + __in BOOL fPrereq, + __in IBootstrapperEngine* pEngine, + __in const BOOTSTRAPPER_COMMAND* pCommand + ) : CBalBaseBootstrapperApplication(pEngine, pCommand, 3, 3000) + { + m_hModule = hModule; + memcpy_s(&m_command, sizeof(m_command), pCommand, sizeof(BOOTSTRAPPER_COMMAND)); + + // Pre-req BA should only show help or do an install (to launch the Managed BA which can then do the right action). + if (fPrereq && BOOTSTRAPPER_ACTION_HELP != m_command.action && BOOTSTRAPPER_ACTION_INSTALL != m_command.action) + { + m_command.action = BOOTSTRAPPER_ACTION_INSTALL; + } + else // maybe modify the action state if the bundle is or is not already installed. + { + LONGLONG llInstalled = 0; + HRESULT hr = BalGetNumericVariable(L"WixBundleInstalled", &llInstalled); + if (SUCCEEDED(hr) && BOOTSTRAPPER_RESUME_TYPE_REBOOT != m_command.resumeType && 0 < llInstalled && BOOTSTRAPPER_ACTION_INSTALL == m_command.action) + { + m_command.action = BOOTSTRAPPER_ACTION_MODIFY; + } + else if (0 == llInstalled && (BOOTSTRAPPER_ACTION_MODIFY == m_command.action || BOOTSTRAPPER_ACTION_REPAIR == m_command.action)) + { + m_command.action = BOOTSTRAPPER_ACTION_INSTALL; + } + } + + m_plannedAction = BOOTSTRAPPER_ACTION_UNKNOWN; + + // When resuming from restart doing some install-like operation, try to find the package that forced the + // restart. We'll use this information during planning. + m_sczAfterForcedRestartPackage = NULL; + + if (BOOTSTRAPPER_RESUME_TYPE_REBOOT == m_command.resumeType && BOOTSTRAPPER_ACTION_UNINSTALL < m_command.action) + { + // Ensure the forced restart package variable is null when it is an empty string. + HRESULT hr = BalGetStringVariable(L"WixBundleForcedRestartPackage", &m_sczAfterForcedRestartPackage); + if (FAILED(hr) || !m_sczAfterForcedRestartPackage || !*m_sczAfterForcedRestartPackage) + { + ReleaseNullStr(m_sczAfterForcedRestartPackage); + } + } + + m_pWixLoc = NULL; + memset(&m_Bundle, 0, sizeof(m_Bundle)); + memset(&m_Conditions, 0, sizeof(m_Conditions)); + m_sczConfirmCloseMessage = NULL; + m_sczFailedMessage = NULL; + + m_sczLanguage = NULL; + m_pTheme = NULL; + memset(m_rgdwPageIds, 0, sizeof(m_rgdwPageIds)); + m_dwCurrentPage = 0; + m_hUiThread = NULL; + m_fRegistered = FALSE; + m_hWnd = NULL; + + m_state = WIXSTDBA_STATE_INITIALIZING; + m_hrFinal = S_OK; + + m_fDowngrading = FALSE; + m_restartResult = BOOTSTRAPPER_APPLY_RESTART_NONE; + m_fRestartRequired = FALSE; + m_fAllowRestart = FALSE; + + m_sczLicenseFile = NULL; + m_sczLicenseUrl = NULL; + m_fSuppressOptionsUI = FALSE; + m_fSuppressDowngradeFailure = FALSE; + m_fSuppressRepair = FALSE; + m_fShowVersion = FALSE; + + m_sdOverridableVariables = NULL; + m_pTaskbarList = NULL; + m_uTaskbarButtonCreatedMessage = UINT_MAX; + m_fTaskbarButtonOK = FALSE; + m_fShowingInternalUiThisPackage = FALSE; + + m_fPrereq = fPrereq; + m_sczPrereqPackage = NULL; + m_fPrereqInstalled = FALSE; + m_fPrereqAlreadyInstalled = FALSE; + + m_fUpdating = FALSE; + + pEngine->AddRef(); + m_pEngine = pEngine; + + m_hBAFModule = NULL; + m_pBAFunction = NULL; + } + + + // + // Destructor - release member variables. + // + ~CWixStandardBootstrapperApplication() + { + AssertSz(!::IsWindow(m_hWnd), "Window should have been destroyed before destructor."); + AssertSz(!m_pTheme, "Theme should have been released before destuctor."); + + ReleaseObject(m_pTaskbarList); + ReleaseDict(m_sdOverridableVariables); + ReleaseStr(m_sczFailedMessage); + ReleaseStr(m_sczConfirmCloseMessage); + BalConditionsUninitialize(&m_Conditions); + BalInfoUninitialize(&m_Bundle); + LocFree(m_pWixLoc); + + ReleaseStr(m_sczLanguage); + ReleaseStr(m_sczLicenseFile); + ReleaseStr(m_sczLicenseUrl); + ReleaseStr(m_sczPrereqPackage); + ReleaseStr(m_sczAfterForcedRestartPackage); + ReleaseNullObject(m_pEngine); + + if (m_hBAFModule) + { + ::FreeLibrary(m_hBAFModule); + m_hBAFModule = NULL; + } + } + +private: + HMODULE m_hModule; + BOOTSTRAPPER_COMMAND m_command; + IBootstrapperEngine* m_pEngine; + BOOTSTRAPPER_ACTION m_plannedAction; + + LPWSTR m_sczAfterForcedRestartPackage; + + WIX_LOCALIZATION* m_pWixLoc; + BAL_INFO_BUNDLE m_Bundle; + BAL_CONDITIONS m_Conditions; + LPWSTR m_sczFailedMessage; + LPWSTR m_sczConfirmCloseMessage; + + LPWSTR m_sczLanguage; + THEME* m_pTheme; + DWORD m_rgdwPageIds[countof(vrgwzPageNames)]; + DWORD m_dwCurrentPage; + HANDLE m_hUiThread; + BOOL m_fRegistered; + HWND m_hWnd; + + WIXSTDBA_STATE m_state; + WIXSTDBA_STATE m_stateBeforeOptions; + HRESULT m_hrFinal; + + BOOL m_fStartedExecution; + DWORD m_dwCalculatedCacheProgress; + DWORD m_dwCalculatedExecuteProgress; + + BOOL m_fDowngrading; + BOOTSTRAPPER_APPLY_RESTART m_restartResult; + BOOL m_fRestartRequired; + BOOL m_fAllowRestart; + + LPWSTR m_sczLicenseFile; + LPWSTR m_sczLicenseUrl; + BOOL m_fSuppressOptionsUI; + BOOL m_fSuppressDowngradeFailure; + BOOL m_fSuppressRepair; + BOOL m_fShowVersion; + BOOL m_fLaunchPassive; + BOOL m_fLaunchQuiet; + + STRINGDICT_HANDLE m_sdOverridableVariables; + + BOOL m_fPrereq; + LPWSTR m_sczPrereqPackage; + BOOL m_fPrereqInstalled; + BOOL m_fPrereqAlreadyInstalled; + + ITaskbarList3* m_pTaskbarList; + UINT m_uTaskbarButtonCreatedMessage; + BOOL m_fTaskbarButtonOK; + BOOL m_fShowingInternalUiThisPackage; + + BOOL m_fUpdating; + LPCWSTR m_wzUpdateLocation; + + HMODULE m_hBAFModule; + IBootstrapperBAFunction* m_pBAFunction; +}; + + +// +// CreateUserExperience - creates a new IBurnUserExperience object. +// +HRESULT CreateBootstrapperApplication( + __in HMODULE hModule, + __in BOOL fPrereq, + __in IBootstrapperEngine* pEngine, + __in const BOOTSTRAPPER_COMMAND* pCommand, + __out IBootstrapperApplication** ppApplication + ) +{ + HRESULT hr = S_OK; + CWixStandardBootstrapperApplication* pApplication = NULL; + + pApplication = new CWixStandardBootstrapperApplication(hModule, fPrereq, pEngine, pCommand); + ExitOnNull(pApplication, hr, E_OUTOFMEMORY, "Failed to create new standard bootstrapper application object."); + + *ppApplication = pApplication; + pApplication = NULL; + +LExit: + ReleaseObject(pApplication); + return hr; +} diff --git a/wixstdba/precomp.h b/wixstdba/precomp.h new file mode 100644 index 0000000..61bee4f --- /dev/null +++ b/wixstdba/precomp.h @@ -0,0 +1,56 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +// +// +// Precompiled header for standard bootstrapper application. +// +//------------------------------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dutil.h" +#include "memutil.h" +#include "dictutil.h" +#include "dirutil.h" +#include "fileutil.h" +#include "locutil.h" +#include "logutil.h" +#include "pathutil.h" +#include "resrutil.h" +#include "shelutil.h" +#include "strutil.h" +#include "thmutil.h" +#include "uriutil.h" +#include "xmlutil.h" + +#include "IBootstrapperEngine.h" +#include "IBootstrapperApplication.h" + +#include "BalBaseBootstrapperApplication.h" +#include "balinfo.h" +#include "balcondition.h" + +HRESULT CreateBootstrapperApplication( + __in HMODULE hModule, + __in BOOL fPrereq, + __in IBootstrapperEngine* pEngine, + __in const BOOTSTRAPPER_COMMAND* pCommand, + __out IBootstrapperApplication** ppApplication + ); + +#include "..\bafunctions\IBootstrapperBAFunction.h" + diff --git a/wixstdba/resource.h b/wixstdba/resource.h new file mode 100644 index 0000000..53c03c3 --- /dev/null +++ b/wixstdba/resource.h @@ -0,0 +1,25 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +//------------------------------------------------------------------------------------------------- + +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// +#define IDC_STATIC -1 + + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1003 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/wixstdba/wixstdba.cpp b/wixstdba/wixstdba.cpp new file mode 100644 index 0000000..59c389c --- /dev/null +++ b/wixstdba/wixstdba.cpp @@ -0,0 +1,61 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +// +// +// Setup chainer/bootstrapper standard UI for WiX toolset. +// +//------------------------------------------------------------------------------------------------- + +#include "precomp.h" + +static HINSTANCE vhInstance = NULL; + +extern "C" BOOL WINAPI DllMain( + IN HINSTANCE hInstance, + IN DWORD dwReason, + IN LPVOID /* pvReserved */ + ) +{ + switch(dwReason) + { + case DLL_PROCESS_ATTACH: + ::DisableThreadLibraryCalls(hInstance); + vhInstance = hInstance; + break; + + case DLL_PROCESS_DETACH: + vhInstance = NULL; + break; + } + + return TRUE; +} + + +extern "C" HRESULT WINAPI BootstrapperApplicationCreate( + __in IBootstrapperEngine* pEngine, + __in const BOOTSTRAPPER_COMMAND* pCommand, + __out IBootstrapperApplication** ppApplication + ) +{ + HRESULT hr = S_OK; + + BalInitialize(pEngine); + + hr = CreateBootstrapperApplication(vhInstance, FALSE, pEngine, pCommand, ppApplication); + BalExitOnFailure(hr, "Failed to create bootstrapper application interface."); + +LExit: + return hr; +} + + +extern "C" void WINAPI BootstrapperApplicationDestroy() +{ + BalUninitialize(); +} diff --git a/wixstdba/wixstdba.def b/wixstdba/wixstdba.def new file mode 100644 index 0000000..e2de8e8 --- /dev/null +++ b/wixstdba/wixstdba.def @@ -0,0 +1,16 @@ +;------------------------------------------------------------------------------------------------- +; +; Copyright (c) 2004, Outercurve Foundation. +; This software is released under Microsoft Reciprocal License (MS-RL). +; The license and further copyright text can be found in the file +; LICENSE.TXT at the root directory of the distribution. +; +; +; +; WiX Standard Bootstrapper Application DLL entry points. +; +;------------------------------------------------------------------------------------------------- + +EXPORTS + BootstrapperApplicationCreate + BootstrapperApplicationDestroy diff --git a/wixstdba/wixstdba.rc b/wixstdba/wixstdba.rc new file mode 100644 index 0000000..98a03ba --- /dev/null +++ b/wixstdba/wixstdba.rc @@ -0,0 +1,19 @@ +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +// +// +// WiX Extendend Bootstrapper Application resource file. +// +//------------------------------------------------------------------------------------------------- + +#define VER_APP +#define VER_ORIGINAL_FILENAME "wixextba.dll" +#define VER_INTERNAL_NAME "wixextba" +#define VER_PRODUCT_NAME "WiX Extendend Bootstrapper Application" +#define VER_FILE_DESCRIPTION "WiX Extendend Bootstrapper Application" +#include "wix.rc" diff --git a/wixstdba/wixstdba.vcxproj b/wixstdba/wixstdba.vcxproj new file mode 100644 index 0000000..3bde57e --- /dev/null +++ b/wixstdba/wixstdba.vcxproj @@ -0,0 +1,144 @@ + + + + + + Debug + Win32 + + + Release + Win32 + + + + {41085a22-e6aa-4e8b-ab1b-ddee0dc89dfa} + WixStdBA + Win32Proj + DynamicLibrary + MultiByte + wixextba + + + + v120 + + + v120 + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(Configuration)\ + $(Configuration)\ + true + AllRules.ruleset + + + $(Configuration)\ + $(Configuration)\ + true + AllRules.ruleset + + + + + + + + + + Disabled + $(WiX)SDK\VS2010\inc;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;DEBUG;%(PreprocessorDefinitions);$(ExtraDefinitions) + true + EnableFastChecks + MultiThreadedDebug + Use + precomp.h + $(IntDir)$(ProjectName).pdb + Level4 + ProgramDatabase + StdCall + true + + + $(ProjectDir)..\inc;%(AdditionalIncludeDirectories) + + + dutil.lib;balutil.lib;comctl32.lib;gdiplus.lib;shlwapi.lib;wininet.lib;version.lib;msimg32.lib;%(AdditionalDependencies) + $(WiX)SDK\VS2010\lib\x86;%(AdditionalLibraryDirectories) + wixstdba.def + true + Windows + + + + + Disabled + $(WiX)SDK\VS2010\inc;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);$(ExtraDefinitions) + true + EnableFastChecks + MultiThreaded + Use + precomp.h + $(IntDir)$(ProjectName).pdb + Level4 + ProgramDatabase + StdCall + true + + + $(ProjectDir)..\inc;%(AdditionalIncludeDirectories) + + + dutil.lib;balutil.lib;comctl32.lib;gdiplus.lib;shlwapi.lib;wininet.lib;version.lib;msimg32.lib;%(AdditionalDependencies) + $(WiX)SDK\VS2010\lib\x86;%(AdditionalLibraryDirectories) + wixstdba.def + false + Windows + + + + + + Create + Create + + + + + + + + + + Designer + + + + + + + + + + + + + + \ No newline at end of file diff --git a/wixstdba/wixstdba.vcxproj.filters b/wixstdba/wixstdba.vcxproj.filters new file mode 100644 index 0000000..ba94b5a --- /dev/null +++ b/wixstdba/wixstdba.vcxproj.filters @@ -0,0 +1,61 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + Source Files + + + + + Source Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + + + Header Files + + + Header Files + + + + + Resource Files + + + \ No newline at end of file