fix(desktop-wake): avoid in-process UIA FindAll crash (1.2.4)
All checks were successful
Publish Python Package to Gitea / publish (push) Successful in 27s
All checks were successful
Publish Python Package to Gitea / publish (push) Successful in 27s
Keep DuiLib subclass wake only with GETOBJECT reentrancy guard; let ensure probe warm out-of-process. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "jiangchang-platform-kit"
|
name = "jiangchang-platform-kit"
|
||||||
version = "1.2.3"
|
version = "1.2.4"
|
||||||
description = "匠厂平台共享组件:Skill 实体 SDK + 桌面应用自动化 SDK + 桌面 UIA 暖树"
|
description = "匠厂平台共享组件:Skill 实体 SDK + 桌面应用自动化 SDK + 桌面 UIA 暖树"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
# jiangchang_desktop_wake 验收(阶段 A:ensure 主路径)
|
# jiangchang_desktop_wake 验收(ensure 主路径,1.2.4+)
|
||||||
|
|
||||||
正式对外路径是 **`ensure`**(内部:`activate` → `desktop-wake --mode n2-wake` → `probe`)。
|
正式对外路径是 **`ensure`**(内部:`activate` → `desktop-wake --mode n2-wake` → `probe`)。
|
||||||
|
`n2-wake` **不再**在企微进程内跑 UIAutomation FindAll(防 `uiautomationcore.dll` 崩溃);判暖只看进程外 probe。
|
||||||
`c2` / `inject` 仅诊断用。
|
`c2` / `inject` 仅诊断用。
|
||||||
|
|
||||||
## 0. 编译(企微先完全退出,含托盘)
|
## 0. 编译(企微先完全退出,含托盘)
|
||||||
@@ -56,8 +57,9 @@ python -m jiangchang_desktop_wake probe --profile wecom
|
|||||||
| `probe_after.findall_count` | **≥ 80**(常见 300+) |
|
| `probe_after.findall_count` | **≥ 80**(常见 300+) |
|
||||||
| markers | 含 `con_op`、`searchedit` |
|
| markers | 含 `con_op`、`searchedit` |
|
||||||
| 企微 UI | 可点,无「未响应」 |
|
| 企微 UI | 可点,无「未响应」 |
|
||||||
| provider | `done=1` `subclass=1` `dui=1` `lr_client≠0` |
|
| provider | `done=1` `subclass=1` `dui=1` `no_inproc_uia=1`;`lr_client≠0` 更佳 |
|
||||||
| subclass | `method=SetWindowLongPtr`,`ok=1`,`userdata≠0` |
|
| subclass | `method=SetWindowLongPtr`,`ok=1`,`userdata≠0` |
|
||||||
|
| 企微进程 | **不崩**、无「错误报告」对话框 |
|
||||||
|
|
||||||
### 失败时
|
### 失败时
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
桌面 UIA Provider **暖树**(与 `jiangchang_skill_core` / `jiangchang_desktop_sdk` 平级)。
|
桌面 UIA Provider **暖树**(与 `jiangchang_skill_core` / `jiangchang_desktop_sdk` 平级)。
|
||||||
|
|
||||||
企微主路径:注入 `wecom_wake.dll`,对主窗 `SetWindowLongPtr` 后走 DuiLib
|
企微主路径:注入 `wecom_wake.dll`,对主窗 `SetWindowLongPtr` 后走 DuiLib
|
||||||
`GetAccessible` / `OnGetObject`(已验收冷树 findall 2→300+)。
|
`GetAccessible` / `OnGetObject`;**不在进程内 FindAll**(1.2.4+,避免 uiautomationcore 崩溃)。
|
||||||
|
|
||||||
可整目录删除:`src/jiangchang_desktop_wake` + `tests/desktop_wake`。
|
可整目录删除:`src/jiangchang_desktop_wake` + `tests/desktop_wake`。
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -6,23 +6,20 @@
|
|||||||
* WakeTarget — 旧子类化(危险,仅 n2-hook)
|
* WakeTarget — 旧子类化(危险,仅 n2-hook)
|
||||||
* JcCallWndProc — 旧钩子(危险,仅 n2-hook)
|
* JcCallWndProc — 旧钩子(危险,仅 n2-hook)
|
||||||
*
|
*
|
||||||
* C2+ 主路径:
|
* 1.2.4 主路径(防 uiautomationcore 崩):
|
||||||
* 1) STA 工作线程 + 进程内 UIA(保持客户端)
|
* - SetWindowLongPtr 子类化,WM_GETOBJECT → DuiLib GetAccessible/OnGetObject
|
||||||
* 2) SetWindowSubclass:WM_GETOBJECT 时走 DuiLib 已导出的
|
* - 重入守卫:处理 GETOBJECT 时不再二次进 DuiLib
|
||||||
* GetAccessible / OnGetObject(不挂钩、不用 CreateStdAccessibleObject)
|
* - 不做进程内 UIAutomation FindAll / AccessibleObjectFromWindow(判暖交给进程外 probe)
|
||||||
*/
|
*/
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <commctrl.h>
|
#include <commctrl.h>
|
||||||
#include <oleacc.h>
|
#include <oleacc.h>
|
||||||
#include <UIAutomationClient.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#pragma comment(lib, "oleacc.lib")
|
#pragma comment(lib, "oleacc.lib")
|
||||||
#pragma comment(lib, "ole32.lib")
|
#pragma comment(lib, "ole32.lib")
|
||||||
#pragma comment(lib, "oleaut32.lib")
|
|
||||||
#pragma comment(lib, "uuid.lib")
|
|
||||||
#pragma comment(lib, "user32.lib")
|
#pragma comment(lib, "user32.lib")
|
||||||
#pragma comment(lib, "comctl32.lib")
|
#pragma comment(lib, "comctl32.lib")
|
||||||
|
|
||||||
@@ -35,9 +32,6 @@
|
|||||||
#ifndef CHILDID_SELF
|
#ifndef CHILDID_SELF
|
||||||
#define CHILDID_SELF 0
|
#define CHILDID_SELF 0
|
||||||
#endif
|
#endif
|
||||||
#ifndef ANR_ON
|
|
||||||
#define ANR_ON 0x00000001
|
|
||||||
#endif
|
|
||||||
#ifndef UiaRootObjectId
|
#ifndef UiaRootObjectId
|
||||||
#define UiaRootObjectId ((LONG)0xFFFFFFE7)
|
#define UiaRootObjectId ((LONG)0xFFFFFFE7)
|
||||||
#endif
|
#endif
|
||||||
@@ -49,23 +43,21 @@
|
|||||||
static HMODULE g_self = NULL;
|
static HMODULE g_self = NULL;
|
||||||
static HWND g_hwnd = NULL;
|
static HWND g_hwnd = NULL;
|
||||||
static WNDPROC g_oldProc = NULL;
|
static WNDPROC g_oldProc = NULL;
|
||||||
|
static WNDPROC g_duiOldProc = NULL;
|
||||||
static volatile LONG g_getobjectHits = 0;
|
static volatile LONG g_getobjectHits = 0;
|
||||||
static volatile LONG g_hookHits = 0;
|
static volatile LONG g_hookHits = 0;
|
||||||
static volatile LONG g_duiHits = 0;
|
static volatile LONG g_duiHits = 0;
|
||||||
|
static volatile LONG g_reenterSkip = 0;
|
||||||
|
static volatile LONG g_subclassInstalled = 0;
|
||||||
|
|
||||||
static HANDLE g_staThread = NULL;
|
static HANDLE g_staThread = NULL;
|
||||||
static HANDLE g_staReady = NULL;
|
static HANDLE g_staReady = NULL;
|
||||||
static HWND g_msgHwnd = NULL;
|
static HWND g_msgHwnd = NULL;
|
||||||
static volatile LONG g_staStarted = 0;
|
static volatile LONG g_staStarted = 0;
|
||||||
|
|
||||||
static IUIAutomation* g_auto = NULL;
|
/* per-thread reentrancy guard for WM_GETOBJECT */
|
||||||
static IUIAutomationElement* g_root = NULL;
|
static __declspec(thread) int t_inGetObject = 0;
|
||||||
static IUIAutomationElementArray* g_arr = NULL;
|
|
||||||
static IAccessible* g_acc = NULL;
|
|
||||||
|
|
||||||
static volatile LONG g_subclassInstalled = 0;
|
|
||||||
|
|
||||||
/* DuiLib thiscall helpers (x86) */
|
|
||||||
typedef IAccessible*(__thiscall* FnGetAccessible)(void* self);
|
typedef IAccessible*(__thiscall* FnGetAccessible)(void* self);
|
||||||
typedef LRESULT(__thiscall* FnOnGetObject)(
|
typedef LRESULT(__thiscall* FnOnGetObject)(
|
||||||
void* self, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* bHandled);
|
void* self, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* bHandled);
|
||||||
@@ -138,25 +130,6 @@ static void NudgeWinEvents(HWND hwnd)
|
|||||||
PostMessageW(hwnd, WM_NULL, 0, 0);
|
PostMessageW(hwnd, WM_NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TryAccUtilityState(HWND hwnd)
|
|
||||||
{
|
|
||||||
HMODULE oleacc = GetModuleHandleW(L"oleacc.dll");
|
|
||||||
if (!oleacc) oleacc = LoadLibraryW(L"oleacc.dll");
|
|
||||||
if (!oleacc) return;
|
|
||||||
typedef HRESULT(WINAPI* PFN)(HWND, DWORD, DWORD);
|
|
||||||
PFN fn = (PFN)GetProcAddress(oleacc, "AccSetRunningUtilityState");
|
|
||||||
if (!fn) return;
|
|
||||||
fn(hwnd, ANR_ON, ANR_ON);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ReleaseKeepAlive()
|
|
||||||
{
|
|
||||||
if (g_arr) { g_arr->Release(); g_arr = NULL; }
|
|
||||||
if (g_root) { g_root->Release(); g_root = NULL; }
|
|
||||||
if (g_auto) { g_auto->Release(); g_auto = NULL; }
|
|
||||||
if (g_acc) { g_acc->Release(); g_acc = NULL; }
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ResolveDuiLib()
|
static bool ResolveDuiLib()
|
||||||
{
|
{
|
||||||
if (g_fnGetAccessible && g_fnOnGetObject) return true;
|
if (g_fnGetAccessible && g_fnOnGetObject) return true;
|
||||||
@@ -171,7 +144,6 @@ static bool ResolveDuiLib()
|
|||||||
return g_fnGetAccessible != NULL || g_fnOnGetObject != NULL;
|
return g_fnGetAccessible != NULL || g_fnOnGetObject != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Force DuiLib MSAA for WM_GETOBJECT — no CreateStdAccessibleObject (avoids UI hang). */
|
|
||||||
static LRESULT TryDuiLibGetObject(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
static LRESULT TryDuiLibGetObject(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
if (!ResolveDuiLib())
|
if (!ResolveDuiLib())
|
||||||
@@ -194,7 +166,6 @@ static LRESULT TryDuiLibGetObject(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||||||
IAccessible* acc = g_fnGetAccessible(self);
|
IAccessible* acc = g_fnGetAccessible(self);
|
||||||
if (acc) {
|
if (acc) {
|
||||||
LRESULT lr = LresultFromObject(IID_IAccessible, wParam, (LPUNKNOWN)acc);
|
LRESULT lr = LresultFromObject(IID_IAccessible, wParam, (LPUNKNOWN)acc);
|
||||||
/* LresultFromObject AddRef's; release our ref from GetAccessible */
|
|
||||||
acc->Release();
|
acc->Release();
|
||||||
return lr;
|
return lr;
|
||||||
}
|
}
|
||||||
@@ -202,7 +173,33 @@ static LRESULT TryDuiLibGetObject(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WNDPROC g_duiOldProc = NULL;
|
static LRESULT HandleGetObject(
|
||||||
|
HWND hwnd, WPARAM wParam, LPARAM lParam, WNDPROC oldProc, bool useDefSubclass)
|
||||||
|
{
|
||||||
|
InterlockedIncrement(&g_getobjectHits);
|
||||||
|
|
||||||
|
if (t_inGetObject) {
|
||||||
|
InterlockedIncrement(&g_reenterSkip);
|
||||||
|
if (useDefSubclass)
|
||||||
|
return DefSubclassProc(hwnd, WM_GETOBJECT, wParam, lParam);
|
||||||
|
if (oldProc)
|
||||||
|
return CallWindowProcW(oldProc, hwnd, WM_GETOBJECT, wParam, lParam);
|
||||||
|
return DefWindowProcW(hwnd, WM_GETOBJECT, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
t_inGetObject = 1;
|
||||||
|
LRESULT r = 0;
|
||||||
|
if (useDefSubclass)
|
||||||
|
r = DefSubclassProc(hwnd, WM_GETOBJECT, wParam, lParam);
|
||||||
|
else if (oldProc)
|
||||||
|
r = CallWindowProcW(oldProc, hwnd, WM_GETOBJECT, wParam, lParam);
|
||||||
|
|
||||||
|
if (r == 0)
|
||||||
|
r = TryDuiLibGetObject(hwnd, wParam, lParam);
|
||||||
|
|
||||||
|
t_inGetObject = 0;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static LRESULT CALLBACK DuiSubclassProc(
|
static LRESULT CALLBACK DuiSubclassProc(
|
||||||
HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
|
HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
|
||||||
@@ -210,34 +207,15 @@ static LRESULT CALLBACK DuiSubclassProc(
|
|||||||
{
|
{
|
||||||
(void)uIdSubclass;
|
(void)uIdSubclass;
|
||||||
(void)dwRefData;
|
(void)dwRefData;
|
||||||
if (uMsg == WM_GETOBJECT) {
|
if (uMsg == WM_GETOBJECT)
|
||||||
InterlockedIncrement(&g_getobjectHits);
|
return HandleGetObject(hWnd, wParam, lParam, NULL, true);
|
||||||
LRESULT r = DefSubclassProc(hWnd, uMsg, wParam, lParam);
|
|
||||||
if (r != 0)
|
|
||||||
return r;
|
|
||||||
r = TryDuiLibGetObject(hWnd, wParam, lParam);
|
|
||||||
if (r != 0)
|
|
||||||
return r;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
|
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fallback when comctl SetWindowSubclass unavailable in host */
|
|
||||||
static LRESULT CALLBACK DuiWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
static LRESULT CALLBACK DuiWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
if (msg == WM_GETOBJECT) {
|
if (msg == WM_GETOBJECT)
|
||||||
InterlockedIncrement(&g_getobjectHits);
|
return HandleGetObject(hwnd, wParam, lParam, g_duiOldProc, false);
|
||||||
LRESULT r = 0;
|
|
||||||
if (g_duiOldProc)
|
|
||||||
r = CallWindowProcW(g_duiOldProc, hwnd, msg, wParam, lParam);
|
|
||||||
if (r != 0)
|
|
||||||
return r;
|
|
||||||
r = TryDuiLibGetObject(hwnd, wParam, lParam);
|
|
||||||
if (r != 0)
|
|
||||||
return r;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (g_duiOldProc)
|
if (g_duiOldProc)
|
||||||
return CallWindowProcW(g_duiOldProc, hwnd, msg, wParam, lParam);
|
return CallWindowProcW(g_duiOldProc, hwnd, msg, wParam, lParam);
|
||||||
return DefWindowProcW(hwnd, msg, wParam, lParam);
|
return DefWindowProcW(hwnd, msg, wParam, lParam);
|
||||||
@@ -251,21 +229,7 @@ static bool InstallDuiSubclass(HWND hwnd)
|
|||||||
|
|
||||||
ResolveDuiLib();
|
ResolveDuiLib();
|
||||||
void* userdata = (void*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
|
void* userdata = (void*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
|
||||||
LONG_PTR accPtr = 0;
|
|
||||||
LONG_PTR ongetLr = 0;
|
|
||||||
if (userdata && g_fnGetAccessible) {
|
|
||||||
IAccessible* acc = g_fnGetAccessible(userdata);
|
|
||||||
accPtr = (LONG_PTR)acc;
|
|
||||||
if (acc) {
|
|
||||||
long kids = -1;
|
|
||||||
acc->get_accChildCount(&kids);
|
|
||||||
ongetLr = kids;
|
|
||||||
/* keep one ref for diagnostics; Release extra if we AddRef'd — GetAccessible owns */
|
|
||||||
acc->Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 企微进程里 SetWindowSubclass 常失败;主用 SetWindowLongPtr(只转发 DuiLib GetAccessible,不挂钩) */
|
|
||||||
SetLastError(0);
|
SetLastError(0);
|
||||||
g_duiOldProc = (WNDPROC)SetWindowLongPtrW(
|
g_duiOldProc = (WNDPROC)SetWindowLongPtrW(
|
||||||
hwnd, GWLP_WNDPROC, (LONG_PTR)DuiWndProc);
|
hwnd, GWLP_WNDPROC, (LONG_PTR)DuiWndProc);
|
||||||
@@ -288,10 +252,9 @@ static bool InstallDuiSubclass(HWND hwnd)
|
|||||||
char line[512];
|
char line[512];
|
||||||
sprintf_s(line,
|
sprintf_s(line,
|
||||||
"hwnd=%p ok=%d gle=%lu method=%s userdata=%p "
|
"hwnd=%p ok=%d gle=%lu method=%s userdata=%p "
|
||||||
"getacc_ret=%p getacc_kids=%ld duilib=%p getacc=%p onget=%p\r\n",
|
"duilib=%p getacc=%p onget=%p\r\n",
|
||||||
hwnd, (int)ok, gle, method, userdata,
|
hwnd, (int)ok, gle, method, userdata,
|
||||||
(void*)accPtr, (long)ongetLr, g_duilib,
|
g_duilib, g_fnGetAccessible, g_fnOnGetObject);
|
||||||
g_fnGetAccessible, g_fnOnGetObject);
|
|
||||||
WriteMarker("jiangchang_desktop_wake_subclass.txt", line);
|
WriteMarker("jiangchang_desktop_wake_subclass.txt", line);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
InterlockedExchange(&g_subclassInstalled, 0);
|
InterlockedExchange(&g_subclassInstalled, 0);
|
||||||
@@ -300,78 +263,35 @@ static bool InstallDuiSubclass(HWND hwnd)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DoInProcessUiaWake(HWND hwnd)
|
/* 只装子类化 + 异步 nudge;可选一次短超时 GETOBJECT 看 lr(无进程内 UIA) */
|
||||||
|
static void DoSafeWake(HWND hwnd)
|
||||||
{
|
{
|
||||||
char line[1024];
|
char line[512];
|
||||||
LONG findall = -1;
|
|
||||||
LONG msaaKids = -1;
|
|
||||||
HRESULT hrAuto = E_FAIL;
|
|
||||||
HRESULT hrEl = E_FAIL;
|
|
||||||
HRESULT hrFind = E_FAIL;
|
|
||||||
HRESULT hrMsaa = E_FAIL;
|
|
||||||
LRESULT lrClient = 0;
|
LRESULT lrClient = 0;
|
||||||
LRESULT lrUia = 0;
|
|
||||||
int subclass_ok = 0;
|
int subclass_ok = 0;
|
||||||
int dui_ok = 0;
|
int dui_ok = 0;
|
||||||
|
|
||||||
TryAccUtilityState(hwnd);
|
|
||||||
ResolveDuiLib();
|
ResolveDuiLib();
|
||||||
dui_ok = (g_fnGetAccessible || g_fnOnGetObject) ? 1 : 0;
|
dui_ok = (g_fnGetAccessible || g_fnOnGetObject) ? 1 : 0;
|
||||||
subclass_ok = InstallDuiSubclass(hwnd) ? 1 : 0;
|
subclass_ok = InstallDuiSubclass(hwnd) ? 1 : 0;
|
||||||
|
|
||||||
NudgeWinEvents(hwnd);
|
NudgeWinEvents(hwnd);
|
||||||
|
|
||||||
/* Sync probe WM_GETOBJECT after subclass — goes through our handler */
|
DWORD_PTR smResult = 0;
|
||||||
lrClient = SendMessageW(hwnd, WM_GETOBJECT, 0, (LPARAM)OBJID_CLIENT);
|
if (SendMessageTimeoutW(
|
||||||
lrUia = SendMessageW(hwnd, WM_GETOBJECT, 0, (LPARAM)UiaRootObjectId);
|
hwnd, WM_GETOBJECT, 0, (LPARAM)OBJID_CLIENT,
|
||||||
|
SMTO_ABORTIFHUNG, 2000, &smResult)) {
|
||||||
ReleaseKeepAlive();
|
lrClient = (LRESULT)smResult;
|
||||||
|
|
||||||
hrAuto = CoCreateInstance(
|
|
||||||
CLSID_CUIAutomation, NULL, CLSCTX_INPROC_SERVER,
|
|
||||||
IID_IUIAutomation, (void**)&g_auto);
|
|
||||||
if (SUCCEEDED(hrAuto) && g_auto) {
|
|
||||||
hrEl = g_auto->ElementFromHandle(hwnd, &g_root);
|
|
||||||
if (SUCCEEDED(hrEl) && g_root) {
|
|
||||||
IUIAutomationCondition* cond = NULL;
|
|
||||||
if (SUCCEEDED(g_auto->CreateTrueCondition(&cond)) && cond) {
|
|
||||||
hrFind = g_root->FindAll(TreeScope_Subtree, cond, &g_arr);
|
|
||||||
cond->Release();
|
|
||||||
if (SUCCEEDED(hrFind) && g_arr) {
|
|
||||||
int len = 0;
|
|
||||||
if (SUCCEEDED(g_arr->get_Length(&len)))
|
|
||||||
findall = len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
IAccessible* acc = NULL;
|
|
||||||
hrMsaa = AccessibleObjectFromWindow(
|
|
||||||
hwnd, OBJID_CLIENT, IID_IAccessible, (void**)&acc);
|
|
||||||
if (SUCCEEDED(hrMsaa) && acc) {
|
|
||||||
g_acc = acc;
|
|
||||||
long kids = 0;
|
|
||||||
if (SUCCEEDED(acc->get_accChildCount(&kids)))
|
|
||||||
msaaKids = kids;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NudgeWinEvents(hwnd);
|
NudgeWinEvents(hwnd);
|
||||||
|
|
||||||
sprintf_s(line,
|
sprintf_s(line,
|
||||||
"hwnd=%p sta_tid=%lu findall=%ld msaa_kids=%ld "
|
"hwnd=%p sta_tid=%lu lr_client=%ld subclass=%d dui=%d "
|
||||||
"lr_client=%ld lr_uia=%ld subclass=%d dui=%d "
|
"dui_hits=%ld getobject_hits=%ld reenter_skip=%ld "
|
||||||
"dui_hits=%ld getobject_hits=%ld "
|
"no_inproc_uia=1 done=1\r\n",
|
||||||
"hr_auto=0x%08lx hr_el=0x%08lx hr_find=0x%08lx hr_msaa=0x%08lx "
|
hwnd, GetCurrentThreadId(), (long)lrClient, subclass_ok, dui_ok,
|
||||||
"keep_auto=%d keep_root=%d keep_arr=%d keep_acc=%d done=1\r\n",
|
(long)g_duiHits, (long)g_getobjectHits, (long)g_reenterSkip);
|
||||||
hwnd, GetCurrentThreadId(), (long)findall, (long)msaaKids,
|
|
||||||
(long)lrClient, (long)lrUia, subclass_ok, dui_ok,
|
|
||||||
(long)g_duiHits, (long)g_getobjectHits,
|
|
||||||
(unsigned long)hrAuto, (unsigned long)hrEl,
|
|
||||||
(unsigned long)hrFind, (unsigned long)hrMsaa,
|
|
||||||
g_auto ? 1 : 0, g_root ? 1 : 0, g_arr ? 1 : 0, g_acc ? 1 : 0);
|
|
||||||
WriteMarker("jiangchang_desktop_wake_provider.txt", line);
|
WriteMarker("jiangchang_desktop_wake_provider.txt", line);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,7 +300,7 @@ static LRESULT CALLBACK MsgWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
|
|||||||
if (msg == WM_JC_WAKE) {
|
if (msg == WM_JC_WAKE) {
|
||||||
HWND target = (HWND)wParam;
|
HWND target = (HWND)wParam;
|
||||||
if (target && IsWindow(target))
|
if (target && IsWindow(target))
|
||||||
DoInProcessUiaWake(target);
|
DoSafeWake(target);
|
||||||
else
|
else
|
||||||
WriteMarker("jiangchang_desktop_wake_provider.txt", "err=bad_hwnd done=1\r\n");
|
WriteMarker("jiangchang_desktop_wake_provider.txt", "err=bad_hwnd done=1\r\n");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -394,9 +314,6 @@ static LRESULT CALLBACK MsgWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
|
|||||||
|
|
||||||
static DWORD WINAPI StaThreadProc(LPVOID)
|
static DWORD WINAPI StaThreadProc(LPVOID)
|
||||||
{
|
{
|
||||||
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
|
||||||
bool needUninit = SUCCEEDED(hr) || hr == S_FALSE;
|
|
||||||
|
|
||||||
WNDCLASSW wc;
|
WNDCLASSW wc;
|
||||||
ZeroMemory(&wc, sizeof(wc));
|
ZeroMemory(&wc, sizeof(wc));
|
||||||
wc.lpfnWndProc = MsgWndProc;
|
wc.lpfnWndProc = MsgWndProc;
|
||||||
@@ -413,7 +330,6 @@ static DWORD WINAPI StaThreadProc(LPVOID)
|
|||||||
|
|
||||||
if (!g_msgHwnd) {
|
if (!g_msgHwnd) {
|
||||||
WriteMarker("jiangchang_desktop_wake_provider.txt", "err=no_msg_hwnd done=1\r\n");
|
WriteMarker("jiangchang_desktop_wake_provider.txt", "err=no_msg_hwnd done=1\r\n");
|
||||||
if (needUninit) CoUninitialize();
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -423,12 +339,10 @@ static DWORD WINAPI StaThreadProc(LPVOID)
|
|||||||
DispatchMessageW(&msg);
|
DispatchMessageW(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReleaseKeepAlive();
|
|
||||||
if (g_msgHwnd) {
|
if (g_msgHwnd) {
|
||||||
DestroyWindow(g_msgHwnd);
|
DestroyWindow(g_msgHwnd);
|
||||||
g_msgHwnd = NULL;
|
g_msgHwnd = NULL;
|
||||||
}
|
}
|
||||||
if (needUninit) CoUninitialize();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -475,7 +389,7 @@ extern "C" __declspec(dllexport) DWORD WINAPI WakeProvider(LPVOID param)
|
|||||||
DWORD_PTR result = 0;
|
DWORD_PTR result = 0;
|
||||||
LRESULT ok = SendMessageTimeoutW(
|
LRESULT ok = SendMessageTimeoutW(
|
||||||
g_msgHwnd, WM_JC_WAKE, (WPARAM)hwnd, 0,
|
g_msgHwnd, WM_JC_WAKE, (WPARAM)hwnd, 0,
|
||||||
SMTO_ABORTIFHUNG, 15000, &result);
|
SMTO_ABORTIFHUNG, 8000, &result);
|
||||||
|
|
||||||
if (ok == 0) {
|
if (ok == 0) {
|
||||||
char line[256];
|
char line[256];
|
||||||
@@ -519,13 +433,7 @@ static LRESULT TryStdAccessible(HWND hwnd, WPARAM wParam, LONG objId)
|
|||||||
static LRESULT CALLBACK SubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
static LRESULT CALLBACK SubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
if (msg == WM_GETOBJECT) {
|
if (msg == WM_GETOBJECT) {
|
||||||
InterlockedIncrement(&g_getobjectHits);
|
LRESULT r = HandleGetObject(hwnd, wParam, lParam, g_oldProc, false);
|
||||||
LRESULT r = 0;
|
|
||||||
if (g_oldProc)
|
|
||||||
r = CallWindowProcW(g_oldProc, hwnd, msg, wParam, lParam);
|
|
||||||
if (r != 0)
|
|
||||||
return r;
|
|
||||||
r = TryDuiLibGetObject(hwnd, wParam, lParam);
|
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
LONG objId = (LONG)lParam;
|
LONG objId = (LONG)lParam;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ $bat = Join-Path $env:TEMP "jiangchang_build_wecom_wake.bat"
|
|||||||
@"
|
@"
|
||||||
@echo off
|
@echo off
|
||||||
call "$vcvars32" || exit /b 1
|
call "$vcvars32" || exit /b 1
|
||||||
cl /nologo /LD /O2 /EHsc /DWIN32 /D_WINDOWS /D_USRDLL /utf-8 "$srcCpp" /Fe"$dllTarget" /Fo"$objPath" /link /DEF:"$srcDef" user32.lib ole32.lib oleacc.lib oleaut32.lib uuid.lib comctl32.lib
|
cl /nologo /LD /O2 /EHsc /DWIN32 /D_WINDOWS /D_USRDLL /utf-8 "$srcCpp" /Fe"$dllTarget" /Fo"$objPath" /link /DEF:"$srcDef" user32.lib ole32.lib oleacc.lib comctl32.lib
|
||||||
exit /b %ERRORLEVEL%
|
exit /b %ERRORLEVEL%
|
||||||
"@ | Set-Content -Path $bat -Encoding ASCII
|
"@ | Set-Content -Path $bat -Encoding ASCII
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user