You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在GetMsgProc钩子中调用GetPointerFrameTouchInfo遇Error 998求解决

在GetMsgProc钩子中调用GetPointerFrameTouchInfo返回Error 998的原因及解决方法

我之前在钩子场景里调用指针相关API时也踩过类似的坑,咱们一步步拆解这个Error 998(内存访问无效)的问题:

常见原因

  • 缓冲区分配逻辑错误:GetPointerFrameTouchInfo需要先查询所需的缓冲区大小,再对应分配内存。如果直接用固定大小的缓冲区,或者分配的内存不足/未正确初始化,函数会尝试访问超出缓冲区范围的内存,触发998错误。
  • 无效的Pointer ID:你传入的指针ID可能不是当前有效触摸指针的ID,或者在钩子触发时该指针的上下文已经失效,导致函数尝试访问无效的内存区域。
  • 线程上下文不匹配:GetMsgProc是运行在目标线程的上下文中的,如果你的缓冲区是在钩子所在的外部线程分配的(比如主进程堆),目标线程没有访问权限,也会触发内存访问错误。

针对性解决方法

  1. 严格遵循"先查大小再分配"的流程
    这是最容易踩坑的点,一定要先调用函数获取所需的触摸点数量,再分配对应内存,示例代码如下:

    UINT touchCount = 0;
    // 第一次调用:仅获取所需的触摸点数量
    if (GetPointerFrameTouchInfo(pointerId, &touchCount, NULL) == FALSE) {
        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
            // 在当前线程堆上分配内存(适配钩子的线程上下文)
            PTOUCH_POINTER_INFO pTouchData = (PTOUCH_POINTER_INFO)LocalAlloc(LPTR, touchCount * sizeof(TOUCH_POINTER_INFO));
            if (pTouchData != NULL) {
                // 第二次调用:获取实际触摸数据
                if (GetPointerFrameTouchInfo(pointerId, &touchCount, pTouchData)) {
                    // 在这里处理触摸数据
                }
                // 用完记得释放内存
                LocalFree(pTouchData);
            }
        }
    }
    

    这里用LocalAlloc是因为它会在当前线程的堆上分配内存,避免跨线程内存访问权限问题。

  2. 先验证Pointer ID的有效性
    在调用GetPointerFrameTouchInfo前,先确认指针ID是有效的触摸类型:

    POINTER_INPUT_TYPE pointerType;
    if (GetPointerType(pointerId, &pointerType) && pointerType == PT_TOUCH) {
        // 确认是有效触摸指针后,再调用获取帧信息的函数
    }
    
  3. 避免在钩子中使用跨线程内存
    绝对不要在钩子过程中使用主进程分配的全局缓冲区,必须在钩子执行的线程内分配内存(比如用LocalAlloc或HeapAlloc(GetCurrentProcessHeap(), ...)),确保目标线程拥有访问权限。

  4. 检查钩子的注入与权限
    如果是全局GetMsgProc钩子,确保你的DLL已经正确注入到目标进程,并且拥有足够的内存访问权限。另外,不要在钩子中执行耗时操作,防止破坏目标线程的上下文。

内容的提问来源于stack exchange,提问作者Wolverine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:09:17