main
cpp 529 lines 15.3 KB
Raw
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 "BalBaseBAFunctions.h"
5 #include "BalBaseBAFunctionsProc.h"
6
7 static const LPCWSTR BAFTHMUTILTESTING_WINDOW_CLASS = L"BafThmUtilTesting";
8
9 enum BAF_CONTROL
10 {
11 BAF_CONTROL_INSTALL_TEST_BUTTON = BAFUNCTIONS_FIRST_ASSIGN_CONTROL_ID,
12 };
13
14 enum BAFTHMUTILTESTING_CONTROL
15 {
16 BAFTHMUTILTESTING_CONTROL_LISTVIEW_TOP_LEFT = THEME_FIRST_ASSIGN_CONTROL_ID,
17 BAFTHMUTILTESTING_CONTROL_LISTVIEW_TOP_RIGHT,
18 BAFTHMUTILTESTING_CONTROL_LISTVIEW_BOTTOM_LEFT,
19 BAFTHMUTILTESTING_CONTROL_LISTVIEW_BOTTOM_RIGHT,
20 BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_STANDARD,
21 BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_IMAGE,
22 };
23
24 static THEME_ASSIGN_CONTROL_ID vrgInitControls[] = {
25 { BAFTHMUTILTESTING_CONTROL_LISTVIEW_TOP_LEFT, L"ListViewTopLeft" },
26 { BAFTHMUTILTESTING_CONTROL_LISTVIEW_TOP_RIGHT, L"ListViewTopRight" },
27 { BAFTHMUTILTESTING_CONTROL_LISTVIEW_BOTTOM_LEFT, L"ListViewBottomLeft" },
28 { BAFTHMUTILTESTING_CONTROL_LISTVIEW_BOTTOM_RIGHT, L"ListViewBottomRight" },
29 { BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_IMAGE, L"ImageProgressBar" },
30 { BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_STANDARD, L"StandardProgressBar" },
31 };
32
33 static HRESULT LogUserSid();
34 static void CALLBACK BafThmUtilTestingTraceError(
35 __in_z LPCSTR szFile,
36 __in int iLine,
37 __in REPORT_LEVEL rl,
38 __in UINT source,
39 __in HRESULT hrError,
40 __in_z __format_string LPCSTR szFormat,
41 __in va_list args
42 );
43
44 class CBafThmUtilTesting : public CBalBaseBAFunctions
45 {
46 public: // IBAFunctions
47 virtual STDMETHODIMP OnCreate(
48 __in IBootstrapperEngine* pEngine,
49 __in BOOTSTRAPPER_COMMAND* pCommand
50 )
51 {
52 m_commandDisplay = pCommand->display;
53
54 return __super::OnCreate(pEngine, pCommand);
55 }
56
57 virtual STDMETHODIMP OnThemeControlLoading(
58 __in LPCWSTR wzName,
59 __inout BOOL* pfProcessed,
60 __inout WORD* pwId,
61 __inout DWORD* /*pdwAutomaticBehaviorType*/
62 )
63 {
64 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzName, -1, L"InstallTestButton", -1))
65 {
66 *pfProcessed = TRUE;
67 *pwId = BAF_CONTROL_INSTALL_TEST_BUTTON;
68 }
69
70 return S_OK;
71 }
72
73 virtual STDMETHODIMP OnThemeControlWmCommand(
74 __in WPARAM wParam,
75 __in LPCWSTR /*wzName*/,
76 __in WORD wId,
77 __in HWND /*hWnd*/,
78 __inout BOOL* pfProcessed,
79 __inout LRESULT* plResult
80 )
81 {
82 HRESULT hr = S_OK;
83
84 switch (HIWORD(wParam))
85 {
86 case BN_CLICKED:
87 switch (wId)
88 {
89 case BAF_CONTROL_INSTALL_TEST_BUTTON:
90 OnShowTheme();
91 *pfProcessed = TRUE;
92 *plResult = 0;
93 break;
94 }
95
96 break;
97 }
98
99 return hr;
100 }
101
102 public: //IBootstrapperApplication
103 virtual STDMETHODIMP OnExecuteBegin(
104 __in DWORD /*cExecutingPackages*/,
105 __inout BOOL* pfCancel
106 )
107 {
108 if (BOOTSTRAPPER_DISPLAY_FULL <= m_commandDisplay)
109 {
110 if (IDCANCEL == ::MessageBoxW(m_hwndParent, L"Shutdown requests should be denied right now.", L"OnExecuteBegin", MB_OKCANCEL))
111 {
112 *pfCancel = TRUE;
113 }
114 }
115
116 return S_OK;
117 }
118
119 private:
120 HRESULT OnShowTheme()
121 {
122 HRESULT hr = S_OK;
123 BOOL fRet = FALSE;
124 MSG msg = { };
125
126 hr = ThemeLoadFromResource(m_hModule, MAKEINTRESOURCEA(1), &m_pBafTheme);
127 BalExitOnFailure(hr, "Failed to load BafThmUtilTesting theme.");
128
129 hr = CreateTestingWindow();
130 BalExitOnFailure(hr, "Failed to create BafThmUtilTesting window.");
131
132 ::EnableWindow(m_hwndParent, FALSE);
133
134 // message pump
135 while (0 != (fRet = ::GetMessageW(&msg, NULL, 0, 0)))
136 {
137 if (-1 == fRet)
138 {
139 hr = E_UNEXPECTED;
140 BalExitOnFailure(hr, "Unexpected return value from message pump.");
141 }
142 else if (!ThemeHandleKeyboardMessage(m_pBafTheme, msg.hwnd, &msg))
143 {
144 ::TranslateMessage(&msg);
145 ::DispatchMessageW(&msg);
146 }
147 }
148
149 LExit:
150 ::EnableWindow(m_hwndParent, TRUE);
151
152 DestroyTestingWindow();
153
154 ReleaseTheme(m_pBafTheme);
155
156 return hr;
157 }
158
159 HRESULT CreateTestingWindow()
160 {
161 HRESULT hr = S_OK;
162 WNDCLASSW wc = { };
163 int x = CW_USEDEFAULT;
164 int y = CW_USEDEFAULT;
165 POINT ptCursor = { };
166
167 ThemeInitializeWindowClass(m_pBafTheme, &wc, CBafThmUtilTesting::TestingWndProc, m_hModule, BAFTHMUTILTESTING_WINDOW_CLASS);
168
169 Assert(wc.lpszClassName);
170
171 // If the theme did not provide an icon, try using the icon from the bundle engine.
172 if (!wc.hIcon)
173 {
174 HMODULE hBootstrapperEngine = ::GetModuleHandleW(NULL);
175 if (hBootstrapperEngine)
176 {
177 wc.hIcon = ::LoadIconW(hBootstrapperEngine, MAKEINTRESOURCEW(1));
178 }
179 }
180
181 // Register the window class and create the window.
182 if (!::RegisterClassW(&wc))
183 {
184 ExitWithLastError(hr, "Failed to register window.");
185 }
186
187 m_fRegistered = TRUE;
188
189 // Center the window on the monitor with the mouse.
190 if (::GetCursorPos(&ptCursor))
191 {
192 x = ptCursor.x;
193 y = ptCursor.y;
194 }
195
196 hr = ThemeCreateParentWindow(m_pBafTheme, 0, wc.lpszClassName, m_pBafTheme->sczCaption, m_pBafTheme->dwStyle, x, y, m_hwndParent, m_hModule, this, THEME_WINDOW_INITIAL_POSITION_CENTER_MONITOR_FROM_COORDINATES, &m_hWndBaf);
197 ExitOnFailure(hr, "Failed to create baf testing window.");
198
199 hr = S_OK;
200
201 LExit:
202 return hr;
203 }
204
205 void DestroyTestingWindow()
206 {
207 if (::IsWindow(m_hWndBaf))
208 {
209 ::DestroyWindow(m_hWndBaf);
210 m_hWndBaf = NULL;
211 }
212
213 if (m_fRegistered)
214 {
215 ::UnregisterClassW(BAFTHMUTILTESTING_WINDOW_CLASS, m_hModule);
216 m_fRegistered = FALSE;
217 }
218 }
219
220 static LRESULT CALLBACK TestingWndProc(
221 __in HWND hWnd,
222 __in UINT uMsg,
223 __in WPARAM wParam,
224 __in LPARAM lParam
225 )
226 {
227 #pragma warning(suppress:4312)
228 CBafThmUtilTesting* pBaf = reinterpret_cast<CBafThmUtilTesting*>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA));
229
230 switch (uMsg)
231 {
232 case WM_NCCREATE:
233 {
234 LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
235 pBaf = reinterpret_cast<CBafThmUtilTesting*>(lpcs->lpCreateParams);
236 #pragma warning(suppress:4244)
237 ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pBaf));
238 break;
239 }
240
241 case WM_CLOSE:
242 if (pBaf)
243 {
244 ::EnableWindow(pBaf->m_hwndParent, TRUE);
245 }
246
247 break;
248
249 case WM_NCDESTROY:
250 {
251 LRESULT lres = ThemeDefWindowProc(pBaf ? pBaf->m_pBafTheme : NULL, hWnd, uMsg, wParam, lParam);
252 ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, 0);
253
254 ::PostQuitMessage(0);
255 return lres;
256 }
257
258 case WM_THMUTIL_LOADING_CONTROL:
259 return pBaf->OnThemeLoadingControl(reinterpret_cast<THEME_LOADINGCONTROL_ARGS*>(wParam), reinterpret_cast<THEME_LOADINGCONTROL_RESULTS*>(lParam));
260
261 case WM_THMUTIL_LOADED_CONTROL:
262 return pBaf->OnThemeLoadedControl(hWnd, reinterpret_cast<THEME_LOADEDCONTROL_ARGS*>(wParam), reinterpret_cast<THEME_LOADEDCONTROL_RESULTS*>(lParam));
263
264 case WM_TIMER:
265 if (!lParam && BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_IMAGE == wParam && pBaf)
266 {
267 pBaf->UpdateProgressBarProgress();
268
269 return 0;
270 }
271 break;
272 }
273
274 return ThemeDefWindowProc(pBaf ? pBaf->m_pBafTheme : NULL, hWnd, uMsg, wParam, lParam);
275 }
276
277 HRESULT OnCreatedListView(
278 __in HWND hWndListView
279 )
280 {
281 HRESULT hr = S_OK;
282 LVITEMW lvitem = { };
283 LVGROUP lvgroup = { };
284 static UINT puColumns[] = { 0, 1, 2 };
285
286 lvgroup.cbSize = sizeof(LVGROUP);
287 lvgroup.mask = LVGF_GROUPID | LVGF_TITLEIMAGE | LVGF_DESCRIPTIONTOP | LVGF_HEADER;
288
289 for (int i = 0; i < 3; ++i)
290 {
291 lvgroup.iGroupId = i;
292 lvgroup.iTitleImage = i;
293
294 hr = StrAllocFormatted(&lvgroup.pszDescriptionTop, L"DescriptionTop_%d", i);
295 BalExitOnFailure(hr, "Failed to alloc list view group description.");
296
297 hr = StrAllocFormatted(&lvgroup.pszHeader, L"Header_%d", i);
298 BalExitOnFailure(hr, "Failed to alloc list view group header.");
299
300 ListView_InsertGroup(hWndListView, -1, &lvgroup);
301
302 lvitem.mask = LVIF_COLUMNS | LVIF_GROUPID | LVIF_IMAGE | LVIF_TEXT;
303 lvitem.iItem = i;
304 lvitem.iSubItem = 0;
305
306 hr = StrAllocFormatted(&lvitem.pszText, L"ListViewItem_%d", i);
307 BalExitOnFailure(hr, "Failed to alloc list view item text.");
308
309 lvitem.iImage = i;
310 lvitem.iGroupId = i;
311 lvitem.cColumns = countof(puColumns);
312 lvitem.puColumns = puColumns;
313
314 ListView_InsertItem(hWndListView, &lvitem);
315
316 for (int j = 0; j < 3; ++j)
317 {
318 lvitem.mask = LVIF_TEXT;
319 lvitem.iSubItem = j + 1;
320
321 hr = StrAllocFormatted(&lvitem.pszText, L"%d_%d", j, i);
322 BalExitOnFailure(hr, "Failed to alloc list view subitem text.");
323
324 ListView_InsertItem(hWndListView, &lvitem);
325 }
326 }
327
328 LExit:
329 ReleaseStr(lvgroup.pszDescriptionTop);
330 ReleaseStr(lvgroup.pszHeader);
331 ReleaseStr(lvitem.pszText);
332
333 return hr;
334 }
335
336 BOOL OnThemeLoadingControl(
337 __in const THEME_LOADINGCONTROL_ARGS* pArgs,
338 __in THEME_LOADINGCONTROL_RESULTS* pResults
339 )
340 {
341 HRESULT hr = S_OK;
342 BOOL fProcessed = FALSE;
343
344 for (DWORD iAssignControl = 0; iAssignControl < countof(vrgInitControls); ++iAssignControl)
345 {
346 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pArgs->pThemeControl->sczName, -1, vrgInitControls[iAssignControl].wzName, -1))
347 {
348 fProcessed = TRUE;
349 pResults->wId = vrgInitControls[iAssignControl].wId;
350 break;
351 }
352 }
353
354 pResults->hr = hr;
355 return fProcessed || FAILED(hr);
356 }
357
358 BOOL OnThemeLoadedControl(
359 __in HWND hWndParent,
360 __in const THEME_LOADEDCONTROL_ARGS* pArgs,
361 __in THEME_LOADEDCONTROL_RESULTS* pResults
362 )
363 {
364 HRESULT hr = S_OK;
365 BOOL fProcessed = FALSE;
366
367 switch (pArgs->pThemeControl->wId)
368 {
369 case BAFTHMUTILTESTING_CONTROL_LISTVIEW_TOP_LEFT:
370 case BAFTHMUTILTESTING_CONTROL_LISTVIEW_TOP_RIGHT:
371 case BAFTHMUTILTESTING_CONTROL_LISTVIEW_BOTTOM_LEFT:
372 case BAFTHMUTILTESTING_CONTROL_LISTVIEW_BOTTOM_RIGHT:
373 fProcessed = TRUE;
374
375 hr = OnCreatedListView(pArgs->pThemeControl->hWnd);
376 ExitOnFailure(hr, "Failed to populate list view.");
377
378 if (BAFTHMUTILTESTING_CONTROL_LISTVIEW_TOP_RIGHT == pArgs->pThemeControl->wId)
379 {
380 ListView_EnableGroupView(pArgs->pThemeControl->hWnd, TRUE);
381 }
382
383 break;
384
385 case BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_STANDARD:
386 fProcessed = TRUE;
387
388 ::SetTimer(hWndParent, BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_IMAGE, 500, NULL);
389 break;
390 }
391
392 LExit:
393 pResults->hr = hr;
394 return fProcessed || FAILED(hr);
395 }
396
397 void UpdateProgressBarProgress()
398 {
399 const THEME_CONTROL* pControlProgressbarImage = NULL;
400 const THEME_CONTROL* pControlProgressbarStandard = NULL;
401 static DWORD dwProgress = 0;
402 DWORD dwCurrent = dwProgress < 100 ? dwProgress : 200 - dwProgress;
403
404 ThemeControlExistsById(m_pBafTheme, BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_IMAGE, &pControlProgressbarImage);
405 ThemeControlExistsById(m_pBafTheme, BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_STANDARD, &pControlProgressbarStandard);
406
407 if (0 == dwProgress || 100 == dwProgress)
408 {
409 ThemeSetProgressControlColor(pControlProgressbarImage, 100 == dwProgress ? 1 : 0);
410 }
411
412 dwProgress = (dwProgress + 10) % 200;
413
414 ThemeSetProgressControl(pControlProgressbarImage, dwCurrent);
415 ThemeSetProgressControl(pControlProgressbarStandard, dwCurrent);
416 }
417
418 public:
419 //
420 // Constructor - initialize member variables.
421 //
422 CBafThmUtilTesting(
423 __in HMODULE hModule
424 ) : CBalBaseBAFunctions(hModule)
425 {
426 m_commandDisplay = BOOTSTRAPPER_DISPLAY_UNKNOWN;
427 m_pBafTheme = NULL;
428 m_fRegistered = FALSE;
429 m_hWndBaf = NULL;
430
431 ThemeInitialize(hModule);
432 }
433
434 //
435 // Destructor - release member variables.
436 //
437 ~CBafThmUtilTesting()
438 {
439 Assert(!::IsWindow(m_hWndBaf));
440 Assert(!m_pBafTheme);
441
442 ThemeUninitialize();
443 }
444
445 private:
446 BOOTSTRAPPER_DISPLAY m_commandDisplay;
447 THEME* m_pBafTheme;
448 BOOL m_fRegistered;
449 HWND m_hWndBaf;
450 };
451
452 HRESULT WINAPI CreateBAFunctions(
453 __in HMODULE hModule,
454 __in const BA_FUNCTIONS_CREATE_ARGS* pArgs,
455 __inout BA_FUNCTIONS_CREATE_RESULTS* pResults
456 )
457 {
458 HRESULT hr = S_OK;
459 CBafThmUtilTesting* pBAFunctions = NULL;
460
461 DutilInitialize(&BafThmUtilTestingTraceError);
462
463 #if TODO_REWRITE
464 hr = BalInitializeFromCreateArgs(pArgs->pBootstrapperCreateArgs, &pEngine);
465 ExitOnFailure(hr, "Failed to initialize Bal.");
466 #endif
467
468 pBAFunctions = new CBafThmUtilTesting(hModule);
469 ExitOnNull(pBAFunctions, hr, E_OUTOFMEMORY, "Failed to create new CBafThmUtilTesting object.");
470
471 hr = pBAFunctions->OnCreate(pArgs->pEngine, pArgs->pCommand);
472 ExitOnFailure(hr, "Failed to call OnCreate CPrereqBaf.");
473
474 pResults->pfnBAFunctionsProc = BalBaseBAFunctionsProc;
475 pResults->pvBAFunctionsProcContext = pBAFunctions;
476 pBAFunctions = NULL;
477
478 LogUserSid();
479
480 LExit:
481 ReleaseObject(pBAFunctions);
482
483 return hr;
484 }
485
486 static HRESULT LogUserSid()
487 {
488 HRESULT hr = S_OK;
489 TOKEN_USER* pTokenUser = NULL;
490 LPWSTR sczSid = NULL;
491
492 hr = ProcGetTokenInformation(::GetCurrentProcess(), TokenUser, reinterpret_cast<LPVOID*>(&pTokenUser));
493 BalExitOnFailure(hr, "Failed to get user from process token.");
494
495 if (!::ConvertSidToStringSidW(pTokenUser->User.Sid, &sczSid))
496 {
497 BalExitWithLastError(hr, "Failed to convert sid to string.");
498 }
499
500 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Current User SID: %ls", sczSid);
501
502 LExit:
503 ReleaseMem(pTokenUser);
504
505 if (sczSid)
506 {
507 ::LocalFree(sczSid);
508 }
509
510 return hr;
511 }
512
513 static void CALLBACK BafThmUtilTestingTraceError(
514 __in_z LPCSTR /*szFile*/,
515 __in int /*iLine*/,
516 __in REPORT_LEVEL /*rl*/,
517 __in UINT source,
518 __in HRESULT hrError,
519 __in_z __format_string LPCSTR szFormat,
520 __in va_list args
521 )
522 {
523 // BalLogError currently uses the Exit... macros,
524 // so if expanding the scope need to ensure this doesn't get called recursively.
525 if (DUTIL_SOURCE_THMUTIL == source)
526 {
527 BalLogErrorArgs(hrError, szFormat, args);
528 }
529 }