Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337/* * PROJECT: ReactOS API tests * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+) * PURPOSE: debugging and analysis of message states * COPYRIGHT: Copyright 2019-2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> */
#include "precomp.h"#include "undocuser.h"#include "winxx.h"#include <imm.h>#include <strsafe.h>
#define MAX_MSGS 512
static MSG s_Msgs[MAX_MSGS];static UINT s_cMsgs = 0;static CHAR s_prefix[16] = "";static HWND s_hMainWnd = NULL;static HWND s_hwndEdit = NULL;static HWND s_hImeWnd = NULL;static WNDPROC s_fnOldEditWndProc = NULL;static WNDPROC s_fnOldImeWndProc = NULL;
#define MSGDUMP_PRINTF trace#define MSGDUMP_PREFIX s_prefix#include "msgdump.h" /* msgdump.h needs MSGDUMP_TPRINTF and MSGDUMP_PREFIX */
static void MD_build_prefix(void){ DWORD Flags = InSendMessageEx(NULL); INT i = 0;
if (Flags & ISMEX_CALLBACK) s_prefix[i++] = 'C'; if (Flags & ISMEX_NOTIFY) s_prefix[i++] = 'N'; if (Flags & ISMEX_REPLIED) s_prefix[i++] = 'R'; if (Flags & ISMEX_SEND) s_prefix[i++] = 'S'; if (i == 0) s_prefix[i++] = 'P';
s_prefix[i++] = ':'; s_prefix[i++] = ' '; s_prefix[i] = 0;}
#define STAGE_1 1#define STAGE_2 2#define STAGE_3 3#define STAGE_4 4#define STAGE_5 5
static INT findMessage(INT iMsg, HWND hwnd, UINT uMsg){ if (iMsg == -1) iMsg = 0; for (; iMsg < s_cMsgs; ++iMsg) { if (s_Msgs[iMsg].message == uMsg && s_Msgs[iMsg].hwnd == hwnd) return iMsg; } return -1;}
typedef struct TEST_ENTRY{ INT line; LPCSTR name; UINT iFound;} TEST_ENTRY, *PTEST_ENTRY;
static VOID DoAnalyzeEntries(size_t nCount, PTEST_ENTRY pEntries){ size_t i; for (i = 0; i < nCount - 1; ++i) { PTEST_ENTRY entry1 = &pEntries[i]; PTEST_ENTRY entry2 = &pEntries[i + 1]; ok(entry1->iFound < entry2->iFound, "Line %d: message wrong order (%d >= %d): %s vs %s\n", entry1->line, entry1->iFound, entry2->iFound, entry1->name, entry2->name); }}
static VOID DoAnalyzeAllMessages(VOID){ size_t i; TEST_ENTRY entries1[] = { { __LINE__, "WM_NCCREATE", findMessage(0, s_hMainWnd, WM_NCCREATE) }, { __LINE__, "WM_NCCALCSIZE", findMessage(0, s_hMainWnd, WM_NCCALCSIZE) }, { __LINE__, "WM_CREATE", findMessage(0, s_hMainWnd, WM_CREATE) }, { __LINE__, "WM_PARENTNOTIFY", findMessage(0, s_hMainWnd, WM_PARENTNOTIFY) }, { __LINE__, "WM_WINDOWPOSCHANGING", findMessage(0, s_hMainWnd, WM_WINDOWPOSCHANGING) }, { __LINE__, "WM_ACTIVATEAPP", findMessage(0, s_hMainWnd, WM_ACTIVATEAPP) }, { __LINE__, "WM_NCACTIVATE", findMessage(0, s_hMainWnd, WM_NCACTIVATE) }, { __LINE__, "WM_ACTIVATE", findMessage(0, s_hMainWnd, WM_ACTIVATE) }, { __LINE__, "WM_IME_SETCONTEXT", findMessage(0, s_hMainWnd, WM_IME_SETCONTEXT) }, { __LINE__, "WM_IME_NOTIFY", findMessage(0, s_hMainWnd, WM_IME_NOTIFY) }, { __LINE__, "WM_SETFOCUS", findMessage(0, s_hMainWnd, WM_SETFOCUS) }, { __LINE__, "WM_KILLFOCUS", findMessage(0, s_hMainWnd, WM_KILLFOCUS) }, }; INT iFound1 = entries1[_countof(entries1) - 1].iFound; TEST_ENTRY entries2[] = { { __LINE__, "WM_IME_SETCONTEXT", findMessage(iFound1, s_hMainWnd, WM_IME_SETCONTEXT) }, { __LINE__, "WM_IME_SETCONTEXT", findMessage(iFound1, s_hwndEdit, WM_IME_SETCONTEXT) }, { __LINE__, "WM_SETFOCUS", findMessage(iFound1, s_hwndEdit, WM_SETFOCUS) }, { __LINE__, "WM_SHOWWINDOW", findMessage(iFound1, s_hMainWnd, WM_SHOWWINDOW) }, { __LINE__, "WM_WINDOWPOSCHANGING", findMessage(iFound1, s_hMainWnd, WM_WINDOWPOSCHANGING) }, { __LINE__, "WM_NCPAINT", findMessage(iFound1, s_hMainWnd, WM_NCPAINT) }, { __LINE__, "WM_ERASEBKGND", findMessage(iFound1, s_hMainWnd, WM_ERASEBKGND) }, { __LINE__, "WM_WINDOWPOSCHANGED", findMessage(iFound1, s_hMainWnd, WM_WINDOWPOSCHANGED) }, { __LINE__, "WM_SIZE", findMessage(iFound1, s_hMainWnd, WM_SIZE) }, { __LINE__, "WM_MOVE", findMessage(iFound1, s_hMainWnd, WM_MOVE) }, }; INT iFound2 = entries2[_countof(entries2) - 1].iFound; TEST_ENTRY entries3[] = { { __LINE__, "WM_IME_KEYDOWN", findMessage(iFound2, s_hwndEdit, WM_IME_KEYDOWN) }, { __LINE__, "WM_KEYDOWN", findMessage(iFound2, s_hwndEdit, WM_KEYDOWN) }, { __LINE__, "WM_IME_KEYUP", findMessage(iFound2, s_hwndEdit, WM_IME_KEYUP) }, { __LINE__, "WM_CHAR", findMessage(iFound2, s_hwndEdit, WM_CHAR) }, { __LINE__, "WM_IME_CHAR", findMessage(iFound2, s_hwndEdit, WM_IME_CHAR) }, }; INT iFound3 = entries3[_countof(entries3) - 1].iFound; TEST_ENTRY entries4[] = { { __LINE__, "WM_IME_NOTIFY", findMessage(iFound3, s_hwndEdit, WM_IME_NOTIFY) }, { __LINE__, "WM_IME_NOTIFY", findMessage(iFound3, s_hImeWnd, WM_IME_NOTIFY) }, { __LINE__, "WM_IME_SETCONTEXT", findMessage(iFound3, s_hwndEdit, WM_IME_SETCONTEXT) }, { __LINE__, "WM_IME_SETCONTEXT", findMessage(iFound3, s_hImeWnd, WM_IME_SETCONTEXT) }, }; INT iFound4 = entries4[_countof(entries4) - 1].iFound; TEST_ENTRY entries5[] = { { __LINE__, "WM_DESTROY", findMessage(iFound4, s_hMainWnd, WM_DESTROY) }, { __LINE__, "WM_DESTROY", findMessage(iFound4, s_hwndEdit, WM_DESTROY) }, { __LINE__, "WM_NCDESTROY", findMessage(iFound4, s_hwndEdit, WM_NCDESTROY) }, { __LINE__, "WM_NCDESTROY", findMessage(iFound4, s_hMainWnd, WM_NCDESTROY) }, }; DoAnalyzeEntries(_countof(entries1), entries1); DoAnalyzeEntries(_countof(entries2), entries2); DoAnalyzeEntries(_countof(entries3), entries3); //DoAnalyzeEntries(_countof(entries4), entries4); // No order DoAnalyzeEntries(_countof(entries5), entries5);
ok(iFound1 < entries2[0].iFound, "%d vs %d\n", iFound1, entries2[0].iFound); ok(iFound2 < entries3[0].iFound, "%d vs %d\n", iFound2, entries3[0].iFound); ok(iFound3 < entries4[0].iFound, "%d vs %d\n", iFound3, entries4[0].iFound); ok(iFound4 < entries5[0].iFound, "%d vs %d\n", iFound4, entries5[0].iFound);
for (i = 0; i < _countof(entries4); ++i) { ok(entries4[i].iFound != -1, "entries4[%d].iFound was -1\n", i); }}
static LRESULT CALLBACKEditWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ LRESULT ret; MSG msg = { hwnd, uMsg, wParam, lParam };
/* Build s_prefix */ MD_build_prefix();
/* message dump */ MD_msgdump(hwnd, uMsg, wParam, lParam);
/* Add message */ if (s_cMsgs < MAX_MSGS) s_Msgs[s_cMsgs++] = msg;
/* Do inner task */ ret = CallWindowProc(s_fnOldEditWndProc, hwnd, uMsg, wParam, lParam);
/* message return */ StringCbCopyA(s_prefix, sizeof(s_prefix), "R: "); MD_msgresult(hwnd, uMsg, wParam, lParam, ret);
return ret;}
static LRESULT CALLBACKImeWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ LRESULT ret; MSG msg = { hwnd, uMsg, wParam, lParam };
/* Build s_prefix */ MD_build_prefix();
/* message dump */ MD_msgdump(hwnd, uMsg, wParam, lParam);
/* Add message */ if (s_cMsgs < MAX_MSGS) s_Msgs[s_cMsgs++] = msg;
/* Do inner task */ ret = CallWindowProc(s_fnOldImeWndProc, hwnd, uMsg, wParam, lParam);
/* message return */ StringCbCopyA(s_prefix, sizeof(s_prefix), "R: "); MD_msgresult(hwnd, uMsg, wParam, lParam, ret);
return ret;}
static LRESULT CALLBACKInnerWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ switch (uMsg) { case WM_NCCREATE: s_hMainWnd = hwnd; trace("s_hMainWnd: %p\n", s_hMainWnd); break; case WM_CREATE: s_hwndEdit = CreateWindowW(L"EDIT", NULL, WS_CHILD | WS_VISIBLE, 0, 0, 100, 20, hwnd, NULL, GetModuleHandleW(NULL), NULL); ok(s_hwndEdit != NULL, "s_hwndEdit was NULL\n"); trace("s_hwndEdit: %p\n", s_hwndEdit); s_fnOldEditWndProc = (WNDPROC)SetWindowLongPtrW(s_hwndEdit, GWLP_WNDPROC, (LONG_PTR)EditWindowProc); SetFocus(s_hwndEdit); PostMessageW(hwnd, WM_COMMAND, STAGE_1, 0); break; case WM_COMMAND: switch (LOWORD(wParam)) { case STAGE_1: s_hImeWnd = ImmGetDefaultIMEWnd(hwnd); ok(s_hImeWnd != NULL, "s_hImeWnd was NULL\n"); trace("s_hImeWnd: %p\n", s_hImeWnd ); s_fnOldImeWndProc = (WNDPROC)SetWindowLongPtrW(s_hImeWnd, GWLP_WNDPROC, (LONG_PTR)ImeWindowProc); PostMessageW(hwnd, WM_COMMAND, STAGE_2, 0); break; case STAGE_2: PostMessageW(s_hwndEdit, WM_IME_KEYDOWN, 'A', 0); PostMessageW(hwnd, WM_COMMAND, STAGE_3, 0); break; case STAGE_3: PostMessageW(s_hwndEdit, WM_IME_KEYUP, 'A', 0); PostMessageW(hwnd, WM_COMMAND, STAGE_4, 0); break; case STAGE_4: PostMessageW(s_hwndEdit, WM_IME_CHAR, 'A', 0); PostMessageW(hwnd, WM_COMMAND, STAGE_5, 0); break; case STAGE_5: PostMessageW(hwnd, WM_CLOSE, 0, 0); break; } break; case WM_DESTROY: PostQuitMessage(0); break; }
return DefWindowProcW(hwnd, uMsg, wParam, lParam);}
static LRESULT CALLBACKWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ LRESULT ret; MSG msg = { hwnd, uMsg, wParam, lParam };
/* Build s_prefix */ MD_build_prefix();
/* message dump */ MD_msgdump(hwnd, uMsg, wParam, lParam);
/* Add message */ if (s_cMsgs < MAX_MSGS) s_Msgs[s_cMsgs++] = msg;
/* Do inner task */ ret = InnerWindowProc(hwnd, uMsg, wParam, lParam);
/* message return */ StringCbCopyA(s_prefix, sizeof(s_prefix), "R: "); MD_msgresult(hwnd, uMsg, wParam, lParam, ret);
return ret;}
START_TEST(MessageStateAnalyzer){ WNDCLASSW wc; HWND hwnd; MSG msg; static const WCHAR s_szName[] = L"MessageStateAnalyzer";
/* register window class */ ZeroMemory(&wc, sizeof(wc)); wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; wc.lpfnWndProc = WindowProc; wc.hInstance = GetModuleHandleW(NULL); wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); wc.lpszClassName = s_szName; if (!RegisterClassW(&wc)) { skip("RegisterClassW failed.\n"); return; }
/* create a window */ hwnd = CreateWindowW(s_szName, s_szName, WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 300, 200, NULL, NULL, GetModuleHandleW(NULL), NULL); if (!hwnd) { skip("CreateWindowW failed.\n"); return; }
/* message loop */ while (GetMessageW(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessageW(&msg); }
DoAnalyzeAllMessages();}