https://git.reactos.org/?p=reactos.git;a=commitdiff;h=90de2b660b12919c2f60f2f31ad41e37c123d662

commit 90de2b660b12919c2f60f2f31ad41e37c123d662
Author:     Doug Lyons <dougly...@douglyons.com>
AuthorDate: Sun Aug 4 02:53:04 2024 -0500
Commit:     GitHub <nore...@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;
                   }
                }

Reply via email to