mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
10309 lines
234 KiB
10309 lines
234 KiB
/****************************** Module Header ******************************\
|
|
* Module Name: ntstubs.c
|
|
*
|
|
* Copyright (c) 1985-95, Microsoft Corporation
|
|
*
|
|
* Kernel-mode stubs
|
|
*
|
|
* History:
|
|
* 03-16-95 JimA Created.
|
|
* 08-12-96 jparsons Added lparam validate for WM_NCCREATE [51986]
|
|
\***************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
/*
|
|
* Setup and control macros
|
|
*/
|
|
#define BEGINRECV(type, err) \
|
|
type retval; \
|
|
type errret = err; \
|
|
EnterCrit();
|
|
|
|
#define BEGINRECV_SHARED(type, err) \
|
|
type retval; \
|
|
type errret = err; \
|
|
EnterSharedCrit();
|
|
|
|
#define BEGINRECV_VOID() \
|
|
EnterCrit();
|
|
|
|
#define BEGINRECV_HWND(type, err, hwnd) \
|
|
type retval; \
|
|
type errret = err; \
|
|
PWND pwnd; \
|
|
EnterCrit(); \
|
|
if ((pwnd = ValidateHwnd((hwnd))) == NULL) { \
|
|
retval = errret; \
|
|
goto errorexit; \
|
|
}
|
|
|
|
#define BEGINRECV_HWND_VOID(hwnd) \
|
|
PWND pwnd; \
|
|
EnterCrit(); \
|
|
if ((pwnd = ValidateHwnd((hwnd))) == NULL) { \
|
|
goto errorexit; \
|
|
}
|
|
|
|
#define BEGINRECV_HWND_SHARED(type, err, hwnd) \
|
|
type retval; \
|
|
type errret = err; \
|
|
PWND pwnd; \
|
|
EnterSharedCrit(); \
|
|
if ((pwnd = ValidateHwnd((hwnd))) == NULL) { \
|
|
retval = errret; \
|
|
goto errorexit; \
|
|
}
|
|
|
|
#define BEGINRECV_HWNDLOCK(type, err, hwnd) \
|
|
type retval; \
|
|
type errret = err; \
|
|
PWND pwnd; \
|
|
TL tlpwnd; \
|
|
PTHREADINFO ptiCurrent; \
|
|
EnterCrit(); \
|
|
if ((pwnd = ValidateHwnd((hwnd))) == NULL) { \
|
|
LeaveCrit(); \
|
|
return err; \
|
|
} \
|
|
ptiCurrent = PtiCurrent(); \
|
|
ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd);
|
|
|
|
#define BEGINRECV_HWNDLOCK_OPT(type, err, hwnd) \
|
|
type retval; \
|
|
type errret = err; \
|
|
PWND pwnd; \
|
|
TL tlpwnd; \
|
|
PTHREADINFO ptiCurrent; \
|
|
EnterCrit(); \
|
|
if (hwnd) { \
|
|
if ((pwnd = ValidateHwnd(hwnd)) == NULL) { \
|
|
LeaveCrit(); \
|
|
return err; \
|
|
} \
|
|
} else { \
|
|
pwnd = NULL; \
|
|
} \
|
|
ptiCurrent = PtiCurrent(); \
|
|
ThreadLockWithPti(ptiCurrent, pwnd, &tlpwnd);
|
|
|
|
#define BEGINRECV_HWNDLOCK_VOID(hwnd) \
|
|
PWND pwnd; \
|
|
TL tlpwnd; \
|
|
PTHREADINFO ptiCurrent; \
|
|
EnterCrit(); \
|
|
if ((pwnd = ValidateHwnd((hwnd))) == NULL) { \
|
|
LeaveCrit(); \
|
|
return; \
|
|
} \
|
|
ptiCurrent = PtiCurrent(); \
|
|
ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd);
|
|
|
|
#define CLEANUPRECV() \
|
|
cleanupexit:
|
|
|
|
#define ENDRECV() \
|
|
goto errorexit; \
|
|
errorexit: \
|
|
LeaveCrit(); \
|
|
return retval;
|
|
|
|
#define ENDRECV_VOID() \
|
|
goto errorexit; \
|
|
errorexit: \
|
|
LeaveCrit(); \
|
|
return;
|
|
|
|
#define ENDRECV_HWND() \
|
|
goto errorexit; \
|
|
errorexit: \
|
|
LeaveCrit(); \
|
|
return retval;
|
|
|
|
#define ENDRECV_HWNDLOCK() \
|
|
goto errorexit; \
|
|
errorexit: \
|
|
ThreadUnlock(&tlpwnd); \
|
|
LeaveCrit(); \
|
|
return retval;
|
|
|
|
#define ENDRECV_HWNDLOCK_VOID() \
|
|
goto errorexit; \
|
|
errorexit: \
|
|
ThreadUnlock(&tlpwnd); \
|
|
LeaveCrit(); \
|
|
return;
|
|
|
|
#define MSGERROR() { \
|
|
retval = errret; \
|
|
goto errorexit; }
|
|
|
|
#define MSGERROR_VOID() { \
|
|
goto errorexit; }
|
|
|
|
#define MSGERRORCLEANUP() { \
|
|
retval = errret; \
|
|
goto cleanupexit; }
|
|
|
|
#if DBG
|
|
#define StubExceptionHandler() _StubExceptionHandler(GetExceptionInformation())
|
|
#else
|
|
#define StubExceptionHandler() EXCEPTION_EXECUTE_HANDLER
|
|
#endif
|
|
|
|
#define TESTFLAGS(flags, mask) \
|
|
if (((flags) & ~(mask)) != 0) { \
|
|
RIPERR2(ERROR_INVALID_FLAGS, RIP_WARNING, "Invalid flags, %x & ~%x != 0 " #mask, \
|
|
flags, mask); \
|
|
MSGERROR(); \
|
|
}
|
|
|
|
#define LIMITVALUE(value, limit, szText) \
|
|
if ((value) > (limit)) { \
|
|
RIPERR3(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid parameter, %d > %d in %s", \
|
|
value, limit, szText); \
|
|
MSGERROR(); \
|
|
}
|
|
|
|
#define MESSAGECALL(api) \
|
|
LONG NtUserfn ## api( \
|
|
HWND hwnd, \
|
|
UINT msg, \
|
|
DWORD wParam, \
|
|
LONG lParam, \
|
|
DWORD xParam, \
|
|
DWORD xpfnProc, \
|
|
BOOL bAnsi)
|
|
|
|
#define CALLPROC(p) FNID(p)
|
|
|
|
/*
|
|
* Validation macros
|
|
*/
|
|
#define ValidateHWNDNoRIP(p,h) \
|
|
if ((p = ValidateHwnd(h)) == NULL) \
|
|
MSGERROR();
|
|
|
|
#define ValidateHWND(p,h) \
|
|
if ((p = ValidateHwnd(h)) == NULL) \
|
|
MSGERROR();
|
|
|
|
#define ValidateHWNDND(p,h) \
|
|
if ( ((p = ValidateHwnd(h)) == NULL) || \
|
|
(p == _GetDesktopWindow()) ) \
|
|
MSGERROR();
|
|
|
|
#define ValidateHWNDOPT(p,h) \
|
|
if (h) { \
|
|
if ((p = ValidateHwnd(h)) == NULL) \
|
|
MSGERROR(); \
|
|
} else { \
|
|
p = NULL; \
|
|
}
|
|
|
|
#define ValidateHWNDIA(p,h) \
|
|
if (h == (HWND)0x0000FFFF) { \
|
|
h = (HWND)-1; \
|
|
} \
|
|
if (h != HWND_TOP && \
|
|
h != HWND_BOTTOM && \
|
|
h != HWND_TOPMOST && \
|
|
h != HWND_NOTOPMOST) { \
|
|
if ( ((p = ValidateHwnd(h)) == NULL) || \
|
|
(p == _GetDesktopWindow()) ) \
|
|
MSGERROR(); \
|
|
} else { \
|
|
p = (PWND)h; \
|
|
}
|
|
|
|
#define ValidateHWNDFF(p,h) \
|
|
if ((h != (HWND)-1) && (h !=(HWND)0xffff)) { \
|
|
if ((p = ValidateHwnd(h)) == NULL) \
|
|
MSGERROR(); \
|
|
} else { \
|
|
p = (PWND)-1; \
|
|
}
|
|
|
|
#define ValidateHMENUOPT(p,h) \
|
|
if (h) { \
|
|
if ((p = ValidateHmenu(h)) == NULL) \
|
|
MSGERROR(); \
|
|
} else { \
|
|
p = NULL; \
|
|
}
|
|
|
|
#define ValidateHMENU(p,h) \
|
|
if ((p = ValidateHmenu(h)) == NULL) \
|
|
MSGERROR();
|
|
|
|
#define ValidateHACCEL(p,h) \
|
|
if ((p = HMValidateHandle(h, TYPE_ACCELTABLE)) == NULL) \
|
|
MSGERROR();
|
|
|
|
#define ValidateHCURSOR(p,h) \
|
|
if ((p = HMValidateHandle(h, TYPE_CURSOR)) == NULL) \
|
|
MSGERROR();
|
|
|
|
#define ValidateHCURSOROPT(p,h) \
|
|
if (h) { \
|
|
if ((p = HMValidateHandle(h, TYPE_CURSOR)) == NULL) \
|
|
MSGERROR(); \
|
|
} else { \
|
|
p = NULL; \
|
|
}
|
|
|
|
#define ValidateHICON(p,h) \
|
|
if ((p = HMValidateHandle(h, TYPE_CURSOR)) == NULL) \
|
|
MSGERROR();
|
|
|
|
#define ValidateHHOOK(p,h) \
|
|
if ((p = HMValidateHandle(h, TYPE_HOOK)) == NULL) \
|
|
MSGERROR();
|
|
|
|
#define ValidateHDWP(p,h) \
|
|
if ((p = HMValidateHandle(h, TYPE_SETWINDOWPOS)) == NULL) \
|
|
MSGERROR();
|
|
|
|
#ifdef FE_IME
|
|
#define ValidateHIMC(p,h) \
|
|
if ((p = HMValidateHandle((HANDLE)h, TYPE_INPUTCONTEXT)) == NULL) \
|
|
MSGERROR();
|
|
|
|
#define ValidateHIMCOPT(p,h) \
|
|
if (h) { \
|
|
if ((p = HMValidateHandle((HANDLE)h, TYPE_INPUTCONTEXT)) == NULL) \
|
|
MSGERROR(); \
|
|
} else { \
|
|
p = NULL; \
|
|
}
|
|
#endif
|
|
|
|
#if DBG
|
|
ULONG _StubExceptionHandler(
|
|
PEXCEPTION_POINTERS pexi)
|
|
{
|
|
char szT[80];
|
|
|
|
wsprintfA(szT, "Stub exception: c=%08x, f=%08x, a=%08x, info=%08x",
|
|
pexi->ExceptionRecord->ExceptionCode,
|
|
pexi->ExceptionRecord->ExceptionFlags,
|
|
CONTEXT_TO_PROGRAM_COUNTER(pexi->ContextRecord),
|
|
pexi);
|
|
|
|
if (RipOutput(0, RIP_ERROR | RIP_COMPONENT, "", 0, szT, pexi)) {
|
|
DbgBreakPoint();
|
|
}
|
|
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
#endif
|
|
|
|
BOOL NtUserHardErrorControl(
|
|
IN HARDERRORCONTROL dwCmd,
|
|
IN HDESK hdeskRestore)
|
|
{
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
retval = HardErrorControl(dwCmd, hdeskRestore);
|
|
|
|
TRACE("NtUserHardErrorControl");
|
|
ENDRECV();
|
|
}
|
|
|
|
VOID NtUserSetDebugErrorLevel(
|
|
IN DWORD dwErrorLevel)
|
|
{
|
|
BEGINRECV_VOID();
|
|
|
|
_SetDebugErrorLevel(dwErrorLevel);
|
|
|
|
TRACEVOID("NtUserSetDebugErrorLevel");
|
|
ENDRECV_VOID();
|
|
}
|
|
|
|
BOOL NtUserRegisterLogonProcess(
|
|
IN DWORD dwProcessId,
|
|
IN BOOL fSecure)
|
|
{
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
retval = _RegisterLogonProcess(dwProcessId, TRUE);
|
|
|
|
TRACE("NtUserRegisterLogonProcess");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserGetObjectInformation(
|
|
IN HANDLE hObject,
|
|
IN int nIndex,
|
|
OUT PVOID pvInfo,
|
|
IN DWORD nLength,
|
|
IN OPTIONAL LPDWORD pnLengthNeeded)
|
|
{
|
|
DWORD dwAlign;
|
|
DWORD dwLocalLength;
|
|
BEGINRECV_SHARED(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
#if defined(_X86_)
|
|
dwAlign = sizeof(BYTE);
|
|
#else
|
|
if (nIndex == UOI_FLAGS)
|
|
dwAlign = sizeof(DWORD);
|
|
else
|
|
dwAlign = sizeof(WCHAR);
|
|
#endif
|
|
ProbeForWrite(pvInfo, nLength, dwAlign);
|
|
if (ARGUMENT_PRESENT(pnLengthNeeded))
|
|
ProbeForWriteUlong(pnLengthNeeded);
|
|
|
|
retval = _GetUserObjectInformation(hObject,
|
|
nIndex, pvInfo,
|
|
nLength, &dwLocalLength);
|
|
|
|
if (ARGUMENT_PRESENT(pnLengthNeeded))
|
|
*pnLengthNeeded = dwLocalLength;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetObjectInformation");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSetObjectInformation(
|
|
IN HANDLE hObject,
|
|
IN int nIndex,
|
|
IN PVOID pvInfo,
|
|
IN DWORD nLength)
|
|
{
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
#if defined(_X86_)
|
|
ProbeForRead(pvInfo, nLength, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(pvInfo, nLength, sizeof(DWORD));
|
|
#endif
|
|
|
|
retval = _SetUserObjectInformation(hObject,
|
|
nIndex, pvInfo, nLength);
|
|
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserSetObjectInformation");
|
|
ENDRECV();
|
|
}
|
|
|
|
NTSTATUS NtUserConsoleControl(
|
|
IN CONSOLECONTROL ConsoleCommand,
|
|
IN PVOID ConsoleInformation,
|
|
IN DWORD ConsoleInformationLength)
|
|
{
|
|
PVOID pvCapture = NULL;
|
|
NTSTATUS retval = STATUS_SUCCESS;
|
|
|
|
if (ConsoleInformationLength)
|
|
{
|
|
pvCapture = UserAllocPoolWithQuota(ConsoleInformationLength, TAG_SYSTEM);
|
|
|
|
if (pvCapture)
|
|
{
|
|
/*
|
|
* Probe all read/write arguments
|
|
*/
|
|
try {
|
|
ProbeForWrite(ConsoleInformation,
|
|
ConsoleInformationLength,
|
|
sizeof(WORD));
|
|
|
|
RtlCopyMemory(pvCapture,
|
|
ConsoleInformation,
|
|
ConsoleInformationLength);
|
|
|
|
} except (StubExceptionHandler()) {
|
|
|
|
retval = STATUS_UNSUCCESSFUL;
|
|
}
|
|
} else
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
if (NT_SUCCESS(retval))
|
|
{
|
|
EnterCrit();
|
|
|
|
retval = ConsoleControl(ConsoleCommand,
|
|
pvCapture,
|
|
ConsoleInformationLength);
|
|
|
|
LeaveCrit();
|
|
}
|
|
|
|
if (pvCapture)
|
|
{
|
|
if (NT_SUCCESS(retval))
|
|
{
|
|
try {
|
|
RtlCopyMemory(ConsoleInformation,
|
|
pvCapture,
|
|
ConsoleInformationLength);
|
|
|
|
} except (StubExceptionHandler()) {
|
|
|
|
retval = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
UserFreePool(pvCapture);
|
|
}
|
|
|
|
TRACE("NtUserConsoleControl");
|
|
|
|
return retval;
|
|
}
|
|
|
|
HWINSTA InternalUserCreateWindowStation(
|
|
IN POBJECT_ATTRIBUTES pObja,
|
|
IN DWORD dwReserved,
|
|
IN ACCESS_MASK amRequest,
|
|
IN HANDLE hKbdLayoutFile,
|
|
IN DWORD offTable,
|
|
IN PUNICODE_STRING pstrKLID,
|
|
UINT uKbdInputLocale)
|
|
{
|
|
|
|
PWINDOWSTATION pwinsta;
|
|
NTSTATUS Status;
|
|
HWINSTA retval;
|
|
WCHAR awchKF[sizeof(((PKL)0)->spkf->awchKF)];
|
|
|
|
|
|
retval = xxxCreateWindowStation(pObja, KernelMode, amRequest);
|
|
|
|
if (retval != NULL) {
|
|
|
|
/*
|
|
* Load the initial keyboard layout.
|
|
*/
|
|
Status = ObReferenceObjectByHandle(
|
|
retval,
|
|
0,
|
|
NULL,
|
|
KernelMode,
|
|
&pwinsta,
|
|
NULL);
|
|
if (NT_SUCCESS(Status)) {
|
|
xxxLoadKeyboardLayoutEx(
|
|
pwinsta,
|
|
hKbdLayoutFile,
|
|
(HKL)NULL,
|
|
offTable,
|
|
awchKF,
|
|
uKbdInputLocale,
|
|
KLF_ACTIVATE | KLF_INITTIME);
|
|
ObDereferenceObject(pwinsta);
|
|
}
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
HWINSTA NtUserCreateWindowStation(
|
|
IN POBJECT_ATTRIBUTES pObja,
|
|
IN DWORD dwReserved,
|
|
IN ACCESS_MASK amRequest,
|
|
IN HANDLE hKbdLayoutFile,
|
|
IN DWORD offTable,
|
|
IN PUNICODE_STRING pstrKLID,
|
|
UINT uKbdInputLocale)
|
|
{
|
|
PWINDOWSTATION pwinsta;
|
|
NTSTATUS Status;
|
|
OBJECT_ATTRIBUTES CapturedAttributes;
|
|
SECURITY_QUALITY_OF_SERVICE qosCaptured;
|
|
PSECURITY_DESCRIPTOR psdCaptured = NULL;
|
|
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
|
|
KPROCESSOR_MODE ProbeMode;
|
|
LUID luidService;
|
|
UNICODE_STRING strWinSta;
|
|
UNICODE_STRING strKLID;
|
|
WCHAR awchName[(sizeof(WINSTA_DIR L"\\Service-0x0000-0000$")) / sizeof(WCHAR)];
|
|
WCHAR awchKF[sizeof(((PKL)0)->spkf->awchKF)];
|
|
UINT chMax;
|
|
BOOL fDone = FALSE;
|
|
|
|
BEGINRECV(HWINSTA, NULL);
|
|
|
|
/*
|
|
* Set status so we can clean up in case of failure
|
|
*/
|
|
Status = STATUS_SUCCESS;
|
|
|
|
/*
|
|
* HACK: Don't probe if we are calling from kernel mode
|
|
*/
|
|
ProbeMode = PreviousMode;
|
|
if (PreviousMode != KernelMode) {
|
|
try {
|
|
/*
|
|
* Probe and capture the ??? string
|
|
*/
|
|
strKLID = ProbeAndReadUnicodeString(pstrKLID);
|
|
#if defined(_X86_)
|
|
ProbeForRead(strKLID.Buffer, strKLID.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(strKLID.Buffer, strKLID.Length, sizeof(WCHAR));
|
|
#endif
|
|
chMax = min(sizeof(awchKF) - sizeof(WCHAR), strKLID.Length) / sizeof(WCHAR);
|
|
wcsncpycch(awchKF, strKLID.Buffer, chMax);
|
|
awchKF[chMax] = 0;
|
|
|
|
/*
|
|
* Probe the object attributes
|
|
*/
|
|
ProbeForRead(pObja, sizeof(*pObja), sizeof(DWORD));
|
|
|
|
/*
|
|
* If no object name was specified, capture all
|
|
* other components of the object attributes. This will allow
|
|
* ObCreateObject to properly probe and capture the attributes.
|
|
*/
|
|
if (pObja->ObjectName == NULL && pObja->RootDirectory == NULL) {
|
|
|
|
/*
|
|
* Mark the call as finished.
|
|
*/
|
|
fDone = TRUE;
|
|
|
|
/*
|
|
* Use the logon authentication id to form the windowstation
|
|
* name.
|
|
*/
|
|
CapturedAttributes = *pObja;
|
|
Status = GetProcessLuid(NULL, &luidService);
|
|
if (NT_SUCCESS(Status)) {
|
|
wsprintfW(awchName, L"%ws\\Service-0x%x-%x$",
|
|
szWindowStationDirectory,
|
|
luidService.HighPart, luidService.LowPart);
|
|
RtlInitUnicodeString(&strWinSta, awchName);
|
|
CapturedAttributes.ObjectName = &strWinSta;
|
|
}
|
|
|
|
if (CapturedAttributes.SecurityQualityOfService) {
|
|
PSECURITY_QUALITY_OF_SERVICE pqos;
|
|
|
|
pqos = CapturedAttributes.SecurityQualityOfService;
|
|
ProbeForRead(pqos, sizeof(*pqos), sizeof(DWORD));
|
|
qosCaptured = *pqos;
|
|
CapturedAttributes.SecurityQualityOfService = &qosCaptured;
|
|
}
|
|
|
|
if (NT_SUCCESS(Status) && CapturedAttributes.SecurityDescriptor != NULL) {
|
|
Status = SeCaptureSecurityDescriptor(
|
|
CapturedAttributes.SecurityDescriptor,
|
|
PreviousMode,
|
|
PagedPool,
|
|
FALSE,
|
|
&psdCaptured);
|
|
CapturedAttributes.SecurityDescriptor = psdCaptured;
|
|
}
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
RtlInitUnicodeString(&strKLID, awchKF);
|
|
|
|
/*
|
|
* Create the windowstation and return a kernel
|
|
* handle. This is how we create windowstations
|
|
* for non-administrators.
|
|
*/
|
|
retval = InternalUserCreateWindowStation(
|
|
&CapturedAttributes,
|
|
dwReserved,
|
|
amRequest,
|
|
hKbdLayoutFile,
|
|
offTable,
|
|
&strKLID,
|
|
uKbdInputLocale);
|
|
|
|
}
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
Status = GetExceptionCode();
|
|
}
|
|
if (!NT_SUCCESS(Status))
|
|
MSGERRORCLEANUP();
|
|
}
|
|
|
|
if (!fDone) {
|
|
retval = xxxCreateWindowStation(pObja, ProbeMode, amRequest);
|
|
|
|
if (retval != NULL) {
|
|
|
|
/*
|
|
* Load the initial keyboard layout.
|
|
*/
|
|
Status = ObReferenceObjectByHandle(
|
|
retval,
|
|
0,
|
|
NULL,
|
|
KernelMode,
|
|
&pwinsta,
|
|
NULL);
|
|
if (NT_SUCCESS(Status)) {
|
|
xxxLoadKeyboardLayoutEx(
|
|
pwinsta,
|
|
hKbdLayoutFile,
|
|
(HKL)NULL,
|
|
offTable,
|
|
awchKF,
|
|
uKbdInputLocale,
|
|
KLF_ACTIVATE | KLF_INITTIME);
|
|
ObDereferenceObject(pwinsta);
|
|
}
|
|
} else {
|
|
retval = NULL;
|
|
}
|
|
}
|
|
|
|
CLEANUPRECV();
|
|
|
|
/*
|
|
* Release captured security descriptor.
|
|
*/
|
|
if (psdCaptured != NULL) {
|
|
SeReleaseSecurityDescriptor(
|
|
psdCaptured,
|
|
PreviousMode,
|
|
FALSE);
|
|
}
|
|
|
|
TRACE("NtUserCreateWindowStation");
|
|
ENDRECV();
|
|
}
|
|
|
|
|
|
HWINSTA NtUserOpenWindowStation(
|
|
IN POBJECT_ATTRIBUTES pObja,
|
|
IN ACCESS_MASK amRequest)
|
|
{
|
|
NTSTATUS Status;
|
|
LUID luidService;
|
|
WCHAR awchName[sizeof(L"Service-0x0000-0000$") / sizeof(WCHAR)];
|
|
|
|
BEGINRECV(HWINSTA, NULL);
|
|
|
|
retval = NULL;
|
|
|
|
try {
|
|
/*
|
|
* Probe the object attributes. We need to be able to read the
|
|
* OBJECT_ATTRIBUTES and to write the ObjectName (UNICODE_STRING).
|
|
*/
|
|
ProbeForRead(pObja, sizeof(*pObja), sizeof(DWORD));
|
|
|
|
#if defined(_X86_)
|
|
ProbeForWrite(pObja->ObjectName, sizeof(*(pObja->ObjectName)), sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite(pObja->ObjectName, sizeof(*(pObja->ObjectName)), sizeof(DWORD));
|
|
#endif
|
|
|
|
/*
|
|
* If we are trying to open the NULL or "" WindowStation, remap this
|
|
* benign name to Service-0x????-????$.
|
|
*/
|
|
if (KeGetPreviousMode() == UserMode &&
|
|
pObja->RootDirectory != NULL &&
|
|
pObja->ObjectName != NULL &&
|
|
pObja->ObjectName->Buffer != NULL &&
|
|
pObja->ObjectName->MaximumLength == sizeof(awchName) &&
|
|
pObja->ObjectName->Length == (sizeof(awchName) - sizeof(UNICODE_NULL))) {
|
|
|
|
/*
|
|
* Use the logon authentication id to form the windowstation
|
|
* name. Put this in the user's buffer since we were the one
|
|
* who allocated it in OpenWindowStation.
|
|
*/
|
|
|
|
#if defined(_X86_)
|
|
ProbeForWrite(pObja->ObjectName->Buffer, pObja->ObjectName->Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite(pObja->ObjectName->Buffer, pObja->ObjectName->Length, sizeof(WCHAR));
|
|
#endif
|
|
|
|
if (!_wcsicmp(pObja->ObjectName->Buffer, L"Service-0x0000-0000$")) {
|
|
Status = GetProcessLuid(NULL, &luidService);
|
|
if (NT_SUCCESS(Status)) {
|
|
wsprintfW(pObja->ObjectName->Buffer,
|
|
L"Service-0x%x-%x$",
|
|
luidService.HighPart,
|
|
luidService.LowPart);
|
|
/*
|
|
* We need to re-initialize the string to get the counted
|
|
* length correct. Otherwise the hashing function used
|
|
* by ObpLookupDirectoryEntry will fail.
|
|
*/
|
|
RtlInitUnicodeString( pObja->ObjectName, pObja->ObjectName->Buffer );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Open the WindowStation
|
|
*/
|
|
retval = _OpenWindowStation(pObja, amRequest);
|
|
|
|
} except (StubExceptionHandler()) {
|
|
RIPNTERR0(GetExceptionCode(), RIP_VERBOSE, "");
|
|
}
|
|
|
|
TRACE("NtUserOpenWindowStation");
|
|
ENDRECV();
|
|
|
|
UNREFERENCED_PARAMETER(awchName);
|
|
}
|
|
|
|
BOOL NtUserCloseWindowStation(
|
|
IN HWINSTA hwinsta)
|
|
{
|
|
PWINDOWSTATION pwinsta;
|
|
HWINSTA hwinstaCurrent;
|
|
NTSTATUS Status;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
retval = FALSE;
|
|
|
|
Status = ValidateHwinsta(hwinsta, 0, &pwinsta);
|
|
if (NT_SUCCESS(Status)) {
|
|
_GetProcessWindowStation(&hwinstaCurrent);
|
|
if (hwinsta != hwinstaCurrent)
|
|
retval = NT_SUCCESS(ZwClose(hwinsta));
|
|
ObDereferenceObject(pwinsta);
|
|
}
|
|
|
|
TRACE("NtUserCloseWindowStation");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSetProcessWindowStation(
|
|
IN HWINSTA hwinsta)
|
|
{
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
retval = xxxSetProcessWindowStation(hwinsta);
|
|
|
|
TRACE("NtUserSetProcessWindowStation");
|
|
ENDRECV();
|
|
}
|
|
|
|
HWINSTA NtUserGetProcessWindowStation(
|
|
VOID)
|
|
{
|
|
BEGINRECV_SHARED(HWINSTA, NULL);
|
|
|
|
_GetProcessWindowStation(&retval);
|
|
|
|
TRACE("NtUserGetProcessWindowStation");
|
|
ENDRECV();
|
|
}
|
|
|
|
HDESK NtUserCreateDesktop(
|
|
IN POBJECT_ATTRIBUTES pObja,
|
|
IN PUNICODE_STRING pstrDevice,
|
|
IN LPDEVMODEW pDevmode,
|
|
IN DWORD dwFlags,
|
|
IN ACCESS_MASK amRequest)
|
|
{
|
|
UNICODE_STRING strDevice;
|
|
PDEVMODEW pCaptDevmode;
|
|
|
|
BEGINRECV(HDESK, NULL);
|
|
|
|
/*
|
|
* Probe and capture arguments not probed by ObOpenObjectByName
|
|
*/
|
|
|
|
if (ProbeAndCaptureDeviceName(&strDevice, pstrDevice)) {
|
|
|
|
if (NT_SUCCESS(ProbeAndCaptureDevmode(&strDevice,
|
|
&pCaptDevmode,
|
|
pDevmode,
|
|
FALSE))) {
|
|
|
|
retval = xxxCreateDesktop(pObja,
|
|
UserMode,
|
|
&strDevice,
|
|
pCaptDevmode,
|
|
dwFlags,
|
|
amRequest);
|
|
|
|
/*
|
|
* Free captured devmode
|
|
*/
|
|
if (pCaptDevmode)
|
|
UserFreePool(pCaptDevmode);
|
|
}
|
|
|
|
/*
|
|
* Free captured device name
|
|
*/
|
|
if (strDevice.Buffer)
|
|
UserFreePool(strDevice.Buffer);
|
|
}
|
|
|
|
TRACE("NtUserCreateDesktop");
|
|
ENDRECV();
|
|
}
|
|
|
|
HDESK NtUserOpenDesktop(
|
|
IN POBJECT_ATTRIBUTES pObja,
|
|
IN DWORD dwFlags,
|
|
IN ACCESS_MASK amRequest)
|
|
{
|
|
BOOL bShutDown;
|
|
|
|
BEGINRECV(HDESK, NULL);
|
|
|
|
retval = xxxOpenDesktop(pObja, dwFlags, amRequest, &bShutDown);
|
|
|
|
TRACE("NtUserOpenDesktop");
|
|
ENDRECV();
|
|
}
|
|
|
|
HDESK NtUserOpenInputDesktop(
|
|
IN DWORD dwFlags,
|
|
IN BOOL fInherit,
|
|
IN DWORD amRequest)
|
|
{
|
|
HWINSTA hwinsta;
|
|
PWINDOWSTATION pwinsta;
|
|
NTSTATUS Status;
|
|
|
|
BEGINRECV(HDESK, NULL);
|
|
|
|
if (grpdeskRitInput == NULL) {
|
|
RIPERR0(ERROR_OPEN_FAILED, RIP_VERBOSE, "");
|
|
} else {
|
|
pwinsta = _GetProcessWindowStation(&hwinsta);
|
|
if (pwinsta == NULL) {
|
|
RIPERR0(ERROR_ACCESS_DENIED, RIP_VERBOSE, "");
|
|
}
|
|
if (pwinsta->dwFlags & WSF_NOIO) {
|
|
RIPERR0(ERROR_INVALID_FUNCTION, RIP_VERBOSE, "");
|
|
} else {
|
|
|
|
/*
|
|
* Require read/write access
|
|
*/
|
|
amRequest |= DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS;
|
|
|
|
Status = ObOpenObjectByPointer(
|
|
pwinsta->rpdeskCurrent,
|
|
fInherit ? OBJ_INHERIT : 0,
|
|
NULL,
|
|
amRequest,
|
|
*ExDesktopObjectType,
|
|
KeGetPreviousMode(),
|
|
&retval);
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
BOOL bShutDown;
|
|
/*
|
|
* Complete the desktop open
|
|
*/
|
|
if (!OpenDesktopCompletion(pwinsta->rpdeskCurrent, retval,
|
|
dwFlags, &bShutDown)) {
|
|
|
|
ZwClose(retval);
|
|
retval = NULL;
|
|
}
|
|
} else
|
|
retval = NULL;
|
|
}
|
|
}
|
|
|
|
TRACE("NtUserOpenInputDesktop");
|
|
ENDRECV();
|
|
}
|
|
|
|
HDESK NtUserResolveDesktop(
|
|
IN HANDLE hProcess,
|
|
IN PUNICODE_STRING pstrDesktop,
|
|
IN BOOL fInherit,
|
|
OUT HWINSTA *phwinsta)
|
|
{
|
|
UNICODE_STRING strDesktop;
|
|
HWINSTA hwinsta = NULL;
|
|
PTHREADINFO pti;
|
|
TL tlBuffer;
|
|
BOOL fFreeBuffer = FALSE;
|
|
BOOL bShutDown = FALSE;
|
|
|
|
BEGINRECV(HDESK, NULL);
|
|
|
|
pti = PtiCurrent();
|
|
/*
|
|
* Probe and capture desktop path
|
|
*/
|
|
if (KeGetPreviousMode() == UserMode) {
|
|
try {
|
|
strDesktop = ProbeAndReadUnicodeString(pstrDesktop);
|
|
ProbeForWriteHandle((PHANDLE)phwinsta);
|
|
if (strDesktop.Length > 0) {
|
|
#if defined(_X86_)
|
|
ProbeForRead(strDesktop.Buffer, strDesktop.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(strDesktop.Buffer, strDesktop.Length, sizeof(WCHAR));
|
|
#endif
|
|
strDesktop.Buffer = UserAllocPoolWithQuota(strDesktop.Length, TAG_TEXT2);
|
|
if (strDesktop.Buffer) {
|
|
fFreeBuffer = TRUE;
|
|
ThreadLockPool(pti, strDesktop.Buffer, &tlBuffer);
|
|
RtlCopyMemory(strDesktop.Buffer, pstrDesktop->Buffer,
|
|
strDesktop.Length);
|
|
} else
|
|
ExRaiseStatus(STATUS_NO_MEMORY);
|
|
} else {
|
|
strDesktop.Buffer = NULL;
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
MSGERRORCLEANUP();
|
|
}
|
|
} else {
|
|
strDesktop = *pstrDesktop;
|
|
}
|
|
|
|
retval = xxxResolveDesktop(hProcess, &strDesktop, &hwinsta,
|
|
fInherit, &bShutDown);
|
|
|
|
CLEANUPRECV();
|
|
if (fFreeBuffer)
|
|
ThreadUnlockAndFreePool(pti, &tlBuffer);
|
|
|
|
try {
|
|
*phwinsta = hwinsta;
|
|
} except (StubExceptionHandler()) {
|
|
xxxCloseDesktop(retval);
|
|
if (hwinsta)
|
|
ZwClose(hwinsta);
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserResolveDesktop");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserCloseDesktop(
|
|
IN HDESK hdesk)
|
|
{
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
retval = xxxCloseDesktop(hdesk);
|
|
|
|
TRACE("NtUserCloseDesktop");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSetThreadDesktop(
|
|
IN HDESK hdesk)
|
|
{
|
|
PDESKTOP pdesk;
|
|
NTSTATUS Status;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
Status = ValidateHdesk(hdesk, 0, &pdesk);
|
|
if (NT_SUCCESS(Status)) {
|
|
retval = _SetThreadDesktop(hdesk, pdesk);
|
|
ObDereferenceObject(pdesk);
|
|
} else if (hdesk == NULL && PsGetCurrentProcess() == gpepCSRSS) {
|
|
retval = _SetThreadDesktop(NULL, NULL);
|
|
} else
|
|
retval = FALSE;
|
|
|
|
TRACE("NtUserSetThreadDesktop");
|
|
ENDRECV();
|
|
}
|
|
|
|
HDESK NtUserGetThreadDesktop(
|
|
IN DWORD dwThreadId,
|
|
IN HDESK hdeskConsole)
|
|
{
|
|
BEGINRECV_SHARED(HDESK, NULL);
|
|
|
|
retval = xxxGetThreadDesktop(dwThreadId, hdeskConsole);
|
|
|
|
TRACE("NtUserGetThreadDesktop");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSwitchDesktop(
|
|
IN HDESK hdesk)
|
|
{
|
|
PDESKTOP pdesk;
|
|
TL tlpdesk;
|
|
PTHREADINFO ptiCurrent;
|
|
NTSTATUS Status;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ptiCurrent = PtiCurrent();
|
|
Status = ValidateHdesk(hdesk, DESKTOP_SWITCHDESKTOP, &pdesk);
|
|
if (NT_SUCCESS(Status)) {
|
|
if (pdesk->rpwinstaParent->dwFlags & WSF_NOIO) {
|
|
ObDereferenceObject(pdesk);
|
|
RIPERR0(ERROR_ACCESS_DENIED, RIP_VERBOSE, "");
|
|
retval = FALSE;
|
|
} else {
|
|
ThreadLockDesktop(ptiCurrent, pdesk, &tlpdesk);
|
|
ObDereferenceObject(pdesk);
|
|
retval = xxxSwitchDesktop(NULL, pdesk, FALSE);
|
|
ThreadUnlockDesktop(ptiCurrent, &tlpdesk);
|
|
}
|
|
} else
|
|
retval = FALSE;
|
|
|
|
TRACE("NtUserSwitchDesktop");
|
|
ENDRECV();
|
|
}
|
|
|
|
NTSTATUS NtUserInitializeClientPfnArrays(
|
|
IN PPFNCLIENT ppfnClientA OPTIONAL,
|
|
IN PPFNCLIENT ppfnClientW OPTIONAL,
|
|
IN HANDLE hModUser)
|
|
{
|
|
BEGINRECV(NTSTATUS, STATUS_UNSUCCESSFUL);
|
|
|
|
/*
|
|
* Probe all read arguments
|
|
*/
|
|
try {
|
|
if (ARGUMENT_PRESENT(ppfnClientA)) {
|
|
ProbeForRead(ppfnClientA, sizeof(*ppfnClientA), sizeof(DWORD));
|
|
}
|
|
if (ARGUMENT_PRESENT(ppfnClientW)) {
|
|
ProbeForRead(ppfnClientW, sizeof(*ppfnClientW), sizeof(DWORD));
|
|
}
|
|
|
|
retval = InitializeClientPfnArrays(
|
|
ppfnClientA, ppfnClientW, hModUser);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserInitializeThreadInfo");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserWaitForMsgAndEvent(
|
|
IN HANDLE hevent)
|
|
{
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
retval = xxxSleepTask(FALSE, hevent);
|
|
|
|
TRACE("NtUserWaitForMsgAndEvent");
|
|
ENDRECV();
|
|
}
|
|
|
|
HWND NtUserWOWFindWindow(
|
|
IN PUNICODE_STRING pstrClassName,
|
|
IN PUNICODE_STRING pstrWindowName)
|
|
{
|
|
UNICODE_STRING strClassName;
|
|
UNICODE_STRING strWindowName;
|
|
|
|
BEGINRECV(HWND, NULL);
|
|
|
|
/*
|
|
* Probe all read arguments
|
|
*/
|
|
try {
|
|
strClassName = ProbeAndReadUnicodeString(pstrClassName);
|
|
strWindowName = ProbeAndReadUnicodeString(pstrWindowName);
|
|
#if defined(_X86_)
|
|
ProbeForRead(strClassName.Buffer, strClassName.Length, sizeof(BYTE));
|
|
ProbeForRead(strWindowName.Buffer, strWindowName.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(strClassName.Buffer, strClassName.Length, sizeof(WCHAR));
|
|
ProbeForRead(strWindowName.Buffer, strWindowName.Length, sizeof(WCHAR));
|
|
#endif
|
|
|
|
retval = (HWND)_FindWindowEx(
|
|
NULL,
|
|
NULL,
|
|
(LPTSTR)strClassName.Buffer,
|
|
(LPTSTR)strWindowName.Buffer,
|
|
FW_16BIT);
|
|
retval = PtoH((PVOID)retval);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserWOWFindWindow");
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserDragObject(
|
|
IN HWND hwndParent,
|
|
IN HWND hwndFrom,
|
|
IN UINT wFmt,
|
|
IN DWORD dwData,
|
|
IN HCURSOR hcur)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
PWND pwndFrom;
|
|
PCURSOR pcur;
|
|
TL tlpwndFrom;
|
|
TL tlpcur;
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwndParent);
|
|
|
|
ValidateHWNDOPT(pwndFrom, hwndFrom);
|
|
ValidateHCURSOROPT(pcur, hcur);
|
|
|
|
ThreadLockWithPti(ptiCurrent, pwndFrom, &tlpwndFrom);
|
|
ThreadLockWithPti(ptiCurrent, pcur, &tlpcur);
|
|
|
|
retval = xxxDragObject(
|
|
pwnd,
|
|
pwndFrom,
|
|
wFmt,
|
|
dwData,
|
|
pcur);
|
|
|
|
ThreadUnlock(&tlpcur);
|
|
ThreadUnlock(&tlpwndFrom);
|
|
|
|
TRACE("NtUserDragObject");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
BOOL NtUserGetIconInfo(
|
|
IN HICON hIcon,
|
|
OUT PICONINFO piconinfo,
|
|
OUT OPTIONAL PUNICODE_STRING pstrInstanceName,
|
|
OUT OPTIONAL PUNICODE_STRING pstrResName,
|
|
OUT LPDWORD pbpp,
|
|
IN BOOL fInternal)
|
|
{
|
|
PICON pIcon;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
/*
|
|
* NOTE -- this can't be _SHARED since it calls Gre code with system HDC's.
|
|
*/
|
|
|
|
ValidateHCURSOR(pIcon, hIcon);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
if (pstrInstanceName != NULL) {
|
|
ProbeAndReadUnicodeString(pstrInstanceName);
|
|
}
|
|
if (pstrResName != NULL) {
|
|
ProbeAndReadUnicodeString(pstrResName);
|
|
}
|
|
if (pbpp != NULL) {
|
|
ProbeForWrite(pbpp, sizeof(DWORD), sizeof(DWORD));
|
|
}
|
|
#if defined(_X86_)
|
|
ProbeForWrite(piconinfo, sizeof(*piconinfo), sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite(piconinfo, sizeof(*piconinfo), sizeof(DWORD));
|
|
#endif
|
|
|
|
retval = _InternalGetIconInfo(
|
|
pIcon,
|
|
piconinfo,
|
|
pstrInstanceName,
|
|
pstrResName,
|
|
pbpp,
|
|
fInternal);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetIconInfo");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserGetIconSize(
|
|
IN HICON hIcon,
|
|
IN UINT istepIfAniCur,
|
|
OUT int *pcx,
|
|
OUT int *pcy)
|
|
{
|
|
PCURSOR picon;
|
|
|
|
BEGINRECV_SHARED(BOOL, FALSE);
|
|
|
|
ValidateHICON(picon, hIcon);
|
|
|
|
if (picon->CURSORF_flags & CURSORF_ACON) {
|
|
PACON pacon = (PACON)picon;
|
|
picon = pacon->aspcur[pacon->aicur[istepIfAniCur]];
|
|
}
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeAndWriteLong(pcx, picon->cx);
|
|
ProbeAndWriteLong(pcy, picon->cy);
|
|
|
|
retval = 1;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetIconSize");
|
|
ENDRECV();
|
|
}
|
|
|
|
|
|
|
|
BOOL NtUserDrawIconEx(
|
|
IN HDC hdc,
|
|
IN int x,
|
|
IN int y,
|
|
IN HICON hicon,
|
|
IN int cx,
|
|
IN int cy,
|
|
IN UINT istepIfAniCur,
|
|
IN HBRUSH hbrush,
|
|
IN UINT diFlags,
|
|
IN BOOL fMeta,
|
|
OUT DRAWICONEXDATA *pdid)
|
|
{
|
|
PCURSOR picon;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHICON(picon, hicon);
|
|
|
|
if (fMeta) {
|
|
if (picon->CURSORF_flags & CURSORF_ACON)
|
|
picon = ((PACON)picon)->aspcur[((PACON)picon)->aicur[0]];
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
#if defined(_X86_)
|
|
ProbeForWrite(pdid, sizeof(*pdid), sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite(pdid, sizeof(*pdid), sizeof(DWORD));
|
|
#endif
|
|
|
|
pdid->hbmMask = picon->hbmMask;
|
|
pdid->hbmColor = picon->hbmColor;
|
|
|
|
pdid->cx = cx ? cx : picon->cx ;
|
|
pdid->cy = cy ? cy : picon->cy ;
|
|
|
|
retval = 1;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
} else {
|
|
retval = _DrawIconEx(hdc, x, y, picon,
|
|
cx, cy,
|
|
istepIfAniCur, hbrush,
|
|
diFlags );
|
|
}
|
|
|
|
TRACE("NtUserDrawIconEx");
|
|
ENDRECV();
|
|
}
|
|
|
|
HANDLE NtUserDeferWindowPos(
|
|
IN HDWP hWinPosInfo,
|
|
IN HWND hwnd,
|
|
IN HWND hwndInsertAfter,
|
|
IN int x,
|
|
IN int y,
|
|
IN int cx,
|
|
IN int cy,
|
|
IN UINT wFlags)
|
|
{
|
|
PWND pwnd;
|
|
PWND pwndInsertAfter;
|
|
PSMWP psmwp;
|
|
|
|
BEGINRECV(HANDLE, NULL);
|
|
|
|
TESTFLAGS(wFlags, SWP_VALID);
|
|
|
|
ValidateHWNDND(pwnd, hwnd);
|
|
ValidateHWNDIA(pwndInsertAfter, hwndInsertAfter);
|
|
ValidateHDWP(psmwp, hWinPosInfo);
|
|
|
|
if (wFlags & ~(SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER |
|
|
SWP_NOREDRAW | SWP_NOACTIVATE | SWP_FRAMECHANGED |
|
|
SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOCOPYBITS |
|
|
SWP_NOOWNERZORDER)) {
|
|
RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid flags (0x%lx) passed to DeferWindowPos",
|
|
wFlags);
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* Make sure the window coordinates can fit in WORDs.
|
|
*/
|
|
if (!(wFlags & SWP_NOMOVE)) {
|
|
if (x > SHRT_MAX) {
|
|
x = SHRT_MAX;
|
|
} else if (x < SHRT_MIN) {
|
|
x = SHRT_MIN;
|
|
}
|
|
if (y > SHRT_MAX) {
|
|
y = SHRT_MAX;
|
|
} else if (y < SHRT_MIN) {
|
|
y = SHRT_MIN;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Actually, if we were going to be really strict about this we'd
|
|
* make sure that x + cx < SHRT_MAX, etc but since we do maintain
|
|
* signed 32-bit coords internally this case doesn't cause a problem.
|
|
*/
|
|
if (!(wFlags & SWP_NOSIZE)) {
|
|
if (cx < 0) {
|
|
cx = 0;
|
|
} else if (cx > SHRT_MAX) {
|
|
cx = SHRT_MAX;
|
|
}
|
|
if (cy < 0) {
|
|
cy = 0;
|
|
} else if (cy > SHRT_MAX) {
|
|
cy = SHRT_MAX;
|
|
}
|
|
}
|
|
|
|
#ifdef NEVER
|
|
//
|
|
// do not fail these conditions because real apps use them.
|
|
//
|
|
if (!(wFlags & SWP_NOMOVE) &&
|
|
(x > SHRT_MAX || x < SHRT_MIN ||
|
|
y > SHRT_MAX || y < SHRT_MIN)) {
|
|
RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid coordinate passed to SetWindowPos");
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* Actually, if we were going to be really strict about this we'd
|
|
* make sure that x + cx < SHRT_MAX, etc but since we do maintain
|
|
* signed 32-bit coords internally this case doesn't cause a problem.
|
|
*/
|
|
if (!(wFlags & SWP_NOSIZE) &&
|
|
(cx < 0 || cx > SHRT_MAX ||
|
|
cy < 0 || cy > SHRT_MAX)) {
|
|
RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid width/height passed to SetWindowPos");
|
|
MSGERROR();
|
|
}
|
|
#endif
|
|
|
|
retval = _DeferWindowPos(
|
|
psmwp,
|
|
pwnd,
|
|
pwndInsertAfter,
|
|
x,
|
|
y,
|
|
cx,
|
|
cy,
|
|
wFlags);
|
|
retval = PtoH((PVOID)retval);
|
|
|
|
TRACE("NtUserDeferWindowPos");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserEndDeferWindowPosEx(
|
|
IN HDWP hWinPosInfo,
|
|
IN BOOL fAsync)
|
|
{
|
|
PSMWP psmwp;
|
|
TL tlpsmp;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHDWP(psmwp, hWinPosInfo);
|
|
|
|
ThreadLockAlways(psmwp, &tlpsmp);
|
|
|
|
retval = xxxEndDeferWindowPosEx(
|
|
psmwp,
|
|
fAsync);
|
|
|
|
ThreadUnlock(&tlpsmp);
|
|
|
|
TRACE("NtUserEndDeferWindowPosEx");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserGetMessage(
|
|
IN LPMSG pmsg,
|
|
IN HWND hwnd,
|
|
IN UINT wMsgFilterMin,
|
|
IN UINT wMsgFilterMax,
|
|
OUT HKL *pHKL)
|
|
{
|
|
MSG msg;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
retval = xxxGetMessage(
|
|
&msg,
|
|
hwnd,
|
|
wMsgFilterMin,
|
|
wMsgFilterMax);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeAndWriteStructure(pmsg, msg, MSG);
|
|
ProbeAndWriteHandle((PHANDLE)pHKL, (HANDLE)PtiCurrent()->spklActive->hkl);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetMessage");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserMoveWindow(
|
|
IN HWND hwnd,
|
|
IN int x,
|
|
IN int y,
|
|
IN int cx,
|
|
IN int cy,
|
|
IN BOOL fRepaint)
|
|
{
|
|
PWND pwnd;
|
|
TL tlpwnd;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHWNDND(pwnd, hwnd);
|
|
|
|
/*
|
|
* Make sure the window coordinates can fit in WORDs.
|
|
*/
|
|
if (x > SHRT_MAX) {
|
|
x = SHRT_MAX;
|
|
} else if (x < SHRT_MIN) {
|
|
x = SHRT_MIN;
|
|
}
|
|
if (y > SHRT_MAX) {
|
|
y = SHRT_MAX;
|
|
} else if (y < SHRT_MIN) {
|
|
y = SHRT_MIN;
|
|
}
|
|
|
|
/*
|
|
* Actually, if we were going to be really strict about this we'd
|
|
* make sure that x + cx < SHRT_MAX, etc but since we do maintain
|
|
* signed 32-bit coords internally this case doesn't cause a problem.
|
|
*/
|
|
if (cx < 0) {
|
|
cx = 0;
|
|
} else if (cx > SHRT_MAX) {
|
|
cx = SHRT_MAX;
|
|
}
|
|
if (cy < 0) {
|
|
cy = 0;
|
|
} else if (cy > SHRT_MAX) {
|
|
cy = SHRT_MAX;
|
|
}
|
|
|
|
#ifdef NEVER
|
|
//
|
|
// do not fail these conditions because real apps use them.
|
|
//
|
|
if (x > SHRT_MAX || x < SHRT_MIN ||
|
|
y > SHRT_MAX || y < SHRT_MIN) {
|
|
RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid coordinate passed to MoveWindow");
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* Actually, if we were going to be really strict about this we'd
|
|
* make sure that x + cx < SHRT_MAX, etc but since we do maintain
|
|
* signed 32-bit coords internally this case doesn't cause a problem.
|
|
*/
|
|
if (cx < 0 || cx > SHRT_MAX ||
|
|
cy < 0 || cy > SHRT_MAX) {
|
|
RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid width/height passed to MoveWindow");
|
|
MSGERROR();
|
|
}
|
|
#endif
|
|
|
|
ThreadLockAlways(pwnd, &tlpwnd);
|
|
|
|
retval = xxxMoveWindow(
|
|
pwnd,
|
|
x,
|
|
y,
|
|
cx,
|
|
cy,
|
|
fRepaint);
|
|
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("NtUserMoveWindow");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserDeleteObject(
|
|
IN HANDLE hobj,
|
|
IN UINT utype)
|
|
{
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
switch (utype) {
|
|
|
|
case OBJ_BITMAP:
|
|
case OBJ_BRUSH:
|
|
case OBJ_FONT:
|
|
retval = (BOOL)GreDeleteObject(hobj);
|
|
break;
|
|
}
|
|
|
|
TRACE("NtUserDeleteObject");
|
|
ENDRECV();
|
|
}
|
|
|
|
int NtUserTranslateAccelerator(
|
|
IN HWND hwnd,
|
|
IN HACCEL haccel,
|
|
IN LPMSG lpmsg)
|
|
{
|
|
PWND pwnd;
|
|
LPACCELTABLE pat;
|
|
TL tlpwnd;
|
|
TL tlpat;
|
|
PTHREADINFO ptiCurrent;
|
|
MSG msg;
|
|
|
|
BEGINRECV(int, 0);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
msg = ProbeAndReadMessage(lpmsg);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* This is called within a message loop. If the window gets destroyed,
|
|
* there still may be other messages in the queue that get returned
|
|
* after the window is destroyed. The app will call TranslateAccelerator()
|
|
* on every one of these, causing RIPs.... Make it nice so it just
|
|
* returns FALSE.
|
|
*/
|
|
ValidateHWNDNoRIP(pwnd, hwnd);
|
|
ValidateHACCEL(pat, haccel);
|
|
|
|
ptiCurrent = PtiCurrent();
|
|
ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd);
|
|
ThreadLockAlwaysWithPti(ptiCurrent, pat, &tlpat);
|
|
|
|
retval = xxxTranslateAccelerator(
|
|
pwnd,
|
|
pat,
|
|
&msg);
|
|
|
|
ThreadUnlock(&tlpat);
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("NtUserTranslateAccelerator");
|
|
ENDRECV();
|
|
}
|
|
|
|
LONG NtUserSetClassLong(
|
|
IN HWND hwnd,
|
|
IN int nIndex,
|
|
OUT LONG dwNewLong,
|
|
IN BOOL bAnsi)
|
|
{
|
|
CLSMENUNAME cmn, *pcmnSave;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
|
|
try {
|
|
switch (nIndex) {
|
|
case GCL_MENUNAME:
|
|
ProbeForRead((PVOID)dwNewLong, sizeof(cmn), sizeof(DWORD));
|
|
RtlCopyMemory(&cmn, (PVOID) dwNewLong, sizeof(cmn));
|
|
pcmnSave = (PCLSMENUNAME) dwNewLong;
|
|
dwNewLong = (DWORD) &cmn;
|
|
break;
|
|
}
|
|
|
|
retval = xxxSetClassLong(
|
|
pwnd,
|
|
nIndex,
|
|
dwNewLong,
|
|
bAnsi);
|
|
|
|
switch (nIndex) {
|
|
case GCL_MENUNAME:
|
|
ProbeAndWriteStructure(pcmnSave, cmn, CLSMENUNAME);
|
|
break;
|
|
}
|
|
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserSetClassLong");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
BOOL NtUserSetKeyboardState(
|
|
IN LPBYTE lpKeyState)
|
|
{
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForRead(lpKeyState, 256, sizeof(BYTE));
|
|
|
|
retval = _SetKeyboardState(lpKeyState);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserSetKeyboardState");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSetWindowPos(
|
|
IN HWND hwnd,
|
|
IN HWND hwndInsertAfter,
|
|
IN int x,
|
|
IN int y,
|
|
IN int cx,
|
|
IN int cy,
|
|
IN UINT dwFlags)
|
|
{
|
|
PWND pwnd;
|
|
PWND pwndT;
|
|
PWND pwndInsertAfter;
|
|
TL tlpwnd;
|
|
TL tlpwndT;
|
|
PTHREADINFO ptiCurrent;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
TESTFLAGS(dwFlags, SWP_VALID);
|
|
|
|
ValidateHWNDND(pwnd, hwnd);
|
|
ValidateHWNDIA(pwndInsertAfter, hwndInsertAfter);
|
|
|
|
/*
|
|
* Let's not allow the window to be shown/hidden once we
|
|
* started the destruction of the window.
|
|
*/
|
|
if (TestWF(pwnd, WFINDESTROY)) {
|
|
RIPERR1(ERROR_INVALID_PARAMETER,
|
|
RIP_WARNING,
|
|
"SetWindowPos: Window is being destroyed (pwnd == 0x%lx)",
|
|
pwnd);
|
|
MSGERROR();
|
|
}
|
|
|
|
if (dwFlags & ~SWP_VALID) {
|
|
RIPERR1(ERROR_INVALID_PARAMETER,
|
|
RIP_WARNING,
|
|
"SetWindowPos: Invalid flags passed in (flags == 0x%lx)",
|
|
dwFlags);
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* Make sure the window coordinates can fit in WORDs.
|
|
*/
|
|
if (!(dwFlags & SWP_NOMOVE)) {
|
|
if (x > SHRT_MAX) {
|
|
x = SHRT_MAX;
|
|
} else if (x < SHRT_MIN) {
|
|
x = SHRT_MIN;
|
|
}
|
|
if (y > SHRT_MAX) {
|
|
y = SHRT_MAX;
|
|
} else if (y < SHRT_MIN) {
|
|
y = SHRT_MIN;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Actually, if we were going to be really strict about this we'd
|
|
* make sure that x + cx < SHRT_MAX, etc but since we do maintain
|
|
* signed 32-bit coords internally this case doesn't cause a problem.
|
|
*/
|
|
if (!(dwFlags & SWP_NOSIZE)) {
|
|
if (cx < 0) {
|
|
cx = 0;
|
|
} else if (cx > SHRT_MAX) {
|
|
cx = SHRT_MAX;
|
|
}
|
|
if (cy < 0) {
|
|
cy = 0;
|
|
} else if (cy > SHRT_MAX) {
|
|
cy = SHRT_MAX;
|
|
}
|
|
}
|
|
|
|
#ifdef NEVER
|
|
//
|
|
// do not fail these conditions because real apps use them.
|
|
//
|
|
if (!(dwFlags & SWP_NOMOVE) &&
|
|
(x > SHRT_MAX || x < SHRT_MIN ||
|
|
y > SHRT_MAX || y < SHRT_MIN)) {
|
|
RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid coordinate passed to SetWindowPos");
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* Actually, if we were going to be really strict about this we'd
|
|
* make sure that x + cx < SHRT_MAX, etc but since we do maintain
|
|
* signed 32-bit coords internally this case doesn't cause a problem.
|
|
*/
|
|
if (!(dwFlags & SWP_NOSIZE) &&
|
|
(cx < 0 || cx > SHRT_MAX ||
|
|
cy < 0 || cy > SHRT_MAX)) {
|
|
RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid width/height passed to SetWindowPos");
|
|
MSGERROR();
|
|
}
|
|
#endif
|
|
|
|
ptiCurrent = PtiCurrent();
|
|
|
|
ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd);
|
|
|
|
switch((DWORD)pwndInsertAfter) {
|
|
case (DWORD)HWND_TOPMOST:
|
|
case (DWORD)HWND_NOTOPMOST:
|
|
case (DWORD)HWND_TOP:
|
|
case (DWORD)HWND_BOTTOM:
|
|
pwndT = NULL;
|
|
break;
|
|
|
|
default:
|
|
pwndT = pwndInsertAfter;
|
|
break;
|
|
}
|
|
|
|
ThreadLockWithPti(ptiCurrent, pwndT, &tlpwndT);
|
|
|
|
retval = xxxSetWindowPos(
|
|
pwnd,
|
|
pwndInsertAfter,
|
|
x,
|
|
y,
|
|
cx,
|
|
cy,
|
|
dwFlags);
|
|
|
|
ThreadUnlock(&tlpwndT);
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("NtUserSetWindowPos");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSetShellWindowEx(
|
|
IN HWND hwnd,
|
|
IN HWND hwndBkGnd)
|
|
{
|
|
PWND pwnd;
|
|
PWND pwndBkGnd;
|
|
TL tlpwnd;
|
|
TL tlpwndBkGnd;
|
|
PTHREADINFO ptiCurrent;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHWNDND(pwnd, hwnd);
|
|
ValidateHWNDND(pwndBkGnd, hwndBkGnd);
|
|
|
|
ptiCurrent = PtiCurrent();
|
|
ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd);
|
|
ThreadLockAlwaysWithPti(ptiCurrent, pwndBkGnd, &tlpwndBkGnd);
|
|
|
|
retval = xxxSetShellWindow(pwnd, pwndBkGnd);
|
|
|
|
ThreadUnlock(&tlpwndBkGnd);
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("NtUserSetShellWindowEx");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSystemParametersInfo(
|
|
IN UINT wFlag,
|
|
IN DWORD wParam,
|
|
IN LPVOID lpData,
|
|
IN UINT flags,
|
|
IN BOOL bAnsi)
|
|
{
|
|
UNICODE_STRING strData;
|
|
ULONG ulLength;
|
|
|
|
union {
|
|
INT MouseData[3];
|
|
LOGFONTW LogFont;
|
|
MOUSEKEYS MouseKeys;
|
|
FILTERKEYS FilterKeys;
|
|
STICKYKEYS StickyKeys;
|
|
TOGGLEKEYS ToggleKeys;
|
|
SOUNDSENTRY SoundSentry;
|
|
ACCESSTIMEOUT AccessTimeout;
|
|
RECT Rect;
|
|
ANIMATIONINFO AnimationInfo;
|
|
NONCLIENTMETRICS NonClientMetrics;
|
|
MINIMIZEDMETRICS MinimizedMetrics;
|
|
ICONMETRICS IconMetrics;
|
|
HKL hkl;
|
|
} CaptureBuffer;
|
|
PTHREADINFO pti;
|
|
TL tlBuffer;
|
|
BOOL fFreeBuffer = FALSE;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
try {
|
|
switch(wFlag) {
|
|
|
|
case SPI_SETDESKPATTERN:
|
|
/*
|
|
* If wParam is -1, that means read the new wallpaper from
|
|
* win.ini. If wParam is not -1, lParam points to the wallpaper
|
|
* string.
|
|
*/
|
|
if (wParam == (WPARAM)-1)
|
|
break;
|
|
|
|
/*
|
|
* SetDeskPattern may take a string in lpData; if lpData
|
|
* is one of the magic values it obviously is not a string
|
|
*/
|
|
if (lpData == (PVOID)0xFFFFFFFF || lpData == (PVOID)NULL)
|
|
break;
|
|
|
|
goto ProbeString;
|
|
|
|
case SPI_SETDESKWALLPAPER:
|
|
|
|
/*
|
|
* If the caller passed in (-1) in the wParam, then the
|
|
* wallpaper-name is to be loaded later. Otherwise,
|
|
* they passed in a unicode-string in the lParam.
|
|
*/
|
|
if (wParam == (WPARAM)-1)
|
|
break;
|
|
|
|
if (((LPWSTR)lpData == NULL) ||
|
|
((LPWSTR)lpData == SETWALLPAPER_METRICS) ||
|
|
((LPWSTR)lpData == SETWALLPAPER_DEFAULT)) {
|
|
break;
|
|
}
|
|
|
|
ProbeString:
|
|
|
|
/*
|
|
* Probe and capture the string. Capture is necessary to
|
|
* the pointer to be passed directly to the registry routines
|
|
* which cannot cleanly handle exceptions.
|
|
*/
|
|
strData = ProbeAndReadUnicodeString((PUNICODE_STRING)lpData);
|
|
#if defined(_X86_)
|
|
ProbeForRead(strData.Buffer, strData.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(strData.Buffer, strData.Length, sizeof(WCHAR));
|
|
#endif
|
|
strData.Buffer = UserAllocPoolWithQuota(strData.Length + sizeof(WCHAR), TAG_TEXT2);
|
|
if (strData.Buffer == NULL) {
|
|
ExRaiseStatus(STATUS_NO_MEMORY);
|
|
}
|
|
pti = PtiCurrent();
|
|
ThreadLockPool(pti, strData.Buffer, &tlBuffer);
|
|
fFreeBuffer = TRUE;
|
|
RtlCopyMemory(strData.Buffer,
|
|
((PUNICODE_STRING)lpData)->Buffer,
|
|
strData.Length);
|
|
strData.Buffer[strData.Length / sizeof(WCHAR)] = 0;
|
|
lpData = strData.Buffer;
|
|
break;
|
|
|
|
case SPI_SETMOUSE:
|
|
ulLength = sizeof(INT) * 3;
|
|
goto ProbeRead;
|
|
case SPI_SETICONTITLELOGFONT:
|
|
if (!ARGUMENT_PRESENT(lpData))
|
|
break;
|
|
ulLength = sizeof(LOGFONTW);
|
|
goto ProbeRead;
|
|
case SPI_SETMOUSEKEYS:
|
|
ulLength = sizeof(MOUSEKEYS);
|
|
goto ProbeRead;
|
|
case SPI_SETFILTERKEYS:
|
|
ulLength = sizeof(FILTERKEYS);
|
|
goto ProbeRead;
|
|
case SPI_SETSTICKYKEYS:
|
|
ulLength = sizeof(STICKYKEYS);
|
|
goto ProbeRead;
|
|
case SPI_SETTOGGLEKEYS:
|
|
ulLength = sizeof(TOGGLEKEYS);
|
|
goto ProbeRead;
|
|
case SPI_SETSOUNDSENTRY:
|
|
ulLength = sizeof(SOUNDSENTRY);
|
|
goto ProbeRead;
|
|
case SPI_SETACCESSTIMEOUT:
|
|
ulLength = sizeof(ACCESSTIMEOUT);
|
|
goto ProbeRead;
|
|
case SPI_SETWORKAREA:
|
|
ulLength = sizeof(RECT);
|
|
goto ProbeRead;
|
|
case SPI_SETANIMATION:
|
|
ulLength = sizeof(ANIMATIONINFO);
|
|
goto ProbeRead;
|
|
case SPI_SETNONCLIENTMETRICS:
|
|
ulLength = sizeof(NONCLIENTMETRICS);
|
|
goto ProbeRead;
|
|
case SPI_SETMINIMIZEDMETRICS:
|
|
ulLength = sizeof(MINIMIZEDMETRICS);
|
|
goto ProbeRead;
|
|
case SPI_SETICONMETRICS:
|
|
ulLength = sizeof(ICONMETRICS);
|
|
goto ProbeRead;
|
|
case SPI_SETDEFAULTINPUTLANG:
|
|
ulLength = sizeof(HKL);
|
|
goto ProbeRead;
|
|
|
|
/*
|
|
* Probe and capture the data. Capture is necessary to
|
|
* allow the pointer to be passed to the worker routines
|
|
* where exceptions cannot be cleanly handled.
|
|
*/
|
|
ProbeRead:
|
|
#if defined(_X86_)
|
|
ProbeForRead(lpData, ulLength, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(lpData, ulLength, sizeof(DWORD));
|
|
#endif
|
|
RtlCopyMemory(&CaptureBuffer, lpData, ulLength);
|
|
lpData = &CaptureBuffer;
|
|
break;
|
|
|
|
case SPI_ICONHORIZONTALSPACING: // returns INT
|
|
case SPI_ICONVERTICALSPACING: // returns INT
|
|
if (HIWORD(lpData) == 0)
|
|
break;
|
|
|
|
/*
|
|
* Fall through and probe the data
|
|
*/
|
|
case SPI_GETBEEP: // returns BOOL
|
|
case SPI_GETBORDER: // returns INT
|
|
case SPI_GETKEYBOARDSPEED: // returns DWORD
|
|
case SPI_GETKEYBOARDDELAY: // returns INT
|
|
case SPI_GETSCREENSAVETIMEOUT: // returns INT
|
|
case SPI_GETSCREENSAVEACTIVE: // returns BOOL
|
|
case SPI_GETGRIDGRANULARITY: // returns INT
|
|
case SPI_GETICONTITLEWRAP: // returns BOOL
|
|
case SPI_GETMENUDROPALIGNMENT: // returns BOOL
|
|
case SPI_GETFASTTASKSWITCH: // returns BOOL
|
|
case SPI_GETDRAGFULLWINDOWS: // returns INT
|
|
case SPI_GETSHOWSOUNDS: // returns BOOL
|
|
case SPI_GETFONTSMOOTHING: // returns INT
|
|
case SPI_GETSNAPTODEFBUTTON: // returns BOOL
|
|
case SPI_GETDEFAULTINPUTLANG:
|
|
case SPI_GETMOUSEHOVERWIDTH:
|
|
case SPI_GETMOUSEHOVERHEIGHT:
|
|
case SPI_GETMOUSEHOVERTIME:
|
|
case SPI_GETWHEELSCROLLLINES:
|
|
case SPI_GETMENUSHOWDELAY:
|
|
case SPI_GETUSERPREFERENCE:
|
|
ProbeForWriteUlong((PULONG)lpData);
|
|
break;
|
|
|
|
case SPI_GETICONTITLELOGFONT: // returns LOGFONT
|
|
ulLength = sizeof(LOGFONT);
|
|
goto ProbeWrite;
|
|
case SPI_GETMOUSE: // returns 3 INTs
|
|
ulLength = sizeof(INT) * 3;
|
|
goto ProbeWrite;
|
|
case SPI_GETFILTERKEYS: // returns FILTERKEYS
|
|
ulLength = sizeof(FILTERKEYS);
|
|
goto ProbeWrite;
|
|
case SPI_GETSTICKYKEYS: // returns STICKYKEYS
|
|
ulLength = sizeof(STICKYKEYS);
|
|
goto ProbeWrite;
|
|
case SPI_GETMOUSEKEYS: // returns MOUSEKEYS
|
|
ulLength = sizeof(MOUSEKEYS);
|
|
goto ProbeWrite;
|
|
case SPI_GETTOGGLEKEYS: // returns TOGGLEKEYS
|
|
ulLength = sizeof(TOGGLEKEYS);
|
|
goto ProbeWrite;
|
|
case SPI_GETSOUNDSENTRY: // returns SOUNDSENTRY
|
|
ulLength = sizeof(SOUNDSENTRY);
|
|
goto ProbeWrite;
|
|
case SPI_GETACCESSTIMEOUT: // returns ACCESSTIMEOUT
|
|
ulLength = sizeof(ACCESSTIMEOUT);
|
|
goto ProbeWrite;
|
|
case SPI_GETANIMATION: // returns ANIMATIONINFO
|
|
ulLength = sizeof(ANIMATIONINFO);
|
|
goto ProbeWrite;
|
|
case SPI_GETNONCLIENTMETRICS: // returns NONCLIENTMETRICS
|
|
ulLength = sizeof(NONCLIENTMETRICS);
|
|
goto ProbeWrite;
|
|
case SPI_GETMINIMIZEDMETRICS: // returns MINIMIZEDMETRICS
|
|
ulLength = sizeof(MINIMIZEDMETRICS);
|
|
goto ProbeWrite;
|
|
case SPI_GETICONMETRICS: // returns ICONMETRICS
|
|
ulLength = sizeof(ICONMETRICS);
|
|
goto ProbeWrite;
|
|
case SPI_GETWORKAREA: // returns RECT
|
|
ulLength = sizeof(RECT);
|
|
goto ProbeWrite;
|
|
|
|
/*
|
|
* Probe the data. wParam contains the length
|
|
*/
|
|
ProbeWrite:
|
|
#if defined(_X86_)
|
|
ProbeForWrite(lpData, ulLength, sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite(lpData, ulLength, sizeof(DWORD));
|
|
#endif
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
retval = xxxSystemParametersInfo(wFlag, wParam, lpData, flags);
|
|
|
|
} except (StubExceptionHandler()) {
|
|
MSGERRORCLEANUP();
|
|
}
|
|
|
|
CLEANUPRECV();
|
|
if (fFreeBuffer)
|
|
ThreadUnlockAndFreePool(pti, &tlBuffer);
|
|
|
|
TRACE("NtUserSystemParametersInfo");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserUpdatePerUserSystemParameters(
|
|
IN BOOL bUserLoggedOn)
|
|
{
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
retval = xxxUpdatePerUserSystemParameters(bUserLoggedOn);
|
|
|
|
TRACE("NtUserUpdatePerUserSystemParameters");
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserDdeInitialize(
|
|
OUT LPDWORD phInst,
|
|
OUT HWND *phwnd,
|
|
OUT LPDWORD pMonFlags,
|
|
IN DWORD afCmd,
|
|
IN PVOID pcii)
|
|
{
|
|
DWORD hInst;
|
|
HWND hwnd;
|
|
DWORD MonFlags;
|
|
|
|
BEGINRECV(DWORD, DMLERR_INVALIDPARAMETER);
|
|
|
|
retval = xxxCsDdeInitialize(&hInst, &hwnd,
|
|
&MonFlags, afCmd, pcii);
|
|
|
|
/*
|
|
* Probe arguments. pcii is not dereferenced in the kernel so probing
|
|
* is not needed.
|
|
*/
|
|
if (retval == DMLERR_NO_ERROR) {
|
|
try {
|
|
ProbeAndWriteUlong(phInst, hInst);
|
|
ProbeAndWriteHandle((PHANDLE)phwnd, hwnd);
|
|
ProbeAndWriteUlong(pMonFlags, MonFlags);
|
|
} except (StubExceptionHandler()) {
|
|
xxxDestroyThreadDDEObject(PtiCurrent(), HtoP(hInst));
|
|
MSGERROR();
|
|
}
|
|
}
|
|
|
|
TRACE("NtUserDdeInitialize");
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserUpdateInstance(
|
|
IN HANDLE hInst,
|
|
IN LPDWORD pMonFlags,
|
|
IN DWORD afCmd)
|
|
{
|
|
BEGINRECV(DWORD, DMLERR_INVALIDPARAMETER);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWriteUlong(pMonFlags);
|
|
|
|
retval = _CsUpdateInstance(hInst, pMonFlags, afCmd);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserUpdateInstance");
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserEvent(
|
|
IN PEVENT_PACKET pep)
|
|
{
|
|
BEGINRECV(DWORD, 0);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForRead(pep, sizeof(*pep), sizeof(DWORD));
|
|
ProbeForRead(&pep->Data, pep->cbEventData, sizeof(BYTE));
|
|
|
|
retval = xxxCsEvent((PEVENT_PACKET)pep);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserEvent");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserFillWindow(
|
|
IN HWND hwndBrush,
|
|
IN HWND hwndPaint,
|
|
IN HDC hdc,
|
|
IN HBRUSH hbr)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
PWND pwndBrush;
|
|
TL tlpwndBrush;
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwndPaint);
|
|
|
|
ValidateHWNDOPT(pwndBrush, hwndBrush);
|
|
|
|
ThreadLockWithPti(ptiCurrent, pwndBrush, &tlpwndBrush);
|
|
|
|
retval = xxxFillWindow(
|
|
pwndBrush,
|
|
pwnd,
|
|
hdc,
|
|
hbr);
|
|
|
|
ThreadUnlock(&tlpwndBrush);
|
|
|
|
TRACE("NtUserFillWindow");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
HANDLE NtUserGetInputEvent(
|
|
IN DWORD dwWakeMask)
|
|
{
|
|
BEGINRECV(HANDLE, NULL);
|
|
|
|
retval = xxxGetInputEvent(
|
|
dwWakeMask);
|
|
|
|
TRACE("NtUserGetInputEvent");
|
|
ENDRECV();
|
|
}
|
|
|
|
PCLS NtUserGetWOWClass(
|
|
IN HINSTANCE hInstance,
|
|
IN PUNICODE_STRING pString)
|
|
{
|
|
UNICODE_STRING strClassName;
|
|
|
|
BEGINRECV_SHARED(PCLS, NULL);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
strClassName = ProbeAndReadUnicodeString(pString);
|
|
if (strClassName.Length == 0) {
|
|
MSGERROR();
|
|
}
|
|
#if defined(_X86_)
|
|
ProbeForRead(strClassName.Buffer, strClassName.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(strClassName.Buffer, strClassName.Length, sizeof(WCHAR));
|
|
#endif
|
|
|
|
retval = _GetWOWClass(
|
|
hInstance,
|
|
(LPWSTR)strClassName.Buffer);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetWOWClass");
|
|
ENDRECV();
|
|
}
|
|
|
|
UINT NtUserGetInternalWindowPos(
|
|
IN HWND hwnd,
|
|
OUT LPRECT lpRect OPTIONAL,
|
|
OUT LPPOINT lpPoint OPTIONAL)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND_SHARED(DWORD, 0, hwnd);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
if (ARGUMENT_PRESENT(lpRect)) {
|
|
ProbeForWriteRect(lpRect);
|
|
}
|
|
if (ARGUMENT_PRESENT(lpPoint)) {
|
|
ProbeForWritePoint(lpPoint);
|
|
}
|
|
|
|
retval = _GetInternalWindowPos(
|
|
pwnd,
|
|
lpRect,
|
|
lpPoint);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetInternalWindowPos");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
NTSTATUS NtUserInitTask(
|
|
IN UINT dwExpWinVer,
|
|
IN PUNICODE_STRING pstrAppName,
|
|
IN DWORD hTaskWow,
|
|
IN DWORD dwHotkey,
|
|
IN DWORD idTask,
|
|
IN DWORD dwX,
|
|
IN DWORD dwY,
|
|
IN DWORD dwXSize,
|
|
IN DWORD dwYSize,
|
|
IN WORD wShowWindow)
|
|
{
|
|
UNICODE_STRING strAppName;
|
|
|
|
BEGINRECV(NTSTATUS, STATUS_UNSUCCESSFUL);
|
|
|
|
/*
|
|
* Make sure this is really a WOW process.
|
|
*/
|
|
if (PpiCurrent()->pwpi == NULL) {
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
strAppName = ProbeAndReadUnicodeString(pstrAppName);
|
|
#if defined(_X86_)
|
|
ProbeForRead(strAppName.Buffer, strAppName.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(strAppName.Buffer, strAppName.Length, sizeof(WCHAR));
|
|
#endif
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = xxxInitTask(
|
|
dwExpWinVer,
|
|
&strAppName,
|
|
hTaskWow,
|
|
dwHotkey,
|
|
idTask,
|
|
dwX,
|
|
dwY,
|
|
dwXSize,
|
|
dwYSize,
|
|
wShowWindow);
|
|
|
|
TRACE("NtUserInitTask");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserPostThreadMessage(
|
|
IN DWORD id,
|
|
IN UINT msg,
|
|
IN DWORD wParam,
|
|
IN LONG lParam)
|
|
{
|
|
PTHREADINFO pti;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
pti = PtiFromThreadId(id);
|
|
if (pti == NULL) {
|
|
/* now we have to check if id is a Win16 hTask */
|
|
struct tagWOWPROCESSINFO *pwpi;
|
|
PTDB ptdb;
|
|
|
|
for (pwpi=gpwpiFirstWow; pwpi; pwpi=pwpi->pwpiNext) {
|
|
for (ptdb=pwpi->ptdbHead; ptdb; ptdb=ptdb->ptdbNext) {
|
|
if (ptdb->hTaskWow == id) {
|
|
pti=ptdb->pti;
|
|
goto PTM_DoIt;
|
|
}
|
|
}
|
|
}
|
|
|
|
RIPERR0(ERROR_INVALID_THREAD_ID, RIP_VERBOSE, "");
|
|
MSGERROR();
|
|
}
|
|
|
|
PTM_DoIt:
|
|
retval = _PostThreadMessage(
|
|
pti,
|
|
msg,
|
|
wParam,
|
|
lParam);
|
|
|
|
TRACE("NtUserPostThreadMessage");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserRegisterTasklist(
|
|
IN HWND hwnd)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND(DWORD, 0, hwnd);
|
|
|
|
retval = _RegisterTasklist(
|
|
pwnd);
|
|
|
|
TRACE("NtUserRegisterTasklist");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
BOOL NtUserSetClipboardData(
|
|
IN UINT fmt,
|
|
IN HANDLE hData,
|
|
IN PSETCLIPBDATA pscd)
|
|
{
|
|
SETCLIPBDATA scd;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
scd = ProbeAndReadSetClipBData(pscd);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = _SetClipboardData(
|
|
fmt,
|
|
hData,
|
|
scd.fGlobalHandle,
|
|
scd.fIncSerialNumber);
|
|
|
|
TRACE("NtUserSetClipboardData");
|
|
ENDRECV();
|
|
}
|
|
|
|
HANDLE NtUserConvertMemHandle(
|
|
IN LPBYTE lpData,
|
|
IN UINT cbData)
|
|
{
|
|
BEGINRECV(HANDLE, NULL);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
|
|
ProbeForRead(lpData, cbData, sizeof(BYTE));
|
|
|
|
retval = _ConvertMemHandle(lpData, cbData);
|
|
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserConvertMemHandle");
|
|
ENDRECV();
|
|
}
|
|
|
|
NTSTATUS NtUserCreateLocalMemHandle(
|
|
IN HANDLE hMem,
|
|
OUT LPBYTE lpData OPTIONAL,
|
|
IN UINT cbData,
|
|
OUT PUINT lpcbNeeded OPTIONAL)
|
|
{
|
|
PCLIPDATA pClipData;
|
|
|
|
BEGINRECV(NTSTATUS, STATUS_INVALID_HANDLE);
|
|
|
|
pClipData = HMValidateHandle(hMem, TYPE_CLIPDATA);
|
|
if (pClipData == NULL)
|
|
MSGERROR();
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
if (ARGUMENT_PRESENT(lpData)) {
|
|
ProbeForWrite(lpData, cbData, sizeof(BYTE));
|
|
}
|
|
|
|
if (ARGUMENT_PRESENT(lpcbNeeded)) {
|
|
ProbeAndWriteUlong(lpcbNeeded, pClipData->cbData);
|
|
}
|
|
|
|
if (!ARGUMENT_PRESENT(lpData) || cbData < pClipData->cbData) {
|
|
retval = STATUS_BUFFER_TOO_SMALL;
|
|
} else {
|
|
RtlCopyMemory(lpData, &pClipData->vData, pClipData->cbData);
|
|
retval = STATUS_SUCCESS;
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserCreateLocalMemHandle");
|
|
ENDRECV();
|
|
}
|
|
|
|
HHOOK NtUserSetWindowsHookEx(
|
|
IN HANDLE hmod,
|
|
IN PUNICODE_STRING pstrLib OPTIONAL,
|
|
IN DWORD idThread,
|
|
IN int nFilterType,
|
|
IN PROC pfnFilterProc,
|
|
IN BOOL bAnsi)
|
|
{
|
|
PTHREADINFO ptiThread;
|
|
|
|
BEGINRECV(HHOOK, NULL);
|
|
|
|
if (idThread != 0) {
|
|
ptiThread = PtiFromThreadId(idThread);
|
|
if (ptiThread == NULL) {
|
|
RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, "");
|
|
MSGERROR();
|
|
}
|
|
} else {
|
|
ptiThread = NULL;
|
|
}
|
|
|
|
/*
|
|
* Probe pstrLib in GetHmodTableIndex().
|
|
*/
|
|
retval = (HHOOK)_SetWindowsHookEx(
|
|
hmod,
|
|
pstrLib,
|
|
ptiThread,
|
|
nFilterType,
|
|
pfnFilterProc,
|
|
bAnsi);
|
|
retval = PtoH((PVOID)retval);
|
|
|
|
TRACE("NtUserSetWindowsHookEx");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSetInternalWindowPos(
|
|
IN HWND hwnd,
|
|
IN UINT cmdShow,
|
|
IN LPRECT lpRect,
|
|
IN LPPOINT lpPoint)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeRect(lpRect);
|
|
ProbePoint(lpPoint);
|
|
|
|
retval = xxxSetInternalWindowPos(
|
|
pwnd,
|
|
cmdShow,
|
|
lpRect,
|
|
lpPoint);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserSetInternalWindowPos");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
|
|
BOOL NtUserChangeClipboardChain(
|
|
IN HWND hwndRemove,
|
|
IN HWND hwndNewNext)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
PWND pwndNewNext;
|
|
TL tlpwndNewNext;
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwndRemove);
|
|
|
|
ValidateHWNDOPT(pwndNewNext, hwndNewNext);
|
|
|
|
ThreadLockWithPti(ptiCurrent, pwndNewNext, &tlpwndNewNext);
|
|
retval = xxxChangeClipboardChain(
|
|
pwnd,
|
|
pwndNewNext);
|
|
|
|
ThreadUnlock(&tlpwndNewNext);
|
|
|
|
TRACE("NtUserChangeClipboardChain");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
DWORD NtUserCheckMenuItem(
|
|
IN HMENU hmenu,
|
|
IN UINT wIDCheckItem,
|
|
IN UINT wCheck)
|
|
{
|
|
PMENU pmenu;
|
|
|
|
BEGINRECV(DWORD, (DWORD)-1);
|
|
|
|
TESTFLAGS(wCheck, MF_VALID);
|
|
|
|
ValidateHMENU(pmenu, hmenu);
|
|
|
|
retval = _CheckMenuItem(
|
|
pmenu,
|
|
wIDCheckItem,
|
|
wCheck);
|
|
|
|
TRACE("NtUserCheckMenuItem");
|
|
ENDRECV();
|
|
}
|
|
|
|
HWND NtUserChildWindowFromPointEx(
|
|
IN HWND hwndParent,
|
|
IN POINT point,
|
|
IN UINT flags)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND(HWND, NULL, hwndParent);
|
|
|
|
retval = (HWND)_ChildWindowFromPointEx(pwnd, point, flags);
|
|
retval = PtoH((PVOID)retval);
|
|
|
|
TRACE("NtUserChildWindowFromPointEx");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
BOOL NtUserClipCursor(
|
|
IN CONST RECT *lpRect OPTIONAL)
|
|
{
|
|
RECT rc;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
if (ARGUMENT_PRESENT(lpRect)) {
|
|
try {
|
|
rc = ProbeAndReadRect(lpRect);
|
|
lpRect = &rc;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
}
|
|
|
|
retval = _ClipCursor(lpRect);
|
|
|
|
TRACE("NtUserClipCursor");
|
|
ENDRECV();
|
|
}
|
|
|
|
HACCEL NtUserCreateAcceleratorTable(
|
|
IN LPACCEL paccel,
|
|
IN INT cbElem)
|
|
{
|
|
BEGINRECV(HACCEL, NULL);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
#if defined(_X86_)
|
|
ProbeForRead(paccel, cbElem, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(paccel, cbElem, sizeof(DWORD));
|
|
#endif
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = (HACCEL)_CreateAcceleratorTable(
|
|
(LPACCEL)paccel,
|
|
cbElem);
|
|
retval = PtoH((PVOID)retval);
|
|
|
|
TRACE("NtUserCreateAcceleratorTable");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserDeleteMenu(
|
|
IN HMENU hmenu,
|
|
IN UINT nPosition,
|
|
IN UINT dwFlags)
|
|
{
|
|
PMENU pmenu;
|
|
#ifdef MEMPHIS_MENUS
|
|
TL tlpmenu;
|
|
#endif // MEMPHIS_MENUS
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
TESTFLAGS(dwFlags, MF_VALID);
|
|
|
|
ValidateHMENU(pmenu, hmenu);
|
|
#ifdef MEMPHIS_MENUS
|
|
ThreadLock(pmenu, &tlpmenu);
|
|
retval = xxxDeleteMenu(
|
|
pmenu,
|
|
nPosition,
|
|
dwFlags);
|
|
ThreadUnlock(&tlpmenu);
|
|
#else
|
|
retval = _DeleteMenu(
|
|
pmenu,
|
|
nPosition,
|
|
dwFlags);
|
|
#endif // MEMPHIS_MENUS
|
|
|
|
TRACE("NtUserDeleteMenu");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserDestroyAcceleratorTable(
|
|
IN HACCEL hAccel)
|
|
{
|
|
LPACCELTABLE pat;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHACCEL(pat, hAccel);
|
|
|
|
/*
|
|
* Mark the object for destruction - if it says it's ok to free,
|
|
* then free it.
|
|
*/
|
|
if (HMMarkObjectDestroy(pat))
|
|
HMFreeObject(pat);
|
|
retval = TRUE;
|
|
|
|
TRACE("NtUserDestroyAcceleratorTable");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserDestroyCursor(
|
|
IN HCURSOR hcurs,
|
|
IN DWORD cmd)
|
|
{
|
|
PCURSOR pcurs;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHCURSOR(pcurs, hcurs);
|
|
|
|
retval = _DestroyCursor(
|
|
pcurs, cmd);
|
|
|
|
TRACE("NtUserDestroyCursor");
|
|
ENDRECV();
|
|
}
|
|
|
|
HANDLE NtUserGetClipboardData(
|
|
IN UINT fmt,
|
|
OUT PGETCLIPBDATA pgcd)
|
|
{
|
|
PTHREADINFO ptiCurrent;
|
|
TL tlpwinsta;
|
|
PWINDOWSTATION pwinsta;
|
|
|
|
BEGINRECV(HANDLE, NULL);
|
|
|
|
ptiCurrent = PtiCurrent();
|
|
if (!CheckClipboardAccess(&pwinsta))
|
|
MSGERROR();
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ThreadLockWinSta(ptiCurrent, pwinsta, &tlpwinsta);
|
|
|
|
ProbeForWriteGetClipData(pgcd);
|
|
|
|
/*
|
|
* Start out assuming the format requested
|
|
* will be the format returned.
|
|
*/
|
|
pgcd->uFmtRet = fmt;
|
|
|
|
retval = xxxGetClipboardData(pwinsta, fmt, pgcd);
|
|
|
|
} except (StubExceptionHandler()) {
|
|
MSGERRORCLEANUP();
|
|
}
|
|
|
|
CLEANUPRECV();
|
|
ThreadUnlockWinSta(ptiCurrent, &tlpwinsta);
|
|
|
|
TRACE("NtUserGetClipboardData");
|
|
ENDRECV();
|
|
|
|
}
|
|
|
|
BOOL NtUserDestroyMenu(
|
|
IN HMENU hmenu)
|
|
{
|
|
PMENU pmenu;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHMENU(pmenu, hmenu);
|
|
|
|
retval = _DestroyMenu(
|
|
pmenu);
|
|
|
|
TRACE("NtUserDestroyMenu");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserDestroyWindow(
|
|
IN HWND hwnd)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND(DWORD, 0, hwnd);
|
|
|
|
retval = xxxDestroyWindow(pwnd);
|
|
|
|
TRACE("NtUserDestroyWindow");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
LONG NtUserDispatchMessage(
|
|
IN CONST MSG *pmsg)
|
|
{
|
|
MSG msg;
|
|
|
|
BEGINRECV(LONG, 0);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
msg = ProbeAndReadMessage(pmsg);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = xxxDispatchMessage(&msg);
|
|
|
|
TRACE("NtUserDispatchMessage");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserEnableMenuItem(
|
|
IN HMENU hMenu,
|
|
IN UINT wIDEnableItem,
|
|
IN UINT wEnable)
|
|
{
|
|
PMENU pmenu;
|
|
|
|
BEGINRECV(BOOL, -1);
|
|
|
|
TESTFLAGS(wEnable, MF_VALID);
|
|
|
|
ValidateHMENU(pmenu, hMenu);
|
|
|
|
retval = _EnableMenuItem(
|
|
pmenu,
|
|
wIDEnableItem,
|
|
wEnable);
|
|
|
|
TRACE("NtUserEnableMenuItem");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserAttachThreadInput(
|
|
IN DWORD idAttach,
|
|
IN DWORD idAttachTo,
|
|
IN BOOL fAttach)
|
|
{
|
|
PTHREADINFO ptiAttach;
|
|
PTHREADINFO ptiAttachTo;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
/*
|
|
* Always must attach or detach from a real thread id.
|
|
*/
|
|
if ((ptiAttach = PtiFromThreadId(idAttach)) == NULL) {
|
|
MSGERROR();
|
|
}
|
|
if ((ptiAttachTo = PtiFromThreadId(idAttachTo)) == NULL) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = _AttachThreadInput(
|
|
ptiAttach,
|
|
ptiAttachTo,
|
|
fAttach);
|
|
|
|
TRACE("NtUserAttachThreadInput");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserGetWindowPlacement(
|
|
IN HWND hwnd,
|
|
OUT PWINDOWPLACEMENT pwp)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND_SHARED(DWORD, 0, hwnd);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWriteWindowPlacement(pwp);
|
|
|
|
retval = _GetWindowPlacement(pwnd, pwp);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetWindowPlacement");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
BOOL NtUserSetWindowPlacement(
|
|
IN HWND hwnd,
|
|
IN CONST WINDOWPLACEMENT *pwp)
|
|
{
|
|
WINDOWPLACEMENT wp;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
wp = ProbeAndReadWindowPlacement(pwp);
|
|
|
|
if (wp.length != sizeof(WINDOWPLACEMENT)) {
|
|
if (Is400Compat(PtiCurrent()->dwExpWinVer)) {
|
|
RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "SetWindowPlacement: invalid length %lX", pwp->length);
|
|
pwp = NULL;
|
|
retval = 0;
|
|
} else {
|
|
RIPMSG1(RIP_WARNING, "SetWindowPlacement: invalid length %lX", pwp->length);
|
|
}
|
|
}
|
|
|
|
if (pwp != NULL)
|
|
retval = xxxSetWindowPlacement(pwnd, &wp);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserSetWindowPlacement");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
BOOL NtUserLockWindowUpdate(
|
|
IN HWND hwnd)
|
|
{
|
|
PWND pwnd;
|
|
TL tlpwnd;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
ThreadLock(pwnd, &tlpwnd);
|
|
retval = xxxLockWindowUpdate2(pwnd, FALSE);
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("NtUserLockWindowUpdate");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserGetClipCursor(
|
|
OUT LPRECT lpRect)
|
|
{
|
|
BEGINRECV_SHARED(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWriteRect(lpRect);
|
|
|
|
retval = _GetClipCursor(lpRect);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetClipCursor");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserEnableScrollBar(
|
|
IN HWND hwnd,
|
|
IN UINT wSBflags,
|
|
IN UINT wArrows)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(BOOL, FALSE, hwnd);
|
|
|
|
retval = xxxEnableScrollBar(pwnd, wSBflags, wArrows);
|
|
|
|
TRACE("NtUserEnableScrollBar");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
BOOL NtUserDdeSetQualityOfService(
|
|
IN HWND hwndClient,
|
|
IN CONST SECURITY_QUALITY_OF_SERVICE *pqosNew,
|
|
IN PSECURITY_QUALITY_OF_SERVICE pqosPrev OPTIONAL)
|
|
{
|
|
SECURITY_QUALITY_OF_SERVICE qosNew, qosPrev;
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND(BOOL, FALSE, hwndClient);
|
|
|
|
if (GETPTI(pwnd) != PtiCurrent()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
#if defined(_X86_)
|
|
ProbeForRead(pqosNew, sizeof(*pqosNew), sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(pqosNew, sizeof(*pqosNew), sizeof(DWORD));
|
|
#endif
|
|
qosNew = *pqosNew;
|
|
if (ARGUMENT_PRESENT(pqosPrev))
|
|
ProbeForWrite(pqosPrev, sizeof(*pqosPrev), sizeof(DWORD));
|
|
|
|
retval = _DdeSetQualityOfService(
|
|
pwnd,
|
|
&qosNew,
|
|
&qosPrev);
|
|
|
|
if (ARGUMENT_PRESENT(pqosPrev))
|
|
*pqosPrev = qosPrev;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserDdeSetQualityOfService");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
BOOL NtUserDdeGetQualityOfService(
|
|
IN HWND hwndClient,
|
|
IN HWND hwndServer,
|
|
IN PSECURITY_QUALITY_OF_SERVICE pqos)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
PWND pwndServer;
|
|
PTHREADINFO ptiCurrent;
|
|
|
|
BEGINRECV_HWND(BOOL, FALSE, hwndClient);
|
|
|
|
ValidateHWNDOPT(pwndServer, hwndServer);
|
|
ptiCurrent = PtiCurrent();
|
|
if (GETPTI(pwnd) != ptiCurrent && pwndServer != NULL &&
|
|
GETPTI(pwndServer) != ptiCurrent) {
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
#if defined(_X86_)
|
|
ProbeForWrite(pqos, sizeof(*pqos), sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite(pqos, sizeof(*pqos), sizeof(DWORD));
|
|
#endif
|
|
|
|
retval = _DdeGetQualityOfService(
|
|
pwnd,
|
|
pwndServer,
|
|
pqos);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserDdeGetQualityOfService");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
DWORD NtUserGetMenuIndex(
|
|
IN HMENU hMenu,
|
|
IN HMENU hSubMenu)
|
|
{
|
|
|
|
PMENU pmenu;
|
|
PMENU psubmenu;
|
|
DWORD idx;
|
|
|
|
BEGINRECV_SHARED(DWORD, 0);
|
|
|
|
ValidateHMENU(pmenu, hMenu);
|
|
ValidateHMENU(psubmenu, hSubMenu);
|
|
|
|
retval = (DWORD)-1;
|
|
|
|
if (pmenu && psubmenu) {
|
|
for (idx=0; idx<pmenu->cItems; idx++)
|
|
if ((pmenu->rgItems[idx].spSubMenu == psubmenu)) {
|
|
retval = idx;
|
|
break;
|
|
}
|
|
}
|
|
|
|
TRACE("NtUserGetMenuIndex");
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserCallNoParam(
|
|
IN DWORD xpfnProc)
|
|
{
|
|
BEGINRECV(DWORD, 0);
|
|
|
|
UserAssert(xpfnProc < ulMaxSimpleCall);
|
|
if (xpfnProc >= ulMaxSimpleCall) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = (apfnSimpleCall[xpfnProc]());
|
|
|
|
TRACE(apszSimpleCallNames[xpfnProc]);
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserBreak(void)
|
|
{
|
|
try {
|
|
if (**((PUCHAR *)&KdDebuggerEnabled) != FALSE) {
|
|
DbgBreakPointWithStatus(DBG_STATUS_SYSRQ);
|
|
}
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD NtUserCallNoParamTranslate(
|
|
IN DWORD xpfnProc)
|
|
{
|
|
BEGINRECV(DWORD, 0);
|
|
|
|
UserAssert(xpfnProc < ulMaxSimpleCall);
|
|
if (xpfnProc >= ulMaxSimpleCall) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = (apfnSimpleCall[xpfnProc]());
|
|
retval = (DWORD)PtoH((PVOID)retval);
|
|
|
|
TRACE(apszSimpleCallNames[xpfnProc]);
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserCallOneParam(
|
|
IN DWORD dwParam,
|
|
IN DWORD xpfnProc)
|
|
{
|
|
BEGINRECV(DWORD, 0);
|
|
|
|
UserAssert(xpfnProc < ulMaxSimpleCall);
|
|
if (xpfnProc >= ulMaxSimpleCall) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = (apfnSimpleCall[xpfnProc](dwParam));
|
|
|
|
TRACE(apszSimpleCallNames[xpfnProc]);
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserCallOneParamTranslate(
|
|
IN DWORD dwParam,
|
|
IN DWORD xpfnProc)
|
|
{
|
|
BEGINRECV(DWORD, 0);
|
|
|
|
UserAssert(xpfnProc < ulMaxSimpleCall);
|
|
if (xpfnProc >= ulMaxSimpleCall) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = (apfnSimpleCall[xpfnProc](dwParam));
|
|
retval = (DWORD)PtoH((PVOID)retval);
|
|
|
|
TRACE(apszSimpleCallNames[xpfnProc]);
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserCallHwnd(
|
|
IN HWND hwnd,
|
|
IN DWORD xpfnProc)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND(DWORD, 0, hwnd);
|
|
|
|
UserAssert(xpfnProc < ulMaxSimpleCall);
|
|
if (xpfnProc >= ulMaxSimpleCall) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = (apfnSimpleCall[xpfnProc](pwnd));
|
|
|
|
TRACE(apszSimpleCallNames[xpfnProc]);
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
DWORD NtUserCallHwndLock(
|
|
IN HWND hwnd,
|
|
IN DWORD xpfnProc)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
|
|
UserAssert(xpfnProc < ulMaxSimpleCall);
|
|
if (xpfnProc >= ulMaxSimpleCall) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = (apfnSimpleCall[xpfnProc](pwnd));
|
|
|
|
TRACE(apszSimpleCallNames[xpfnProc]);
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
DWORD NtUserCallHwndOpt(
|
|
IN HWND hwnd,
|
|
IN DWORD xpfnProc)
|
|
{
|
|
PWND pwnd;
|
|
|
|
BEGINRECV(DWORD, 0);
|
|
|
|
UserAssert(xpfnProc < ulMaxSimpleCall);
|
|
if (xpfnProc >= ulMaxSimpleCall) {
|
|
MSGERROR();
|
|
}
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
retval = (apfnSimpleCall[xpfnProc](pwnd));
|
|
|
|
TRACE(apszSimpleCallNames[xpfnProc]);
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserCallTwoParam(
|
|
DWORD dwParam1,
|
|
DWORD dwParam2,
|
|
IN DWORD xpfnProc)
|
|
{
|
|
BEGINRECV(DWORD, 0);
|
|
|
|
UserAssert(xpfnProc < ulMaxSimpleCall);
|
|
if (xpfnProc >= ulMaxSimpleCall) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = (apfnSimpleCall[xpfnProc](dwParam1, dwParam2));
|
|
|
|
TRACE(apszSimpleCallNames[xpfnProc]);
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserCallHwndParam(
|
|
IN HWND hwnd,
|
|
IN DWORD dwParam,
|
|
IN DWORD xpfnProc)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND(DWORD, 0, hwnd);
|
|
|
|
UserAssert(xpfnProc < ulMaxSimpleCall);
|
|
if (xpfnProc >= ulMaxSimpleCall) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = (apfnSimpleCall[xpfnProc](pwnd, dwParam));
|
|
|
|
TRACE(apszSimpleCallNames[xpfnProc]);
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
DWORD NtUserCallHwndParamLock(
|
|
IN HWND hwnd,
|
|
IN DWORD dwParam,
|
|
IN DWORD xpfnProc)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
|
|
UserAssert(xpfnProc < ulMaxSimpleCall);
|
|
if (xpfnProc >= ulMaxSimpleCall) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = (apfnSimpleCall[xpfnProc](pwnd, dwParam));
|
|
|
|
TRACE(apszSimpleCallNames[xpfnProc]);
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
BOOL NtUserThunkedMenuItemInfo(
|
|
IN HMENU hMenu,
|
|
IN UINT nPosition,
|
|
IN BOOL fByPosition,
|
|
IN BOOL fInsert,
|
|
IN LPMENUITEMINFOW lpmii OPTIONAL,
|
|
IN PUNICODE_STRING pstrItem OPTIONAL,
|
|
IN BOOL fAnsi)
|
|
{
|
|
PMENU pmenu;
|
|
MENUITEMINFO mii;
|
|
UNICODE_STRING strItem;
|
|
#ifdef MEMPHIS_MENUS
|
|
TL tlpmenu;
|
|
#endif // MEMPHIS_MENUS
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
if (ARGUMENT_PRESENT(lpmii)) {
|
|
mii = ProbeAndReadMenuItem(lpmii);
|
|
}
|
|
if (ARGUMENT_PRESENT(pstrItem)) {
|
|
strItem = ProbeAndReadUnicodeString(pstrItem);
|
|
#if defined(_X86_)
|
|
ProbeForRead(strItem.Buffer, strItem.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(strItem.Buffer, strItem.Length, sizeof(WCHAR));
|
|
#endif
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
ValidateHMENU(pmenu, hMenu);
|
|
|
|
if (mii.fMask & MIIM_TYPE) {
|
|
}
|
|
|
|
#ifdef MEMPHIS_MENUS
|
|
ThreadLock(pmenu, &tlpmenu);
|
|
#endif // MEMPHIS_MENUS
|
|
if (fInsert)
|
|
#ifdef MEMPHIS_MENUS
|
|
retval = xxxInsertMenuItem(
|
|
#else
|
|
retval = _InsertMenuItem(
|
|
#endif // MEMPHIS_MENUS
|
|
pmenu,
|
|
nPosition,
|
|
fByPosition,
|
|
&mii,
|
|
&strItem);
|
|
else
|
|
#ifdef MEMPHIS_MENUS
|
|
retval = xxxSetMenuItemInfo(
|
|
#else
|
|
retval = _SetMenuItemInfo(
|
|
#endif // MEMPHIS_MENUS
|
|
pmenu,
|
|
nPosition,
|
|
fByPosition,
|
|
&mii,
|
|
&strItem);
|
|
#ifdef MEMPHIS_MENUS
|
|
ThreadUnlock(&tlpmenu);
|
|
#endif // MEMPHIS_MENUS
|
|
|
|
TRACE("NtUserThunkedMenuItemInfo");
|
|
ENDRECV();
|
|
}
|
|
|
|
#ifdef MEMPHIS_MENU_WATERMARKS
|
|
BOOL NtUserThunkedMenuInfo(
|
|
IN HMENU hMenu,
|
|
IN LPCMENUINFO lpmi,
|
|
IN WORD wAPICode,
|
|
IN BOOL fAnsi)
|
|
{
|
|
PMENU pmenu;
|
|
MENUINFO mi;
|
|
TL tlpmenu;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
if (ARGUMENT_PRESENT(lpmi)) {
|
|
mi = ProbeAndReadMenuInfo(lpmi);
|
|
lpmi = &mi;
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
ValidateHMENU(pmenu, hMenu);
|
|
|
|
ThreadLock(pmenu, &tlpmenu);
|
|
retval = xxxSetMenuInfo( pmenu, lpmi);
|
|
ThreadUnlock(&tlpmenu);
|
|
|
|
TRACE("NtUserThunkedMenuInfo");
|
|
ENDRECV();
|
|
}
|
|
#endif // MEMPHIS_MENU_WATERMARKS
|
|
|
|
BOOL NtUserCheckMenuRadioItem(
|
|
IN HMENU hMenu,
|
|
IN UINT wIDFirst,
|
|
IN UINT wIDLast,
|
|
IN UINT wIDCheck,
|
|
IN UINT flags)
|
|
{
|
|
PMENU pmenu;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHMENU(pmenu, hMenu);
|
|
|
|
retval = _CheckMenuRadioItem(
|
|
pmenu,
|
|
wIDFirst,
|
|
wIDLast,
|
|
wIDCheck,
|
|
flags);
|
|
|
|
TRACE("NtUserCheckMenuRadioItem");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSetMenuDefaultItem(
|
|
IN HMENU hMenu,
|
|
IN UINT wID,
|
|
IN UINT fByPosition)
|
|
{
|
|
PMENU pmenu;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHMENU(pmenu, hMenu);
|
|
|
|
retval = _SetMenuDefaultItem(
|
|
pmenu,
|
|
wID,
|
|
fByPosition);
|
|
|
|
TRACE("NtUserSetMenuDefaultItem");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSetMenuContextHelpId(
|
|
IN HMENU hMenu,
|
|
IN DWORD dwContextHelpId)
|
|
{
|
|
PMENU pmenu;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHMENU(pmenu, hMenu);
|
|
|
|
retval = _SetMenuContextHelpId(
|
|
pmenu,
|
|
dwContextHelpId);
|
|
|
|
TRACE("NtUserSetMenuContextHelpId");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserInitBrushes(
|
|
OUT HBRUSH *pahbrSystem,
|
|
OUT HBRUSH *phbrGray)
|
|
{
|
|
BEGINRECV_SHARED(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWrite(pahbrSystem, sizeof(HBRUSH) * COLOR_MAX, sizeof(DWORD));
|
|
ProbeAndWriteHandle((PHANDLE)phbrGray, ghbrGray);
|
|
|
|
RtlCopyMemory(pahbrSystem, ahbrSystem, sizeof(HBRUSH) * COLOR_MAX);
|
|
|
|
retval = TRUE;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserInitBrushes");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserDrawAnimatedRects(
|
|
IN HWND hwnd,
|
|
IN int idAni,
|
|
IN CONST RECT *lprcFrom,
|
|
IN CONST RECT *lprcTo)
|
|
{
|
|
PWND pwnd;
|
|
TL tlpwnd;
|
|
RECT rcFrom;
|
|
RECT rcTo;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
rcFrom = ProbeAndReadRect(lprcFrom);
|
|
rcTo = ProbeAndReadRect(lprcTo);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* We must lock because _DrawAnimatedRect() calls xxxDrawCaptionTemp()
|
|
* that does leave the critical section.
|
|
*/
|
|
ThreadLock(pwnd, &tlpwnd);
|
|
|
|
retval = xxx_DrawAnimatedRects(
|
|
pwnd,
|
|
idAni,
|
|
&rcFrom,
|
|
&rcTo
|
|
);
|
|
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("NtUserDrawAnimatedRects");
|
|
ENDRECV();
|
|
}
|
|
|
|
|
|
BOOL NtUserDrawCaption(
|
|
IN HWND hwnd,
|
|
IN HDC hdc,
|
|
IN CONST RECT *lprc,
|
|
IN UINT flags)
|
|
{
|
|
RECT rc;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, TRUE, hwnd);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
rc = ProbeAndReadRect(lprc);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = xxxDrawCaptionTemp(pwnd, hdc, &rc, NULL, NULL, NULL, flags);
|
|
|
|
TRACE("NtUserDrawCaption");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
BOOL NtUserPaintDesktop(
|
|
IN HDC hdc)
|
|
{
|
|
PTHREADINFO ptiCurrent;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ptiCurrent = PtiCurrent();
|
|
|
|
if (ptiCurrent->rpdesk != NULL) {
|
|
retval = InternalPaintDesktop((PDESKWND)(ptiCurrent->rpdesk->pDeskInfo->spwnd),
|
|
hdc,
|
|
TRUE);
|
|
}
|
|
|
|
TRACE("NtUserPaintDesktop");
|
|
ENDRECV();
|
|
}
|
|
|
|
SHORT NtUserGetAsyncKeyState(
|
|
IN int vKey)
|
|
{
|
|
|
|
PTHREADINFO ptiCurrent;
|
|
BEGINRECV_SHARED(SHORT, 0);
|
|
|
|
|
|
ptiCurrent = PtiCurrentShared();
|
|
UserAssert(ptiCurrent);
|
|
|
|
/*
|
|
* Don't allow other processes to spy on other deskops or a process
|
|
* to spy on the foreground if the desktop does not allow input spying
|
|
*/
|
|
if ((ptiCurrent->rpdesk != grpdeskRitInput) ||
|
|
( ((gptiForeground == NULL) || (PpiCurrent() != gptiForeground->ppi)) &&
|
|
!RtlAreAnyAccessesGranted(ptiCurrent->amdesk, (DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD)))) {
|
|
RIPERR0(ERROR_ACCESS_DENIED, RIP_WARNING, "GetAysncKeyState: not"
|
|
" foreground desktop or no desktop hooking (input spying)");
|
|
MSGERROR();
|
|
}
|
|
UserAssert(!(ptiCurrent->rpdesk->rpwinstaParent->dwFlags & WSF_NOIO));
|
|
|
|
retval = _GetAsyncKeyState(vKey);
|
|
|
|
/*
|
|
* Update the client side key state cache.
|
|
*/
|
|
ptiCurrent->pClientInfo->dwAsyncKeyCache = gpsi->dwAsyncKeyCache;
|
|
RtlCopyMemory(ptiCurrent->pClientInfo->afAsyncKeyState,
|
|
gafAsyncKeyState,
|
|
CBASYNCKEYCACHE);
|
|
RtlCopyMemory(ptiCurrent->pClientInfo->afAsyncKeyStateRecentDown,
|
|
gafAsyncKeyStateRecentDown,
|
|
CBASYNCKEYCACHE);
|
|
|
|
TRACE("NtUserGetAsyncKeyState");
|
|
ENDRECV();
|
|
}
|
|
|
|
HBRUSH NtUserGetControlBrush(
|
|
IN HWND hwnd,
|
|
IN HDC hdc,
|
|
IN UINT msg)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(HBRUSH, NULL, hwnd);
|
|
|
|
retval = xxxGetControlBrush(
|
|
pwnd,
|
|
hdc,
|
|
msg);
|
|
|
|
TRACE("NtUserGetControlBrush");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
HBRUSH NtUserGetControlColor(
|
|
IN HWND hwndParent,
|
|
IN HWND hwndCtl,
|
|
IN HDC hdc,
|
|
IN UINT msg)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
PWND pwndCtl;
|
|
TL tlpwndCtl;
|
|
|
|
BEGINRECV_HWNDLOCK(HBRUSH, NULL, hwndParent);
|
|
|
|
ValidateHWND(pwndCtl, hwndCtl);
|
|
|
|
ThreadLockAlwaysWithPti(ptiCurrent, pwndCtl, &tlpwndCtl);
|
|
|
|
retval = xxxGetControlColor(
|
|
pwnd,
|
|
pwndCtl,
|
|
hdc,
|
|
msg);
|
|
|
|
ThreadUnlock(&tlpwndCtl);
|
|
|
|
TRACE("NtUserGetControlColor");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
HMENU NtUserEndMenu(VOID)
|
|
{
|
|
PTHREADINFO ptiCurrent;
|
|
|
|
BEGINRECV(HMENU, NULL);
|
|
|
|
ptiCurrent = PtiCurrent();
|
|
|
|
if (ptiCurrent->pMenuState != NULL) {
|
|
xxxEndMenu(ptiCurrent->pMenuState);
|
|
}
|
|
retval = NULL;
|
|
|
|
TRACEVOID("NtUserEndMenu");
|
|
ENDRECV();
|
|
}
|
|
|
|
int NtUserCountClipboardFormats(
|
|
VOID)
|
|
{
|
|
PWINDOWSTATION pwinsta;
|
|
|
|
BEGINRECV_SHARED(int, 0);
|
|
|
|
/*
|
|
* Blow it off if the caller doesn't have the proper access rights
|
|
*/
|
|
if (!CheckClipboardAccess(&pwinsta)) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = pwinsta->cNumClipFormats;
|
|
|
|
TRACE("NtUserCountClipboardFormats");
|
|
ENDRECV();
|
|
}
|
|
|
|
UINT NtUserGetCaretBlinkTime(
|
|
VOID)
|
|
{
|
|
BEGINRECV_SHARED(UINT, 0);
|
|
|
|
/*
|
|
* Blow it off if the caller doesn't have the proper access rights
|
|
*/
|
|
if (!CheckGrantedAccess(PpiCurrent()->amwinsta, WINSTA_READATTRIBUTES)) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = gpsi->dtCaretBlink;
|
|
|
|
TRACE("NtUserGetCaretBlinkTime");
|
|
ENDRECV();
|
|
}
|
|
|
|
HWND NtUserGetClipboardOwner(
|
|
VOID)
|
|
{
|
|
PWINDOWSTATION pwinsta;
|
|
|
|
BEGINRECV_SHARED(HWND, NULL);
|
|
|
|
/*
|
|
* Blow it off if the caller doesn't have the proper access rights
|
|
*/
|
|
if (!CheckClipboardAccess(&pwinsta)) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = PtoH(pwinsta->spwndClipOwner);
|
|
|
|
TRACE("NtUserGetClipboardOwner");
|
|
ENDRECV();
|
|
}
|
|
|
|
HWND NtUserGetClipboardViewer(
|
|
VOID)
|
|
{
|
|
PWINDOWSTATION pwinsta;
|
|
|
|
BEGINRECV_SHARED(HWND, NULL);
|
|
|
|
/*
|
|
* Blow it off if the caller doesn't have the proper access rights
|
|
*/
|
|
if (!CheckClipboardAccess(&pwinsta)) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = PtoH(pwinsta->spwndClipViewer);
|
|
|
|
TRACE("NtUserGetClipboardViewer");
|
|
ENDRECV();
|
|
}
|
|
|
|
UINT NtUserGetDoubleClickTime(
|
|
VOID)
|
|
{
|
|
BEGINRECV_SHARED(UINT, 0);
|
|
|
|
/*
|
|
* Blow it off if the caller doesn't have the proper access rights
|
|
*/
|
|
if (!CheckGrantedAccess(PpiCurrent()->amwinsta, WINSTA_READATTRIBUTES)) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = dtDblClk;
|
|
|
|
TRACE("NtUserGetDoubleClickTime");
|
|
ENDRECV();
|
|
}
|
|
|
|
HWND NtUserGetForegroundWindow(
|
|
VOID)
|
|
{
|
|
BEGINRECV_SHARED(HWND, NULL);
|
|
|
|
/*
|
|
* Only return a window if there is a foreground queue and the
|
|
* caller has access to the current desktop.
|
|
*/
|
|
if (gpqForeground == NULL || gpqForeground->spwndActive == NULL ||
|
|
PtiCurrentShared()->rpdesk != gpqForeground->spwndActive->head.rpdesk) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = PtoHq(gpqForeground->spwndActive);
|
|
|
|
TRACE("NtUserGetForegroundWindow");
|
|
ENDRECV();
|
|
}
|
|
|
|
HWND NtUserGetOpenClipboardWindow(
|
|
VOID)
|
|
{
|
|
PWINDOWSTATION pwinsta;
|
|
|
|
BEGINRECV_SHARED(HWND, NULL);
|
|
|
|
/*
|
|
* Blow it off if the caller doesn't have the proper access rights
|
|
*/
|
|
if (!CheckClipboardAccess(&pwinsta)) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = PtoH(pwinsta->spwndClipOpen);
|
|
|
|
TRACE("NtUserGetOpenClipboardWindow");
|
|
ENDRECV();
|
|
}
|
|
|
|
int NtUserGetPriorityClipboardFormat(
|
|
IN UINT *paFormatPriorityList,
|
|
IN int cFormats)
|
|
{
|
|
BEGINRECV_SHARED(int, 0);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
#if defined(_X86_)
|
|
ProbeForRead(paFormatPriorityList, sizeof(UINT) * cFormats, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(paFormatPriorityList, sizeof(UINT) * cFormats, sizeof(DWORD));
|
|
#endif
|
|
|
|
retval = _GetPriorityClipboardFormat(
|
|
paFormatPriorityList,
|
|
cFormats);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetPriorityClipboardFormat");
|
|
ENDRECV();
|
|
}
|
|
|
|
HMENU NtUserGetSystemMenu(
|
|
IN HWND hwnd,
|
|
IN BOOL bRevert)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND(HMENU, NULL, hwnd);
|
|
|
|
retval = (HMENU)_GetSystemMenu(pwnd, bRevert);
|
|
retval = PtoH((PVOID)retval);
|
|
|
|
TRACE("NtUserGetSystemMenu");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
BOOL NtUserGetUpdateRect(
|
|
IN HWND hwnd,
|
|
IN LPRECT prect OPTIONAL,
|
|
IN BOOL bErase)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
if (ARGUMENT_PRESENT(prect))
|
|
ProbeForWriteRect(prect);
|
|
|
|
retval = xxxGetUpdateRect(
|
|
pwnd,
|
|
prect,
|
|
bErase);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetUpdateRect");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
BOOL NtUserHideCaret(
|
|
IN HWND hwnd)
|
|
{
|
|
PWND pwnd;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
retval = _HideCaret(pwnd);
|
|
|
|
TRACE("NtUserHideCaret");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserHiliteMenuItem(
|
|
IN HWND hwnd,
|
|
IN HMENU hMenu,
|
|
IN UINT uIDHiliteItem,
|
|
IN UINT uHilite)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
PMENU pmenu;
|
|
TL tlpmenu;
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
|
|
TESTFLAGS(uHilite, MF_VALID);
|
|
|
|
ValidateHMENU(pmenu, hMenu);
|
|
|
|
ThreadLockAlwaysWithPti(ptiCurrent, pmenu, &tlpmenu);
|
|
|
|
retval = xxxHiliteMenuItem(
|
|
pwnd,
|
|
pmenu,
|
|
uIDHiliteItem,
|
|
uHilite);
|
|
|
|
ThreadUnlock(&tlpmenu);
|
|
|
|
TRACE("NtUserHiliteMenuItem");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
BOOL NtUserInvalidateRect(
|
|
IN HWND hwnd,
|
|
IN CONST RECT *prect OPTIONAL,
|
|
IN BOOL bErase)
|
|
{
|
|
PWND pwnd;
|
|
TL tlpwnd;
|
|
RECT rc;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
if (ARGUMENT_PRESENT(prect)) {
|
|
try {
|
|
rc = ProbeAndReadRect(prect);
|
|
prect = &rc;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
}
|
|
|
|
ThreadLock(pwnd, &tlpwnd);
|
|
|
|
retval = xxxInvalidateRect(
|
|
pwnd,
|
|
(PRECT)prect,
|
|
bErase);
|
|
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("NtUserInvalidateRect");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserIsClipboardFormatAvailable(
|
|
IN UINT nFormat)
|
|
{
|
|
PWINDOWSTATION pwinsta;
|
|
|
|
BEGINRECV_SHARED(BOOL, FALSE);
|
|
|
|
/*
|
|
* Blow it off if the caller doesn't have the proper access rights
|
|
*/
|
|
if (!CheckClipboardAccess(&pwinsta)) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = (FindClipFormat(pwinsta, nFormat) != NULL);
|
|
|
|
TRACE("NtUserIsClipboardFormatAvailable");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserKillTimer(
|
|
IN HWND hwnd,
|
|
IN UINT nIDEvent)
|
|
{
|
|
PWND pwnd;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
retval = _KillTimer(
|
|
pwnd,
|
|
nIDEvent);
|
|
|
|
TRACE("NtUserKillTimer");
|
|
ENDRECV();
|
|
}
|
|
|
|
HWND NtUserMinMaximize(
|
|
IN HWND hwnd,
|
|
IN UINT nCmdShow,
|
|
IN BOOL fKeepHidden)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(HWND, NULL, hwnd);
|
|
|
|
retval = (HWND)xxxMinMaximize(
|
|
pwnd,
|
|
nCmdShow,
|
|
MAKELONG(fKeepHidden != 0, gfAnimate));
|
|
retval = PtoH((PVOID)retval);
|
|
|
|
TRACE("NtUserMinMaximize");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
BOOL NtUserOpenClipboard(
|
|
IN HWND hwnd,
|
|
OUT PBOOL pfEmptyClient)
|
|
{
|
|
PWND pwnd;
|
|
TL tlpwnd;
|
|
BOOL fEmptyClient;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
ThreadLock(pwnd, &tlpwnd);
|
|
|
|
retval = xxxOpenClipboard(pwnd, &fEmptyClient);
|
|
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeAndWriteUlong(pfEmptyClient, fEmptyClient);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserOpenClipboard");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserPeekMessage(
|
|
OUT LPMSG pmsg,
|
|
IN HWND hwnd,
|
|
IN UINT wMsgFilterMin,
|
|
IN UINT wMsgFilterMax,
|
|
IN UINT wRemoveMsg,
|
|
OUT HKL *pHKL)
|
|
{
|
|
MSG msg;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
TESTFLAGS(wRemoveMsg, PM_VALID);
|
|
|
|
retval = xxxPeekMessage(
|
|
&msg,
|
|
hwnd,
|
|
wMsgFilterMin,
|
|
wMsgFilterMax,
|
|
wRemoveMsg);
|
|
|
|
/*
|
|
* Probe and write arguments only if PeekMessage suceeds otherwise
|
|
* we want to leave MSG undisturbed (bug 16224) to be compatible.
|
|
*/
|
|
if (retval) {
|
|
try {
|
|
ProbeAndWriteStructure(pmsg, msg, MSG);
|
|
ProbeAndWriteHandle((PHANDLE)pHKL, PtiCurrent()->spklActive->hkl);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
}
|
|
|
|
TRACE("NtUserPeekMessage");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserPostMessage(
|
|
IN HWND hwnd,
|
|
IN UINT msg,
|
|
IN DWORD wParam,
|
|
IN LONG lParam)
|
|
{
|
|
PWND pwnd;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
switch ((DWORD)hwnd) {
|
|
case 0xFFFFFFFF:
|
|
case 0x0000FFFF:
|
|
pwnd = (PWND)-1;
|
|
break;
|
|
|
|
case 0:
|
|
pwnd = NULL;
|
|
break;
|
|
|
|
default:
|
|
if ((pwnd = ValidateHwnd(hwnd)) == NULL) {
|
|
/*
|
|
* We fake terminates to dead windows! (SAS)
|
|
*/
|
|
errret = (msg == WM_DDE_TERMINATE);
|
|
MSGERROR();
|
|
}
|
|
break;
|
|
}
|
|
|
|
retval = _PostMessage(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
lParam);
|
|
|
|
TRACE("NtUserPostMessage");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSendNotifyMessage(
|
|
IN HWND hwnd,
|
|
IN UINT Msg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam OPTIONAL)
|
|
{
|
|
PWND pwnd;
|
|
TL tlpwnd;
|
|
LARGE_STRING strLParam;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
if ((Msg == WM_WININICHANGE || Msg == WM_DEVMODECHANGE) &&
|
|
ARGUMENT_PRESENT(lParam)) {
|
|
try {
|
|
strLParam = ProbeAndReadLargeString((PLARGE_STRING)lParam);
|
|
#if defined(_X86_)
|
|
ProbeForRead(strLParam.Buffer, strLParam.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(strLParam.Buffer, strLParam.Length,
|
|
strLParam.bAnsi ? sizeof(BYTE) : sizeof(WORD));
|
|
#endif
|
|
lParam = (LPARAM)&strLParam;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
}
|
|
|
|
ValidateHWNDFF(pwnd, hwnd);
|
|
|
|
if (pwnd != (PWND)0xFFFFFFFF)
|
|
ThreadLockAlways(pwnd, &tlpwnd);
|
|
|
|
retval = xxxSendNotifyMessage(
|
|
pwnd,
|
|
Msg,
|
|
wParam,
|
|
lParam );
|
|
|
|
if (pwnd != (PWND)0xFFFFFFFF)
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("NtUserSendNotifyMessage");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSendMessageCallback(
|
|
IN HWND hwnd,
|
|
IN UINT wMsg,
|
|
IN DWORD wParam,
|
|
IN LONG lParam,
|
|
IN SENDASYNCPROC lpResultCallBack,
|
|
IN DWORD dwData)
|
|
{
|
|
PWND pwnd;
|
|
TL tlpwnd;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHWNDFF(pwnd, hwnd);
|
|
|
|
if (pwnd != (PWND)0xFFFFFFFF)
|
|
ThreadLockAlways(pwnd, &tlpwnd);
|
|
|
|
retval = xxxSendMessageCallback(
|
|
pwnd,
|
|
wMsg,
|
|
wParam,
|
|
lParam,
|
|
lpResultCallBack,
|
|
dwData,
|
|
TRUE );
|
|
|
|
if (pwnd != (PWND)0xFFFFFFFF)
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("NtUserSendMessageCallback");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserRegisterHotKey(
|
|
IN HWND hwnd,
|
|
IN int id,
|
|
IN UINT fsModifiers,
|
|
IN UINT vk)
|
|
{
|
|
PWND pwnd;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
retval = _RegisterHotKey(
|
|
pwnd,
|
|
id,
|
|
fsModifiers,
|
|
vk);
|
|
|
|
TRACE("NtUserRegisterHotKey");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserRemoveMenu(
|
|
IN HMENU hmenu,
|
|
IN UINT nPosition,
|
|
IN UINT dwFlags)
|
|
{
|
|
PMENU pmenu;
|
|
#ifdef MEMPHIS_MENUS
|
|
TL tlpmenu;
|
|
#endif // MEMPHIS_MENUS
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
TESTFLAGS(dwFlags, MF_VALID);
|
|
|
|
ValidateHMENU(pmenu, hmenu);
|
|
|
|
#ifdef MEMPHIS_MENUS
|
|
ThreadLock( pmenu, &tlpmenu);
|
|
retval = xxxRemoveMenu(
|
|
pmenu,
|
|
nPosition,
|
|
dwFlags);
|
|
ThreadUnlock(&tlpmenu);
|
|
#else
|
|
retval = _RemoveMenu(
|
|
pmenu,
|
|
nPosition,
|
|
dwFlags);
|
|
#endif // MEMPHIS_MENUS
|
|
TRACE("NtUserRemoveMenu");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserScrollWindowEx(
|
|
IN HWND hwnd,
|
|
IN int dx,
|
|
IN int dy,
|
|
IN CONST RECT *prcScroll OPTIONAL,
|
|
IN CONST RECT *prcClip OPTIONAL,
|
|
IN HRGN hrgnUpdate,
|
|
OUT LPRECT prcUpdate OPTIONAL,
|
|
IN UINT flags)
|
|
{
|
|
RECT rcScroll;
|
|
RECT rcClip;
|
|
RECT rcUpdate;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
if (ARGUMENT_PRESENT(prcScroll)) {
|
|
rcScroll = ProbeAndReadRect(prcScroll);
|
|
prcScroll = &rcScroll;
|
|
}
|
|
if (ARGUMENT_PRESENT(prcClip)) {
|
|
rcClip = ProbeAndReadRect(prcClip);
|
|
prcClip = &rcClip;
|
|
}
|
|
|
|
retval = xxxScrollWindowEx(
|
|
pwnd,
|
|
dx,
|
|
dy,
|
|
(PRECT)prcScroll,
|
|
(PRECT)prcClip,
|
|
hrgnUpdate,
|
|
prcUpdate ? &rcUpdate : NULL,
|
|
flags);
|
|
|
|
if (ARGUMENT_PRESENT(prcUpdate)) {
|
|
ProbeAndWriteStructure(prcUpdate, rcUpdate, RECT);
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserScrollWindow");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
HWND NtUserSetActiveWindow(
|
|
IN HWND hwnd)
|
|
{
|
|
PWND pwnd;
|
|
TL tlpwnd;
|
|
|
|
BEGINRECV(HWND, NULL);
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
ThreadLock(pwnd, &tlpwnd);
|
|
|
|
retval = (HWND)xxxSetActiveWindow(pwnd);
|
|
retval = PtoH((PVOID)retval);
|
|
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("NtUserSetActiveWindow");
|
|
ENDRECV();
|
|
}
|
|
|
|
HWND NtUserSetCapture(
|
|
IN HWND hwnd)
|
|
{
|
|
PWND pwnd;
|
|
TL tlpwnd;
|
|
|
|
BEGINRECV(HWND, NULL);
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
ThreadLock(pwnd, &tlpwnd);
|
|
|
|
retval = (HWND)xxxSetCapture(pwnd);
|
|
retval = PtoH((PVOID)retval);
|
|
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("NtUserSetCapture");
|
|
ENDRECV();
|
|
}
|
|
|
|
WORD NtUserSetClassWord(
|
|
IN HWND hwnd,
|
|
IN int nIndex,
|
|
IN WORD wNewWord)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND(WORD, 0, hwnd);
|
|
|
|
retval = _SetClassWord(
|
|
pwnd,
|
|
nIndex,
|
|
wNewWord);
|
|
|
|
TRACE("NtUserSetClassWord");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
HWND NtUserSetClipboardViewer(
|
|
IN HWND hwnd)
|
|
{
|
|
PWND pwnd;
|
|
TL tlpwnd;
|
|
|
|
BEGINRECV(HWND, NULL);
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
ThreadLock(pwnd, &tlpwnd);
|
|
|
|
retval = (HWND)xxxSetClipboardViewer(pwnd);
|
|
retval = PtoH((PVOID)retval);
|
|
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("NtUserSetClipboardViewer");
|
|
ENDRECV();
|
|
}
|
|
|
|
HCURSOR NtUserSetCursor(
|
|
IN HCURSOR hCursor)
|
|
{
|
|
PCURSOR pCursor;
|
|
|
|
BEGINRECV(HCURSOR, NULL);
|
|
|
|
ValidateHCURSOROPT(pCursor, hCursor);
|
|
|
|
retval = (HCURSOR)_SetCursor(pCursor);
|
|
retval = PtoH((PVOID)retval);
|
|
|
|
TRACE("NtUserSetCursor");
|
|
ENDRECV();
|
|
}
|
|
|
|
HWND NtUserSetFocus(
|
|
IN HWND hwnd)
|
|
{
|
|
PWND pwnd;
|
|
TL tlpwnd;
|
|
|
|
BEGINRECV(HWND, NULL);
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
ThreadLock(pwnd, &tlpwnd);
|
|
|
|
retval = (HWND)xxxSetFocus(pwnd);
|
|
retval = PtoH((PVOID)retval);
|
|
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("NtUserSetFocus");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSetMenu(
|
|
IN HWND hwnd,
|
|
IN HMENU hmenu,
|
|
IN BOOL fRedraw)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
PMENU pmenu;
|
|
TL tlpmenu;
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
|
|
ValidateHMENUOPT(pmenu, hmenu);
|
|
|
|
ThreadLockWithPti(ptiCurrent, pmenu, &tlpmenu);
|
|
|
|
retval = xxxSetMenu(
|
|
pwnd,
|
|
pmenu,
|
|
fRedraw);
|
|
|
|
ThreadUnlock(&tlpmenu);
|
|
|
|
TRACE("NtUserSetMenu");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
HWND NtUserSetParent(
|
|
IN HWND hwndChild,
|
|
IN HWND hwndNewParent)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
PWND pwndNewParent;
|
|
TL tlpwndNewParent;
|
|
|
|
BEGINRECV_HWNDLOCK(HWND, NULL, hwndChild);
|
|
|
|
ValidateHWNDOPT(pwndNewParent, hwndNewParent);
|
|
|
|
ThreadLockWithPti(ptiCurrent, pwndNewParent, &tlpwndNewParent);
|
|
|
|
retval = (HWND)xxxSetParent(
|
|
pwnd,
|
|
pwndNewParent);
|
|
retval = PtoH((PVOID)retval);
|
|
|
|
ThreadUnlock(&tlpwndNewParent);
|
|
|
|
TRACE("NtUserSetParent");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
int NtUserSetScrollInfo(
|
|
IN HWND hwnd,
|
|
IN int nBar,
|
|
IN LPCSCROLLINFO pInfo,
|
|
IN BOOL fRedraw)
|
|
{
|
|
SCROLLINFO si;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
|
|
LIMITVALUE(nBar, SB_MAX, "SetScrollInfo");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
si = ProbeAndReadScrollInfo(pInfo);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = xxxSetScrollBar(
|
|
pwnd,
|
|
nBar,
|
|
&si,
|
|
fRedraw);
|
|
|
|
TRACE("NtUserSetScrollInfo");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
BOOL NtUserSetSysColors(
|
|
IN int nCount,
|
|
IN CONST INT *pSysColor,
|
|
IN CONST COLORREF *pColorValues,
|
|
IN UINT uOptions)
|
|
{
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
#if defined(_X86_)
|
|
ProbeForRead(pSysColor, nCount * sizeof(*pSysColor), sizeof(BYTE));
|
|
ProbeForRead(pColorValues, nCount * sizeof(*pColorValues), sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(pSysColor, nCount * sizeof(*pSysColor), sizeof(DWORD));
|
|
ProbeForRead(pColorValues, nCount * sizeof(*pColorValues), sizeof(DWORD));
|
|
#endif
|
|
|
|
retval = xxxSetSysColors(
|
|
nCount,
|
|
(LPINT)pSysColor,
|
|
(LPDWORD)pColorValues,
|
|
uOptions);
|
|
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserSetSysColors");
|
|
ENDRECV();
|
|
}
|
|
|
|
UINT NtUserSetTimer(
|
|
IN HWND hwnd,
|
|
IN UINT nIDEvent,
|
|
IN UINT wElapse,
|
|
IN TIMERPROC pTimerFunc)
|
|
{
|
|
PWND pwnd;
|
|
|
|
BEGINRECV(UINT, 0);
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
retval = _SetTimer(
|
|
pwnd,
|
|
nIDEvent,
|
|
wElapse,
|
|
(WNDPROC_PWND)pTimerFunc);
|
|
|
|
TRACE("NtUserSetTimer");
|
|
ENDRECV();
|
|
}
|
|
|
|
LONG NtUserSetWindowLong(
|
|
IN HWND hwnd,
|
|
IN int nIndex,
|
|
IN LONG dwNewLong,
|
|
IN BOOL bAnsi)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
|
|
retval = xxxSetWindowLong(
|
|
pwnd,
|
|
nIndex,
|
|
dwNewLong,
|
|
bAnsi);
|
|
|
|
TRACE("NtUserSetWindowLong");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
WORD NtUserSetWindowWord(
|
|
IN HWND hwnd,
|
|
IN int nIndex,
|
|
IN WORD wNewWord)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND(WORD, 0, hwnd);
|
|
|
|
retval = _SetWindowWord(
|
|
pwnd,
|
|
nIndex,
|
|
wNewWord);
|
|
|
|
TRACE("NtUserSetWindowWord");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
HHOOK NtUserSetWindowsHookAW(
|
|
IN int nFilterType,
|
|
IN HOOKPROC pfnFilterProc,
|
|
IN BOOL bAnsi)
|
|
{
|
|
BEGINRECV(HHOOK, NULL);
|
|
|
|
retval = (HHOOK)_SetWindowsHookAW(
|
|
nFilterType,
|
|
pfnFilterProc,
|
|
bAnsi);
|
|
|
|
TRACE("NtUserSetWindowsHookAW");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserShowCaret(
|
|
IN HWND hwnd)
|
|
{
|
|
PWND pwnd;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
retval = _ShowCaret(
|
|
pwnd);
|
|
|
|
TRACE("NtUserShowCaret");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserShowScrollBar(
|
|
IN HWND hwnd,
|
|
IN int iBar,
|
|
IN BOOL fShow)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
|
|
LIMITVALUE(iBar, SB_MAX, "ShowScrollBar");
|
|
|
|
retval = xxxShowScrollBar(
|
|
pwnd,
|
|
iBar,
|
|
fShow);
|
|
|
|
TRACE("NtUserShowScrollBar");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
BOOL NtUserShowWindowAsync(
|
|
IN HWND hwnd,
|
|
IN int nCmdShow)
|
|
{
|
|
PWND pwnd;
|
|
TL tlpwnd;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
LIMITVALUE(nCmdShow, SW_MAX, "ShowWindowAsync");
|
|
|
|
ValidateHWNDND(pwnd, hwnd);
|
|
|
|
ThreadLockAlways(pwnd, &tlpwnd);
|
|
|
|
retval = _ShowWindowAsync(
|
|
pwnd,
|
|
nCmdShow);
|
|
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("NtUserShowWindowAsync");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserShowWindow(
|
|
IN HWND hwnd,
|
|
IN int nCmdShow)
|
|
{
|
|
PWND pwnd;
|
|
TL tlpwnd;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
LIMITVALUE(nCmdShow, SW_MAX, "ShowWindow");
|
|
|
|
ValidateHWNDND(pwnd, hwnd);
|
|
|
|
/*
|
|
* Let's not allow the window to be shown/hidden once we
|
|
* started the destruction of the window.
|
|
*/
|
|
if (TestWF(pwnd, WFINDESTROY)) {
|
|
RIPERR1(ERROR_INVALID_PARAMETER,
|
|
RIP_WARNING,
|
|
"ShowWindow: Window is being destroyed (0x%lx)",
|
|
pwnd);
|
|
MSGERROR();
|
|
}
|
|
|
|
ThreadLockAlways(pwnd, &tlpwnd);
|
|
|
|
retval = xxxShowWindow(
|
|
pwnd,
|
|
MAKELONG(nCmdShow, gfAnimate));
|
|
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("NtUserShowWindow");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserTrackMouseEvent(
|
|
IN OUT LPTRACKMOUSEEVENT lpTME)
|
|
{
|
|
TRACKMOUSEEVENT tme;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
tme = ProbeAndReadTrackMouseEvent(lpTME);
|
|
|
|
if (tme.cbSize != sizeof(tme)) {
|
|
RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "TrackMouseEvent: invalid size %lX", tme.cbSize);
|
|
MSGERROR();
|
|
}
|
|
|
|
TESTFLAGS(tme.dwFlags, TME_VALID);
|
|
|
|
if (tme.dwFlags & TME_QUERY) {
|
|
retval = QueryTrackMouseEvent(&tme);
|
|
RtlCopyMemory(lpTME, &tme, sizeof(tme));
|
|
} else {
|
|
retval = TrackMouseEvent(&tme);
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserTrackMouseEvent");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserTrackPopupMenuEx(
|
|
IN HMENU hMenu,
|
|
IN UINT uFlags,
|
|
IN int x,
|
|
IN int y,
|
|
IN HWND hwnd,
|
|
IN LPTPMPARAMS pparamst OPTIONAL)
|
|
{
|
|
PWND pwnd;
|
|
PMENU pmenu;
|
|
TL tlpwnd;
|
|
TL tlpmenu;
|
|
PTHREADINFO ptiCurrent;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
TESTFLAGS(uFlags, TPM_VALID | TPM_RETURNCMD);
|
|
|
|
ValidateHMENU(pmenu, hMenu);
|
|
ValidateHWND(pwnd, hwnd);
|
|
|
|
ptiCurrent = PtiCurrent();
|
|
ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd);
|
|
ThreadLockAlwaysWithPti(ptiCurrent, pmenu, &tlpmenu);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
if (ARGUMENT_PRESENT(pparamst))
|
|
ProbeAndReadPopupParams(pparamst);
|
|
|
|
retval = xxxTrackPopupMenuEx(
|
|
pmenu,
|
|
uFlags,
|
|
x,
|
|
y,
|
|
pwnd,
|
|
pparamst);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERRORCLEANUP();
|
|
}
|
|
|
|
CLEANUPRECV();
|
|
|
|
ThreadUnlock(&tlpmenu);
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("NtUserTrackPopupMenuEx");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserTranslateMessage(
|
|
IN CONST MSG *lpMsg,
|
|
IN UINT flags)
|
|
{
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeMessage(lpMsg);
|
|
|
|
if (ValidateHwnd(lpMsg->hwnd) != NULL) {
|
|
retval = _TranslateMessage(
|
|
(LPMSG)lpMsg,
|
|
flags);
|
|
} else {
|
|
retval = FALSE;
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserTranslateMessage");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserUnhookWindowsHookEx(
|
|
IN HHOOK hhk)
|
|
{
|
|
PHOOK phk;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHHOOK(phk, hhk);
|
|
|
|
retval = _UnhookWindowsHookEx(
|
|
phk);
|
|
|
|
TRACE("NtUserUnhookWindowsHookEx");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserUnregisterHotKey(
|
|
IN HWND hwnd,
|
|
IN int id)
|
|
{
|
|
PWND pwnd;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
retval = _UnregisterHotKey(
|
|
pwnd,
|
|
id);
|
|
|
|
TRACE("NtUserUnregisterHotKey");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserValidateRect(
|
|
IN HWND hwnd,
|
|
IN CONST RECT *lpRect OPTIONAL)
|
|
{
|
|
PWND pwnd;
|
|
TL tlpwnd;
|
|
RECT rc;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
if (ARGUMENT_PRESENT(lpRect)) {
|
|
try {
|
|
rc = ProbeAndReadRect(lpRect);
|
|
lpRect = &rc;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
}
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
ThreadLock(pwnd, &tlpwnd);
|
|
|
|
retval = xxxValidateRect(pwnd, (PRECT)lpRect);
|
|
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("NtUserValidateRect");
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserWaitForInputIdle(
|
|
IN DWORD idProcess,
|
|
IN DWORD dwMilliseconds,
|
|
IN BOOL fSharedWow)
|
|
{
|
|
BEGINRECV(DWORD, (DWORD)-1);
|
|
|
|
retval = xxxWaitForInputIdle(
|
|
(DWORD)idProcess,
|
|
dwMilliseconds,
|
|
fSharedWow);
|
|
|
|
TRACE("NtUserWaitForInputIdle");
|
|
ENDRECV();
|
|
}
|
|
|
|
HWND NtUserWindowFromPoint(
|
|
IN POINT Point)
|
|
{
|
|
BEGINRECV(HWND, NULL);
|
|
|
|
retval = (HWND)xxxWindowFromPoint(
|
|
Point);
|
|
retval = PtoH((PVOID)retval);
|
|
|
|
TRACE("NtUserWindowFromPoint");
|
|
ENDRECV();
|
|
}
|
|
|
|
HDC NtUserBeginPaint(
|
|
IN HWND hwnd,
|
|
OUT LPPAINTSTRUCT lpPaint)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(HDC, NULL, hwnd);
|
|
|
|
retval = xxxBeginPaint(pwnd, &ps);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeAndWriteStructure(lpPaint, ps, PAINTSTRUCT);
|
|
} except (StubExceptionHandler()) {
|
|
_EndPaint(pwnd, &ps);
|
|
retval = 0;
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserBeginPaint");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
BOOL NtUserCreateCaret(
|
|
IN HWND hwnd,
|
|
IN HBITMAP hBitmap,
|
|
IN int nWidth,
|
|
IN int nHeight)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND(DWORD, 0, hwnd);
|
|
|
|
retval = _CreateCaret(
|
|
pwnd,
|
|
hBitmap,
|
|
nWidth,
|
|
nHeight
|
|
);
|
|
|
|
TRACE("NtUserCreateCaret");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
BOOL NtUserEndPaint(
|
|
IN HWND hwnd,
|
|
IN CONST PAINTSTRUCT *lpPaint)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND(BOOL, FALSE, hwnd);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ps = ProbeAndReadPaintStruct(lpPaint);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = _EndPaint(pwnd, &ps);
|
|
|
|
TRACE("NtUserEndPaint");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
int NtUserExcludeUpdateRgn(
|
|
IN HDC hdc,
|
|
IN HWND hwnd)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND(int, ERROR, hwnd);
|
|
|
|
retval = _ExcludeUpdateRgn(hdc, pwnd);
|
|
|
|
TRACE("NtUserExcludeUpdateRgn");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
HDC NtUserGetDC(
|
|
IN HWND hwnd)
|
|
{
|
|
PWND pwnd;
|
|
|
|
BEGINRECV(HDC, NULL);
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
retval = _GetDC(
|
|
pwnd);
|
|
|
|
TRACE("NtUserGetDC");
|
|
ENDRECV();
|
|
}
|
|
|
|
HDC NtUserGetDCEx(
|
|
IN HWND hwnd,
|
|
IN HRGN hrgnClip,
|
|
IN DWORD flags)
|
|
{
|
|
PWND pwnd;
|
|
|
|
BEGINRECV(HDC, NULL);
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
retval = _GetDCEx(
|
|
pwnd,
|
|
hrgnClip,
|
|
flags);
|
|
|
|
TRACE("NtUserGetDCEx");
|
|
ENDRECV();
|
|
}
|
|
|
|
HDC NtUserGetWindowDC(
|
|
IN HWND hwnd)
|
|
{
|
|
PWND pwnd;
|
|
|
|
BEGINRECV(HDC, NULL);
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
|
|
retval = _GetWindowDC(pwnd);
|
|
|
|
TRACE("NtUserGetWindowDC");
|
|
ENDRECV();
|
|
}
|
|
|
|
int NtUserGetUpdateRgn(
|
|
IN HWND hwnd,
|
|
IN HRGN hrgn,
|
|
IN BOOL bErase)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(int, ERROR, hwnd);
|
|
|
|
retval = xxxGetUpdateRgn(
|
|
pwnd,
|
|
hrgn,
|
|
bErase);
|
|
|
|
TRACE("NtUserGetUpdateRgn");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
BOOL NtUserRedrawWindow(
|
|
IN HWND hwnd,
|
|
IN CONST RECT *lprcUpdate OPTIONAL,
|
|
IN HRGN hrgnUpdate,
|
|
IN UINT flags)
|
|
{
|
|
RECT rc;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK_OPT(BOOL, FALSE, hwnd);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
if (ARGUMENT_PRESENT(lprcUpdate)) {
|
|
try {
|
|
rc = ProbeAndReadRect(lprcUpdate);
|
|
lprcUpdate = &rc;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
}
|
|
|
|
TESTFLAGS(flags, RDW_VALIDMASK);
|
|
|
|
retval = xxxRedrawWindow(
|
|
pwnd,
|
|
(PRECT)lprcUpdate,
|
|
hrgnUpdate,
|
|
flags);
|
|
|
|
TRACE("NtUserRedrawWindow");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
BOOL NtUserInvalidateRgn(
|
|
IN HWND hwnd,
|
|
IN HRGN hrgn,
|
|
IN BOOL bErase)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(BOOL, FALSE, hwnd);
|
|
|
|
retval = xxxInvalidateRgn(
|
|
pwnd,
|
|
hrgn,
|
|
bErase);
|
|
|
|
TRACE("NtUserInvalidateRgn");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
int NtUserSetWindowRgn(
|
|
IN HWND hwnd,
|
|
IN HRGN hrgn,
|
|
IN BOOL bRedraw)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(int, 0, hwnd);
|
|
|
|
if (pwnd == PWNDDESKTOP(pwnd))
|
|
MSGERROR();
|
|
|
|
retval = xxxSetWindowRgn(pwnd, hrgn, bRedraw);
|
|
|
|
TRACE("NtUserSetWindowRgn");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
BOOL NtUserScrollDC(
|
|
IN HDC hdc,
|
|
IN int dx,
|
|
IN int dy,
|
|
IN CONST RECT *prcScroll OPTIONAL,
|
|
IN CONST RECT *prcClip OPTIONAL,
|
|
IN HRGN hrgnUpdate,
|
|
OUT LPRECT prcUpdate OPTIONAL)
|
|
{
|
|
RECT rcScroll;
|
|
RECT rcClip;
|
|
RECT rcUpdate;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
if (ARGUMENT_PRESENT(prcScroll)) {
|
|
rcScroll = ProbeAndReadRect(prcScroll);
|
|
prcScroll = &rcScroll;
|
|
}
|
|
if (ARGUMENT_PRESENT(prcClip)) {
|
|
rcClip = ProbeAndReadRect(prcClip);
|
|
prcClip = &rcClip;
|
|
}
|
|
|
|
retval = _ScrollDC(
|
|
hdc,
|
|
dx,
|
|
dy,
|
|
(PRECT)prcScroll,
|
|
(PRECT)prcClip,
|
|
hrgnUpdate,
|
|
prcUpdate ? &rcUpdate : NULL);
|
|
|
|
if (ARGUMENT_PRESENT(prcUpdate)) {
|
|
ProbeAndWriteStructure(prcUpdate, rcUpdate, RECT);
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
ENDRECV();
|
|
}
|
|
|
|
int NtUserInternalGetWindowText(
|
|
IN HWND hwnd,
|
|
OUT LPWSTR lpString,
|
|
IN int nMaxCount)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND_SHARED(DWORD, 0, hwnd);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
#if defined(_X86_)
|
|
ProbeForWrite(lpString, nMaxCount * sizeof(WCHAR), sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite(lpString, nMaxCount * sizeof(WCHAR), sizeof(WCHAR));
|
|
#endif
|
|
|
|
retval = _InternalGetWindowText(
|
|
pwnd,
|
|
lpString,
|
|
nMaxCount);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserInternalGetWindowText");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
int NtUserToUnicodeEx(
|
|
IN UINT wVirtKey,
|
|
IN UINT wScanCode,
|
|
IN PBYTE lpKeyState,
|
|
OUT LPWSTR pwszBuff,
|
|
IN int cchBuff,
|
|
IN UINT wFlags,
|
|
IN HKL hKeyboardLayout)
|
|
{
|
|
BEGINRECV_SHARED(int, 0);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForRead(lpKeyState, 256, sizeof(BYTE));
|
|
#if defined(_X86_)
|
|
ProbeForWrite(pwszBuff, cchBuff * sizeof(WCHAR), sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite(pwszBuff, cchBuff * sizeof(WCHAR), sizeof(WCHAR));
|
|
#endif
|
|
|
|
retval = _ToUnicodeEx(
|
|
wVirtKey,
|
|
wScanCode,
|
|
(LPBYTE)lpKeyState,
|
|
(LPWSTR)pwszBuff,
|
|
cchBuff,
|
|
wFlags,
|
|
hKeyboardLayout);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserToUnicodeEx");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserYieldTask(
|
|
VOID)
|
|
{
|
|
PTHREADINFO ptiCurrent;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
/*
|
|
* Make sure this process is running in the background if it is just
|
|
* spinning.
|
|
*/
|
|
ptiCurrent = PtiCurrent();
|
|
|
|
ptiCurrent->pClientInfo->cSpins++;
|
|
|
|
/*
|
|
* CheckProcessBackground see input.c for comments
|
|
*/
|
|
if (ptiCurrent->pClientInfo->cSpins >= CSPINBACKGROUND) {
|
|
ptiCurrent->pClientInfo->cSpins = 0;
|
|
ptiCurrent->TIF_flags |= TIF_SPINNING;
|
|
ptiCurrent->pClientInfo->dwTIFlags |= TIF_SPINNING;
|
|
|
|
if (!(ptiCurrent->ppi->W32PF_Flags & W32PF_FORCEBACKGROUNDPRIORITY)) {
|
|
ptiCurrent->ppi->W32PF_Flags |= W32PF_FORCEBACKGROUNDPRIORITY;
|
|
if (ptiCurrent->ppi == gppiWantForegroundPriority) {
|
|
SetForegroundPriority(ptiCurrent, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = xxxUserYield(ptiCurrent);
|
|
|
|
TRACE("NtUserYieldTask");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserWaitMessage(
|
|
VOID)
|
|
{
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
retval = xxxWaitMessage();
|
|
|
|
TRACE("NtUserWaitMessage");
|
|
ENDRECV();
|
|
}
|
|
|
|
UINT NtUserLockWindowStation(
|
|
IN HWINSTA hwinsta)
|
|
{
|
|
PWINDOWSTATION pwinsta;
|
|
NTSTATUS Status;
|
|
|
|
BEGINRECV(UINT, 0);
|
|
|
|
Status = ValidateHwinsta(hwinsta, 0, &pwinsta);
|
|
if (!NT_SUCCESS(Status))
|
|
MSGERROR();
|
|
|
|
retval = _LockWindowStation(pwinsta);
|
|
|
|
ObDereferenceObject(pwinsta);
|
|
|
|
TRACE("NtUserLockWindowStation");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserUnlockWindowStation(
|
|
IN HWINSTA hwinsta)
|
|
{
|
|
PWINDOWSTATION pwinsta;
|
|
NTSTATUS Status;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
Status = ValidateHwinsta(hwinsta, 0, &pwinsta);
|
|
if (!NT_SUCCESS(Status))
|
|
MSGERROR();
|
|
|
|
retval = _UnlockWindowStation(pwinsta);
|
|
|
|
ObDereferenceObject(pwinsta);
|
|
|
|
TRACE("NtUserUnlockWindowStation");
|
|
ENDRECV();
|
|
}
|
|
|
|
UINT NtUserSetWindowStationUser(
|
|
IN HWINSTA hwinsta,
|
|
IN PLUID pLuidUser,
|
|
IN PSID pSidUser OPTIONAL,
|
|
IN DWORD cbSidUser)
|
|
{
|
|
PWINDOWSTATION pwinsta;
|
|
NTSTATUS Status;
|
|
|
|
BEGINRECV(UINT, FALSE);
|
|
|
|
Status = ValidateHwinsta(hwinsta, 0, &pwinsta);
|
|
if (!NT_SUCCESS(Status))
|
|
MSGERROR();
|
|
|
|
try {
|
|
ProbeForRead(pLuidUser, sizeof(*pLuidUser), sizeof(DWORD));
|
|
if (ARGUMENT_PRESENT(pSidUser))
|
|
ProbeForRead(pSidUser, cbSidUser, sizeof(DWORD));
|
|
|
|
retval = _SetWindowStationUser(pwinsta, pLuidUser, pSidUser, cbSidUser);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERRORCLEANUP();
|
|
}
|
|
|
|
CLEANUPRECV();
|
|
|
|
ObDereferenceObject(pwinsta);
|
|
|
|
TRACE("NtUserSetWindowStationUser");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSetLogonNotifyWindow(
|
|
IN HWINSTA hwinsta,
|
|
IN HWND hwnd)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
PWINDOWSTATION pwinsta;
|
|
NTSTATUS Status;
|
|
|
|
BEGINRECV_HWND(DWORD, 0, hwnd);
|
|
|
|
Status = ValidateHwinsta(hwinsta, 0, &pwinsta);
|
|
if (!NT_SUCCESS(Status))
|
|
MSGERROR();
|
|
|
|
retval = _SetLogonNotifyWindow(pwinsta, pwnd);
|
|
|
|
ObDereferenceObject(pwinsta);
|
|
|
|
TRACE("NtUserSetLogonNotifyWindow");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
BOOL NtUserSetSystemCursor(
|
|
IN HCURSOR hcur,
|
|
IN DWORD id)
|
|
{
|
|
PCURSOR pcur;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHCURSOROPT(pcur, hcur);
|
|
|
|
retval = _SetSystemCursor(
|
|
pcur,
|
|
id);
|
|
|
|
TRACE("NtUserSetSystemCursor");
|
|
ENDRECV();
|
|
}
|
|
|
|
HCURSOR NtUserGetCursorInfo(
|
|
IN HCURSOR hcur,
|
|
IN int iFrame,
|
|
OUT LPDWORD pjifRate,
|
|
OUT LPINT pccur)
|
|
{
|
|
PCURSOR pcur;
|
|
|
|
BEGINRECV_SHARED(HCURSOR, NULL);
|
|
|
|
ValidateHCURSOROPT(pcur, hcur);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWriteUlong(pjifRate);
|
|
ProbeForWriteLong(pccur);
|
|
|
|
retval = (HCURSOR)_GetCursorInfo(
|
|
pcur,
|
|
iFrame,
|
|
pjifRate,
|
|
pccur);
|
|
retval = PtoH((PVOID)retval);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetCursorInfo");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSetCursorContents(
|
|
IN HCURSOR hCursor,
|
|
IN HCURSOR hCursorNew)
|
|
{
|
|
PCURSOR pCursor;
|
|
PCURSOR pCursorNew;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHCURSOR(pCursor, hCursor);
|
|
ValidateHCURSOR(pCursorNew, hCursorNew);
|
|
|
|
retval = _SetCursorContents(pCursor, pCursorNew);
|
|
|
|
TRACE("NtUserSetCursorContents");
|
|
ENDRECV();
|
|
}
|
|
|
|
HCURSOR NtUserFindExistingCursorIcon(
|
|
IN PUNICODE_STRING pstrModName,
|
|
IN PUNICODE_STRING pstrResName,
|
|
IN PCURSORFIND pcfSearch)
|
|
{
|
|
ATOM atomModName;
|
|
UNICODE_STRING strModName;
|
|
UNICODE_STRING strResName;
|
|
PCURSOR pcurSrc;
|
|
CURSORFIND cfSearch;
|
|
|
|
BEGINRECV_SHARED(HCURSOR, NULL);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
|
|
cfSearch = ProbeAndReadCursorFind(pcfSearch);
|
|
|
|
ValidateHCURSOROPT(pcurSrc, cfSearch.hcur);
|
|
|
|
strModName = ProbeAndReadUnicodeString(pstrModName);
|
|
#if defined(_X86_)
|
|
ProbeForRead(strModName.Buffer, strModName.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(strModName.Buffer, strModName.Length, sizeof(WCHAR));
|
|
#endif
|
|
|
|
strResName = ProbeAndReadUnicodeString(pstrResName);
|
|
ProbeForRead(strResName.Buffer, strResName.Length, sizeof(WCHAR));
|
|
|
|
if (atomModName = UserFindAtom(strModName.Buffer)) {
|
|
|
|
retval = (HCURSOR)_FindExistingCursorIcon(atomModName,
|
|
&strResName,
|
|
pcurSrc,
|
|
&cfSearch);
|
|
|
|
retval = (HCURSOR)PtoH((PCURSOR)retval);
|
|
|
|
} else {
|
|
|
|
retval = 0;
|
|
}
|
|
|
|
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserFindExistingCursorIcon");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSetCursorIconData(
|
|
IN HCURSOR hCursor,
|
|
IN PUNICODE_STRING pstrModName,
|
|
IN PUNICODE_STRING pstrResName,
|
|
IN PCURSORDATA pData,
|
|
IN DWORD cbData)
|
|
{
|
|
UNICODE_STRING strModName;
|
|
UNICODE_STRING strResName;
|
|
PCURSOR pCursor;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHCURSOR(pCursor, hCursor);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
|
|
strModName = ProbeAndReadUnicodeString(pstrModName);
|
|
strResName = ProbeAndReadUnicodeString(pstrResName);
|
|
|
|
#if defined(_X86_)
|
|
ProbeForRead(strResName.Buffer, strResName.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(strResName.Buffer, strResName.Length, sizeof(WCHAR));
|
|
#endif
|
|
ProbeForRead(strModName.Buffer, strModName.Length, sizeof(WCHAR));
|
|
ProbeForRead(pData, cbData, sizeof(DWORD));
|
|
|
|
retval = _SetCursorIconData(pCursor,
|
|
&strModName,
|
|
&strResName,
|
|
pData,
|
|
cbData);
|
|
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserSetCursorIconData");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserWOWCleanup(
|
|
IN HANDLE hInstance,
|
|
IN DWORD hTaskWow,
|
|
IN PNEMODULESEG SelList,
|
|
IN DWORD nSel)
|
|
{
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
/*
|
|
* The routine does all probing.
|
|
*/
|
|
_WOWCleanup(hInstance, hTaskWow, SelList, nSel);
|
|
retval = FALSE;
|
|
|
|
TRACE("NtUserWOWCleanup");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserGetMenuItemRect(
|
|
IN HWND hwnd,
|
|
IN HMENU hMenu,
|
|
IN UINT uItem,
|
|
OUT LPRECT lprcItem)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
PMENU pmenu;
|
|
TL tlpmenu;
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
|
|
ValidateHMENU(pmenu, hMenu);
|
|
|
|
ThreadLockAlwaysWithPti(ptiCurrent, pmenu, &tlpmenu);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
|
|
ProbeForWriteRect(lprcItem);
|
|
retval = xxxGetMenuItemRect(
|
|
pwnd,
|
|
pmenu,
|
|
uItem,
|
|
lprcItem);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERRORCLEANUP();
|
|
}
|
|
|
|
CLEANUPRECV();
|
|
|
|
ThreadUnlock(&tlpmenu);
|
|
|
|
TRACE("NtUserGetMenuItemRect");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
int NtUserMenuItemFromPoint(
|
|
IN HWND hwnd,
|
|
IN HMENU hMenu,
|
|
IN POINT ptScreen)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
PMENU pmenu;
|
|
TL tlpmenu;
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
|
|
ValidateHMENU(pmenu, hMenu);
|
|
|
|
ThreadLockAlwaysWithPti(ptiCurrent, pmenu, &tlpmenu);
|
|
|
|
retval = xxxMenuItemFromPoint(
|
|
pwnd,
|
|
pmenu,
|
|
ptScreen);
|
|
|
|
ThreadUnlock(&tlpmenu);
|
|
|
|
TRACE("NtUserMenuItemFromPoint");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
BOOL NtUserGetCaretPos(
|
|
OUT LPPOINT lpPoint)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_SHARED(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWritePoint(lpPoint);
|
|
|
|
retval = _GetCaretPos(
|
|
lpPoint);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetCaretPos");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserDefSetText(
|
|
IN HWND hwnd,
|
|
IN PLARGE_STRING pstrText OPTIONAL)
|
|
{
|
|
LARGE_STRING strText;
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND(DWORD, 0, hwnd);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
if (ARGUMENT_PRESENT(pstrText)) {
|
|
try {
|
|
strText = ProbeAndReadLargeString(pstrText);
|
|
#if defined(_X86_)
|
|
ProbeForRead(strText.Buffer, strText.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(strText.Buffer, strText.Length,
|
|
strText.bAnsi ? sizeof(BYTE) : sizeof(WORD));
|
|
#endif
|
|
pstrText = &strText;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
}
|
|
|
|
retval = DefSetText(
|
|
pwnd,
|
|
pstrText);
|
|
|
|
TRACE("NtUserDefSetText");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
NTSTATUS NtUserQueryInformationThread(
|
|
IN HANDLE hThread,
|
|
IN USERTHREADINFOCLASS ThreadInfoClass,
|
|
OUT PVOID ThreadInformation,
|
|
IN ULONG ThreadInformationLength,
|
|
IN OUT PULONG ReturnLength OPTIONAL)
|
|
{
|
|
BEGINRECV(NTSTATUS, STATUS_UNSUCCESSFUL);
|
|
/*
|
|
* note -- QueryInformationThread can call xxxSwitchDesktop, so it is not sharable
|
|
*/
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
if (ARGUMENT_PRESENT(ThreadInformation)) {
|
|
switch (ThreadInfoClass) {
|
|
case UserThreadShutdownInformation:
|
|
case UserThreadFlags:
|
|
case UserThreadWOWInformation:
|
|
case UserThreadHungStatus:
|
|
ProbeForWriteBoolean((PBOOLEAN)ThreadInformation);
|
|
break;
|
|
case UserThreadTaskName:
|
|
ProbeForWrite(ThreadInformation, ThreadInformationLength,
|
|
sizeof(WCHAR));
|
|
break;
|
|
}
|
|
}
|
|
if (ARGUMENT_PRESENT(ReturnLength))
|
|
ProbeForWriteUlong(ReturnLength);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = QueryInformationThread(hThread,
|
|
ThreadInfoClass, ThreadInformation,
|
|
ThreadInformationLength, ReturnLength);
|
|
|
|
TRACE("NtUserQueryInformationThread");
|
|
ENDRECV();
|
|
}
|
|
|
|
NTSTATUS NtUserSetInformationThread(
|
|
IN HANDLE hThread,
|
|
IN USERTHREADINFOCLASS ThreadInfoClass,
|
|
IN PVOID ThreadInformation,
|
|
IN ULONG ThreadInformationLength)
|
|
{
|
|
BEGINRECV(NTSTATUS, STATUS_UNSUCCESSFUL);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForRead(ThreadInformation, ThreadInformationLength,
|
|
sizeof(DWORD));
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = SetInformationThread(hThread,
|
|
ThreadInfoClass, ThreadInformation,
|
|
ThreadInformationLength);
|
|
|
|
TRACE("NtUserSetInformationThread");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserNotifyProcessCreate(
|
|
IN DWORD dwProcessId,
|
|
IN DWORD dwParentThreadId,
|
|
IN DWORD dwData,
|
|
IN DWORD dwFlags)
|
|
{
|
|
extern BOOL UserNotifyProcessCreate(DWORD idProcess, DWORD idParentThread,
|
|
DWORD dwData, DWORD dwFlags);
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
retval = UserNotifyProcessCreate(dwProcessId,
|
|
dwParentThreadId,
|
|
dwData,
|
|
dwFlags);
|
|
|
|
TRACE("NtUserNotifyProcessCreate");
|
|
ENDRECV();
|
|
}
|
|
|
|
NTSTATUS NtUserSoundSentry(
|
|
IN UINT uVideoMode)
|
|
{
|
|
BEGINRECV(NTSTATUS, STATUS_UNSUCCESSFUL);
|
|
|
|
retval = (_UserSoundSentryWorker(uVideoMode) ?
|
|
STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
|
|
|
|
TRACE("NtUserSoundSentry");
|
|
ENDRECV();
|
|
}
|
|
|
|
NTSTATUS NtUserTestForInteractiveUser(
|
|
IN PLUID pluidCaller)
|
|
{
|
|
extern NTSTATUS TestForInteractiveUser(PLUID);
|
|
|
|
BEGINRECV_SHARED(NTSTATUS, STATUS_UNSUCCESSFUL);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeAndReadUquad((PQUAD)pluidCaller);
|
|
retval = TestForInteractiveUser(pluidCaller);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserTestForInteractiveUser");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSetConsoleReserveKeys(
|
|
IN HWND hwnd,
|
|
IN DWORD fsReserveKeys)
|
|
{
|
|
BOOL _SetConsoleReserveKeys(PWND, DWORD);
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND(BOOL, FALSE, hwnd);
|
|
|
|
retval = _SetConsoleReserveKeys(pwnd, fsReserveKeys);
|
|
|
|
TRACE("NtUserSetConsoleReserveKeys");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
DWORD NtUserGetUserStartupInfoFlags(
|
|
VOID)
|
|
{
|
|
BEGINRECV_SHARED(DWORD, 0);
|
|
|
|
retval = PpiCurrent()->usi.dwFlags;
|
|
|
|
TRACE("NtUserGetUserStartupInfoFlags");
|
|
ENDRECV();
|
|
}
|
|
|
|
VOID NtUserSetUserStartupInfoFlags(
|
|
IN DWORD dwFlags)
|
|
{
|
|
BEGINRECV_VOID();
|
|
|
|
PpiCurrent()->usi.dwFlags = dwFlags;
|
|
|
|
TRACEVOID("NtUserSetUserStartupInfoFlags");
|
|
ENDRECV_VOID();
|
|
}
|
|
|
|
BOOL NtUserSetWindowFNID(
|
|
IN HWND hwnd,
|
|
IN WORD fnid)
|
|
{
|
|
BEGINRECV_HWND(BOOL, FALSE, hwnd);
|
|
|
|
/*
|
|
* Remember what window class this window belongs to. Can't use
|
|
* the real class because any app can call CallWindowProc()
|
|
* directly no matter what the class is!
|
|
*/
|
|
if ((GETFNID(pwnd) == 0) || (fnid == FNID_CLEANEDUP_BIT)) {
|
|
pwnd->fnid |= fnid;
|
|
retval = TRUE;
|
|
}
|
|
|
|
TRACE("NtUserSetWindowFNID");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
VOID NtUserAlterWindowStyle(
|
|
IN HWND hwnd,
|
|
IN DWORD mask,
|
|
IN DWORD flags)
|
|
{
|
|
BEGINRECV_HWND_VOID(hwnd);
|
|
|
|
pwnd->style = (pwnd->style & (~mask)) | (flags & mask);
|
|
|
|
TRACEVOID("NtUserAlterWindowStyle");
|
|
ENDRECV_VOID();
|
|
}
|
|
|
|
VOID NtUserSetThreadState(
|
|
IN DWORD dwFlags,
|
|
IN DWORD dwMask)
|
|
{
|
|
PTHREADINFO ptiCurrent;
|
|
DWORD dwOldFlags;
|
|
|
|
if (dwFlags & ~(QF_DIALOGACTIVE)) {
|
|
return;
|
|
}
|
|
|
|
BEGINRECV_VOID();
|
|
|
|
ptiCurrent = PtiCurrent();
|
|
dwOldFlags = ptiCurrent->pq->QF_flags;
|
|
ptiCurrent->pq->QF_flags ^= ((dwOldFlags ^ dwFlags) & dwMask);
|
|
|
|
TRACEVOID("NtUserSetThreadState");
|
|
ENDRECV_VOID();
|
|
}
|
|
|
|
DWORD NtUserGetThreadState(
|
|
IN USERTHREADSTATECLASS ThreadState)
|
|
{
|
|
PTHREADINFO ptiCurrent = PtiCurrentShared();
|
|
|
|
BEGINRECV_SHARED(DWORD, 0);
|
|
|
|
switch (ThreadState) {
|
|
case UserThreadStateFocusWindow:
|
|
retval = (DWORD)HW(ptiCurrent->pq->spwndFocus);
|
|
break;
|
|
case UserThreadStateActiveWindow:
|
|
retval = (DWORD)HW(ptiCurrent->pq->spwndActive);
|
|
break;
|
|
case UserThreadStateCaptureWindow:
|
|
retval = (DWORD)HW(ptiCurrent->pq->spwndCapture);
|
|
break;
|
|
#ifdef FE_IME
|
|
case UserThreadStateDefaultImeWindow:
|
|
retval = (DWORD)HW(ptiCurrent->spwndDefaultIme);
|
|
break;
|
|
case UserThreadStateDefaultInputContext:
|
|
retval = (DWORD)PtoH(ptiCurrent->spDefaultImc);
|
|
break;
|
|
#endif
|
|
case UserThreadStateInputState:
|
|
retval = (DWORD)_GetInputState();
|
|
break;
|
|
case UserThreadStateCursor:
|
|
retval = (DWORD)ptiCurrent->pq->hcurCurrent;
|
|
break;
|
|
case UserThreadStateChangeBits:
|
|
retval = ptiCurrent->pcti->fsChangeBits;
|
|
break;
|
|
case UserThreadStatePeekMessage:
|
|
/*
|
|
* Update the last read time so that hung app painting won't occur.
|
|
*/
|
|
SET_TIME_LAST_READ(ptiCurrent);
|
|
retval = (DWORD)FALSE;
|
|
break;
|
|
case UserThreadStateExtraInfo:
|
|
retval = ptiCurrent->pq->ExtraInfo;
|
|
break;
|
|
case UserThreadStateInSendMessage:
|
|
retval = ptiCurrent->psmsCurrent != NULL;
|
|
break;
|
|
case UserThreadStateMessageTime:
|
|
retval = ptiCurrent->timeLast;
|
|
break;
|
|
case UserThreadStateIsForeground:
|
|
retval = (ptiCurrent->pq == gpqForeground);
|
|
break;
|
|
default:
|
|
retval = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserGetListboxString(
|
|
IN HWND hwnd,
|
|
IN UINT msg,
|
|
IN DWORD wParam,
|
|
IN PLARGE_STRING pString,
|
|
IN DWORD xParam,
|
|
IN DWORD xpfn,
|
|
OUT PBOOL pbNotString)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
LARGE_STRING str;
|
|
DWORD dw;
|
|
BOOL bNotString;
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
|
|
/*
|
|
* Probe all arguments
|
|
*/
|
|
try {
|
|
str = ProbeAndReadLargeString((PLARGE_STRING)pString);
|
|
#if defined(_X86_)
|
|
ProbeForWrite((PVOID)str.Buffer, str.MaximumLength, sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite((PVOID)str.Buffer, str.MaximumLength,
|
|
str.bAnsi ? sizeof(BYTE) : sizeof(WORD));
|
|
#endif
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = CALLPROC(xpfn)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LONG)&str,
|
|
xParam);
|
|
|
|
/*
|
|
* If the control is ownerdraw and does not have the CBS/LBS_HASSTRINGS
|
|
* style, then a 32-bits of application data has been obtained,
|
|
* not a string. Indicate this by returning a length of -1.
|
|
* In the test below, it may be better to use:
|
|
* (pwnd->pcls->atomClassName == atomSysClass[LISTBOXCLASS])
|
|
* instead of (msg == LB_GETTEXT), and
|
|
* (pwnd->pcls->atomClassName == atomSysClass[COMBOBOXCLASS]) (??)
|
|
* instead of (msg == CB_GETLBTEXT)
|
|
*/
|
|
|
|
dw = pwnd->style;
|
|
try {
|
|
bNotString =
|
|
(
|
|
( (msg == LB_GETTEXT) &&
|
|
!(dw & LBS_HASSTRINGS) &&
|
|
(dw & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE))
|
|
) || (
|
|
(msg == CB_GETLBTEXT) &&
|
|
!(dw & CBS_HASSTRINGS) &&
|
|
(dw & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE))
|
|
)
|
|
);
|
|
ProbeAndWriteUlong(pbNotString, bNotString);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetListboxString");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
HWND NtUserCreateWindowEx(
|
|
IN DWORD dwExStyle,
|
|
IN PLARGE_STRING pstrClassName,
|
|
IN PLARGE_STRING pstrWindowName OPTIONAL,
|
|
IN DWORD dwStyle,
|
|
IN int x,
|
|
IN int y,
|
|
IN int nWidth,
|
|
IN int nHeight,
|
|
IN HWND hwndParent,
|
|
IN HMENU hmenu,
|
|
IN HANDLE hModule,
|
|
IN LPVOID pParam,
|
|
IN DWORD dwFlags,
|
|
IN LPDWORD pWOW OPTIONAL)
|
|
{
|
|
LARGE_STRING strClassName;
|
|
LARGE_STRING strWindowName;
|
|
PWND pwndParent;
|
|
PMENU pmenu;
|
|
TL tlpwndParent;
|
|
TL tlpmenu;
|
|
BOOL fLockMenu = FALSE;
|
|
PTHREADINFO ptiCurrent;
|
|
DWORD adwWOW[WND_CNT_WOWDWORDS];
|
|
|
|
BEGINRECV(HWND, NULL);
|
|
|
|
ValidateHWNDOPT(pwndParent, hwndParent);
|
|
|
|
/*
|
|
* Win3.1 only checks for WS_CHILD before treating pmenu as an id. This
|
|
* is a bug, because throughout the code, the real check is TestwndChild(),
|
|
* which checks (style & (WS_CHILD | WS_POPUP)) == WS_CHILD. This is
|
|
* because old style "iconic popup" is WS_CHILD | WS_POPUP. So... if on
|
|
* win3.1 an app used ws_iconicpopup, menu validation would not occur
|
|
* (could crash if hmenu != NULL). On Win32, check for the real thing -
|
|
* but allow NULL!
|
|
*/
|
|
ptiCurrent = PtiCurrent();
|
|
if (((dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) &&
|
|
(hmenu != NULL)) {
|
|
ValidateHMENU(pmenu, hmenu);
|
|
|
|
ThreadLockAlwaysWithPti(ptiCurrent, pmenu, &tlpmenu);
|
|
fLockMenu = TRUE;
|
|
|
|
} else {
|
|
pmenu = (PMENU)hmenu;
|
|
}
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
#if defined(_X86_)
|
|
if (ARGUMENT_PRESENT(pWOW)) {
|
|
ProbeForRead(pWOW, sizeof(adwWOW), sizeof(BYTE));
|
|
RtlCopyMemory(adwWOW, pWOW, sizeof(adwWOW));
|
|
pWOW = adwWOW;
|
|
}
|
|
if (HIWORD(pstrClassName)) {
|
|
strClassName = ProbeAndReadLargeString(pstrClassName);
|
|
ProbeForRead(pstrClassName->Buffer, pstrClassName->Length,
|
|
sizeof(BYTE));
|
|
pstrClassName = &strClassName;
|
|
}
|
|
if (ARGUMENT_PRESENT(pstrWindowName)) {
|
|
strWindowName = ProbeAndReadLargeString(pstrWindowName);
|
|
ProbeForRead(pstrWindowName->Buffer, pstrWindowName->Length,
|
|
sizeof(BYTE));
|
|
pstrWindowName = &strWindowName;
|
|
}
|
|
#else
|
|
if (ARGUMENT_PRESENT(pWOW)) {
|
|
ProbeForRead(pWOW, sizeof(adwWOW), sizeof(DWORD));
|
|
RtlCopyMemory(adwWOW, pWOW, sizeof(adwWOW));
|
|
pWOW = adwWOW;
|
|
}
|
|
if (HIWORD(pstrClassName)) {
|
|
strClassName = ProbeAndReadLargeString(pstrClassName);
|
|
ProbeForRead(pstrClassName->Buffer, pstrClassName->Length,
|
|
sizeof(WORD));
|
|
pstrClassName = &strClassName;
|
|
}
|
|
if (ARGUMENT_PRESENT(pstrWindowName)) {
|
|
strWindowName = ProbeAndReadLargeString(pstrWindowName);
|
|
ProbeForRead(pstrWindowName->Buffer, pstrWindowName->Length,
|
|
(pstrWindowName->bAnsi ? sizeof(BYTE) : sizeof(WORD)));
|
|
pstrWindowName = &strWindowName;
|
|
}
|
|
#endif
|
|
} except (StubExceptionHandler()) {
|
|
MSGERRORCLEANUP();
|
|
}
|
|
|
|
ThreadLockWithPti(ptiCurrent, pwndParent, &tlpwndParent);
|
|
|
|
retval = (HWND)xxxCreateWindowExWOW(
|
|
dwExStyle,
|
|
pstrClassName,
|
|
pstrWindowName,
|
|
dwStyle,
|
|
x,
|
|
y,
|
|
nWidth,
|
|
nHeight,
|
|
pwndParent,
|
|
pmenu,
|
|
hModule,
|
|
pParam,
|
|
dwFlags,
|
|
pWOW);
|
|
retval = PtoH((PVOID)retval);
|
|
|
|
ThreadUnlock(&tlpwndParent);
|
|
|
|
CLEANUPRECV();
|
|
if (fLockMenu)
|
|
ThreadUnlock(&tlpmenu);
|
|
|
|
TRACE("NtUserCreateWindowEx");
|
|
ENDRECV();
|
|
}
|
|
|
|
NTSTATUS NtUserBuildHwndList(
|
|
IN HDESK hdesk,
|
|
IN HWND hwndNext,
|
|
IN BOOL fEnumChildren,
|
|
IN DWORD idThread,
|
|
IN UINT cHwndMax,
|
|
OUT HWND *phwndFirst,
|
|
OUT PUINT pcHwndNeeded)
|
|
{
|
|
PWND pwndNext;
|
|
PDESKTOP pdesk;
|
|
PBWL pbwl;
|
|
PTHREADINFO pti;
|
|
UINT cHwndNeeded;
|
|
UINT wFlags = BWL_ENUMLIST;
|
|
|
|
BEGINRECV(NTSTATUS, STATUS_INVALID_HANDLE);
|
|
|
|
/*
|
|
* Validate prior to referencing the desktop
|
|
*/
|
|
ValidateHWNDOPT(pwndNext, hwndNext);
|
|
|
|
if (idThread) {
|
|
pti = PtiFromThreadId(idThread);
|
|
if (pti == NULL || pti->rpdesk == NULL)
|
|
MSGERROR();
|
|
pwndNext = pti->rpdesk->pDeskInfo->spwnd->spwndChild;
|
|
} else {
|
|
pti = NULL;
|
|
}
|
|
|
|
if (hdesk) {
|
|
retval = ValidateHdesk(hdesk, DESKTOP_READOBJECTS, &pdesk);
|
|
if (!NT_SUCCESS(retval))
|
|
MSGERROR();
|
|
pwndNext = pdesk->pDeskInfo->spwnd->spwndChild;
|
|
} else {
|
|
pdesk = NULL;
|
|
}
|
|
|
|
if (pwndNext == NULL) {
|
|
pwndNext = _GetDesktopWindow()->spwndChild;
|
|
} else {
|
|
if (fEnumChildren) {
|
|
wFlags |= BWL_ENUMCHILDREN;
|
|
pwndNext = pwndNext->spwndChild;
|
|
}
|
|
}
|
|
|
|
if ((pbwl = BuildHwndList(pwndNext, wFlags, pti)) == NULL) {
|
|
retval = STATUS_NO_MEMORY;
|
|
MSGERRORCLEANUP();
|
|
}
|
|
|
|
cHwndNeeded = (pbwl->phwndNext - pbwl->rghwnd) + 1;
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWrite(phwndFirst, cHwndMax * sizeof(HWND), sizeof(DWORD));
|
|
ProbeForWriteUlong(pcHwndNeeded);
|
|
|
|
/*
|
|
* If we have enough space, copy out list of hwnds to user mode buffer.
|
|
*/
|
|
if (cHwndNeeded <= cHwndMax) {
|
|
RtlCopyMemory(phwndFirst, pbwl->rghwnd, cHwndNeeded * sizeof(HWND));
|
|
retval = STATUS_SUCCESS;
|
|
} else {
|
|
retval = STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
*pcHwndNeeded = cHwndNeeded;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERRORCLEANUP();
|
|
}
|
|
|
|
CLEANUPRECV();
|
|
|
|
if (pbwl != NULL) {
|
|
FreeHwndList(pbwl);
|
|
}
|
|
|
|
if (pdesk != NULL)
|
|
ObDereferenceObject(pdesk);
|
|
|
|
TRACE("NtUserBuildHwndList");
|
|
ENDRECV();
|
|
}
|
|
|
|
NTSTATUS NtUserBuildPropList(
|
|
IN HWND hwnd,
|
|
IN UINT cPropMax,
|
|
OUT PPROPSET pPropSet,
|
|
OUT PUINT pcPropNeeded)
|
|
{
|
|
BEGINRECV_HWNDLOCK(NTSTATUS, STATUS_INVALID_HANDLE, hwnd);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWrite(pPropSet, cPropMax * sizeof(*pPropSet), sizeof(DWORD));
|
|
ProbeForWriteUlong(pcPropNeeded);
|
|
|
|
retval = _BuildPropList(
|
|
pwnd,
|
|
pPropSet,
|
|
cPropMax,
|
|
pcPropNeeded);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserBuildPropList");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
NTSTATUS NtUserBuildNameList(
|
|
IN HWINSTA hwinsta,
|
|
IN UINT cbNameList,
|
|
OUT PNAMELIST pNameList,
|
|
OUT PUINT pcbNeeded)
|
|
{
|
|
PWINDOWSTATION pwinsta = NULL;
|
|
|
|
BEGINRECV_SHARED(NTSTATUS, STATUS_INVALID_HANDLE);
|
|
|
|
if (hwinsta != NULL) {
|
|
retval = ValidateHwinsta(hwinsta, WINSTA_ENUMDESKTOPS, &pwinsta);
|
|
} else {
|
|
retval = STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWriteUlong(pcbNeeded);
|
|
ProbeForWrite(pNameList, cbNameList, sizeof(DWORD));
|
|
|
|
if (!NT_SUCCESS(retval)) {
|
|
*pNameList->awchNames = 0;
|
|
pNameList->cb = 1;
|
|
} else {
|
|
retval = _BuildNameList(
|
|
pwinsta,
|
|
pNameList,
|
|
cbNameList,
|
|
pcbNeeded);
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
MSGERRORCLEANUP();
|
|
}
|
|
|
|
CLEANUPRECV();
|
|
|
|
if (pwinsta != NULL)
|
|
ObDereferenceObject(pwinsta);
|
|
|
|
TRACE("NtUserBuildNameList");
|
|
ENDRECV();
|
|
}
|
|
|
|
HKL NtUserActivateKeyboardLayout(
|
|
IN HKL hkl,
|
|
IN UINT Flags)
|
|
{
|
|
BEGINRECV(HKL, NULL);
|
|
|
|
retval = (HKL)xxxActivateKeyboardLayout(
|
|
_GetProcessWindowStation(NULL),
|
|
hkl,
|
|
Flags);
|
|
|
|
TRACE("NtUserActivateKeyboardLayout");
|
|
ENDRECV();
|
|
}
|
|
|
|
HKL NtUserLoadKeyboardLayoutEx(
|
|
IN HANDLE hFile,
|
|
IN DWORD offTable,
|
|
IN HKL hkl,
|
|
IN PUNICODE_STRING pstrKLID,
|
|
IN UINT KbdInputLocale,
|
|
IN UINT Flags)
|
|
{
|
|
UNICODE_STRING strKLID;
|
|
PWINDOWSTATION pwinsta;
|
|
WCHAR awchKF[sizeof(((PKL)0)->spkf->awchKF)];
|
|
UINT chMax;
|
|
|
|
BEGINRECV(HKL, NULL);
|
|
|
|
pwinsta = _GetProcessWindowStation(NULL);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
strKLID = ProbeAndReadUnicodeString(pstrKLID);
|
|
#if defined(_X86_)
|
|
ProbeForRead(strKLID.Buffer, strKLID.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(strKLID.Buffer, strKLID.Length, sizeof(WCHAR));
|
|
#endif
|
|
chMax = min(sizeof(awchKF) - sizeof(WCHAR), strKLID.Length) / sizeof(WCHAR);
|
|
wcsncpy(awchKF, strKLID.Buffer, chMax);
|
|
awchKF[chMax] = 0;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = xxxLoadKeyboardLayoutEx(
|
|
pwinsta,
|
|
hFile,
|
|
hkl,
|
|
offTable,
|
|
awchKF,
|
|
KbdInputLocale,
|
|
Flags);
|
|
|
|
TRACE("NtUserLoadKeyboardLayoutEx");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserUnloadKeyboardLayout(
|
|
IN HKL hkl)
|
|
{
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
retval = xxxUnloadKeyboardLayout(
|
|
_GetProcessWindowStation(NULL),
|
|
hkl);
|
|
|
|
TRACE("NtUserUnloadKeyboardLayout");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSetSystemMenu(
|
|
IN HWND hwnd,
|
|
IN HMENU hmenu)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
PMENU pmenu;
|
|
TL tlpmenu;
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
|
|
ValidateHMENU(pmenu, hmenu);
|
|
|
|
ThreadLockAlwaysWithPti(ptiCurrent, pmenu, &tlpmenu);
|
|
|
|
retval = xxxSetSystemMenu(pwnd, pmenu);
|
|
|
|
ThreadUnlock(&tlpmenu);
|
|
|
|
TRACE("NtUserSetSystemMenu");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
BOOL NtUserDragDetect(
|
|
IN HWND hwnd,
|
|
IN POINT pt)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
|
|
retval = xxxDragDetect(pwnd, pt);
|
|
|
|
TRACE("NtUserDragDetect");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
UINT NtUserSetSystemTimer(
|
|
IN HWND hwnd,
|
|
IN UINT nIDEvent,
|
|
IN DWORD dwElapse,
|
|
IN WNDPROC pTimerFunc)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND(DWORD, 0, hwnd);
|
|
|
|
retval = _SetSystemTimer(pwnd,
|
|
nIDEvent,
|
|
dwElapse,
|
|
(WNDPROC_PWND)pTimerFunc);
|
|
|
|
TRACE("NtUserSetSystemTimer");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
BOOL NtUserQuerySendMessage(
|
|
PMSG pmsg OPTIONAL)
|
|
{
|
|
BEGINRECV_SHARED(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
if (ARGUMENT_PRESENT(pmsg))
|
|
ProbeForWriteMessage(pmsg);
|
|
|
|
retval = _QuerySendMessage(pmsg);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserQuerySendMessage");
|
|
ENDRECV();
|
|
}
|
|
|
|
VOID NtUserkeybd_event(
|
|
IN BYTE bVk,
|
|
IN BYTE bScan,
|
|
IN DWORD dwFlags,
|
|
IN DWORD dwExtraInfo)
|
|
{
|
|
BEGINRECV_VOID();
|
|
|
|
InternalKeyEvent(
|
|
bVk,
|
|
bScan,
|
|
dwFlags,
|
|
dwExtraInfo);
|
|
|
|
TRACEVOID("NtUserkeybd_event");
|
|
ENDRECV_VOID();
|
|
}
|
|
|
|
VOID NtUsermouse_event(
|
|
IN DWORD dwFlags,
|
|
IN DWORD dx,
|
|
IN DWORD dy,
|
|
IN DWORD cButtons,
|
|
IN DWORD dwExtraInfo)
|
|
{
|
|
BEGINRECV_VOID();
|
|
|
|
_MouseEvent(
|
|
dwFlags,
|
|
dx,
|
|
dy,
|
|
cButtons,
|
|
dwExtraInfo);
|
|
|
|
TRACEVOID("NtUsermouse_event");
|
|
ENDRECV_VOID();
|
|
}
|
|
|
|
BOOL NtUserImpersonateDdeClientWindow(
|
|
IN HWND hwndClient,
|
|
IN HWND hwndServer)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
PWND pwndServer;
|
|
|
|
BEGINRECV_HWND(BOOL, FALSE, hwndClient);
|
|
|
|
ValidateHWND(pwndServer, hwndServer);
|
|
if (GETPTI(pwndServer) != PtiCurrent()) {
|
|
RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, "");
|
|
MSGERROR();
|
|
}
|
|
|
|
if (GETPWNDPPI(pwnd) == GETPWNDPPI(pwndServer)) {
|
|
retval = TRUE; // impersonating self is a NOOP
|
|
} else {
|
|
retval = _ImpersonateDdeClientWindow(pwnd, pwndServer);
|
|
}
|
|
|
|
TRACE("NtUserImpersonateDdeClientWindow");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
DWORD NtUserGetCPD(
|
|
IN HWND hwnd,
|
|
IN DWORD options,
|
|
IN DWORD dwData)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND(DWORD, 0, hwnd);
|
|
|
|
if (!(options & (CPD_WND | CPD_DIALOG | CPD_WNDTOCLS))) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = GetCPD(pwnd, options, dwData);
|
|
|
|
TRACE("NtUserGetCPD");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
int NtUserCopyAcceleratorTable(
|
|
IN HACCEL hAccelSrc,
|
|
IN OUT LPACCEL lpAccelDst OPTIONAL,
|
|
IN int cAccelEntries)
|
|
{
|
|
LPACCELTABLE pat;
|
|
|
|
BEGINRECV(int, 0);
|
|
|
|
ValidateHACCEL(pat, hAccelSrc);
|
|
|
|
if (lpAccelDst == NULL) {
|
|
retval = _CopyAcceleratorTable(pat, NULL, 0);
|
|
} else {
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
#if defined(_X86_)
|
|
ProbeForWrite(lpAccelDst, cAccelEntries * sizeof(*lpAccelDst),
|
|
sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite(lpAccelDst, cAccelEntries * sizeof(*lpAccelDst),
|
|
sizeof(DWORD));
|
|
#endif
|
|
|
|
retval = _CopyAcceleratorTable(
|
|
pat,
|
|
lpAccelDst,
|
|
cAccelEntries);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
}
|
|
|
|
TRACE("NtUserCopyAcceleratorTable");
|
|
ENDRECV();
|
|
}
|
|
|
|
HWND NtUserFindWindowEx(
|
|
IN HWND hwndParent,
|
|
IN HWND hwndChild,
|
|
IN PUNICODE_STRING pstrClassName,
|
|
IN PUNICODE_STRING pstrWindowName)
|
|
{
|
|
UNICODE_STRING strClassName;
|
|
UNICODE_STRING strWindowName;
|
|
PWND pwndParent, pwndChild;
|
|
TL tlpwndParent, tlpwndChild;
|
|
PTHREADINFO ptiCurrent;
|
|
|
|
BEGINRECV(HWND, NULL);
|
|
|
|
ValidateHWNDOPT(pwndParent, hwndParent);
|
|
ValidateHWNDOPT(pwndChild, hwndChild);
|
|
|
|
ptiCurrent = PtiCurrent();
|
|
ThreadLockWithPti(ptiCurrent, pwndParent, &tlpwndParent);
|
|
ThreadLockWithPti(ptiCurrent, pwndChild, &tlpwndChild);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
strClassName = ProbeAndReadUnicodeString(pstrClassName);
|
|
strWindowName = ProbeAndReadUnicodeString(pstrWindowName);
|
|
#if defined(_X86_)
|
|
ProbeForRead(strClassName.Buffer, strClassName.Length, sizeof(BYTE));
|
|
ProbeForRead(strWindowName.Buffer, strWindowName.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(strClassName.Buffer, strClassName.Length, sizeof(WCHAR));
|
|
ProbeForRead(strWindowName.Buffer, strWindowName.Length, sizeof(WCHAR));
|
|
#endif
|
|
|
|
retval = (HWND)_FindWindowEx(
|
|
pwndParent,
|
|
pwndChild,
|
|
strClassName.Buffer,
|
|
strWindowName.Buffer,
|
|
FW_BOTH);
|
|
retval = PtoH((PVOID)retval);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERRORCLEANUP();
|
|
}
|
|
|
|
CLEANUPRECV();
|
|
|
|
ThreadUnlock(&tlpwndChild);
|
|
ThreadUnlock(&tlpwndParent);
|
|
|
|
TRACE("NtUserFindWindowEx");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserGetClassInfo(
|
|
IN HINSTANCE hInstance OPTIONAL,
|
|
IN PUNICODE_STRING pstrClassName,
|
|
OUT LPWNDCLASSEXW lpWndClass,
|
|
OUT LPWSTR *ppszMenuName,
|
|
IN BOOL bAnsi)
|
|
{
|
|
UNICODE_STRING strClassName;
|
|
|
|
BEGINRECV_SHARED(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
strClassName = ProbeAndReadUnicodeString(pstrClassName);
|
|
|
|
/*
|
|
* The class name may either be a string or an atom. Only
|
|
* probe strings.
|
|
*/
|
|
#if defined(_X86_)
|
|
if (HIWORD(strClassName.Buffer))
|
|
ProbeForRead(strClassName.Buffer, strClassName.Length,
|
|
sizeof(BYTE));
|
|
ProbeForWrite(lpWndClass, sizeof(*lpWndClass), sizeof(BYTE));
|
|
#else
|
|
if (HIWORD(strClassName.Buffer))
|
|
ProbeForRead(strClassName.Buffer, strClassName.Length,
|
|
sizeof(WCHAR));
|
|
ProbeForWrite(lpWndClass, sizeof(*lpWndClass), sizeof(DWORD));
|
|
#endif
|
|
ProbeForWriteUlong((PULONG)ppszMenuName);
|
|
|
|
retval = _GetClassInfoEx(
|
|
hInstance,
|
|
(LPTSTR)strClassName.Buffer,
|
|
lpWndClass,
|
|
ppszMenuName,
|
|
bAnsi);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetClassInfo");
|
|
ENDRECV();
|
|
}
|
|
|
|
int NtUserGetClassName(
|
|
IN HWND hwnd,
|
|
IN OUT PUNICODE_STRING pstrClassName)
|
|
{
|
|
UNICODE_STRING strClassName;
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND_SHARED(DWORD, 0, hwnd);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
strClassName = ProbeAndReadUnicodeString(pstrClassName);
|
|
#if defined(_X86_)
|
|
ProbeForWrite(strClassName.Buffer, strClassName.MaximumLength,
|
|
sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite(strClassName.Buffer, strClassName.MaximumLength,
|
|
sizeof(WCHAR));
|
|
#endif
|
|
|
|
retval = GetAtomNameW(
|
|
pwnd->pcls->atomClassName,
|
|
strClassName.Buffer,
|
|
strClassName.MaximumLength / sizeof(WCHAR));
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetClassName");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
int NtUserGetClipboardFormatName(
|
|
IN UINT format,
|
|
OUT LPWSTR lpszFormatName,
|
|
IN UINT chMax)
|
|
{
|
|
BEGINRECV_SHARED(int, 0);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
#if defined(_X86_)
|
|
ProbeForWrite(lpszFormatName, chMax * sizeof(WCHAR), sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite(lpszFormatName, chMax * sizeof(WCHAR), sizeof(WCHAR));
|
|
#endif
|
|
|
|
retval = _GetClipboardFormatName(
|
|
format,
|
|
lpszFormatName,
|
|
chMax);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetClipboardFormatName");
|
|
ENDRECV();
|
|
}
|
|
|
|
int NtUserGetKeyNameText(
|
|
IN LONG lParam,
|
|
OUT LPWSTR lpszKeyName,
|
|
IN UINT chMax)
|
|
{
|
|
BEGINRECV_SHARED(int, 0);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
#if defined(_X86_)
|
|
ProbeForWrite(lpszKeyName, chMax * sizeof(WCHAR), sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite(lpszKeyName, chMax * sizeof(WCHAR), sizeof(WCHAR));
|
|
#endif
|
|
|
|
retval = _GetKeyNameText(
|
|
lParam,
|
|
lpszKeyName,
|
|
chMax);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetKeyNameText");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserGetKeyboardLayoutName(
|
|
IN OUT PUNICODE_STRING pstrKLID)
|
|
{
|
|
UNICODE_STRING strKLID;
|
|
|
|
BEGINRECV_SHARED(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
strKLID = ProbeAndReadUnicodeString(pstrKLID);
|
|
#if defined(_X86_)
|
|
ProbeForWrite(strKLID.Buffer, strKLID.MaximumLength, sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite(strKLID.Buffer, strKLID.MaximumLength, sizeof(WCHAR));
|
|
#endif
|
|
|
|
retval = _GetKeyboardLayoutName(&strKLID);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetKeyboardLayoutName");
|
|
ENDRECV();
|
|
}
|
|
|
|
UINT NtUserGetKeyboardLayoutList(
|
|
IN UINT nItems,
|
|
OUT HKL *lpBuff)
|
|
{
|
|
PWINDOWSTATION pwinsta;
|
|
|
|
BEGINRECV_SHARED(UINT, 0);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
#if defined(_X86_)
|
|
ProbeForWrite(lpBuff, nItems * sizeof(*lpBuff), sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite(lpBuff, nItems * sizeof(*lpBuff), sizeof(DWORD));
|
|
#endif
|
|
pwinsta = _GetProcessWindowStation(NULL);
|
|
|
|
retval = (DWORD)_GetKeyboardLayoutList(pwinsta, nItems, lpBuff);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetKeyboardLayoutList");
|
|
ENDRECV();
|
|
}
|
|
|
|
NTSTATUS NtUserGetStats(
|
|
IN HANDLE hProcess,
|
|
IN int iPidType,
|
|
OUT PVOID pResults,
|
|
IN UINT cjResultSize
|
|
)
|
|
{
|
|
BEGINRECV(NTSTATUS, STATUS_UNSUCCESSFUL);
|
|
|
|
/*
|
|
* Probing is done in HMGetStats
|
|
*/
|
|
retval = HMGetStats(hProcess, iPidType, pResults, cjResultSize);
|
|
|
|
TRACE("NtUserGetStats");
|
|
ENDRECV();
|
|
}
|
|
|
|
UINT NtUserMapVirtualKeyEx(
|
|
IN UINT uCode,
|
|
IN UINT uMapType,
|
|
IN DWORD dwHKLorPKL,
|
|
IN BOOL bHKL)
|
|
{
|
|
PKL pkl;
|
|
|
|
BEGINRECV_SHARED(UINT, 0);
|
|
|
|
/*
|
|
* See if we need to convert an HKL to a PKL. MapVirtualKey passes a PKL and
|
|
* MapVirtualKeyEx passes an HKL. The conversion must be done in the kernel.
|
|
*/
|
|
if (bHKL) {
|
|
pkl = HKLtoPKL((HKL)dwHKLorPKL);
|
|
} else {
|
|
pkl = PtiCurrentShared()->spklActive;
|
|
}
|
|
|
|
if (pkl == NULL) {
|
|
retval = 0;
|
|
} else {
|
|
retval = InternalMapVirtualKeyEx(uCode, uMapType, pkl->spkf->pKbdTbl);
|
|
}
|
|
|
|
TRACE("NtUserMapVirtualKeyEx");
|
|
ENDRECV();
|
|
}
|
|
|
|
ATOM NtUserRegisterClassExWOW(
|
|
IN WNDCLASSEX *lpWndClass,
|
|
IN PUNICODE_STRING pstrClassName,
|
|
IN PCLSMENUNAME pcmn,
|
|
IN PROC lpfnWorker,
|
|
IN WORD fnid,
|
|
IN DWORD dwFlags,
|
|
IN LPDWORD pdwWOWstuff OPTIONAL)
|
|
{
|
|
#if defined(_X86_)
|
|
#define DATAALIGN sizeof(BYTE)
|
|
#define CHARALIGN sizeof(BYTE)
|
|
#else
|
|
#define DATAALIGN sizeof(DWORD)
|
|
#define CHARALIGN sizeof(WCHAR)
|
|
#endif
|
|
|
|
UNICODE_STRING strClassName;
|
|
UNICODE_STRING strMenuName;
|
|
WNDCLASSEX WndClass;
|
|
DWORD adwWOW[sizeof(((PCLS)0)->adwWOW) / sizeof(DWORD)];
|
|
CLSMENUNAME cmn;
|
|
|
|
BEGINRECV(ATOM, 0);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
strClassName = ProbeAndReadUnicodeString(pstrClassName);
|
|
ProbeForRead(pcmn, sizeof(*pcmn), sizeof(DWORD));
|
|
RtlCopyMemory(&cmn, pcmn, sizeof(cmn));
|
|
strMenuName = ProbeAndReadUnicodeString(pcmn->pusMenuName);
|
|
ProbeForRead(lpWndClass, sizeof(*lpWndClass), DATAALIGN);
|
|
ProbeForRead(strClassName.Buffer, strClassName.Length, CHARALIGN);
|
|
ProbeForRead(strMenuName.Buffer, strMenuName.Length, CHARALIGN);
|
|
if (ARGUMENT_PRESENT(pdwWOWstuff)) {
|
|
ProbeForRead(pdwWOWstuff, sizeof(adwWOW), sizeof(BYTE));
|
|
RtlCopyMemory(adwWOW, pdwWOWstuff, sizeof(adwWOW));
|
|
pdwWOWstuff = adwWOW;
|
|
}
|
|
WndClass = *lpWndClass;
|
|
WndClass.lpszClassName = strClassName.Buffer;
|
|
WndClass.lpszMenuName = strMenuName.Buffer;
|
|
} except (StubExceptionHandler()) {
|
|
RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, "RegisterClass: Invalid Parameter");
|
|
MSGERROR();
|
|
}
|
|
|
|
|
|
retval = _RegisterClassEx(
|
|
&WndClass,
|
|
lpfnWorker,
|
|
&cmn,
|
|
fnid,
|
|
dwFlags,
|
|
pdwWOWstuff);
|
|
|
|
TRACE("NtUserRegisterClassExWOW");
|
|
ENDRECV();
|
|
|
|
#undef DATAALIGN
|
|
#undef CHARALIGN
|
|
|
|
}
|
|
|
|
UINT NtUserRegisterClipboardFormat(
|
|
IN PUNICODE_STRING pstrFormat)
|
|
{
|
|
UNICODE_STRING strFormat;
|
|
|
|
BEGINRECV(UINT, 0);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
strFormat = ProbeAndReadUnicodeString(pstrFormat);
|
|
if (strFormat.Length == 0) {
|
|
MSGERROR();
|
|
}
|
|
#if defined(_X86_)
|
|
ProbeForRead(strFormat.Buffer, strFormat.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(strFormat.Buffer, strFormat.Length, sizeof(WCHAR));
|
|
#endif
|
|
|
|
retval = _RegisterClipboardFormat(strFormat.Buffer);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserRegisterClipboardFormat");
|
|
ENDRECV();
|
|
}
|
|
|
|
UINT NtUserRegisterWindowMessage(
|
|
IN PUNICODE_STRING pstrMessage)
|
|
{
|
|
UNICODE_STRING strMessage;
|
|
|
|
BEGINRECV(UINT, 0);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
strMessage = ProbeAndReadUnicodeString(pstrMessage);
|
|
if (strMessage.Length == 0) {
|
|
MSGERROR();
|
|
}
|
|
#if defined(_X86_)
|
|
ProbeForRead(strMessage.Buffer, strMessage.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(strMessage.Buffer, strMessage.Length, sizeof(WCHAR));
|
|
#endif
|
|
|
|
retval = _RegisterWindowMessage(
|
|
(LPTSTR)strMessage.Buffer);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserRegisterWindowMessage");
|
|
ENDRECV();
|
|
}
|
|
|
|
HANDLE NtUserRemoveProp(
|
|
IN HWND hwnd,
|
|
IN DWORD dwProp)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND(HANDLE, NULL, hwnd);
|
|
|
|
retval = InternalRemoveProp(pwnd, (LPWSTR)LOWORD(dwProp), FALSE);
|
|
|
|
TRACE("NtUserRemoveProp");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
BOOL NtUserSetProp(
|
|
IN HWND hwnd,
|
|
IN DWORD dwProp,
|
|
IN HANDLE hData)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window handle translation. This
|
|
// operation is performed in the User server API dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWND(DWORD, 0, hwnd);
|
|
|
|
retval = InternalSetProp(
|
|
pwnd,
|
|
(LPTSTR)LOWORD(dwProp),
|
|
hData,
|
|
HIWORD(dwProp) ? PROPF_STRING : 0);
|
|
|
|
TRACE("NtUserSetProp");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
BOOL NtUserUnregisterClass(
|
|
IN PUNICODE_STRING pstrClassName,
|
|
IN HINSTANCE hInstance,
|
|
OUT PCLSMENUNAME pcmn)
|
|
{
|
|
UNICODE_STRING strClassName;
|
|
CLSMENUNAME cmn;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
strClassName = ProbeAndReadUnicodeString(pstrClassName);
|
|
if (HIWORD(strClassName.Buffer)) {
|
|
if (strClassName.Length == 0) {
|
|
MSGERROR();
|
|
}
|
|
#if defined(_X86_)
|
|
ProbeForRead(strClassName.Buffer, strClassName.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(strClassName.Buffer, strClassName.Length, sizeof(WCHAR));
|
|
#endif
|
|
}
|
|
|
|
retval = _UnregisterClass(
|
|
strClassName.Buffer,
|
|
hInstance,
|
|
&cmn);
|
|
|
|
ProbeAndWriteStructure(pcmn, cmn, CLSMENUNAME);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserUnregisterClass");
|
|
ENDRECV();
|
|
}
|
|
|
|
SHORT NtUserVkKeyScanEx(
|
|
IN WCHAR cChar,
|
|
IN DWORD dwHKLorPKL,
|
|
IN BOOL bHKL)
|
|
{
|
|
PKL pkl;
|
|
|
|
BEGINRECV_SHARED(SHORT, -1);
|
|
|
|
/*
|
|
* See if we need to convert an HKL to a PKL. VkKeyScan passes a PKL and
|
|
* VkKeyScanEx passes an HKL. The conversion must be done on the server side.
|
|
*/
|
|
if (bHKL) {
|
|
pkl = HKLtoPKL((HKL)dwHKLorPKL);
|
|
} else {
|
|
pkl = PtiCurrentShared()->spklActive;
|
|
}
|
|
|
|
if (pkl == NULL) {
|
|
retval = (SHORT)-1;
|
|
} else {
|
|
retval = InternalVkKeyScanEx(cChar, pkl->spkf->pKbdTbl);
|
|
}
|
|
|
|
TRACE("NtUserVkKeyScanEx");
|
|
ENDRECV();
|
|
}
|
|
|
|
NTSTATUS NtUserEnumDisplayDevices(
|
|
PVOID Unused,
|
|
DWORD iDevNum,
|
|
LPDISPLAY_DEVICEW lpDisplayDevice)
|
|
{
|
|
WCHAR linkName[32];
|
|
UNICODE_STRING devString;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
NTSTATUS Status;
|
|
HANDLE handle;
|
|
|
|
BEGINRECV(NTSTATUS, STATUS_UNSUCCESSFUL);
|
|
|
|
retval = STATUS_UNSUCCESSFUL;
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
|
|
ProbeForWrite(lpDisplayDevice, sizeof(DISPLAY_DEVICE), sizeof(DWORD));
|
|
|
|
RtlZeroMemory(&(lpDisplayDevice->DeviceString[0]), 256);
|
|
|
|
/*
|
|
* Open the symbolic links to see if it exists.
|
|
*/
|
|
|
|
if (iDevNum > 0 && iDevNum < cphysDevInfo) {
|
|
|
|
wsprintf(&(lpDisplayDevice->DeviceName[0]),
|
|
L"\\\\.\\DISPLAY%d",
|
|
iDevNum);
|
|
|
|
wsprintf(linkName,
|
|
L"\\DosDevices\\DISPLAY%d",
|
|
iDevNum);
|
|
|
|
RtlInitUnicodeString(&devString,
|
|
linkName);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&devString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
Status = ZwOpenSymbolicLinkObject(&handle,
|
|
GENERIC_READ,
|
|
&ObjectAttributes);
|
|
|
|
/*
|
|
* If the name exists, then increment the string and go to the next
|
|
* name.
|
|
* If the link does not exist, assume we are at the end and just
|
|
* return.
|
|
*/
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
ZwClose(handle);
|
|
|
|
lpDisplayDevice->StateFlags = gphysDevInfo[iDevNum].stateFlags;
|
|
|
|
retval = STATUS_SUCCESS;
|
|
|
|
} else {
|
|
|
|
RtlZeroMemory(&(lpDisplayDevice->DeviceName[0]), 64);
|
|
}
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserEnumDisplayDevices");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserCallMsgFilter(
|
|
IN LPMSG lpMsg,
|
|
IN int nCode)
|
|
{
|
|
MSG msg;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWriteMessage(lpMsg);
|
|
msg = *lpMsg;
|
|
|
|
retval = _CallMsgFilter(
|
|
&msg,
|
|
nCode);
|
|
*lpMsg = msg;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserCallMsgFilter");
|
|
ENDRECV();
|
|
}
|
|
|
|
int NtUserDrawMenuBarTemp(
|
|
IN HWND hwnd,
|
|
IN HDC hdc,
|
|
IN LPRECT lprc,
|
|
IN HMENU hMenu,
|
|
IN HFONT hFont)
|
|
{
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
PMENU pMenu;
|
|
TL tlpMenu;
|
|
RECT rc;
|
|
|
|
|
|
BEGINRECV_HWNDLOCK(int, 0, hwnd);
|
|
|
|
/*
|
|
* Probe and capture arguments.
|
|
*/
|
|
try {
|
|
rc = ProbeAndReadRect(lprc);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
ValidateHMENU(pMenu, hMenu);
|
|
|
|
ThreadLockAlwaysWithPti(ptiCurrent, pMenu, &tlpMenu);
|
|
|
|
retval = xxxDrawMenuBarTemp(
|
|
pwnd,
|
|
hdc,
|
|
&rc,
|
|
pMenu,
|
|
hFont);
|
|
|
|
ThreadUnlock(&tlpMenu);
|
|
|
|
TRACE("NtUserDrawMenuBarTemp");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
BOOL NtUserDrawCaptionTemp(
|
|
IN HWND hwnd,
|
|
IN HDC hdc,
|
|
IN LPRECT lprc,
|
|
IN HFONT hFont,
|
|
IN HICON hIcon,
|
|
IN PUNICODE_STRING pstrText,
|
|
IN UINT flags)
|
|
{
|
|
PCURSOR pcur;
|
|
TL tlpcur;
|
|
RECT rc;
|
|
UNICODE_STRING strCapture;
|
|
PWND pwnd;
|
|
TL tlpwnd;
|
|
PTHREADINFO ptiCurrent;
|
|
TL tlBuffer;
|
|
BOOL fFreeBuffer = FALSE;
|
|
|
|
BEGINRECV(DWORD, FALSE);
|
|
|
|
ptiCurrent = PtiCurrent();
|
|
|
|
ValidateHWNDOPT(pwnd, hwnd);
|
|
ValidateHCURSOROPT(pcur, hIcon);
|
|
|
|
/*
|
|
* Probe and capture arguments. Capturing the text is ugly,
|
|
* but must be done because it is passed to GDI.
|
|
*/
|
|
try {
|
|
rc = ProbeAndReadRect(lprc);
|
|
strCapture = ProbeAndReadUnicodeString(pstrText);
|
|
if (strCapture.Buffer != NULL) {
|
|
strCapture.Buffer = UserAllocPoolWithQuota(strCapture.Length, TAG_TEXT);
|
|
if (strCapture.Buffer != NULL) {
|
|
fFreeBuffer = TRUE;
|
|
ThreadLockPool(ptiCurrent, strCapture.Buffer, &tlBuffer);
|
|
RtlCopyMemory(strCapture.Buffer, pstrText->Buffer,
|
|
strCapture.Length);
|
|
pstrText = &strCapture;
|
|
} else {
|
|
ExRaiseStatus(STATUS_NO_MEMORY);
|
|
}
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
MSGERRORCLEANUP();
|
|
}
|
|
|
|
ThreadLockWithPti(ptiCurrent, pwnd, &tlpwnd);
|
|
ThreadLockWithPti(ptiCurrent, pcur, &tlpcur);
|
|
|
|
retval = xxxDrawCaptionTemp(
|
|
pwnd,
|
|
hdc,
|
|
&rc,
|
|
hFont,
|
|
pcur,
|
|
strCapture.Buffer ? &strCapture : NULL,
|
|
flags);
|
|
|
|
ThreadUnlock(&tlpcur);
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
CLEANUPRECV();
|
|
if (fFreeBuffer)
|
|
ThreadUnlockAndFreePool(ptiCurrent, &tlBuffer);
|
|
|
|
TRACE("NtUserDrawCaptionTemp");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserGetKeyboardState(
|
|
OUT PBYTE pb)
|
|
{
|
|
int i;
|
|
PQ pq;
|
|
BEGINRECV_SHARED(SHORT, 0)
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWrite(pb, 256, sizeof(BYTE));
|
|
|
|
pq = PtiCurrentShared()->pq;
|
|
|
|
for (i = 0; i < 256; i++, pb++) {
|
|
*pb = 0;
|
|
if (TestKeyStateDown(pq, i))
|
|
*pb |= 0x80;
|
|
|
|
if (TestKeyStateToggle(pq, i))
|
|
*pb |= 0x01;
|
|
}
|
|
retval = TRUE;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
ENDRECV();
|
|
}
|
|
|
|
SHORT NtUserGetKeyState(
|
|
IN int vk)
|
|
{
|
|
PTHREADINFO ptiCurrent;
|
|
BEGINRECV_SHARED(SHORT, 0)
|
|
|
|
ptiCurrent = PtiCurrentShared();
|
|
if (ptiCurrent->pq->QF_flags & QF_UPDATEKEYSTATE) {
|
|
|
|
/*
|
|
* We are going to change the system state, so we
|
|
* must have an exclusive lock
|
|
*/
|
|
ExReleaseResource(gpresUser);
|
|
ExAcquireResourceExclusiveLite(gpresUser, TRUE);
|
|
gptiCurrent = ((PTHREADINFO)(W32GetCurrentThread()));
|
|
|
|
/*
|
|
* If this thread needs a key state event, give one to it. There are
|
|
* cases where any app may be looping looking at GetKeyState(), plus
|
|
* calling PeekMessage(). Key state events don't get created unless
|
|
* new hardware input comes along. If the app isn't receiving hardware
|
|
* input, it won't get the new key state. So ResyncKeyState() will
|
|
* ensure that if the app is looping on GetKeyState(), it'll get the
|
|
* right key state.
|
|
*/
|
|
if (ptiCurrent->pq->QF_flags & QF_UPDATEKEYSTATE) {
|
|
PostUpdateKeyStateEvent(ptiCurrent->pq);
|
|
}
|
|
}
|
|
retval = _GetKeyState(vk);
|
|
|
|
/*
|
|
* Update the client side key state cache.
|
|
*/
|
|
ptiCurrent->pClientInfo->dwKeyCache = gpsi->dwKeyCache;
|
|
RtlCopyMemory(ptiCurrent->pClientInfo->afKeyState,
|
|
ptiCurrent->pq->afKeyState,
|
|
CBKEYCACHE);
|
|
|
|
ENDRECV();
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* NtUserQueryWindow
|
|
*
|
|
* 03-18-95 JimA Created.
|
|
\**************************************************************************/
|
|
|
|
HANDLE NtUserQueryWindow(
|
|
HWND hwnd,
|
|
WINDOWINFOCLASS WindowInfo)
|
|
{
|
|
PTHREADINFO ptiWnd;
|
|
PWND pwnd;
|
|
|
|
/*
|
|
* Don't use BEGINRECV_HWND because we don't want
|
|
* to thread lock the window. Speed is important here.
|
|
*/
|
|
BEGINRECV_SHARED(HANDLE, NULL);
|
|
|
|
pwnd = ValidateHwnd(hwnd);
|
|
if (pwnd == NULL) {
|
|
MSGERROR();
|
|
}
|
|
ptiWnd = GETPTI(pwnd);
|
|
|
|
switch (WindowInfo) {
|
|
case WindowProcess:
|
|
|
|
/*
|
|
* Special case console windows
|
|
*/
|
|
if (ptiWnd->TIF_flags & TIF_CSRSSTHREAD &&
|
|
pwnd->pcls->atomClassName == gatomConsoleClass) {
|
|
retval = (HANDLE)_GetWindowLong(pwnd, 0, FALSE);
|
|
} else {
|
|
retval = (HANDLE)ptiWnd->Thread->Cid.UniqueProcess;
|
|
}
|
|
break;
|
|
case WindowThread:
|
|
|
|
/*
|
|
* Special case console windows
|
|
*/
|
|
if (ptiWnd->TIF_flags & TIF_CSRSSTHREAD &&
|
|
pwnd->pcls->atomClassName == gatomConsoleClass) {
|
|
retval = (HANDLE)_GetWindowLong(pwnd, 4, FALSE);
|
|
} else {
|
|
retval = (HANDLE)ptiWnd->Thread->Cid.UniqueThread;
|
|
}
|
|
break;
|
|
case WindowActiveWindow:
|
|
retval = (HANDLE)HW(ptiWnd->pq->spwndActive);
|
|
break;
|
|
case WindowFocusWindow:
|
|
retval = (HANDLE)HW(ptiWnd->pq->spwndFocus);
|
|
break;
|
|
case WindowIsHung:
|
|
retval = (HANDLE)FHungApp(ptiWnd, CMSHUNGAPPTIMEOUT);
|
|
break;
|
|
case WindowIsForegroundThread:
|
|
retval = (HANDLE)(ptiWnd->pq == gpqForeground);
|
|
break;
|
|
#ifdef FE_IME
|
|
case WindowDefaultImeWindow:
|
|
retval = (HANDLE)HW(ptiWnd->spwndDefaultIme);
|
|
break;
|
|
|
|
case WindowDefaultInputContext:
|
|
retval = (HANDLE)PtoH(ptiWnd->spDefaultImc);
|
|
break;
|
|
#endif
|
|
}
|
|
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSBGetParms(
|
|
IN HWND hwnd,
|
|
IN int code,
|
|
IN PSBDATA pw,
|
|
OUT LPSCROLLINFO lpsi)
|
|
{
|
|
PWND pwnd;
|
|
|
|
/*
|
|
* Don't use BEGINRECV_HWND because we don't want
|
|
* to thread lock the window. Speed is important here.
|
|
*/
|
|
BEGINRECV_SHARED(BOOL, FALSE);
|
|
|
|
pwnd = ValidateHwnd(hwnd);
|
|
|
|
if (pwnd == NULL) {
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWriteScrollInfo(lpsi);
|
|
|
|
/*
|
|
* Probe the 4 DWORDS (MIN, MAX, PAGE, POS)
|
|
*/
|
|
ProbeForRead(pw, 4 * sizeof(DWORD), sizeof(DWORD));
|
|
|
|
retval = _SBGetParms(pwnd, code, pw, lpsi);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
ENDRECV();
|
|
}
|
|
|
|
VOID NtUserPlayEventSound(
|
|
IN PUNICODE_STRING pstrEvent)
|
|
{
|
|
UNICODE_STRING strEvent;
|
|
|
|
BEGINRECV_VOID();
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
strEvent = ProbeAndReadUnicodeString(pstrEvent);
|
|
if (strEvent.Length == 0) {
|
|
MSGERROR_VOID();
|
|
}
|
|
#if defined(_X86_)
|
|
ProbeForRead(strEvent.Buffer, strEvent.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(strEvent.Buffer, strEvent.Length, sizeof(WCHAR));
|
|
#endif
|
|
xxxPlayEventSound(strEvent.Buffer);
|
|
} except (StubExceptionHandler()) {
|
|
}
|
|
|
|
ENDRECV_VOID();
|
|
}
|
|
|
|
BOOL NtUserBitBltSysBmp(
|
|
IN HDC hdc,
|
|
IN int xDest,
|
|
IN int yDest,
|
|
IN int cxDest,
|
|
IN int cyDest,
|
|
IN int xSrc,
|
|
IN int ySrc,
|
|
IN DWORD dwRop)
|
|
{
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
retval = GreBitBlt(hdc,
|
|
xDest,
|
|
yDest,
|
|
cxDest,
|
|
cyDest,
|
|
gpDispInfo->hdcBits,
|
|
xSrc,
|
|
ySrc,
|
|
dwRop,
|
|
0);
|
|
|
|
ENDRECV();
|
|
}
|
|
|
|
HPALETTE NtUserSelectPalette(
|
|
IN HDC hdc,
|
|
IN HPALETTE hpalette,
|
|
IN BOOL fForceBackground)
|
|
{
|
|
BEGINRECV(HPALETTE, NULL)
|
|
|
|
retval = _SelectPalette(hdc, hpalette, fForceBackground);
|
|
|
|
ENDRECV();
|
|
}
|
|
|
|
/*
|
|
* Message thunks
|
|
*/
|
|
|
|
MESSAGECALL(DWORD)
|
|
{
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnDWORD");
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
lParam,
|
|
xParam);
|
|
|
|
TRACE("fnDWORD");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(OPTOUTLPDWORDOPTOUTLPDWORD)
|
|
{
|
|
DWORD dwwParam, dwlParam;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnOPTOUTLPDWORDOPTOUTLPDWORD");
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
(WPARAM)&dwwParam,
|
|
(LPARAM)&dwlParam,
|
|
xParam);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
if (ARGUMENT_PRESENT(wParam)) {
|
|
ProbeAndWriteUlong((PULONG)wParam, dwwParam);
|
|
}
|
|
if (ARGUMENT_PRESENT(lParam)) {
|
|
ProbeAndWriteUlong((PULONG)lParam, dwlParam);
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("fnOPTOUTLPDWORDOPTOUTLPDWORD");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INOUTNEXTMENU)
|
|
{
|
|
MDINEXTMENU mnm;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINOUTNEXTMENU");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWriteMDINextMenu((PMDINEXTMENU)lParam);
|
|
mnm = *(PMDINEXTMENU)lParam;
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&mnm,
|
|
xParam);
|
|
|
|
*(PMDINEXTMENU)lParam = mnm;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("fnINOUTNEXTMENU");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(DWORDOPTINLPMSG)
|
|
{
|
|
MSG msgstruct;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnDWORDOPTINLPMSG");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
if (ARGUMENT_PRESENT(lParam)) {
|
|
msgstruct = ProbeAndReadMessage((LPMSG)lParam);
|
|
lParam = (LPARAM)&msgstruct;
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
lParam,
|
|
xParam);
|
|
|
|
TRACE("fnDWORDOPTINLPMSG");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(COPYGLOBALDATA)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnCOPYGLOBALDATA");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForRead((PVOID)lParam, wParam, sizeof(BYTE));
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* !!! Data pointed to by lParam must be captured
|
|
* in xxxInterSendMsgEx
|
|
*/
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
lParam,
|
|
xParam);
|
|
|
|
TRACE("fnCOPYGLOBALDATA");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(COPYDATA)
|
|
{
|
|
COPYDATASTRUCT cds;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnCOPYDATA");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
if (ARGUMENT_PRESENT(lParam)) {
|
|
cds = ProbeAndReadCopyDataStruct((PCOPYDATASTRUCT)lParam);
|
|
if (cds.lpData)
|
|
ProbeForRead(cds.lpData, cds.cbData, sizeof(BYTE));
|
|
lParam = (LPARAM)&cds;
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* !!! Data pointed to by cds.lpData must be captured
|
|
* in xxxInterSendMsgEx
|
|
*/
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
lParam,
|
|
xParam);
|
|
|
|
TRACE("fnCOPYDATA");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(SENTDDEMSG)
|
|
{
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnSENTDDEMSG");
|
|
|
|
if (xpfnProc == FNID_CALLWINDOWPROC) {
|
|
retval = CALLPROC(xpfnProc)(pwnd,
|
|
msg | MSGFLAG_DDE_SPECIAL_SEND,
|
|
wParam, lParam, xParam);
|
|
} else if ((ptiCurrent->TIF_flags & TIF_16BIT) &&
|
|
(ptiCurrent->ptdb) &&
|
|
(ptiCurrent->ptdb->hTaskWow)) {
|
|
/*
|
|
* Note that this function may modify msg by ORing in a bit in the
|
|
* high word. This bit is ignored when thunking messages.
|
|
* This allows the DdeTrackSendMessage() hook to be skipped - which
|
|
* would cause an error - and instead allows this thunk to carry
|
|
* the message all the way across.
|
|
*/
|
|
retval = xxxDDETrackPostHook(&msg, pwnd, wParam, &lParam, TRUE);
|
|
switch (retval) {
|
|
case DO_POST:
|
|
/*
|
|
* Or in the MSGFLAG_DDE_SPECIAL_SEND so that
|
|
* xxxSendMessageTimeout() will not pass this on to
|
|
* xxxDdeTrackSendMsg() which would think it was evil.
|
|
*
|
|
* Since the SendMessage() thunks ignore the reserved bits
|
|
* it will still get maped to the fnSENTDDEMSG callback thunk.
|
|
*/
|
|
retval = CALLPROC(xpfnProc)(pwnd,
|
|
msg | MSGFLAG_DDE_SPECIAL_SEND,
|
|
wParam, lParam, xParam);
|
|
break;
|
|
|
|
case FAKE_POST:
|
|
case FAIL_POST:
|
|
retval = 0;
|
|
}
|
|
}
|
|
|
|
TRACE("fnSENTDDEMSG");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(DDEINIT)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
PWND pwndFrom;
|
|
TL tlpwndFrom;
|
|
PDDEIMP pddei;
|
|
PSECURITY_QUALITY_OF_SERVICE pqos;
|
|
NTSTATUS Status;
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnDDEINIT");
|
|
|
|
ValidateHWND(pwndFrom, (HWND)wParam);
|
|
ThreadLockAlwaysWithPti(ptiCurrent, pwndFrom, &tlpwndFrom);
|
|
|
|
/*
|
|
* Create temporary DDEIMP property for client window - this stays around
|
|
* only during the initiate phase.
|
|
*/
|
|
if ((pddei = (PDDEIMP)_GetProp(pwndFrom, PROP_DDEIMP, TRUE))
|
|
== NULL) {
|
|
pddei = (PDDEIMP)UserAllocPoolWithQuota(sizeof(DDEIMP), TAG_DDEd);
|
|
if (pddei == NULL) {
|
|
RIPERR0(ERROR_NOT_ENOUGH_MEMORY, RIP_WARNING, "fnDDEINIT: LocalAlloc failed.");
|
|
MSGERRORCLEANUP();
|
|
}
|
|
pqos = (PSECURITY_QUALITY_OF_SERVICE)_GetProp(pwndFrom, PROP_QOS, TRUE);
|
|
if (pqos == NULL) {
|
|
pqos = &gqosDefault;
|
|
}
|
|
pddei->qos = *pqos;
|
|
Status = SeCreateClientSecurity(PsGetCurrentThread(),
|
|
pqos, FALSE, &pddei->ClientContext);
|
|
if (!NT_SUCCESS(Status)) {
|
|
RIPMSG0(RIP_WARNING, "SeCreateClientContext failed.");
|
|
UserFreePool(pddei);
|
|
MSGERRORCLEANUP();
|
|
}
|
|
pddei->cRefInit = 1;
|
|
pddei->cRefConv = 0;
|
|
InternalSetProp(pwndFrom, PROP_DDEIMP, pddei, PROPF_INTERNAL);
|
|
} else {
|
|
pddei->cRefInit++; // cover broadcast case!
|
|
}
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
lParam,
|
|
xParam);
|
|
|
|
/*
|
|
* Reaquire pddei incase pwndFrom was destroyed.
|
|
*/
|
|
pddei = (PDDEIMP)_GetProp(pwndFrom, PROP_DDEIMP, TRUE);
|
|
if (pddei != NULL) {
|
|
/*
|
|
* Decrement reference count from DDEImpersonate property and remove property.
|
|
*/
|
|
pddei->cRefInit--;
|
|
if (pddei->cRefInit == 0) {
|
|
InternalRemoveProp(pwndFrom, PROP_DDEIMP, TRUE);
|
|
if (pddei->cRefConv == 0) {
|
|
SeDeleteClientSecurity(&pddei->ClientContext);
|
|
UserFreePool(pddei);
|
|
}
|
|
}
|
|
}
|
|
|
|
CLEANUPRECV();
|
|
ThreadUnlock(&tlpwndFrom);
|
|
|
|
TRACE("fnDDEINIT");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INPAINTCLIPBRD)
|
|
{
|
|
PWND pwnd;
|
|
TL tlpwnd;
|
|
PAINTSTRUCT ps;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
TRACETHUNK("fnINPAINTCLIPBRD");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ps = ProbeAndReadPaintStruct((PPAINTSTRUCT)lParam);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
ValidateHWNDFF(pwnd, hwnd);
|
|
|
|
if (pwnd != (PWND)0xFFFFFFFF)
|
|
ThreadLockAlways(pwnd, &tlpwnd);
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&ps,
|
|
xParam);
|
|
|
|
if (pwnd != (PWND)0xFFFFFFFF)
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("fnINPAINTCLIPBRD");
|
|
ENDRECV();
|
|
}
|
|
|
|
MESSAGECALL(INSIZECLIPBRD)
|
|
{
|
|
PWND pwnd;
|
|
TL tlpwnd;
|
|
RECT rc;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
TRACETHUNK("fnINSIZECLIPBRD");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
rc = ProbeAndReadRect((PRECT)lParam);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
ValidateHWNDFF(pwnd, hwnd);
|
|
|
|
if (pwnd != (PWND)0xFFFFFFFF)
|
|
ThreadLockAlways(pwnd, &tlpwnd);
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&rc,
|
|
xParam);
|
|
|
|
if (pwnd != (PWND)0xFFFFFFFF)
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("fnINSIZECLIPBRD");
|
|
ENDRECV();
|
|
}
|
|
|
|
#if 0
|
|
|
|
// !!!LATER not needed until we support multiple screens
|
|
|
|
MESSAGECALL(FULLSCREEN)
|
|
{
|
|
TL tlpwnd;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
TRACETHUNK("fnFULLSCREEN");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
ValidateHWND(pwnd, hwnd);
|
|
|
|
ThreadLockAlways(pwnd, &tlpwnd);
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
pmsg->msg,
|
|
pmsg->wParam,
|
|
(LONG)pdeviceinfo,
|
|
pmsg->xParam);
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("fnFULLSCREEN");
|
|
ENDRECV();
|
|
}
|
|
|
|
#endif // 0
|
|
|
|
MESSAGECALL(INOUTDRAG)
|
|
{
|
|
DROPSTRUCT ds;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINOUTDRAG");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWriteDropStruct((PDROPSTRUCT)lParam);
|
|
ds = *(PDROPSTRUCT)lParam;
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&ds,
|
|
xParam);
|
|
|
|
*(PDROPSTRUCT)lParam = ds;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("fnINOUTDRAG");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(GETTEXTLENGTHS)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnGETTEXTLENGTHS");
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
bAnsi,
|
|
xParam);
|
|
|
|
TRACE("fnGETTEXTLENGTHS");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INLPCREATESTRUCT)
|
|
{
|
|
CREATESTRUCTEX csex;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINLPCREATESTRUCT");
|
|
|
|
if (ARGUMENT_PRESENT(lParam)) {
|
|
try {
|
|
csex.cs = ProbeAndReadCreateStruct((LPCREATESTRUCTW)lParam);
|
|
if (bAnsi) {
|
|
RtlInitLargeAnsiString((PLARGE_ANSI_STRING)&csex.strName,
|
|
(LPSTR)csex.cs.lpszName, (UINT)-1);
|
|
if (HIWORD(csex.cs.lpszClass)) {
|
|
RtlInitLargeAnsiString((PLARGE_ANSI_STRING)&csex.strClass,
|
|
(LPSTR)csex.cs.lpszClass, (UINT)-1);
|
|
}
|
|
} else {
|
|
RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&csex.strName,
|
|
csex.cs.lpszName, (UINT)-1);
|
|
if (HIWORD(csex.cs.lpszClass)) {
|
|
RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&csex.strClass,
|
|
csex.cs.lpszClass, (UINT)-1);
|
|
}
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
}
|
|
|
|
// Per Win95, do not allow NULL lpcreatestructs for WM_NCCREATE [51986]
|
|
// Allowed for WM_CREATE in Win95 for ObjectVision
|
|
else if (msg == WM_NCCREATE) {
|
|
MSGERROR() ;
|
|
}
|
|
|
|
/*
|
|
* !!! Strings pointed to by cs.cs must be captured in xxxInterSendMsgEx
|
|
*/
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
lParam ? (LPARAM)&csex : 0,
|
|
xParam);
|
|
|
|
TRACE("fnINLPCREATESTRUCT");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
LONG NtUserfnINLPMDICREATESTRUCT(
|
|
HWND hwnd,
|
|
UINT msg,
|
|
DWORD wParam,
|
|
LONG lParam,
|
|
PUNICODE_STRING pstrClass,
|
|
PUNICODE_STRING pstrTitle OPTIONAL,
|
|
DWORD xParam,
|
|
DWORD xpfnProc,
|
|
BOOL bAnsi)
|
|
{
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
MDICREATESTRUCTEX mdics;
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINLPMDICREATESTRUCT");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
mdics.mdics = ProbeAndReadMDICreateStruct((LPMDICREATESTRUCTW)lParam);
|
|
|
|
if (pstrTitle != NULL) {
|
|
mdics.strTitle = ProbeAndReadUnicodeString(pstrTitle);
|
|
#if defined(_X86_)
|
|
ProbeForRead(mdics.strTitle.Buffer, mdics.strTitle.Length,
|
|
sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(mdics.strTitle.Buffer, mdics.strTitle.Length,
|
|
sizeof(WCHAR));
|
|
#endif
|
|
} else {
|
|
RtlZeroMemory(&mdics.strTitle, sizeof(UNICODE_STRING));
|
|
}
|
|
mdics.mdics.szTitle = mdics.strTitle.Buffer;
|
|
|
|
mdics.strClass = ProbeAndReadUnicodeString(pstrClass);
|
|
#if defined(_X86_)
|
|
ProbeForRead(mdics.strClass.Buffer, mdics.strClass.Length,
|
|
sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(mdics.strClass.Buffer, mdics.strClass.Length,
|
|
sizeof(WCHAR));
|
|
#endif
|
|
mdics.mdics.szClass = mdics.strClass.Buffer;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* !!! Strings pointed to by mdics must be captured in xxxInterSendMsgEx
|
|
*/
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LONG)&mdics,
|
|
xParam);
|
|
|
|
TRACE("fnINLPMDICREATESTRUCT");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INOUTLPSCROLLINFO)
|
|
{
|
|
SCROLLINFO scrollinfo;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINOUTLPSCROLLINFO");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWriteScrollInfo((LPSCROLLINFO)lParam);
|
|
scrollinfo = *(LPSCROLLINFO)lParam;
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&scrollinfo,
|
|
xParam);
|
|
|
|
*(LPSCROLLINFO)lParam = scrollinfo;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("fnINOUTLPSCROLLINFO");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INOUTLPPOINT5)
|
|
{
|
|
POINT5 pt5;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINOUTLPPOINT5");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWritePoint5((LPPOINT5)lParam);
|
|
pt5 = *(LPPOINT5)lParam;
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&pt5,
|
|
xParam);
|
|
|
|
*(LPPOINT5)lParam = pt5;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("fnINOUTLPPOINT5");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INSTRING)
|
|
{
|
|
LARGE_STRING str;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINSTRING");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
str = ProbeAndReadLargeString((PLARGE_STRING)lParam);
|
|
#if defined(_X86_)
|
|
ProbeForRead(str.Buffer, str.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(str.Buffer, str.Length,
|
|
str.bAnsi ? sizeof(BYTE) : sizeof(WORD));
|
|
#endif
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* Don't allow any app to send a LB_DIR or CB_DIR with the postmsgs bit
|
|
* set (ObjectVision does this). This is because there is actually a legal
|
|
* case that we need to thunk of user posting a LB_DIR or CB_DIR
|
|
* (DlgDirListHelper()). In the post case, we thunk the lParam (pointer
|
|
* to a string) differently, and we track that post case with the
|
|
* DDL_POSTMSGS bit. If an app sends a message with this bit, then our
|
|
* thunking gets confused, so clear it here. Let's hope that no app
|
|
* depends on this bit set when either of these messages are sent.
|
|
*/
|
|
switch (msg) {
|
|
case LB_DIR:
|
|
case CB_DIR:
|
|
wParam &= ~DDL_POSTMSGS;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* !!! str.Buffer must be captured in xxxInterSendMsgEx
|
|
*/
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&str,
|
|
xParam);
|
|
|
|
TRACE("fnINSTRING");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INSTRINGNULL)
|
|
{
|
|
LARGE_STRING str;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINSTRINGNULL");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
if (ARGUMENT_PRESENT(lParam)) {
|
|
str = ProbeAndReadLargeString((PLARGE_STRING)lParam);
|
|
#if defined(_X86_)
|
|
ProbeForRead(str.Buffer, str.Length, sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(str.Buffer, str.Length,
|
|
str.bAnsi ? sizeof(BYTE) : sizeof(WORD));
|
|
#endif
|
|
lParam = (LPARAM)&str;
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* !!! str.Buffer must be captured in xxxInterSendMsgEx
|
|
*/
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
lParam,
|
|
xParam);
|
|
|
|
TRACE("fnINSTRINGNULL");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INDEVICECHANGE)
|
|
{
|
|
BOOL fPtr = (BOOL)((wParam & 0x8000) == 0x8000);
|
|
DWORD cbSize;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINDEVICECHANGE");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
if (fPtr && lParam) {
|
|
try {
|
|
cbSize = ProbeAndReadUlong((PULONG)lParam);
|
|
ProbeForRead((PVOID)lParam, cbSize, sizeof(BYTE));
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* !!! lParam must be captured in xxxInterSendMsgEx
|
|
*/
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
lParam,
|
|
xParam);
|
|
|
|
TRACE("fnINDEVICECHANGE");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
|
|
MESSAGECALL(INOUTNCCALCSIZE)
|
|
{
|
|
NCCALCSIZE_PARAMS params;
|
|
WINDOWPOS pos;
|
|
PWINDOWPOS pposClient;
|
|
RECT rc;
|
|
LPARAM lParamLocal;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINOUTNCCALCSIZE");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
if (wParam != 0) {
|
|
ProbeForWriteNCCalcSize((LPNCCALCSIZE_PARAMS)lParam);
|
|
params = *(LPNCCALCSIZE_PARAMS)lParam;
|
|
ProbeForWriteWindowPos(params.lppos);
|
|
pposClient = params.lppos;
|
|
pos = *params.lppos;
|
|
params.lppos = &pos;
|
|
lParamLocal = (LPARAM)¶ms;
|
|
} else {
|
|
ProbeForWriteRect((LPRECT)lParam);
|
|
rc = *(LPRECT)lParam;
|
|
lParamLocal = (LPARAM)&rc;
|
|
}
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
lParamLocal,
|
|
xParam);
|
|
|
|
if (wParam != 0) {
|
|
*(LPNCCALCSIZE_PARAMS)lParam = params;
|
|
((LPNCCALCSIZE_PARAMS)lParam)->lppos = pposClient;
|
|
*pposClient = pos;
|
|
} else {
|
|
*(LPRECT)lParam = rc;
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("fnINOUTNCCALCSIZE");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INOUTSTYLECHANGE)
|
|
{
|
|
STYLESTRUCT ss;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINOUTSTYLECHANGE");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWriteStyleStruct((LPSTYLESTRUCT)lParam);
|
|
ss = *(LPSTYLESTRUCT)lParam;
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&ss,
|
|
xParam);
|
|
|
|
*(LPSTYLESTRUCT)lParam = ss;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("fnINOUTSTYLECHANGE");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INOUTLPRECT)
|
|
{
|
|
RECT rc;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINOUTLPRECT");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWriteRect((PRECT)lParam);
|
|
rc = *(PRECT)lParam;
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&rc,
|
|
xParam);
|
|
|
|
*(PRECT)lParam = rc;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("fnINOUTLPRECT");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(OUTLPSCROLLINFO)
|
|
{
|
|
SCROLLINFO scrollinfo;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnOUTLPSCROLLINFO");
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&scrollinfo,
|
|
xParam);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWriteScrollInfo((LPSCROLLINFO)lParam);
|
|
*(LPSCROLLINFO)lParam = scrollinfo;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("fnOUTLPSCROLLINFO");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(OUTLPRECT)
|
|
{
|
|
RECT rc;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnOUTLPRECT");
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&rc,
|
|
xParam);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWriteRect((PRECT)lParam);
|
|
*(PRECT)lParam = rc;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("fnOUTLPRECT");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INLPCOMPAREITEMSTRUCT)
|
|
{
|
|
COMPAREITEMSTRUCT compareitemstruct;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINLPCOMPAREITEMSTRUCT");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
compareitemstruct = ProbeAndReadCompareItemStruct((PCOMPAREITEMSTRUCT)lParam);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&compareitemstruct,
|
|
xParam);
|
|
|
|
TRACE("fnINLPCOMPAREITEMSTRUCT");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INLPDELETEITEMSTRUCT)
|
|
{
|
|
DELETEITEMSTRUCT deleteitemstruct;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINLPDELETEITEMSTRUCT");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
deleteitemstruct = ProbeAndReadDeleteItemStruct((PDELETEITEMSTRUCT)lParam);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&deleteitemstruct,
|
|
xParam);
|
|
|
|
TRACE("fnINLPDELETEITEMSTRUCT");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INLPHLPSTRUCT)
|
|
{
|
|
HLP hlp;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINLPHLPSTRUCT");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
hlp = ProbeAndReadHelp((LPHLP)lParam);
|
|
ProbeForRead((PVOID)lParam, hlp.cbData, sizeof(BYTE));
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* !!! Data pointed to by lParam must be captured in xxxInterSendMsgEx
|
|
*/
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
lParam,
|
|
xParam);
|
|
|
|
TRACE("fnINLPHLPSTRUCT");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INLPHELPINFOSTRUCT)
|
|
{
|
|
HELPINFO helpinfo;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINLPHELPINFOSTRUCT");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
helpinfo = ProbeAndReadHelpInfo((LPHELPINFO)lParam);
|
|
ProbeForRead((PVOID)lParam, helpinfo.cbSize, sizeof(BYTE));
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* !!! Data pointed to by lParam must be captured in xxxInterSendMsgEx
|
|
*/
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
lParam,
|
|
xParam);
|
|
|
|
TRACE("fnINLPHELPINFOSTRUCT");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INLPDRAWITEMSTRUCT)
|
|
{
|
|
DRAWITEMSTRUCT drawitemstruct;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINLPDRAWITEMSTRUCT");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
drawitemstruct = ProbeAndReadDrawItemStruct((PDRAWITEMSTRUCT)lParam);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&drawitemstruct,
|
|
xParam);
|
|
|
|
TRACE("fnINLPDRAWITEMSTRUCT");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INOUTLPMEASUREITEMSTRUCT)
|
|
{
|
|
MEASUREITEMSTRUCT measureitemstruct;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINOUTLPMEASUREITEMSTRUCT");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWriteMeasureItemStruct((PMEASUREITEMSTRUCT)lParam);
|
|
measureitemstruct = *(PMEASUREITEMSTRUCT)lParam;
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&measureitemstruct,
|
|
xParam);
|
|
|
|
*(PMEASUREITEMSTRUCT)lParam = measureitemstruct;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("fnINOUTLPMEASUREITEMSTRUCT");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(OUTSTRING)
|
|
{
|
|
LARGE_STRING str;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnOUTSTRING");
|
|
|
|
/*
|
|
* Probe all arguments
|
|
*/
|
|
try {
|
|
str = ProbeAndReadLargeString((PLARGE_STRING)lParam);
|
|
#if defined(_X86_)
|
|
ProbeForWrite((PVOID)str.Buffer, str.MaximumLength, sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite((PVOID)str.Buffer, str.MaximumLength,
|
|
str.bAnsi ? sizeof(BYTE) : sizeof(WORD));
|
|
#endif
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* !!! String buffer must be created in xxxInterSendMsgEx and
|
|
* lParam probed for write again upon return.
|
|
*/
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&str,
|
|
xParam);
|
|
|
|
TRACE("fnOUTSTRING");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(OUTDWORDINDWORD)
|
|
{
|
|
DWORD dw;
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnOUTDWORDINDWORD");
|
|
|
|
/*
|
|
* Probe wParam
|
|
*/
|
|
try {
|
|
dw = ProbeRect((LPRECT)wParam);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
lParam,
|
|
xParam);
|
|
|
|
TRACE("fnOUTDWORDINDWORD");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INCNTOUTSTRING)
|
|
{
|
|
LARGE_STRING str;
|
|
PWND pwnd;
|
|
TL tlpwnd;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
TRACETHUNK("fnINCNTOUTSTRING");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
str = ProbeAndReadLargeString((PLARGE_STRING)lParam);
|
|
#if defined(_X86_)
|
|
ProbeForWrite((PVOID)str.Buffer, str.MaximumLength, sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite((PVOID)str.Buffer, str.MaximumLength,
|
|
str.bAnsi ? sizeof(BYTE) : sizeof(WORD));
|
|
#endif
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
ValidateHWNDFF(pwnd, hwnd);
|
|
|
|
if (pwnd != (PWND)0xFFFFFFFF)
|
|
ThreadLockAlways(pwnd, &tlpwnd);
|
|
|
|
/*
|
|
* !!! String buffer must be created in xxxInterSendMsgEx and
|
|
* lParam probed for write again upon return.
|
|
*/
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&str,
|
|
xParam);
|
|
|
|
if (pwnd != (PWND)0xFFFFFFFF)
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
TRACE("fnINCNTOUTSTRING");
|
|
ENDRECV();
|
|
}
|
|
|
|
MESSAGECALL(INCNTOUTSTRINGNULL)
|
|
{
|
|
LARGE_STRING str;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINCNTOUTSTRINGNULL");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
str = ProbeAndReadLargeString((PLARGE_STRING)lParam);
|
|
#if defined(_X86_)
|
|
ProbeForWrite((PVOID)str.Buffer, str.MaximumLength, sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite((PVOID)str.Buffer, str.MaximumLength,
|
|
str.bAnsi ? sizeof(BYTE) : sizeof(WORD));
|
|
#endif
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* !!! String buffer must be created in xxxInterSendMsgEx and
|
|
* lParam probed for write again upon return.
|
|
*/
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&str,
|
|
xParam);
|
|
|
|
TRACE("fnINCNTOUTSTRINGNULL");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(POUTLPINT)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnPOUTLPINT");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
#if defined(_X86_)
|
|
ProbeForWrite((PVOID)lParam, wParam * sizeof(INT), sizeof(BYTE));
|
|
#else
|
|
ProbeForWrite((PVOID)lParam, wParam * sizeof(INT), sizeof(INT));
|
|
#endif
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* !!! Buffer must be created in xxxInterSendMsgEx and
|
|
* lParam probed for write again upon return.
|
|
*/
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
lParam,
|
|
xParam);
|
|
|
|
TRACE("fnPOUTLPINT");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(POPTINLPUINT)
|
|
{
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnPOPTINLPUINT");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
#if defined(_X86_)
|
|
if (lParam)
|
|
ProbeForRead((PVOID)lParam, wParam * sizeof(UINT), sizeof(BYTE));
|
|
#else
|
|
if (lParam)
|
|
ProbeForRead((PVOID)lParam, wParam * sizeof(UINT), sizeof(DWORD));
|
|
#endif
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* !!! Data pointed to by lParam must be captured in xxxInterSendMsgEx
|
|
*/
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
lParam,
|
|
xParam);
|
|
|
|
TRACE("fnPOPTINLPUINT");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INOUTLPWINDOWPOS)
|
|
{
|
|
WINDOWPOS pos;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINOUTLPWINDOWPOS");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWriteWindowPos((PWINDOWPOS)lParam);
|
|
pos = *(PWINDOWPOS)lParam;
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&pos,
|
|
xParam);
|
|
|
|
*(PWINDOWPOS)lParam = pos;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("fnINOUTLPWINDOWPOS");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
MESSAGECALL(INLPWINDOWPOS)
|
|
{
|
|
WINDOWPOS pos;
|
|
|
|
//
|
|
// N.B. This function has implicit window translation and thread locking
|
|
// enabled. These operations are performed in the User server API
|
|
// dispatcher.
|
|
//
|
|
|
|
BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
|
|
TRACETHUNK("fnINLPWINDOWPOS");
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
pos = ProbeAndReadWindowPos((PWINDOWPOS)lParam);
|
|
|
|
retval = CALLPROC(xpfnProc)(
|
|
pwnd,
|
|
msg,
|
|
wParam,
|
|
(LPARAM)&pos,
|
|
xParam);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("fnINLPWINDOWPOS");
|
|
ENDRECV_HWNDLOCK();
|
|
}
|
|
|
|
/*
|
|
* Hook stubs
|
|
*/
|
|
|
|
DWORD NtUserfnHkINLPCBTCREATESTRUCT(
|
|
IN UINT msg,
|
|
IN DWORD wParam,
|
|
IN LPCBT_CREATEWND pcbt,
|
|
IN PLARGE_UNICODE_STRING pstrName OPTIONAL,
|
|
IN PUNICODE_STRING pstrClass,
|
|
IN DWORD xpfnProc)
|
|
{
|
|
CBT_CREATEWND cbt;
|
|
CREATESTRUCTEX csex;
|
|
|
|
BEGINRECV(DWORD, 0);
|
|
|
|
UNREFERENCED_PARAMETER(xpfnProc);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
cbt = ProbeAndReadCBTCreateStruct(pcbt);
|
|
ProbeForWriteCreateStruct(cbt.lpcs);
|
|
csex.cs = *pcbt->lpcs;
|
|
cbt.lpcs = (LPCREATESTRUCT)&csex;
|
|
if (pstrName) {
|
|
csex.strName = ProbeAndReadLargeString((PLARGE_STRING)pstrName);
|
|
#if defined(_X86_)
|
|
ProbeForRead(csex.strName.Buffer, csex.strName.MaximumLength,
|
|
sizeof(BYTE));
|
|
#else
|
|
ProbeForRead(csex.strName.Buffer, csex.strName.MaximumLength,
|
|
sizeof(WORD));
|
|
#endif
|
|
} else {
|
|
RtlZeroMemory(&csex.strName, sizeof(csex.strName));
|
|
}
|
|
csex.cs.lpszName = csex.strName.Buffer;
|
|
|
|
csex.strClass.bAnsi = FALSE;
|
|
csex.strClass.Buffer = pstrClass->Buffer;
|
|
csex.strClass.Length = pstrClass->Length;
|
|
csex.strClass.MaximumLength = pstrClass->MaximumLength;
|
|
ProbeForRead(csex.strClass.Buffer, csex.strClass.MaximumLength,
|
|
sizeof(BYTE));
|
|
csex.cs.lpszClass = csex.strClass.Buffer;
|
|
|
|
retval = xxxCallNextHookEx(
|
|
msg,
|
|
wParam,
|
|
(UINT)&cbt);
|
|
|
|
pcbt->hwndInsertAfter = cbt.hwndInsertAfter;
|
|
pcbt->lpcs->x = cbt.lpcs->x;
|
|
pcbt->lpcs->y = cbt.lpcs->y;
|
|
pcbt->lpcs->cx = cbt.lpcs->cx;
|
|
pcbt->lpcs->cy = cbt.lpcs->cy;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserfnHkINLPCBTCREATESTRUCT");
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserfnHkINLPRECT(
|
|
IN DWORD nCode,
|
|
IN DWORD wParam,
|
|
IN LPRECT lParam,
|
|
IN DWORD xParam,
|
|
IN DWORD xpfnProc)
|
|
{
|
|
RECT rc;
|
|
|
|
BEGINRECV(DWORD, 0);
|
|
|
|
UNREFERENCED_PARAMETER(xParam);
|
|
UNREFERENCED_PARAMETER(xpfnProc);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
rc = ProbeAndReadRect((PRECT)lParam);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = xxxCallNextHookEx(
|
|
nCode,
|
|
wParam,
|
|
(UINT)&rc);
|
|
|
|
TRACE("NtUserfnHkINLPRECT");
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserfnHkINDWORD(
|
|
IN DWORD nCode,
|
|
IN DWORD wParam,
|
|
IN LONG lParam,
|
|
IN DWORD xParam,
|
|
IN DWORD xpfnProc)
|
|
{
|
|
BEGINRECV(DWORD, 0);
|
|
|
|
UNREFERENCED_PARAMETER(xParam);
|
|
UNREFERENCED_PARAMETER(xpfnProc);
|
|
|
|
retval = xxxCallNextHookEx(
|
|
nCode,
|
|
wParam,
|
|
lParam);
|
|
|
|
TRACE("NtUserfnHkINDWORD");
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserfnHkINLPMSG(
|
|
IN DWORD nCode,
|
|
IN DWORD wParam,
|
|
IN LPMSG lParam,
|
|
IN DWORD xParam,
|
|
IN DWORD xpfnProc)
|
|
{
|
|
MSG msg;
|
|
|
|
BEGINRECV(DWORD, 0);
|
|
|
|
UNREFERENCED_PARAMETER(xParam);
|
|
UNREFERENCED_PARAMETER(xpfnProc);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
msg = ProbeAndReadMessage((PMSG)lParam);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = xxxCallNextHookEx(
|
|
nCode,
|
|
wParam,
|
|
(UINT)&msg);
|
|
|
|
TRACE("NtUserfnHkINLPMSG");
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserfnHkINLPDEBUGHOOKSTRUCT(
|
|
IN DWORD nCode,
|
|
IN DWORD wParam,
|
|
IN LPDEBUGHOOKINFO lParam,
|
|
IN DWORD xParam,
|
|
IN DWORD xpfnProc)
|
|
{
|
|
DEBUGHOOKINFO hookinfo;
|
|
|
|
BEGINRECV(DWORD, 0);
|
|
|
|
UNREFERENCED_PARAMETER(xParam);
|
|
UNREFERENCED_PARAMETER(xpfnProc);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
hookinfo = ProbeAndReadHookInfo((PDEBUGHOOKINFO)lParam);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = xxxCallNextHookEx(
|
|
nCode,
|
|
wParam,
|
|
(UINT)&hookinfo);
|
|
|
|
TRACE("NtUserfnHkINLPDEBUGHOOKSTRUCT");
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserfnHkOPTINLPEVENTMSG(
|
|
IN DWORD nCode,
|
|
IN DWORD wParam,
|
|
IN OUT LPEVENTMSGMSG lParam OPTIONAL,
|
|
IN DWORD xParam,
|
|
IN DWORD xpfnProc)
|
|
{
|
|
EVENTMSG event;
|
|
|
|
BEGINRECV(DWORD, 0);
|
|
|
|
UNREFERENCED_PARAMETER(xParam);
|
|
UNREFERENCED_PARAMETER(xpfnProc);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
if (ARGUMENT_PRESENT(lParam)) {
|
|
try {
|
|
ProbeForWriteEvent((LPEVENTMSGMSG)lParam);
|
|
event = *(LPEVENTMSGMSG)lParam;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
}
|
|
|
|
retval = xxxCallNextHookEx(
|
|
nCode,
|
|
wParam,
|
|
(UINT)(lParam ? &event : NULL));
|
|
|
|
if (ARGUMENT_PRESENT(lParam)) {
|
|
try {
|
|
*(LPEVENTMSGMSG)lParam = event;
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
}
|
|
|
|
TRACE("NtUserfnHkINLPEVENTMSG");
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserfnHkINLPMOUSEHOOKSTRUCT(
|
|
IN DWORD nCode,
|
|
IN DWORD wParam,
|
|
IN LPMOUSEHOOKSTRUCT lParam,
|
|
IN DWORD xParam,
|
|
IN DWORD xpfnProc)
|
|
{
|
|
MOUSEHOOKSTRUCT mousehook;
|
|
|
|
BEGINRECV(DWORD, 0);
|
|
|
|
UNREFERENCED_PARAMETER(xParam);
|
|
UNREFERENCED_PARAMETER(xpfnProc);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
mousehook = ProbeAndReadMouseHook((PMOUSEHOOKSTRUCT)lParam);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = xxxCallNextHookEx(
|
|
nCode,
|
|
wParam,
|
|
(UINT)&mousehook);
|
|
|
|
TRACE("NtUserfnHkINLPMOUSEHOOKSTRUCT");
|
|
ENDRECV();
|
|
}
|
|
|
|
DWORD NtUserfnHkINLPCBTACTIVATESTRUCT(
|
|
IN DWORD nCode,
|
|
IN DWORD wParam,
|
|
IN LPCBTACTIVATESTRUCT lParam,
|
|
IN DWORD xParam,
|
|
IN DWORD xpfnProc)
|
|
{
|
|
CBTACTIVATESTRUCT cbtactivate;
|
|
|
|
BEGINRECV(DWORD, 0);
|
|
|
|
UNREFERENCED_PARAMETER(xParam);
|
|
UNREFERENCED_PARAMETER(xpfnProc);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
cbtactivate = ProbeAndReadCBTActivateStruct((LPCBTACTIVATESTRUCT)lParam);
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = xxxCallNextHookEx(
|
|
nCode,
|
|
wParam,
|
|
(UINT)&cbtactivate);
|
|
|
|
TRACE("NtUserfnHkINLPCBTACTIVATESTRUCT");
|
|
ENDRECV();
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* NtUserECQueryInputLangChange
|
|
*
|
|
* The abuser tried to change input language, allow it only if the new
|
|
* language will fit into the current font. See if the new locale will fit
|
|
* into the current font. If not, reject the call.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
BOOL NtUserECQueryInputLangChange(
|
|
IN HWND hwnd,
|
|
IN WPARAM wParam,
|
|
IN HKL hkl,
|
|
IN UINT bCharsets)
|
|
{
|
|
PWND pwnd;
|
|
PWINDOWSTATION pwinsta;
|
|
PKL pkl, pklStart, pklStop;
|
|
|
|
BEGINRECV(DWORD, FALSE);
|
|
|
|
pwinsta = _GetProcessWindowStation(NULL);
|
|
|
|
pkl = pklStart = pklStop = pwinsta->spklList;
|
|
|
|
do {
|
|
/*
|
|
* Find the HKL we are looking for.
|
|
*/
|
|
if (pkl->hkl == hkl) {
|
|
#ifdef DEBUG
|
|
if (pkl->dwFlags & KL_UNLOADED) {
|
|
KdPrint(("NtUserECQueryInputLangChange: pkl->dwFlags & KL_UNLOADED\n"));
|
|
}
|
|
#endif
|
|
/*
|
|
* If the HKL supports the requested Windows codepage,
|
|
* then allow the input language to change.
|
|
*/
|
|
if (pkl->bCharsets & bCharsets) {
|
|
retval = TRUE;
|
|
goto DoneQuery;
|
|
}
|
|
|
|
/*
|
|
* If we are hotkeying forward/backward through HKLs, get set to
|
|
* find an HKL that supports the requested codepage: we will change
|
|
* to that input language by posting WM_INPUTLANGCHANGEREQUEST
|
|
*/
|
|
if (wParam & LANGCHANGE_FORWARD) {
|
|
pklStart = pkl->pklNext;
|
|
pklStop = pkl->pklPrev;
|
|
break;
|
|
} else if (wParam & LANGCHANGE_BACKWARD) {
|
|
pklStart = pkl->pklPrev;
|
|
pklStop = pkl->pklNext;
|
|
break;
|
|
} else {
|
|
/*
|
|
* Not rotating forwards/backwards through HKLs, so just deny
|
|
* the input language change now.
|
|
*/
|
|
retval = FALSE;
|
|
goto DoneQuery;
|
|
}
|
|
}
|
|
pkl = pkl->pklNext;
|
|
} while (pkl != pklStop);
|
|
|
|
ValidateHWND(pwnd, hwnd);
|
|
|
|
/*
|
|
* We are hotkeying forward/backward through HKLs.
|
|
* Find the next loaded HKL that supports the system's Windows codepage,
|
|
* then request the input language change accordingly.
|
|
*
|
|
* BUG BUG : Apparently, Win95 restricts this to ANSI_CHARSET (and
|
|
* indicates that the HKL can be used with the system charset by
|
|
* setting wParam TRUE): NT shouldn't really have this restriction.
|
|
*/
|
|
for (pkl = pklStart;
|
|
pkl != pklStop;
|
|
pkl = (wParam & LANGCHANGE_FORWARD ? pkl->pklNext: pkl->pklPrev)) {
|
|
if (pkl->dwFlags & KL_UNLOADED) {
|
|
continue;
|
|
}
|
|
if (pkl->bCharsets & bCharsets) {
|
|
_PostMessage(pwnd, WM_INPUTLANGCHANGEREQUEST, 1,
|
|
(LPARAM)pkl->hkl);
|
|
break;
|
|
}
|
|
}
|
|
|
|
retval = FALSE;
|
|
|
|
DoneQuery:
|
|
TRACE("NtUserECQueryInputLangChange");
|
|
ENDRECV();
|
|
}
|
|
|
|
|
|
NTSTATUS NtUserGetMediaChangeEvents(
|
|
IN ULONG cMaxEvents,
|
|
OUT HANDLE phEvent[] OPTIONAL,
|
|
OUT PULONG pcEventsNeeded)
|
|
{
|
|
ULONG i;
|
|
ULONG cdRomCount;
|
|
HANDLE hMediaEvent;
|
|
PCONFIGURATION_INFORMATION pCI;
|
|
UNICODE_STRING ustrMediaChange;
|
|
WCHAR szEventName[64];
|
|
|
|
BEGINRECV(NTSTATUS, STATUS_UNSUCCESSFUL);
|
|
|
|
UserAssert( pcEventsNeeded );
|
|
|
|
/*
|
|
* Only allow CSR to make this call
|
|
*/
|
|
if (PpiCurrent()->Process != gpepCSRSS) {
|
|
MSGERROR();
|
|
}
|
|
|
|
try {
|
|
pCI = IoGetConfigurationInformation();
|
|
cdRomCount = pCI->CdRomCount;
|
|
/*
|
|
* Probe the arguments
|
|
*/
|
|
ProbeForWriteUlong(pcEventsNeeded);
|
|
*pcEventsNeeded = 0;
|
|
if (phEvent) {
|
|
ProbeForWrite(phEvent, cMaxEvents*sizeof(HANDLE), sizeof(DWORD));
|
|
|
|
/*
|
|
* Determine the number of CD-ROM devices in the system (this number
|
|
* will never change). For each of these CD-ROM devices create a
|
|
* notification event so we know when the media will change.
|
|
*/
|
|
|
|
|
|
for (i=0; i < cdRomCount && i < cMaxEvents; i++) {
|
|
/*
|
|
* Create the string \\Device\MediaChangeEvent#
|
|
*/
|
|
wsprintfW(szEventName, L"\\Device\\MediaChangeEvent%d", i);
|
|
RtlInitUnicodeString(&ustrMediaChange, szEventName);
|
|
|
|
/*
|
|
* Initialize the CD-ROM \device\MediaChangeEvent. This event allows us
|
|
* to know when the media on a CD-ROM is changed.
|
|
*/
|
|
IoCreateSynchronizationEvent(&ustrMediaChange, &hMediaEvent);
|
|
UserAssert(hMediaEvent != NULL);
|
|
*phEvent++ = hMediaEvent;
|
|
}
|
|
*pcEventsNeeded = i;
|
|
} else {
|
|
*pcEventsNeeded = cdRomCount;
|
|
}
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = STATUS_SUCCESS;
|
|
|
|
ENDRECV();
|
|
TRACE("NtUserGetMediaChangeEvents");
|
|
}
|
|
|
|
|
|
#ifdef FE_IME
|
|
|
|
HIMC NtUserCreateInputContext(
|
|
IN DWORD dwClientImcData)
|
|
{
|
|
BEGINRECV(HIMC, (HIMC)NULL);
|
|
|
|
if (dwClientImcData == 0) {
|
|
RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid hMemClientIC parameter");
|
|
MSGERROR();
|
|
}
|
|
|
|
retval = (HIMC)xxxCreateInputContext(dwClientImcData);
|
|
|
|
retval = (HIMC)PtoH((PVOID)retval);
|
|
|
|
TRACE("NtUserCreateInputContext");
|
|
ENDRECV();
|
|
}
|
|
|
|
|
|
BOOL NtUserDestroyInputContext(
|
|
IN HIMC hImc)
|
|
{
|
|
PIMC pImc;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHIMC(pImc, hImc);
|
|
|
|
retval = DestroyInputContext(pImc);
|
|
|
|
TRACE("NtUserDestroyInputContext");
|
|
ENDRECV();
|
|
}
|
|
|
|
|
|
HIMC NtUserAssociateInputContext(
|
|
IN HWND hwnd,
|
|
IN HIMC hImc)
|
|
{
|
|
PIMC pImc;
|
|
|
|
BEGINRECV_HWND(HIMC, (HIMC)NULL, hwnd);
|
|
|
|
ValidateHIMCOPT(pImc, hImc);
|
|
|
|
retval = AssociateInputContext(pwnd, pImc);
|
|
|
|
TRACE("NtUserAssociateInputContext");
|
|
ENDRECV_HWND();
|
|
}
|
|
|
|
|
|
BOOL NtUserUpdateInputContext(
|
|
IN HIMC hImc,
|
|
IN UPDATEINPUTCONTEXTCLASS UpdateType,
|
|
IN DWORD UpdateValue)
|
|
{
|
|
PIMC pImc;
|
|
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
ValidateHIMC(pImc, hImc);
|
|
|
|
retval = UpdateInputContext(pImc, UpdateType, UpdateValue);
|
|
|
|
TRACE("NtUserUpdateInputContext");
|
|
ENDRECV();
|
|
}
|
|
|
|
|
|
DWORD NtUserQueryInputContext(
|
|
IN HIMC hImc,
|
|
IN INPUTCONTEXTINFOCLASS InputContextInfo)
|
|
{
|
|
PTHREADINFO ptiImc;
|
|
PIMC pImc;
|
|
|
|
BEGINRECV_SHARED(DWORD, 0);
|
|
|
|
ValidateHIMC(pImc, hImc);
|
|
|
|
ptiImc = GETPTI(pImc);
|
|
|
|
switch (InputContextInfo) {
|
|
case InputContextProcess:
|
|
retval = (DWORD)ptiImc->Thread->Cid.UniqueProcess;
|
|
break;
|
|
|
|
case InputContextThread:
|
|
retval = (DWORD)ptiImc->Thread->Cid.UniqueThread;
|
|
break;
|
|
}
|
|
|
|
ENDRECV();
|
|
}
|
|
|
|
NTSTATUS NtUserBuildHimcList(
|
|
IN DWORD idThread,
|
|
IN UINT cHimcMax,
|
|
OUT HIMC *phimcFirst,
|
|
OUT PUINT pcHimcNeeded)
|
|
{
|
|
PTHREADINFO pti;
|
|
UINT cHimcNeeded;
|
|
|
|
BEGINRECV(NTSTATUS, STATUS_UNSUCCESSFUL);
|
|
|
|
if (idThread) {
|
|
pti = PtiFromThreadId(idThread);
|
|
if (pti == NULL || pti->rpdesk == NULL)
|
|
MSGERROR();
|
|
} else {
|
|
pti = NULL;
|
|
}
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForWrite(phimcFirst, cHimcMax * sizeof(HIMC), sizeof(DWORD));
|
|
ProbeForWriteUlong(pcHimcNeeded);
|
|
|
|
cHimcNeeded = BuildHimcList(pti, cHimcMax, phimcFirst);
|
|
|
|
if (cHimcNeeded <= cHimcMax) {
|
|
retval = STATUS_SUCCESS;
|
|
} else {
|
|
retval = STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
*pcHimcNeeded = cHimcNeeded;
|
|
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserBuildHimcList");
|
|
ENDRECV();
|
|
}
|
|
|
|
|
|
BOOL NtUserGetImeInfoEx(
|
|
IN PIMEINFOEX piiex,
|
|
IN IMEINFOEXCLASS SearchType)
|
|
{
|
|
BEGINRECV_SHARED(BOOL, FALSE);
|
|
|
|
try {
|
|
ProbeForWrite(piiex, sizeof(*piiex), sizeof(BYTE));
|
|
|
|
retval = GetImeInfoEx(
|
|
_GetProcessWindowStation(NULL),
|
|
piiex,
|
|
SearchType);
|
|
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserGetImeInfoEx");
|
|
ENDRECV();
|
|
}
|
|
|
|
|
|
BOOL NtUserSetImeInfoEx(
|
|
IN PIMEINFOEX piiex)
|
|
{
|
|
BEGINRECV(BOOL, FALSE);
|
|
|
|
/*
|
|
* Probe arguments
|
|
*/
|
|
try {
|
|
ProbeForRead(piiex, sizeof(*piiex), sizeof(BYTE));
|
|
|
|
retval = SetImeInfoEx(
|
|
_GetProcessWindowStation(NULL),
|
|
piiex);
|
|
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
|
|
TRACE("NtUserSetImeInfoEx");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserGetImeHotKey(
|
|
IN DWORD dwID,
|
|
OUT PUINT puModifiers,
|
|
OUT PUINT puVKey,
|
|
OUT LPHKL phkl)
|
|
{
|
|
BEGINRECV(BOOL, FALSE);
|
|
try {
|
|
ProbeForWriteUlong(((PULONG)puModifiers));
|
|
ProbeForWriteUlong(((PULONG)puVKey));
|
|
if (ARGUMENT_PRESENT(phkl)) {
|
|
ProbeForWriteHandle((PHANDLE)phkl);
|
|
}
|
|
retval = GetImeHotKey( dwID, puModifiers, puVKey, phkl );
|
|
|
|
} except (StubExceptionHandler()) {
|
|
MSGERROR();
|
|
}
|
|
TRACE("NtUserGetImeHotKey");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSetImeHotKey(
|
|
DWORD dwID,
|
|
UINT uModifiers,
|
|
UINT uVKey,
|
|
HKL hkl,
|
|
DWORD dwFlags)
|
|
{
|
|
BEGINRECV(BOOL, FALSE);
|
|
retval = SetImeHotKey( dwID, uModifiers, uVKey, hkl, dwFlags );
|
|
TRACE("NtUserSetImeHotKey");
|
|
ENDRECV();
|
|
}
|
|
|
|
BOOL NtUserSetImeOwnerWindow(
|
|
IN HWND hwndIme,
|
|
IN HWND hwndFocus)
|
|
{
|
|
PTHREADINFO ptiImeWnd;
|
|
PWND pwndFocus;
|
|
PWND pwndTopLevel;
|
|
PWND pwndT;
|
|
|
|
BEGINRECV_HWND(BOOL, FALSE, hwndIme);
|
|
|
|
ValidateHWNDOPT(pwndFocus, hwndFocus);
|
|
|
|
if (pwndFocus != NULL) {
|
|
|
|
if (TestCF(pwndFocus, CFIME) ||
|
|
pwndFocus->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME]) {
|
|
RIPMSG0(RIP_WARNING, "Focus window should not be an IME/UI window!!");
|
|
MSGERROR();
|
|
}
|
|
|
|
/*
|
|
* Child window cannot be an owner window.
|
|
*/
|
|
pwndTopLevel = pwndT = GetTopLevelWindow(pwndFocus);
|
|
|
|
while (pwndT != NULL) {
|
|
if (pwndT->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME]) {
|
|
RIPMSG0(RIP_WARNING,
|
|
"The owner of focus window should not be an IME window!!");
|
|
pwndTopLevel = NULL;
|
|
break;
|
|
}
|
|
pwndT = pwndT->spwndOwner;
|
|
}
|
|
|
|
Lock(&pwnd->spwndOwner, pwndTopLevel);
|
|
ImeCheckTopmost(pwnd);
|
|
}
|
|
else {
|
|
ptiImeWnd = GETPTI(pwnd);
|
|
if (ptiImeWnd->pq->spwndActive == NULL) {
|
|
ImeSetFutureOwner(pwnd, pwnd->spwndOwner);
|
|
ImeCheckTopmost(pwnd);
|
|
}
|
|
else if (pwnd->spwndOwner != ptiImeWnd->pq->spwndActive) {
|
|
Lock(&pwnd->spwndOwner, ptiImeWnd->pq->spwndActive);
|
|
ImeCheckTopmost(pwnd);
|
|
}
|
|
}
|
|
|
|
retval = TRUE;
|
|
|
|
TRACE("NtUserSetImeNewOwner");
|
|
ENDRECV();
|
|
}
|
|
|
|
|
|
VOID NtUserSetThreadLayoutHandles(
|
|
IN HKL hklNew,
|
|
IN HKL hklOld)
|
|
{
|
|
PTHREADINFO ptiCurrent;
|
|
PKL pklNew;
|
|
|
|
BEGINRECV_VOID();
|
|
|
|
ptiCurrent = PtiCurrent();
|
|
|
|
if (ptiCurrent->spklActive != NULL && ptiCurrent->spklActive->hkl != hklOld)
|
|
MSGERROR_VOID();
|
|
|
|
if ((pklNew = HKLtoPKL(hklNew)) == NULL)
|
|
MSGERROR_VOID();
|
|
|
|
/*
|
|
* hklPrev is only used for IME, non-IME toggle hotkey.
|
|
* The purpose we remember hklPrev is to jump from
|
|
* non-IME keyboard layout to the most recently used
|
|
* IME layout, or to jump from an IME layout to
|
|
* the most recently used non-IME layout. Therefore
|
|
* piti->hklPrev is updated only when [ IME -> non-IME ]
|
|
* or [ non-IME -> IME ] transition is happened.
|
|
*/
|
|
if (IS_IME_KBDLAYOUT(hklNew) ^ IS_IME_KBDLAYOUT(hklOld))
|
|
ptiCurrent->hklPrev = hklOld;
|
|
|
|
Lock(&ptiCurrent->spklActive, pklNew);
|
|
|
|
TRACEVOID("NtUserSetThreadLayoutHandles");
|
|
ENDRECV_VOID();
|
|
}
|
|
|
|
#endif
|