1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
|
void EndDeferWindowPosAsync(HDWP hWinPosInfo)
{
if(usingNT)
{
// The kernel-mode part of the Windows USER API has a function called NtUserEndDeferWindowPosEx.
// This function takes two parameters - the HDWP (the same one used for *DeferWindowPos functions),
// and a boolean parameter which dictates if the function should work asynchronously.
// The 2nd parameter is only used internally from Task Manager, so it wouldn't hang while tiling windows.
// EndDeferWindowPos in user32.dll is simply a wrapper around the NtUserEndDeferWindowPosEx syscall function,
// similar to:
//
// BOOL WINAPI EndDeferWindowPos(HDWP hWinPosInfo)
// {
// return NtUserEndDeferWindowPosEx(hWinPosInfo, FALSE);
// }
//
// The following code will get the address of NtUserEndDeferWindowPosEx, and call it directly.
HMODULE user32 = GetModuleHandle("user32.dll");
unsigned char* func = (unsigned char*)GetProcAddress(user32, "EndDeferWindowPos");
if(func && func[10]==0xE8) // CALL IMM32 opcode
{
// --------------- ERREUR CI-DESSOUS
typedef int WINAPI (*NtUserEndDeferWindowPosEx)(HDWP, BOOL); // ERREUR -----------------------------
// get address of NtUserEndDeferWindowPosEx, from within EndDeferWindowPos's code
NtUserEndDeferWindowPosEx func2 = (NtUserEndDeferWindowPosEx)
(func +
15 + // 10+5 (5 is size of the CALL instruction)
(func[11] << 0 | // CALL's argument is an offset relative to the address of the next instruction
func[12] << 8 |
func[13] << 16 |
func[14] << 24));
// call it
func2(hWinPosInfo, TRUE);
}
else // something's wrong, do it normally
EndDeferWindowPos(hWinPosInfo);
}
else
{
// the above can't apply to Win9x, try to create a simple thread to wrap around the potentially-blocking call
DWORD tid;
// this MIGHT be possible to write as CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)EndDeferWindowPos, ...) (that is,
// create the thread directly with the API), but the way compilers/linkers do DLL bindings could break this
CloseHandle(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)EndDeferWindowPosThreadProc, (LPVOID)hWinPosInfo, 0, &tid));
}
} |
Partager