From: Anders Kjersem <andersdev@proton.me> --- dlls/wshom.ocx/shell.c | 77 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/dlls/wshom.ocx/shell.c b/dlls/wshom.ocx/shell.c index 4056201a6b7..525dec7f932 100644 --- a/dlls/wshom.ocx/shell.c +++ b/dlls/wshom.ocx/shell.c @@ -1820,8 +1820,81 @@ static HRESULT WINAPI WshShell3_LogEvent(IWshShell3 *iface, VARIANT *Type, BSTR static HRESULT WINAPI WshShell3_AppActivate(IWshShell3 *iface, VARIANT *App, VARIANT *Wait, VARIANT_BOOL *out_Success) { - FIXME("(%s %s %p): stub\n", debugstr_variant(App), debugstr_variant(Wait), out_Success); - return E_NOTIMPL; + HRESULT hr = S_FALSE; + HWND hWnd = GetWindow(GetDesktopWindow(), GW_CHILD); + HWND hWndTarget = NULL; + VARIANT vTmp; + if (!App) + return E_POINTER; + + V_VT(&vTmp) = VT_EMPTY; + if (V_VT(App) != VT_BSTR && SUCCEEDED(VariantChangeType(&vTmp, App, 0, VT_I4)) && V_I4(&vTmp)) + { + DWORD pidFind = V_I4(&vTmp), pid; + for (; hWnd; hWnd = GetWindow(hWnd, GW_HWNDNEXT)) + { + if (!GetWindowThreadProcessId(hWnd, &pid) || pid != pidFind || !IsWindowVisible(hWnd)) + continue; + if (IsWindowEnabled(hWnd)) + { + hWndTarget = hWnd; + break; // Enabled and visible, we are done + } + else if (!hWndTarget) + { + hWndTarget = hWnd; // We will accept a disabled window if we have to + } + } + } + else if (SUCCEEDED(VariantChangeType(&vTmp, App, 0, VT_BSTR))) + { + BSTR bsFind = V_BSTR(&vTmp); + UINT lenFind = lstrlenW(bsFind); + for (; hWnd && !hWndTarget && lenFind; hWnd = GetWindow(hWnd, GW_HWNDNEXT)) + { + UINT cch = GetWindowTextLengthW(hWnd); + if (!cch) + continue; + BSTR bsBuf = SysAllocStringLen(NULL, ++cch); + if (!bsBuf) + { + hr = E_OUTOFMEMORY; + break; + } + cch = GetWindowTextW(hWnd, bsBuf, cch); + if (cch >= lenFind && CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, bsBuf, + lenFind, bsFind, lenFind) == CSTR_EQUAL) + { + hWndTarget = hWnd; + } + SysFreeString(bsBuf); + } + VariantClear(&vTmp); + } + + if (hWndTarget) + { + DWORD mytid = GetCurrentThreadId(), pid; + DWORD othertid = GetWindowThreadProcessId(hWnd, &pid); + BOOL attached = AttachThreadInput(mytid, othertid, TRUE); + SetForegroundWindow(hWndTarget); + V_VT(&vTmp) = VT_EMPTY; + if (Wait && !is_optional_argument(Wait) && + SUCCEEDED(VariantChangeType(&vTmp, Wait, 0, VT_BOOL)) && V_BOOL(&vTmp)) + { + UINT wait = 2000, interval = 100; + for (; wait && GetForegroundWindow() != hWndTarget; wait -= interval) + Sleep(interval); + } + SetLastError(0); + hr = (SetFocus(hWndTarget) || !GetLastError()) ? S_OK : S_FALSE; + if (attached) + AttachThreadInput(mytid, othertid, FALSE); + } + + if (out_Success) + *out_Success = (hr == S_OK) ? VARIANT_TRUE : VARIANT_FALSE; + return hr; } static HRESULT WINAPI WshShell3_SendKeys(IWshShell3 *iface, BSTR Keys, VARIANT *Wait) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11157