aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2021-10-27 13:55:16 -0500
committerSean Hall <r.sean.hall@gmail.com>2021-11-01 16:34:09 -0500
commit8fa040da9d0d3826f5ffda6bcbec4f53abd97452 (patch)
treea8a1094f3ac17bd6feed8a6f971c0d6008694345 /src
parent4917383e6f52f0e44f63c60a645f1dd7e8f8d5f9 (diff)
downloadwix-8fa040da9d0d3826f5ffda6bcbec4f53abd97452.tar.gz
wix-8fa040da9d0d3826f5ffda6bcbec4f53abd97452.tar.bz2
wix-8fa040da9d0d3826f5ffda6bcbec4f53abd97452.zip
Allow more customization of control ids in thmutil.
Allow BAFunctions to set control ids. Make sure control ids don't collide.
Diffstat (limited to 'src')
-rw-r--r--src/api/burn/balutil/inc/BAFunctions.h18
-rw-r--r--src/api/burn/balutil/inc/BalBaseBAFunctions.h9
-rw-r--r--src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h12
-rw-r--r--src/api/burn/balutil/inc/IBAFunctions.h8
-rw-r--r--src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp65
-rw-r--r--src/libs/dutil/WixToolset.DUtil/inc/thmutil.h35
-rw-r--r--src/libs/dutil/WixToolset.DUtil/thmutil.cpp75
-rw-r--r--src/samples/thmviewer/display.cpp2
-rw-r--r--src/samples/thmviewer/thmviewer.cpp27
-rw-r--r--src/test/burn/TestData/Manual/BafThmutilTesting/BafThmUtilTesting.cpp59
-rw-r--r--src/test/burn/TestData/Manual/BundleA/BundleA.wixproj2
-rw-r--r--src/test/burn/TestData/Manual/BundleA/BundleA.wxs3
-rw-r--r--src/test/burn/TestData/Manual/BundleA/CustomHyperlinkTheme.xml107
13 files changed, 374 insertions, 48 deletions
diff --git a/src/api/burn/balutil/inc/BAFunctions.h b/src/api/burn/balutil/inc/BAFunctions.h
index 43786701..2a34aaad 100644
--- a/src/api/burn/balutil/inc/BAFunctions.h
+++ b/src/api/burn/balutil/inc/BAFunctions.h
@@ -85,6 +85,7 @@ enum BA_FUNCTIONS_MESSAGE
85 85
86 BA_FUNCTIONS_MESSAGE_ONTHEMELOADED = 1024, 86 BA_FUNCTIONS_MESSAGE_ONTHEMELOADED = 1024,
87 BA_FUNCTIONS_MESSAGE_WNDPROC, 87 BA_FUNCTIONS_MESSAGE_WNDPROC,
88 BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLLOADING,
88}; 89};
89 90
90typedef HRESULT(WINAPI *PFN_BA_FUNCTIONS_PROC)( 91typedef HRESULT(WINAPI *PFN_BA_FUNCTIONS_PROC)(
@@ -94,6 +95,10 @@ typedef HRESULT(WINAPI *PFN_BA_FUNCTIONS_PROC)(
94 __in_opt LPVOID pvContext 95 __in_opt LPVOID pvContext
95 ); 96 );
96 97
98// Should be the same as THEME_FIRST_ASSIGN_CONTROL_ID.
99// BAFunctions must only assign ids in the range [BAFUNCTIONS_FIRST_ASSIGN_CONTROL_ID, 0x8000) to avoid collisions.
100const WORD BAFUNCTIONS_FIRST_ASSIGN_CONTROL_ID = 0x4000;
101
97struct BA_FUNCTIONS_CREATE_ARGS 102struct BA_FUNCTIONS_CREATE_ARGS
98{ 103{
99 DWORD cbSize; 104 DWORD cbSize;
@@ -108,6 +113,19 @@ struct BA_FUNCTIONS_CREATE_RESULTS
108 LPVOID pvBAFunctionsProcContext; 113 LPVOID pvBAFunctionsProcContext;
109}; 114};
110 115
116struct BA_FUNCTIONS_ONTHEMECONTROLLOADING_ARGS
117{
118 DWORD cbSize;
119 LPCWSTR wzName;
120};
121
122struct BA_FUNCTIONS_ONTHEMECONTROLLOADING_RESULTS
123{
124 DWORD cbSize;
125 BOOL fProcessed;
126 WORD wId;
127};
128
111struct BA_FUNCTIONS_ONTHEMELOADED_ARGS 129struct BA_FUNCTIONS_ONTHEMELOADED_ARGS
112{ 130{
113 DWORD cbSize; 131 DWORD cbSize;
diff --git a/src/api/burn/balutil/inc/BalBaseBAFunctions.h b/src/api/burn/balutil/inc/BalBaseBAFunctions.h
index a3054709..c2c8a6dc 100644
--- a/src/api/burn/balutil/inc/BalBaseBAFunctions.h
+++ b/src/api/burn/balutil/inc/BalBaseBAFunctions.h
@@ -841,6 +841,15 @@ public: // IBAFunctions
841 return E_NOTIMPL; 841 return E_NOTIMPL;
842 } 842 }
843 843
844 virtual STDMETHODIMP OnThemeControlLoading(
845 __in LPCWSTR /*wzName*/,
846 __inout BOOL* /*pfProcessed*/,
847 __inout WORD* /*pwId*/
848 )
849 {
850 return S_OK;
851 }
852
844protected: 853protected:
845 CBalBaseBAFunctions( 854 CBalBaseBAFunctions(
846 __in HMODULE hModule, 855 __in HMODULE hModule,
diff --git a/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h b/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h
index 8d1227fc..efe22ddd 100644
--- a/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h
+++ b/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h
@@ -24,6 +24,15 @@ static HRESULT BalBaseBAFunctionsProcWndProc(
24 return pBAFunctions->WndProc(pArgs->pTheme, pArgs->hWnd, pArgs->uMsg, pArgs->wParam, pArgs->lParam, &pResults->lres); 24 return pBAFunctions->WndProc(pArgs->pTheme, pArgs->hWnd, pArgs->uMsg, pArgs->wParam, pArgs->lParam, &pResults->lres);
25} 25}
26 26
27static HRESULT BalBaseBAFunctionsProcOnThemeControlLoading(
28 __in IBAFunctions* pBAFunctions,
29 __in BA_FUNCTIONS_ONTHEMECONTROLLOADING_ARGS* pArgs,
30 __inout BA_FUNCTIONS_ONTHEMECONTROLLOADING_RESULTS* pResults
31 )
32{
33 return pBAFunctions->OnThemeControlLoading(pArgs->wzName, &pResults->fProcessed, &pResults->wId);
34}
35
27/******************************************************************* 36/*******************************************************************
28BalBaseBAFunctionsProc - requires pvContext to be of type IBAFunctions. 37BalBaseBAFunctionsProc - requires pvContext to be of type IBAFunctions.
29Provides a default mapping between the message based BAFunctions interface and 38Provides a default mapping between the message based BAFunctions interface and
@@ -125,6 +134,9 @@ static HRESULT WINAPI BalBaseBAFunctionsProc(
125 case BA_FUNCTIONS_MESSAGE_WNDPROC: 134 case BA_FUNCTIONS_MESSAGE_WNDPROC:
126 hr = BalBaseBAFunctionsProcWndProc(pBAFunctions, reinterpret_cast<BA_FUNCTIONS_WNDPROC_ARGS*>(pvArgs), reinterpret_cast<BA_FUNCTIONS_WNDPROC_RESULTS*>(pvResults)); 135 hr = BalBaseBAFunctionsProcWndProc(pBAFunctions, reinterpret_cast<BA_FUNCTIONS_WNDPROC_ARGS*>(pvArgs), reinterpret_cast<BA_FUNCTIONS_WNDPROC_RESULTS*>(pvResults));
127 break; 136 break;
137 case BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLLOADING:
138 hr = BalBaseBAFunctionsProcOnThemeControlLoading(pBAFunctions, reinterpret_cast<BA_FUNCTIONS_ONTHEMECONTROLLOADING_ARGS*>(pvArgs), reinterpret_cast<BA_FUNCTIONS_ONTHEMECONTROLLOADING_RESULTS*>(pvResults));
139 break;
128 } 140 }
129 } 141 }
130 142
diff --git a/src/api/burn/balutil/inc/IBAFunctions.h b/src/api/burn/balutil/inc/IBAFunctions.h
index 7d8a07fa..d41b7c9b 100644
--- a/src/api/burn/balutil/inc/IBAFunctions.h
+++ b/src/api/burn/balutil/inc/IBAFunctions.h
@@ -31,4 +31,12 @@ DECLARE_INTERFACE_IID_(IBAFunctions, IBootstrapperApplication, "0FB445ED-17BD-49
31 __inout LPVOID pvResults, 31 __inout LPVOID pvResults,
32 __in_opt LPVOID pvContext 32 __in_opt LPVOID pvContext
33 ) = 0; 33 ) = 0;
34
35 // OnThemeControlLoading - Called while creating a control for the theme.
36 //
37 STDMETHOD(OnThemeControlLoading)(
38 __in LPCWSTR wzName,
39 __inout BOOL* pfProcessed,
40 __inout WORD* pwId
41 ) = 0;
34}; 42};
diff --git a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
index 74e0b7d3..8cdd31ce 100644
--- a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
+++ b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
@@ -77,10 +77,15 @@ static LPCWSTR vrgwzPageNames[] = {
77 L"Failure", 77 L"Failure",
78}; 78};
79 79
80// The range [0, 100) is unused to avoid collisions with system ids,
81// the range [100, 0x4000) is unused to avoid collisions with thmutil,
82// the range [0x4000, 0x8000) is unused to avoid collisions with BAFunctions.
83const WORD WIXSTDBA_FIRST_ASSIGN_CONTROL_ID = 0x8000;
84
80enum WIXSTDBA_CONTROL 85enum WIXSTDBA_CONTROL
81{ 86{
82 // Welcome page 87 // Welcome page
83 WIXSTDBA_CONTROL_INSTALL_BUTTON = THEME_FIRST_ASSIGN_CONTROL_ID, 88 WIXSTDBA_CONTROL_INSTALL_BUTTON = WIXSTDBA_FIRST_ASSIGN_CONTROL_ID,
84 WIXSTDBA_CONTROL_EULA_RICHEDIT, 89 WIXSTDBA_CONTROL_EULA_RICHEDIT,
85 WIXSTDBA_CONTROL_EULA_LINK, 90 WIXSTDBA_CONTROL_EULA_LINK,
86 WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX, 91 WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX,
@@ -2833,6 +2838,9 @@ private:
2833 } 2838 }
2834 break; 2839 break;
2835 2840
2841 case WM_THMUTIL_LOADING_CONTROL:
2842 return pBA->OnThemeLoadingControl(reinterpret_cast<THEME_LOADINGCONTROL_ARGS*>(wParam), reinterpret_cast<THEME_LOADINGCONTROL_RESULTS*>(lParam));
2843
2836 case WM_QUERYENDSESSION: 2844 case WM_QUERYENDSESSION:
2837 fCancel = true; 2845 fCancel = true;
2838 pBA->OnSystemShutdown(static_cast<DWORD>(lParam), &fCancel); 2846 pBA->OnSystemShutdown(static_cast<DWORD>(lParam), &fCancel);
@@ -2956,7 +2964,7 @@ private:
2956 BA_FUNCTIONS_ONTHEMELOADED_ARGS themeLoadedArgs = { }; 2964 BA_FUNCTIONS_ONTHEMELOADED_ARGS themeLoadedArgs = { };
2957 BA_FUNCTIONS_ONTHEMELOADED_RESULTS themeLoadedResults = { }; 2965 BA_FUNCTIONS_ONTHEMELOADED_RESULTS themeLoadedResults = { };
2958 2966
2959 hr = ThemeLoadControls(m_pTheme, vrgInitControls, countof(vrgInitControls)); 2967 hr = ThemeLoadControls(m_pTheme);
2960 BalExitOnFailure(hr, "Failed to load theme controls."); 2968 BalExitOnFailure(hr, "Failed to load theme controls.");
2961 2969
2962 C_ASSERT(COUNT_WIXSTDBA_PAGE == countof(vrgwzPageNames)); 2970 C_ASSERT(COUNT_WIXSTDBA_PAGE == countof(vrgwzPageNames));
@@ -3029,6 +3037,57 @@ private:
3029 return SUCCEEDED(hr); 3037 return SUCCEEDED(hr);
3030 } 3038 }
3031 3039
3040 BOOL OnThemeLoadingControl(
3041 __in const THEME_LOADINGCONTROL_ARGS* pArgs,
3042 __in THEME_LOADINGCONTROL_RESULTS* pResults
3043 )
3044 {
3045 HRESULT hr = S_OK;
3046 BOOL fProcessed = FALSE;
3047 BA_FUNCTIONS_ONTHEMECONTROLLOADING_ARGS themeControlLoadingArgs = { };
3048 BA_FUNCTIONS_ONTHEMECONTROLLOADING_RESULTS themeControlLoadingResults = { };
3049
3050 for (DWORD iAssignControl = 0; iAssignControl < countof(vrgInitControls); ++iAssignControl)
3051 {
3052 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pArgs->pThemeControl->sczName, -1, vrgInitControls[iAssignControl].wzName, -1))
3053 {
3054 fProcessed = TRUE;
3055 pResults->wId = vrgInitControls[iAssignControl].wId;
3056 ExitFunction();
3057 }
3058 }
3059
3060 if (m_pfnBAFunctionsProc)
3061 {
3062 themeControlLoadingArgs.cbSize = sizeof(themeControlLoadingArgs);
3063 themeControlLoadingArgs.wzName = pArgs->pThemeControl->sczName;
3064
3065 themeControlLoadingResults.cbSize = sizeof(themeControlLoadingResults);
3066 themeControlLoadingResults.wId = pResults->wId;
3067
3068 hr = m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLLOADING, &themeControlLoadingArgs, &themeControlLoadingResults, m_pvBAFunctionsProcContext);
3069
3070 if (E_NOTIMPL == hr)
3071 {
3072 hr = S_OK;
3073 }
3074 else
3075 {
3076 BalExitOnFailure(hr, "BAFunctions OnThemeControlLoading failed.");
3077
3078 if (themeControlLoadingResults.fProcessed)
3079 {
3080 fProcessed = TRUE;
3081 pResults->wId = themeControlLoadingResults.wId;
3082 }
3083 }
3084 }
3085
3086 LExit:
3087 pResults->hr = hr;
3088 return fProcessed || FAILED(hr);
3089 }
3090
3032 3091
3033 // 3092 //
3034 // OnShowFailure - display the failure page. 3093 // OnShowFailure - display the failure page.
@@ -3857,7 +3916,7 @@ private:
3857 BalExitOnNullWithLastError(pfnBAFunctionsCreate, hr, "Failed to get BAFunctionsCreate entry-point from: %ls", sczBafPath); 3916 BalExitOnNullWithLastError(pfnBAFunctionsCreate, hr, "Failed to get BAFunctionsCreate entry-point from: %ls", sczBafPath);
3858 3917
3859 bafCreateArgs.cbSize = sizeof(bafCreateArgs); 3918 bafCreateArgs.cbSize = sizeof(bafCreateArgs);
3860 bafCreateArgs.qwBAFunctionsAPIVersion = MAKEQWORDVERSION(0, 0, 0, 2); // TODO: need to decide whether to keep this, and if so when to update it. 3919 bafCreateArgs.qwBAFunctionsAPIVersion = MAKEQWORDVERSION(2021, 9, 20, 0);
3861 bafCreateArgs.pBootstrapperCreateArgs = &m_createArgs; 3920 bafCreateArgs.pBootstrapperCreateArgs = &m_createArgs;
3862 3921
3863 bafCreateResults.cbSize = sizeof(bafCreateResults); 3922 bafCreateResults.cbSize = sizeof(bafCreateResults);
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/thmutil.h b/src/libs/dutil/WixToolset.DUtil/inc/thmutil.h
index 6ac3711f..dc554219 100644
--- a/src/libs/dutil/WixToolset.DUtil/inc/thmutil.h
+++ b/src/libs/dutil/WixToolset.DUtil/inc/thmutil.h
@@ -95,6 +95,15 @@ typedef enum THEME_WINDOW_INITIAL_POSITION
95 THEME_WINDOW_INITIAL_POSITION_CENTER_MONITOR_FROM_COORDINATES, 95 THEME_WINDOW_INITIAL_POSITION_CENTER_MONITOR_FROM_COORDINATES,
96} THEME_WINDOW_INITIAL_POSITION; 96} THEME_WINDOW_INITIAL_POSITION;
97 97
98// These messages are sent by thmutil to the parent window created in ThemeCreateParentWindow.
99// thmutil reserves the last values of WM_USER's range.
100typedef enum _WM_THMUTIL
101{
102 // Sent while creating a control.
103 // wparam is THEME_LOADINGCONTROL_ARGS* and lparam is THEME_LOADINGCONTROL_RESULTS*.
104 // Return code is TRUE if it was processed.
105 WM_THMUTIL_LOADING_CONTROL = WM_APP - 1,
106} WM_THMUTIL;
98 107
99struct THEME_COLUMN 108struct THEME_COLUMN
100{ 109{
@@ -171,7 +180,7 @@ struct THEME_ASSIGN_CONTROL_ID
171 LPCWSTR wzName; // name of control to match 180 LPCWSTR wzName; // name of control to match
172}; 181};
173 182
174const DWORD THEME_FIRST_ASSIGN_CONTROL_ID = 1024; // Recommended first control id to be assigned. 183const WORD THEME_FIRST_ASSIGN_CONTROL_ID = 0x4000; // Recommended first control id to be assigned.
175 184
176struct THEME_CONTROL 185struct THEME_CONTROL
177{ 186{
@@ -325,7 +334,7 @@ struct THEME_FONT
325 334
326struct THEME 335struct THEME
327{ 336{
328 WORD wId; 337 WORD wNextControlId;
329 338
330 BOOL fAutoResize; 339 BOOL fAutoResize;
331 BOOL fForceResize; 340 BOOL fForceResize;
@@ -388,6 +397,24 @@ struct THEME
388 LPVOID pvVariableContext; 397 LPVOID pvVariableContext;
389}; 398};
390 399
400typedef struct _THEME_LOADINGCONTROL_ARGS
401{
402 DWORD cbSize;
403 const THEME_CONTROL* pThemeControl;
404} THEME_LOADINGCONTROL_ARGS;
405
406typedef struct _THEME_LOADINGCONTROL_RESULTS
407{
408 DWORD cbSize;
409 HRESULT hr;
410
411 // Used to apply a specific id to the control (usually used for WM_COMMAND).
412 // If assigning an id, it is recommended to start with THEME_FIRST_ASSIGN_CONTROL_ID to avoid collisions with well known ids such as IDOK and IDCANCEL.
413 // The values [100, THEME_FIRST_ASSIGN_CONTROL_ID) are reserved for thmutil.
414 // Due to this value being packed into 16 bits for many system window messages, this is restricted to a WORD.
415 WORD wId;
416} THEME_LOADINGCONTROL_RESULTS;
417
391 418
392/******************************************************************** 419/********************************************************************
393 ThemeInitialize - initialized theme management. 420 ThemeInitialize - initialized theme management.
@@ -472,9 +499,7 @@ HRESULT DAPI ThemeCreateParentWindow(
472 499
473*******************************************************************/ 500*******************************************************************/
474HRESULT DAPI ThemeLoadControls( 501HRESULT DAPI ThemeLoadControls(
475 __in THEME* pTheme, 502 __in THEME* pTheme
476 __in_ecount_opt(cAssignControlIds) const THEME_ASSIGN_CONTROL_ID* rgAssignControlIds,
477 __in DWORD cAssignControlIds
478 ); 503 );
479 504
480/******************************************************************** 505/********************************************************************
diff --git a/src/libs/dutil/WixToolset.DUtil/thmutil.cpp b/src/libs/dutil/WixToolset.DUtil/thmutil.cpp
index 53257d8e..d796bbaf 100644
--- a/src/libs/dutil/WixToolset.DUtil/thmutil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/thmutil.cpp
@@ -39,6 +39,7 @@
39#define LWS_NOPREFIX 0x0004 39#define LWS_NOPREFIX 0x0004
40#endif 40#endif
41 41
42const WORD THEME_FIRST_AUTO_ASSIGN_CONTROL_ID = 100;
42const DWORD THEME_INVALID_ID = 0xFFFFFFFF; 43const DWORD THEME_INVALID_ID = 0xFFFFFFFF;
43const COLORREF THEME_INVISIBLE_COLORREF = 0xFFFFFFFF; 44const COLORREF THEME_INVISIBLE_COLORREF = 0xFFFFFFFF;
44const DWORD GROW_FONT_INSTANCES = 3; 45const DWORD GROW_FONT_INSTANCES = 3;
@@ -272,11 +273,14 @@ static HRESULT FindImageList(
272 __in_z LPCWSTR wzImageListName, 273 __in_z LPCWSTR wzImageListName,
273 __out HIMAGELIST *phImageList 274 __out HIMAGELIST *phImageList
274 ); 275 );
276static HRESULT OnLoadingControl(
277 __in THEME* pTheme,
278 __in const THEME_CONTROL* pControl,
279 __inout WORD* pwId
280 );
275static HRESULT LoadControls( 281static HRESULT LoadControls(
276 __in THEME* pTheme, 282 __in THEME* pTheme,
277 __in_opt THEME_CONTROL* pParentControl, 283 __in_opt THEME_CONTROL* pParentControl
278 __in_ecount_opt(cAssignControlIds) const THEME_ASSIGN_CONTROL_ID* rgAssignControlIds,
279 __in DWORD cAssignControlIds
280 ); 284 );
281static HRESULT ShowControl( 285static HRESULT ShowControl(
282 __in THEME* pTheme, 286 __in THEME* pTheme,
@@ -871,9 +875,7 @@ LExit:
871 875
872 876
873DAPI_(HRESULT) ThemeLoadControls( 877DAPI_(HRESULT) ThemeLoadControls(
874 __in THEME* pTheme, 878 __in THEME* pTheme
875 __in_ecount_opt(cAssignControlIds) const THEME_ASSIGN_CONTROL_ID* rgAssignControlIds,
876 __in DWORD cAssignControlIds
877 ) 879 )
878{ 880{
879 HRESULT hr = S_OK; 881 HRESULT hr = S_OK;
@@ -883,7 +885,7 @@ DAPI_(HRESULT) ThemeLoadControls(
883 ThmExitOnFailure(hr = E_INVALIDSTATE, "ThemeLoadControls called before theme parent window created."); 885 ThmExitOnFailure(hr = E_INVALIDSTATE, "ThemeLoadControls called before theme parent window created.");
884 } 886 }
885 887
886 hr = LoadControls(pTheme, NULL, rgAssignControlIds, cAssignControlIds); 888 hr = LoadControls(pTheme, NULL);
887 889
888LExit: 890LExit:
889 return hr; 891 return hr;
@@ -1844,8 +1846,6 @@ static HRESULT ParseTheme(
1844 __out THEME** ppTheme 1846 __out THEME** ppTheme
1845 ) 1847 )
1846{ 1848{
1847 static WORD wThemeId = 0;
1848
1849 HRESULT hr = S_OK; 1849 HRESULT hr = S_OK;
1850 THEME* pTheme = NULL; 1850 THEME* pTheme = NULL;
1851 IXMLDOMElement *pThemeElement = NULL; 1851 IXMLDOMElement *pThemeElement = NULL;
@@ -1858,8 +1858,8 @@ static HRESULT ParseTheme(
1858 pTheme = static_cast<THEME*>(MemAlloc(sizeof(THEME), TRUE)); 1858 pTheme = static_cast<THEME*>(MemAlloc(sizeof(THEME), TRUE));
1859 ThmExitOnNull(pTheme, hr, E_OUTOFMEMORY, "Failed to allocate memory for theme."); 1859 ThmExitOnNull(pTheme, hr, E_OUTOFMEMORY, "Failed to allocate memory for theme.");
1860 1860
1861 pTheme->wId = ++wThemeId;
1862 pTheme->nDpi = USER_DEFAULT_SCREEN_DPI; 1861 pTheme->nDpi = USER_DEFAULT_SCREEN_DPI;
1862 pTheme->wNextControlId = THEME_FIRST_AUTO_ASSIGN_CONTROL_ID;
1863 1863
1864 // Parse the optional background resource image. 1864 // Parse the optional background resource image.
1865 hr = GetAttributeImageFileOrResource(hModule, wzRelativePath, pThemeElement, &pBitmap); 1865 hr = GetAttributeImageFileOrResource(hModule, wzRelativePath, pThemeElement, &pBitmap);
@@ -5248,7 +5248,7 @@ static BOOL OnButtonClicked(
5248LExit: 5248LExit:
5249 return fHandled; 5249 return fHandled;
5250} 5250}
5251 5251
5252static BOOL OnDpiChanged( 5252static BOOL OnDpiChanged(
5253 __in THEME* pTheme, 5253 __in THEME* pTheme,
5254 __in WPARAM wParam, 5254 __in WPARAM wParam,
@@ -5934,11 +5934,38 @@ static LRESULT CALLBACK StaticOwnerDrawWndProc(
5934 } 5934 }
5935} 5935}
5936 5936
5937static HRESULT OnLoadingControl(
5938 __in THEME* pTheme,
5939 __in const THEME_CONTROL* pControl,
5940 __inout WORD* pwId
5941 )
5942{
5943 HRESULT hr = S_OK;
5944 THEME_LOADINGCONTROL_ARGS loadingControlArgs = { };
5945 THEME_LOADINGCONTROL_RESULTS loadingControlResults = { };
5946
5947 loadingControlArgs.cbSize = sizeof(loadingControlArgs);
5948 loadingControlArgs.pThemeControl = pControl;
5949
5950 loadingControlResults.cbSize = sizeof(loadingControlResults);
5951 loadingControlResults.hr = E_NOTIMPL;
5952 loadingControlResults.wId = *pwId;
5953
5954 if (::SendMessageW(pTheme->hwndParent, WM_THMUTIL_LOADING_CONTROL, reinterpret_cast<WPARAM>(&loadingControlArgs), reinterpret_cast<LPARAM>(&loadingControlResults)))
5955 {
5956 hr = loadingControlResults.hr;
5957 if (SUCCEEDED(hr))
5958 {
5959 *pwId = loadingControlResults.wId;
5960 }
5961 }
5962
5963 return hr;
5964}
5965
5937static HRESULT LoadControls( 5966static HRESULT LoadControls(
5938 __in THEME* pTheme, 5967 __in THEME* pTheme,
5939 __in_opt THEME_CONTROL* pParentControl, 5968 __in_opt THEME_CONTROL* pParentControl
5940 __in_ecount_opt(cAssignControlIds) const THEME_ASSIGN_CONTROL_ID* rgAssignControlIds,
5941 __in DWORD cAssignControlIds
5942 ) 5969 )
5943{ 5970{
5944 HRESULT hr = S_OK; 5971 HRESULT hr = S_OK;
@@ -6101,16 +6128,16 @@ static HRESULT LoadControls(
6101 } 6128 }
6102 ThmExitOnNull(wzWindowClass, hr, E_INVALIDDATA, "Failed to configure control %u because of unknown type: %u", i, pControl->type); 6129 ThmExitOnNull(wzWindowClass, hr, E_INVALIDDATA, "Failed to configure control %u because of unknown type: %u", i, pControl->type);
6103 6130
6104 // Default control ids to the theme id and its index in the control array, unless there 6131 // Default control ids to the next id, unless there is a specific id to assign to a control.
6105 // is a specific id to assign to a named control. 6132 WORD wControlId = THEME_FIRST_AUTO_ASSIGN_CONTROL_ID;
6106 WORD wControlId = MAKEWORD(i, pTheme->wId); 6133 hr = OnLoadingControl(pTheme, pControl, &wControlId);
6107 for (DWORD iAssignControl = 0; pControl->sczName && iAssignControl < cAssignControlIds; ++iAssignControl) 6134 ThmExitOnFailure(hr, "ThmLoadingControl failed.");
6135
6136 // This range is reserved for thmutil. The process will run out of available window handles before reaching the end of the range.
6137 if (THEME_FIRST_AUTO_ASSIGN_CONTROL_ID <= wControlId && THEME_FIRST_ASSIGN_CONTROL_ID > wControlId)
6108 { 6138 {
6109 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pControl->sczName, -1, rgAssignControlIds[iAssignControl].wzName, -1)) 6139 wControlId = pTheme->wNextControlId;
6110 { 6140 pTheme->wNextControlId += 1;
6111 wControlId = rgAssignControlIds[iAssignControl].wId;
6112 break;
6113 }
6114 } 6141 }
6115 6142
6116 pControl->wId = wControlId; 6143 pControl->wId = wControlId;
@@ -6296,7 +6323,7 @@ static HRESULT LoadControls(
6296 6323
6297 if (pControl->cControls) 6324 if (pControl->cControls)
6298 { 6325 {
6299 hr = LoadControls(pTheme, pControl, rgAssignControlIds, cAssignControlIds); 6326 hr = LoadControls(pTheme, pControl);
6300 ThmExitOnFailure(hr, "Failed to load child controls."); 6327 ThmExitOnFailure(hr, "Failed to load child controls.");
6301 } 6328 }
6302 } 6329 }
diff --git a/src/samples/thmviewer/display.cpp b/src/samples/thmviewer/display.cpp
index 52fa3cf8..c0e6c7e1 100644
--- a/src/samples/thmviewer/display.cpp
+++ b/src/samples/thmviewer/display.cpp
@@ -329,7 +329,7 @@ static BOOL DisplayOnCreate(
329{ 329{
330 HRESULT hr = S_OK; 330 HRESULT hr = S_OK;
331 331
332 hr = ThemeLoadControls(pTheme, NULL, 0); 332 hr = ThemeLoadControls(pTheme);
333 ExitOnFailure(hr, "Failed to load theme controls"); 333 ExitOnFailure(hr, "Failed to load theme controls");
334 334
335 // Pre-populate some control types with data. 335 // Pre-populate some control types with data.
diff --git a/src/samples/thmviewer/thmviewer.cpp b/src/samples/thmviewer/thmviewer.cpp
index f83182d3..cffa3851 100644
--- a/src/samples/thmviewer/thmviewer.cpp
+++ b/src/samples/thmviewer/thmviewer.cpp
@@ -14,10 +14,6 @@ enum THMVWR_CONTROL
14 THMVWR_CONTROL_TREE = THEME_FIRST_ASSIGN_CONTROL_ID, 14 THMVWR_CONTROL_TREE = THEME_FIRST_ASSIGN_CONTROL_ID,
15}; 15};
16 16
17static THEME_ASSIGN_CONTROL_ID vrgInitControls[] = {
18 { THMVWR_CONTROL_TREE, L"Tree" },
19};
20
21// Internal functions 17// Internal functions
22 18
23static HRESULT ProcessCommandLine( 19static HRESULT ProcessCommandLine(
@@ -52,6 +48,10 @@ static void OnNewTheme(
52 __in HWND hWnd, 48 __in HWND hWnd,
53 __in HANDLE_THEME* pHandle 49 __in HANDLE_THEME* pHandle
54 ); 50 );
51static BOOL OnThemeLoadingControl(
52 __in const THEME_LOADINGCONTROL_ARGS* pArgs,
53 __in THEME_LOADINGCONTROL_RESULTS* pResults
54 );
55static void CALLBACK ThmviewerTraceError( 55static void CALLBACK ThmviewerTraceError(
56 __in_z LPCSTR szFile, 56 __in_z LPCSTR szFile,
57 __in int iLine, 57 __in int iLine,
@@ -353,7 +353,7 @@ static LRESULT CALLBACK MainWndProc(
353 353
354 case WM_CREATE: 354 case WM_CREATE:
355 { 355 {
356 HRESULT hr = ThemeLoadControls(vpTheme, vrgInitControls, countof(vrgInitControls)); 356 HRESULT hr = ThemeLoadControls(vpTheme);
357 if (FAILED(hr)) 357 if (FAILED(hr))
358 { 358 {
359 return -1; 359 return -1;
@@ -400,6 +400,9 @@ static LRESULT CALLBACK MainWndProc(
400 } 400 }
401 } 401 }
402 break; 402 break;
403
404 case WM_THMUTIL_LOADING_CONTROL:
405 return OnThemeLoadingControl(reinterpret_cast<THEME_LOADINGCONTROL_ARGS*>(wParam), reinterpret_cast<THEME_LOADINGCONTROL_RESULTS*>(lParam));
403 } 406 }
404 407
405 return ThemeDefWindowProc(vpTheme, hWnd, uMsg, wParam, lParam); 408 return ThemeDefWindowProc(vpTheme, hWnd, uMsg, wParam, lParam);
@@ -541,3 +544,17 @@ static void OnNewTheme(
541 ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_SELECTITEM, TVGN_CARET, reinterpret_cast<LPARAM>(htiSelected)); 544 ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_SELECTITEM, TVGN_CARET, reinterpret_cast<LPARAM>(htiSelected));
542 } 545 }
543} 546}
547
548static BOOL OnThemeLoadingControl(
549 __in const THEME_LOADINGCONTROL_ARGS* pArgs,
550 __in THEME_LOADINGCONTROL_RESULTS* pResults
551 )
552{
553 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pArgs->pThemeControl->sczName, -1, L"Tree", -1))
554 {
555 pResults->wId = THMVWR_CONTROL_TREE;
556 }
557
558 pResults->hr = S_OK;
559 return TRUE;
560}
diff --git a/src/test/burn/TestData/Manual/BafThmutilTesting/BafThmUtilTesting.cpp b/src/test/burn/TestData/Manual/BafThmutilTesting/BafThmUtilTesting.cpp
index 8b49cab6..b35b4e02 100644
--- a/src/test/burn/TestData/Manual/BafThmutilTesting/BafThmUtilTesting.cpp
+++ b/src/test/burn/TestData/Manual/BafThmutilTesting/BafThmUtilTesting.cpp
@@ -6,6 +6,11 @@
6 6
7static const LPCWSTR BAFTHMUTILTESTING_WINDOW_CLASS = L"BafThmUtilTesting"; 7static const LPCWSTR BAFTHMUTILTESTING_WINDOW_CLASS = L"BafThmUtilTesting";
8 8
9enum BAF_CONTROL
10{
11 BAF_CONTROL_INSTALL_TEST_BUTTON = BAFUNCTIONS_FIRST_ASSIGN_CONTROL_ID,
12};
13
9enum BAFTHMUTILTESTING_CONTROL 14enum BAFTHMUTILTESTING_CONTROL
10{ 15{
11 BAFTHMUTILTESTING_CONTROL_LISTVIEW_TOP_LEFT = THEME_FIRST_ASSIGN_CONTROL_ID, 16 BAFTHMUTILTESTING_CONTROL_LISTVIEW_TOP_LEFT = THEME_FIRST_ASSIGN_CONTROL_ID,
@@ -59,24 +64,41 @@ public: // IBAFunctions
59 __inout LRESULT* plRes 64 __inout LRESULT* plRes
60 ) 65 )
61 { 66 {
62 HRESULT hr = S_OK;
63
64 __super::WndProc(pTheme, hWnd, uMsg, wParam, lParam, plRes);
65
66 // Show our window when any button is clicked.
67 switch (uMsg) 67 switch (uMsg)
68 { 68 {
69 case WM_COMMAND: 69 case WM_COMMAND:
70 switch (HIWORD(wParam)) 70 switch (HIWORD(wParam))
71 { 71 {
72 case BN_CLICKED: 72 case BN_CLICKED:
73 OnShowTheme(); 73 switch (LOWORD(wParam))
74 {
75 case BAF_CONTROL_INSTALL_TEST_BUTTON:
76 OnShowTheme();
77 *plRes = 0;
78 return S_OK;
79 }
80
74 break; 81 break;
75 } 82 }
76 break; 83 break;
77 } 84 }
78 85
79 return hr; 86 return __super::WndProc(pTheme, hWnd, uMsg, wParam, lParam, plRes);
87 }
88
89 virtual STDMETHODIMP OnThemeControlLoading(
90 __in LPCWSTR wzName,
91 __inout BOOL* pfProcessed,
92 __inout WORD* pwId
93 )
94 {
95 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzName, -1, L"InstallTestButton", -1))
96 {
97 *pfProcessed = TRUE;
98 *pwId = BAF_CONTROL_INSTALL_TEST_BUTTON;
99 }
100
101 return S_OK;
80 } 102 }
81 103
82private: 104private:
@@ -229,6 +251,9 @@ private:
229 } 251 }
230 break; 252 break;
231 253
254 case WM_THMUTIL_LOADING_CONTROL:
255 return pBaf->OnThemeLoadingControl(reinterpret_cast<THEME_LOADINGCONTROL_ARGS*>(wParam), reinterpret_cast<THEME_LOADINGCONTROL_RESULTS*>(lParam));
256
232 case WM_TIMER: 257 case WM_TIMER:
233 if (!lParam && pBaf) 258 if (!lParam && pBaf)
234 { 259 {
@@ -255,7 +280,7 @@ private:
255 HWND hwndBottomLeft = NULL; 280 HWND hwndBottomLeft = NULL;
256 HWND hwndBottomRight = NULL; 281 HWND hwndBottomRight = NULL;
257 282
258 hr = ThemeLoadControls(m_pBafTheme, vrgInitControls, countof(vrgInitControls)); 283 hr = ThemeLoadControls(m_pBafTheme);
259 BalExitOnFailure(hr, "Failed to load theme controls."); 284 BalExitOnFailure(hr, "Failed to load theme controls.");
260 285
261 hwndTopLeft = ::GetDlgItem(m_pBafTheme->hwndParent, BAFTHMUTILTESTING_CONTROL_LISTVIEW_TOP_LEFT); 286 hwndTopLeft = ::GetDlgItem(m_pBafTheme->hwndParent, BAFTHMUTILTESTING_CONTROL_LISTVIEW_TOP_LEFT);
@@ -333,6 +358,24 @@ private:
333 return SUCCEEDED(hr); 358 return SUCCEEDED(hr);
334 } 359 }
335 360
361 BOOL OnThemeLoadingControl(
362 __in const THEME_LOADINGCONTROL_ARGS* pArgs,
363 __in THEME_LOADINGCONTROL_RESULTS* pResults
364 )
365 {
366 for (DWORD iAssignControl = 0; iAssignControl < countof(vrgInitControls); ++iAssignControl)
367 {
368 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pArgs->pThemeControl->sczName, -1, vrgInitControls[iAssignControl].wzName, -1))
369 {
370 pResults->wId = vrgInitControls[iAssignControl].wId;
371 break;
372 }
373 }
374
375 pResults->hr = S_OK;
376 return TRUE;
377 }
378
336 void UpdateProgressBarProgress() 379 void UpdateProgressBarProgress()
337 { 380 {
338 static DWORD dwProgress = 0; 381 static DWORD dwProgress = 0;
diff --git a/src/test/burn/TestData/Manual/BundleA/BundleA.wixproj b/src/test/burn/TestData/Manual/BundleA/BundleA.wixproj
index dcfd3b7e..907b85c9 100644
--- a/src/test/burn/TestData/Manual/BundleA/BundleA.wixproj
+++ b/src/test/burn/TestData/Manual/BundleA/BundleA.wixproj
@@ -2,7 +2,7 @@
2<Project Sdk="WixToolset.Sdk"> 2<Project Sdk="WixToolset.Sdk">
3 <PropertyGroup> 3 <PropertyGroup>
4 <OutputType>Bundle</OutputType> 4 <OutputType>Bundle</OutputType>
5 <BA>hyperlinkLicense</BA> 5 <BA>customHyperlinkLicense</BA>
6 <UpgradeCode>{98ACBCF6-B54A-46AF-8990-DFB8795B965B}</UpgradeCode> 6 <UpgradeCode>{98ACBCF6-B54A-46AF-8990-DFB8795B965B}</UpgradeCode>
7 </PropertyGroup> 7 </PropertyGroup>
8 <ItemGroup> 8 <ItemGroup>
diff --git a/src/test/burn/TestData/Manual/BundleA/BundleA.wxs b/src/test/burn/TestData/Manual/BundleA/BundleA.wxs
index 1706f4e8..20706b6a 100644
--- a/src/test/burn/TestData/Manual/BundleA/BundleA.wxs
+++ b/src/test/burn/TestData/Manual/BundleA/BundleA.wxs
@@ -3,7 +3,8 @@
3 3
4<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal"> 4<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
5 <Fragment> 5 <Fragment>
6 <BootstrapperApplication> 6 <BootstrapperApplication Id="customHyperlinkLicense">
7 <bal:WixStandardBootstrapperApplication LicenseUrl="" Theme="hyperlinkLicense" ThemeFile="CustomHyperlinkTheme.xml" />
7 <Payload SourceFile="$(var.BafThmUtilTesting.TargetPath)" bal:BAFunctions="yes" /> 8 <Payload SourceFile="$(var.BafThmUtilTesting.TargetPath)" bal:BAFunctions="yes" />
8 </BootstrapperApplication> 9 </BootstrapperApplication>
9 <PackageGroup Id="BundlePackages"> 10 <PackageGroup Id="BundlePackages">
diff --git a/src/test/burn/TestData/Manual/BundleA/CustomHyperlinkTheme.xml b/src/test/burn/TestData/Manual/BundleA/CustomHyperlinkTheme.xml
new file mode 100644
index 00000000..b8157193
--- /dev/null
+++ b/src/test/burn/TestData/Manual/BundleA/CustomHyperlinkTheme.xml
@@ -0,0 +1,107 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4
5<Theme xmlns="http://wixtoolset.org/schemas/v4/thmutil">
6 <Font Id="0" Height="-12" Weight="500" Foreground="windowtext" Background="window">Segoe UI</Font>
7 <Font Id="1" Height="-24" Weight="500" Foreground="windowtext">Segoe UI</Font>
8 <Font Id="2" Height="-22" Weight="500" Foreground="graytext">Segoe UI</Font>
9 <Font Id="3" Height="-12" Weight="500" Foreground="windowtext" Background="window">Segoe UI</Font>
10
11 <Window Width="485" Height="300" HexStyle="100a0000" FontId="0" Caption="#(loc.Caption)">
12 <ImageControl X="11" Y="11" Width="64" Height="64" ImageFile="logo.png" Visible="yes"/>
13 <Label X="80" Y="11" Width="-11" Height="64" FontId="1" Visible="yes" DisablePrefix="yes">#(loc.Title)</Label>
14
15 <Page Name="Help">
16 <Label X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.HelpHeader)</Label>
17 <Label X="11" Y="112" Width="-11" Height="-35" FontId="3" DisablePrefix="yes">#(loc.HelpText)</Label>
18 <Button Name="HelpCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
19 <Text>#(loc.HelpCloseButton)</Text>
20 <CloseWindowAction />
21 </Button>
22 </Page>
23 <Page Name="Install">
24 <Hypertext Name="EulaHyperlink" X="11" Y="121" Width="-11" Height="51" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallLicenseLinkText)</Hypertext>
25 <Checkbox Name="EulaAcceptCheckbox" X="-11" Y="-41" Width="260" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallAcceptCheckbox)</Checkbox>
26 <Button Name="InstallTestButton" X="-251" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">Test</Button>
27 <Button Name="OptionsButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" VisibleCondition="NOT WixStdBASuppressOptionsUI">
28 <Text>#(loc.InstallOptionsButton)</Text>
29 <ChangePageAction Page="Options" />
30 </Button>
31 <Button Name="InstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallInstallButton)</Button>
32 <Button Name="InstallCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
33 <Text>#(loc.InstallCancelButton)</Text>
34 <CloseWindowAction />
35 </Button>
36 </Page>
37 <Page Name="Options">
38 <Label X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.OptionsHeader)</Label>
39 <Label X="11" Y="121" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OptionsLocationLabel)</Label>
40 <Editbox Name="InstallFolder" X="11" Y="143" Width="-91" Height="21" TabStop="yes" FontId="3" FileSystemAutoComplete="yes" />
41 <Button Name="BrowseButton" X="-11" Y="142" Width="75" Height="23" TabStop="yes" FontId="3">
42 <Text>#(loc.OptionsBrowseButton)</Text>
43 <BrowseDirectoryAction VariableName="InstallFolder" />
44 </Button>
45 <Button Name="OptionsOkButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
46 <Text>#(loc.OptionsOkButton)</Text>
47 <ChangePageAction Page="Install" />
48 </Button>
49 <Button Name="OptionsCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
50 <Text>#(loc.OptionsCancelButton)</Text>
51 <ChangePageAction Page="Install" Cancel="yes" />
52 </Button>
53 </Page>
54 <Page Name="Progress">
55 <Label X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ProgressHeader)</Label>
56 <Label X="11" Y="121" Width="70" Height="17" FontId="3" DisablePrefix="yes">#(loc.ProgressLabel)</Label>
57 <Label Name="OverallProgressPackageText" X="85" Y="121" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OverallProgressPackageText)</Label>
58 <Progressbar Name="OverallCalculatedProgressbar" X="11" Y="143" Width="-11" Height="15" />
59 <Button Name="ProgressCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ProgressCancelButton)</Button>
60 </Page>
61 <Page Name="Modify">
62 <Label X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ModifyHeader)</Label>
63 <Button Name="RepairButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.ModifyRepairButton)</Button>
64 <Button Name="UninstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyUninstallButton)</Button>
65 <Button Name="ModifyCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
66 <Text>#(loc.ModifyCancelButton)</Text>
67 <CloseWindowAction />
68 </Button>
69 </Page>
70 <Page Name="Success">
71 <Label X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">
72 <Text>#(loc.SuccessHeader)</Text>
73 <Text Condition="WixBundleAction = 2">#(loc.SuccessLayoutHeader)</Text>
74 <Text Condition="WixBundleAction = 3">#(loc.SuccessUninstallHeader)</Text>
75 <Text Condition="WixBundleAction = 5">#(loc.SuccessInstallHeader)</Text>
76 <Text Condition="WixBundleAction = 7">#(loc.SuccessRepairHeader)</Text>
77 </Label>
78 <Button Name="LaunchButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessLaunchButton)</Button>
79 <Label X="-11" Y="-51" Width="400" Height="34" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBARestartRequired">
80 <Text>#(loc.SuccessRestartText)</Text>
81 <Text Condition="WixBundleAction = 3">#(loc.SuccessUninstallRestartText)</Text>
82 </Label>
83 <Button Name="SuccessRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessRestartButton)</Button>
84 <Button Name="SuccessCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
85 <Text>#(loc.SuccessCloseButton)</Text>
86 <CloseWindowAction />
87 </Button>
88 </Page>
89 <Page Name="Failure">
90 <Label X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">
91 <Text>#(loc.FailureHeader)</Text>
92 <Text Condition="WixBundleAction = 2">#(loc.FailureLayoutHeader)</Text>
93 <Text Condition="WixBundleAction = 3">#(loc.FailureUninstallHeader)</Text>
94 <Text Condition="WixBundleAction = 5">#(loc.FailureInstallHeader)</Text>
95 <Text Condition="WixBundleAction = 7">#(loc.FailureRepairHeader)</Text>
96 </Label>
97 <Hypertext Name="FailureLogFileLink" X="11" Y="121" Width="-11" Height="42" FontId="3" TabStop="yes" HideWhenDisabled="yes">#(loc.FailureHyperlinkLogText)</Hypertext>
98 <Hypertext Name="FailureMessageText" X="22" Y="163" Width="-11" Height="51" FontId="3" TabStop="yes" HideWhenDisabled="yes" />
99 <Label X="-11" Y="-51" Width="400" Height="34" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBARestartRequired">#(loc.FailureRestartText)</Label>
100 <Button Name="FailureRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FailureRestartButton)</Button>
101 <Button Name="FailureCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
102 <Text>#(loc.FailureCloseButton)</Text>
103 <CloseWindowAction />
104 </Button>
105 </Page>
106 </Window>
107</Theme>