abdelkader
abdelkader

Reputation: 71

How to Reverse Engineer 'Windows Messages' in delphi applications

IDR is a good tool for decompiling Delphi applications, but hHow do I know the ID number of Windows messages assigned to message handlers?

For example, from IDR decompiling, I see:

procedure sub_004D2398(var Msg: TMsg);dynamic;

The original source code is:

procedure Name_procedure(var Msg: TMsg); message 1028;

How do I know the message number 1028 while reverse-engineering the code in IDR?

Upvotes: 1

Views: 858

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 596101

A given procedure doesn't know whether it is a message handler or not, because that information is not stored in the procedure itself where a decompiler can easily access it (it in available in RTTI, though).

Every class has its own dispatch table that the compiler generates to hold pointers to all of the class's dynamic and message methods (and in the case of message, also their message IDs). So, when you declare a class procedure as a message handler, the compiler inserts an entry for that message ID in that class's dispatch table along with a pointer to the handler.

When a UI control receives a message, the message first goes to the control's WindowProc (which the app can subclass directly). If the message is not handled, it goes to the control's WndProc() method. If the message is still not handled, it goes to the TObject.Dispatch() method, which looks up the message ID in the control's dispatch table and calls the associated procedure if one is found. Otherwise, the message goes to the control's DefaultHandler() method.

So, unless IDR is smart enough to decompile a procedure, determine which class it belongs to, and find and decompile that class's dispatch table or RTTI to determine the message ID belonging to the procedure, then you will have to do this manually while you are analyzing the decompiled output. A class's VMT contains pointers to the class's dispatch table and RTTI (amongst other things).

Once you are able to determine the message ID that belongs to a given message handler, only then can you research and figure out what kind of message that ID might refer to, as described in Deltics' answer.

Upvotes: 5

Deltics
Deltics

Reputation: 23036

Normally to find the message declaration corresponding to a given message number you would just look in any header file (C/C++) or unit (Delphi) that declares message constants. From memory I think in (older?) Delphi versions this is in the Windows unit, or possibly Messages.

In the case of Delphi you will find a bunch of declarations similar to:

const
  WM_LBUTTONDOWN = 513;

Or if in hex:

const
  WM_LBUTTONDOWN = $0201;

Just find the declaration for the WM_ constant with a value of 1028 (or the hex equivalent, $0404).

However you almost certainly will not find one!

Private Messages

1028 is greater than 1024, and 1024 is the constant for the "special message": WM_USER. This is not intended to be used as a message directly but rather indicates the first message number that an application can use for its own, custom/private messages.

i.e. the message with value 1028 has no standard meaning across all Windows applications.

Rather it is the 4th "custom" or private message (or possibly 5th - some people start with WM_USER+1 as documented, others start with WM_USER) used by, and meaningful to, only that application.

In the absence of the original declared constant name for the message, whatever it means and is used for can only be determined by inspecting the code and identifying its use within that code.

Upvotes: 0

Related Questions