user32 - set_active_window uses SendMessage instead ofPostMessage for WM_ACTIVATEAPP messages.

Peter Dons Tychsen donpedro at tdcadsl.dk
Sun Aug 5 14:13:59 CDT 2007


On Sun, 2007-08-05 at 21:12 +0200, Peter Dons Tychsen wrote:
> 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 -----

By the way, this code does prove (if run on Windows-XP), that
ACTIVATEAPP should be posted and not sent.

/pedro




More information about the wine-devel mailing list