[NTUSER] Implement BroadcastSystemMessage with 'Environment' parameter

CORE-19372
CORE-19583
This commit is contained in:
Doug Lyons 2024-05-13 22:55:54 -05:00
parent 1a162375f9
commit b87a3351a4

View file

@ -12,9 +12,33 @@
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)
#define EXCEPTION_ACCESS_VIOLATION ((DWORD)0xC0000005)
/* 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. */
INT PosInArray(WCHAR String[])
{
INT i;
INT End = ARRAYSIZE(StrUserKernel);
for (i = 0; i < End; ++i)
{
if (wcsncmp(String, StrUserKernel[i], sizeof(StrUserKernel[0])) == 0)
return i;
}
return -1;
}
NTSTATUS FASTCALL
IntInitMessageImpl(VOID)
{
@ -459,8 +483,30 @@ CopyMsgToKernelMem(MSG *KernelModeMsg, MSG *UserModeMsg, PMSGMEMORY MsgMemoryEnt
/* Copy data if required */
if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_READ))
{
WCHAR lParamMsg[sizeof(StrUserKernel[0])/2 + 1] = { 0 };
TRACE("Copy Message %u from usermode buffer\n", KernelModeMsg->message);
Status = MmCopyFromCaller(KernelMem, (PVOID) UserModeMsg->lParam, Size);
_SEH2_TRY
{
if (UserModeMsg->lParam)
RtlCopyMemory( lParamMsg, (WCHAR*)UserModeMsg->lParam, sizeof(lParamMsg));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_SEH2_YIELD(return EXCEPTION_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;
}
else
Status = MmCopyFromCaller(KernelMem, (PVOID) UserModeMsg->lParam, Size);
if (! NT_SUCCESS(Status))
{
ERR("Failed to copy message to kernel: invalid usermode lParam buffer\n");
@ -2721,6 +2767,12 @@ NtUserMessageCall( HWND hWnd,
}
ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
}
if (lParam && !wParam && wcscmp((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;
}
}