--- sourceforge.net/trunk/seamlessrdp/ServerExe/HookDll/hookdll.c 2006/03/17 16:23:08 1160 +++ sourceforge.net/trunk/seamlessrdp/ServerExe/HookDll/hookdll.c 2006/03/21 14:58:29 1179 @@ -45,9 +45,18 @@ int g_instance_count SHARED = 0; // blocks for locally generated events +HWND g_block_move_hwnd SHARED = NULL; +unsigned int g_block_move_serial SHARED = 0; RECT g_block_move SHARED = { 0, 0, 0, 0 }; + +unsigned int g_blocked_zchange_serial SHARED = 0; HWND g_blocked_zchange[2] SHARED = { NULL, NULL }; + +unsigned int g_blocked_focus_serial SHARED = 0; HWND g_blocked_focus SHARED = NULL; + +unsigned int g_blocked_state_serial SHARED = 0; +HWND g_blocked_state_hwnd SHARED = NULL; int g_blocked_state SHARED = -1; #pragma data_seg () @@ -69,24 +78,107 @@ update_position(HWND hwnd) { RECT rect, blocked; + HWND blocked_hwnd; + unsigned int serial; + + WaitForSingleObject(g_mutex, INFINITE); + blocked_hwnd = g_block_move_hwnd; + serial = g_block_move_serial; + memcpy(&blocked, &g_block_move, sizeof(RECT)); + ReleaseMutex(g_mutex); + + vchannel_block(); if (!GetWindowRect(hwnd, &rect)) { debug("GetWindowRect failed!\n"); - return; + goto end; } - WaitForSingleObject(g_mutex, INFINITE); - memcpy(&blocked, &g_block_move, sizeof(RECT)); - ReleaseMutex(g_mutex); - - if ((rect.left == blocked.left) && (rect.top == blocked.top) + if ((hwnd == blocked_hwnd) && (rect.left == blocked.left) && (rect.top == blocked.top) && (rect.right == blocked.right) && (rect.bottom == blocked.bottom)) - return; + goto end; - vchannel_write("POSITION,0x%p,%d,%d,%d,%d,0x%x", + vchannel_write("POSITION", "0x%p,%d,%d,%d,%d,0x%x", hwnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0); + + end: + vchannel_unblock(); +} + +static void +update_zorder(HWND hwnd) +{ + HWND behind; + HWND block_hwnd, block_behind; + unsigned int serial; + + WaitForSingleObject(g_mutex, INFINITE); + serial = g_blocked_zchange_serial; + block_hwnd = g_blocked_zchange[0]; + block_behind = g_blocked_zchange[1]; + ReleaseMutex(g_mutex); + + vchannel_block(); + + behind = GetNextWindow(hwnd, GW_HWNDPREV); + while (behind) + { + LONG style; + + style = GetWindowLong(behind, GWL_STYLE); + + if ((!(style & WS_CHILD) || (style & WS_POPUP)) && (style & WS_VISIBLE)) + break; + + behind = GetNextWindow(behind, GW_HWNDPREV); + } + + if ((hwnd == block_hwnd) && (behind == block_behind)) + vchannel_write("ACK", "%u", serial); + else + vchannel_write("ZCHANGE", "0x%p,0x%p,0x%x", hwnd, behind, 0); + + vchannel_unblock(); +} + +static HWND +get_parent(HWND hwnd) +{ + LONG style; + HWND parent; + + style = GetWindowLong(hwnd, GWL_STYLE); + + if (style & (WS_POPUP | DS_MODALFRAME)) + { + parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT); + + if (parent) + { + style = GetWindowLong(parent, GWL_STYLE); + if (((style & WS_CHILD) && !(style & WS_POPUP)) || !(style & WS_VISIBLE)) + parent = NULL; + } + + if (!parent) + parent = GetWindow(hwnd, GW_OWNER); + + if (parent) + { + style = GetWindowLong(parent, GWL_STYLE); + if (((style & WS_CHILD) && !(style & WS_POPUP)) || !(style & WS_VISIBLE)) + parent = NULL; + } + + if (!parent) + parent = (HWND) - 1; + } + else + parent = NULL; + + return parent; } static LRESULT CALLBACK @@ -114,14 +206,7 @@ if ((style & WS_CHILD) && !(style & WS_POPUP)) goto end; - if (style & WS_POPUP) - { - parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT); - if (!parent) - parent = (HWND) - 1; - } - else - parent = NULL; + parent = get_parent(hwnd); switch (msg) { @@ -133,12 +218,22 @@ { unsigned short title[150]; int state; + DWORD pid; + int flags; + + GetWindowThreadProcessId(hwnd, &pid); - vchannel_write("CREATE,0x%p,0x%p,0x%x", hwnd, parent, 0); + flags = 0; + if (style & DS_MODALFRAME) + flags |= SEAMLESS_CREATE_MODAL; + + vchannel_write("CREATE", "0x%08lx,0x%08lx,0x%08lx,0x%08x", + (long) hwnd, (long) pid, (long) parent, + flags); GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title)); - vchannel_write("TITLE,0x%x,%s,0x%x", hwnd, + vchannel_write("TITLE", "0x%x,%s,0x%x", hwnd, vchannel_strfilter_unicode(title), 0); if (style & WS_MAXIMIZE) @@ -150,11 +245,11 @@ update_position(hwnd); - vchannel_write("STATE,0x%p,0x%x,0x%x", hwnd, state, 0); + vchannel_write("STATE", "0x%p,0x%x,0x%x", hwnd, state, 0); } if (wp->flags & SWP_HIDEWINDOW) - vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0); + vchannel_write("DESTROY", "0x%p,0x%x", hwnd, 0); if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE)) break; @@ -162,24 +257,6 @@ if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE)) update_position(hwnd); - if (!(wp->flags & SWP_NOZORDER)) - { - HWND block_hwnd, block_behind; - WaitForSingleObject(g_mutex, INFINITE); - block_hwnd = g_blocked_zchange[0]; - block_behind = g_blocked_zchange[1]; - ReleaseMutex(g_mutex); - - if ((hwnd != block_hwnd) - || (wp->hwndInsertAfter != block_behind)) - { - vchannel_write("ZCHANGE,0x%p,0x%p,0x%x", - hwnd, - wp->flags & SWP_NOACTIVATE ? wp-> - hwndInsertAfter : 0, 0); - } - } - break; } @@ -198,7 +275,7 @@ case WM_DESTROY: if (!(style & WS_VISIBLE)) break; - vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0); + vchannel_write("DESTROY", "0x%p,0x%x", hwnd, 0); break; default: @@ -234,17 +311,24 @@ if ((style & WS_CHILD) && !(style & WS_POPUP)) goto end; - if (style & WS_POPUP) - { - parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT); - if (!parent) - parent = (HWND) - 1; - } - else - parent = NULL; + parent = get_parent(hwnd); switch (msg) { + case WM_WINDOWPOSCHANGED: + { + WINDOWPOS *wp = (WINDOWPOS *) lparam; + + if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE)) + break; + + if (!(wp->flags & SWP_NOZORDER)) + update_zorder(hwnd); + + break; + } + + case WM_SETTEXT: { unsigned short title[150]; @@ -253,7 +337,7 @@ /* We cannot use the string in lparam because we need unicode. */ GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title)); - vchannel_write("TITLE,0x%p,%s,0x%x", hwnd, + vchannel_write("TITLE", "0x%p,%s,0x%x", hwnd, vchannel_strfilter_unicode(title), 0); break; } @@ -268,6 +352,8 @@ way to solve this. */ if ((GetActiveWindow() != hwnd) && !parent) SetActiveWindow(hwnd); + + vchannel_write("ACK", "%u", g_blocked_focus_serial); } end: @@ -285,8 +371,12 @@ case HCBT_MINMAX: { int show, state, blocked; + HWND blocked_hwnd; + unsigned int serial; WaitForSingleObject(g_mutex, INFINITE); + blocked_hwnd = g_blocked_state_hwnd; + serial = g_blocked_state_serial; blocked = g_blocked_state; ReleaseMutex(g_mutex); @@ -305,9 +395,11 @@ break; } - if (blocked != state) - vchannel_write("STATE,0x%p,0x%x,0x%x", (HWND) wparam, state, - 0); + if ((blocked_hwnd == (HWND) wparam) && (blocked == state)) + vchannel_write("ACK", "%u", serial); + else + vchannel_write("STATE", "0x%p,0x%x,0x%x", (HWND) wparam, + state, 0); break; } @@ -348,9 +440,13 @@ } DLL_EXPORT void -SafeMoveWindow(HWND hwnd, int x, int y, int width, int height) +SafeMoveWindow(unsigned int serial, HWND hwnd, int x, int y, int width, int height) { + RECT rect; + WaitForSingleObject(g_mutex, INFINITE); + g_block_move_hwnd = hwnd; + g_block_move_serial = serial; g_block_move.left = x; g_block_move.top = y; g_block_move.right = x + width; @@ -359,22 +455,32 @@ SetWindowPos(hwnd, NULL, x, y, width, height, SWP_NOACTIVATE | SWP_NOZORDER); + vchannel_write("ACK", "%u", serial); + + if (!GetWindowRect(hwnd, &rect)) + debug("GetWindowRect failed!\n"); + else if ((rect.left != x) || (rect.top != y) || (rect.right != x + width) + || (rect.bottom != y + height)) + update_position(hwnd); + WaitForSingleObject(g_mutex, INFINITE); + g_block_move_hwnd = NULL; memset(&g_block_move, 0, sizeof(RECT)); ReleaseMutex(g_mutex); } DLL_EXPORT void -SafeZChange(HWND hwnd, HWND behind) +SafeZChange(unsigned int serial, HWND hwnd, HWND behind) { - if (behind == NULL) - behind = HWND_TOP; - WaitForSingleObject(g_mutex, INFINITE); + g_blocked_zchange_serial = serial; g_blocked_zchange[0] = hwnd; g_blocked_zchange[1] = behind; ReleaseMutex(g_mutex); + if (behind == NULL) + behind = HWND_TOP; + SetWindowPos(hwnd, behind, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); WaitForSingleObject(g_mutex, INFINITE); @@ -384,9 +490,10 @@ } DLL_EXPORT void -SafeFocus(HWND hwnd) +SafeFocus(unsigned int serial, HWND hwnd) { WaitForSingleObject(g_mutex, INFINITE); + g_blocked_focus_serial = serial; g_blocked_focus = hwnd; ReleaseMutex(g_mutex); @@ -398,12 +505,37 @@ } DLL_EXPORT void -SafeSetState(HWND hwnd, int state) +SafeSetState(unsigned int serial, HWND hwnd, int state) { + LONG style; + int curstate; + + vchannel_block(); + + style = GetWindowLong(hwnd, GWL_STYLE); + + if (style & WS_MAXIMIZE) + curstate = 2; + else if (style & WS_MINIMIZE) + curstate = 1; + else + curstate = 0; + + if (state == curstate) + { + vchannel_write("ACK", "%u", serial); + vchannel_unblock(); + return; + } + WaitForSingleObject(g_mutex, INFINITE); + g_blocked_state_hwnd = hwnd; + g_blocked_state_serial = serial; g_blocked_state = state; ReleaseMutex(g_mutex); + vchannel_unblock(); + if (state == 0) ShowWindow(hwnd, SW_RESTORE); else if (state == 1) @@ -414,6 +546,7 @@ debug("Invalid state %d sent.", state); WaitForSingleObject(g_mutex, INFINITE); + g_blocked_state_hwnd = NULL; g_blocked_state = -1; ReleaseMutex(g_mutex); }