Skip to content

Commit 2e47094

Browse files
committed
[SYSSETUP] Apply theming from unattend files very early on when booting the LiveCD or a new install (reactos#7797)
Use a `[Shell]` section with `DefaultThemesOff` and `CustomDefaultThemeFile` values, specifying respectively whether to use the classic theme or a custom one, and the complete path to the custom .theme (or .msstyles) file. These values are compatible with those documented in the "MS Windows Preinstallation Reference" help file of the Windows installation CD (DEPLOY.CAB\ref.chm) [BOOTDATA] bootcd/unattend.inf: Use the Shell/CustomDefaultThemeFile value to specify which theme to use
1 parent 8e2d1b3 commit 2e47094

File tree

3 files changed

+153
-16
lines changed

3 files changed

+153
-16
lines changed

boot/bootdata/bootcd/unattend.inf

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,12 @@ LocaleID = 409
5959
; 1: ReactOS Workstation
6060
ProductOption = 0
6161

62-
; enable this section to automatically launch programs
62+
; Enable this section to automatically launch programs
6363
; after 3rd boot
64-
;
6564
; [GuiRunOnce]
6665
; %SystemRoot%\system32\cmd.exe
67-
; Enable the next line (+ the GuiRunOnce section) to enable the lautus theme
68-
; "rundll32.exe shell32.dll,Control_RunDLL desk.cpl desk,@Appearance /Action:ActivateMSTheme /file:%SYSTEMROOT%\Resources\themes\lautus\lautus.msstyles"
6966

70-
71-
; enable this section to change resolution / bpp
67+
; Enable this section to change resolution / bpp
7268
; setting a value to 0 or skipping it will leave it unchanged
7369
; [Display]
7470
; BitsPerPel = 32
@@ -80,3 +76,8 @@ ProductOption = 0
8076
;[Env]
8177
;WINETEST_PLATFORM=reactos
8278

79+
; Enable this section to enable the default ReactOS theme
80+
; [Shell]
81+
; DefaultThemesOff = no
82+
; CustomDefaultThemeFile = "%WINDIR%\Resources\Themes\Lautus\lautus.msstyles"
83+

dll/win32/syssetup/install.c

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -985,6 +985,61 @@ IsConsoleBoot(VOID)
985985
return bConsoleBoot;
986986
}
987987

988+
extern VOID
989+
EnableVisualTheme(
990+
_In_opt_ HWND hwndParent,
991+
_In_opt_ PCWSTR ThemeFile);
992+
993+
/**
994+
* @brief
995+
* Pre-process unattended file to apply early settings.
996+
*
997+
* @param[in] IsInstall
998+
* TRUE if this is ReactOS installation, invoked from InstallReactOS(),
999+
* FALSE if this is run as part of LiveCD, invoked form InstallLiveCD().
1000+
**/
1001+
static VOID
1002+
PreprocessUnattend(
1003+
_In_ BOOL IsInstall)
1004+
{
1005+
WCHAR szPath[MAX_PATH];
1006+
WCHAR szValue[MAX_PATH];
1007+
BOOL bDefaultThemesOff;
1008+
1009+
if (IsInstall)
1010+
{
1011+
/* See also wizard.c!ProcessSetupInf()
1012+
* Retrieve the path of the setup INF */
1013+
GetSystemDirectoryW(szPath, _countof(szPath));
1014+
wcscat(szPath, L"\\$winnt$.inf");
1015+
}
1016+
else
1017+
{
1018+
/* See also userinit/livecd.c!RunLiveCD() */
1019+
GetWindowsDirectoryW(szPath, _countof(szPath));
1020+
wcscat(szPath, L"\\unattend.inf");
1021+
}
1022+
1023+
/*
1024+
* Apply initial default theming
1025+
*/
1026+
1027+
/* Check whether to use the classic theme (TRUE) instead of the default theme */
1028+
bDefaultThemesOff = FALSE;
1029+
if (GetPrivateProfileStringW(L"Shell", L"DefaultThemesOff", L"no", szValue, _countof(szValue), szPath) && *szValue)
1030+
bDefaultThemesOff = (_wcsicmp(szValue, L"yes") == 0);
1031+
1032+
if (!bDefaultThemesOff)
1033+
{
1034+
/* Retrieve the complete path to a .theme (or for ReactOS, a .msstyles) file */
1035+
if (!GetPrivateProfileStringW(L"Shell", L"CustomDefaultThemeFile", NULL, szValue, _countof(szValue), szPath) || !*szValue)
1036+
bDefaultThemesOff = TRUE; // None specified, fall back to the classic theme.
1037+
}
1038+
1039+
/* Enable the chosen theme, or use the classic theme */
1040+
EnableVisualTheme(NULL, bDefaultThemesOff ? NULL : szValue);
1041+
}
1042+
9881043
static BOOL
9891044
CommonInstall(VOID)
9901045
{
@@ -1007,7 +1062,7 @@ CommonInstall(VOID)
10071062
goto Exit;
10081063
}
10091064

