https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2e47094764559867d1314…
commit 2e47094764559867d1314076a8a215e7b3e79972
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Tue Mar 18 13:52:39 2025 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Tue Mar 18 23:02:34 2025 +0100
[SYSSETUP] Apply theming from unattend files very early on when booting the LiveCD or
a new install (#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
---
boot/bootdata/bootcd/unattend.inf | 13 +++---
dll/win32/syssetup/install.c | 60 +++++++++++++++++++++++-
dll/win32/syssetup/wizard.c | 96 +++++++++++++++++++++++++++++++++++----
3 files changed, 153 insertions(+), 16 deletions(-)
diff --git a/boot/bootdata/bootcd/unattend.inf b/boot/bootdata/bootcd/unattend.inf
index ec41adcc97b..3dcffae4cd5 100644
--- a/boot/bootdata/bootcd/unattend.inf
+++ b/boot/bootdata/bootcd/unattend.inf
@@ -59,16 +59,12 @@ LocaleID = 409
; 1: ReactOS Workstation
ProductOption = 0
-; enable this section to automatically launch programs
+; Enable this section to automatically launch programs
; after 3rd boot
-;
; [GuiRunOnce]
; %SystemRoot%\system32\cmd.exe
-; Enable the next line (+ the GuiRunOnce section) to enable the lautus theme
-; "rundll32.exe shell32.dll,Control_RunDLL desk.cpl desk,@Appearance
/Action:ActivateMSTheme /file:%SYSTEMROOT%\Resources\themes\lautus\lautus.msstyles"
-
-; enable this section to change resolution / bpp
+; Enable this section to change resolution / bpp
; setting a value to 0 or skipping it will leave it unchanged
; [Display]
; BitsPerPel = 32
@@ -80,3 +76,8 @@ ProductOption = 0
;[Env]
;WINETEST_PLATFORM=reactos
+; Enable this section to enable the default ReactOS theme
+; [Shell]
+; DefaultThemesOff = no
+; CustomDefaultThemeFile = "%WINDIR%\Resources\Themes\Lautus\lautus.msstyles"
+
diff --git a/dll/win32/syssetup/install.c b/dll/win32/syssetup/install.c
index 74b7148a096..8895e0628c0 100644
--- a/dll/win32/syssetup/install.c
+++ b/dll/win32/syssetup/install.c
@@ -985,6 +985,61 @@ cleanup:
return bConsoleBoot;
}
+extern VOID
+EnableVisualTheme(
+ _In_opt_ HWND hwndParent,
+ _In_opt_ PCWSTR ThemeFile);
+
+/**
+ * @brief
+ * Pre-process unattended file to apply early settings.
+ *
+ * @param[in] IsInstall
+ * TRUE if this is ReactOS installation, invoked from InstallReactOS(),
+ * FALSE if this is run as part of LiveCD, invoked form InstallLiveCD().
+ **/
+static VOID
+PreprocessUnattend(
+ _In_ BOOL IsInstall)
+{
+ WCHAR szPath[MAX_PATH];
+ WCHAR szValue[MAX_PATH];
+ BOOL bDefaultThemesOff;
+
+ if (IsInstall)
+ {
+ /* See also wizard.c!ProcessSetupInf()
+ * Retrieve the path of the setup INF */
+ GetSystemDirectoryW(szPath, _countof(szPath));
+ wcscat(szPath, L"\\$winnt$.inf");
+ }
+ else
+ {
+ /* See also userinit/livecd.c!RunLiveCD() */
+ GetWindowsDirectoryW(szPath, _countof(szPath));
+ wcscat(szPath, L"\\unattend.inf");
+ }
+
+ /*
+ * Apply initial default theming
+ */
+
+ /* Check whether to use the classic theme (TRUE) instead of the default theme */
+ bDefaultThemesOff = FALSE;
+ if (GetPrivateProfileStringW(L"Shell", L"DefaultThemesOff",
L"no", szValue, _countof(szValue), szPath) && *szValue)
+ bDefaultThemesOff = (_wcsicmp(szValue, L"yes") == 0);
+
+ if (!bDefaultThemesOff)
+ {
+ /* Retrieve the complete path to a .theme (or for ReactOS, a .msstyles) file */
+ if (!GetPrivateProfileStringW(L"Shell",
L"CustomDefaultThemeFile", NULL, szValue, _countof(szValue), szPath) ||
!*szValue)
+ bDefaultThemesOff = TRUE; // None specified, fall back to the classic theme.
+ }
+
+ /* Enable the chosen theme, or use the classic theme */
+ EnableVisualTheme(NULL, bDefaultThemesOff ? NULL : szValue);
+}
+
static BOOL
CommonInstall(VOID)
{
@@ -1007,7 +1062,7 @@ CommonInstall(VOID)
goto Exit;
}
- if(!InstallSysSetupInfComponents())
+ if (!InstallSysSetupInfComponents())
{
FatalError("InstallSysSetupInfComponents() failed!\n");
goto Exit;
@@ -1038,7 +1093,6 @@ CommonInstall(VOID)
bResult = TRUE;
Exit:
-
if (bResult == FALSE)
{
SetupCloseInfFile(hSysSetupInf);
@@ -1062,6 +1116,7 @@ InstallLiveCD(VOID)
PROCESS_INFORMATION ProcessInformation;
BOOL bRes;
+ PreprocessUnattend(FALSE);
if (!CommonInstall())
goto error;
@@ -1579,6 +1634,7 @@ InstallReactOS(VOID)
hHotkeyThread = CreateThread(NULL, 0, HotkeyThread, NULL, 0, NULL);
+ PreprocessUnattend(TRUE);
if (!CommonInstall())
return 0;
diff --git a/dll/win32/syssetup/wizard.c b/dll/win32/syssetup/wizard.c
index ade3c295a3f..9ec3d167db7 100644
--- a/dll/win32/syssetup/wizard.c
+++ b/dll/win32/syssetup/wizard.c
@@ -52,7 +52,6 @@ typedef struct _TIMEZONE_ENTRY
extern void WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD
nCmdShow);
-
static VOID
CenterWindow(HWND hWnd)
{
@@ -1367,6 +1366,90 @@ RunControlPanelApplet(HWND hwnd, PCWSTR pwszCPLParameters)
return TRUE;
}
+
+VOID
+EnableVisualTheme(
+ _In_opt_ HWND hwndParent,
+ _In_opt_ PCWSTR ThemeFile)
+{
+ enum { THEME_FILE, STYLE_FILE, UNKNOWN } fType;
+ WCHAR szPath[MAX_PATH]; // Expanded path of the file to use.
+ WCHAR szStyleFile[MAX_PATH];
+
+ fType = THEME_FILE; // Default to Classic theme.
+ if (ThemeFile)
+ {
+ /* Expand the path if possible */
+ if (ExpandEnvironmentStringsW(ThemeFile, szPath, _countof(szPath)) != 0)
+ ThemeFile = szPath;
+
+ /* Determine the file type from its extension */
+ fType = UNKNOWN; {
+ PCWSTR pszExt = wcsrchr(ThemeFile, L'.'); //
PathFindExtensionW(ThemeFile);
+ if (pszExt)
+ {
+ if (_wcsicmp(pszExt, L".theme") == 0)
+ fType = THEME_FILE;
+ else if (_wcsicmp(pszExt, L".msstyles") == 0)
+ fType = STYLE_FILE;
+ } }
+ if (fType == UNKNOWN)
+ {
+ DPRINT1("EnableVisualTheme(): Unknown file '%S'\n",
ThemeFile);
+ return;
+ }
+ }
+
+ DPRINT1("Applying visual %s '%S'\n",
+ (fType == THEME_FILE) ? "theme" : "style",
+ ThemeFile ? ThemeFile : L"(Classic)");
+
+//
+// TODO: Use instead uxtheme!SetSystemVisualStyle() once it is implemented,
+//
https://stackoverflow.com/a/1036903
+//
https://pinvoke.net/default.aspx/uxtheme.SetSystemVisualStyle
+// or ApplyTheme(NULL, 0, NULL) for restoring the classic theme.
+//
+// NOTE: The '/Action:ActivateMSTheme' is ReactOS-specific.
+//
+
+ if (ThemeFile && (fType == THEME_FILE))
+ {
+ /* Retrieve the visual style specified in the theme file.
+ * If none, fall back to the classic theme. */
+ if (GetPrivateProfileStringW(L"VisualStyles", L"Path", NULL,
+ szStyleFile, _countof(szStyleFile), ThemeFile)
&& *szStyleFile)
+ {
+ /* Expand the path if possible */
+ ThemeFile = szStyleFile;
+ if (ExpandEnvironmentStringsW(ThemeFile, szPath, _countof(szPath)) != 0)
+ ThemeFile = szPath;
+ }
+ else
+ {
+ ThemeFile = NULL;
+ }
+
+ DPRINT1("--> Applying visual style '%S'\n",
+ ThemeFile ? ThemeFile : L"(Classic)");
+ }
+
+ if (ThemeFile)
+ {
+ WCHAR wszParams[1024];
+ // FIXME: L"desk.cpl desk,@Appearance" regression, see commit
50d260a7f0
+ PCWSTR format = L"desk.cpl,,2 /Action:ActivateMSTheme
/file:\"%s\"";
+
+ StringCchPrintfW(wszParams, _countof(wszParams), format, ThemeFile);
+ RunControlPanelApplet(hwndParent, wszParams);
+ }
+ else
+ {
+ RunControlPanelApplet(hwndParent, L"desk.cpl,,2
/Action:ActivateMSTheme");
+ }
+}
+
+
static VOID
WriteUserLocale(VOID)
{
@@ -1927,13 +2010,14 @@ ThemePageDlgProc(HWND hwndDlg,
/* Register the imagelist */
ListView_SetImageList(hListView, himl, LVSIL_NORMAL);
- /* Transparant background */
+ /* Transparent background */
ListView_SetBkColor(hListView, CLR_NONE);
ListView_SetTextBkColor(hListView, CLR_NONE);
/* Reduce the size between the items */
ListView_SetIconSpacing(hListView, 190, 173);
break;
}
+
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code)
{
@@ -1947,17 +2031,13 @@ ThemePageDlgProc(HWND hwndDlg,
if (Themes[iTheme].ThemeFile)
{
- WCHAR wszParams[1024];
WCHAR wszTheme[MAX_PATH];
- WCHAR* format = L"desk.cpl,,2 /Action:ActivateMSTheme
/file:\"%s\"";
-
SHGetFolderPathAndSubDirW(0, CSIDL_RESOURCES, NULL,
SHGFP_TYPE_DEFAULT, Themes[iTheme].ThemeFile, wszTheme);
- swprintf(wszParams, format, wszTheme);
- RunControlPanelApplet(hwndDlg, wszParams);
+ EnableVisualTheme(hwndDlg, wszTheme);
}
else
{
- RunControlPanelApplet(hwndDlg, L"desk.cpl,,2
/Action:ActivateMSTheme");
+ EnableVisualTheme(hwndDlg, Themes[iTheme].ThemeFile);
}
}
break;