aboutsummaryrefslogtreecommitdiff
path: root/src/wixstdba/WixStandardBootstrapperApplication.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/wixstdba/WixStandardBootstrapperApplication.cpp3849
1 files changed, 3849 insertions, 0 deletions
diff --git a/src/wixstdba/WixStandardBootstrapperApplication.cpp b/src/wixstdba/WixStandardBootstrapperApplication.cpp
new file mode 100644
index 00000000..6d2fd3e2
--- /dev/null
+++ b/src/wixstdba/WixStandardBootstrapperApplication.cpp
@@ -0,0 +1,3849 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3#include "precomp.h"
4#include "BalBaseBootstrapperApplicationProc.h"
5#include "BalBaseBootstrapperApplication.h"
6
7static const LPCWSTR WIXBUNDLE_VARIABLE_ELEVATED = L"WixBundleElevated";
8
9static const LPCWSTR WIXSTDBA_WINDOW_CLASS = L"WixStdBA";
10
11static const LPCWSTR WIXSTDBA_VARIABLE_INSTALL_FOLDER = L"InstallFolder";
12static const LPCWSTR WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH = L"LaunchTarget";
13static const LPCWSTR WIXSTDBA_VARIABLE_LAUNCH_TARGET_ELEVATED_ID = L"LaunchTargetElevatedId";
14static const LPCWSTR WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS = L"LaunchArguments";
15static const LPCWSTR WIXSTDBA_VARIABLE_LAUNCH_HIDDEN = L"LaunchHidden";
16static const LPCWSTR WIXSTDBA_VARIABLE_LAUNCH_WORK_FOLDER = L"LaunchWorkingFolder";
17
18static const DWORD WIXSTDBA_ACQUIRE_PERCENTAGE = 30;
19
20static const LPCWSTR WIXSTDBA_VARIABLE_BUNDLE_FILE_VERSION = L"WixBundleFileVersion";
21static const LPCWSTR WIXSTDBA_VARIABLE_LANGUAGE_ID = L"WixStdBALanguageId";
22static const LPCWSTR WIXSTDBA_VARIABLE_RESTART_REQUIRED = L"WixStdBARestartRequired";
23static const LPCWSTR WIXSTDBA_VARIABLE_SHOW_VERSION = L"WixStdBAShowVersion";
24static const LPCWSTR WIXSTDBA_VARIABLE_SUPPRESS_OPTIONS_UI = L"WixStdBASuppressOptionsUI";
25
26enum WIXSTDBA_STATE
27{
28 WIXSTDBA_STATE_INITIALIZING,
29 WIXSTDBA_STATE_INITIALIZED,
30 WIXSTDBA_STATE_HELP,
31 WIXSTDBA_STATE_DETECTING,
32 WIXSTDBA_STATE_DETECTED,
33 WIXSTDBA_STATE_PLANNING,
34 WIXSTDBA_STATE_PLANNED,
35 WIXSTDBA_STATE_APPLYING,
36 WIXSTDBA_STATE_CACHING,
37 WIXSTDBA_STATE_CACHED,
38 WIXSTDBA_STATE_EXECUTING,
39 WIXSTDBA_STATE_EXECUTED,
40 WIXSTDBA_STATE_APPLIED,
41 WIXSTDBA_STATE_FAILED,
42};
43
44enum WM_WIXSTDBA
45{
46 WM_WIXSTDBA_SHOW_HELP = WM_APP + 100,
47 WM_WIXSTDBA_DETECT_PACKAGES,
48 WM_WIXSTDBA_PLAN_PACKAGES,
49 WM_WIXSTDBA_APPLY_PACKAGES,
50 WM_WIXSTDBA_CHANGE_STATE,
51 WM_WIXSTDBA_SHOW_FAILURE,
52};
53
54// This enum must be kept in the same order as the vrgwzPageNames array.
55enum WIXSTDBA_PAGE
56{
57 WIXSTDBA_PAGE_LOADING,
58 WIXSTDBA_PAGE_HELP,
59 WIXSTDBA_PAGE_INSTALL,
60 WIXSTDBA_PAGE_MODIFY,
61 WIXSTDBA_PAGE_PROGRESS,
62 WIXSTDBA_PAGE_PROGRESS_PASSIVE,
63 WIXSTDBA_PAGE_SUCCESS,
64 WIXSTDBA_PAGE_FAILURE,
65 COUNT_WIXSTDBA_PAGE,
66};
67
68// This array must be kept in the same order as the WIXSTDBA_PAGE enum.
69static LPCWSTR vrgwzPageNames[] = {
70 L"Loading",
71 L"Help",
72 L"Install",
73 L"Modify",
74 L"Progress",
75 L"ProgressPassive",
76 L"Success",
77 L"Failure",
78};
79
80enum WIXSTDBA_CONTROL
81{
82 // Welcome page
83 WIXSTDBA_CONTROL_INSTALL_BUTTON = THEME_FIRST_ASSIGN_CONTROL_ID,
84 WIXSTDBA_CONTROL_EULA_RICHEDIT,
85 WIXSTDBA_CONTROL_EULA_LINK,
86 WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX,
87
88 // Modify page
89 WIXSTDBA_CONTROL_REPAIR_BUTTON,
90 WIXSTDBA_CONTROL_UNINSTALL_BUTTON,
91
92 // Progress page
93 WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT,
94 WIXSTDBA_CONTROL_CACHE_PROGRESS_BAR,
95 WIXSTDBA_CONTROL_CACHE_PROGRESS_TEXT,
96
97 WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT,
98 WIXSTDBA_CONTROL_EXECUTE_PROGRESS_BAR,
99 WIXSTDBA_CONTROL_EXECUTE_PROGRESS_TEXT,
100 WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT,
101
102 WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT,
103 WIXSTDBA_CONTROL_OVERALL_PROGRESS_BAR,
104 WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR,
105 WIXSTDBA_CONTROL_OVERALL_PROGRESS_TEXT,
106
107 WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON,
108
109 // Success page
110 WIXSTDBA_CONTROL_LAUNCH_BUTTON,
111 WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON,
112
113 // Failure page
114 WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK,
115 WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT,
116 WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON,
117};
118
119static THEME_ASSIGN_CONTROL_ID vrgInitControls[] = {
120 { WIXSTDBA_CONTROL_INSTALL_BUTTON, L"InstallButton" },
121 { WIXSTDBA_CONTROL_EULA_RICHEDIT, L"EulaRichedit" },
122 { WIXSTDBA_CONTROL_EULA_LINK, L"EulaHyperlink" },
123 { WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX, L"EulaAcceptCheckbox" },
124
125 { WIXSTDBA_CONTROL_REPAIR_BUTTON, L"RepairButton" },
126 { WIXSTDBA_CONTROL_UNINSTALL_BUTTON, L"UninstallButton" },
127
128 { WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, L"CacheProgressPackageText" },
129 { WIXSTDBA_CONTROL_CACHE_PROGRESS_BAR, L"CacheProgressbar" },
130 { WIXSTDBA_CONTROL_CACHE_PROGRESS_TEXT, L"CacheProgressText" },
131 { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, L"ExecuteProgressPackageText" },
132 { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_BAR, L"ExecuteProgressbar" },
133 { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_TEXT, L"ExecuteProgressText" },
134 { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, L"ExecuteProgressActionDataText"},
135 { WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, L"OverallProgressPackageText" },
136 { WIXSTDBA_CONTROL_OVERALL_PROGRESS_BAR, L"OverallProgressbar" },
137 { WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, L"OverallCalculatedProgressbar" },
138 { WIXSTDBA_CONTROL_OVERALL_PROGRESS_TEXT, L"OverallProgressText" },
139 { WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, L"ProgressCancelButton" },
140
141 { WIXSTDBA_CONTROL_LAUNCH_BUTTON, L"LaunchButton" },
142 { WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON, L"SuccessRestartButton" },
143
144 { WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK, L"FailureLogFileLink" },
145 { WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, L"FailureMessageText" },
146 { WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON, L"FailureRestartButton" },
147};
148
149typedef struct _WIXSTDBA_PREREQ_PACKAGE
150{
151 LPWSTR sczPackageId;
152 BOOL fWasAlreadyInstalled;
153 BOOL fPlannedToBeInstalled;
154 BOOL fSuccessfullyInstalled;
155} WIXSTDBA_PREREQ_PACKAGE;
156
157
158static HRESULT DAPI EvaluateVariableConditionCallback(
159 __in_z LPCWSTR wzCondition,
160 __out BOOL* pf,
161 __in_opt LPVOID pvContext
162 );
163static HRESULT DAPI FormatVariableStringCallback(
164 __in_z LPCWSTR wzFormat,
165 __inout LPWSTR* psczOut,
166 __in_opt LPVOID pvContext
167 );
168static HRESULT DAPI GetVariableNumericCallback(
169 __in_z LPCWSTR wzVariable,
170 __out LONGLONG* pllValue,
171 __in_opt LPVOID pvContext
172 );
173static HRESULT DAPI SetVariableNumericCallback(
174 __in_z LPCWSTR wzVariable,
175 __in LONGLONG llValue,
176 __in_opt LPVOID pvContext
177 );
178static HRESULT DAPI GetVariableStringCallback(
179 __in_z LPCWSTR wzVariable,
180 __inout LPWSTR* psczValue,
181 __in_opt LPVOID pvContext
182 );
183static HRESULT DAPI SetVariableStringCallback(
184 __in_z LPCWSTR wzVariable,
185 __in_z_opt LPCWSTR wzValue,
186 __in_opt LPVOID pvContext
187 );
188static LPCSTR LoggingRequestStateToString(
189 __in BOOTSTRAPPER_REQUEST_STATE requestState
190 );
191static LPCSTR LoggingMsiFeatureStateToString(
192 __in BOOTSTRAPPER_FEATURE_STATE featureState
193 );
194
195
196class CWixStandardBootstrapperApplication : public CBalBaseBootstrapperApplication
197{
198public: // IBootstrapperApplication
199 virtual STDMETHODIMP OnStartup()
200 {
201 HRESULT hr = S_OK;
202 DWORD dwUIThreadId = 0;
203
204 // create UI thread
205 m_hUiThread = ::CreateThread(NULL, 0, UiThreadProc, this, 0, &dwUIThreadId);
206 if (!m_hUiThread)
207 {
208 ExitWithLastError(hr, "Failed to create UI thread.");
209 }
210
211 LExit:
212 return hr;
213 }
214
215
216 virtual STDMETHODIMP OnShutdown(
217 __inout BOOTSTRAPPER_SHUTDOWN_ACTION* pAction
218 )
219 {
220 HRESULT hr = S_OK;
221
222 // wait for UI thread to terminate
223 if (m_hUiThread)
224 {
225 ::WaitForSingleObject(m_hUiThread, INFINITE);
226 ReleaseHandle(m_hUiThread);
227 }
228
229 // If a restart was required.
230 if (m_fRestartRequired)
231 {
232 if (m_fAllowRestart)
233 {
234 *pAction = BOOTSTRAPPER_SHUTDOWN_ACTION_RESTART;
235 }
236
237 if (m_fPrereq)
238 {
239 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, m_fAllowRestart ? "The prerequisites scheduled a restart. The bootstrapper application will be reloaded after the computer is restarted."
240 : "A restart is required by the prerequisites but the user delayed it. The bootstrapper application will be reloaded after the computer is restarted.");
241 }
242 }
243 else if (m_fPrereqInstalled)
244 {
245 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were successfully installed. The bootstrapper application will be reloaded.");
246 *pAction = BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER;
247 }
248 else if (m_fPrereqAlreadyInstalled)
249 {
250 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were already installed. The bootstrapper application will not be reloaded to prevent an infinite loop.");
251 }
252 else if (m_fPrereq)
253 {
254 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were not successfully installed, error: 0x%x. The bootstrapper application will be not reloaded.", m_hrFinal);
255 }
256
257 return hr;
258 }
259
260
261 virtual STDMETHODIMP OnDetectRelatedBundle(
262 __in LPCWSTR wzBundleId,
263 __in BOOTSTRAPPER_RELATION_TYPE relationType,
264 __in LPCWSTR wzBundleTag,
265 __in BOOL fPerMachine,
266 __in DWORD64 dw64Version,
267 __in BOOTSTRAPPER_RELATED_OPERATION operation,
268 __inout BOOL* pfCancel
269 )
270 {
271 BalInfoAddRelatedBundleAsPackage(&m_Bundle.packages, wzBundleId, relationType, fPerMachine);
272
273 // If we're not doing a prerequisite install, remember when our bundle would cause a downgrade.
274 if (!m_fPrereq && BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE == operation)
275 {
276 m_fDowngrading = TRUE;
277 }
278
279 return CBalBaseBootstrapperApplication::OnDetectRelatedBundle(wzBundleId, relationType, wzBundleTag, fPerMachine, dw64Version, operation, pfCancel);
280 }
281
282
283 virtual STDMETHODIMP OnDetectPackageComplete(
284 __in LPCWSTR wzPackageId,
285 __in HRESULT /*hrStatus*/,
286 __in BOOTSTRAPPER_PACKAGE_STATE state
287 )
288 {
289 WIXSTDBA_PREREQ_PACKAGE* pPrereqPackage = NULL;
290 BAL_INFO_PACKAGE* pPackage = NULL;
291 HRESULT hr = GetPrereqPackage(wzPackageId, &pPrereqPackage, &pPackage);
292 if (SUCCEEDED(hr) && BOOTSTRAPPER_PACKAGE_STATE_PRESENT == state)
293 {
294 // If the prerequisite package is already installed, remember that.
295 pPrereqPackage->fWasAlreadyInstalled = TRUE;
296 }
297
298 return S_OK;
299 }
300
301
302 virtual STDMETHODIMP OnDetectComplete(
303 __in HRESULT hrStatus
304 )
305 {
306 HRESULT hr = S_OK;
307
308 if (SUCCEEDED(hrStatus))
309 {
310 hrStatus = EvaluateConditions();
311
312 if (m_fPrereq)
313 {
314 m_fPrereqAlreadyInstalled = TRUE;
315
316 // At this point we have to assume that all prerequisite packages need to be installed, so set to false if any of them aren't installed.
317 for (DWORD i = 0; i < m_cPrereqPackages; ++i)
318 {
319 if (m_rgPrereqPackages[i].sczPackageId && !m_rgPrereqPackages[i].fWasAlreadyInstalled)
320 {
321 m_fPrereqAlreadyInstalled = FALSE;
322 break;
323 }
324 }
325 }
326 }
327
328 SetState(WIXSTDBA_STATE_DETECTED, hrStatus);
329
330 if (BOOTSTRAPPER_ACTION_CACHE == m_plannedAction)
331 {
332 if (m_fSupportCacheOnly)
333 {
334 // Doesn't make sense to prompt the user if cache only is requested.
335 if (BOOTSTRAPPER_DISPLAY_PASSIVE < m_command.display)
336 {
337 m_command.display = BOOTSTRAPPER_DISPLAY_PASSIVE;
338 }
339
340 m_command.action = BOOTSTRAPPER_ACTION_CACHE;
341 }
342 else
343 {
344 BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Ignoring attempt to only cache a bundle that does not explicitly support it.");
345 }
346 }
347
348 // If we're not interacting with the user or we're doing a layout or we're just after a force restart
349 // then automatically start planning.
350 if (BOOTSTRAPPER_DISPLAY_FULL > m_command.display || BOOTSTRAPPER_ACTION_LAYOUT == m_command.action || BOOTSTRAPPER_RESUME_TYPE_REBOOT == m_command.resumeType)
351 {
352 if (SUCCEEDED(hrStatus))
353 {
354 ::PostMessageW(m_hWnd, WM_WIXSTDBA_PLAN_PACKAGES, 0, m_command.action);
355 }
356 }
357
358 return hr;
359 }
360
361
362 virtual STDMETHODIMP OnPlanRelatedBundle(
363 __in_z LPCWSTR wzBundleId,
364 __in BOOTSTRAPPER_REQUEST_STATE recommendedState,
365 __inout_z BOOTSTRAPPER_REQUEST_STATE* pRequestedState,
366 __inout BOOL* pfCancel
367 )
368 {
369 // If we're only installing prerequisites, do not touch related bundles.
370 if (m_fPrereq)
371 {
372 *pRequestedState = BOOTSTRAPPER_REQUEST_STATE_NONE;
373 }
374
375 return CBalBaseBootstrapperApplication::OnPlanRelatedBundle(wzBundleId, recommendedState, pRequestedState, pfCancel);
376 }
377
378
379 virtual STDMETHODIMP OnPlanPackageBegin(
380 __in_z LPCWSTR wzPackageId,
381 __in BOOTSTRAPPER_REQUEST_STATE recommendedState,
382 __inout BOOTSTRAPPER_REQUEST_STATE *pRequestState,
383 __inout BOOL* pfCancel
384 )
385 {
386 HRESULT hr = S_OK;
387 WIXSTDBA_PREREQ_PACKAGE* pPrereqPackage = NULL;
388 BAL_INFO_PACKAGE* pPackage = NULL;
389
390 // If we're planning to install a prerequisite, install it. The prerequisite needs to be installed
391 // in all cases (even uninstall!) so the BA can load next.
392 if (m_fPrereq)
393 {
394 // Only install prerequisite packages, and check the InstallCondition on prerequisite support packages.
395 BOOL fInstall = FALSE;
396 hr = GetPrereqPackage(wzPackageId, &pPrereqPackage, &pPackage);
397 if (SUCCEEDED(hr) && pPackage)
398 {
399 if (pPackage->sczInstallCondition && *pPackage->sczInstallCondition)
400 {
401 hr = BalEvaluateCondition(pPackage->sczInstallCondition, &fInstall);
402 if (FAILED(hr))
403 {
404 fInstall = FALSE;
405 }
406 }
407 else
408 {
409 // If the InstallCondition is missing, then it should always be installed.
410 fInstall = TRUE;
411 }
412
413 pPrereqPackage->fPlannedToBeInstalled = fInstall;
414 }
415
416 if (fInstall)
417 {
418 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT;
419 }
420 else
421 {
422 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;
423 }
424 }
425 else if (m_sczAfterForcedRestartPackage) // after force restart, skip packages until after the package that caused the restart.
426 {
427 // After restart we need to finish the dependency registration for our package so allow the package
428 // to go present.
429 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, m_sczAfterForcedRestartPackage, -1))
430 {
431 // Do not allow a repair because that could put us in a perpetual restart loop.
432 if (BOOTSTRAPPER_REQUEST_STATE_REPAIR == *pRequestState)
433 {
434 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT;
435 }
436
437 ReleaseNullStr(m_sczAfterForcedRestartPackage); // no more skipping now.
438 }
439 else // not the matching package, so skip it.
440 {
441 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Skipping package: %ls, after restart because it was applied before the restart.", wzPackageId);
442
443 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;
444 }
445 }
446
447 return CBalBaseBootstrapperApplication::OnPlanPackageBegin(wzPackageId, recommendedState, pRequestState, pfCancel);
448 }
449
450
451 virtual STDMETHODIMP OnPlanComplete(
452 __in HRESULT hrStatus
453 )
454 {
455 HRESULT hr = S_OK;
456
457 if (m_fPrereq)
458 {
459 m_fPrereqAlreadyInstalled = TRUE;
460
461 // Now that we've planned the packages, we can focus on the prerequisite packages that are supposed to be installed.
462 for (DWORD i = 0; i < m_cPrereqPackages; ++i)
463 {
464 if (m_rgPrereqPackages[i].sczPackageId && !m_rgPrereqPackages[i].fWasAlreadyInstalled && m_rgPrereqPackages[i].fPlannedToBeInstalled)
465 {
466 m_fPrereqAlreadyInstalled = FALSE;
467 break;
468 }
469 }
470 }
471
472 SetState(WIXSTDBA_STATE_PLANNED, hrStatus);
473
474 if (SUCCEEDED(hrStatus))
475 {
476 ::PostMessageW(m_hWnd, WM_WIXSTDBA_APPLY_PACKAGES, 0, 0);
477 }
478
479 m_fStartedExecution = FALSE;
480 m_dwCalculatedCacheProgress = 0;
481 m_dwCalculatedExecuteProgress = 0;
482
483 return hr;
484 }
485
486
487 virtual STDMETHODIMP OnCachePackageBegin(
488 __in_z LPCWSTR wzPackageId,
489 __in DWORD cCachePayloads,
490 __in DWORD64 dw64PackageCacheSize,
491 __inout BOOL* pfCancel
492 )
493 {
494 if (wzPackageId && *wzPackageId)
495 {
496 BAL_INFO_PACKAGE* pPackage = NULL;
497 HRESULT hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);
498 LPCWSTR wz = (SUCCEEDED(hr) && pPackage->sczDisplayName) ? pPackage->sczDisplayName : wzPackageId;
499
500 ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, wz);
501
502 // If something started executing, leave it in the overall progress text.
503 if (!m_fStartedExecution)
504 {
505 ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wz);
506 }
507 }
508
509 return __super::OnCachePackageBegin(wzPackageId, cCachePayloads, dw64PackageCacheSize, pfCancel);
510 }
511
512
513 virtual STDMETHODIMP OnCacheAcquireProgress(
514 __in_z LPCWSTR wzPackageOrContainerId,
515 __in_z_opt LPCWSTR wzPayloadId,
516 __in DWORD64 dw64Progress,
517 __in DWORD64 dw64Total,
518 __in DWORD dwOverallPercentage,
519 __inout BOOL* pfCancel
520 )
521 {
522#ifdef DEBUG
523 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnCacheAcquireProgress() - container/package: %ls, payload: %ls, progress: %I64u, total: %I64u, overall progress: %u%%", wzPackageOrContainerId, wzPayloadId, dw64Progress, dw64Total, dwOverallPercentage);
524#endif
525
526 UpdateCacheProgress(dwOverallPercentage);
527
528 return __super::OnCacheAcquireProgress(wzPackageOrContainerId, wzPayloadId, dw64Progress, dw64Total, dwOverallPercentage, pfCancel);
529 }
530
531
532 virtual STDMETHODIMP OnCacheAcquireComplete(
533 __in_z LPCWSTR wzPackageOrContainerId,
534 __in_z_opt LPCWSTR wzPayloadId,
535 __in HRESULT hrStatus,
536 __in BOOTSTRAPPER_CACHEACQUIRECOMPLETE_ACTION recommendation,
537 __inout BOOTSTRAPPER_CACHEACQUIRECOMPLETE_ACTION* pAction
538 )
539 {
540 SetProgressState(hrStatus);
541 return __super::OnCacheAcquireComplete(wzPackageOrContainerId, wzPayloadId, hrStatus, recommendation, pAction);
542 }
543
544
545 virtual STDMETHODIMP OnCacheVerifyComplete(
546 __in_z LPCWSTR wzPackageId,
547 __in_z LPCWSTR wzPayloadId,
548 __in HRESULT hrStatus,
549 __in BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION recommendation,
550 __inout BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION* pAction
551 )
552 {
553 SetProgressState(hrStatus);
554 return __super::OnCacheVerifyComplete(wzPackageId, wzPayloadId, hrStatus, recommendation, pAction);
555 }
556
557
558 virtual STDMETHODIMP OnCacheComplete(
559 __in HRESULT hrStatus
560 )
561 {
562 UpdateCacheProgress(SUCCEEDED(hrStatus) ? 100 : 0);
563 ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, L"");
564 SetState(WIXSTDBA_STATE_CACHED, S_OK); // we always return success here and let OnApplyComplete() deal with the error.
565 return __super::OnCacheComplete(hrStatus);
566 }
567
568
569 virtual STDMETHODIMP OnError(
570 __in BOOTSTRAPPER_ERROR_TYPE errorType,
571 __in LPCWSTR wzPackageId,
572 __in DWORD dwCode,
573 __in_z LPCWSTR wzError,
574 __in DWORD dwUIHint,
575 __in DWORD /*cData*/,
576 __in_ecount_z_opt(cData) LPCWSTR* /*rgwzData*/,
577 __in int /*nRecommendation*/,
578 __inout int* pResult
579 )
580 {
581 HRESULT hr = S_OK;
582 int nResult = *pResult;
583 LPWSTR sczError = NULL;
584
585 if (BOOTSTRAPPER_DISPLAY_EMBEDDED == m_command.display)
586 {
587 hr = m_pEngine->SendEmbeddedError(dwCode, wzError, dwUIHint, &nResult);
588 if (FAILED(hr))
589 {
590 nResult = IDERROR;
591 }
592 }
593 else if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display)
594 {
595 // If this is an authentication failure, let the engine try to handle it for us.
596 if (BOOTSTRAPPER_ERROR_TYPE_HTTP_AUTH_SERVER == errorType || BOOTSTRAPPER_ERROR_TYPE_HTTP_AUTH_PROXY == errorType)
597 {
598 nResult = IDTRYAGAIN;
599 }
600 else // show a generic error message box.
601 {
602 BalRetryErrorOccurred(wzPackageId, dwCode);
603
604 if (!m_fShowingInternalUiThisPackage)
605 {
606 // If no error message was provided, use the error code to try and get an error message.
607 if (!wzError || !*wzError || BOOTSTRAPPER_ERROR_TYPE_WINDOWS_INSTALLER != errorType)
608 {
609 hr = StrAllocFromError(&sczError, dwCode, NULL);
610 if (FAILED(hr) || !sczError || !*sczError)
611 {
612 // special case for ERROR_FAIL_NOACTION_REBOOT: use loc string for Windows XP
613 if (ERROR_FAIL_NOACTION_REBOOT == dwCode)
614 {
615 LOC_STRING* pLocString = NULL;
616 hr = LocGetString(m_pWixLoc, L"#(loc.ErrorFailNoActionReboot)", &pLocString);
617 if (SUCCEEDED(hr))
618 {
619 StrAllocString(&sczError, pLocString->wzText, 0);
620 }
621 else
622 {
623 StrAllocFormatted(&sczError, L"0x%x", dwCode);
624 }
625 }
626 else
627 {
628 StrAllocFormatted(&sczError, L"0x%x", dwCode);
629 }
630 }
631 hr = S_OK;
632 }
633
634 nResult = ::MessageBoxW(m_hWnd, sczError ? sczError : wzError, m_pTheme->sczCaption, dwUIHint);
635 }
636 }
637
638 SetProgressState(HRESULT_FROM_WIN32(dwCode));
639 }
640 else // just take note of the error code and let things continue.
641 {
642 BalRetryErrorOccurred(wzPackageId, dwCode);
643 }
644
645 ReleaseStr(sczError);
646 *pResult = nResult;
647 return hr;
648 }
649
650
651 virtual STDMETHODIMP OnExecuteMsiMessage(
652 __in_z LPCWSTR wzPackageId,
653 __in INSTALLMESSAGE messageType,
654 __in DWORD dwUIHint,
655 __in_z LPCWSTR wzMessage,
656 __in DWORD cData,
657 __in_ecount_z_opt(cData) LPCWSTR* rgwzData,
658 __in int nRecommendation,
659 __inout int* pResult
660 )
661 {
662#ifdef DEBUG
663 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnExecuteMsiMessage() - package: %ls, message: %ls", wzPackageId, wzMessage);
664#endif
665 if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display && (INSTALLMESSAGE_WARNING == messageType || INSTALLMESSAGE_USER == messageType))
666 {
667 if (!m_fShowingInternalUiThisPackage)
668 {
669 int nResult = ::MessageBoxW(m_hWnd, wzMessage, m_pTheme->sczCaption, dwUIHint);
670 return nResult;
671 }
672 }
673
674 if (INSTALLMESSAGE_ACTIONSTART == messageType)
675 {
676 ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, wzMessage);
677 }
678
679 return __super::OnExecuteMsiMessage(wzPackageId, messageType, dwUIHint, wzMessage, cData, rgwzData, nRecommendation, pResult);
680 }
681
682
683 virtual STDMETHODIMP OnProgress(
684 __in DWORD dwProgressPercentage,
685 __in DWORD dwOverallProgressPercentage,
686 __inout BOOL* pfCancel
687 )
688 {
689 WCHAR wzProgress[5] = { };
690
691#ifdef DEBUG
692 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnProgress() - progress: %u%%, overall progress: %u%%", dwProgressPercentage, dwOverallProgressPercentage);
693#endif
694
695 ::StringCchPrintfW(wzProgress, countof(wzProgress), L"%u%%", dwOverallProgressPercentage);
696 ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_TEXT, wzProgress);
697
698 ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_BAR, dwOverallProgressPercentage);
699 SetTaskbarButtonProgress(dwOverallProgressPercentage);
700
701 return __super::OnProgress(dwProgressPercentage, dwOverallProgressPercentage, pfCancel);
702 }
703
704
705 virtual STDMETHODIMP OnExecutePackageBegin(
706 __in_z LPCWSTR wzPackageId,
707 __in BOOL fExecute,
708 __inout BOOL* pfCancel
709 )
710 {
711 LPWSTR sczFormattedString = NULL;
712
713 m_fStartedExecution = TRUE;
714
715 if (wzPackageId && *wzPackageId)
716 {
717 BAL_INFO_PACKAGE* pPackage = NULL;
718 BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);
719
720 LPCWSTR wz = wzPackageId;
721 if (pPackage)
722 {
723 LOC_STRING* pLocString = NULL;
724
725 switch (pPackage->type)
726 {
727 case BAL_INFO_PACKAGE_TYPE_BUNDLE_ADDON:
728 LocGetString(m_pWixLoc, L"#(loc.ExecuteAddonRelatedBundleMessage)", &pLocString);
729 break;
730
731 case BAL_INFO_PACKAGE_TYPE_BUNDLE_PATCH:
732 LocGetString(m_pWixLoc, L"#(loc.ExecutePatchRelatedBundleMessage)", &pLocString);
733 break;
734
735 case BAL_INFO_PACKAGE_TYPE_BUNDLE_UPGRADE:
736 LocGetString(m_pWixLoc, L"#(loc.ExecuteUpgradeRelatedBundleMessage)", &pLocString);
737 break;
738 }
739
740 if (pLocString)
741 {
742 // If the wix developer is showing a hidden variable in the UI, then obviously they don't care about keeping it safe
743 // so don't go down the rabbit hole of making sure that this is securely freed.
744 BalFormatString(pLocString->wzText, &sczFormattedString);
745 }
746
747 wz = sczFormattedString ? sczFormattedString : pPackage->sczDisplayName ? pPackage->sczDisplayName : wzPackageId;
748 }
749
750 //Burn engine doesn't show internal UI for msi packages during uninstall or repair actions.
751 m_fShowingInternalUiThisPackage = pPackage && pPackage->fDisplayInternalUI && BOOTSTRAPPER_ACTION_UNINSTALL != m_plannedAction && BOOTSTRAPPER_ACTION_REPAIR != m_plannedAction;
752
753 ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, wz);
754 ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wz);
755 }
756 else
757 {
758 m_fShowingInternalUiThisPackage = FALSE;
759 }
760
761 ReleaseStr(sczFormattedString);
762 return __super::OnExecutePackageBegin(wzPackageId, fExecute, pfCancel);
763 }
764
765
766 virtual STDMETHODIMP OnExecuteProgress(
767 __in_z LPCWSTR wzPackageId,
768 __in DWORD dwProgressPercentage,
769 __in DWORD dwOverallProgressPercentage,
770 __inout BOOL* pfCancel
771 )
772 {
773 WCHAR wzProgress[5] = { };
774
775#ifdef DEBUG
776 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnExecuteProgress() - package: %ls, progress: %u%%, overall progress: %u%%", wzPackageId, dwProgressPercentage, dwOverallProgressPercentage);
777#endif
778
779 ::StringCchPrintfW(wzProgress, countof(wzProgress), L"%u%%", dwOverallProgressPercentage);
780 ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_TEXT, wzProgress);
781
782 ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_BAR, dwOverallProgressPercentage);
783
784 m_dwCalculatedExecuteProgress = dwOverallProgressPercentage * (100 - WIXSTDBA_ACQUIRE_PERCENTAGE) / 100;
785 ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress);
786
787 SetTaskbarButtonProgress(m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress);
788
789 return __super::OnExecuteProgress(wzPackageId, dwProgressPercentage, dwOverallProgressPercentage, pfCancel);
790 }
791
792
793 virtual STDMETHODIMP OnExecutePackageComplete(
794 __in_z LPCWSTR wzPackageId,
795 __in HRESULT hrStatus,
796 __in BOOTSTRAPPER_APPLY_RESTART restart,
797 __in BOOTSTRAPPER_EXECUTEPACKAGECOMPLETE_ACTION recommendation,
798 __inout BOOTSTRAPPER_EXECUTEPACKAGECOMPLETE_ACTION* pAction
799 )
800 {
801 HRESULT hr = S_OK;
802 SetProgressState(hrStatus);
803
804 hr = __super::OnExecutePackageComplete(wzPackageId, hrStatus, restart, recommendation, pAction);
805
806 WIXSTDBA_PREREQ_PACKAGE* pPrereqPackage = NULL;
807 BAL_INFO_PACKAGE* pPackage;
808 HRESULT hrPrereq = GetPrereqPackage(wzPackageId, &pPrereqPackage, &pPackage);
809 if (SUCCEEDED(hrPrereq))
810 {
811 pPrereqPackage->fSuccessfullyInstalled = SUCCEEDED(hrStatus);
812
813 // If the prerequisite required a restart (any restart) then do an immediate
814 // restart to ensure that the bundle will get launched again post reboot.
815 if (BOOTSTRAPPER_APPLY_RESTART_NONE != restart)
816 {
817 *pAction = BOOTSTRAPPER_EXECUTEPACKAGECOMPLETE_ACTION_RESTART;
818 }
819 }
820
821 return hr;
822 }
823
824
825 virtual STDMETHODIMP OnExecuteComplete(
826 __in HRESULT hrStatus
827 )
828 {
829 HRESULT hr = S_OK;
830
831 ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, L"");
832 ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, L"");
833 ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, L"");
834 ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, FALSE); // no more cancel.
835
836 SetState(WIXSTDBA_STATE_EXECUTED, S_OK); // we always return success here and let OnApplyComplete() deal with the error.
837 SetProgressState(hrStatus);
838
839 return hr;
840 }
841
842
843 virtual STDMETHODIMP OnResolveSource(
844 __in_z LPCWSTR wzPackageOrContainerId,
845 __in_z_opt LPCWSTR wzPayloadId,
846 __in_z LPCWSTR wzLocalSource,
847 __in_z_opt LPCWSTR wzDownloadSource,
848 __in BOOTSTRAPPER_RESOLVESOURCE_ACTION /*recommendation*/,
849 __inout BOOTSTRAPPER_RESOLVESOURCE_ACTION* pAction,
850 __inout BOOL* pfCancel
851 )
852 {
853 HRESULT hr = S_OK;
854
855 if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display)
856 {
857 if (wzDownloadSource)
858 {
859 *pAction = BOOTSTRAPPER_RESOLVESOURCE_ACTION_DOWNLOAD;
860 }
861 else // prompt to change the source location.
862 {
863 OPENFILENAMEW ofn = { };
864 WCHAR wzFile[MAX_PATH] = { };
865
866 ::StringCchCopyW(wzFile, countof(wzFile), wzLocalSource);
867
868 ofn.lStructSize = sizeof(ofn);
869 ofn.hwndOwner = m_hWnd;
870 ofn.lpstrFile = wzFile;
871 ofn.nMaxFile = countof(wzFile);
872 ofn.lpstrFilter = L"All Files\0*.*\0";
873 ofn.nFilterIndex = 1;
874 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
875 ofn.lpstrTitle = m_pTheme->sczCaption;
876
877 if (::GetOpenFileNameW(&ofn))
878 {
879 hr = m_pEngine->SetLocalSource(wzPackageOrContainerId, wzPayloadId, ofn.lpstrFile);
880 *pAction = BOOTSTRAPPER_RESOLVESOURCE_ACTION_RETRY;
881 }
882 else
883 {
884 *pfCancel = TRUE;
885 }
886 }
887 }
888 else if (wzDownloadSource)
889 {
890 // If doing a non-interactive install and download source is available, let's try downloading the package silently
891 *pAction = BOOTSTRAPPER_RESOLVESOURCE_ACTION_DOWNLOAD;
892 }
893 // else there's nothing more we can do in non-interactive mode
894
895 *pfCancel |= CheckCanceled();
896 return hr;
897 }
898
899
900 virtual STDMETHODIMP OnApplyComplete(
901 __in HRESULT hrStatus,
902 __in BOOTSTRAPPER_APPLY_RESTART restart,
903 __in BOOTSTRAPPER_APPLYCOMPLETE_ACTION recommendation,
904 __inout BOOTSTRAPPER_APPLYCOMPLETE_ACTION* pAction
905 )
906 {
907 HRESULT hr = S_OK;
908
909 __super::OnApplyComplete(hrStatus, restart, recommendation, pAction);
910
911 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.
912
913 // If a restart was encountered and we are not suppressing restarts, then restart is required.
914 m_fRestartRequired = (BOOTSTRAPPER_APPLY_RESTART_NONE != restart && BOOTSTRAPPER_RESTART_NEVER < m_command.restart);
915 BalSetStringVariable(WIXSTDBA_VARIABLE_RESTART_REQUIRED, m_fRestartRequired ? L"1" : NULL);
916
917 // 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.
918 m_fAllowRestart = m_fRestartRequired && (BOOTSTRAPPER_DISPLAY_FULL > m_command.display || BOOTSTRAPPER_RESTART_PROMPT < m_command.restart);
919
920 if (m_fPrereq)
921 {
922 m_fPrereqInstalled = TRUE;
923 BOOL fInstalledAPackage = FALSE;
924
925 for (DWORD i = 0; i < m_cPrereqPackages; ++i)
926 {
927 if (m_rgPrereqPackages[i].sczPackageId && m_rgPrereqPackages[i].fPlannedToBeInstalled && !m_rgPrereqPackages[i].fWasAlreadyInstalled)
928 {
929 if (m_rgPrereqPackages[i].fSuccessfullyInstalled)
930 {
931 fInstalledAPackage = TRUE;
932 }
933 else
934 {
935 m_fPrereqInstalled = FALSE;
936 break;
937 }
938 }
939 }
940
941 m_fPrereqInstalled = m_fPrereqInstalled && fInstalledAPackage;
942 }
943
944 // If we are showing UI, wait a beat before moving to the final screen.
945 if (BOOTSTRAPPER_DISPLAY_NONE < m_command.display)
946 {
947 ::Sleep(250);
948 }
949
950 SetState(WIXSTDBA_STATE_APPLIED, hrStatus);
951 SetTaskbarButtonProgress(100); // show full progress bar, green, yellow, or red
952
953 *pAction = BOOTSTRAPPER_APPLYCOMPLETE_ACTION_NONE;
954
955 return hr;
956 }
957
958 virtual STDMETHODIMP OnLaunchApprovedExeComplete(
959 __in HRESULT hrStatus,
960 __in DWORD /*processId*/
961 )
962 {
963 HRESULT hr = S_OK;
964
965 if (HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hrStatus)
966 {
967 //try with ShelExec next time
968 OnClickLaunchButton();
969 }
970 else
971 {
972 ::PostMessageW(m_hWnd, WM_CLOSE, 0, 0);
973 }
974
975 return hr;
976 }
977
978 virtual STDMETHODIMP_(void) BAProcFallback(
979 __in BOOTSTRAPPER_APPLICATION_MESSAGE message,
980 __in const LPVOID pvArgs,
981 __inout LPVOID pvResults,
982 __inout HRESULT* phr,
983 __in_opt LPVOID /*pvContext*/
984 )
985 {
986 if (!m_pfnBAFunctionsProc || FAILED(*phr))
987 {
988 return;
989 }
990
991 // Always log before and after so we don't get blamed when BAFunctions changes something.
992 switch (message)
993 {
994 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTBEGIN:
995 OnDetectBeginFallback(reinterpret_cast<BA_ONDETECTBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTBEGIN_RESULTS*>(pvResults));
996 break;
997 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTCOMPLETE:
998 OnDetectCompleteFallback(reinterpret_cast<BA_ONDETECTCOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTCOMPLETE_RESULTS*>(pvResults));
999 break;
1000 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANBEGIN:
1001 OnPlanBeginFallback(reinterpret_cast<BA_ONPLANBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANBEGIN_RESULTS*>(pvResults));
1002 break;
1003 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPLETE:
1004 OnPlanCompleteFallback(reinterpret_cast<BA_ONPLANCOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANCOMPLETE_RESULTS*>(pvResults));
1005 break;
1006 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONSTARTUP: // BAFunctions is loaded during this event on a separate thread so it's not possible to forward it.
1007 break;
1008 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONSHUTDOWN:
1009 OnShutdownFallback(reinterpret_cast<BA_ONSHUTDOWN_ARGS*>(pvArgs), reinterpret_cast<BA_ONSHUTDOWN_RESULTS*>(pvResults));
1010 break;
1011 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONSYSTEMSHUTDOWN:
1012 OnSystemShutdownFallback(reinterpret_cast<BA_ONSYSTEMSHUTDOWN_ARGS*>(pvArgs), reinterpret_cast<BA_ONSYSTEMSHUTDOWN_RESULTS*>(pvResults));
1013 break;
1014 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTFORWARDCOMPATIBLEBUNDLE:
1015 OnDetectForwardCompatibleBundleFallback(reinterpret_cast<BA_ONDETECTFORWARDCOMPATIBLEBUNDLE_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTFORWARDCOMPATIBLEBUNDLE_RESULTS*>(pvResults));
1016 break;
1017 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTUPDATEBEGIN:
1018 OnDetectUpdateBeginFallback(reinterpret_cast<BA_ONDETECTUPDATEBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTUPDATEBEGIN_RESULTS*>(pvResults));
1019 break;
1020 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTUPDATE:
1021 OnDetectUpdateFallback(reinterpret_cast<BA_ONDETECTUPDATE_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTUPDATE_RESULTS*>(pvResults));
1022 break;
1023 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTUPDATECOMPLETE:
1024 OnDetectUpdateCompleteFallback(reinterpret_cast<BA_ONDETECTUPDATECOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTUPDATECOMPLETE_RESULTS*>(pvResults));
1025 break;
1026 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTRELATEDBUNDLE:
1027 OnDetectRelatedBundleFallback(reinterpret_cast<BA_ONDETECTRELATEDBUNDLE_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTRELATEDBUNDLE_RESULTS*>(pvResults));
1028 break;
1029 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTPACKAGEBEGIN:
1030 OnDetectPackageBeginFallback(reinterpret_cast<BA_ONDETECTPACKAGEBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTPACKAGEBEGIN_RESULTS*>(pvResults));
1031 break;
1032 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTCOMPATIBLEMSIPACKAGE:
1033 OnDetectCompatibleMsiPackageFallback(reinterpret_cast<BA_ONDETECTCOMPATIBLEMSIPACKAGE_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTCOMPATIBLEMSIPACKAGE_RESULTS*>(pvResults));
1034 break;
1035 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTRELATEDMSIPACKAGE:
1036 OnDetectRelatedMsiPackageFallback(reinterpret_cast<BA_ONDETECTRELATEDMSIPACKAGE_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTRELATEDMSIPACKAGE_RESULTS*>(pvResults));
1037 break;
1038 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTTARGETMSIPACKAGE:
1039 OnDetectTargetMsiPackageFallback(reinterpret_cast<BA_ONDETECTTARGETMSIPACKAGE_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTTARGETMSIPACKAGE_RESULTS*>(pvResults));
1040 break;
1041 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTMSIFEATURE:
1042 OnDetectMsiFeatureFallback(reinterpret_cast<BA_ONDETECTMSIFEATURE_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTMSIFEATURE_RESULTS*>(pvResults));
1043 break;
1044 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTPACKAGECOMPLETE:
1045 OnDetectPackageCompleteFallback(reinterpret_cast<BA_ONDETECTPACKAGECOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTPACKAGECOMPLETE_RESULTS*>(pvResults));
1046 break;
1047 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRELATEDBUNDLE:
1048 OnPlanRelatedBundleFallback(reinterpret_cast<BA_ONPLANRELATEDBUNDLE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANRELATEDBUNDLE_RESULTS*>(pvResults));
1049 break;
1050 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANPACKAGEBEGIN:
1051 OnPlanPackageBeginFallback(reinterpret_cast<BA_ONPLANPACKAGEBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANPACKAGEBEGIN_RESULTS*>(pvResults));
1052 break;
1053 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGEBEGIN:
1054 OnPlanCompatibleMsiPackageBeginFallback(reinterpret_cast<BA_ONPLANCOMPATIBLEMSIPACKAGEBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANCOMPATIBLEMSIPACKAGEBEGIN_RESULTS*>(pvResults));
1055 break;
1056 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE:
1057 OnPlanCompatibleMsiPackageCompleteFallback(reinterpret_cast<BA_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE_RESULTS*>(pvResults));
1058 break;
1059 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANTARGETMSIPACKAGE:
1060 OnPlanTargetMsiPackageFallback(reinterpret_cast<BA_ONPLANTARGETMSIPACKAGE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANTARGETMSIPACKAGE_RESULTS*>(pvResults));
1061 break;
1062 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANMSIFEATURE:
1063 OnPlanMsiFeatureFallback(reinterpret_cast<BA_ONPLANMSIFEATURE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANMSIFEATURE_RESULTS*>(pvResults));
1064 break;
1065 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANPACKAGECOMPLETE:
1066 OnPlanPackageCompleteFallback(reinterpret_cast<BA_ONPLANPACKAGECOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANPACKAGECOMPLETE_RESULTS*>(pvResults));
1067 break;
1068 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONAPPLYBEGIN:
1069 OnApplyBeginFallback(reinterpret_cast<BA_ONAPPLYBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONAPPLYBEGIN_RESULTS*>(pvResults));
1070 break;
1071 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONELEVATEBEGIN:
1072 OnElevateBeginFallback(reinterpret_cast<BA_ONELEVATEBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONELEVATEBEGIN_RESULTS*>(pvResults));
1073 break;
1074 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONELEVATECOMPLETE:
1075 OnElevateCompleteFallback(reinterpret_cast<BA_ONELEVATECOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONELEVATECOMPLETE_RESULTS*>(pvResults));
1076 break;
1077 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPROGRESS:
1078 OnProgressFallback(reinterpret_cast<BA_ONPROGRESS_ARGS*>(pvArgs), reinterpret_cast<BA_ONPROGRESS_RESULTS*>(pvResults));
1079 break;
1080 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONERROR:
1081 OnErrorFallback(reinterpret_cast<BA_ONERROR_ARGS*>(pvArgs), reinterpret_cast<BA_ONERROR_RESULTS*>(pvResults));
1082 break;
1083 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONREGISTERBEGIN:
1084 OnRegisterBeginFallback(reinterpret_cast<BA_ONREGISTERBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONREGISTERBEGIN_RESULTS*>(pvResults));
1085 break;
1086 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONREGISTERCOMPLETE:
1087 OnRegisterCompleteFallback(reinterpret_cast<BA_ONREGISTERCOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONREGISTERCOMPLETE_RESULTS*>(pvResults));
1088 break;
1089 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEBEGIN:
1090 OnCacheBeginFallback(reinterpret_cast<BA_ONCACHEBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONCACHEBEGIN_RESULTS*>(pvResults));
1091 break;
1092 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPACKAGEBEGIN:
1093 OnCachePackageBeginFallback(reinterpret_cast<BA_ONCACHEPACKAGEBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONCACHEPACKAGEBEGIN_RESULTS*>(pvResults));
1094 break;
1095 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIREBEGIN:
1096 OnCacheAcquireBeginFallback(reinterpret_cast<BA_ONCACHEACQUIREBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONCACHEACQUIREBEGIN_RESULTS*>(pvResults));
1097 break;
1098 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIREPROGRESS:
1099 OnCacheAcquireProgressFallback(reinterpret_cast<BA_ONCACHEACQUIREPROGRESS_ARGS*>(pvArgs), reinterpret_cast<BA_ONCACHEACQUIREPROGRESS_RESULTS*>(pvResults));
1100 break;
1101 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONRESOLVESOURCE:
1102 OnResolveSourceFallback(reinterpret_cast<BA_ONRESOLVESOURCE_ARGS*>(pvArgs), reinterpret_cast<BA_ONRESOLVESOURCE_RESULTS*>(pvResults));
1103 break;
1104 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIRECOMPLETE:
1105 OnCacheAcquireCompleteFallback(reinterpret_cast<BA_ONCACHEACQUIRECOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONCACHEACQUIRECOMPLETE_RESULTS*>(pvResults));
1106 break;
1107 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEVERIFYBEGIN:
1108 OnCacheVerifyBeginFallback(reinterpret_cast<BA_ONCACHEVERIFYBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONCACHEVERIFYBEGIN_RESULTS*>(pvResults));
1109 break;
1110 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEVERIFYCOMPLETE:
1111 OnCacheVerifyCompleteFallback(reinterpret_cast<BA_ONCACHEVERIFYCOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONCACHEVERIFYCOMPLETE_RESULTS*>(pvResults));
1112 break;
1113 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPACKAGECOMPLETE:
1114 OnCachePackageCompleteFallback(reinterpret_cast<BA_ONCACHEPACKAGECOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONCACHEPACKAGECOMPLETE_RESULTS*>(pvResults));
1115 break;
1116 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHECOMPLETE:
1117 OnCacheCompleteFallback(reinterpret_cast<BA_ONCACHECOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONCACHECOMPLETE_RESULTS*>(pvResults));
1118 break;
1119 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONEXECUTEBEGIN:
1120 OnExecuteBeginFallback(reinterpret_cast<BA_ONEXECUTEBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONEXECUTEBEGIN_RESULTS*>(pvResults));
1121 break;
1122 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONEXECUTEPACKAGEBEGIN:
1123 OnExecutePackageBeginFallback(reinterpret_cast<BA_ONEXECUTEPACKAGEBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONEXECUTEPACKAGEBEGIN_RESULTS*>(pvResults));
1124 break;
1125 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONEXECUTEPATCHTARGET:
1126 OnExecutePatchTargetFallback(reinterpret_cast<BA_ONEXECUTEPATCHTARGET_ARGS*>(pvArgs), reinterpret_cast<BA_ONEXECUTEPATCHTARGET_RESULTS*>(pvResults));
1127 break;
1128 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONEXECUTEPROGRESS:
1129 OnExecuteProgressFallback(reinterpret_cast<BA_ONEXECUTEPROGRESS_ARGS*>(pvArgs), reinterpret_cast<BA_ONEXECUTEPROGRESS_RESULTS*>(pvResults));
1130 break;
1131 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONEXECUTEMSIMESSAGE:
1132 OnExecuteMsiMessageFallback(reinterpret_cast<BA_ONEXECUTEMSIMESSAGE_ARGS*>(pvArgs), reinterpret_cast<BA_ONEXECUTEMSIMESSAGE_RESULTS*>(pvResults));
1133 break;
1134 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONEXECUTEFILESINUSE:
1135 OnExecuteFilesInUseFallback(reinterpret_cast<BA_ONEXECUTEFILESINUSE_ARGS*>(pvArgs), reinterpret_cast<BA_ONEXECUTEFILESINUSE_RESULTS*>(pvResults));
1136 break;
1137 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONEXECUTEPACKAGECOMPLETE:
1138 OnExecutePackageCompleteFallback(reinterpret_cast<BA_ONEXECUTEPACKAGECOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONEXECUTEPACKAGECOMPLETE_RESULTS*>(pvResults));
1139 break;
1140 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONEXECUTECOMPLETE:
1141 OnExecuteCompleteFallback(reinterpret_cast<BA_ONEXECUTECOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONEXECUTECOMPLETE_RESULTS*>(pvResults));
1142 break;
1143 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONUNREGISTERBEGIN:
1144 OnUnregisterBeginFallback(reinterpret_cast<BA_ONUNREGISTERBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONUNREGISTERBEGIN_RESULTS*>(pvResults));
1145 break;
1146 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONUNREGISTERCOMPLETE:
1147 OnUnregisterCompleteFallback(reinterpret_cast<BA_ONUNREGISTERCOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONUNREGISTERCOMPLETE_RESULTS*>(pvResults));
1148 break;
1149 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONAPPLYCOMPLETE:
1150 OnApplyCompleteFallback(reinterpret_cast<BA_ONAPPLYCOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONAPPLYCOMPLETE_RESULTS*>(pvResults));
1151 break;
1152 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONLAUNCHAPPROVEDEXEBEGIN:
1153 OnLaunchApprovedExeBeginFallback(reinterpret_cast<BA_ONLAUNCHAPPROVEDEXEBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONLAUNCHAPPROVEDEXEBEGIN_RESULTS*>(pvResults));
1154 break;
1155 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONLAUNCHAPPROVEDEXECOMPLETE:
1156 OnLaunchApprovedExeCompleteFallback(reinterpret_cast<BA_ONLAUNCHAPPROVEDEXECOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONLAUNCHAPPROVEDEXECOMPLETE_RESULTS*>(pvResults));
1157 break;
1158 default:
1159 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: Forwarding unknown BA message: %d", message);
1160 m_pfnBAFunctionsProc((BA_FUNCTIONS_MESSAGE)message, pvArgs, pvResults, m_pvBAFunctionsProcContext);
1161 break;
1162 }
1163 }
1164
1165
1166private: // privates
1167 void OnDetectBeginFallback(
1168 __in BA_ONDETECTBEGIN_ARGS* pArgs,
1169 __inout BA_ONDETECTBEGIN_RESULTS* pResults
1170 )
1171 {
1172 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONDETECTBEGIN, pArgs, pResults, m_pvBAFunctionsProcContext);
1173 }
1174
1175 void OnDetectCompleteFallback(
1176 __in BA_ONDETECTCOMPLETE_ARGS* pArgs,
1177 __inout BA_ONDETECTCOMPLETE_RESULTS* pResults
1178 )
1179 {
1180 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONDETECTCOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext);
1181 }
1182
1183 void OnPlanBeginFallback(
1184 __in BA_ONPLANBEGIN_ARGS* pArgs,
1185 __inout BA_ONPLANBEGIN_RESULTS* pResults
1186 )
1187 {
1188 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONPLANBEGIN, pArgs, pResults, m_pvBAFunctionsProcContext);
1189 }
1190
1191 void OnPlanCompleteFallback(
1192 __in BA_ONPLANCOMPLETE_ARGS* pArgs,
1193 __inout BA_ONPLANCOMPLETE_RESULTS* pResults
1194 )
1195 {
1196 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONPLANCOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext);
1197 }
1198
1199 void OnShutdownFallback(
1200 __in BA_ONSHUTDOWN_ARGS* pArgs,
1201 __inout BA_ONSHUTDOWN_RESULTS* pResults
1202 )
1203 {
1204 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONSHUTDOWN, pArgs, pResults, m_pvBAFunctionsProcContext);
1205 }
1206
1207 void OnSystemShutdownFallback(
1208 __in BA_ONSYSTEMSHUTDOWN_ARGS* pArgs,
1209 __inout BA_ONSYSTEMSHUTDOWN_RESULTS* pResults
1210 )
1211 {
1212 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONSYSTEMSHUTDOWN, pArgs, pResults, m_pvBAFunctionsProcContext);
1213 }
1214
1215 void OnDetectForwardCompatibleBundleFallback(
1216 __in BA_ONDETECTFORWARDCOMPATIBLEBUNDLE_ARGS* pArgs,
1217 __inout BA_ONDETECTFORWARDCOMPATIBLEBUNDLE_RESULTS* pResults
1218 )
1219 {
1220 BOOL fIgnoreBundle = pResults->fIgnoreBundle;
1221 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONDETECTFORWARDCOMPATIBLEBUNDLE, pArgs, pResults, m_pvBAFunctionsProcContext);
1222 BalLogId(BOOTSTRAPPER_LOG_LEVEL_STANDARD, MSG_WIXSTDBA_DETECTED_FORWARD_COMPATIBLE_BUNDLE, m_hModule, pArgs->wzBundleId, fIgnoreBundle ? "ignore" : "enable", pResults->fIgnoreBundle ? "ignore" : "enable");
1223 }
1224
1225 void OnDetectUpdateBeginFallback(
1226 __in BA_ONDETECTUPDATEBEGIN_ARGS* pArgs,
1227 __inout BA_ONDETECTUPDATEBEGIN_RESULTS* pResults
1228 )
1229 {
1230 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONDETECTUPDATEBEGIN, pArgs, pResults, m_pvBAFunctionsProcContext);
1231 }
1232
1233 void OnDetectUpdateFallback(
1234 __in BA_ONDETECTUPDATE_ARGS* pArgs,
1235 __inout BA_ONDETECTUPDATE_RESULTS* pResults
1236 )
1237 {
1238 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONDETECTUPDATE, pArgs, pResults, m_pvBAFunctionsProcContext);
1239 }
1240
1241 void OnDetectUpdateCompleteFallback(
1242 __in BA_ONDETECTUPDATECOMPLETE_ARGS* pArgs,
1243 __inout BA_ONDETECTUPDATECOMPLETE_RESULTS* pResults
1244 )
1245 {
1246 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONDETECTUPDATECOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext);
1247 }
1248
1249 void OnDetectRelatedBundleFallback(
1250 __in BA_ONDETECTRELATEDBUNDLE_ARGS* pArgs,
1251 __inout BA_ONDETECTRELATEDBUNDLE_RESULTS* pResults
1252 )
1253 {
1254 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONDETECTRELATEDBUNDLE, pArgs, pResults, m_pvBAFunctionsProcContext);
1255 }
1256
1257 void OnDetectPackageBeginFallback(
1258 __in BA_ONDETECTPACKAGEBEGIN_ARGS* pArgs,
1259 __inout BA_ONDETECTPACKAGEBEGIN_RESULTS* pResults
1260 )
1261 {
1262 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONDETECTPACKAGEBEGIN, pArgs, pResults, m_pvBAFunctionsProcContext);
1263 }
1264
1265 void OnDetectCompatibleMsiPackageFallback(
1266 __in BA_ONDETECTCOMPATIBLEMSIPACKAGE_ARGS* pArgs,
1267 __inout BA_ONDETECTCOMPATIBLEMSIPACKAGE_RESULTS* pResults
1268 )
1269 {
1270 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONDETECTCOMPATIBLEMSIPACKAGE, pArgs, pResults, m_pvBAFunctionsProcContext);
1271 }
1272
1273 void OnDetectRelatedMsiPackageFallback(
1274 __in BA_ONDETECTRELATEDMSIPACKAGE_ARGS* pArgs,
1275 __inout BA_ONDETECTRELATEDMSIPACKAGE_RESULTS* pResults
1276 )
1277 {
1278 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONDETECTRELATEDMSIPACKAGE, pArgs, pResults, m_pvBAFunctionsProcContext);
1279 }
1280
1281 void OnDetectTargetMsiPackageFallback(
1282 __in BA_ONDETECTTARGETMSIPACKAGE_ARGS* pArgs,
1283 __inout BA_ONDETECTTARGETMSIPACKAGE_RESULTS* pResults
1284 )
1285 {
1286 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONDETECTTARGETMSIPACKAGE, pArgs, pResults, m_pvBAFunctionsProcContext);
1287 }
1288
1289 void OnDetectMsiFeatureFallback(
1290 __in BA_ONDETECTMSIFEATURE_ARGS* pArgs,
1291 __inout BA_ONDETECTMSIFEATURE_RESULTS* pResults
1292 )
1293 {
1294 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONDETECTMSIFEATURE, pArgs, pResults, m_pvBAFunctionsProcContext);
1295 }
1296
1297 void OnDetectPackageCompleteFallback(
1298 __in BA_ONDETECTPACKAGECOMPLETE_ARGS* pArgs,
1299 __inout BA_ONDETECTPACKAGECOMPLETE_RESULTS* pResults
1300 )
1301 {
1302 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONDETECTPACKAGECOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext);
1303 }
1304
1305 void OnPlanRelatedBundleFallback(
1306 __in BA_ONPLANRELATEDBUNDLE_ARGS* pArgs,
1307 __inout BA_ONPLANRELATEDBUNDLE_RESULTS* pResults
1308 )
1309 {
1310 BOOTSTRAPPER_REQUEST_STATE requestedState = pResults->requestedState;
1311 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONPLANRELATEDBUNDLE, pArgs, pResults, m_pvBAFunctionsProcContext);
1312 BalLogId(BOOTSTRAPPER_LOG_LEVEL_STANDARD, MSG_WIXSTDBA_PLANNED_RELATED_BUNDLE, m_hModule, pArgs->wzBundleId, LoggingRequestStateToString(requestedState), LoggingRequestStateToString(pResults->requestedState));
1313 }
1314
1315 void OnPlanPackageBeginFallback(
1316 __in BA_ONPLANPACKAGEBEGIN_ARGS* pArgs,
1317 __inout BA_ONPLANPACKAGEBEGIN_RESULTS* pResults
1318 )
1319 {
1320 BOOTSTRAPPER_REQUEST_STATE requestedState = pResults->requestedState;
1321 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONPLANPACKAGEBEGIN, pArgs, pResults, m_pvBAFunctionsProcContext);
1322 BalLogId(BOOTSTRAPPER_LOG_LEVEL_STANDARD, MSG_WIXSTDBA_PLANNED_PACKAGE, m_hModule, pArgs->wzPackageId, LoggingRequestStateToString(requestedState), LoggingRequestStateToString(pResults->requestedState));
1323 }
1324
1325 void OnPlanCompatibleMsiPackageBeginFallback(
1326 __in BA_ONPLANCOMPATIBLEMSIPACKAGEBEGIN_ARGS* pArgs,
1327 __inout BA_ONPLANCOMPATIBLEMSIPACKAGEBEGIN_RESULTS* pResults
1328 )
1329 {
1330 BOOTSTRAPPER_REQUEST_STATE requestedState = pResults->requestedState;
1331 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGEBEGIN, pArgs, pResults, m_pvBAFunctionsProcContext);
1332 BalLogId(BOOTSTRAPPER_LOG_LEVEL_STANDARD, MSG_WIXSTDBA_PLANNED_COMPATIBLE_MSI_PACKAGE, m_hModule, pArgs->wzPackageId, pArgs->wzCompatiblePackageId, LoggingRequestStateToString(requestedState), LoggingRequestStateToString(pResults->requestedState));
1333 }
1334
1335 void OnPlanCompatibleMsiPackageCompleteFallback(
1336 __in BA_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE_ARGS* pArgs,
1337 __inout BA_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE_RESULTS* pResults
1338 )
1339 {
1340 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONPLANCOMPATIBLEMSIPACKAGECOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext);
1341 }
1342
1343 void OnPlanTargetMsiPackageFallback(
1344 __in BA_ONPLANTARGETMSIPACKAGE_ARGS* pArgs,
1345 __inout BA_ONPLANTARGETMSIPACKAGE_RESULTS* pResults
1346 )
1347 {
1348 BOOTSTRAPPER_REQUEST_STATE requestedState = pResults->requestedState;
1349 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONPLANTARGETMSIPACKAGE, pArgs, pResults, m_pvBAFunctionsProcContext);
1350 BalLogId(BOOTSTRAPPER_LOG_LEVEL_STANDARD, MSG_WIXSTDBA_PLANNED_TARGET_MSI_PACKAGE, m_hModule, pArgs->wzPackageId, pArgs->wzProductCode, LoggingRequestStateToString(requestedState), LoggingRequestStateToString(pResults->requestedState));
1351 }
1352
1353 void OnPlanMsiFeatureFallback(
1354 __in BA_ONPLANMSIFEATURE_ARGS* pArgs,
1355 __inout BA_ONPLANMSIFEATURE_RESULTS* pResults
1356 )
1357 {
1358 BOOTSTRAPPER_FEATURE_STATE requestedState = pResults->requestedState;
1359 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONPLANMSIFEATURE, pArgs, pResults, m_pvBAFunctionsProcContext);
1360 BalLogId(BOOTSTRAPPER_LOG_LEVEL_STANDARD, MSG_WIXSTDBA_PLANNED_MSI_FEATURE, m_hModule, pArgs->wzPackageId, pArgs->wzFeatureId, LoggingMsiFeatureStateToString(requestedState), LoggingMsiFeatureStateToString(pResults->requestedState));
1361 }
1362
1363 void OnPlanPackageCompleteFallback(
1364 __in BA_ONPLANPACKAGECOMPLETE_ARGS* pArgs,
1365 __inout BA_ONPLANPACKAGECOMPLETE_RESULTS* pResults
1366 )
1367 {
1368 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONPLANPACKAGECOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext);
1369 }
1370
1371 void OnApplyBeginFallback(
1372 __in BA_ONAPPLYBEGIN_ARGS* pArgs,
1373 __inout BA_ONAPPLYBEGIN_RESULTS* pResults
1374 )
1375 {
1376 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONAPPLYBEGIN, pArgs, pResults, m_pvBAFunctionsProcContext);
1377 }
1378
1379 void OnElevateBeginFallback(
1380 __in BA_ONELEVATEBEGIN_ARGS* pArgs,
1381 __inout BA_ONELEVATEBEGIN_RESULTS* pResults
1382 )
1383 {
1384 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONELEVATEBEGIN, pArgs, pResults, m_pvBAFunctionsProcContext);
1385 }
1386
1387 void OnElevateCompleteFallback(
1388 __in BA_ONELEVATECOMPLETE_ARGS* pArgs,
1389 __inout BA_ONELEVATECOMPLETE_RESULTS* pResults
1390 )
1391 {
1392 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONELEVATECOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext);
1393 }
1394
1395 void OnProgressFallback(
1396 __in BA_ONPROGRESS_ARGS* pArgs,
1397 __inout BA_ONPROGRESS_RESULTS* pResults
1398 )
1399 {
1400 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONPROGRESS, pArgs, pResults, m_pvBAFunctionsProcContext);
1401 }
1402
1403 void OnErrorFallback(
1404 __in BA_ONERROR_ARGS* pArgs,
1405 __inout BA_ONERROR_RESULTS* pResults
1406 )
1407 {
1408 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONERROR, pArgs, pResults, m_pvBAFunctionsProcContext);
1409 }
1410
1411 void OnRegisterBeginFallback(
1412 __in BA_ONREGISTERBEGIN_ARGS* pArgs,
1413 __inout BA_ONREGISTERBEGIN_RESULTS* pResults
1414 )
1415 {
1416 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONREGISTERBEGIN, pArgs, pResults, m_pvBAFunctionsProcContext);
1417 }
1418
1419 void OnRegisterCompleteFallback(
1420 __in BA_ONREGISTERCOMPLETE_ARGS* pArgs,
1421 __inout BA_ONREGISTERCOMPLETE_RESULTS* pResults
1422 )
1423 {
1424 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONREGISTERCOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext);
1425 }
1426
1427 void OnCacheBeginFallback(
1428 __in BA_ONCACHEBEGIN_ARGS* pArgs,
1429 __inout BA_ONCACHEBEGIN_RESULTS* pResults
1430 )
1431 {
1432 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONCACHEBEGIN, pArgs, pResults, m_pvBAFunctionsProcContext);
1433 }
1434
1435 void OnCachePackageBeginFallback(
1436 __in BA_ONCACHEPACKAGEBEGIN_ARGS* pArgs,
1437 __inout BA_ONCACHEPACKAGEBEGIN_RESULTS* pResults
1438 )
1439 {
1440 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONCACHEPACKAGEBEGIN, pArgs, pResults, m_pvBAFunctionsProcContext);
1441 }
1442
1443 void OnCacheAcquireBeginFallback(
1444 __in BA_ONCACHEACQUIREBEGIN_ARGS* pArgs,
1445 __inout BA_ONCACHEACQUIREBEGIN_RESULTS* pResults
1446 )
1447 {
1448 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONCACHEACQUIREBEGIN, pArgs, pResults, m_pvBAFunctionsProcContext);
1449 }
1450
1451 void OnCacheAcquireProgressFallback(
1452 __in BA_ONCACHEACQUIREPROGRESS_ARGS* pArgs,
1453 __inout BA_ONCACHEACQUIREPROGRESS_RESULTS* pResults
1454 )
1455 {
1456 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONCACHEACQUIREPROGRESS, pArgs, pResults, m_pvBAFunctionsProcContext);
1457 }
1458
1459 void OnResolveSourceFallback(
1460 __in BA_ONRESOLVESOURCE_ARGS* pArgs,
1461 __inout BA_ONRESOLVESOURCE_RESULTS* pResults
1462 )
1463 {
1464 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONRESOLVESOURCE, pArgs, pResults, m_pvBAFunctionsProcContext);
1465 }
1466
1467 void OnCacheAcquireCompleteFallback(
1468 __in BA_ONCACHEACQUIRECOMPLETE_ARGS* pArgs,
1469 __inout BA_ONCACHEACQUIRECOMPLETE_RESULTS* pResults
1470 )
1471 {
1472 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONCACHEACQUIRECOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext);
1473 }
1474
1475 void OnCacheVerifyBeginFallback(
1476 __in BA_ONCACHEVERIFYBEGIN_ARGS* pArgs,
1477 __inout BA_ONCACHEVERIFYBEGIN_RESULTS* pResults
1478 )
1479 {
1480 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONCACHEVERIFYBEGIN, pArgs, pResults, m_pvBAFunctionsProcContext);
1481 }
1482
1483 void OnCacheVerifyCompleteFallback(
1484 __in BA_ONCACHEVERIFYCOMPLETE_ARGS* pArgs,
1485 __inout BA_ONCACHEVERIFYCOMPLETE_RESULTS* pResults
1486 )
1487 {
1488 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONCACHEVERIFYCOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext);
1489 }
1490
1491 void OnCachePackageCompleteFallback(
1492 __in BA_ONCACHEPACKAGECOMPLETE_ARGS* pArgs,
1493 __inout BA_ONCACHEPACKAGECOMPLETE_RESULTS* pResults
1494 )
1495 {
1496 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONCACHEPACKAGECOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext);
1497 }
1498
1499 void OnCacheCompleteFallback(
1500 __in BA_ONCACHECOMPLETE_ARGS* pArgs,
1501 __inout BA_ONCACHECOMPLETE_RESULTS* pResults
1502 )
1503 {
1504 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONCACHECOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext);
1505 }
1506
1507 void OnExecuteBeginFallback(
1508 __in BA_ONEXECUTEBEGIN_ARGS* pArgs,
1509 __inout BA_ONEXECUTEBEGIN_RESULTS* pResults
1510 )
1511 {
1512 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONEXECUTEBEGIN, pArgs, pResults, m_pvBAFunctionsProcContext);
1513 }
1514
1515 void OnExecutePackageBeginFallback(
1516 __in BA_ONEXECUTEPACKAGEBEGIN_ARGS* pArgs,
1517 __inout BA_ONEXECUTEPACKAGEBEGIN_RESULTS* pResults
1518 )
1519 {
1520 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONEXECUTEPACKAGEBEGIN, pArgs, pResults, m_pvBAFunctionsProcContext);
1521 }
1522
1523 void OnExecutePatchTargetFallback(
1524 __in BA_ONEXECUTEPATCHTARGET_ARGS* pArgs,
1525 __inout BA_ONEXECUTEPATCHTARGET_RESULTS* pResults
1526 )
1527 {
1528 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONEXECUTEPATCHTARGET, pArgs, pResults, m_pvBAFunctionsProcContext);
1529 }
1530
1531 void OnExecuteProgressFallback(
1532 __in BA_ONEXECUTEPROGRESS_ARGS* pArgs,
1533 __inout BA_ONEXECUTEPROGRESS_RESULTS* pResults
1534 )
1535 {
1536 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONEXECUTEPROGRESS, pArgs, pResults, m_pvBAFunctionsProcContext);
1537 }
1538
1539 void OnExecuteMsiMessageFallback(
1540 __in BA_ONEXECUTEMSIMESSAGE_ARGS* pArgs,
1541 __inout BA_ONEXECUTEMSIMESSAGE_RESULTS* pResults
1542 )
1543 {
1544 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONEXECUTEMSIMESSAGE, pArgs, pResults, m_pvBAFunctionsProcContext);
1545 }
1546
1547 void OnExecuteFilesInUseFallback(
1548 __in BA_ONEXECUTEFILESINUSE_ARGS* pArgs,
1549 __inout BA_ONEXECUTEFILESINUSE_RESULTS* pResults
1550 )
1551 {
1552 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONEXECUTEFILESINUSE, pArgs, pResults, m_pvBAFunctionsProcContext);
1553 }
1554
1555 void OnExecutePackageCompleteFallback(
1556 __in BA_ONEXECUTEPACKAGECOMPLETE_ARGS* pArgs,
1557 __inout BA_ONEXECUTEPACKAGECOMPLETE_RESULTS* pResults
1558 )
1559 {
1560 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONEXECUTEPACKAGECOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext);
1561 }
1562
1563 void OnExecuteCompleteFallback(
1564 __in BA_ONEXECUTECOMPLETE_ARGS* pArgs,
1565 __inout BA_ONEXECUTECOMPLETE_RESULTS* pResults
1566 )
1567 {
1568 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONEXECUTECOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext);
1569 }
1570
1571 void OnUnregisterBeginFallback(
1572 __in BA_ONUNREGISTERBEGIN_ARGS* pArgs,
1573 __inout BA_ONUNREGISTERBEGIN_RESULTS* pResults
1574 )
1575 {
1576 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONUNREGISTERBEGIN, pArgs, pResults, m_pvBAFunctionsProcContext);
1577 }
1578
1579 void OnUnregisterCompleteFallback(
1580 __in BA_ONUNREGISTERCOMPLETE_ARGS* pArgs,
1581 __inout BA_ONUNREGISTERCOMPLETE_RESULTS* pResults
1582 )
1583 {
1584 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONUNREGISTERCOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext);
1585 }
1586
1587 void OnApplyCompleteFallback(
1588 __in BA_ONAPPLYCOMPLETE_ARGS* pArgs,
1589 __inout BA_ONAPPLYCOMPLETE_RESULTS* pResults
1590 )
1591 {
1592 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONAPPLYCOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext);
1593 }
1594
1595 void OnLaunchApprovedExeBeginFallback(
1596 __in BA_ONLAUNCHAPPROVEDEXEBEGIN_ARGS* pArgs,
1597 __inout BA_ONLAUNCHAPPROVEDEXEBEGIN_RESULTS* pResults
1598 )
1599 {
1600 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONLAUNCHAPPROVEDEXEBEGIN, pArgs, pResults, m_pvBAFunctionsProcContext);
1601 }
1602
1603 void OnLaunchApprovedExeCompleteFallback(
1604 __in BA_ONLAUNCHAPPROVEDEXECOMPLETE_ARGS* pArgs,
1605 __inout BA_ONLAUNCHAPPROVEDEXECOMPLETE_RESULTS* pResults
1606 )
1607 {
1608 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONLAUNCHAPPROVEDEXECOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext);
1609 }
1610
1611 //
1612 // UiThreadProc - entrypoint for UI thread.
1613 //
1614 static DWORD WINAPI UiThreadProc(
1615 __in LPVOID pvContext
1616 )
1617 {
1618 HRESULT hr = S_OK;
1619 CWixStandardBootstrapperApplication* pThis = (CWixStandardBootstrapperApplication*)pvContext;
1620 BOOL fComInitialized = FALSE;
1621 BOOL fRet = FALSE;
1622 MSG msg = { };
1623
1624 // Initialize COM and theme.
1625 hr = ::CoInitialize(NULL);
1626 BalExitOnFailure(hr, "Failed to initialize COM.");
1627 fComInitialized = TRUE;
1628
1629 hr = ThemeInitialize(pThis->m_hModule);
1630 BalExitOnFailure(hr, "Failed to initialize theme manager.");
1631
1632 hr = pThis->InitializeData();
1633 BalExitOnFailure(hr, "Failed to initialize data in bootstrapper application.");
1634
1635 // Create main window.
1636 pThis->InitializeTaskbarButton();
1637 hr = pThis->CreateMainWindow();
1638 BalExitOnFailure(hr, "Failed to create main window.");
1639
1640 if (FAILED(pThis->m_hrFinal))
1641 {
1642 pThis->SetState(WIXSTDBA_STATE_FAILED, hr);
1643 ::PostMessageW(pThis->m_hWnd, WM_WIXSTDBA_SHOW_FAILURE, 0, 0);
1644 }
1645 else
1646 {
1647 // Okay, we're ready for packages now.
1648 pThis->SetState(WIXSTDBA_STATE_INITIALIZED, hr);
1649 ::PostMessageW(pThis->m_hWnd, BOOTSTRAPPER_ACTION_HELP == pThis->m_command.action ? WM_WIXSTDBA_SHOW_HELP : WM_WIXSTDBA_DETECT_PACKAGES, 0, 0);
1650 }
1651
1652 // message pump
1653 while (0 != (fRet = ::GetMessageW(&msg, NULL, 0, 0)))
1654 {
1655 if (-1 == fRet)
1656 {
1657 hr = E_UNEXPECTED;
1658 BalExitOnFailure(hr, "Unexpected return value from message pump.");
1659 }
1660 else if (!ThemeHandleKeyboardMessage(pThis->m_pTheme, msg.hwnd, &msg))
1661 {
1662 ::TranslateMessage(&msg);
1663 ::DispatchMessageW(&msg);
1664 }
1665 }
1666
1667 // Succeeded thus far, check to see if anything went wrong while actually
1668 // executing changes.
1669 if (FAILED(pThis->m_hrFinal))
1670 {
1671 hr = pThis->m_hrFinal;
1672 }
1673 else if (pThis->CheckCanceled())
1674 {
1675 hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
1676 }
1677
1678 LExit:
1679 // destroy main window
1680 pThis->DestroyMainWindow();
1681
1682 // initiate engine shutdown
1683 DWORD dwQuit = HRESULT_CODE(hr);
1684 if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == pThis->m_restartResult)
1685 {
1686 dwQuit = ERROR_SUCCESS_REBOOT_INITIATED;
1687 }
1688 else if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == pThis->m_restartResult)
1689 {
1690 dwQuit = ERROR_SUCCESS_REBOOT_REQUIRED;
1691 }
1692 pThis->m_pEngine->Quit(dwQuit);
1693
1694 ReleaseTheme(pThis->m_pTheme);
1695 ThemeUninitialize();
1696
1697 // uninitialize COM
1698 if (fComInitialized)
1699 {
1700 ::CoUninitialize();
1701 }
1702
1703 return hr;
1704 }
1705
1706
1707 //
1708 // InitializeData - initializes all the package and prerequisite information.
1709 //
1710 HRESULT InitializeData()
1711 {
1712 HRESULT hr = S_OK;
1713 LPWSTR sczModulePath = NULL;
1714 IXMLDOMDocument *pixdManifest = NULL;
1715
1716 hr = BalManifestLoad(m_hModule, &pixdManifest);
1717 BalExitOnFailure(hr, "Failed to load bootstrapper application manifest.");
1718
1719 hr = ParseOverridableVariablesFromXml(pixdManifest);
1720 BalExitOnFailure(hr, "Failed to read overridable variables.");
1721
1722 hr = ProcessCommandLine(&m_sczLanguage);
1723 ExitOnFailure(hr, "Unknown commandline parameters.");
1724
1725 hr = PathRelativeToModule(&sczModulePath, NULL, m_hModule);
1726 BalExitOnFailure(hr, "Failed to get module path.");
1727
1728 hr = LoadLocalization(sczModulePath, m_sczLanguage);
1729 ExitOnFailure(hr, "Failed to load localization.");
1730
1731 hr = LoadTheme(sczModulePath, m_sczLanguage);
1732 ExitOnFailure(hr, "Failed to load theme.");
1733
1734 hr = BalInfoParseFromXml(&m_Bundle, pixdManifest);
1735 BalExitOnFailure(hr, "Failed to load bundle information.");
1736
1737 hr = BalConditionsParseFromXml(&m_Conditions, pixdManifest, m_pWixLoc);
1738 BalExitOnFailure(hr, "Failed to load conditions from XML.");
1739
1740 hr = LoadBAFunctions(pixdManifest);
1741 BalExitOnFailure(hr, "Failed to load bootstrapper functions.");
1742
1743 GetBundleFileVersion();
1744 // don't fail if we couldn't get the version info; best-effort only
1745
1746 if (m_fPrereq)
1747 {
1748 hr = ParsePrerequisiteInformationFromXml(pixdManifest);
1749 BalExitOnFailure(hr, "Failed to read prerequisite information.");
1750 }
1751 else
1752 {
1753 hr = ParseBootstrapperApplicationDataFromXml(pixdManifest);
1754 BalExitOnFailure(hr, "Failed to read bootstrapper application data.");
1755 }
1756
1757 LExit:
1758 ReleaseObject(pixdManifest);
1759 ReleaseStr(sczModulePath);
1760
1761 return hr;
1762 }
1763
1764
1765 //
1766 // ProcessCommandLine - process the provided command line arguments.
1767 //
1768 HRESULT ProcessCommandLine(
1769 __inout LPWSTR* psczLanguage
1770 )
1771 {
1772 HRESULT hr = S_OK;
1773 int argc = 0;
1774 LPWSTR* argv = NULL;
1775 LPWSTR sczVariableName = NULL;
1776 LPWSTR sczVariableValue = NULL;
1777
1778 if (m_command.wzCommandLine && *m_command.wzCommandLine)
1779 {
1780 hr = AppParseCommandLine(m_command.wzCommandLine, &argc, &argv);
1781 ExitOnFailure(hr, "Failed to parse command line.");
1782
1783 for (int i = 0; i < argc; ++i)
1784 {
1785 if (argv[i][0] == L'-' || argv[i][0] == L'/')
1786 {
1787 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"lang", -1))
1788 {
1789 if (i + 1 >= argc)
1790 {
1791 hr = E_INVALIDARG;
1792 BalExitOnFailure(hr, "Must specify a language.");
1793 }
1794
1795 ++i;
1796
1797 hr = StrAllocString(psczLanguage, &argv[i][0], 0);
1798 BalExitOnFailure(hr, "Failed to copy language.");
1799 }
1800 }
1801 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"cache", -1))
1802 {
1803 m_plannedAction = BOOTSTRAPPER_ACTION_CACHE;
1804 }
1805 else if (m_sdOverridableVariables)
1806 {
1807 const wchar_t* pwc = wcschr(argv[i], L'=');
1808 if (pwc)
1809 {
1810 hr = StrAllocString(&sczVariableName, argv[i], pwc - argv[i]);
1811 BalExitOnFailure(hr, "Failed to copy variable name.");
1812
1813 hr = DictKeyExists(m_sdOverridableVariables, sczVariableName);
1814 if (E_NOTFOUND == hr)
1815 {
1816 BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Ignoring attempt to set non-overridable variable: '%ls'.", sczVariableName);
1817 hr = S_OK;
1818 continue;
1819 }
1820 ExitOnFailure(hr, "Failed to check the dictionary of overridable variables.");
1821
1822 hr = StrAllocString(&sczVariableValue, ++pwc, 0);
1823 BalExitOnFailure(hr, "Failed to copy variable value.");
1824
1825 hr = m_pEngine->SetVariableString(sczVariableName, sczVariableValue);
1826 BalExitOnFailure(hr, "Failed to set variable.");
1827 }
1828 else
1829 {
1830 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Ignoring unknown argument: %ls", argv[i]);
1831 }
1832 }
1833 }
1834 }
1835
1836 LExit:
1837 if (argv)
1838 {
1839 AppFreeCommandLineArgs(argv);
1840 }
1841
1842 ReleaseStr(sczVariableName);
1843 ReleaseStr(sczVariableValue);
1844
1845 return hr;
1846 }
1847
1848 HRESULT LoadLocalization(
1849 __in_z LPCWSTR wzModulePath,
1850 __in_z_opt LPCWSTR wzLanguage
1851 )
1852 {
1853 HRESULT hr = S_OK;
1854 LPWSTR sczLocPath = NULL;
1855 LPWSTR sczFormatted = NULL;
1856 LPCWSTR wzLocFileName = m_fPrereq ? L"mbapreq.wxl" : L"thm.wxl";
1857
1858 // Find and load .wxl file.
1859 hr = LocProbeForFile(wzModulePath, wzLocFileName, wzLanguage, &sczLocPath);
1860 BalExitOnFailure(hr, "Failed to probe for loc file: %ls in path: %ls", wzLocFileName, wzModulePath);
1861
1862 hr = LocLoadFromFile(sczLocPath, &m_pWixLoc);
1863 BalExitOnFailure(hr, "Failed to load loc file from path: %ls", sczLocPath);
1864
1865 // Set WixStdBALanguageId to .wxl language id.
1866 if (WIX_LOCALIZATION_LANGUAGE_NOT_SET != m_pWixLoc->dwLangId)
1867 {
1868 ::SetThreadLocale(m_pWixLoc->dwLangId);
1869
1870 hr = m_pEngine->SetVariableNumeric(WIXSTDBA_VARIABLE_LANGUAGE_ID, m_pWixLoc->dwLangId);
1871 BalExitOnFailure(hr, "Failed to set WixStdBALanguageId variable.");
1872 }
1873
1874 // Load ConfirmCancelMessage.
1875 hr = StrAllocString(&m_sczConfirmCloseMessage, L"#(loc.ConfirmCancelMessage)", 0);
1876 ExitOnFailure(hr, "Failed to initialize confirm message loc identifier.");
1877
1878 hr = LocLocalizeString(m_pWixLoc, &m_sczConfirmCloseMessage);
1879 BalExitOnFailure(hr, "Failed to localize confirm close message: %ls", m_sczConfirmCloseMessage);
1880
1881 hr = BalFormatString(m_sczConfirmCloseMessage, &sczFormatted);
1882 if (SUCCEEDED(hr))
1883 {
1884 ReleaseStr(m_sczConfirmCloseMessage);
1885 m_sczConfirmCloseMessage = sczFormatted;
1886 sczFormatted = NULL;
1887 }
1888
1889 LExit:
1890 ReleaseStr(sczFormatted);
1891 ReleaseStr(sczLocPath);
1892
1893 return hr;
1894 }
1895
1896
1897 HRESULT LoadTheme(
1898 __in_z LPCWSTR wzModulePath,
1899 __in_z_opt LPCWSTR wzLanguage
1900 )
1901 {
1902 HRESULT hr = S_OK;
1903 LPWSTR sczThemePath = NULL;
1904 LPCWSTR wzThemeFileName = m_fPrereq ? L"mbapreq.thm" : L"thm.xml";
1905
1906 hr = LocProbeForFile(wzModulePath, wzThemeFileName, wzLanguage, &sczThemePath);
1907 BalExitOnFailure(hr, "Failed to probe for theme file: %ls in path: %ls", wzThemeFileName, wzModulePath);
1908
1909 hr = ThemeLoadFromFile(sczThemePath, &m_pTheme);
1910 BalExitOnFailure(hr, "Failed to load theme from path: %ls", sczThemePath);
1911
1912 hr = ThemeRegisterVariableCallbacks(m_pTheme, EvaluateVariableConditionCallback, FormatVariableStringCallback, GetVariableNumericCallback, SetVariableNumericCallback, GetVariableStringCallback, SetVariableStringCallback, NULL);
1913 BalExitOnFailure(hr, "Failed to register variable theme callbacks.");
1914
1915 hr = ThemeLocalize(m_pTheme, m_pWixLoc);
1916 BalExitOnFailure(hr, "Failed to localize theme: %ls", sczThemePath);
1917
1918 LExit:
1919 ReleaseStr(sczThemePath);
1920
1921 return hr;
1922 }
1923
1924
1925 HRESULT ParseOverridableVariablesFromXml(
1926 __in IXMLDOMDocument* pixdManifest
1927 )
1928 {
1929 HRESULT hr = S_OK;
1930 IXMLDOMNode* pNode = NULL;
1931 IXMLDOMNodeList* pNodes = NULL;
1932 DWORD cNodes = 0;
1933 LPWSTR scz = NULL;
1934
1935 // Get the list of variables users can override on the command line.
1936 hr = XmlSelectNodes(pixdManifest, L"/BootstrapperApplicationData/WixStdbaOverridableVariable", &pNodes);
1937 if (S_FALSE == hr)
1938 {
1939 ExitFunction1(hr = S_OK);
1940 }
1941 ExitOnFailure(hr, "Failed to select overridable variable nodes.");
1942
1943 hr = pNodes->get_length((long*)&cNodes);
1944 ExitOnFailure(hr, "Failed to get overridable variable node count.");
1945
1946 if (cNodes)
1947 {
1948 hr = DictCreateStringList(&m_sdOverridableVariables, 32, DICT_FLAG_NONE);
1949 ExitOnFailure(hr, "Failed to create the string dictionary.");
1950
1951 for (DWORD i = 0; i < cNodes; ++i)
1952 {
1953 hr = XmlNextElement(pNodes, &pNode, NULL);
1954 ExitOnFailure(hr, "Failed to get next node.");
1955
1956 // @Name
1957 hr = XmlGetAttributeEx(pNode, L"Name", &scz);
1958 ExitOnFailure(hr, "Failed to get @Name.");
1959
1960 hr = DictAddKey(m_sdOverridableVariables, scz);
1961 ExitOnFailure(hr, "Failed to add \"%ls\" to the string dictionary.", scz);
1962
1963 // prepare next iteration
1964 ReleaseNullObject(pNode);
1965 }
1966 }
1967
1968 LExit:
1969 ReleaseObject(pNode);
1970 ReleaseObject(pNodes);
1971 ReleaseStr(scz);
1972 return hr;
1973 }
1974
1975
1976 HRESULT ParsePrerequisiteInformationFromXml(
1977 __in IXMLDOMDocument* pixdManifest
1978 )
1979 {
1980 HRESULT hr = S_OK;
1981 IXMLDOMNode* pNode = NULL;
1982 IXMLDOMNodeList* pNodes = NULL;
1983 DWORD cNodes = 0;
1984 LPWSTR scz = NULL;
1985 WIXSTDBA_PREREQ_PACKAGE* pPrereqPackage = NULL;
1986 BAL_INFO_PACKAGE* pPackage = NULL;
1987
1988 hr = XmlSelectNodes(pixdManifest, L"/BootstrapperApplicationData/WixMbaPrereqInformation", &pNodes);
1989 if (S_FALSE == hr)
1990 {
1991 hr = E_INVALIDARG;
1992 BalExitOnFailure(hr, "BootstrapperApplication.xml manifest is missing prerequisite information.");
1993 }
1994 BalExitOnFailure(hr, "Failed to select prerequisite information nodes.");
1995
1996 hr = pNodes->get_length((long*)&cNodes);
1997 BalExitOnFailure(hr, "Failed to get prerequisite information node count.");
1998
1999 m_cPrereqPackages = cNodes;
2000 m_rgPrereqPackages = static_cast<WIXSTDBA_PREREQ_PACKAGE*>(MemAlloc(sizeof(WIXSTDBA_PREREQ_PACKAGE) * m_cPrereqPackages, TRUE));
2001
2002 hr = DictCreateWithEmbeddedKey(&m_shPrereqSupportPackages, m_cPrereqPackages, reinterpret_cast<void **>(&m_rgPrereqPackages), offsetof(WIXSTDBA_PREREQ_PACKAGE, sczPackageId), DICT_FLAG_NONE);
2003 BalExitOnFailure(hr, "Failed to create the prerequisite package dictionary.");
2004
2005 for (DWORD i = 0; i < cNodes; ++i)
2006 {
2007 hr = XmlNextElement(pNodes, &pNode, NULL);
2008 BalExitOnFailure(hr, "Failed to get next node.");
2009
2010 hr = XmlGetAttributeEx(pNode, L"PackageId", &scz);
2011 BalExitOnFailure(hr, "Failed to get @PackageId.");
2012
2013 hr = DictGetValue(m_shPrereqSupportPackages, scz, reinterpret_cast<void **>(&pPrereqPackage));
2014 if (SUCCEEDED(hr))
2015 {
2016 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
2017 BalExitOnFailure(hr, "Duplicate prerequisite information: %ls", scz);
2018 }
2019 else if (E_NOTFOUND != hr)
2020 {
2021 BalExitOnFailure(hr, "Failed to check if \"%ls\" was in the prerequisite package dictionary.", scz);
2022 }
2023
2024 hr = BalInfoFindPackageById(&m_Bundle.packages, scz, &pPackage);
2025 BalExitOnFailure(hr, "Failed to get info about \"%ls\" from BootstrapperApplicationData.", scz);
2026
2027 pPrereqPackage = &m_rgPrereqPackages[i];
2028 pPrereqPackage->sczPackageId = pPackage->sczId;
2029 hr = DictAddValue(m_shPrereqSupportPackages, pPrereqPackage);
2030 BalExitOnFailure(hr, "Failed to add \"%ls\" to the prerequisite package dictionary.", pPrereqPackage->sczPackageId);
2031
2032 hr = XmlGetAttributeEx(pNode, L"LicenseFile", &scz);
2033 if (E_NOTFOUND != hr)
2034 {
2035 BalExitOnFailure(hr, "Failed to get @LicenseFile.");
2036
2037 if (m_sczLicenseFile)
2038 {
2039 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
2040 BalExitOnFailure(hr, "More than one license file specified in prerequisite info.");
2041 }
2042
2043 m_sczLicenseFile = scz;
2044 scz = NULL;
2045 }
2046
2047 hr = XmlGetAttributeEx(pNode, L"LicenseUrl", &scz);
2048 if (E_NOTFOUND != hr)
2049 {
2050 BalExitOnFailure(hr, "Failed to get @LicenseUrl.");
2051
2052 if (m_sczLicenseUrl)
2053 {
2054 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
2055 BalExitOnFailure(hr, "More than one license URL specified in prerequisite info.");
2056 }
2057
2058 m_sczLicenseUrl = scz;
2059 scz = NULL;
2060 }
2061
2062 // Prepare next iteration.
2063 ReleaseNullObject(pNode);
2064 }
2065
2066 LExit:
2067 ReleaseObject(pNode);
2068 ReleaseObject(pNodes);
2069 ReleaseStr(scz);
2070 return hr;
2071 }
2072
2073
2074 HRESULT ParseBootstrapperApplicationDataFromXml(
2075 __in IXMLDOMDocument* pixdManifest
2076 )
2077 {
2078 HRESULT hr = S_OK;
2079 IXMLDOMNode* pNode = NULL;
2080 DWORD dwBool = 0;
2081
2082 hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixStdbaInformation", &pNode);
2083 if (S_FALSE == hr)
2084 {
2085 hr = E_INVALIDARG;
2086 }
2087 BalExitOnFailure(hr, "BootstrapperApplication.xml manifest is missing wixstdba information.");
2088
2089 hr = XmlGetAttributeEx(pNode, L"LicenseFile", &m_sczLicenseFile);
2090 if (E_NOTFOUND == hr)
2091 {
2092 hr = S_OK;
2093 }
2094 BalExitOnFailure(hr, "Failed to get license file.");
2095
2096 hr = XmlGetAttributeEx(pNode, L"LicenseUrl", &m_sczLicenseUrl);
2097 if (E_NOTFOUND == hr)
2098 {
2099 hr = S_OK;
2100 }
2101 BalExitOnFailure(hr, "Failed to get license URL.");
2102
2103 ReleaseObject(pNode);
2104
2105 hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixStdbaOptions", &pNode);
2106 if (S_FALSE == hr)
2107 {
2108 ExitFunction1(hr = S_OK);
2109 }
2110 BalExitOnFailure(hr, "Failed to read wixstdba options from BootstrapperApplication.xml manifest.");
2111
2112 hr = XmlGetAttributeNumber(pNode, L"SuppressOptionsUI", &dwBool);
2113 if (S_FALSE == hr)
2114 {
2115 hr = S_OK;
2116 }
2117 else if (SUCCEEDED(hr) && dwBool)
2118 {
2119 hr = BalSetNumericVariable(WIXSTDBA_VARIABLE_SUPPRESS_OPTIONS_UI, 1);
2120 BalExitOnFailure(hr, "Failed to set '%ls' variable.", WIXSTDBA_VARIABLE_SUPPRESS_OPTIONS_UI);
2121 }
2122 BalExitOnFailure(hr, "Failed to get SuppressOptionsUI value.");
2123
2124 dwBool = 0;
2125 hr = XmlGetAttributeNumber(pNode, L"SuppressDowngradeFailure", &dwBool);
2126 if (S_FALSE == hr)
2127 {
2128 hr = S_OK;
2129 }
2130 else if (SUCCEEDED(hr))
2131 {
2132 m_fSuppressDowngradeFailure = 0 < dwBool;
2133 }
2134 BalExitOnFailure(hr, "Failed to get SuppressDowngradeFailure value.");
2135
2136 dwBool = 0;
2137 hr = XmlGetAttributeNumber(pNode, L"SuppressRepair", &dwBool);
2138 if (S_FALSE == hr)
2139 {
2140 hr = S_OK;
2141 }
2142 else if (SUCCEEDED(hr))
2143 {
2144 m_fSuppressRepair = 0 < dwBool;
2145 }
2146 BalExitOnFailure(hr, "Failed to get SuppressRepair value.");
2147
2148 hr = XmlGetAttributeNumber(pNode, L"ShowVersion", &dwBool);
2149 if (S_FALSE == hr)
2150 {
2151 hr = S_OK;
2152 }
2153 else if (SUCCEEDED(hr) && dwBool)
2154 {
2155 hr = BalSetNumericVariable(WIXSTDBA_VARIABLE_SHOW_VERSION, 1);
2156 BalExitOnFailure(hr, "Failed to set '%ls' variable.", WIXSTDBA_VARIABLE_SHOW_VERSION);
2157 }
2158 BalExitOnFailure(hr, "Failed to get ShowVersion value.");
2159
2160 hr = XmlGetAttributeNumber(pNode, L"SupportCacheOnly", &dwBool);
2161 if (S_FALSE == hr)
2162 {
2163 hr = S_OK;
2164 }
2165 else if (SUCCEEDED(hr))
2166 {
2167 m_fSupportCacheOnly = 0 < dwBool;
2168 }
2169 BalExitOnFailure(hr, "Failed to get SupportCacheOnly value.");
2170
2171 LExit:
2172 ReleaseObject(pNode);
2173 return hr;
2174 }
2175
2176 HRESULT GetPrereqPackage(
2177 __in_z LPCWSTR wzPackageId,
2178 __out WIXSTDBA_PREREQ_PACKAGE** ppPrereqPackage,
2179 __out BAL_INFO_PACKAGE** ppPackage
2180 )
2181 {
2182 HRESULT hr = E_NOTFOUND;
2183 WIXSTDBA_PREREQ_PACKAGE* pPrereqPackage = NULL;
2184 BAL_INFO_PACKAGE* pPackage = NULL;
2185
2186 Assert(wzPackageId && *wzPackageId);
2187 Assert(ppPackage);
2188 Assert(ppPrereqPackage);
2189
2190 if (m_shPrereqSupportPackages)
2191 {
2192 hr = DictGetValue(m_shPrereqSupportPackages, wzPackageId, reinterpret_cast<void **>(&pPrereqPackage));
2193 if (E_NOTFOUND != hr)
2194 {
2195 ExitOnFailure(hr, "Failed to check the dictionary of prerequisite packages.");
2196
2197 // Ignore error.
2198 BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);
2199 }
2200 }
2201
2202 if (pPrereqPackage)
2203 {
2204 *ppPrereqPackage = pPrereqPackage;
2205 *ppPackage = pPackage;
2206 }
2207 LExit:
2208 return hr;
2209 }
2210
2211
2212 //
2213 // Get the file version of the bootstrapper and record in bootstrapper log file
2214 //
2215 HRESULT GetBundleFileVersion()
2216 {
2217 HRESULT hr = S_OK;
2218 ULARGE_INTEGER uliVersion = { };
2219 LPWSTR sczCurrentPath = NULL;
2220
2221 hr = PathForCurrentProcess(&sczCurrentPath, NULL);
2222 BalExitOnFailure(hr, "Failed to get bundle path.");
2223
2224 hr = FileVersion(sczCurrentPath, &uliVersion.HighPart, &uliVersion.LowPart);
2225 BalExitOnFailure(hr, "Failed to get bundle file version.");
2226
2227 hr = m_pEngine->SetVariableVersion(WIXSTDBA_VARIABLE_BUNDLE_FILE_VERSION, uliVersion.QuadPart);
2228 BalExitOnFailure(hr, "Failed to set WixBundleFileVersion variable.");
2229
2230 LExit:
2231 ReleaseStr(sczCurrentPath);
2232
2233 return hr;
2234 }
2235
2236
2237 //
2238 // CreateMainWindow - creates the main install window.
2239 //
2240 HRESULT CreateMainWindow()
2241 {
2242 HRESULT hr = S_OK;
2243 HICON hIcon = reinterpret_cast<HICON>(m_pTheme->hIcon);
2244 WNDCLASSW wc = { };
2245 DWORD dwWindowStyle = 0;
2246 int x = CW_USEDEFAULT;
2247 int y = CW_USEDEFAULT;
2248 POINT ptCursor = { };
2249 HMONITOR hMonitor = NULL;
2250 MONITORINFO mi = { };
2251
2252 // If the theme did not provide an icon, try using the icon from the bundle engine.
2253 if (!hIcon)
2254 {
2255 HMODULE hBootstrapperEngine = ::GetModuleHandleW(NULL);
2256 if (hBootstrapperEngine)
2257 {
2258 hIcon = ::LoadIconW(hBootstrapperEngine, MAKEINTRESOURCEW(1));
2259 }
2260 }
2261
2262 // Register the window class and create the window.
2263 wc.lpfnWndProc = CWixStandardBootstrapperApplication::WndProc;
2264 wc.hInstance = m_hModule;
2265 wc.hIcon = hIcon;
2266 wc.hCursor = ::LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
2267 wc.hbrBackground = m_pTheme->rgFonts[m_pTheme->dwFontId].hBackground;
2268 wc.lpszMenuName = NULL;
2269 wc.lpszClassName = WIXSTDBA_WINDOW_CLASS;
2270 if (!::RegisterClassW(&wc))
2271 {
2272 ExitWithLastError(hr, "Failed to register window.");
2273 }
2274
2275 m_fRegistered = TRUE;
2276
2277 // Calculate the window style based on the theme style and command display value.
2278 dwWindowStyle = m_pTheme->dwStyle;
2279 if (BOOTSTRAPPER_DISPLAY_NONE >= m_command.display)
2280 {
2281 dwWindowStyle &= ~WS_VISIBLE;
2282 }
2283
2284 // Don't show the window if there is a splash screen (it will be made visible when the splash screen is hidden)
2285 if (::IsWindow(m_command.hwndSplashScreen))
2286 {
2287 dwWindowStyle &= ~WS_VISIBLE;
2288 }
2289
2290 // Center the window on the monitor with the mouse.
2291 if (::GetCursorPos(&ptCursor))
2292 {
2293 hMonitor = ::MonitorFromPoint(ptCursor, MONITOR_DEFAULTTONEAREST);
2294 if (hMonitor)
2295 {
2296 mi.cbSize = sizeof(mi);
2297 if (::GetMonitorInfoW(hMonitor, &mi))
2298 {
2299 x = mi.rcWork.left + (mi.rcWork.right - mi.rcWork.left - m_pTheme->nWidth) / 2;
2300 y = mi.rcWork.top + (mi.rcWork.bottom - mi.rcWork.top - m_pTheme->nHeight) / 2;
2301 }
2302 }
2303 }
2304
2305 m_hWnd = ::CreateWindowExW(0, wc.lpszClassName, m_pTheme->sczCaption, dwWindowStyle, x, y, m_pTheme->nWidth, m_pTheme->nHeight, HWND_DESKTOP, NULL, m_hModule, this);
2306 ExitOnNullWithLastError(m_hWnd, hr, "Failed to create window.");
2307
2308 hr = S_OK;
2309
2310 LExit:
2311 return hr;
2312 }
2313
2314
2315 //
2316 // InitializeTaskbarButton - initializes taskbar button for progress.
2317 //
2318 void InitializeTaskbarButton()
2319 {
2320 HRESULT hr = S_OK;
2321
2322 hr = ::CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_ALL, __uuidof(ITaskbarList3), reinterpret_cast<LPVOID*>(&m_pTaskbarList));
2323 if (REGDB_E_CLASSNOTREG == hr) // not supported before Windows 7
2324 {
2325 ExitFunction1(hr = S_OK);
2326 }
2327 BalExitOnFailure(hr, "Failed to create ITaskbarList3. Continuing.");
2328
2329 m_uTaskbarButtonCreatedMessage = ::RegisterWindowMessageW(L"TaskbarButtonCreated");
2330 BalExitOnNullWithLastError(m_uTaskbarButtonCreatedMessage, hr, "Failed to get TaskbarButtonCreated message. Continuing.");
2331
2332 LExit:
2333 return;
2334 }
2335
2336 //
2337 // DestroyMainWindow - clean up all the window registration.
2338 //
2339 void DestroyMainWindow()
2340 {
2341 if (::IsWindow(m_hWnd))
2342 {
2343 ::DestroyWindow(m_hWnd);
2344 m_hWnd = NULL;
2345 m_fTaskbarButtonOK = FALSE;
2346 }
2347
2348 if (m_fRegistered)
2349 {
2350 ::UnregisterClassW(WIXSTDBA_WINDOW_CLASS, m_hModule);
2351 m_fRegistered = FALSE;
2352 }
2353 }
2354
2355 static LRESULT CallDefaultWndProc(
2356 __in CWixStandardBootstrapperApplication* pBA,
2357 __in HWND hWnd,
2358 __in UINT uMsg,
2359 __in WPARAM wParam,
2360 __in LPARAM lParam
2361 )
2362 {
2363 LRESULT lres = NULL;
2364 THEME* pTheme = NULL;
2365 HRESULT hr = S_OK;
2366 BA_FUNCTIONS_WNDPROC_ARGS wndProcArgs = { };
2367 BA_FUNCTIONS_WNDPROC_RESULTS wndProcResults = { };
2368
2369 if (pBA)
2370 {
2371 pTheme = pBA->m_pTheme;
2372
2373 if (pBA->m_pfnBAFunctionsProc)
2374 {
2375 wndProcArgs.cbSize = sizeof(wndProcArgs);
2376 wndProcArgs.pTheme = pTheme;
2377 wndProcArgs.hWnd = hWnd;
2378 wndProcArgs.uMsg = uMsg;
2379 wndProcArgs.wParam = wParam;
2380 wndProcArgs.lParam = lParam;
2381 wndProcResults.cbSize = sizeof(wndProcResults);
2382
2383 hr = pBA->m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_WNDPROC, &wndProcArgs, &wndProcResults, pBA->m_pvBAFunctionsProcContext);
2384 if (E_NOTIMPL != hr)
2385 {
2386 lres = wndProcResults.lres;
2387 ExitFunction();
2388 }
2389 }
2390 }
2391
2392 lres = ThemeDefWindowProc(pTheme, hWnd, uMsg, wParam, lParam);
2393
2394 LExit:
2395 return lres;
2396 }
2397
2398 //
2399 // WndProc - standard windows message handler.
2400 //
2401 static LRESULT CALLBACK WndProc(
2402 __in HWND hWnd,
2403 __in UINT uMsg,
2404 __in WPARAM wParam,
2405 __in LPARAM lParam
2406 )
2407 {
2408#pragma warning(suppress:4312)
2409 CWixStandardBootstrapperApplication* pBA = reinterpret_cast<CWixStandardBootstrapperApplication*>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA));
2410 BOOL fCancel = FALSE;
2411
2412 switch (uMsg)
2413 {
2414 case WM_NCCREATE:
2415 {
2416 LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
2417 pBA = reinterpret_cast<CWixStandardBootstrapperApplication*>(lpcs->lpCreateParams);
2418#pragma warning(suppress:4244)
2419 ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pBA));
2420 }
2421 break;
2422
2423 case WM_NCDESTROY:
2424 {
2425 LRESULT lres = CallDefaultWndProc(pBA, hWnd, uMsg, wParam, lParam);
2426 ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, 0);
2427 ::PostQuitMessage(0);
2428 return lres;
2429 }
2430
2431 case WM_CREATE:
2432 if (!pBA->OnCreate(hWnd))
2433 {
2434 return -1;
2435 }
2436 break;
2437
2438 case WM_QUERYENDSESSION:
2439 fCancel = true;
2440 pBA->OnSystemShutdown(static_cast<DWORD>(lParam), &fCancel);
2441 return !fCancel;
2442
2443 case WM_CLOSE:
2444 // If the user chose not to close, do *not* let the default window proc handle the message.
2445 if (!pBA->OnClose())
2446 {
2447 return 0;
2448 }
2449 break;
2450
2451 case WM_WIXSTDBA_SHOW_HELP:
2452 pBA->OnShowHelp();
2453 return 0;
2454
2455 case WM_WIXSTDBA_DETECT_PACKAGES:
2456 pBA->OnDetect();
2457 return 0;
2458
2459 case WM_WIXSTDBA_PLAN_PACKAGES:
2460 pBA->OnPlan(static_cast<BOOTSTRAPPER_ACTION>(lParam));
2461 return 0;
2462
2463 case WM_WIXSTDBA_APPLY_PACKAGES:
2464 pBA->OnApply();
2465 return 0;
2466
2467 case WM_WIXSTDBA_CHANGE_STATE:
2468 pBA->OnChangeState(static_cast<WIXSTDBA_STATE>(lParam));
2469 return 0;
2470
2471 case WM_WIXSTDBA_SHOW_FAILURE:
2472 pBA->OnShowFailure();
2473 return 0;
2474
2475 case WM_COMMAND:
2476 switch (HIWORD(wParam))
2477 {
2478 case BN_CLICKED:
2479 switch (LOWORD(wParam))
2480 {
2481 case WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX:
2482 pBA->OnClickAcceptCheckbox();
2483 return 0;
2484
2485 case WIXSTDBA_CONTROL_INSTALL_BUTTON:
2486 pBA->OnClickInstallButton();
2487 return 0;
2488
2489 case WIXSTDBA_CONTROL_REPAIR_BUTTON:
2490 pBA->OnClickRepairButton();
2491 return 0;
2492
2493 case WIXSTDBA_CONTROL_UNINSTALL_BUTTON:
2494 pBA->OnClickUninstallButton();
2495 return 0;
2496
2497 case WIXSTDBA_CONTROL_LAUNCH_BUTTON:
2498 pBA->OnClickLaunchButton();
2499 return 0;
2500
2501 case WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON: __fallthrough;
2502 case WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON:
2503 pBA->OnClickRestartButton();
2504 return 0;
2505
2506 case WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON:
2507 pBA->OnClickCloseButton();
2508 return 0;
2509 }
2510 break;
2511 }
2512 break;
2513
2514 case WM_NOTIFY:
2515 if (lParam)
2516 {
2517 LPNMHDR pnmhdr = reinterpret_cast<LPNMHDR>(lParam);
2518 switch (pnmhdr->code)
2519 {
2520 case NM_CLICK: __fallthrough;
2521 case NM_RETURN:
2522 switch (static_cast<DWORD>(pnmhdr->idFrom))
2523 {
2524 case WIXSTDBA_CONTROL_EULA_LINK:
2525 pBA->OnClickEulaLink();
2526 return 1;
2527 case WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK:
2528 pBA->OnClickLogFileLink();
2529 return 1;
2530 }
2531 }
2532 }
2533 break;
2534 }
2535
2536 if (pBA && pBA->m_pTaskbarList && uMsg == pBA->m_uTaskbarButtonCreatedMessage)
2537 {
2538 pBA->m_fTaskbarButtonOK = TRUE;
2539 return 0;
2540 }
2541
2542 return CallDefaultWndProc(pBA, hWnd, uMsg, wParam, lParam);
2543 }
2544
2545
2546 //
2547 // OnCreate - finishes loading the theme.
2548 //
2549 BOOL OnCreate(
2550 __in HWND hWnd
2551 )
2552 {
2553 HRESULT hr = S_OK;
2554 LPWSTR sczLicenseFormatted = NULL;
2555 LPWSTR sczLicensePath = NULL;
2556 LPWSTR sczLicenseDirectory = NULL;
2557 LPWSTR sczLicenseFilename = NULL;
2558 BA_FUNCTIONS_ONTHEMELOADED_ARGS themeLoadedArgs = { };
2559 BA_FUNCTIONS_ONTHEMELOADED_RESULTS themeLoadedResults = { };
2560
2561 hr = ThemeLoadControls(m_pTheme, hWnd, vrgInitControls, countof(vrgInitControls));
2562 BalExitOnFailure(hr, "Failed to load theme controls.");
2563
2564 C_ASSERT(COUNT_WIXSTDBA_PAGE == countof(vrgwzPageNames));
2565 C_ASSERT(countof(m_rgdwPageIds) == countof(vrgwzPageNames));
2566
2567 ThemeGetPageIds(m_pTheme, vrgwzPageNames, m_rgdwPageIds, countof(m_rgdwPageIds));
2568
2569 // Load the RTF EULA control with text if the control exists.
2570 if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_RICHEDIT))
2571 {
2572 hr = (m_sczLicenseFile && *m_sczLicenseFile) ? S_OK : E_INVALIDDATA;
2573 if (SUCCEEDED(hr))
2574 {
2575 hr = StrAllocString(&sczLicenseFormatted, m_sczLicenseFile, 0);
2576 if (SUCCEEDED(hr))
2577 {
2578 hr = LocLocalizeString(m_pWixLoc, &sczLicenseFormatted);
2579 if (SUCCEEDED(hr))
2580 {
2581 // Assume there is no hidden variables to be formatted
2582 // so don't worry about securely freeing it.
2583 hr = BalFormatString(sczLicenseFormatted, &sczLicenseFormatted);
2584 if (SUCCEEDED(hr))
2585 {
2586 hr = PathRelativeToModule(&sczLicensePath, sczLicenseFormatted, m_hModule);
2587 if (SUCCEEDED(hr))
2588 {
2589 hr = PathGetDirectory(sczLicensePath, &sczLicenseDirectory);
2590 if (SUCCEEDED(hr))
2591 {
2592 hr = StrAllocString(&sczLicenseFilename, PathFile(sczLicenseFormatted), 0);
2593 if (SUCCEEDED(hr))
2594 {
2595 hr = LocProbeForFile(sczLicenseDirectory, sczLicenseFilename, m_sczLanguage, &sczLicensePath);
2596 if (SUCCEEDED(hr))
2597 {
2598 hr = ThemeLoadRichEditFromFile(m_pTheme, WIXSTDBA_CONTROL_EULA_RICHEDIT, sczLicensePath, m_hModule);
2599 }
2600 }
2601 }
2602 }
2603 }
2604 }
2605 }
2606 }
2607
2608 if (FAILED(hr))
2609 {
2610 BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Failed to load file into license richedit control from path '%ls' manifest value: %ls", sczLicensePath, m_sczLicenseFile);
2611 hr = S_OK;
2612 }
2613 }
2614
2615 if (m_pfnBAFunctionsProc)
2616 {
2617 themeLoadedArgs.cbSize = sizeof(themeLoadedArgs);
2618 themeLoadedArgs.pTheme = m_pTheme;
2619 themeLoadedArgs.pWixLoc = m_pWixLoc;
2620 themeLoadedResults.cbSize = sizeof(themeLoadedResults);
2621 hr = m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONTHEMELOADED, &themeLoadedArgs, &themeLoadedResults, m_pvBAFunctionsProcContext);
2622 BalExitOnFailure(hr, "BAFunctions OnThemeLoaded failed.");
2623 }
2624
2625 LExit:
2626 ReleaseStr(sczLicenseFilename);
2627 ReleaseStr(sczLicenseDirectory);
2628 ReleaseStr(sczLicensePath);
2629 ReleaseStr(sczLicenseFormatted);
2630
2631 return SUCCEEDED(hr);
2632 }
2633
2634
2635 //
2636 // OnShowFailure - display the failure page.
2637 //
2638 void OnShowFailure()
2639 {
2640 SetState(WIXSTDBA_STATE_FAILED, S_OK);
2641
2642 // If the UI should be visible, display it now and hide the splash screen
2643 if (BOOTSTRAPPER_DISPLAY_NONE < m_command.display)
2644 {
2645 ::ShowWindow(m_pTheme->hwndParent, SW_SHOW);
2646 }
2647
2648 m_pEngine->CloseSplashScreen();
2649
2650 return;
2651 }
2652
2653
2654 //
2655 // OnShowHelp - display the help page.
2656 //
2657 void OnShowHelp()
2658 {
2659 SetState(WIXSTDBA_STATE_HELP, S_OK);
2660
2661 // If the UI should be visible, display it now and hide the splash screen
2662 if (BOOTSTRAPPER_DISPLAY_NONE < m_command.display)
2663 {
2664 ::ShowWindow(m_pTheme->hwndParent, SW_SHOW);
2665 }
2666
2667 m_pEngine->CloseSplashScreen();
2668
2669 return;
2670 }
2671
2672
2673 //
2674 // OnDetect - start the processing of packages.
2675 //
2676 void OnDetect()
2677 {
2678 HRESULT hr = S_OK;
2679
2680 SetState(WIXSTDBA_STATE_DETECTING, hr);
2681
2682 // If the UI should be visible, display it now and hide the splash screen
2683 if (BOOTSTRAPPER_DISPLAY_NONE < m_command.display)
2684 {
2685 ::ShowWindow(m_pTheme->hwndParent, SW_SHOW);
2686 }
2687
2688 m_pEngine->CloseSplashScreen();
2689
2690 // Tell the core we're ready for the packages to be processed now.
2691 hr = m_pEngine->Detect();
2692 BalExitOnFailure(hr, "Failed to start detecting chain.");
2693
2694 LExit:
2695 if (FAILED(hr))
2696 {
2697 SetState(WIXSTDBA_STATE_DETECTING, hr);
2698 }
2699
2700 return;
2701 }
2702
2703
2704 //
2705 // OnPlan - plan the detected changes.
2706 //
2707 void OnPlan(
2708 __in BOOTSTRAPPER_ACTION action
2709 )
2710 {
2711 HRESULT hr = S_OK;
2712
2713 m_plannedAction = action;
2714
2715 // If we are going to apply a downgrade, bail.
2716 if (m_fDowngrading && BOOTSTRAPPER_ACTION_UNINSTALL < action)
2717 {
2718 if (m_fSuppressDowngradeFailure)
2719 {
2720 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "A newer version of this product is installed but downgrade failure has been suppressed; continuing...");
2721 }
2722 else
2723 {
2724 hr = HRESULT_FROM_WIN32(ERROR_PRODUCT_VERSION);
2725 BalExitOnFailure(hr, "Cannot install a product when a newer version is installed.");
2726 }
2727 }
2728
2729 SetState(WIXSTDBA_STATE_PLANNING, hr);
2730
2731 hr = m_pEngine->Plan(action);
2732 BalExitOnFailure(hr, "Failed to start planning packages.");
2733
2734 LExit:
2735 if (FAILED(hr))
2736 {
2737 SetState(WIXSTDBA_STATE_PLANNING, hr);
2738 }
2739
2740 return;
2741 }
2742
2743
2744 //
2745 // OnApply - apply the packages.
2746 //
2747 void OnApply()
2748 {
2749 HRESULT hr = S_OK;
2750
2751 SetState(WIXSTDBA_STATE_APPLYING, hr);
2752 SetProgressState(hr);
2753 SetTaskbarButtonProgress(0);
2754
2755 hr = m_pEngine->Apply(m_hWnd);
2756 BalExitOnFailure(hr, "Failed to start applying packages.");
2757
2758 ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, TRUE); // ensure the cancel button is enabled before starting.
2759
2760 LExit:
2761 if (FAILED(hr))
2762 {
2763 SetState(WIXSTDBA_STATE_APPLYING, hr);
2764 }
2765
2766 return;
2767 }
2768
2769
2770 //
2771 // OnChangeState - change state.
2772 //
2773 void OnChangeState(
2774 __in WIXSTDBA_STATE state
2775 )
2776 {
2777 WIXSTDBA_STATE stateOld = m_state;
2778 DWORD dwOldPageId = 0;
2779 DWORD dwNewPageId = 0;
2780 LPWSTR sczText = NULL;
2781 LPWSTR sczUnformattedText = NULL;
2782 LPWSTR sczControlState = NULL;
2783 LPWSTR sczControlName = NULL;
2784
2785 m_state = state;
2786
2787 // If our install is at the end (success or failure) and we're not showing full UI or
2788 // we successfully installed the prerequisite then exit (prompt for restart if required).
2789 if ((WIXSTDBA_STATE_APPLIED <= m_state && BOOTSTRAPPER_DISPLAY_FULL > m_command.display) ||
2790 (WIXSTDBA_STATE_APPLIED == m_state && m_fPrereq))
2791 {
2792 // If a restart was required but we were not automatically allowed to
2793 // accept the reboot then do the prompt.
2794 if (m_fRestartRequired && !m_fAllowRestart)
2795 {
2796 StrAllocFromError(&sczUnformattedText, HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED), NULL);
2797
2798 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);
2799 m_fAllowRestart = (IDOK == nResult);
2800 }
2801
2802 // Quietly exit.
2803 ::PostMessageW(m_hWnd, WM_CLOSE, 0, 0);
2804 }
2805 else // try to change the pages.
2806 {
2807 DeterminePageId(stateOld, &dwOldPageId);
2808 DeterminePageId(m_state, &dwNewPageId);
2809
2810 if (dwOldPageId != dwNewPageId)
2811 {
2812 // Enable disable controls per-page.
2813 if (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == dwNewPageId) // on the "Install" page, ensure the install button is enabled/disabled correctly.
2814 {
2815 LONGLONG llElevated = 0;
2816 if (m_Bundle.fPerMachine)
2817 {
2818 BalGetNumericVariable(WIXBUNDLE_VARIABLE_ELEVATED, &llElevated);
2819 }
2820 ThemeControlElevates(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, (m_Bundle.fPerMachine && !llElevated));
2821
2822 // If the EULA control exists, show it only if a license URL is provided as well.
2823 if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_LINK))
2824 {
2825 BOOL fEulaLink = (m_sczLicenseUrl && *m_sczLicenseUrl);
2826 ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_EULA_LINK, fEulaLink);
2827 ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX, fEulaLink);
2828 }
2829
2830 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);
2831 ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAcceptedLicense);
2832 }
2833 else if (m_rgdwPageIds[WIXSTDBA_PAGE_MODIFY] == dwNewPageId)
2834 {
2835 ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_REPAIR_BUTTON, !m_fSuppressRepair);
2836 }
2837 else if (m_rgdwPageIds[WIXSTDBA_PAGE_SUCCESS] == dwNewPageId) // on the "Success" page, check if the restart or launch button should be enabled.
2838 {
2839 BOOL fShowRestartButton = FALSE;
2840 BOOL fLaunchTargetExists = FALSE;
2841 if (m_fRestartRequired)
2842 {
2843 if (BOOTSTRAPPER_RESTART_PROMPT == m_command.restart)
2844 {
2845 fShowRestartButton = TRUE;
2846 }
2847 }
2848 else if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_LAUNCH_BUTTON))
2849 {
2850 fLaunchTargetExists = BalStringVariableExists(WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH);
2851 }
2852
2853 ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_LAUNCH_BUTTON, fLaunchTargetExists && BOOTSTRAPPER_ACTION_UNINSTALL < m_plannedAction);
2854 ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON, fShowRestartButton);
2855 }
2856 else if (m_rgdwPageIds[WIXSTDBA_PAGE_FAILURE] == dwNewPageId) // on the "Failure" page, show error message and check if the restart button should be enabled.
2857 {
2858 BOOL fShowLogLink = (m_Bundle.sczLogVariable && *m_Bundle.sczLogVariable); // if there is a log file variable then we'll assume the log file exists.
2859 BOOL fShowErrorMessage = FALSE;
2860 BOOL fShowRestartButton = FALSE;
2861
2862 if (FAILED(m_hrFinal))
2863 {
2864 // If we know the failure message, use that.
2865 if (m_sczFailedMessage && *m_sczFailedMessage)
2866 {
2867 StrAllocString(&sczUnformattedText, m_sczFailedMessage, 0);
2868 }
2869 else if (E_MBAHOST_NET452_ON_WIN7RTM == m_hrFinal)
2870 {
2871 HRESULT hr = StrAllocString(&sczUnformattedText, L"#(loc.NET452WIN7RTMErrorMessage)", 0);
2872 if (FAILED(hr))
2873 {
2874 BalLogError(hr, "Failed to initialize NET452WIN7RTMErrorMessage loc identifier.");
2875 }
2876 else
2877 {
2878 hr = LocLocalizeString(m_pWixLoc, &sczUnformattedText);
2879 if (FAILED(hr))
2880 {
2881 BalLogError(hr, "Failed to localize NET452WIN7RTMErrorMessage: %ls", sczUnformattedText);
2882 ReleaseNullStr(sczUnformattedText);
2883 }
2884 }
2885 }
2886 else // try to get the error message from the error code.
2887 {
2888 StrAllocFromError(&sczUnformattedText, m_hrFinal, NULL);
2889 if (!sczUnformattedText || !*sczUnformattedText)
2890 {
2891 StrAllocFromError(&sczUnformattedText, E_FAIL, NULL);
2892 }
2893 }
2894
2895 if (E_WIXSTDBA_CONDITION_FAILED == m_hrFinal)
2896 {
2897 if (sczUnformattedText)
2898 {
2899 StrAllocString(&sczText, sczUnformattedText, 0);
2900 }
2901 }
2902 else if (E_MBAHOST_NET452_ON_WIN7RTM == m_hrFinal)
2903 {
2904 if (sczUnformattedText)
2905 {
2906 BalFormatString(sczUnformattedText, &sczText);
2907 }
2908 }
2909 else
2910 {
2911 StrAllocFormatted(&sczText, L"0x%08x - %ls", m_hrFinal, sczUnformattedText);
2912 }
2913
2914 ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, sczText);
2915 fShowErrorMessage = TRUE;
2916 }
2917
2918 if (m_fRestartRequired)
2919 {
2920 if (BOOTSTRAPPER_RESTART_PROMPT == m_command.restart)
2921 {
2922 fShowRestartButton = TRUE;
2923 }
2924 }
2925
2926 ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK, fShowLogLink);
2927 ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, fShowErrorMessage);
2928 ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON, fShowRestartButton);
2929 }
2930
2931 HRESULT hr = ThemeShowPage(m_pTheme, dwOldPageId, SW_HIDE);
2932 if (FAILED(hr))
2933 {
2934 BalLogError(hr, "Failed to hide page: %u", dwOldPageId);
2935 }
2936
2937 hr = ThemeShowPage(m_pTheme, dwNewPageId, SW_SHOW);
2938 if (FAILED(hr))
2939 {
2940 BalLogError(hr, "Failed to show page: %u", dwOldPageId);
2941 }
2942
2943 // On the install page set the focus to the install button or the next enabled control if install is disabled.
2944 if (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == dwNewPageId)
2945 {
2946 ThemeSetFocus(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON);
2947 }
2948 }
2949 }
2950
2951 ReleaseStr(sczText);
2952 ReleaseStr(sczUnformattedText);
2953 ReleaseStr(sczControlState);
2954 ReleaseStr(sczControlName);
2955 }
2956
2957
2958 //
2959 // OnClose - called when the window is trying to be closed.
2960 //
2961 BOOL OnClose()
2962 {
2963 BOOL fClose = FALSE;
2964 BOOL fCancel = FALSE;
2965
2966 // If we've already succeeded or failed or showing the help page, just close (prompts are annoying if the bootstrapper is done).
2967 if (WIXSTDBA_STATE_APPLIED <= m_state || WIXSTDBA_STATE_HELP == m_state)
2968 {
2969 fClose = TRUE;
2970 }
2971 else // prompt the user or force the cancel if there is no UI.
2972 {
2973 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);
2974 fCancel = fClose;
2975 }
2976
2977 // If we're doing progress then we never close, we just cancel to let rollback occur.
2978 if (WIXSTDBA_STATE_APPLYING <= m_state && WIXSTDBA_STATE_APPLIED > m_state)
2979 {
2980 // If we canceled, disable cancel button since clicking it again is silly.
2981 if (fClose)
2982 {
2983 ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, FALSE);
2984 }
2985
2986 fClose = FALSE;
2987 }
2988
2989 if (fClose)
2990 {
2991 DWORD dwCurrentPageId = 0;
2992 DeterminePageId(m_state, &dwCurrentPageId);
2993
2994 // Hide the current page to let thmutil do its thing with variables.
2995 ThemeShowPageEx(m_pTheme, dwCurrentPageId, SW_HIDE, fCancel ? THEME_SHOW_PAGE_REASON_CANCEL : THEME_SHOW_PAGE_REASON_DEFAULT);
2996 }
2997
2998 return fClose;
2999 }
3000
3001
3002 //
3003 // OnClickAcceptCheckbox - allow the install to continue.
3004 //
3005 void OnClickAcceptCheckbox()
3006 {
3007 BOOL fAcceptedLicense = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX);
3008 ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAcceptedLicense);
3009 }
3010
3011
3012 //
3013 // OnClickInstallButton - start the install by planning the packages.
3014 //
3015 void OnClickInstallButton()
3016 {
3017 this->OnPlan(BOOTSTRAPPER_ACTION_INSTALL);
3018 }
3019
3020
3021 //
3022 // OnClickRepairButton - start the repair.
3023 //
3024 void OnClickRepairButton()
3025 {
3026 this->OnPlan(BOOTSTRAPPER_ACTION_REPAIR);
3027 }
3028
3029
3030 //
3031 // OnClickUninstallButton - start the uninstall.
3032 //
3033 void OnClickUninstallButton()
3034 {
3035 this->OnPlan(BOOTSTRAPPER_ACTION_UNINSTALL);
3036 }
3037
3038
3039 //
3040 // OnClickCloseButton - close the application.
3041 //
3042 void OnClickCloseButton()
3043 {
3044 ::SendMessageW(m_hWnd, WM_CLOSE, 0, 0);
3045 }
3046
3047
3048 //
3049 // OnClickEulaLink - show the end user license agreement.
3050 //
3051 void OnClickEulaLink()
3052 {
3053 HRESULT hr = S_OK;
3054 LPWSTR sczLicenseUrl = NULL;
3055 LPWSTR sczLicensePath = NULL;
3056 LPWSTR sczLicenseDirectory = NULL;
3057 LPWSTR sczLicenseFilename = NULL;
3058 URI_PROTOCOL protocol = URI_PROTOCOL_UNKNOWN;
3059
3060 hr = StrAllocString(&sczLicenseUrl, m_sczLicenseUrl, 0);
3061 BalExitOnFailure(hr, "Failed to copy license URL: %ls", m_sczLicenseUrl);
3062
3063 hr = LocLocalizeString(m_pWixLoc, &sczLicenseUrl);
3064 BalExitOnFailure(hr, "Failed to localize license URL: %ls", m_sczLicenseUrl);
3065
3066 // Assume there is no hidden variables to be formatted
3067 // so don't worry about securely freeing it.
3068 hr = BalFormatString(sczLicenseUrl, &sczLicenseUrl);
3069 BalExitOnFailure(hr, "Failed to get formatted license URL: %ls", m_sczLicenseUrl);
3070
3071 hr = UriProtocol(sczLicenseUrl, &protocol);
3072 if (FAILED(hr) || URI_PROTOCOL_UNKNOWN == protocol)
3073 {
3074 // Probe for localized license file
3075 hr = PathRelativeToModule(&sczLicensePath, sczLicenseUrl, m_hModule);
3076 if (SUCCEEDED(hr))
3077 {
3078 hr = PathGetDirectory(sczLicensePath, &sczLicenseDirectory);
3079 if (SUCCEEDED(hr))
3080 {
3081 hr = LocProbeForFile(sczLicenseDirectory, PathFile(sczLicenseUrl), m_sczLanguage, &sczLicensePath);
3082 }
3083 }
3084 }
3085
3086 hr = ShelExecUnelevated(sczLicensePath ? sczLicensePath : sczLicenseUrl, NULL, L"open", NULL, SW_SHOWDEFAULT);
3087 BalExitOnFailure(hr, "Failed to launch URL to EULA.");
3088
3089 LExit:
3090 ReleaseStr(sczLicensePath);
3091 ReleaseStr(sczLicenseUrl);
3092 ReleaseStr(sczLicenseDirectory);
3093 ReleaseStr(sczLicenseFilename);
3094
3095 return;
3096 }
3097
3098
3099 //
3100 // OnClickLaunchButton - launch the app from the success page.
3101 //
3102 void OnClickLaunchButton()
3103 {
3104 HRESULT hr = S_OK;
3105 LPWSTR sczUnformattedLaunchTarget = NULL;
3106 LPWSTR sczLaunchTarget = NULL;
3107 LPWSTR sczLaunchTargetElevatedId = NULL;
3108 LPWSTR sczUnformattedArguments = NULL;
3109 LPWSTR sczArguments = NULL;
3110 LPWSTR sczUnformattedLaunchFolder = NULL;
3111 LPWSTR sczLaunchFolder = NULL;
3112 int nCmdShow = SW_SHOWNORMAL;
3113
3114 hr = BalGetStringVariable(WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH, &sczUnformattedLaunchTarget);
3115 BalExitOnFailure(hr, "Failed to get launch target variable '%ls'.", WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH);
3116
3117 hr = BalFormatString(sczUnformattedLaunchTarget, &sczLaunchTarget);
3118 BalExitOnFailure(hr, "Failed to format launch target variable: %ls", sczUnformattedLaunchTarget);
3119
3120 if (BalStringVariableExists(WIXSTDBA_VARIABLE_LAUNCH_TARGET_ELEVATED_ID))
3121 {
3122 hr = BalGetStringVariable(WIXSTDBA_VARIABLE_LAUNCH_TARGET_ELEVATED_ID, &sczLaunchTargetElevatedId);
3123 BalExitOnFailure(hr, "Failed to get launch target elevated id '%ls'.", WIXSTDBA_VARIABLE_LAUNCH_TARGET_ELEVATED_ID);
3124 }
3125
3126 if (BalStringVariableExists(WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS))
3127 {
3128 hr = BalGetStringVariable(WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS, &sczUnformattedArguments);
3129 BalExitOnFailure(hr, "Failed to get launch arguments '%ls'.", WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS);
3130 }
3131
3132 if (BalStringVariableExists(WIXSTDBA_VARIABLE_LAUNCH_HIDDEN))
3133 {
3134 nCmdShow = SW_HIDE;
3135 }
3136
3137 if (BalStringVariableExists(WIXSTDBA_VARIABLE_LAUNCH_WORK_FOLDER))
3138 {
3139 hr = BalGetStringVariable(WIXSTDBA_VARIABLE_LAUNCH_WORK_FOLDER, &sczUnformattedLaunchFolder);
3140 BalExitOnFailure(hr, "Failed to get launch working directory variable '%ls'.", WIXSTDBA_VARIABLE_LAUNCH_WORK_FOLDER);
3141 }
3142
3143 if (sczLaunchTargetElevatedId && !m_fTriedToLaunchElevated)
3144 {
3145 m_fTriedToLaunchElevated = TRUE;
3146 hr = m_pEngine->LaunchApprovedExe(m_hWnd, sczLaunchTargetElevatedId, sczUnformattedArguments, 0);
3147 if (FAILED(hr))
3148 {
3149 BalLogError(hr, "Failed to launch elevated target: %ls", sczLaunchTargetElevatedId);
3150
3151 //try with ShelExec next time
3152 OnClickLaunchButton();
3153 }
3154 }
3155 else
3156 {
3157 if (sczUnformattedArguments)
3158 {
3159 hr = BalFormatString(sczUnformattedArguments, &sczArguments);
3160 BalExitOnFailure(hr, "Failed to format launch arguments variable: %ls", sczUnformattedArguments);
3161 }
3162
3163 if (sczUnformattedLaunchFolder)
3164 {
3165 hr = BalFormatString(sczUnformattedLaunchFolder, &sczLaunchFolder);
3166 BalExitOnFailure(hr, "Failed to format launch working directory variable: %ls", sczUnformattedLaunchFolder);
3167 }
3168
3169 hr = ShelExec(sczLaunchTarget, sczArguments, L"open", sczLaunchFolder, nCmdShow, m_hWnd, NULL);
3170 BalExitOnFailure(hr, "Failed to launch target: %ls", sczLaunchTarget);
3171
3172 ::PostMessageW(m_hWnd, WM_CLOSE, 0, 0);
3173 }
3174
3175 LExit:
3176 StrSecureZeroFreeString(sczLaunchFolder);
3177 ReleaseStr(sczUnformattedLaunchFolder);
3178 StrSecureZeroFreeString(sczArguments);
3179 ReleaseStr(sczUnformattedArguments);
3180 ReleaseStr(sczLaunchTargetElevatedId);
3181 StrSecureZeroFreeString(sczLaunchTarget);
3182 ReleaseStr(sczUnformattedLaunchTarget);
3183
3184 return;
3185 }
3186
3187
3188 //
3189 // OnClickRestartButton - allows the restart and closes the app.
3190 //
3191 void OnClickRestartButton()
3192 {
3193 AssertSz(m_fRestartRequired, "Restart must be requested to be able to click on the restart button.");
3194
3195 m_fAllowRestart = TRUE;
3196 ::SendMessageW(m_hWnd, WM_CLOSE, 0, 0);
3197
3198 return;
3199 }
3200
3201
3202 //
3203 // OnClickLogFileLink - show the log file.
3204 //
3205 void OnClickLogFileLink()
3206 {
3207 HRESULT hr = S_OK;
3208 LPWSTR sczLogFile = NULL;
3209
3210 hr = BalGetStringVariable(m_Bundle.sczLogVariable, &sczLogFile);
3211 BalExitOnFailure(hr, "Failed to get log file variable '%ls'.", m_Bundle.sczLogVariable);
3212
3213 hr = ShelExecUnelevated(L"notepad.exe", sczLogFile, L"open", NULL, SW_SHOWDEFAULT);
3214 BalExitOnFailure(hr, "Failed to open log file target: %ls", sczLogFile);
3215
3216 LExit:
3217 ReleaseStr(sczLogFile);
3218
3219 return;
3220 }
3221
3222
3223 //
3224 // SetState
3225 //
3226 void SetState(
3227 __in WIXSTDBA_STATE state,
3228 __in HRESULT hrStatus
3229 )
3230 {
3231 if (FAILED(hrStatus))
3232 {
3233 m_hrFinal = hrStatus;
3234 }
3235
3236 if (FAILED(m_hrFinal))
3237 {
3238 state = WIXSTDBA_STATE_FAILED;
3239 }
3240
3241 if (m_state < state)
3242 {
3243 ::PostMessageW(m_hWnd, WM_WIXSTDBA_CHANGE_STATE, 0, state);
3244 }
3245 }
3246
3247
3248 void DeterminePageId(
3249 __in WIXSTDBA_STATE state,
3250 __out DWORD* pdwPageId
3251 )
3252 {
3253 if (BOOTSTRAPPER_DISPLAY_PASSIVE == m_command.display)
3254 {
3255 switch (state)
3256 {
3257 case WIXSTDBA_STATE_INITIALIZED:
3258 *pdwPageId = BOOTSTRAPPER_ACTION_HELP == m_command.action ? m_rgdwPageIds[WIXSTDBA_PAGE_HELP] : m_rgdwPageIds[WIXSTDBA_PAGE_LOADING];
3259 break;
3260
3261 case WIXSTDBA_STATE_HELP:
3262 *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_HELP];
3263 break;
3264
3265 case WIXSTDBA_STATE_DETECTING:
3266 *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];
3267 break;
3268
3269 case WIXSTDBA_STATE_DETECTED: __fallthrough;
3270 case WIXSTDBA_STATE_PLANNING: __fallthrough;
3271 case WIXSTDBA_STATE_PLANNED: __fallthrough;
3272 case WIXSTDBA_STATE_APPLYING: __fallthrough;
3273 case WIXSTDBA_STATE_CACHING: __fallthrough;
3274 case WIXSTDBA_STATE_CACHED: __fallthrough;
3275 case WIXSTDBA_STATE_EXECUTING: __fallthrough;
3276 case WIXSTDBA_STATE_EXECUTED:
3277 *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS_PASSIVE] ? m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS_PASSIVE] : m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS];
3278 break;
3279
3280 default:
3281 *pdwPageId = 0;
3282 break;
3283 }
3284 }
3285 else if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display)
3286 {
3287 switch (state)
3288 {
3289 case WIXSTDBA_STATE_INITIALIZING:
3290 *pdwPageId = 0;
3291 break;
3292
3293 case WIXSTDBA_STATE_INITIALIZED:
3294 *pdwPageId = BOOTSTRAPPER_ACTION_HELP == m_command.action ? m_rgdwPageIds[WIXSTDBA_PAGE_HELP] : m_rgdwPageIds[WIXSTDBA_PAGE_LOADING];
3295 break;
3296
3297 case WIXSTDBA_STATE_HELP:
3298 *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_HELP];
3299 break;
3300
3301 case WIXSTDBA_STATE_DETECTING:
3302 *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_LOADING];
3303 break;
3304
3305 case WIXSTDBA_STATE_DETECTED:
3306 switch (m_command.action)
3307 {
3308 case BOOTSTRAPPER_ACTION_INSTALL:
3309 *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL];
3310 break;
3311
3312 case BOOTSTRAPPER_ACTION_MODIFY: __fallthrough;
3313 case BOOTSTRAPPER_ACTION_REPAIR: __fallthrough;
3314 case BOOTSTRAPPER_ACTION_UNINSTALL:
3315 *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_MODIFY];
3316 break;
3317 }
3318 break;
3319
3320 case WIXSTDBA_STATE_PLANNING: __fallthrough;
3321 case WIXSTDBA_STATE_PLANNED: __fallthrough;
3322 case WIXSTDBA_STATE_APPLYING: __fallthrough;
3323 case WIXSTDBA_STATE_CACHING: __fallthrough;
3324 case WIXSTDBA_STATE_CACHED: __fallthrough;
3325 case WIXSTDBA_STATE_EXECUTING: __fallthrough;
3326 case WIXSTDBA_STATE_EXECUTED:
3327 *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS];
3328 break;
3329
3330 case WIXSTDBA_STATE_APPLIED:
3331 *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_SUCCESS];
3332 break;
3333
3334 case WIXSTDBA_STATE_FAILED:
3335 *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_FAILURE];
3336 break;
3337 }
3338 }
3339 }
3340
3341
3342 HRESULT EvaluateConditions()
3343 {
3344 HRESULT hr = S_OK;
3345 BOOL fResult = FALSE;
3346
3347 for (DWORD i = 0; i < m_Conditions.cConditions; ++i)
3348 {
3349 BAL_CONDITION* pCondition = m_Conditions.rgConditions + i;
3350
3351 hr = BalConditionEvaluate(pCondition, m_pEngine, &fResult, &m_sczFailedMessage);
3352 BalExitOnFailure(hr, "Failed to evaluate condition.");
3353
3354 if (!fResult)
3355 {
3356 hr = E_WIXSTDBA_CONDITION_FAILED;
3357 BalExitOnFailure(hr, "%ls", m_sczFailedMessage);
3358 }
3359 }
3360
3361 ReleaseNullStrSecure(m_sczFailedMessage);
3362
3363 LExit:
3364 return hr;
3365 }
3366
3367 void UpdateCacheProgress(
3368 __in DWORD dwOverallPercentage
3369 )
3370 {
3371 WCHAR wzProgress[5] = { };
3372
3373 ::StringCchPrintfW(wzProgress, countof(wzProgress), L"%u%%", dwOverallPercentage);
3374 ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_TEXT, wzProgress);
3375
3376 ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_BAR, dwOverallPercentage);
3377
3378 m_dwCalculatedCacheProgress = dwOverallPercentage * WIXSTDBA_ACQUIRE_PERCENTAGE / 100;
3379 ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress);
3380
3381 SetTaskbarButtonProgress(m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress);
3382 }
3383
3384
3385 void SetTaskbarButtonProgress(
3386 __in DWORD dwOverallPercentage
3387 )
3388 {
3389 HRESULT hr = S_OK;
3390
3391 if (m_fTaskbarButtonOK)
3392 {
3393 hr = m_pTaskbarList->SetProgressValue(m_hWnd, dwOverallPercentage, 100UL);
3394 BalExitOnFailure(hr, "Failed to set taskbar button progress to: %d%%.", dwOverallPercentage);
3395 }
3396
3397 LExit:
3398 return;
3399 }
3400
3401
3402 void SetTaskbarButtonState(
3403 __in TBPFLAG tbpFlags
3404 )
3405 {
3406 HRESULT hr = S_OK;
3407
3408 if (m_fTaskbarButtonOK)
3409 {
3410 hr = m_pTaskbarList->SetProgressState(m_hWnd, tbpFlags);
3411 BalExitOnFailure(hr, "Failed to set taskbar button state.", tbpFlags);
3412 }
3413
3414 LExit:
3415 return;
3416 }
3417
3418
3419 void SetProgressState(
3420 __in HRESULT hrStatus
3421 )
3422 {
3423 TBPFLAG flag = TBPF_NORMAL;
3424
3425 if (IsCanceled() || HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) == hrStatus)
3426 {
3427 flag = TBPF_PAUSED;
3428 }
3429 else if (IsRollingBack() || FAILED(hrStatus))
3430 {
3431 flag = TBPF_ERROR;
3432 }
3433
3434 SetTaskbarButtonState(flag);
3435 }
3436
3437
3438 HRESULT LoadBAFunctions(
3439 __in IXMLDOMDocument* pixdManifest
3440 )
3441 {
3442 HRESULT hr = S_OK;
3443 IXMLDOMNode* pBAFunctionsNode = NULL;
3444 IXMLDOMNode* pPayloadNode = NULL;
3445 LPWSTR sczPayloadId = NULL;
3446 LPWSTR sczPayloadXPath = NULL;
3447 LPWSTR sczBafName = NULL;
3448 LPWSTR sczBafPath = NULL;
3449 BA_FUNCTIONS_CREATE_ARGS bafCreateArgs = { };
3450 BA_FUNCTIONS_CREATE_RESULTS bafCreateResults = { };
3451
3452 hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixBalBAFunctions", &pBAFunctionsNode);
3453 BalExitOnFailure(hr, "Failed to read WixBalBAFunctions node from BootstrapperApplicationData.xml.");
3454
3455 if (S_FALSE == hr)
3456 {
3457 ExitFunction();
3458 }
3459
3460 hr = XmlGetAttributeEx(pBAFunctionsNode, L"PayloadId", &sczPayloadId);
3461 BalExitOnFailure(hr, "Failed to get BAFunctions PayloadId.");
3462
3463 hr = StrAllocFormatted(&sczPayloadXPath, L"/BootstrapperApplicationData/WixPayloadProperties[@Payload='%ls']", sczPayloadId);
3464 BalExitOnFailure(hr, "Failed to format BAFunctions payload XPath.");
3465
3466 hr = XmlSelectSingleNode(pixdManifest, sczPayloadXPath, &pPayloadNode);
3467 if (S_FALSE == hr)
3468 {
3469 hr = E_NOTFOUND;
3470 }
3471 BalExitOnFailure(hr, "Failed to find WixPayloadProperties node for BAFunctions PayloadId: %ls.", sczPayloadId);
3472
3473 hr = XmlGetAttributeEx(pPayloadNode, L"Name", &sczBafName);
3474 BalExitOnFailure(hr, "Failed to get BAFunctions Name.");
3475
3476 hr = PathRelativeToModule(&sczBafPath, sczBafName, m_hModule);
3477 BalExitOnFailure(hr, "Failed to get path to BAFunctions DLL.");
3478
3479 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: LoadBAFunctions() - BAFunctions DLL %ls", sczBafPath);
3480
3481 m_hBAFModule = ::LoadLibraryExW(sczBafPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
3482 BalExitOnNullWithLastError(m_hBAFModule, hr, "WIXSTDBA: LoadBAFunctions() - Failed to load DLL %ls", sczBafPath);
3483
3484 PFN_BA_FUNCTIONS_CREATE pfnBAFunctionsCreate = reinterpret_cast<PFN_BA_FUNCTIONS_CREATE>(::GetProcAddress(m_hBAFModule, "BAFunctionsCreate"));
3485 BalExitOnNullWithLastError(pfnBAFunctionsCreate, hr, "Failed to get BAFunctionsCreate entry-point from: %ls", sczBafPath);
3486
3487 bafCreateArgs.cbSize = sizeof(bafCreateArgs);
3488 bafCreateArgs.qwBAFunctionsAPIVersion = MAKEQWORDVERSION(0, 0, 0, 2); // TODO: need to decide whether to keep this, and if so when to update it.
3489 bafCreateArgs.pBootstrapperCreateArgs = &m_createArgs;
3490
3491 bafCreateResults.cbSize = sizeof(bafCreateResults);
3492
3493 hr = pfnBAFunctionsCreate(&bafCreateArgs, &bafCreateResults);
3494 BalExitOnFailure(hr, "Failed to create BAFunctions.");
3495
3496 m_pfnBAFunctionsProc = bafCreateResults.pfnBAFunctionsProc;
3497 m_pvBAFunctionsProcContext = bafCreateResults.pvBAFunctionsProcContext;
3498
3499 LExit:
3500 if (m_hBAFModule && !m_pfnBAFunctionsProc)
3501 {
3502 ::FreeLibrary(m_hBAFModule);
3503 m_hBAFModule = NULL;
3504 }
3505 ReleaseStr(sczBafPath);
3506 ReleaseStr(sczBafName);
3507 ReleaseStr(sczPayloadXPath);
3508 ReleaseStr(sczPayloadId);
3509 ReleaseObject(pBAFunctionsNode);
3510 ReleaseObject(pPayloadNode);
3511
3512 return hr;
3513 }
3514
3515
3516public:
3517 //
3518 // Constructor - initialize member variables.
3519 //
3520 CWixStandardBootstrapperApplication(
3521 __in HMODULE hModule,
3522 __in BOOL fPrereq,
3523 __in HRESULT hrHostInitialization,
3524 __in IBootstrapperEngine* pEngine,
3525 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs
3526 ) : CBalBaseBootstrapperApplication(pEngine, pArgs, 3, 3000)
3527 {
3528 m_hModule = hModule;
3529 memcpy_s(&m_command, sizeof(m_command), pArgs->pCommand, sizeof(BOOTSTRAPPER_COMMAND));
3530 memcpy_s(&m_createArgs, sizeof(m_createArgs), pArgs, sizeof(BOOTSTRAPPER_CREATE_ARGS));
3531 m_createArgs.pCommand = &m_command;
3532
3533 if (fPrereq)
3534 {
3535 // Pre-req BA should only show help or do an install (to launch the Managed BA which can then do the right action).
3536 if (BOOTSTRAPPER_ACTION_HELP != m_command.action)
3537 {
3538 m_command.action = BOOTSTRAPPER_ACTION_INSTALL;
3539 }
3540 }
3541 else // maybe modify the action state if the bundle is or is not already installed.
3542 {
3543 LONGLONG llInstalled = 0;
3544 HRESULT hr = BalGetNumericVariable(L"WixBundleInstalled", &llInstalled);
3545 if (SUCCEEDED(hr) && BOOTSTRAPPER_RESUME_TYPE_REBOOT != m_command.resumeType && 0 < llInstalled && BOOTSTRAPPER_ACTION_INSTALL == m_command.action)
3546 {
3547 m_command.action = BOOTSTRAPPER_ACTION_MODIFY;
3548 }
3549 else if (0 == llInstalled && (BOOTSTRAPPER_ACTION_MODIFY == m_command.action || BOOTSTRAPPER_ACTION_REPAIR == m_command.action))
3550 {
3551 m_command.action = BOOTSTRAPPER_ACTION_INSTALL;
3552 }
3553 }
3554
3555 m_plannedAction = BOOTSTRAPPER_ACTION_UNKNOWN;
3556
3557 // When resuming from restart doing some install-like operation, try to find the package that forced the
3558 // restart. We'll use this information during planning.
3559 m_sczAfterForcedRestartPackage = NULL;
3560
3561 if (BOOTSTRAPPER_RESUME_TYPE_REBOOT == m_command.resumeType && BOOTSTRAPPER_ACTION_UNINSTALL < m_command.action)
3562 {
3563 // Ensure the forced restart package variable is null when it is an empty string.
3564 HRESULT hr = BalGetStringVariable(L"WixBundleForcedRestartPackage", &m_sczAfterForcedRestartPackage);
3565 if (FAILED(hr) || !m_sczAfterForcedRestartPackage || !*m_sczAfterForcedRestartPackage)
3566 {
3567 ReleaseNullStr(m_sczAfterForcedRestartPackage);
3568 }
3569 }
3570
3571 m_pWixLoc = NULL;
3572 memset(&m_Bundle, 0, sizeof(m_Bundle));
3573 memset(&m_Conditions, 0, sizeof(m_Conditions));
3574 m_sczConfirmCloseMessage = NULL;
3575 m_sczFailedMessage = NULL;
3576
3577 m_sczLanguage = NULL;
3578 m_pTheme = NULL;
3579 memset(m_rgdwPageIds, 0, sizeof(m_rgdwPageIds));
3580 m_hUiThread = NULL;
3581 m_fRegistered = FALSE;
3582 m_hWnd = NULL;
3583
3584 m_state = WIXSTDBA_STATE_INITIALIZING;
3585 m_hrFinal = hrHostInitialization;
3586
3587 m_fDowngrading = FALSE;
3588 m_restartResult = BOOTSTRAPPER_APPLY_RESTART_NONE;
3589 m_fRestartRequired = FALSE;
3590 m_fAllowRestart = FALSE;
3591
3592 m_sczLicenseFile = NULL;
3593 m_sczLicenseUrl = NULL;
3594 m_fSuppressDowngradeFailure = FALSE;
3595 m_fSuppressRepair = FALSE;
3596 m_fSupportCacheOnly = FALSE;
3597
3598 m_sdOverridableVariables = NULL;
3599 m_shPrereqSupportPackages = NULL;
3600 m_rgPrereqPackages = NULL;
3601 m_cPrereqPackages = 0;
3602 m_pTaskbarList = NULL;
3603 m_uTaskbarButtonCreatedMessage = UINT_MAX;
3604 m_fTaskbarButtonOK = FALSE;
3605 m_fShowingInternalUiThisPackage = FALSE;
3606 m_fTriedToLaunchElevated = FALSE;
3607
3608 m_fPrereq = fPrereq;
3609 m_fPrereqInstalled = FALSE;
3610 m_fPrereqAlreadyInstalled = FALSE;
3611
3612 pEngine->AddRef();
3613 m_pEngine = pEngine;
3614
3615 m_hBAFModule = NULL;
3616 m_pfnBAFunctionsProc = NULL;
3617 m_pvBAFunctionsProcContext = NULL;
3618 }
3619
3620
3621 //
3622 // Destructor - release member variables.
3623 //
3624 ~CWixStandardBootstrapperApplication()
3625 {
3626 AssertSz(!::IsWindow(m_hWnd), "Window should have been destroyed before destructor.");
3627 AssertSz(!m_pTheme, "Theme should have been released before destructor.");
3628
3629 ReleaseObject(m_pTaskbarList);
3630 ReleaseDict(m_sdOverridableVariables);
3631 ReleaseDict(m_shPrereqSupportPackages);
3632 ReleaseMem(m_rgPrereqPackages);
3633 ReleaseStr(m_sczFailedMessage);
3634 ReleaseStr(m_sczConfirmCloseMessage);
3635 BalConditionsUninitialize(&m_Conditions);
3636 BalInfoUninitialize(&m_Bundle);
3637 LocFree(m_pWixLoc);
3638
3639 ReleaseStr(m_sczLanguage);
3640 ReleaseStr(m_sczLicenseFile);
3641 ReleaseStr(m_sczLicenseUrl);
3642 ReleaseStr(m_sczAfterForcedRestartPackage);
3643 ReleaseNullObject(m_pEngine);
3644
3645 if (m_hBAFModule)
3646 {
3647 PFN_BA_FUNCTIONS_DESTROY pfnBAFunctionsDestroy = reinterpret_cast<PFN_BA_FUNCTIONS_DESTROY>(::GetProcAddress(m_hBAFModule, "BAFunctionsDestroy"));
3648 if (pfnBAFunctionsDestroy)
3649 {
3650 pfnBAFunctionsDestroy();
3651 }
3652
3653 ::FreeLibrary(m_hBAFModule);
3654 m_hBAFModule = NULL;
3655 }
3656 }
3657
3658private:
3659 HMODULE m_hModule;
3660 BOOTSTRAPPER_CREATE_ARGS m_createArgs;
3661 BOOTSTRAPPER_COMMAND m_command;
3662 IBootstrapperEngine* m_pEngine;
3663 BOOTSTRAPPER_ACTION m_plannedAction;
3664
3665 LPWSTR m_sczAfterForcedRestartPackage;
3666
3667 WIX_LOCALIZATION* m_pWixLoc;
3668 BAL_INFO_BUNDLE m_Bundle;
3669 BAL_CONDITIONS m_Conditions;
3670 LPWSTR m_sczFailedMessage;
3671 LPWSTR m_sczConfirmCloseMessage;
3672
3673 LPWSTR m_sczLanguage;
3674 THEME* m_pTheme;
3675 DWORD m_rgdwPageIds[countof(vrgwzPageNames)];
3676 HANDLE m_hUiThread;
3677 BOOL m_fRegistered;
3678 HWND m_hWnd;
3679
3680 WIXSTDBA_STATE m_state;
3681 HRESULT m_hrFinal;
3682
3683 BOOL m_fStartedExecution;
3684 DWORD m_dwCalculatedCacheProgress;
3685 DWORD m_dwCalculatedExecuteProgress;
3686
3687 BOOL m_fDowngrading;
3688 BOOTSTRAPPER_APPLY_RESTART m_restartResult;
3689 BOOL m_fRestartRequired;
3690 BOOL m_fAllowRestart;
3691
3692 LPWSTR m_sczLicenseFile;
3693 LPWSTR m_sczLicenseUrl;
3694 BOOL m_fSuppressDowngradeFailure;
3695 BOOL m_fSuppressRepair;
3696 BOOL m_fSupportCacheOnly;
3697
3698 STRINGDICT_HANDLE m_sdOverridableVariables;
3699
3700 WIXSTDBA_PREREQ_PACKAGE* m_rgPrereqPackages;
3701 DWORD m_cPrereqPackages;
3702 STRINGDICT_HANDLE m_shPrereqSupportPackages;
3703
3704 BOOL m_fPrereq;
3705 BOOL m_fPrereqInstalled;
3706 BOOL m_fPrereqAlreadyInstalled;
3707
3708 ITaskbarList3* m_pTaskbarList;
3709 UINT m_uTaskbarButtonCreatedMessage;
3710 BOOL m_fTaskbarButtonOK;
3711 BOOL m_fShowingInternalUiThisPackage;
3712 BOOL m_fTriedToLaunchElevated;
3713
3714 HMODULE m_hBAFModule;
3715 PFN_BA_FUNCTIONS_PROC m_pfnBAFunctionsProc;
3716 LPVOID m_pvBAFunctionsProcContext;
3717};
3718
3719
3720//
3721// CreateBootstrapperApplication - creates a new IBootstrapperApplication object.
3722//
3723HRESULT CreateBootstrapperApplication(
3724 __in HMODULE hModule,
3725 __in BOOL fPrereq,
3726 __in HRESULT hrHostInitialization,
3727 __in IBootstrapperEngine* pEngine,
3728 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
3729 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
3730 )
3731{
3732 HRESULT hr = S_OK;
3733 CWixStandardBootstrapperApplication* pApplication = NULL;
3734
3735 pApplication = new CWixStandardBootstrapperApplication(hModule, fPrereq, hrHostInitialization, pEngine, pArgs);
3736 ExitOnNull(pApplication, hr, E_OUTOFMEMORY, "Failed to create new standard bootstrapper application object.");
3737
3738 pResults->pfnBootstrapperApplicationProc = BalBaseBootstrapperApplicationProc;
3739 pResults->pvBootstrapperApplicationProcContext = pApplication;
3740 pApplication = NULL;
3741
3742LExit:
3743 ReleaseObject(pApplication);
3744 return hr;
3745}
3746
3747
3748static HRESULT DAPI EvaluateVariableConditionCallback(
3749 __in_z LPCWSTR wzCondition,
3750 __out BOOL* pf,
3751 __in_opt LPVOID /*pvContext*/
3752 )
3753{
3754 return BalEvaluateCondition(wzCondition, pf);
3755}
3756
3757
3758static HRESULT DAPI FormatVariableStringCallback(
3759 __in_z LPCWSTR wzFormat,
3760 __inout LPWSTR* psczOut,
3761 __in_opt LPVOID /*pvContext*/
3762 )
3763{
3764 return BalFormatString(wzFormat, psczOut);
3765}
3766
3767
3768static HRESULT DAPI GetVariableNumericCallback(
3769 __in_z LPCWSTR wzVariable,
3770 __out LONGLONG* pllValue,
3771 __in_opt LPVOID /*pvContext*/
3772 )
3773{
3774 return BalGetNumericVariable(wzVariable, pllValue);
3775}
3776
3777
3778static HRESULT DAPI SetVariableNumericCallback(
3779 __in_z LPCWSTR wzVariable,
3780 __in LONGLONG llValue,
3781 __in_opt LPVOID /*pvContext*/
3782 )
3783{
3784 return BalSetNumericVariable(wzVariable, llValue);
3785}
3786
3787
3788static HRESULT DAPI GetVariableStringCallback(
3789 __in_z LPCWSTR wzVariable,
3790 __inout LPWSTR* psczValue,
3791 __in_opt LPVOID /*pvContext*/
3792 )
3793{
3794 return BalGetStringVariable(wzVariable, psczValue);
3795}
3796
3797
3798static HRESULT DAPI SetVariableStringCallback(
3799 __in_z LPCWSTR wzVariable,
3800 __in_z_opt LPCWSTR wzValue,
3801 __in_opt LPVOID /*pvContext*/
3802 )
3803{
3804 return BalSetStringVariable(wzVariable, wzValue);
3805}
3806
3807static LPCSTR LoggingRequestStateToString(
3808 __in BOOTSTRAPPER_REQUEST_STATE requestState
3809 )
3810{
3811 switch (requestState)
3812 {
3813 case BOOTSTRAPPER_REQUEST_STATE_NONE:
3814 return "None";
3815 case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT:
3816 return "ForceAbsent";
3817 case BOOTSTRAPPER_REQUEST_STATE_ABSENT:
3818 return "Absent";
3819 case BOOTSTRAPPER_REQUEST_STATE_CACHE:
3820 return "Cache";
3821 case BOOTSTRAPPER_REQUEST_STATE_PRESENT:
3822 return "Present";
3823 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
3824 return "Repair";
3825 default:
3826 return "Invalid";
3827 }
3828}
3829
3830static LPCSTR LoggingMsiFeatureStateToString(
3831 __in BOOTSTRAPPER_FEATURE_STATE featureState
3832 )
3833{
3834 switch (featureState)
3835 {
3836 case BOOTSTRAPPER_FEATURE_STATE_UNKNOWN:
3837 return "Unknown";
3838 case BOOTSTRAPPER_FEATURE_STATE_ABSENT:
3839 return "Absent";
3840 case BOOTSTRAPPER_FEATURE_STATE_ADVERTISED:
3841 return "Advertised";
3842 case BOOTSTRAPPER_FEATURE_STATE_LOCAL:
3843 return "Local";
3844 case BOOTSTRAPPER_FEATURE_STATE_SOURCE:
3845 return "Source";
3846 default:
3847 return "Invalid";
3848 }
3849}