diff --git a/reactos/subsystems/win32/csrss/win32csr/dllmain.c b/reactos/subsystems/win32/csrss/win32csr/dllmain.c index dcaa24faab0..e758ad6144c 100644 --- a/reactos/subsystems/win32/csrss/win32csr/dllmain.c +++ b/reactos/subsystems/win32/csrss/win32csr/dllmain.c @@ -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; } diff --git a/reactos/subsystems/win32/win32k/ntuser/input.c b/reactos/subsystems/win32/win32k/ntuser/input.c index 5b5947fec4c..c8ea14c1d4d 100644 --- a/reactos/subsystems/win32/win32k/ntuser/input.c +++ b/reactos/subsystems/win32/win32k/ntuser/input.c @@ -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; diff --git a/reactos/subsystems/win32/win32k/ntuser/keyboard.c b/reactos/subsystems/win32/win32k/ntuser/keyboard.c index aec40d0066b..3b129a2d5e7 100644 --- a/reactos/subsystems/win32/win32k/ntuser/keyboard.c +++ b/reactos/subsystems/win32/win32k/ntuser/keyboard.c @@ -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; diff --git a/reactos/subsystems/win32/win32k/ntuser/simplecall.c b/reactos/subsystems/win32/win32k/ntuser/simplecall.c index e2828414826..e6039e6446c 100644 --- a/reactos/subsystems/win32/win32k/ntuser/simplecall.c +++ b/reactos/subsystems/win32/win32k/ntuser/simplecall.c @@ -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);