Skip to content

Instantly share code, notes, and snippets.

@taviso
Last active December 7, 2022 15:58
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save taviso/767fc1dfbe5632368081de10fb7eeee9 to your computer and use it in GitHub Desktop.
Save taviso/767fc1dfbe5632368081de10fb7eeee9 to your computer and use it in GitHub Desktop.
Enumerating Windows Messages
#include <windows.h>
#include <stdio.h>
#include <stdint.h>
#pragma comment(lib, "USER32")
FARPROC NtUserPostMessage;
BOOL CALLBACK QueryWindowMessageProc(HWND Window, LPARAM Param)
{
BOOL ReturnCode = TRUE;
DWORD Result;
CHAR Title[1024] = {0};
GetWindowText(Window, Title, sizeof Title);
for (DWORD MsgNum = 0; MsgNum <= UINT16_MAX; MsgNum++) {
switch (MsgNum) {
// Whitelisted messages.
case WM_NULL:
case WM_SIZE:
case WM_MOVE:
case WM_GETHOTKEY:
case WM_GETICON:
case WM_RENDERFORMAT:
case WM_DRAWCLIPBOARD:
case WM_CHANGECBCHAIN:
case WM_DWMNCRENDERINGCHANGED:
case WM_THEMECHANGED:
case WM_GETTEXT:
case WM_GETTEXTLENGTH:
case WM_TOUCH:
// WM_SYSMENU, used by explorer to make the right click menu on the previews.
case 0x313:
// Unknown, probably theme related.
case 0x31B:
continue;
}
if (NtUserPostMessage(Window, MsgNum, 0, 0)) {
fprintf(stderr, "Message %#x to \"%s\" was allowed!\n", MsgNum, Title);
ReturnCode = FALSE;
} else {
Result = GetLastError();
if (Result != ERROR_ACCESS_DENIED && Result != ERROR_INVALID_MESSAGE) {
fprintf(stderr, "Message %#x to \"%s\" didn't work, but wasnt denied (%#x).\n",
MsgNum,
Title,
Result);
}
}
}
fprintf(stderr, "Window %p \"%s\" completed.\n", Window, Title);
return ReturnCode;
}
int main(int argc, char **argv)
{
ULONG_PTR WindowId;
DWORD MessageId;
DWORD ThreadId;
CHAR Title[1024] = {0};
CHAR Class[1024] = {0};
// Windows will try to parse the data you provide to PostMessage() so it
// can marshal it. I only want to know if the message is allowed, so
// I'll use the system call directly and skip all the marshaling.
//
// This way I can just check if I got ERROR_ACCESS_DENIED and not worry about
// exceptions interfering with the test results.
NtUserPostMessage = GetProcAddress(LoadLibrary("WIN32U"), "NtUserPostMessage");
if (argc != 2) {
fprintf(stderr, "Usage: %s THREADID\n", *argv);
return 1;
}
ThreadId = strtoul(*++argv, NULL, 0);
EnumThreadWindows(ThreadId, QueryWindowMessageProc, 0);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment