https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b3a25bcf8bdebb4fde966…
commit b3a25bcf8bdebb4fde966449032777857a08dcd1
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Thu Oct 5 22:42:17 2023 +0200
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Wed Oct 18 21:45:39 2023 +0200
[DESK] Reimplement InstallScreenSaverW to behave similarly to Windows' one
(#5766)
CORE-6812 ; see also commit ff0951356 (r66688)
This function "just" changes the per-user SCRNSAVE.EXE registry value
to point to the new specified file, changes the SPI values and opens
the desk.cpl "Screensaver" property tab for letting the user change
the new selected screensaver properties.
In particular, it does *NOT* copy the specified file to System32 or
anything else (and doesn't verify that it is a valid PE executable).
Our previous implementation did none of that, and was also relying on
some private setupapi functions.
We now behave closer to Windows' desk.cpl.
Additionally:
- ReactOS-specific feature (compile-time define) disabled by default:
Verify that the specified file actually exists, before changing
the screensaver.
- Use NDEBUG, disabling DPRINT by default;
- Improve InstallScreenSaver[A,W] spec entries;
- Remove NUM_APPLETS define and use _countof() instead.
---
dll/cpl/desk/desk.c | 129 ++++++++++++++++++++++++++++++++++---------------
dll/cpl/desk/desk.spec | 5 +-
2 files changed, 94 insertions(+), 40 deletions(-)
diff --git a/dll/cpl/desk/desk.c b/dll/cpl/desk/desk.c
index 0bbfc7a4a0e..ce780332d91 100644
--- a/dll/cpl/desk/desk.c
+++ b/dll/cpl/desk/desk.c
@@ -13,9 +13,17 @@
#include <cplext.h>
#include <winnls.h>
+#define NDEBUG
#include <debug.h>
-#define NUM_APPLETS (1)
+
+/* Enable this for InstallScreenSaverW() to determine a possible full path
+ * to the specified screensaver file, verify its existence and use it.
+ * (NOTE: This is not Windows desk.cpl-compatible.) */
+// #define CHECK_SCR_FULL_PATH
+
+
+VOID WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow);
static LONG APIENTRY DisplayApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam);
@@ -26,11 +34,11 @@ INT_PTR CALLBACK AppearancePageProc(HWND hwndDlg, UINT uMsg, WPARAM
wParam, LPAR
INT_PTR CALLBACK SettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM
lParam);
UINT CALLBACK SettingsPageCallbackProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp);
-HINSTANCE hApplet = 0;
-HWND hCPLWindow;
+HINSTANCE hApplet = NULL;
+HWND hCPLWindow = NULL;
/* Applets */
-APPLET Applets[NUM_APPLETS] =
+APPLET Applets[] =
{
{
IDC_DESK_ICON,
@@ -211,8 +219,8 @@ DisplayApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam)
g_GlobalData.bmMonHeight = bitmap.bmHeight;
}
- ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
- psh.dwSize = sizeof(PROPSHEETHEADER);
+ ZeroMemory(&psh, sizeof(psh));
+ psh.dwSize = sizeof(psh);
psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE | PSH_USEICONID;
psh.hwndParent = hCPLWindow;
psh.hInstance = hApplet;
@@ -226,7 +234,7 @@ DisplayApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam)
/* Allow shell extensions to replace the background page */
hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER
TEXT("\\Desk"), MAX_DESK_PAGES - psh.nPages);
- for (i = 0; i != sizeof(PropPages) / sizeof(PropPages[0]); i++)
+ for (i = 0; i < _countof(PropPages); i++)
{
if (pwszSelectedTab && wcsicmp(pwszSelectedTab, PropPages[i].Name) ==
0)
psh.nStartPage = i;
@@ -276,10 +284,10 @@ CPlApplet(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
return TRUE;
case CPL_GETCOUNT:
- return NUM_APPLETS;
+ return _countof(Applets);
case CPL_INQUIRE:
- if (i < NUM_APPLETS)
+ if (i < _countof(Applets))
{
CPLINFO *CPlInfo = (CPLINFO*)lParam2;
CPlInfo->lData = 0;
@@ -294,14 +302,14 @@ CPlApplet(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
break;
case CPL_DBLCLK:
- if (i < NUM_APPLETS)
+ if (i < _countof(Applets))
Applets[i].AppletProc(hwndCPl, uMsg, lParam1, lParam2);
else
return TRUE;
break;
case CPL_STARTWPARMSW:
- if (i < NUM_APPLETS)
+ if (i < _countof(Applets))
return Applets[i].AppletProc(hwndCPl, uMsg, lParam1, lParam2);
break;
}
@@ -317,45 +325,90 @@ InstallScreenSaverW(
IN LPCWSTR pszFile,
IN UINT nCmdShow)
{
- WCHAR pszSystemDir[MAX_PATH];
- WCHAR pszDrive[3];
- WCHAR pszPath[MAX_PATH];
- WCHAR pszFilename[MAX_PATH];
- WCHAR pszExt[MAX_PATH];
- LPWSTR pszOutName;
- UINT uCompressionType=FILE_COMPRESSION_NONE;
- DWORD dwSourceSize;
- DWORD dwTargetSize;
- DWORD rc;
+ LRESULT rc;
+ HKEY regKey;
+ INT Timeout;
+#ifdef CHECK_SCR_FULL_PATH
+ HANDLE hFile;
+ WIN32_FIND_DATAW fdFile;
+#endif
+ DWORD dwLen;
+ WCHAR szFullPath[MAX_PATH];
if (!pszFile)
{
- DPRINT("InstallScreenSaver() null file\n");
+ DPRINT1("InstallScreenSaver() null file\n");
SetLastError(ERROR_INVALID_PARAMETER);
return;
}
DPRINT("InstallScreenSaver() Installing screensaver %ls\n", pszFile);
- rc = SetupGetFileCompressionInfoW(pszFile, &pszOutName, &dwSourceSize,
&dwTargetSize, &uCompressionType);
- if (ERROR_SUCCESS != rc)
+#ifdef CHECK_SCR_FULL_PATH
+ /* Retrieve the actual path to the file and verify whether it exists */
+ dwLen = GetFullPathNameW(pszFile, _countof(szFullPath), szFullPath, NULL);
+ if (dwLen == 0 || dwLen > _countof(szFullPath))
{
- DPRINT("InstallScreenSaver() SetupGetFileCompressionInfo failed with error
0x%lx\n", rc);
- SetLastError(rc);
+ DPRINT1("InstallScreenSaver() File %ls not accessible\n", pszFile);
return;
}
- if (!GetSystemDirectoryW((LPWSTR)pszSystemDir, sizeof(pszSystemDir)/sizeof(WCHAR)))
+ hFile = FindFirstFile(szFullPath, &fdFile);
+ if (hFile == INVALID_HANDLE_VALUE)
{
- MyFree(pszOutName);
- DPRINT("InstallScreenSaver() GetSystemDirectory failed with error
0x%lx\n", GetLastError());
+ DPRINT1("InstallScreenSaver() File %ls not found\n", pszFile);
return;
}
- _wsplitpath(pszOutName, pszDrive, pszPath, pszFilename, pszExt);
- MyFree(pszOutName);
- StringCbCatW(pszSystemDir, sizeof(pszSystemDir), L"\\");
- StringCbCatW(pszSystemDir, sizeof(pszSystemDir), pszFilename);
- StringCbCatW(pszSystemDir, sizeof(pszSystemDir), pszExt);
- rc = SetupDecompressOrCopyFileW(pszFile, pszSystemDir, &uCompressionType);
- DPRINT("InstallScreenSaver() Copying to %ls, compression type %d return
0x%lx\n", pszFile, uCompressionType, rc);
+ FindClose(hFile);
+ /* Use the full file path from now on */
+ pszFile = szFullPath;
+#endif
+
+ rc = RegOpenKeyExW(HKEY_CURRENT_USER,
+ L"Control Panel\\Desktop",
+ 0,
+ KEY_SET_VALUE,
+ ®Key);
+ if (rc == ERROR_SUCCESS)
+ {
+ /* Set the screensaver */
+ SIZE_T Length = (wcslen(pszFile) + 1) * sizeof(WCHAR);
+ rc = RegSetValueExW(regKey,
+ L"SCRNSAVE.EXE",
+ 0,
+ REG_SZ,
+ (PBYTE)pszFile,
+ (DWORD)Length);
+ RegCloseKey(regKey);
+ }
+ if (rc != ERROR_SUCCESS)
+ {
+ DPRINT1("InstallScreenSaver() Could not change the current
screensaver\n");
+ return;
+ }
+
+ SystemParametersInfoW(SPI_SETSCREENSAVEACTIVE, TRUE, 0, SPIF_UPDATEINIFILE);
+
+ /* If no screensaver timeout is present, default to 10 minutes (600 seconds) */
+ Timeout = 0;
+ if (!SystemParametersInfoW(SPI_GETSCREENSAVETIMEOUT, 0, &Timeout, 0) || (Timeout
<= 0))
+ SystemParametersInfoW(SPI_SETSCREENSAVETIMEOUT, 600, 0, SPIF_UPDATEINIFILE);
+
+ /* Retrieve the name of this current instance of desk.cpl */
+ dwLen = GetModuleFileNameW(hApplet, szFullPath, _countof(szFullPath));
+ if ((dwLen == 0) || (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
+ {
+ /* We failed, copy the default value */
+ StringCchCopyW(szFullPath, _countof(szFullPath), L"desk.cpl");
+ }
+
+ /* Build the desk.cpl command-line to start the ScreenSaver page.
+ * Equivalent to: "desk.cpl,ScreenSaver,@ScreenSaver" */
+ rc = StringCchCatW(szFullPath, _countof(szFullPath), L",,1");
+ if (FAILED(rc))
+ return;
+
+ /* Open the ScreenSaver page in this desk.cpl instance */
+ DPRINT("InstallScreenSaver() Starting '%ls'\n", szFullPath);
+ Control_RunDLLW(hWindow, hInstance, szFullPath, nCmdShow);
}
void
@@ -371,7 +424,7 @@ InstallScreenSaverA(
if (!pszFile)
{
- DPRINT("InstallScreenSaver() null file\n");
+ DPRINT1("InstallScreenSaver() null file\n");
SetLastError(ERROR_INVALID_PARAMETER);
return;
}
@@ -393,7 +446,7 @@ InstallScreenSaverA(
}
if (!lpwString)
{
- DPRINT("InstallScreenSaver() not enough memory to convert string to
unicode\n");
+ DPRINT1("InstallScreenSaver() not enough memory to convert string to
unicode\n");
return;
}
diff --git a/dll/cpl/desk/desk.spec b/dll/cpl/desk/desk.spec
index ab028545161..b108c44825f 100644
--- a/dll/cpl/desk/desk.spec
+++ b/dll/cpl/desk/desk.spec
@@ -1,6 +1,7 @@
@ stdcall CPlApplet(ptr long ptr ptr)
@ stdcall DisplayClassInstaller(long ptr ptr)
@ stdcall DisplaySaveSettings(ptr ptr)
-@ stdcall InstallScreenSaverW(long long ptr long)
-@ stdcall InstallScreenSaverA(long long ptr long)
+@ stdcall InstallScreenSaver(ptr ptr str long) InstallScreenSaverA
+@ stdcall InstallScreenSaverA(ptr ptr str long)
+@ stdcall InstallScreenSaverW(ptr ptr wstr long)
@ stdcall MonitorClassInstaller(long ptr ptr)