reactos/win32ss/user/ntuser/simplecall.c

907 lines
24 KiB
C
Raw Normal View History

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: NtUserCallXxx call stubs
* FILE: win32ss/user/ntuser/simplecall.c
* PROGRAMERS: Ge van Geldorp (ge@gse.nl)
* Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/
#include <win32k.h>
DBG_DEFAULT_CHANNEL(UserMisc);
/* Registered logon process ID */
HANDLE gpidLogon = 0;
BOOL FASTCALL
co_IntRegisterLogonProcess(HANDLE ProcessId, BOOL Register)
{
NTSTATUS Status;
PEPROCESS Process;
Status = PsLookupProcessByProcessId(ProcessId, &Process);
if (!NT_SUCCESS(Status))
{
EngSetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
ProcessId = Process->UniqueProcessId;
ObDereferenceObject(Process);
if (Register)
{
/* Register the logon process */
if (gpidLogon != 0)
return FALSE;
gpidLogon = ProcessId;
}
else
{
/* Deregister the logon process */
if (gpidLogon != ProcessId)
return FALSE;
gpidLogon = 0;
}
return TRUE;
}
/*
* @unimplemented
*/
DWORD_PTR
APIENTRY
NtUserCallNoParam(DWORD Routine)
{
DWORD_PTR Result = 0;
TRACE("Enter NtUserCallNoParam\n");
UserEnterExclusive();
switch (Routine)
{
case NOPARAM_ROUTINE_CREATEMENU:
Result = (DWORD_PTR)UserCreateMenu(GetW32ThreadInfo()->rpdesk, FALSE);
break;
case NOPARAM_ROUTINE_CREATEMENUPOPUP:
Result = (DWORD_PTR)UserCreateMenu(GetW32ThreadInfo()->rpdesk, TRUE);
break;
case NOPARAM_ROUTINE_DESTROY_CARET:
Result = (DWORD_PTR)co_IntDestroyCaret(PsGetCurrentThread()->Tcb.Win32Thread);
break;
case NOPARAM_ROUTINE_INIT_MESSAGE_PUMP:
Result = (DWORD_PTR)IntInitMessagePumpHook();
break;
case NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP:
Result = (DWORD_PTR)IntUninitMessagePumpHook();
break;
case NOPARAM_ROUTINE_MSQCLEARWAKEMASK:
Result = (DWORD_PTR)IntMsqClearWakeMask();
break;
case NOPARAM_ROUTINE_GETMSESSAGEPOS:
{
PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
Result = (DWORD_PTR)MAKELONG(pti->ptLast.x, pti->ptLast.y);
break;
}
case NOPARAM_ROUTINE_RELEASECAPTURE:
Result = (DWORD_PTR)IntReleaseCapture();
break;
case NOPARAM_ROUTINE_LOADUSERAPIHOOK:
Result = UserLoadApiHook();
break;
case NOPARAM_ROUTINE_ZAPACTIVEANDFOUS:
{
PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
TRACE("Zapping the Active and Focus window out of the Queue!\n");
pti->MessageQueue->spwndFocus = NULL;
pti->MessageQueue->spwndActive = NULL;
Result = 0;
break;
}
/* this is a ReactOS only case and is needed for gui-on-demand */
case NOPARAM_ROUTINE_ISCONSOLEMODE:
Result = (ScreenDeviceContext == NULL);
break;
case NOPARAM_ROUTINE_UPDATEPERUSERIMMENABLING:
gpsi->dwSRVIFlags |= SRVINFO_IMM32; // Always set.
Result = TRUE; // Always return TRUE.
break;
default:
ERR("Calling invalid routine number 0x%x in NtUserCallNoParam\n", Routine);
EngSetLastError(ERROR_INVALID_PARAMETER);
break;
}
TRACE("Leave NtUserCallNoParam, ret=%p\n",(PVOID)Result);
UserLeave();
return Result;
}
/*
* @implemented
*/
DWORD_PTR
APIENTRY
NtUserCallOneParam(
DWORD_PTR Param,
DWORD Routine)
{
DWORD_PTR Result;
TRACE("Enter NtUserCallOneParam\n");
UserEnterExclusive();
switch (Routine)
{
case ONEPARAM_ROUTINE_POSTQUITMESSAGE:
{
PTHREADINFO pti;
pti = PsGetCurrentThreadWin32Thread();
MsqPostQuitMessage(pti, Param);
Result = TRUE;
break;
}
case ONEPARAM_ROUTINE_BEGINDEFERWNDPOS:
{
PSMWP psmwp;
HDWP hDwp = NULL;
INT count = (INT)Param;
if (count < 0)
{
EngSetLastError(ERROR_INVALID_PARAMETER);
Result = 0;
break;
}
/* Windows allows zero count, in which case it allocates context for 8 moves */
if (count == 0) count = 8;
psmwp = (PSMWP)UserCreateObject(gHandleTable,
NULL,
NULL,
(PHANDLE)&hDwp,
TYPE_SETWINDOWPOS,
sizeof(SMWP));
if (!psmwp)
{
Result = 0;
break;
}
psmwp->acvr = ExAllocatePoolWithTag(PagedPool, count * sizeof(CVR), USERTAG_SWP);
if (!psmwp->acvr)
{
UserDeleteObject(hDwp, TYPE_SETWINDOWPOS);
Result = 0;
break;
}
RtlZeroMemory(psmwp->acvr, count * sizeof(CVR));
psmwp->bHandle = TRUE;
psmwp->ccvr = 0; // actualCount
psmwp->ccvrAlloc = count; // suggestedCount
Result = (DWORD_PTR)hDwp;
break;
}
case ONEPARAM_ROUTINE_SHOWCURSOR:
Result = (DWORD_PTR)UserShowCursor((BOOL)Param);
break;
case ONEPARAM_ROUTINE_GETDESKTOPMAPPING:
{
PTHREADINFO ti;
ti = GetW32ThreadInfo();
if (ti != NULL)
{
/* Try convert the pointer to a user mode pointer if the desktop is
mapped into the process */
Result = (DWORD_PTR)DesktopHeapAddressToUser((PVOID)Param);
}
else
{
Result = 0;
}
break;
}
case ONEPARAM_ROUTINE_WINDOWFROMDC:
Result = (DWORD_PTR)IntWindowFromDC((HDC)Param);
break;
case ONEPARAM_ROUTINE_SWAPMOUSEBUTTON:
{
Result = gspv.bMouseBtnSwap;
gspv.bMouseBtnSwap = Param ? TRUE : FALSE;
gpsi->aiSysMet[SM_SWAPBUTTON] = gspv.bMouseBtnSwap;
break;
}
case ONEPARAM_ROUTINE_SETCARETBLINKTIME:
Result = (DWORD_PTR)IntSetCaretBlinkTime((UINT)Param);
break;
case ONEPARAM_ROUTINE_SETMESSAGEEXTRAINFO:
Result = (DWORD_PTR)MsqSetMessageExtraInfo((LPARAM)Param);
break;
case ONEPARAM_ROUTINE_CREATEEMPTYCUROBJECT:
{
if (!(Result = (DWORD_PTR)IntCreateCurIconHandle((DWORD)Param)))
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
Result = 0;
}
break;
}
case ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING:
{
BOOL Enable;
PPROCESSINFO Process = PsGetCurrentProcessWin32Process();
if (Process != NULL)
{
Enable = (BOOL)(Param != 0);
if (Enable)
{
Process->W32PF_flags &= ~W32PF_NOWINDOWGHOSTING;
}
else
{
Process->W32PF_flags |= W32PF_NOWINDOWGHOSTING;
}
Result = TRUE;
break;
}
Result = FALSE;
break;
}
case ONEPARAM_ROUTINE_GETINPUTEVENT:
Result = (DWORD_PTR)IntMsqSetWakeMask(Param);
break;
case ONEPARAM_ROUTINE_GETKEYBOARDTYPE:
Result = UserGetKeyboardType(Param);
break;
case ONEPARAM_ROUTINE_GETKEYBOARDLAYOUT:
Result = (DWORD_PTR)UserGetKeyboardLayout(Param);
break;
case ONEPARAM_ROUTINE_RELEASEDC:
Result = UserReleaseDC(NULL, (HDC) Param, FALSE);
break;
case ONEPARAM_ROUTINE_REALIZEPALETTE:
Result = UserRealizePalette((HDC) Param);
break;
case ONEPARAM_ROUTINE_GETQUEUESTATUS:
{
Result = IntGetQueueStatus((DWORD)Param);
break;
}
case ONEPARAM_ROUTINE_ENUMCLIPBOARDFORMATS:
/* FIXME: Should use UserEnterShared */
Result = UserEnumClipboardFormats(Param);
break;
case ONEPARAM_ROUTINE_GETCURSORPOS:
{
PPOINTL pptl;
PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
Result = TRUE;
if (pti->rpdesk != IntGetActiveDesktop())
{
Result = FALSE;
break;
}
_SEH2_TRY
{
ProbeForWrite((POINT*)Param,sizeof(POINT),1);
pptl = (PPOINTL)Param;
*pptl = gpsi->ptCursor;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Result = FALSE;
}
_SEH2_END;
break;
}
case ONEPARAM_ROUTINE_SETPROCDEFLAYOUT:
{
PPROCESSINFO ppi;
if (Param & LAYOUT_ORIENTATIONMASK || Param == LAYOUT_LTR)
{
ppi = PsGetCurrentProcessWin32Process();
ppi->dwLayout = Param;
Result = TRUE;
break;
}
EngSetLastError(ERROR_INVALID_PARAMETER);
Result = FALSE;
break;
}
case ONEPARAM_ROUTINE_GETPROCDEFLAYOUT:
{
PPROCESSINFO ppi;
PDWORD pdwLayout;
Result = TRUE;
if (PsGetCurrentProcess() == gpepCSRSS)
{
EngSetLastError(ERROR_INVALID_ACCESS);
Result = FALSE;
break;
}
ppi = PsGetCurrentProcessWin32Process();
_SEH2_TRY
{
pdwLayout = (PDWORD)Param;
*pdwLayout = ppi->dwLayout;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
SetLastNtError(_SEH2_GetExceptionCode());
Result = FALSE;
}
_SEH2_END;
break;
}
case ONEPARAM_ROUTINE_REPLYMESSAGE:
Result = co_MsqReplyMessage((LRESULT)Param);
break;
case ONEPARAM_ROUTINE_MESSAGEBEEP:
/* TODO: Implement sound sentry */
Result = UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_MESSAGE_BEEP, Param);
break;
case ONEPARAM_ROUTINE_CREATESYSTEMTHREADS:
Result = UserSystemThreadProc(Param);
break;
case ONEPARAM_ROUTINE_LOCKFOREGNDWINDOW:
Result = (DWORD_PTR)IntLockSetForegroundWindow(Param);
break;
case ONEPARAM_ROUTINE_ALLOWSETFOREGND:
Result = (DWORD_PTR)IntAllowSetForegroundWindow(Param);
break;
default:
ERR("Calling invalid routine number 0x%x in NtUserCallOneParam(), Param=0x%x\n",
Routine, Param);
EngSetLastError(ERROR_INVALID_PARAMETER);
Result = 0;
break;
}
TRACE("Leave NtUserCallOneParam, ret=%p\n", (PVOID)Result);
UserLeave();
return Result;
}
/*
* @implemented
*/
DWORD_PTR
APIENTRY
NtUserCallTwoParam(
DWORD_PTR Param1,
DWORD_PTR Param2,
DWORD Routine)
{
PWND Window;
DWORD_PTR Ret;
TRACE("Enter NtUserCallTwoParam\n");
UserEnterExclusive();
switch (Routine)
{
case TWOPARAM_ROUTINE_REDRAWTITLE:
{
Window = UserGetWindowObject((HWND)Param1);
Ret = (DWORD_PTR)UserPaintCaption(Window, (INT)Param2);
break;
}
case TWOPARAM_ROUTINE_SETMENUBARHEIGHT:
{
PMENU MenuObject = IntGetMenuObject((HMENU)Param1);
if (!MenuObject)
{
Ret = 0;
break;
}
if (Param2 > 0)
{
Ret = (MenuObject->cyMenu == (int)Param2);
MenuObject->cyMenu = (int)Param2;
}
else
Ret = (DWORD_PTR)MenuObject->cyMenu;
IntReleaseMenuObject(MenuObject);
break;
}
case TWOPARAM_ROUTINE_SETGUITHRDHANDLE:
{
PTHREADINFO pti = (PTHREADINFO)PsGetCurrentThreadWin32Thread();
ASSERT(pti->MessageQueue);
Ret = (DWORD_PTR)MsqSetStateWindow(pti, (ULONG)Param1, (HWND)Param2);
break;
}
case TWOPARAM_ROUTINE_ENABLEWINDOW:
Ret = IntEnableWindow((HWND)Param1, (BOOL)Param2);
break;
case TWOPARAM_ROUTINE_SHOWOWNEDPOPUPS:
{
Window = UserGetWindowObject((HWND)Param1);
if (!Window)
{
Ret = 0;
break;
}
Ret = (DWORD_PTR)IntShowOwnedPopups(Window, (BOOL)Param2);
break;
}
case TWOPARAM_ROUTINE_ROS_UPDATEUISTATE:
{
WPARAM wParam;
Window = UserGetWindowObject((HWND)Param1);
if (!Window)
{
Ret = 0;
break;
}
/* Unpack wParam */
wParam = MAKEWPARAM((Param2 >> 3) & 0x3,
Param2 & (UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE));
Ret = UserUpdateUiState(Window, wParam);
break;
}
case TWOPARAM_ROUTINE_SWITCHTOTHISWINDOW:
{
HWND hwnd = (HWND)Param1;
BOOL fAltTab = (BOOL)Param2;
Ret = 0;
Window = UserGetWindowObject(hwnd);
if (!Window)
{
break;
}
[WIN32SS:USER] Some minimal work and fixes concerning message queues timeouts. CORE-15147 - Rename CLIENTTHREADINFO::tickLastMsgChecked into timeLastRead as documented in https://reactos.org/wiki/Techwiki:Win32k/CLIENTTHREADINFO . This is the last time the message queue was read. - This is the structure member one must compare against the current tick count timestamp in order to heuristically determine whether a message queue thread is hung!! Fix MsqIsHung() in accordance, add extra debug logging in order to help us determining which of our code present regular GUI hangs, and add as well an extra "TimeOut" parameter so as not to hardcode a fixed value within that function but instead allowing its caller to specify possible different values. - THREADINFO::timeLast is on the contrary the last message time stamp, and will definitively differ from CLIENTTHREADINFO::timeLastRead . It should only be used for information purposes! - Accordingly, in NtUserGetThreadState()::THREADSTATE_UPTIMELASTREAD and in InitThreadCallback(), only (re-)initialize the timeLastRead member of the CLIENTTHREADINFO structure of the THREADINFO of interest. - In co_IntPeekMessage(), update more often the timeLastRead timestamp whenever the current message queue has been read (but NOT timeLast!! That one will be updated ONLY WHEN a message is found!). - In co_IntSendMessageTimeoutSingle() first check whether the window to which we send the message is being destroyed, before checking for queue hangs etc. Collapse the logic checks for queue hang and increase the hang timeout check to 4 times MSQ_HUNG (== 4 * 5 seconds) and display a debug trace.
2019-12-29 14:10:19 +00:00
if (MsqIsHung(Window->head.pti, MSQ_HUNG))
{
// TODO: Make the window ghosted and activate.
break;
}
if (fAltTab)
{
if (Window->style & WS_MINIMIZE)
{
UserPostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
}
/* bring window to top and activate */
co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING |
SWP_NOOWNERZORDER | SWP_ASYNCWINDOWPOS);
}
else
{
UserSetActiveWindow(Window);
}
break;
}
case TWOPARAM_ROUTINE_SETCARETPOS:
Ret = (DWORD_PTR)co_IntSetCaretPos((int)Param1, (int)Param2);
break;
case TWOPARAM_ROUTINE_REGISTERLOGONPROCESS:
Ret = (DWORD_PTR)co_IntRegisterLogonProcess((HANDLE)Param1, (BOOL)Param2);
break;
case TWOPARAM_ROUTINE_SETCURSORPOS:
Ret = (DWORD_PTR)UserSetCursorPos((int)Param1, (int)Param2, 0, 0, FALSE);
break;
case TWOPARAM_ROUTINE_UNHOOKWINDOWSHOOK:
Ret = IntUnhookWindowsHook((int)Param1, (HOOKPROC)Param2);
break;
default:
ERR("Calling invalid routine number 0x%x in NtUserCallTwoParam(), Param1=0x%x Parm2=0x%x\n",
Routine, Param1, Param2);
EngSetLastError(ERROR_INVALID_PARAMETER);
Ret = 0;
}
TRACE("Leave NtUserCallTwoParam, ret=%p\n", (PVOID)Ret);
UserLeave();
return Ret;
}
/*
* @unimplemented
*/
BOOL
APIENTRY
NtUserCallHwndLock(
HWND hWnd,
DWORD Routine)
{
BOOL Ret = FALSE;
PWND Window;
USER_REFERENCE_ENTRY Ref;
TRACE("Enter NtUserCallHwndLock\n");
UserEnterExclusive();
if (!(Window = UserGetWindowObject(hWnd)))
{
Ret = FALSE;
goto Exit;
}
UserRefObjectCo(Window, &Ref);
/* FIXME: Routine can be 0x53 - 0x5E */
switch (Routine)
{
case HWNDLOCK_ROUTINE_ARRANGEICONICWINDOWS:
co_WinPosArrangeIconicWindows(Window);
break;
case HWNDLOCK_ROUTINE_DRAWMENUBAR:
{
TRACE("HWNDLOCK_ROUTINE_DRAWMENUBAR\n");
Ret = TRUE;
if ((Window->style & (WS_CHILD | WS_POPUP)) != WS_CHILD)
co_WinPosSetWindowPos(Window,
HWND_DESKTOP,
0, 0, 0, 0,
SWP_NOSIZE |
SWP_NOMOVE |
SWP_NOZORDER |
SWP_NOACTIVATE |
SWP_FRAMECHANGED);
break;
}
case HWNDLOCK_ROUTINE_REDRAWFRAME:
co_WinPosSetWindowPos(Window,
HWND_DESKTOP,
0, 0, 0, 0,
SWP_NOSIZE |
SWP_NOMOVE |
SWP_NOZORDER |
SWP_NOACTIVATE |
SWP_FRAMECHANGED);
Ret = TRUE;
break;
case HWNDLOCK_ROUTINE_REDRAWFRAMEANDHOOK:
co_WinPosSetWindowPos(Window,
HWND_DESKTOP,
0, 0, 0, 0,
SWP_NOSIZE |
SWP_NOMOVE |
SWP_NOZORDER |
SWP_NOACTIVATE |
SWP_FRAMECHANGED);
if (!Window->spwndOwner && !IntGetParent(Window))
{
co_IntShellHookNotify(HSHELL_REDRAW, (WPARAM)hWnd, FALSE); // FIXME Flashing?
}
Ret = TRUE;
break;
case HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOW:
TRACE("co_IntSetForegroundWindow 1 0x%p\n", hWnd);
Ret = co_IntSetForegroundWindow(Window);
TRACE("co_IntSetForegroundWindow 2 0x%p\n", hWnd);
break;
case HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOWMOUSE:
TRACE("co_IntSetForegroundWindow M 1 0x%p\n", hWnd);
Ret = co_IntSetForegroundWindowMouse(Window);
TRACE("co_IntSetForegroundWindow M 2 0x%p\n", hWnd);
break;
case HWNDLOCK_ROUTINE_UPDATEWINDOW:
co_IntUpdateWindows(Window, RDW_ALLCHILDREN, FALSE);
Ret = TRUE;
break;
}
UserDerefObjectCo(Window);
Exit:
TRACE("Leave NtUserCallHwndLock, ret=%u\n", Ret);
UserLeave();
return Ret;
}
/*
* @unimplemented
*/
HWND
APIENTRY
NtUserCallHwndOpt(
HWND hWnd,
DWORD Routine)
{
switch (Routine)
{
case HWNDOPT_ROUTINE_SETPROGMANWINDOW:
GetW32ThreadInfo()->pDeskInfo->hProgmanWindow = hWnd;
break;
case HWNDOPT_ROUTINE_SETTASKMANWINDOW:
GetW32ThreadInfo()->pDeskInfo->hTaskManWindow = hWnd;
break;
}
return hWnd;
}
DWORD
APIENTRY
NtUserCallHwnd(
HWND hWnd,
DWORD Routine)
{
switch (Routine)
{
case HWND_ROUTINE_GETWNDCONTEXTHLPID:
{
PWND Window;
DWORD HelpId;
UserEnterShared();
if (!(Window = UserGetWindowObject(hWnd)))
{
UserLeave();
return 0;
}
HelpId = (DWORD)(DWORD_PTR)UserGetProp(Window, gpsi->atomContextHelpIdProp, TRUE);
UserLeave();
return HelpId;
}
case HWND_ROUTINE_REGISTERSHELLHOOKWINDOW:
if (IntIsWindow(hWnd))
return IntRegisterShellHookWindow(hWnd);
return FALSE;
break;
case HWND_ROUTINE_DEREGISTERSHELLHOOKWINDOW:
if (IntIsWindow(hWnd))
return IntDeRegisterShellHookWindow(hWnd);
return FALSE;
case HWND_ROUTINE_SETMSGBOX:
{
PWND Window;
UserEnterExclusive();
if ((Window = UserGetWindowObject(hWnd)))
{
Window->state |= WNDS_MSGBOX;
}
UserLeave();
return FALSE;
}
}
STUB;
return 0;
}
DWORD
APIENTRY
NtUserCallHwndParam(
HWND hWnd,
DWORD_PTR Param,
DWORD Routine)
{
switch (Routine)
{
case HWNDPARAM_ROUTINE_KILLSYSTEMTIMER:
return IntKillTimer(UserGetWindowObject(hWnd), (UINT_PTR)Param, TRUE);
case HWNDPARAM_ROUTINE_SETWNDCONTEXTHLPID:
{
PWND Window;
UserEnterExclusive();
if (!(Window = UserGetWindowObject(hWnd)))
{
UserLeave();
return FALSE;
}
if (Param)
UserSetProp(Window, gpsi->atomContextHelpIdProp, (HANDLE)Param, TRUE);
else
UserRemoveProp(Window, gpsi->atomContextHelpIdProp, TRUE);
UserLeave();
return TRUE;
}
case HWNDPARAM_ROUTINE_SETDIALOGPOINTER:
{
PWND pWnd;
USER_REFERENCE_ENTRY Ref;
UserEnterExclusive();
if (!(pWnd = UserGetWindowObject(hWnd)))
{
UserLeave();
return 0;
}
UserRefObjectCo(pWnd, &Ref);
if (pWnd->head.pti->ppi == PsGetCurrentProcessWin32Process() &&
pWnd->cbwndExtra >= DLGWINDOWEXTRA &&
!(pWnd->state & WNDS_SERVERSIDEWINDOWPROC))
{
pWnd->DialogPointer = (PVOID)Param;
if (Param)
{
if (!pWnd->fnid) pWnd->fnid = FNID_DIALOG;
pWnd->state |= WNDS_DIALOGWINDOW;
}
else
{
pWnd->fnid |= FNID_DESTROY;
pWnd->state &= ~WNDS_DIALOGWINDOW;
}
}
UserDerefObjectCo(pWnd);
UserLeave();
return 0;
}
case HWNDPARAM_ROUTINE_ROS_NOTIFYWINEVENT:
{
PWND pWnd;
PNOTIFYEVENT pne;
UserEnterExclusive();
pne = (PNOTIFYEVENT)Param;
if (hWnd)
pWnd = UserGetWindowObject(hWnd);
else
pWnd = NULL;
IntNotifyWinEvent(pne->event, pWnd, pne->idObject, pne->idChild, pne->flags);
UserLeave();
return 0;
}
case HWNDPARAM_ROUTINE_CLEARWINDOWSTATE:
{
PWND pWnd;
UserEnterExclusive();
pWnd = UserGetWindowObject(hWnd);
if (pWnd) IntClearWindowState(pWnd, (UINT)Param);
UserLeave();
return 0;
}
case HWNDPARAM_ROUTINE_SETWINDOWSTATE:
{
PWND pWnd;
UserEnterExclusive();
pWnd = UserGetWindowObject(hWnd);
if (pWnd) IntSetWindowState(pWnd, (UINT)Param);
UserLeave();
return 0;
}
}
STUB;
return 0;
}
DWORD
APIENTRY
NtUserCallHwndParamLock(
HWND hWnd,
DWORD_PTR Param,
DWORD Routine)
{
DWORD Ret = FALSE;
PWND Window;
USER_REFERENCE_ENTRY Ref;
TRACE("Enter NtUserCallHwndParamLock\n");
UserEnterExclusive();
if (!(Window = UserGetWindowObject(hWnd)))
{
Ret = FALSE;
goto Exit;
}
UserRefObjectCo(Window, &Ref);
switch (Routine)
{
case TWOPARAM_ROUTINE_VALIDATERGN:
{
PREGION Rgn = REGION_LockRgn((HRGN)Param);
Ret = (DWORD)co_UserRedrawWindow(Window, NULL, Rgn, RDW_VALIDATE);
if (Rgn) REGION_UnlockRgn(Rgn);
break;
}
}
UserDerefObjectCo(Window);
Exit:
TRACE("Leave NtUserCallHwndParamLock, ret=%lu\n", Ret);
UserLeave();
return Ret;
}
/* EOF */