/* * @implemented */ VOID NTAPI DbgUiRemoteBreakin(VOID) { /* Make sure a debugger is enabled; if so, breakpoint */ if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint(); /* Exit the thread */ RtlExitUserThread(STATUS_SUCCESS); }
/*********************************************************************** * ExitThread [KERNEL32.@] Ends a thread * * RETURNS * None */ void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */ { RtlFreeThreadActivationContextStack(); RtlExitUserThread( code ); }
static void wine_pthread_exit(void *retval, char *currentframe) { RtlFreeThreadActivationContextStack(); RtlExitUserThread( PtrToUlong(retval) ); }
static ULONG NTAPI GuiConsoleInputThread(PVOID Param) { NTSTATUS Status; PCSR_THREAD pcsrt = NULL; PGUI_INIT_INFO GuiInitInfo = (PGUI_INIT_INFO)Param; DESKTOP_CONSOLE_THREAD DesktopConsoleThreadInfo; ULONG_PTR InputThreadId = HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread); HANDLE hThread = NULL; LONG WindowCount = 0; MSG msg; /* * This thread dispatches all the console notifications to the * notification window. It is common for all the console windows * in a given desktop in a window station. */ /* Assign this console input thread to this desktop */ DesktopConsoleThreadInfo.DesktopHandle = GuiInitInfo->Desktop; // Duplicated desktop handle DesktopConsoleThreadInfo.ThreadId = InputThreadId; Status = NtUserConsoleControl(ConsoleCtrlDesktopConsoleThread, &DesktopConsoleThreadInfo, sizeof(DesktopConsoleThreadInfo)); if (!NT_SUCCESS(Status)) goto Quit; /* Connect this CSR thread to the USER subsystem */ pcsrt = CsrConnectToUser(); if (pcsrt == NULL) goto Quit; hThread = pcsrt->ThreadHandle; /* Assign the desktop to this thread */ if (!SetThreadDesktop(DesktopConsoleThreadInfo.DesktopHandle)) goto Quit; /* The thread has been initialized, set the event */ NtSetEvent(GuiInitInfo->GuiThreadStartupEvent, NULL); Status = STATUS_SUCCESS; while (GetMessageW(&msg, NULL, 0, 0)) { switch (msg.message) { case PM_CREATE_CONSOLE: { PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)msg.lParam; PCONSRV_CONSOLE Console = GuiData->Console; HWND NewWindow; RECT rcWnd; DPRINT("PM_CREATE_CONSOLE -- creating window\n"); NewWindow = CreateWindowExW(WS_EX_CLIENTEDGE, GUI_CONWND_CLASS, Console->Title.Buffer, WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, GuiData->IsWindowVisible ? HWND_DESKTOP : HWND_MESSAGE, NULL, ConSrvDllInstance, (PVOID)GuiData); if (NewWindow == NULL) { DPRINT1("Failed to create a new console window\n"); continue; } ASSERT(NewWindow == GuiData->hWindow); InterlockedIncrement(&WindowCount); // // FIXME: TODO: Move everything there into conwnd.c!OnNcCreate() // /* Retrieve our real position */ // See conwnd.c!OnMove() GetWindowRect(GuiData->hWindow, &rcWnd); GuiData->GuiInfo.WindowOrigin.x = rcWnd.left; GuiData->GuiInfo.WindowOrigin.y = rcWnd.top; if (GuiData->IsWindowVisible) { /* Move and resize the window to the user's values */ /* CAN WE DEADLOCK ?? */ GuiConsoleMoveWindow(GuiData); // FIXME: This MUST be done via the CreateWindowExW call. SendMessageW(GuiData->hWindow, PM_RESIZE_TERMINAL, 0, 0); } // FIXME: HACK: Potential HACK for CORE-8129; see revision 63595. CreateSysMenu(GuiData->hWindow); if (GuiData->IsWindowVisible) { /* Switch to full-screen mode if necessary */ // FIXME: Move elsewhere, it cause misdrawings of the window. if (GuiData->GuiInfo.FullScreen) SwitchFullScreen(GuiData, TRUE); DPRINT("PM_CREATE_CONSOLE -- showing window\n"); // ShowWindow(NewWindow, (int)GuiData->GuiInfo.ShowWindow); ShowWindowAsync(NewWindow, (int)GuiData->GuiInfo.ShowWindow); DPRINT("Window showed\n"); } else { DPRINT("PM_CREATE_CONSOLE -- hidden window\n"); ShowWindowAsync(NewWindow, SW_HIDE); } continue; } case PM_DESTROY_CONSOLE: { PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)msg.lParam; MSG TempMsg; /* Exit the full screen mode if it was already set */ // LeaveFullScreen(GuiData); /* * Window creation is done using a PostMessage(), so it's possible * that the window that we want to destroy doesn't exist yet. * So first empty the message queue. */ /* while (PeekMessageW(&TempMsg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&TempMsg); DispatchMessageW(&TempMsg); }*/ while (PeekMessageW(&TempMsg, NULL, 0, 0, PM_REMOVE)) ; if (GuiData->hWindow == NULL) continue; DestroyWindow(GuiData->hWindow); NtSetEvent(GuiData->hGuiTermEvent, NULL); if (InterlockedDecrement(&WindowCount) == 0) { DPRINT("CONSRV: Going to quit the Input Thread 0x%p\n", InputThreadId); goto Quit; } continue; } } TranslateMessage(&msg); DispatchMessageW(&msg); } Quit: DPRINT("CONSRV: Quit the Input Thread 0x%p, Status = 0x%08lx\n", InputThreadId, Status); /* Remove this console input thread from this desktop */ // DesktopConsoleThreadInfo.DesktopHandle; DesktopConsoleThreadInfo.ThreadId = 0; NtUserConsoleControl(ConsoleCtrlDesktopConsoleThread, &DesktopConsoleThreadInfo, sizeof(DesktopConsoleThreadInfo)); /* Close the duplicated desktop handle */ CloseDesktop(DesktopConsoleThreadInfo.DesktopHandle); // NtUserCloseDesktop /* Cleanup CSR thread */ if (pcsrt) { if (hThread != pcsrt->ThreadHandle) DPRINT1("WARNING!! hThread (0x%p) != pcsrt->ThreadHandle (0x%p), you may expect crashes soon!!\n", hThread, pcsrt->ThreadHandle); CsrDereferenceThread(pcsrt); } /* Exit the thread */ RtlExitUserThread(Status); return 0; }
DRPEXPORT VOID InjectNormalRoutine(PVOID ImageBase) { Inject::InjectRoutine(ImageBase, FALSE); RtlExitUserThread(STATUS_SUCCESS); }
/*********************************************************************** * ExitThread [KERNEL32.@] Ends a thread * * RETURNS * None */ void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */ { RtlExitUserThread( code ); }