[WIN32K/CSRSS]

- Spawn keyboard and mouse input threads in csrss user-mode process so they are valid Win32 threads and have TEB

svn path=/trunk/; revision=54125
This commit is contained in:
Rafal Harabien 2011-10-13 22:22:49 +00:00
parent b4721b55d7
commit 81a9b72e90
4 changed files with 160 additions and 44 deletions

View file

@ -178,6 +178,16 @@ PrivateCsrssManualGuiCheck(LONG Check)
NtUserCallOneParam(Check, ONEPARAM_ROUTINE_CSRSS_GUICHECK);
}
DWORD
WINAPI
CreateSystemThreads(PVOID pParam)
{
NtUserCallOneParam((DWORD_PTR)pParam, ONEPARAM_ROUTINE_CREATESYSTEMTHREADS);
DPRINT1("This thread should not terminate!\n");
DbgBreakPoint();
return 0;
}
BOOL WINAPI
Win32CsrInitialization(PCSRSS_API_DEFINITION *ApiDefinitions,
PCSRPLUGIN_SERVER_PROCS ServerProcs,
@ -200,6 +210,33 @@ Win32CsrInitialization(PCSRSS_API_DEFINITION *ApiDefinitions,
RtlInitializeCriticalSection(&Win32CsrDefineDosDeviceCritSec);
InitializeListHead(&DosDeviceHistory);
{
HANDLE ServerThread;
CLIENT_ID ClientId;
NTSTATUS Status;
Status = RtlCreateUserThread(NtCurrentProcess(), NULL, TRUE, 0, 0, 0, (PTHREAD_START_ROUTINE)CreateSystemThreads, (PVOID)0, &ServerThread, &ClientId);
if (NT_SUCCESS(Status))
{
NtResumeThread(ServerThread, NULL);
NtClose(ServerThread);
}
else
DPRINT1("Cannot start keyboard thread!\n");
Status = RtlCreateUserThread(NtCurrentProcess(), NULL, TRUE, 0, 0, 0, (PTHREAD_START_ROUTINE)CreateSystemThreads, (PVOID)1, &ServerThread, &ClientId);
if (NT_SUCCESS(Status))
{
NtResumeThread(ServerThread, NULL);
NtClose(ServerThread);
}
else
DPRINT1("Cannot start mouse thread!\n");
DbgBreakPoint();
}
return TRUE;
}

View file

@ -24,10 +24,6 @@ HANDLE ghKeyboardDevice;
static DWORD LastInputTick = 0;
static HANDLE MouseDeviceHandle;
static HANDLE MouseThreadHandle;
static CLIENT_ID MouseThreadId;
static HANDLE KeyboardThreadHandle;
static CLIENT_ID KeyboardThreadId;
static HANDLE RawInputThreadHandle;
static CLIENT_ID RawInputThreadId;
static KEVENT InputThreadsStart;
@ -212,7 +208,7 @@ MouseThreadMain(PVOID StartContext)
DueTime.QuadPart = (LONGLONG)(-10000000);
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &DueTime);
Status = NtOpenFile(&MouseDeviceHandle,
Status = ZwOpenFile(&MouseDeviceHandle,
FILE_ALL_ACCESS,
&MouseObjectAttributes,
&Iosb,
@ -221,12 +217,12 @@ MouseThreadMain(PVOID StartContext)
} while (!NT_SUCCESS(Status));
/* Need to setup basic win32k for this thread to process WH_MOUSE_LL messages. */
Status = Win32kInitWin32Thread(PsGetCurrentThread());
/*Status = Win32kInitWin32Thread(PsGetCurrentThread());
if (!NT_SUCCESS(Status))
{
ERR("Win32K: Failed making mouse thread a win32 thread.\n");
return; //(Status);
}
}*/
ptiMouse = PsGetCurrentThreadWin32Thread();
ptiMouse->TIF_flags |= TIF_SYSTEMTHREAD;
@ -249,7 +245,7 @@ MouseThreadMain(PVOID StartContext)
TRACE("Mouse Input Thread Starting...\n");
/*FIXME: Does mouse attributes need to be used for anything */
Status = NtDeviceIoControlFile(MouseDeviceHandle,
Status = ZwDeviceIoControlFile(MouseDeviceHandle,
NULL,
NULL,
NULL,
@ -268,7 +264,7 @@ MouseThreadMain(PVOID StartContext)
while(InputThreadsRunning)
{
MOUSE_INPUT_DATA MouseInput;
Status = NtReadFile(MouseDeviceHandle,
Status = ZwReadFile(MouseDeviceHandle,
NULL,
NULL,
NULL,
@ -304,7 +300,7 @@ MouseThreadMain(PVOID StartContext)
}
}
static VOID APIENTRY
VOID NTAPI
KeyboardThreadMain(PVOID StartContext)
{
UNICODE_STRING KeyboardDeviceName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardClass0");
@ -321,11 +317,11 @@ KeyboardThreadMain(PVOID StartContext)
{
LARGE_INTEGER DueTime;
KEVENT Event;
DueTime.QuadPart = (LONGLONG)(-10000000);
DueTime.QuadPart = (LONGLONG)(-100000000);
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &DueTime);
Status = NtOpenFile(&ghKeyboardDevice,
FILE_ALL_ACCESS,
Status = ZwOpenFile(&ghKeyboardDevice,
FILE_READ_ACCESS,//FILE_ALL_ACCESS,
&KeyboardObjectAttributes,
&Iosb,
0,
@ -343,12 +339,12 @@ KeyboardThreadMain(PVOID StartContext)
the message from the system message queue would be responsible
for WH_KEYBOARD_LL processing and we wouldn't need this thread
to be a win32 thread. */
Status = Win32kInitWin32Thread(PsGetCurrentThread());
/*Status = Win32kInitWin32Thread(PsGetCurrentThread());
if (!NT_SUCCESS(Status))
{
ERR("Win32K: Failed making keyboard thread a win32 thread.\n");
return; //(Status);
}
}*/
ptiKeyboard = PsGetCurrentThreadWin32Thread();
ptiKeyboard->TIF_flags |= TIF_SYSTEMTHREAD;
@ -379,7 +375,7 @@ KeyboardThreadMain(PVOID StartContext)
TRACE("KeyInput @ %08x\n", &KeyInput);
Status = NtReadFile (ghKeyboardDevice,
Status = ZwReadFile (ghKeyboardDevice,
NULL,
NULL,
NULL,
@ -479,7 +475,7 @@ RawInputThreadMain(PVOID StartContext)
//
for(;;)
{
TRACE( "Raw Input Thread Waiting for start event\n" );
TRACE("Raw Input Thread Waiting for start event\n");
Status = KeWaitForMultipleObjects( 2,
Objects,
@ -489,13 +485,30 @@ RawInputThreadMain(PVOID StartContext)
TRUE,
NULL,
NULL);
TRACE( "Raw Input Thread Starting...\n" );
TRACE("Raw Input Thread Starting...\n");
ProcessTimers();
}
ERR("Raw Input Thread Exit!\n");
}
DWORD NTAPI
CreateSystemThreads(UINT Type)
{
UserLeave();
switch (Type)
{
case 0: KeyboardThreadMain(NULL); break;
case 1: MouseThreadMain(NULL); break;
default: ERR("Wrong type: %x\n", Type);
}
UserEnterShared();
return 0;
}
INIT_FUNCTION
NTSTATUS
NTAPI
@ -532,30 +545,6 @@ InitInputImpl(VOID)
ERR("Win32K: Failed to create raw thread.\n");
}
Status = PsCreateSystemThread(&KeyboardThreadHandle,
THREAD_ALL_ACCESS,
NULL,
NULL,
&KeyboardThreadId,
KeyboardThreadMain,
NULL);
if (!NT_SUCCESS(Status))
{
ERR("Win32K: Failed to create keyboard thread.\n");
}
Status = PsCreateSystemThread(&MouseThreadHandle,
THREAD_ALL_ACCESS,
NULL,
NULL,
&MouseThreadId,
MouseThreadMain,
NULL);
if (!NT_SUCCESS(Status))
{
ERR("Win32K: Failed to create mouse thread.\n");
}
InputThreadsRunning = TRUE;
KeSetEvent(&InputThreadsStart, IO_NO_INCREMENT, FALSE);
@ -588,7 +577,7 @@ IntBlockInput(PTHREADINFO pti, BOOL BlockIt)
* e.g. services running in the service window station cannot block input
*/
if(!ThreadHasInputAccess(pti) ||
!IntIsActiveDesktop(pti->rpdesk))
!IntIsActiveDesktop(pti->rpdesk))
{
EngSetLastError(ERROR_ACCESS_DENIED);
return FALSE;

View file

@ -671,6 +671,83 @@ co_CallLowLevelKeyboardHook(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjec
return co_HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, uMsg, (LPARAM)&KbdHookData);
}
/*
* SnapWindow
*
* Saves snapshot of specified window or whole screen in the clipboard
*/
static VOID
SnapWindow(HWND hWnd)
{
HBITMAP hbm = NULL, hbmOld;
HDC hdc = NULL, hdcMem;
SETCLIPBDATA scd;
INT cx, cy;
PWND pWnd = NULL;
TRACE("SnapWindow(%p)\n", hWnd);
/* If no windows is given, make snapshot of desktop window */
if (!hWnd)
hWnd = IntGetDesktopWindow();
pWnd = UserGetWindowObject(hWnd);
if (!pWnd)
{
ERR("Invalid window\n");
goto cleanup;
}
hdc = UserGetDCEx(pWnd, NULL, DCX_USESTYLE | DCX_WINDOW);
if (!hdc)
{
ERR("UserGetDCEx failed!\n");
goto cleanup;
}
cx = pWnd->rcWindow.right - pWnd->rcWindow.left;
cy = pWnd->rcWindow.bottom - pWnd->rcWindow.top;
hbm = NtGdiCreateCompatibleBitmap(hdc, cx, cy);
if (!hbm)
{
ERR("NtGdiCreateCompatibleBitmap failed!\n");
goto cleanup;
}
hdcMem = NtGdiCreateCompatibleDC(hdc);
if (!hdcMem)
{
ERR("NtGdiCreateCompatibleDC failed!\n");
goto cleanup;
}
hbmOld = NtGdiSelectBitmap(hdcMem, hbm);
NtGdiBitBlt(hdcMem, 0, 0, cx, cy, hdc, 0, 0, SRCCOPY, 0, 0);
NtGdiSelectBitmap(hdcMem, hbmOld);
IntGdiDeleteDC(hdcMem, FALSE);
/* Save snapshot in clipboard */
if (UserOpenClipboard(NULL))
{
UserEmptyClipboard();
scd.fIncSerialNumber = TRUE;
scd.fGlobalHandle = FALSE;
if (UserSetClipboardData(CF_BITMAP, hbm, &scd))
{
/* Bitmap is managed by system now */
hbm = NULL;
}
UserCloseClipboard();
}
cleanup:
if (hbm)
GreDeleteObject(hbm);
if (hdc)
UserReleaseDC(hWnd, hdc, FALSE);
}
/*
* UserSendKeyboardInput
*
@ -765,7 +842,18 @@ ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD d
/* If we have a focus queue, post a keyboard message */
pFocusQueue = IntGetFocusMessageQueue();
if (pFocusQueue && bPostMsg)
if (bIsDown && wVk == VK_SNAPSHOT)
{
if (pFocusQueue &&
IS_KEY_DOWN(gafAsyncKeyState, VK_MENU) &&
!IS_KEY_DOWN(gafAsyncKeyState, VK_CONTROL))
{
SnapWindow(pFocusQueue->FocusWindow);
}
else
SnapWindow(NULL);
}
else if (pFocusQueue && bPostMsg)
{
/* Init message */
Msg.hwnd = pFocusQueue->FocusWindow;

View file

@ -378,6 +378,8 @@ NtUserCallOneParam(
case ONEPARAM_ROUTINE_MESSAGEBEEP:
RETURN ( UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_MESSAGE_BEEP, Param) );
/* TODO: Implement sound sentry */
case ONEPARAM_ROUTINE_CREATESYSTEMTHREADS:
RETURN(CreateSystemThreads(Param));
}
ERR("Calling invalid routine number 0x%x in NtUserCallOneParam(), Param=0x%x\n",
Routine, Param);