user32 - set_active_window uses SendMessage instead ofPostMessage for WM_ACTIVATEAPP messages.

Peter Dons Tychsen donpedro at tdcadsl.dk
Sun Aug 5 19:46:10 CDT 2007


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

Oh dear... scrap that last comment.
With the comments from Alexandre this no longer valid.
It does not prove anything... back to the drawing board Peter... :-)

/Pedro




More information about the wine-devel mailing list