1010-
if(!InstallSysSetupInfComponents())
1065+
if (!InstallSysSetupInfComponents())
10111066
{
10121067
FatalError("InstallSysSetupInfComponents() failed!\n");
10131068
goto Exit;
@@ -1038,7 +1093,6 @@ CommonInstall(VOID)
10381093
bResult = TRUE;
10391094

10401095
Exit:
1041-
10421096
if (bResult == FALSE)
10431097
{
10441098
SetupCloseInfFile(hSysSetupInf);
@@ -1062,6 +1116,7 @@ InstallLiveCD(VOID)
10621116
PROCESS_INFORMATION ProcessInformation;
10631117
BOOL bRes;
10641118

1119+
PreprocessUnattend(FALSE);
10651120
if (!CommonInstall())
10661121
goto error;
10671122

@@ -1579,6 +1634,7 @@ InstallReactOS(VOID)
15791634

15801635
hHotkeyThread = CreateThread(NULL, 0, HotkeyThread, NULL, 0, NULL);
15811636

1637+
PreprocessUnattend(TRUE);
15821638
if (!CommonInstall())
15831639
return 0;
15841640

dll/win32/syssetup/wizard.c

Lines changed: 88 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ typedef struct _TIMEZONE_ENTRY
5252

5353
extern void WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow);
5454

55-
5655
static VOID
5756
CenterWindow(HWND hWnd)
5857
{
@@ -1367,6 +1366,90 @@ RunControlPanelApplet(HWND hwnd, PCWSTR pwszCPLParameters)
13671366
return TRUE;
13681367
}
13691368

1369+
1370+
VOID
1371+
EnableVisualTheme(
1372+
_In_opt_ HWND hwndParent,
1373+
_In_opt_ PCWSTR ThemeFile)
1374+
{
1375+
enum { THEME_FILE, STYLE_FILE, UNKNOWN } fType;
1376+
WCHAR szPath[MAX_PATH]; // Expanded path of the file to use.
1377+
WCHAR szStyleFile[MAX_PATH];
1378+
1379+
fType = THEME_FILE; // Default to Classic theme.
1380+
if (ThemeFile)
1381+
{
1382+
/* Expand the path if possible */
1383+
if (ExpandEnvironmentStringsW(ThemeFile, szPath, _countof(szPath)) != 0)
1384+
ThemeFile = szPath;
1385+
1386+
/* Determine the file type from its extension */
1387+
fType = UNKNOWN; {
1388+
PCWSTR pszExt = wcsrchr(ThemeFile, L'.'); // PathFindExtensionW(ThemeFile);
1389+
if (pszExt)
1390+
{
1391+
if (_wcsicmp(pszExt, L".theme") == 0)
1392+
fType = THEME_FILE;
1393+
else if (_wcsicmp(pszExt, L".msstyles") == 0)
1394+
fType = STYLE_FILE;
1395+
} }
1396+
if (fType == UNKNOWN)
1397+
{
1398+
DPRINT1("EnableVisualTheme(): Unknown file '%S'\n", ThemeFile);
1399+
return;
1400+
}
1401+
}
1402+
1403+
DPRINT1("Applying visual %s '%S'\n",
1404+
(fType == THEME_FILE) ? "theme" : "style",
1405+
ThemeFile ? ThemeFile : L"(Classic)");
1406+
1407+
//
1408+
// TODO: Use instead uxtheme!SetSystemVisualStyle() once it is implemented,
1409+
// https://stackoverflow.com/a/1036903
1410+
// https://pinvoke.net/default.aspx/uxtheme.SetSystemVisualStyle
1411+
// or ApplyTheme(NULL, 0, NULL) for restoring the classic theme.
1412+
//
1413+
// NOTE: The '/Action:ActivateMSTheme' is ReactOS-specific.
1414+
//
1415+
1416+
if (ThemeFile && (fType == THEME_FILE))
1417+
{
1418+
/* Retrieve the visual style specified in the theme file.
1419+
* If none, fall back to the classic theme. */
1420+
if (GetPrivateProfileStringW(L"VisualStyles", L"Path", NULL,
1421+
szStyleFile, _countof(szStyleFile), ThemeFile) && *szStyleFile)
1422+
{
1423+
/* Expand the path if possible */
1424+
ThemeFile = szStyleFile;
1425+
if (ExpandEnvironmentStringsW(ThemeFile, szPath, _countof(szPath)) != 0)
1426+
ThemeFile = szPath;
1427+
}
1428+
else
1429+
{
1430+
ThemeFile = NULL;
1431+
}
1432+
1433+
DPRINT1("--> Applying visual style '%S'\n",
1434+
ThemeFile ? ThemeFile : L"(Classic)");
1435+
}
1436+
1437+
if (ThemeFile)
1438+
{
1439+
WCHAR wszParams[1024];
1440+
// FIXME: L"desk.cpl desk,@Appearance" regression, see commit 50d260a7f0
1441+
PCWSTR format = L"desk.cpl,,2 /Action:ActivateMSTheme /file:\"%s\"";
1442+
1443+
StringCchPrintfW(wszParams, _countof(wszParams), format, ThemeFile);
1444+
RunControlPanelApplet(hwndParent, wszParams);
1445+
}
1446+
else
1447+
{
1448+
RunControlPanelApplet(hwndParent, L"desk.cpl,,2 /Action:ActivateMSTheme");
1449+
}
1450+
}
1451+
1452+
13701453
static VOID
13711454
WriteUserLocale(VOID)
13721455
{
@@ -1927,13 +2010,14 @@ ThemePageDlgProc(HWND hwndDlg,
19272010

19282011
/* Register the imagelist */
19292012
ListView_SetImageList(hListView, himl, LVSIL_NORMAL);
1930-
/* Transparant background */
2013+
/* Transparent background */
19312014
ListView_SetBkColor(hListView, CLR_NONE);
19322015
ListView_SetTextBkColor(hListView, CLR_NONE);
19332016
/* Reduce the size between the items */
19342017
ListView_SetIconSpacing(hListView, 190, 173);
19352018
break;
19362019
}
2020+
19372021
case WM_NOTIFY:
19382022
switch (((LPNMHDR)lParam)->code)
19392023
{
@@ -1947,17 +2031,13 @@ ThemePageDlgProc(HWND hwndDlg,
19472031

19482032
if (Themes[iTheme].ThemeFile)
19492033
{
1950-
WCHAR wszParams[1024];
19512034
WCHAR wszTheme[MAX_PATH];
1952-
WCHAR* format = L"desk.cpl,,2 /Action:ActivateMSTheme /file:\"%s\"";
1953-
19542035
SHGetFolderPathAndSubDirW(0, CSIDL_RESOURCES, NULL, SHGFP_TYPE_DEFAULT, Themes[iTheme].ThemeFile, wszTheme);
1955-
swprintf(wszParams, format, wszTheme);
1956-
RunControlPanelApplet(hwndDlg, wszParams);
2036+
EnableVisualTheme(hwndDlg, wszTheme);
19572037
}
19582038
else
19592039
{
1960-
RunControlPanelApplet(hwndDlg, L"desk.cpl,,2 /Action:ActivateMSTheme");
2040+
EnableVisualTheme(hwndDlg, Themes[iTheme].ThemeFile);
19612041
}
19622042
}
19632043
break;

0 commit comments

Comments
 (0)