user32 - set_active_window uses SendMessage instead
ofPostMessage for WM_ACTIVATEAPP messages.
Peter Dons Tychsen
donpedro at tdcadsl.dk
Sun Aug 5 14:12:08 CDT 2007
On Sat, 2007-08-04 at 12:04 +0900, Dmitry Timoshkov wrote:
> "Peter Dons Tychsen" <donpedro at tdcadsl.dk> wrote:
>
> > 1) Yes i did testing on Windows-XP. I did it by putting together various
> > examples and by checking with InSendMessage() for all cases. This
> > clearly showed that WM_ACTIVATEAPP was always posted and never sent.
>
> Looks like you misunderstood the InSendMessage behaviour and that led to
> some confusion.
>
> Wine test harness for message sequences works just fine, there is no need
> to blame it.
>
I have found a new way of proving that ACTIVATEAPP must be sent using
the PostMessage call and not the SendMessage call. I have also found a
way to extend the unit test system to cover this.
After realizing my bummer with InSendMessage() i set out to create a new
function that would do what i want: Check if a message was sent with
PostMessage() or SendMessage() on windows. I could not find any function
that would do this so i made my own hack (below):
This piece of code, if inserted into the test system, could (on original
Windows) show us which messages we are incorrectly posting or sending. I
can probably also be used for other test purposes. I works by checking
the call stack for the calls SendMessageA() and SendMessageW(). Works
like charm on Windows-XP. Will need some work to also work inside Wine,
but that is not important for now.
Usage:
1) Call call_stack_check_init().
2) Call called_from_send_message() inside the Proc handler.
Cheers,
/Pedro
------ CODE BEGIN --------
void call_stack_check_init(void)
{
HANDLE process = GetCurrentProcess();
SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
SymInitialize(process, NULL, TRUE);
}
#define SYM_MAX_NAME_SIZE 1000
BOOL call_stack_check_search(char *func)
{
STACKFRAME64 call_stack;
CONTEXT context;
HANDLE thread = GetCurrentThread();
SYMBOL_INFO *sym = (SYMBOL_INFO *) malloc(sizeof(SYMBOL_INFO) +
SYM_MAX_NAME_SIZE);
CHAR name[SYM_MAX_NAME_SIZE];
HANDLE process = GetCurrentProcess();
/* Setup symbol buffer */
ZeroMemory(sym, sizeof(SYMBOL_INFO) + SYM_MAX_NAME_SIZE);
sym->SizeOfStruct = sizeof(SYMBOL_INFO);
sym->MaxNameLen = SYM_MAX_NAME_SIZE;
/* Get thread context */
ZeroMemory(&context, sizeof(context));
context.ContextFlags = CONTEXT_FULL;
__asm call x;
__asm x: pop eax;
__asm mov context.Eip, eax;
__asm mov context.Ebp, ebp;
__asm mov context.Esp, esp;
/* Setup stack walk offset */
ZeroMemory(&call_stack, sizeof(call_stack));
call_stack.AddrPC.Offset = context.Eip;
call_stack.AddrStack.Offset = context.Esp;
call_stack.AddrFrame.Offset = context.Ebp;
call_stack.AddrPC.Mode = AddrModeFlat;
call_stack.AddrStack.Mode = AddrModeFlat;
call_stack.AddrFrame.Mode = AddrModeFlat;
while(1)
{
DWORD64 disp = 0;
/* Walk that rusty old stack... */
if(!StackWalk64(
IMAGE_FILE_MACHINE_I386,
process,
thread,
&call_stack,
NULL,
NULL,
SymFunctionTableAccess64,
SymGetModuleBase64,
NULL)) return FALSE;
/* Get the next symbol on stack */
if(SymFromAddr(GetCurrentProcess(), call_stack.AddrPC.Offset, &disp,
sym))
{
/* Make it readable */
UnDecorateSymbolName(sym->Name, name, SYM_MAX_NAME_SIZE,
UNDNAME_COMPLETE |
UNDNAME_NO_THISTYPE |
UNDNAME_NO_SPECIAL_SYMS |
UNDNAME_NO_MEMBER_TYPE |
UNDNAME_NO_MS_KEYWORDS |
UNDNAME_NO_ACCESS_SPECIFIERS);
/* Check for match */
if(!strcmp(func, name)) return TRUE;
}
}
return FALSE;
}
BOOL called_from_send_message(void)
{
if (call_stack_check_search("SendMessageW")) return TRUE;
if (call_stack_check_search("SendMessageA")) return TRUE;
return FALSE;
}
----- CODE END -----
More information about the wine-devel
mailing list