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@tdcadsl.dk wrote:
- 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:
- Call call_stack_check_init().
- 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