https://git.reactos.org/?p=reactos.git;a=commitdiff;h=90de2b660b12919c2f60f…
commit 90de2b660b12919c2f60f2f31ad41e37c123d662
Author: Doug Lyons <douglyons(a)douglyons.com>
AuthorDate: Sun Aug 4 02:53:04 2024 -0500
Commit: GitHub <noreply(a)github.com>
CommitDate: Sun Aug 4 02:53:04 2024 -0500
[NTUSER] Implement BroadcastSystemMessage with 'Environment' parameter (#6884)
* [NTUSER] Implement BroadcastSystemMessage with 'Environment' parameter
CORE-19372
CORE-19583
* Changes based on reviewer comments.
* Make sure that lParamMsg has a UNICODE_NULL in it.
* Skip extra handling of 1 word messsages.
---
win32ss/user/ntuser/message.c | 68 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 65 insertions(+), 3 deletions(-)
diff --git a/win32ss/user/ntuser/message.c b/win32ss/user/ntuser/message.c
index ce9da97c1a5..c86754abc56 100644
--- a/win32ss/user/ntuser/message.c
+++ b/win32ss/user/ntuser/message.c
@@ -13,8 +13,30 @@ DBG_DEFAULT_CHANNEL(UserMsg);
#define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
+/* Strings that are OK to pass between user and kernel mode.
+ * There may be other strings needed that can easily be added here. */
+WCHAR StrUserKernel[3][20] = {{L"intl"}, {L"Environment"}, {L"Policy"}};
+
/* FUNCTIONS *****************************************************************/
+/* PosInArray checks for strings that can pass between user and kernel mode.
+ * See: https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-settingchange
+ * It mentions 'Environment', 'intl', and 'Policy'.
+ * These strings are enumerated in the StrUserKernel definition.
+ * Returns: A positive integer indicating its position in the array if the
+ * string is found, or returns a minus one (-1) if the string is not found. */
+static INT PosInArray(_In_ PCWSTR String)
+{
+ INT i;
+
+ for (i = 0; i < ARRAYSIZE(StrUserKernel); ++i)
+ {
+ if (wcsncmp(String, StrUserKernel[i], _countof(StrUserKernel[0])) == 0)
+ return i;
+ }
+ return -1;
+}
+
NTSTATUS FASTCALL
IntInitMessageImpl(VOID)
{
@@ -431,7 +453,7 @@ CopyMsgToKernelMem(MSG *KernelModeMsg, MSG *UserModeMsg, PMSGMEMORY MsgMemoryEnt
NTSTATUS Status;
PVOID KernelMem;
- UINT Size;
+ UINT Size, i;
*KernelModeMsg = *UserModeMsg;
@@ -460,8 +482,42 @@ CopyMsgToKernelMem(MSG *KernelModeMsg, MSG *UserModeMsg, PMSGMEMORY MsgMemoryEnt
if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_READ))
{
TRACE("Copy Message %u from usermode buffer\n", KernelModeMsg->message);
- Status = MmCopyFromCaller(KernelMem, (PVOID) UserModeMsg->lParam, Size);
- if (! NT_SUCCESS(Status))
+ /* Don't do extra testing for 1 word messages. For examples see
+ * https://wiki.winehq.org/List_Of_Windows_Messages. */
+ if (Size > 1)
+ {
+ WCHAR lParamMsg[_countof(StrUserKernel[0]) + 1] = { 0 };
+ _SEH2_TRY
+ {
+ if (UserModeMsg->lParam)
+ RtlCopyMemory(lParamMsg, (WCHAR*)UserModeMsg->lParam, sizeof(lParamMsg));
+ /* Make sure that the last WCHAR is a UNICODE_NULL */
+ for (i = 0; i < ARRAYSIZE(lParamMsg); ++i)
+ {
+ if (lParamMsg[i] == 0)
+ break;
+ }
+ /* If we did not find a UNICODE_NULL, then set last WCHAR to one */
+ if (i == ARRAYSIZE(lParamMsg))
+ lParamMsg[_countof(StrUserKernel[0])] = UNICODE_NULL;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ _SEH2_YIELD(return STATUS_ACCESS_VIOLATION);
+ }
+ _SEH2_END;
+
+ if (UserModeMsg->lParam && !UserModeMsg->wParam &&
+ PosInArray(lParamMsg) >= 0)
+ {
+ TRACE("Copy String '%S' from usermode buffer\n", lParamMsg);
+ wcscpy(KernelMem, lParamMsg);
+ return STATUS_SUCCESS;
+ }
+ }
+
+ Status = MmCopyFromCaller(KernelMem, (PVOID)UserModeMsg->lParam, Size);
+ if (!NT_SUCCESS(Status))
{
ERR("Failed to copy message to kernel: invalid usermode lParam buffer\n");
ExFreePoolWithTag(KernelMem, TAG_MSG);
@@ -2721,6 +2777,12 @@ NtUserMessageCall( HWND hWnd,
}
ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
}
+ if (lParam && !wParam && wcsicmp((WCHAR*)lParam, L"Environment") == 0)
+ {
+ /* Handle Broadcast of WM_SETTINGCHAGE for Environment */
+ co_IntDoSendMessage(HWND_BROADCAST, WM_SETTINGCHANGE,
+ 0, (LPARAM)L"Environment", 0);
+ }
Ret = TRUE;
}
}