mirror of
https://github.com/reactos/reactos.git
synced 2024-11-01 04:11:30 +00:00
83e1193fb2
Fixes random failures on x64.
991 lines
18 KiB
C
991 lines
18 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS Win32k subsystem
|
|
* PURPOSE: Native User stubs
|
|
* FILE: win32ss/user/ntuser/ntstubs.c
|
|
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
|
*/
|
|
|
|
#include <win32k.h>
|
|
DBG_DEFAULT_CHANNEL(UserMisc);
|
|
|
|
//
|
|
// Works like BitBlt, http://msdn.microsoft.com/en-us/library/ms532278(VS.85).aspx
|
|
//
|
|
BOOL
|
|
APIENTRY
|
|
NtUserBitBltSysBmp(
|
|
HDC hdc,
|
|
INT nXDest,
|
|
INT nYDest,
|
|
INT nWidth,
|
|
INT nHeight,
|
|
INT nXSrc,
|
|
INT nYSrc,
|
|
DWORD dwRop )
|
|
{
|
|
BOOL Ret = FALSE;
|
|
UserEnterExclusive();
|
|
|
|
Ret = NtGdiBitBlt( hdc,
|
|
nXDest,
|
|
nYDest,
|
|
nWidth,
|
|
nHeight,
|
|
hSystemBM,
|
|
nXSrc,
|
|
nYSrc,
|
|
dwRop,
|
|
0,
|
|
0);
|
|
|
|
UserLeave();
|
|
return Ret;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserDragObject(
|
|
HWND hwnd1,
|
|
HWND hwnd2,
|
|
UINT u1,
|
|
DWORD dw1,
|
|
HCURSOR hc1
|
|
)
|
|
{
|
|
STUB
|
|
|
|
return 0;
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtUserDrawAnimatedRects(
|
|
HWND hwnd,
|
|
INT idAni,
|
|
RECT *lprcFrom,
|
|
RECT *lprcTo)
|
|
{
|
|
STUB
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserEvent(
|
|
DWORD Unknown0)
|
|
{
|
|
STUB
|
|
|
|
return 0;
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtUserGetAltTabInfo(
|
|
HWND hwnd,
|
|
INT iItem,
|
|
PALTTABINFO pati,
|
|
LPWSTR pszItemText,
|
|
UINT cchItemText,
|
|
BOOL Ansi)
|
|
{
|
|
STUB
|
|
|
|
return 0;
|
|
}
|
|
|
|
NTSTATUS
|
|
APIENTRY
|
|
NtUserInitializeClientPfnArrays(
|
|
PPFNCLIENT pfnClientA,
|
|
PPFNCLIENT pfnClientW,
|
|
PPFNCLIENTWORKER pfnClientWorker,
|
|
HINSTANCE hmodUser)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
TRACE("Enter NtUserInitializeClientPfnArrays User32 0x%p\n", hmodUser);
|
|
|
|
if (ClientPfnInit) return Status;
|
|
|
|
UserEnterExclusive();
|
|
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForRead( pfnClientA, sizeof(PFNCLIENT), 1);
|
|
ProbeForRead( pfnClientW, sizeof(PFNCLIENT), 1);
|
|
ProbeForRead( pfnClientWorker, sizeof(PFNCLIENTWORKER), 1);
|
|
RtlCopyMemory(&gpsi->apfnClientA, pfnClientA, sizeof(PFNCLIENT));
|
|
RtlCopyMemory(&gpsi->apfnClientW, pfnClientW, sizeof(PFNCLIENT));
|
|
RtlCopyMemory(&gpsi->apfnClientWorker, pfnClientWorker, sizeof(PFNCLIENTWORKER));
|
|
|
|
//// FIXME: HAX! Temporary until server side is finished.
|
|
//// Copy the client side procs for now.
|
|
RtlCopyMemory(&gpsi->aStoCidPfn, pfnClientW, sizeof(gpsi->aStoCidPfn));
|
|
|
|
hModClient = hmodUser;
|
|
ClientPfnInit = TRUE;
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status =_SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("Failed reading Client Pfns from user space.\n");
|
|
SetLastNtError(Status);
|
|
}
|
|
|
|
UserLeave();
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserInitTask(
|
|
DWORD Unknown0,
|
|
DWORD Unknown1,
|
|
DWORD Unknown2,
|
|
DWORD Unknown3,
|
|
DWORD Unknown4,
|
|
DWORD Unknown5,
|
|
DWORD Unknown6,
|
|
DWORD Unknown7,
|
|
DWORD Unknown8,
|
|
DWORD Unknown9,
|
|
DWORD Unknown10,
|
|
DWORD Unknown11)
|
|
{
|
|
STUB
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserMNDragLeave(VOID)
|
|
{
|
|
STUB
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserMNDragOver(
|
|
DWORD Unknown0,
|
|
DWORD Unknown1)
|
|
{
|
|
STUB
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserModifyUserStartupInfoFlags(
|
|
DWORD Unknown0,
|
|
DWORD Unknown1)
|
|
{
|
|
STUB
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserQueryUserCounters(
|
|
DWORD Unknown0,
|
|
DWORD Unknown1,
|
|
DWORD Unknown2,
|
|
DWORD Unknown3,
|
|
DWORD Unknown4)
|
|
{
|
|
STUB
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserRegisterTasklist(
|
|
DWORD Unknown0)
|
|
{
|
|
STUB
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserSetConsoleReserveKeys(
|
|
DWORD Unknown0,
|
|
DWORD Unknown1)
|
|
{
|
|
STUB
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserSetDbgTag(
|
|
DWORD Unknown0,
|
|
DWORD Unknown1)
|
|
{
|
|
STUB;
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserSetDbgTagCount(
|
|
DWORD Unknown0)
|
|
{
|
|
STUB;
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserSetRipFlags(
|
|
DWORD Unknown0)
|
|
{
|
|
STUB;
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserDbgWin32HeapFail(
|
|
DWORD Unknown0,
|
|
DWORD Unknown1)
|
|
{
|
|
STUB
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserDbgWin32HeapStat(
|
|
DWORD Unknown0,
|
|
DWORD Unknown1)
|
|
{
|
|
STUB
|
|
|
|
return 0;
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtUserSetSysColors(
|
|
int cElements,
|
|
IN CONST INT *lpaElements,
|
|
IN CONST COLORREF *lpaRgbValues,
|
|
FLONG Flags)
|
|
{
|
|
DWORD Ret = TRUE;
|
|
|
|
if (cElements == 0)
|
|
return TRUE;
|
|
|
|
/* We need this check to prevent overflow later */
|
|
if ((ULONG)cElements >= 0x40000000)
|
|
{
|
|
EngSetLastError(ERROR_NOACCESS);
|
|
return FALSE;
|
|
}
|
|
|
|
UserEnterExclusive();
|
|
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForRead(lpaElements, cElements * sizeof(INT), 1);
|
|
ProbeForRead(lpaRgbValues, cElements * sizeof(COLORREF), 1);
|
|
|
|
IntSetSysColors(cElements, lpaElements, lpaRgbValues);
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
SetLastNtError(_SEH2_GetExceptionCode());
|
|
Ret = FALSE;
|
|
}
|
|
_SEH2_END;
|
|
|
|
if (Ret)
|
|
{
|
|
UserSendNotifyMessage(HWND_BROADCAST, WM_SYSCOLORCHANGE, 0, 0);
|
|
|
|
UserRedrawDesktop();
|
|
}
|
|
|
|
UserLeave();
|
|
return Ret;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserUpdateInstance(
|
|
DWORD Unknown0,
|
|
DWORD Unknown1,
|
|
DWORD Unknown2)
|
|
{
|
|
STUB
|
|
|
|
return 0;
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtUserUserHandleGrantAccess(
|
|
IN HANDLE hUserHandle,
|
|
IN HANDLE hJob,
|
|
IN BOOL bGrant)
|
|
{
|
|
STUB
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserWaitForMsgAndEvent(
|
|
DWORD Unknown0)
|
|
{
|
|
STUB
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserWin32PoolAllocationStats(
|
|
DWORD Unknown0,
|
|
DWORD Unknown1,
|
|
DWORD Unknown2,
|
|
DWORD Unknown3,
|
|
DWORD Unknown4,
|
|
DWORD Unknown5)
|
|
{
|
|
STUB
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserYieldTask(VOID)
|
|
{
|
|
STUB
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserGetRawInputBuffer(
|
|
PRAWINPUT pData,
|
|
PUINT pcbSize,
|
|
UINT cbSizeHeader)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserGetRawInputData(
|
|
HRAWINPUT hRawInput,
|
|
UINT uiCommand,
|
|
LPVOID pData,
|
|
PUINT pcbSize,
|
|
UINT cbSizeHeader)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserGetRawInputDeviceInfo(
|
|
HANDLE hDevice,
|
|
UINT uiCommand,
|
|
LPVOID pData,
|
|
PUINT pcbSize
|
|
)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserGetRawInputDeviceList(
|
|
PRAWINPUTDEVICELIST pRawInputDeviceList,
|
|
PUINT puiNumDevices,
|
|
UINT cbSize)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserGetRegisteredRawInputDevices(
|
|
PRAWINPUTDEVICE pRawInputDevices,
|
|
PUINT puiNumDevices,
|
|
UINT cbSize)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserHardErrorControl(
|
|
DWORD dwUnknown1,
|
|
DWORD dwUnknown2,
|
|
DWORD dwUnknown3)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
BOOL
|
|
NTAPI
|
|
NtUserNotifyProcessCreate(
|
|
HANDLE NewProcessId,
|
|
HANDLE ParentThreadId,
|
|
ULONG dwUnknown,
|
|
ULONG CreateFlags)
|
|
{
|
|
// STUB;
|
|
TRACE("NtUserNotifyProcessCreate is UNIMPLEMENTED\n");
|
|
return FALSE;
|
|
}
|
|
|
|
NTSTATUS
|
|
APIENTRY
|
|
NtUserProcessConnect(
|
|
IN HANDLE ProcessHandle,
|
|
OUT PUSERCONNECT pUserConnect,
|
|
IN ULONG Size)
|
|
{
|
|
NTSTATUS Status;
|
|
PEPROCESS Process = NULL;
|
|
PPROCESSINFO W32Process;
|
|
|
|
TRACE("NtUserProcessConnect\n");
|
|
|
|
if (pUserConnect == NULL ||
|
|
Size != sizeof(*pUserConnect))
|
|
{
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
/* Get the process object the user handle was referencing */
|
|
Status = ObReferenceObjectByHandle(ProcessHandle,
|
|
PROCESS_VM_OPERATION,
|
|
*PsProcessType,
|
|
UserMode,
|
|
(PVOID*)&Process,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status)) return Status;
|
|
|
|
UserEnterShared();
|
|
|
|
/* Get Win32 process information */
|
|
W32Process = PsGetProcessWin32Process(Process);
|
|
|
|
_SEH2_TRY
|
|
{
|
|
UINT i;
|
|
|
|
// FIXME: Check that pUserConnect->ulVersion == USER_VERSION;
|
|
// FIXME: Check the value of pUserConnect->dwDispatchCount.
|
|
|
|
ProbeForWrite(pUserConnect, sizeof(*pUserConnect), sizeof(PVOID));
|
|
|
|
// FIXME: Instead of assuming that the mapping of the heap desktop
|
|
// also holds there, we **MUST** create and map instead the shared
|
|
// section! Its client base must be stored in W32Process->pClientBase.
|
|
// What is currently done (ReactOS-specific only), is that within the
|
|
// IntUserHeapCommitRoutine()/MapGlobalUserHeap() routines we assume
|
|
// it's going to be also called early, so that we manually add a very
|
|
// first memory mapping that corresponds to the "global user heap",
|
|
// and that we use instead of a actual win32 "shared USER section"
|
|
// (see slide 29 of https://paper.bobylive.com/Meeting_Papers/BlackHat/USA-2011/BH_US_11_Mandt_win32k_Slides.pdf )
|
|
|
|
pUserConnect->siClient.ulSharedDelta =
|
|
(ULONG_PTR)W32Process->HeapMappings.KernelMapping -
|
|
(ULONG_PTR)W32Process->HeapMappings.UserMapping;
|
|
|
|
#define SERVER_TO_CLIENT(ptr) \
|
|
((PVOID)((ULONG_PTR)ptr - pUserConnect->siClient.ulSharedDelta))
|
|
|
|
ASSERT(gpsi);
|
|
ASSERT(gHandleTable);
|
|
|
|
pUserConnect->siClient.psi = SERVER_TO_CLIENT(gpsi);
|
|
pUserConnect->siClient.aheList = SERVER_TO_CLIENT(gHandleTable);
|
|
pUserConnect->siClient.pDispInfo = NULL;
|
|
|
|
// NOTE: kernel server should also have a SHAREDINFO gSharedInfo;
|
|
// FIXME: These USER window-proc data should be used somehow!
|
|
|
|
pUserConnect->siClient.DefWindowMsgs.maxMsgs = 0;
|
|
pUserConnect->siClient.DefWindowMsgs.abMsgs = NULL;
|
|
pUserConnect->siClient.DefWindowSpecMsgs.maxMsgs = 0;
|
|
pUserConnect->siClient.DefWindowSpecMsgs.abMsgs = NULL;
|
|
|
|
for (i = 0; i < ARRAYSIZE(pUserConnect->siClient.awmControl); ++i)
|
|
{
|
|
pUserConnect->siClient.awmControl[i].maxMsgs = 0;
|
|
pUserConnect->siClient.awmControl[i].abMsgs = NULL;
|
|
}
|
|
#undef SERVER_TO_CLIENT
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END;
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
SetLastNtError(Status);
|
|
|
|
UserLeave();
|
|
|
|
/* Dereference the process object */
|
|
ObDereferenceObject(Process);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
APIENTRY
|
|
NtUserQueryInformationThread(IN HANDLE ThreadHandle,
|
|
IN USERTHREADINFOCLASS ThreadInformationClass,
|
|
OUT PVOID ThreadInformation,
|
|
IN ULONG ThreadInformationLength)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PETHREAD Thread;
|
|
|
|
/* Allow only CSRSS to perform this operation */
|
|
if (PsGetCurrentProcess() != gpepCSRSS)
|
|
return STATUS_ACCESS_DENIED;
|
|
|
|
UserEnterExclusive();
|
|
|
|
/* Get the Thread */
|
|
Status = ObReferenceObjectByHandle(ThreadHandle,
|
|
THREAD_QUERY_INFORMATION,
|
|
*PsThreadType,
|
|
UserMode,
|
|
(PVOID)&Thread,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status)) goto Quit;
|
|
|
|
switch (ThreadInformationClass)
|
|
{
|
|
default:
|
|
{
|
|
STUB;
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ObDereferenceObject(Thread);
|
|
|
|
Quit:
|
|
UserLeave();
|
|
return Status;
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtUserRealInternalGetMessage(
|
|
LPMSG lpMsg,
|
|
HWND hWnd,
|
|
UINT wMsgFilterMin,
|
|
UINT wMsgFilterMax,
|
|
UINT wRemoveMsg,
|
|
BOOL bGMSG)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtUserRealWaitMessageEx(
|
|
DWORD dwWakeMask,
|
|
UINT uTimeout)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtUserRegisterRawInputDevices(
|
|
IN PCRAWINPUTDEVICE pRawInputDevices,
|
|
IN UINT uiNumDevices,
|
|
IN UINT cbSize)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
DWORD APIENTRY
|
|
NtUserResolveDesktopForWOW(DWORD Unknown0)
|
|
{
|
|
STUB
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserSetInformationProcess(
|
|
DWORD dwUnknown1,
|
|
DWORD dwUnknown2,
|
|
DWORD dwUnknown3,
|
|
DWORD dwUnknown4)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
HDESK FASTCALL
|
|
IntGetDesktopObjectHandle(PDESKTOP DesktopObject);
|
|
|
|
NTSTATUS
|
|
APIENTRY
|
|
NtUserSetInformationThread(IN HANDLE ThreadHandle,
|
|
IN USERTHREADINFOCLASS ThreadInformationClass,
|
|
IN PVOID ThreadInformation,
|
|
IN ULONG ThreadInformationLength)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PETHREAD Thread;
|
|
|
|
/* Allow only CSRSS to perform this operation */
|
|
if (PsGetCurrentProcess() != gpepCSRSS)
|
|
return STATUS_ACCESS_DENIED;
|
|
|
|
UserEnterExclusive();
|
|
|
|
/* Get the Thread */
|
|
Status = ObReferenceObjectByHandle(ThreadHandle,
|
|
THREAD_SET_INFORMATION,
|
|
*PsThreadType,
|
|
UserMode,
|
|
(PVOID)&Thread,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status)) goto Quit;
|
|
|
|
switch (ThreadInformationClass)
|
|
{
|
|
case UserThreadInitiateShutdown:
|
|
{
|
|
ULONG CapturedFlags = 0;
|
|
|
|
TRACE("Shutdown initiated\n");
|
|
|
|
if (ThreadInformationLength != sizeof(CapturedFlags))
|
|
{
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
break;
|
|
}
|
|
|
|
/* Capture the caller value */
|
|
Status = STATUS_SUCCESS;
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForWrite(ThreadInformation, sizeof(CapturedFlags), __alignof(CapturedFlags));
|
|
CapturedFlags = *(PULONG)ThreadInformation;
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
_SEH2_YIELD(break);
|
|
}
|
|
_SEH2_END;
|
|
|
|
Status = UserInitiateShutdown(Thread, &CapturedFlags);
|
|
|
|
/* Return the modified value to the caller */
|
|
_SEH2_TRY
|
|
{
|
|
*(PULONG)ThreadInformation = CapturedFlags;
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END;
|
|
|
|
break;
|
|
}
|
|
|
|
case UserThreadEndShutdown:
|
|
{
|
|
NTSTATUS ShutdownStatus;
|
|
|
|
TRACE("Shutdown ended\n");
|
|
|
|
if (ThreadInformationLength != sizeof(ShutdownStatus))
|
|
{
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
break;
|
|
}
|
|
|
|
/* Capture the caller value */
|
|
Status = STATUS_SUCCESS;
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForRead(ThreadInformation, sizeof(ShutdownStatus), __alignof(ShutdownStatus));
|
|
ShutdownStatus = *(NTSTATUS*)ThreadInformation;
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
_SEH2_YIELD(break);
|
|
}
|
|
_SEH2_END;
|
|
|
|
Status = UserEndShutdown(Thread, ShutdownStatus);
|
|
break;
|
|
}
|
|
|
|
case UserThreadCsrApiPort:
|
|
{
|
|
HANDLE CsrPortHandle;
|
|
|
|
|
|
TRACE("Set CSR API Port for Win32k\n");
|
|
if (ThreadInformationLength != sizeof(CsrPortHandle))
|
|
{
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
break;
|
|
}
|
|
|
|
/* Capture the caller value */
|
|
Status = STATUS_SUCCESS;
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForRead(ThreadInformation, sizeof(CsrPortHandle), __alignof(CsrPortHandle));
|
|
CsrPortHandle = *(PHANDLE)ThreadInformation;
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
_SEH2_YIELD(break);
|
|
}
|
|
_SEH2_END;
|
|
|
|
Status = InitCsrApiPort(CsrPortHandle);
|
|
break;
|
|
}
|
|
|
|
case UserThreadUseActiveDesktop:
|
|
{
|
|
HDESK hdesk;
|
|
|
|
if (Thread != PsGetCurrentThread())
|
|
{
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
break;
|
|
}
|
|
|
|
hdesk = IntGetDesktopObjectHandle(gpdeskInputDesktop);
|
|
IntSetThreadDesktop(hdesk, FALSE);
|
|
|
|
break;
|
|
}
|
|
case UserThreadRestoreDesktop:
|
|
{
|
|
if (Thread != PsGetCurrentThread())
|
|
{
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
break;
|
|
}
|
|
|
|
IntSetThreadDesktop(NULL, FALSE);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
STUB;
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ObDereferenceObject(Thread);
|
|
|
|
Quit:
|
|
UserLeave();
|
|
return Status;
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtUserSoundSentry(VOID)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserTestForInteractiveUser(
|
|
DWORD dwUnknown1)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserRemoteConnect(
|
|
DWORD dwUnknown1,
|
|
DWORD dwUnknown2,
|
|
DWORD dwUnknown3)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserRemoteRedrawRectangle(
|
|
DWORD dwUnknown1,
|
|
DWORD dwUnknown2,
|
|
DWORD dwUnknown3,
|
|
DWORD dwUnknown4)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserRemoteRedrawScreen(VOID)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserRemoteStopScreenUpdates(VOID)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtUserCtxDisplayIOCtl(
|
|
DWORD dwUnknown1,
|
|
DWORD dwUnknown2,
|
|
DWORD dwUnknown3)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
BOOL APIENTRY
|
|
NtUserLockWindowUpdate(HWND hWnd)
|
|
{
|
|
STUB;
|
|
return FALSE;
|
|
}
|
|
|
|
DWORD APIENTRY
|
|
NtUserQuerySendMessage(DWORD Unknown0)
|
|
{
|
|
STUB;
|
|
|
|
return 0;
|
|
}
|
|
|
|
BOOL APIENTRY NtUserAddClipboardFormatListener(
|
|
HWND hwnd
|
|
)
|
|
{
|
|
STUB;
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL APIENTRY NtUserRemoveClipboardFormatListener(
|
|
HWND hwnd
|
|
)
|
|
{
|
|
STUB;
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL APIENTRY NtUserGetUpdatedClipboardFormats(
|
|
PUINT lpuiFormats,
|
|
UINT cFormats,
|
|
PUINT pcFormatsOut
|
|
)
|
|
{
|
|
STUB;
|
|
return FALSE;
|
|
}
|
|
|
|
LONG_PTR
|
|
APIENTRY
|
|
NtUserSetClassLongPtr(
|
|
VOID)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
// Yes, I know, these do not belong here, just tell me where to put them
|
|
BOOL
|
|
APIENTRY
|
|
NtGdiMakeObjectXferable(
|
|
_In_ HANDLE hHandle,
|
|
_In_ DWORD dwProcessId)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtGdiMakeObjectUnXferable(
|
|
_In_ HANDLE hHandle)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
APIENTRY
|
|
NtDxEngGetRedirectionBitmap(
|
|
DWORD Unknown0)
|
|
{
|
|
STUB;
|
|
return 0;
|
|
}
|
|
|
|
/* EOF */
|