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