LRESULT _etk_grab_window(EWin32GraphicsEngine *win32Engine, etk_win32_gdi_callback_t *callback) { if(win32Engine == NULL || callback == NULL || callback->command != WM_ETK_MESSAGE_GRAB_WINDOW || callback->win == NULL || callback->win->win32Window == NULL) return FALSE; EAutolock <EWin32GraphicsEngine> autolock(win32Engine); if(autolock.IsLocked() == false || win32Engine->InitCheck() != E_OK) return FALSE; // TODO: keyboard grab if(callback->grab_mouse == false) return FALSE; if(callback->grab_state) { SetCapture(callback->win->win32Window); GUITHREADINFO info; info.cbSize = sizeof(GUITHREADINFO); GetGUIThreadInfo(win32Engine->win32ThreadID, &info); if(info.hwndCapture != callback->win->win32Window) return FALSE; } else { GUITHREADINFO info; info.cbSize = sizeof(GUITHREADINFO); GetGUIThreadInfo(win32Engine->win32ThreadID, &info); if(info.hwndCapture != callback->win->win32Window) return FALSE; if(ReleaseCapture() == 0) return FALSE; } return TRUE; }
// Determine if the mouse is presently being captured. This call can be // made outside of the GUI thread bool isMouseCaptured(HWND hWnd, HWND &hCaptureWnd) { bool bIsCaptured = false; DWORD processId = GetWindowThreadProcessId(hWnd, NULL); GUITHREADINFO threadInfo; threadInfo.cbSize = sizeof GUITHREADINFO; if (GetGUIThreadInfo(processId, &threadInfo)) { bIsCaptured = bIsCaptured || (threadInfo.hwndCapture != 0); bIsCaptured = bIsCaptured || ((threadInfo.flags & (GUI_INMENUMODE | GUI_INMOVESIZE | GUI_POPUPMENUMODE | GUI_SYSTEMMENUMODE)) != 0); hCaptureWnd = threadInfo.hwndCapture; } else { hCaptureWnd = NULL; //DisplayLastError("Failed to get GUITHREADINFO"); } return bIsCaptured; }
HWND CConEmuInside::CheckInsideFocus() { if (!isInsideWndSet()) { //_ASSERTE(FALSE && "Inside was not initialized"); return NULL; } wchar_t szInfo[512]; GUITHREADINFO tif = { sizeof(tif) }; HWND hParentWnd = GetParentRoot(); DWORD nTID = GetWindowThreadProcessId(hParentWnd, NULL); if (!GetGUIThreadInfo(nTID, &tif)) { _wsprintf(szInfo, SKIPCOUNT(szInfo) L"GetGUIThreadInfo(%u) failed, code=%u", nTID, GetLastError()); LogString(szInfo); return NULL; } static GUITHREADINFO last_tif = {}; if (memcmp(&last_tif, &tif, sizeof(tif)) != 0) { last_tif = tif; _wsprintf(szInfo, SKIPCOUNT(szInfo) L"ParentInputInfo: flags=x%X Active=x%X Focus=x%X Capture=x%X Menu=x%X MoveSize=x%X Caret=x%X (%i,%i)-(%i,%i)", tif.flags, LODWORD(tif.hwndActive), LODWORD(tif.hwndFocus), LODWORD(tif.hwndCapture), LODWORD(tif.hwndMenuOwner), LODWORD(tif.hwndMoveSize), LODWORD(tif.hwndCaret), LOGRECTCOORDS(tif.rcCaret)); LogString(szInfo); } return tif.hwndFocus; }
BOOL WindowUtil_isFocused(HWND hwnd) { HWND focused_hwnd; HWND child, parent; GUITHREADINFO thread_infos; char className[CONSOLE_WINDOW_CLASS_SIZE]; thread_infos.cbSize = sizeof(GUITHREADINFO); if (! GetGUIThreadInfo(GetWindowThreadProcessId(hwnd, NULL), &thread_infos)) { return FALSE; } focused_hwnd = thread_infos.hwndFocus; if (GetClassName(hwnd, className, CONSOLE_WINDOW_CLASS_SIZE) == CONSOLE_WINDOW_CLASS_SIZE - 1) if (strncmp(CONSOLE_WINDOW_CLASS_NAME, className, CONSOLE_WINDOW_CLASS_SIZE) == 0) return (thread_infos.hwndCaret == hwnd); if (focused_hwnd == NULL) return FALSE; if (focused_hwnd == hwnd) return TRUE; parent = focused_hwnd; do { child = parent; parent = GetParent(child); } while(parent); return (child == hwnd); }
/////////////////////////////////////////////////////////////////////////////// // Finds out which window has the focus HWND RemoteGetFocus() { GUITHREADINFO remoteThreadInfo; remoteThreadInfo.cbSize = sizeof(GUITHREADINFO); if(!GetGUIThreadInfo(0, &remoteThreadInfo)) { return NULL; } return remoteThreadInfo.hwndFocus ? remoteThreadInfo.hwndFocus : remoteThreadInfo.hwndActive; }
bool IsInActiveWindow(HWND hwnd) { GUITHREADINFO guit; guit.cbSize = sizeof(guit); if(GetGUIThreadInfo(NULL, &guit)) { while( ::IsWindow(hwnd) ) { if( hwnd == guit.hwndActive ) return true; hwnd = ::GetParent(hwnd); } } return false; }
LRESULT _etk_hide_window(EWin32GraphicsEngine *win32Engine, etk_win32_gdi_callback_t *callback) { if(win32Engine == NULL || callback == NULL || callback->command != WM_ETK_MESSAGE_HIDE_WINDOW || callback->win == NULL || callback->win->win32Window == NULL) return FALSE; EAutolock <EWin32GraphicsEngine> autolock(win32Engine); if(autolock.IsLocked() == false || win32Engine->InitCheck() != E_OK) return FALSE; ShowWindowAsync(callback->win->win32Window, SW_HIDE); GUITHREADINFO info; info.cbSize = sizeof(GUITHREADINFO); GetGUIThreadInfo(win32Engine->win32ThreadID, &info); if(info.hwndCapture == callback->win->win32Window) ReleaseCapture(); return TRUE; }
DWORD Applet::GetCurrentActiveThread() { HWND hwnd = GetForegroundWindow(); DWORD threadId = GetWindowThreadProcessId(hwnd, NULL); // Get GUI thread information GUITHREADINFO gui; ZeroMemory(&gui, sizeof(GUITHREADINFO)); gui.cbSize = sizeof(GUITHREADINFO); GetGUIThreadInfo(threadId, &gui); // Get the most interesting hwnd of an application HWND active = (gui.hwndCaret != NULL) ? gui.hwndCaret : (gui.hwndFocus != NULL) ? gui.hwndFocus : (gui.hwndActive != NULL) ? gui.hwndActive : hwnd; return (active != hwnd) ? GetWindowThreadProcessId(active, NULL) : threadId; }
VOID KbdTestGetKeyNameText() { WCHAR text[20]; HWND hForegroundWnd = NULL; DWORD threadId = 0; HKL hCurrKL = NULL; BYTE btKeyState[256]; UINT scanCode = 21; GUITHREADINFO threadInfo; DWORD focusThread = NULL; hForegroundWnd = GetForegroundWindow(); threadId = GetWindowThreadProcessId(hForegroundWnd, NULL); DebugPrint(L"hForegroundWnd=%x, threadId=%x\n", hForegroundWnd, threadId); memset(&threadInfo, 0, sizeof(threadInfo)); threadInfo.cbSize = sizeof(threadInfo); if (!GetGUIThreadInfo(threadId, &threadInfo)) { DebugPrint(L"GetGUIThreadInfo failed with err=%x for threadId=%x", GetLastError(), threadId); } DebugPrint(L"thread.hwndFocus=%x\n", threadInfo.hwndFocus); focusThread = GetWindowThreadProcessId(threadInfo.hwndFocus, NULL); DebugPrint(L"focusThread=%x\n", focusThread); hCurrKL = GetKeyboardLayout(threadId); DebugPrint(L"Thread hKL=%x\n", hCurrKL); for (int i = 0; i < 10; i++) { hCurrKL = ActivateKeyboardLayout((HKL)HKL_NEXT, 0); DebugPrint(L"ActivateKeyboardLayout:prevHKL=%x\n", hCurrKL); hCurrKL = GetKeyboardLayout(0); DebugPrint(L"Curr thread hKL=%x\n", hCurrKL); //GetKeyboardState(btKeyState); memset(btKeyState, 0, sizeof(btKeyState)); memset(text, 0, sizeof(text)); ToUnicodeEx(MapVirtualKey(scanCode, MAPVK_VSC_TO_VK_EX), scanCode, btKeyState, text, RTL_NUMBER_OF(text), 0, hCurrKL); DebugPrint(L"ToUnicodeEx text is=%ws, unicode=%x\n", text, (USHORT)text[0]); } }
//--------------------------------------------------------------------------- // 函数: g_MessageBox // 功能: Display a System Message Box // 参数: char* lpMsg, ... //--------------------------------------------------------------------------- C_ENGINE_API void g_MessageBox(const char* lpMsg, ...) { char szMsg[1024]; va_list va; va_start(va, lpMsg); vsprintf(szMsg, lpMsg, va); va_end(va); g_DebugLog(szMsg); #ifndef __linux HWND hWnd = NULL; GUITHREADINFO info; memset(&info, 0, sizeof(info)); info.cbSize = sizeof(info); if (GetGUIThreadInfo(NULL, &info)) hWnd = info.hwndActive; MessageBox(hWnd, szMsg, 0, MB_OK | MB_ICONINFORMATION); #endif }
LRESULT _etk_get_window_activate_state(EWin32GraphicsEngine *win32Engine, etk_win32_gdi_callback_t *callback) { if(win32Engine == NULL || callback == NULL || callback->command != WM_ETK_MESSAGE_GET_WINDOW_ACTIVATE_STATE || callback->win == NULL || callback->win->win32Window == NULL) return FALSE; EAutolock <EWin32GraphicsEngine> autolock(win32Engine); if(autolock.IsLocked() == false || win32Engine->InitCheck() != E_OK) return FALSE; bool activate_state = false; GUITHREADINFO info; info.cbSize = sizeof(GUITHREADINFO); if(!(GetGUIThreadInfo(win32Engine->win32ThreadID, &info) == 0 || info.hwndActive != callback->win->win32Window || GetForegroundWindow() != callback->win->win32Window)) activate_state = true; callback->activate_state = activate_state; return TRUE; }
LRESULT _etk_activate_window(EWin32GraphicsEngine *win32Engine, etk_win32_gdi_callback_t *callback) { if(win32Engine == NULL || callback == NULL || callback->command != WM_ETK_MESSAGE_ACTIVATE_WINDOW || callback->win == NULL || callback->win->win32Window == NULL) return FALSE; EAutolock <EWin32GraphicsEngine> autolock(win32Engine); if(autolock.IsLocked() == false || win32Engine->InitCheck() != E_OK) return FALSE; if(callback->activate_state) { if(IsWindowVisible(callback->win->win32Window) == 0) { callback->win->fActivateWhenShown = callback->activate_state; return TRUE; } #if 0 DWORD tidForeground = GetWindowThreadProcessId(GetForegroundWindow(), NULL); eint8 otherThread = (tidForeground == win32Engine->win32ThreadID ? 0 : 1); BOOL retVal = FALSE; if(otherThread == 1) otherThread = (AttachThreadInput(tidForeground, win32Engine->win32ThreadID, TRUE) == 0 ? 2 : 1); if(otherThread <= 1) retVal = (SetForegroundWindow(callback->win->win32Window) == 0 ? FALSE : TRUE); if(otherThread == 1) AttachThreadInput(tidForeground, win32Engine->win32ThreadID, FALSE); if(retVal) retVal = (SetActiveWindow(callback->win->win32Window) == NULL ? (GetLastError() == 0) : TRUE); return retVal; #endif return(SetActiveWindow(callback->win->win32Window) == NULL ? (GetLastError() == 0) : TRUE); } else { GUITHREADINFO info; info.cbSize = sizeof(GUITHREADINFO); GetGUIThreadInfo(win32Engine->win32ThreadID, &info); if(info.hwndCapture == callback->win->win32Window) ReleaseCapture(); PostMessageA(callback->win->win32Window, WM_NCACTIVATE, FALSE, 0); } return TRUE; }
/******************************************************************* * set_active_window */ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus ) { HWND previous = GetActiveWindow(); BOOL ret; DWORD old_thread, new_thread; CBTACTIVATESTRUCT cbt; if (previous == hwnd) { if (prev) *prev = hwnd; return TRUE; } /* call CBT hook chain */ cbt.fMouse = mouse; cbt.hWndActive = previous; if (HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hwnd, (LPARAM)&cbt, TRUE )) return FALSE; if (IsWindow(previous)) { SendMessageW( previous, WM_NCACTIVATE, FALSE, (LPARAM)hwnd ); SendMessageW( previous, WM_ACTIVATE, MAKEWPARAM( WA_INACTIVE, IsIconic(previous) ), (LPARAM)hwnd ); } SERVER_START_REQ( set_active_window ) { req->handle = wine_server_user_handle( hwnd ); if ((ret = !wine_server_call_err( req ))) previous = wine_server_ptr_handle( reply->previous ); } SERVER_END_REQ; if (!ret) return FALSE; if (prev) *prev = previous; if (previous == hwnd) return TRUE; if (hwnd) { /* send palette messages */ if (SendMessageW( hwnd, WM_QUERYNEWPALETTE, 0, 0 )) SendMessageTimeoutW( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hwnd, 0, SMTO_ABORTIFHUNG, 2000, NULL ); if (!IsWindow(hwnd)) return FALSE; } old_thread = previous ? GetWindowThreadProcessId( previous, NULL ) : 0; new_thread = hwnd ? GetWindowThreadProcessId( hwnd, NULL ) : 0; if (old_thread != new_thread) { HWND *list, *phwnd; if ((list = WIN_ListChildren( GetDesktopWindow() ))) { if (old_thread) { for (phwnd = list; *phwnd; phwnd++) { if (GetWindowThreadProcessId( *phwnd, NULL ) == old_thread) SendMessageW( *phwnd, WM_ACTIVATEAPP, 0, new_thread ); } } if (new_thread) { for (phwnd = list; *phwnd; phwnd++) { if (GetWindowThreadProcessId( *phwnd, NULL ) == new_thread) SendMessageW( *phwnd, WM_ACTIVATEAPP, 1, old_thread ); } } HeapFree( GetProcessHeap(), 0, list ); } } if (IsWindow(hwnd)) { SendMessageW( hwnd, WM_NCACTIVATE, (hwnd == GetForegroundWindow()), (LPARAM)previous ); SendMessageW( hwnd, WM_ACTIVATE, MAKEWPARAM( mouse ? WA_CLICKACTIVE : WA_ACTIVE, IsIconic(hwnd) ), (LPARAM)previous ); if (GetAncestor( hwnd, GA_PARENT ) == GetDesktopWindow()) PostMessageW( GetDesktopWindow(), WM_PARENTNOTIFY, WM_NCACTIVATE, (LPARAM)hwnd ); if (hwnd == GetForegroundWindow() && !IsIconic( hwnd )) USER_Driver->pSetActiveWindow( hwnd ); } /* now change focus if necessary */ if (focus) { GUITHREADINFO info; info.cbSize = sizeof(info); GetGUIThreadInfo( GetCurrentThreadId(), &info ); /* Do not change focus if the window is no more active */ if (hwnd == info.hwndActive) { if (!info.hwndFocus || !hwnd || GetAncestor( info.hwndFocus, GA_ROOT ) != hwnd) set_focus_window( hwnd ); } } return TRUE; }
static bool OS_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { if(msg != WM_KEYDOWN && msg != WM_SYSKEYDOWN && msg != WM_KEYUP && msg != WM_SYSKEYUP) return false; GUITHREADINFO info; memset(&info, 0, sizeof(GUITHREADINFO)); info.cbSize = sizeof(GUITHREADINFO); GetGUIThreadInfo(GetCurrentThreadId(), &info); Object *object = (Object*)GetWindowLongPtr(info.hwndFocus, GWLP_USERDATA); if(object == nullptr) return false; if(dynamic_cast<Window*>(object)) { Window &window = (Window&)*object; if(pWindow::modal.size() > 0 && !pWindow::modal.find(&window.p)) return false; Keyboard::Keycode keysym = Keysym(wparam, lparam); if(keysym != Keyboard::Keycode::None) { if((msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) && window.onKeyPress) window.onKeyPress(keysym); if((msg == WM_KEYUP || msg == WM_SYSKEYUP) && window.onKeyRelease) window.onKeyRelease(keysym); } return false; } if(msg == WM_KEYDOWN) { if(dynamic_cast<ListView*>(object)) { ListView &listView = (ListView&)*object; if(wparam == VK_RETURN) { if(listView.onActivate) listView.onActivate(); } } else if(dynamic_cast<LineEdit*>(object)) { LineEdit &lineEdit = (LineEdit&)*object; if(wparam == VK_RETURN) { if(lineEdit.onActivate) lineEdit.onActivate(); } } else if(dynamic_cast<TextEdit*>(object)) { TextEdit &textEdit = (TextEdit&)*object; if(wparam == 'A' && GetKeyState(VK_CONTROL) < 0) { //Ctrl+A = select all text //note: this is not a standard accelerator on Windows Edit_SetSel(textEdit.p.hwnd, 0, ~0); return true; } else if(wparam == 'V' && GetKeyState(VK_CONTROL) < 0) { //Ctrl+V = paste text //note: this formats Unix (LF) and OS9 (CR) line-endings to Windows (CR+LF) line-endings //this is necessary as the EDIT control only supports Windows line-endings OpenClipboard(hwnd); HANDLE handle = GetClipboardData(CF_UNICODETEXT); if(handle) { wchar_t *text = (wchar_t*)GlobalLock(handle); if(text) { string data = (const char*)utf8_t(text); data.replace("\r\n", "\n"); data.replace("\r", "\n"); data.replace("\n", "\r\n"); GlobalUnlock(handle); utf16_t output(data); HGLOBAL resource = GlobalAlloc(GMEM_MOVEABLE, (wcslen(output) + 1) * sizeof(wchar_t)); if(resource) { wchar_t *write = (wchar_t*)GlobalLock(resource); if(write) { wcscpy(write, output); GlobalUnlock(write); if(SetClipboardData(CF_UNICODETEXT, resource) == FALSE) { GlobalFree(resource); } } } } } CloseClipboard(); return false; } } } return false; }
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId; switch (message) { case WM_TIMER: { BOOL hasMoved = FALSE; GUITHREADINFO guiInfo; guiInfo.cbSize = sizeof(guiInfo); GetGUIThreadInfo(0, &guiInfo); if (bFollowMouse) { POINT pNewMouse; //Get current mouse position GetCursorPos (&pNewMouse); #define PointsAreEqual(pt1, pt2) (((pt1).x == (pt2).x) && ((pt1).y == (pt2).y)) //If mouse has moved ... if (!PointsAreEqual(pMouse, pNewMouse)) { //Update to new position pMouse = pNewMouse; cp = pNewMouse; hasMoved = TRUE; } } if(guiInfo.hwndActive != hMainWnd) { if (bFollowCaret) { if (guiInfo.hwndCaret) { POINT ptCaret; ptCaret.x = (guiInfo.rcCaret.left + guiInfo.rcCaret.right) / 2; ptCaret.y = (guiInfo.rcCaret.top + guiInfo.rcCaret.bottom) / 2; if ((pCaretWnd != guiInfo.hwndCaret) || !PointsAreEqual(pCaret, ptCaret)) { //Update to new position pCaret = ptCaret; pCaretWnd = guiInfo.hwndCaret; if(!hasMoved) { ClientToScreen (guiInfo.hwndCaret, (LPPOINT) &ptCaret); cp = ptCaret; hasMoved = TRUE; } } } else { pCaretWnd = NULL; } } if (bFollowFocus) { if(guiInfo.hwndFocus && !guiInfo.hwndCaret) { POINT ptFocus; RECT activeRect; //Get current control focus GetWindowRect(guiInfo.hwndFocus, &activeRect); ptFocus.x = (activeRect.left + activeRect.right) / 2; ptFocus.y = (activeRect.top + activeRect.bottom) / 2; if((guiInfo.hwndFocus != pFocusWnd) || !PointsAreEqual(pFocus, ptFocus)) { //Update to new position pFocus = ptFocus; pFocusWnd = guiInfo.hwndFocus; if(!hasMoved) { cp = ptFocus; hasMoved = TRUE; } } } else { pFocusWnd = NULL; } } } if(!hasMoved) { DWORD newTicks = GetTickCount(); DWORD elapsed = (newTicks - lastTicks); if(elapsed > REPAINT_SPEED) { hasMoved = TRUE; } } if(hasMoved) { lastTicks = GetTickCount(); Refresh(); } return 0; } case WM_COMMAND: { wmId = LOWORD(wParam); /* Parse the menu selections */ switch (wmId) { case IDM_OPTIONS: if(bOptionsDialog) { ShowWindow(hOptionsDialog, SW_HIDE); } else { ShowWindow(hOptionsDialog, SW_SHOW); } break; case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, AboutProc); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } case WM_PAINT: { PAINTSTRUCT PaintStruct; HDC dc; dc = BeginPaint(hWnd, &PaintStruct); Draw(dc); EndPaint(hWnd, &PaintStruct); return 0; } case WM_CONTEXTMENU: TrackPopupMenu(notifyMenu, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), 0, hWnd, NULL); return 0; case WM_LBUTTONDOWN: { RECT rc; POINT pt; SetCapture(hWnd); GetCursorPos(&pt); GetWindowRect(hWnd, &rc); ptDragOffset.x = pt.x - rc.left; ptDragOffset.y = pt.y - rc.top; nearEdge = AppBarConfig.uEdge; break; } case WM_MOUSEMOVE: if(GetCapture() == hWnd) { RECT rc; POINT pt; RECT rcWorkArea; SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, 0); GetCursorPos(&pt); GetWindowRect(hWnd, &rc); if(AppBarConfig.uEdge>=0) { if (pt.x >= rcWorkArea.left && pt.x <= rcWorkArea.right && pt.y >= rcWorkArea.top && pt.y <= rcWorkArea.bottom) { AttachAppBar(-2); // Fixup offset GetWindowRect(hWnd, &rc); ptDragOffset.x = (rc.right-rc.left)/2; ptDragOffset.y = 2; rc.left = pt.x - ptDragOffset.x; rc.top = pt.y - ptDragOffset.y; SetWindowPos(hWnd, HWND_TOPMOST, rc.left, rc.top, 0, 0, SWP_NOSIZE); } } else { if(pt.x <= rcWorkArea.left+8 && nearEdge != ABE_LEFT) { AttachAppBar(ABE_LEFT); nearEdge = ABE_LEFT; } else if(pt.y <= rcWorkArea.top+8 && nearEdge != ABE_TOP) { AttachAppBar(ABE_TOP); nearEdge = ABE_TOP; } else if(pt.x >= rcWorkArea.right-8 && nearEdge != ABE_RIGHT) { AttachAppBar(ABE_RIGHT); nearEdge = ABE_RIGHT; } else if(pt.y >= rcWorkArea.bottom-8 && nearEdge != ABE_BOTTOM) { AttachAppBar(ABE_BOTTOM); nearEdge = ABE_BOTTOM; } else { rc.left = pt.x - ptDragOffset.x; rc.top = pt.y - ptDragOffset.y; SetWindowPos(hWnd, HWND_TOPMOST, rc.left, rc.top, 0, 0, SWP_NOSIZE); nearEdge = -1; } } pMouse = pt; Refresh(); } break; case WM_LBUTTONUP: if(GetCapture() == hWnd) { if (AppBarConfig.uEdge>=0) DoAppBarStuff(ABM_GETSTATE); else SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); ReleaseCapture(); } break; case WM_SIZE: if(AppBarConfig.uEdge>=0) DoAppBarStuff(ABM_SETPOS); /* fallthrough */ case WM_DISPLAYCHANGE: bRecreateOffscreenDC = TRUE; Refresh(); break; case WM_ERASEBKGND: // handle WM_ERASEBKGND by simply returning non-zero because we did all the drawing in WM_PAINT. return 0; case WM_DESTROY: { if (AppBarConfig.uEdge >= 0) DoAppBarStuff(ABM_REMOVE); KillTimer(hWnd, 1); /* Save settings to registry */ SaveSettings(); /* Cleanup notification icon */ ZeroMemory(&nid, sizeof(nid)); nid.cbSize = sizeof(nid); nid.uFlags = NIF_MESSAGE; nid.hWnd = hWnd; nid.uCallbackMessage = APPMSG_NOTIFYICON; Shell_NotifyIcon(NIM_DELETE, &nid); DestroyIcon(notifyIcon); DestroyWindow(hOptionsDialog); PostQuitMessage(0); return 0; } case WM_CREATE: { HMENU tempMenu; /* Get the desktop window */ hDesktopWindow = GetDesktopWindow(); /* Set the timer */ SetTimer(hWnd, 1, TIMER_SPEED, NULL); /* Notification icon */ notifyIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 16, 16, 0); ZeroMemory(&nid, sizeof(nid)); nid.cbSize = sizeof(nid); nid.uFlags = NIF_ICON | NIF_MESSAGE; nid.hWnd = hWnd; nid.uCallbackMessage = APPMSG_NOTIFYICON; nid.hIcon = notifyIcon; Shell_NotifyIcon(NIM_ADD, &nid); tempMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDC_MAGNIFIER)); notifyMenu = GetSubMenu(tempMenu, 0); RemoveMenu(tempMenu, 0, MF_BYPOSITION); DestroyMenu(tempMenu); return 0; } case APPMSG_APPBAR: { switch (wParam) { case ABN_STATECHANGE: DoAppBarStuff(ABM_GETSTATE); break; case ABN_POSCHANGED: DoAppBarStuff(ABM_SETPOS); break; case ABN_FULLSCREENAPP: { if(!lParam) { DoAppBarStuff(ABM_GETSTATE); break; } SetWindowPos(hMainWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); break; } case ABN_WINDOWARRANGE: if(lParam) ShowWindow(hMainWnd, SW_HIDE); else ShowWindow(hMainWnd, SW_SHOW); break; } return 0; } case APPMSG_NOTIFYICON: HandleNotifyIconMessage(hWnd, wParam, lParam); return 0; case WM_ACTIVATE: if(AppBarConfig.uEdge>=0) DoAppBarStuff(ABM_ACTIVATE); break; case WM_WINDOWPOSCHANGED: if(AppBarConfig.uEdge>=0) DoAppBarStuff(ABM_WINDOWPOSCHANGED); Refresh(); break; default: break; } return DefWindowProc(hWnd, message, wParam, lParam); }
VOID PhpThreadProviderUpdate( _In_ PPH_THREAD_PROVIDER ThreadProvider, _In_ PVOID ProcessInformation ) { PPH_THREAD_PROVIDER threadProvider = ThreadProvider; PSYSTEM_PROCESS_INFORMATION process; SYSTEM_PROCESS_INFORMATION localProcess; PSYSTEM_THREAD_INFORMATION threads; ULONG numberOfThreads; ULONG i; process = PhFindProcessInformation(ProcessInformation, threadProvider->ProcessId); if (!process) { // The process doesn't exist anymore. Pretend it does but // has no threads. process = &localProcess; process->NumberOfThreads = 0; } threads = process->Threads; numberOfThreads = process->NumberOfThreads; // System Idle Process has one thread per CPU. // They all have a TID of 0, but we can't have // multiple TIDs, so we'll assign unique TIDs. if (threadProvider->ProcessId == SYSTEM_IDLE_PROCESS_ID) { for (i = 0; i < numberOfThreads; i++) { threads[i].ClientId.UniqueThread = UlongToHandle(i); } } // Look for dead threads. { PPH_LIST threadsToRemove = NULL; ULONG enumerationKey = 0; PPH_THREAD_ITEM *threadItem; while (PhEnumHashtable(threadProvider->ThreadHashtable, (PVOID *)&threadItem, &enumerationKey)) { BOOLEAN found = FALSE; // Check if the thread still exists. for (i = 0; i < numberOfThreads; i++) { PSYSTEM_THREAD_INFORMATION thread = &threads[i]; if ((*threadItem)->ThreadId == thread->ClientId.UniqueThread) { found = TRUE; break; } } if (!found) { // Raise the thread removed event. PhInvokeCallback(&threadProvider->ThreadRemovedEvent, *threadItem); if (!threadsToRemove) threadsToRemove = PhCreateList(2); PhAddItemList(threadsToRemove, *threadItem); } } if (threadsToRemove) { PhAcquireFastLockExclusive(&threadProvider->ThreadHashtableLock); for (i = 0; i < threadsToRemove->Count; i++) { PhpRemoveThreadItem( threadProvider, (PPH_THREAD_ITEM)threadsToRemove->Items[i] ); } PhReleaseFastLockExclusive(&threadProvider->ThreadHashtableLock); PhDereferenceObject(threadsToRemove); } } // Go through the queued thread query data. { PSLIST_ENTRY entry; PPH_THREAD_QUERY_DATA data; entry = RtlInterlockedFlushSList(&threadProvider->QueryListHead); while (entry) { data = CONTAINING_RECORD(entry, PH_THREAD_QUERY_DATA, ListEntry); entry = entry->Next; if (data->StartAddressResolveLevel == PhsrlFunction && data->StartAddressString) { PhSwapReference(&data->ThreadItem->StartAddressString, data->StartAddressString); data->ThreadItem->StartAddressResolveLevel = data->StartAddressResolveLevel; } PhMoveReference(&data->ThreadItem->ServiceName, data->ServiceName); data->ThreadItem->JustResolved = TRUE; if (data->StartAddressString) PhDereferenceObject(data->StartAddressString); PhDereferenceObject(data->ThreadItem); PhFree(data); } } // Look for new threads and update existing ones. for (i = 0; i < numberOfThreads; i++) { PSYSTEM_THREAD_INFORMATION thread = &threads[i]; PPH_THREAD_ITEM threadItem; threadItem = PhReferenceThreadItem(threadProvider, thread->ClientId.UniqueThread); if (!threadItem) { PVOID startAddress = NULL; threadItem = PhCreateThreadItem(thread->ClientId.UniqueThread); threadItem->CreateTime = thread->CreateTime; threadItem->KernelTime = thread->KernelTime; threadItem->UserTime = thread->UserTime; PhUpdateDelta(&threadItem->ContextSwitchesDelta, thread->ContextSwitches); threadItem->Priority = thread->Priority; threadItem->BasePriority = thread->BasePriority; threadItem->State = (KTHREAD_STATE)thread->ThreadState; threadItem->WaitReason = thread->WaitReason; // Try to open a handle to the thread. if (!NT_SUCCESS(PhOpenThread( &threadItem->ThreadHandle, THREAD_QUERY_INFORMATION, threadItem->ThreadId ))) { PhOpenThread( &threadItem->ThreadHandle, ThreadQueryAccess, threadItem->ThreadId ); } // Get the cycle count. if (WINDOWS_HAS_CYCLE_TIME) { ULONG64 cycles; if (NT_SUCCESS(PhpGetThreadCycleTime( threadProvider, threadItem, &cycles ))) { PhUpdateDelta(&threadItem->CyclesDelta, cycles); } } // Initialize the CPU time deltas. PhUpdateDelta(&threadItem->CpuKernelDelta, threadItem->KernelTime.QuadPart); PhUpdateDelta(&threadItem->CpuUserDelta, threadItem->UserTime.QuadPart); // Try to get the start address. if (threadItem->ThreadHandle) { NtQueryInformationThread( threadItem->ThreadHandle, ThreadQuerySetWin32StartAddress, &startAddress, sizeof(PVOID), NULL ); } if (!startAddress) startAddress = thread->StartAddress; threadItem->StartAddress = (ULONG64)startAddress; // Get the Win32 priority. threadItem->PriorityWin32 = GetThreadPriority(threadItem->ThreadHandle); if (threadProvider->SymbolsLoadedRunId != 0) { threadItem->StartAddressString = PhpGetThreadBasicStartAddress( threadProvider, threadItem->StartAddress, &threadItem->StartAddressResolveLevel ); } if (!threadItem->StartAddressString) { threadItem->StartAddressResolveLevel = PhsrlAddress; threadItem->StartAddressString = PhCreateStringEx(NULL, PH_PTR_STR_LEN * 2); PhPrintPointer( threadItem->StartAddressString->Buffer, (PVOID)threadItem->StartAddress ); PhTrimToNullTerminatorString(threadItem->StartAddressString); } PhpQueueThreadQuery(threadProvider, threadItem); // Is it a GUI thread? if (threadItem->ThreadHandle && KphIsConnected()) { PVOID win32Thread; if (NT_SUCCESS(KphQueryInformationThread( threadItem->ThreadHandle, KphThreadWin32Thread, &win32Thread, sizeof(PVOID), NULL ))) { threadItem->IsGuiThread = win32Thread != NULL; } } else { GUITHREADINFO info = { sizeof(GUITHREADINFO) }; threadItem->IsGuiThread = !!GetGUIThreadInfo(HandleToUlong(threadItem->ThreadId), &info); } // Add the thread item to the hashtable. PhAcquireFastLockExclusive(&threadProvider->ThreadHashtableLock); PhAddEntryHashtable(threadProvider->ThreadHashtable, &threadItem); PhReleaseFastLockExclusive(&threadProvider->ThreadHashtableLock); // Raise the thread added event. PhInvokeCallback(&threadProvider->ThreadAddedEvent, threadItem); } else { BOOLEAN modified = FALSE; if (threadItem->JustResolved) modified = TRUE; threadItem->KernelTime = thread->KernelTime; threadItem->UserTime = thread->UserTime; threadItem->Priority = thread->Priority; threadItem->BasePriority = thread->BasePriority; threadItem->State = (KTHREAD_STATE)thread->ThreadState; if (threadItem->WaitReason != thread->WaitReason) { threadItem->WaitReason = thread->WaitReason; modified = TRUE; } // If the resolve level is only at address, it probably // means symbols weren't loaded the last time we // tried to get the start address. Try again. if (threadItem->StartAddressResolveLevel == PhsrlAddress) { if (threadProvider->SymbolsLoadedRunId != 0) { PPH_STRING newStartAddressString; newStartAddressString = PhpGetThreadBasicStartAddress( threadProvider, threadItem->StartAddress, &threadItem->StartAddressResolveLevel ); PhMoveReference( &threadItem->StartAddressString, newStartAddressString ); modified = TRUE; } } // If we couldn't resolve the start address to a // module+offset, use the StartAddress instead // of the Win32StartAddress and try again. // Note that we check the resolve level again // because we may have changed it in the previous // block. if (threadItem->JustResolved && threadItem->StartAddressResolveLevel == PhsrlAddress) { if (threadItem->StartAddress != (ULONG64)thread->StartAddress) { threadItem->StartAddress = (ULONG64)thread->StartAddress; PhpQueueThreadQuery(threadProvider, threadItem); } } // Update the context switch count. { ULONG oldDelta; oldDelta = threadItem->ContextSwitchesDelta.Delta; PhUpdateDelta(&threadItem->ContextSwitchesDelta, thread->ContextSwitches); if (threadItem->ContextSwitchesDelta.Delta != oldDelta) { modified = TRUE; } } // Update the cycle count. if (WINDOWS_HAS_CYCLE_TIME) { ULONG64 cycles; ULONG64 oldDelta; oldDelta = threadItem->CyclesDelta.Delta; if (NT_SUCCESS(PhpGetThreadCycleTime( threadProvider, threadItem, &cycles ))) { PhUpdateDelta(&threadItem->CyclesDelta, cycles); if (threadItem->CyclesDelta.Delta != oldDelta) { modified = TRUE; } } } // Update the CPU time deltas. PhUpdateDelta(&threadItem->CpuKernelDelta, threadItem->KernelTime.QuadPart); PhUpdateDelta(&threadItem->CpuUserDelta, threadItem->UserTime.QuadPart); // Update the CPU usage. // If the cycle time isn't available, we'll fall back to using the CPU time. if (WINDOWS_HAS_CYCLE_TIME && PhEnableCycleCpuUsage && (threadProvider->ProcessId == SYSTEM_IDLE_PROCESS_ID || threadItem->ThreadHandle)) { threadItem->CpuUsage = (FLOAT)threadItem->CyclesDelta.Delta / PhCpuTotalCycleDelta; } else { threadItem->CpuUsage = (FLOAT)(threadItem->CpuKernelDelta.Delta + threadItem->CpuUserDelta.Delta) / (PhCpuKernelDelta.Delta + PhCpuUserDelta.Delta + PhCpuIdleDelta.Delta); } // Update the Win32 priority. { LONG oldPriorityWin32 = threadItem->PriorityWin32; threadItem->PriorityWin32 = GetThreadPriority(threadItem->ThreadHandle); if (threadItem->PriorityWin32 != oldPriorityWin32) { modified = TRUE; } } // Update the GUI thread status. if (threadItem->ThreadHandle && KphIsConnected()) { PVOID win32Thread; if (NT_SUCCESS(KphQueryInformationThread( threadItem->ThreadHandle, KphThreadWin32Thread, &win32Thread, sizeof(PVOID), NULL ))) { BOOLEAN oldIsGuiThread = threadItem->IsGuiThread; threadItem->IsGuiThread = win32Thread != NULL; if (threadItem->IsGuiThread != oldIsGuiThread) modified = TRUE; } } else { GUITHREADINFO info = { sizeof(GUITHREADINFO) }; BOOLEAN oldIsGuiThread = threadItem->IsGuiThread; threadItem->IsGuiThread = !!GetGUIThreadInfo(HandleToUlong(threadItem->ThreadId), &info); if (threadItem->IsGuiThread != oldIsGuiThread) modified = TRUE; } threadItem->JustResolved = FALSE; if (modified) { // Raise the thread modified event. PhInvokeCallback(&threadProvider->ThreadModifiedEvent, threadItem); } PhDereferenceObject(threadItem); } } PhInvokeCallback(&threadProvider->UpdatedEvent, NULL); threadProvider->RunId++; }