当前位置: 首页 > news >正文

InputApc()函数是如何调用ProcessKeyboardInput()函数的?

InputApc()函数是如何调用ProcessKeyboardInput()函数的?

下面是调用栈,这篇文章是解释第五行到第四行的。

.//ntuser/kernel/ntinput.c:2601:VOID xxxKeyEvent(

.//windows/core/ntuser/kernel/ntinput.c:4664:VOID xxxProcessKeyEvent(

.//core/ntuser/kernel/ntinput.c:58:VOID ProcessKeyboardInputWorker(PKEYBOARD_INPUT_DATA pkei,

.//core/ntuser/kernel/ntinput.c:4608:VOID ProcessKeyboardInput(PDEVICEINFO pDeviceInfo)

.//windows/core/ntuser/kernel/ntinput.c:2032:VOID NTAPI InputApc(

第一部分:userk.h

第一部分A

typedef struct tagKEYBOARD_DEVICE_INFO { // DEVICE_TYPE_KEYBOARD

    KEYBOARD_ATTRIBUTES  Attr;

    KEYBOARD_ID_EX IdEx;

    KEYBOARD_INPUT_DATA  Data[MAXIMUM_ITEMS_READ];

} KEYBOARD_DEVICE_INFO, *PKEYBOARD_DEVICE_INFO;

第一部分B

typedef struct tagGENERIC_DEVICE_INFO {

#ifdef GENERIC_INPUT

    HEAD                 head;

#endif

    struct tagDEVICEINFO *pNext;

    BYTE                 type;

    BYTE                 bFlags;

    USHORT               usActions;

    BYTE                 nRetryRead;

    UNICODE_STRING       ustrName;

    HANDLE               handle;

    PVOID                NotificationEntry;

    PKEVENT              pkeHidChangeCompleted; // wake RequestDeviceChange()

    IO_STATUS_BLOCK      iosb;

    NTSTATUS             ReadStatus;

#ifdef DIAGNOSE_IO

    HANDLE               OpenerProcess;

    NTSTATUS             OpenStatus;

    NTSTATUS             AttrStatus;

    ULONG                timeStartRead;     // tick before ZwReadFile

    ULONG                timeEndRead;       // tick after ZwReadFile

    int                  nReadsOutstanding; // ZwReadFile ++, consume data --

#endif

#ifdef PRERELEASE

    UINT                 fForcedDetach : 1; // Set if the device is forced detached from TS

#endif

} GENERIC_DEVICE_INFO, *PGENERIC_DEVICE_INFO;

第一部分C

// valuse for GENERIC_DEVICE_INFO.type

#define DEVICE_TYPE_MOUSE    0

#define DEVICE_TYPE_KEYBOARD 1

#ifdef GENERIC_INPUT

#define DEVICE_TYPE_HID      2

#define DEVICE_TYPE_MAX      2

#else

#define DEVICE_TYPE_MAX      1

#endif

第一部分D

typedef struct tagDEVICEINFO {

    GENERIC_DEVICE_INFO;

    union {

        MOUSE_DEVICE_INFO    mouse;

        KEYBOARD_DEVICE_INFO keyboard;

#ifdef GENERIC_INPUT

        HID_DEVICE_INFO hid;

#endif

    };

} DEVICEINFO, *PDEVICEINFO;

第一部分E

typedef struct tagDEVICE_TEMPLATE {

    SIZE_T cbDeviceInfo;        // bytes to allocate for DEVICEINFO

    const GUID *pClassGUID;     // GUID of the class

    UINT   uiRegistrySection;   // Parameters for class (HKLM\SYSTEM\CurrentControlSet\Services\*\Parameters)

    LPWSTR pwszClassName;       // Class name (eg: L"mouclass")

    LPWSTR pwszDefDevName;      // Default Device Name

    LPWSTR pwszLegacyDevName;   // Legacy Device Name (eg: "PointerClassLegacy0")

    ULONG  IOCTL_Attr;          // IOCTL_*_QUERY_ATTRIBUTES

    UINT   offAttr;             // offset of *_ATTRIBUTES struct within DEVICEINFO

    ULONG  cbAttr;              // sizeof *_ATTRIBUTES struct

    UINT   offData;             // offset of *_INPUT_DATA buffer within DEVICEINFO

    ULONG  cbData;              // sizeof *_INPUT_DATA buffer

    VOID   (*DeviceRead)(PDEVICEINFO); // routine to read the device

    PKEVENT pkeHidChange;       // event to signal changes to this sort of device

#ifdef GENERIC_INPUT

    DWORD dwFlags;              // Flags...

#endif

} DEVICE_TEMPLATE, *PDEVICE_TEMPLATE;

第二部分:pnp.c

DEVICE_TEMPLATE aDeviceTemplate[DEVICE_TYPE_MAX + 1] = {

    // DEVICE_TYPE_MOUSE

    {

        sizeof(GENERIC_DEVICE_INFO)+sizeof(MOUSE_DEVICE_INFO),    // cbDeviceInfo

        &GUID_CLASS_MOUSE,                                        // pClassGUID

        PMAP_MOUCLASS_PARAMS,                                     // uiRegistrySection

        L"mouclass",                                              // pwszClassName

        DD_MOUSE_DEVICE_NAME_U L"0",                              // pwszDefDevName

        DD_MOUSE_DEVICE_NAME_U L"Legacy0",                        // pwszLegacyDevName

        IOCTL_MOUSE_QUERY_ATTRIBUTES,                             // IOCTL_Attr

        FIELD_OFFSET(DEVICEINFO, mouse.Attr),                     // offAttr

        sizeof((PDEVICEINFO)NULL)->mouse.Attr,                    // cbAttr

        FIELD_OFFSET(DEVICEINFO, mouse.Data),                     // offData

        sizeof((PDEVICEINFO)NULL)->mouse.Data,                    // cbData

        ProcessMouseInput,                                        // Reader routine

        NULL                                                      // pkeHidChange

    },

    // DEVICE_TYPE_KEYBOARD

    {

        sizeof(GENERIC_DEVICE_INFO)+sizeof(KEYBOARD_DEVICE_INFO), // cbDeviceInfo

        &GUID_CLASS_KEYBOARD,                                     // pClassGUID

        PMAP_KBDCLASS_PARAMS,                                     // uiRegistrySection

        L"kbdclass",                                              // pwszClassName

        DD_KEYBOARD_DEVICE_NAME_U L"0",                           // pwszDefDevName

        DD_KEYBOARD_DEVICE_NAME_U L"Legacy0",                     // pwszLegacyDevName

        IOCTL_KEYBOARD_QUERY_ATTRIBUTES,                          // IOCTL_Attr

        FIELD_OFFSET(DEVICEINFO, keyboard.Attr),                  // offAttr

        sizeof((PDEVICEINFO)NULL)->keyboard.Attr,                 // cbAttr

        FIELD_OFFSET(DEVICEINFO, keyboard.Data),                  // offData

        sizeof((PDEVICEINFO)NULL)->keyboard.Data,                 // cbData

        ProcessKeyboardInput,                                     // Reader routine

        NULL                                                      // pkeHidChange

    },

#ifdef GENERIC_INPUT

    // DEVICE_TYPE_HID

    {

        sizeof(GENERIC_DEVICE_INFO)+sizeof(HID_DEVICE_INFO),        // cbDeviceInfo

        &GUID_CLASS_INPUT,                                          // pClassGUID

        0,                                                          // uiRegistrySection. LATER: add real one

        L"hid",                                                     // pwszClassName

        L"",                                                        // pwszDefDevName

        L"",                                                        // pwszLegacyDevName

        0,                                                          // IOCTL_ATTR

        0,                                                          // offAttr

        0,                                                          // cbAttr

        0,                                                          // offData

        0,                                                          // cbData

        ProcessHidInput,                                            // Reader routine

        NULL,                                                       // pkeHidChange,

        DT_HID,                                                     // dwFlags

    },

#endif

    // Add new input device type template here

};

第三部分:ntinput.c

        PDEVICE_TEMPLATE pDevTpl = &aDeviceTemplate[pDeviceInfo->type];

对于键盘来说,pDeviceInfo->type等于1,

        pDevTpl->DeviceRead 指针为函数指针ProcessKeyboardInput()

VOID NTAPI InputApc(

    IN PVOID ApcContext,

    IN PIO_STATUS_BLOCK IoStatusBlock,

    IN ULONG Reserved

    )

{

    PDEVICEINFO pDeviceInfo = (PDEVICEINFO)ApcContext;

    UNREFERENCED_PARAMETER(Reserved);

    /*

     * Check if the RIT is being terminated.

     * If we hit this assertion, the RIT was killed by someone inadvertently.

     * Not much can be done if it once happens.

     */

    UserAssert(gptiRit);

    UserAssert((gptiRit->TIF_flags & TIF_INCLEANUP) == 0);

#ifdef DIAGNOSE_IO

    pDeviceInfo->nReadsOutstanding--;

#endif

    /*

     * If this device needs freeing, abandon reading now and request the free.

     * (Don't even process the input that we received in this APC)

     */

    if (pDeviceInfo->usActions & GDIAF_FREEME) {

#ifdef GENERIC_INPUT

        CheckCritOut();

        EnterCrit();

#endif

        EnterDeviceInfoListCrit();

        pDeviceInfo->bFlags &= ~GDIF_READING;

        FreeDeviceInfo(pDeviceInfo);

        LeaveDeviceInfoListCrit();

#ifdef GENERIC_INPUT

        LeaveCrit();

#endif

        return;

    }

    if (NT_SUCCESS(IoStatusBlock->Status) && pDeviceInfo->handle) {

        PDEVICE_TEMPLATE pDevTpl = &aDeviceTemplate[pDeviceInfo->type];

        pDevTpl->DeviceRead(pDeviceInfo);

    }

    if (IsRemoteConnection()) {

        PoSetSystemState(ES_SYSTEM_REQUIRED);

    }

    StartDeviceRead(pDeviceInfo);

}

相关文章:

  • MVC与三层架构分层
  • 用Golang实现图形面积计算
  • HiveSQL实战——大厂面试真题
  • 【JPCS出版】第三届机械、航天技术与材料应用国际学术会议 (MATMA 2024)
  • Go 语言协程管理精解
  • 解决 Go 语言并发问题
  • 我问GPT flutter
  • 2024年10月湖北省自学考试报名流程(5步)
  • LLM概念梳理(一):训练流程之PT、SFT和PO
  • OriginPro快速上手指南:数据可视化与分析的利器
  • Android笔试面试题AI答之Kotlin(18)
  • 本科生毕业答辩全攻略:从开题到终期答辩的全面指南
  • 中国第一起名大师的老师颜廷利: 名字中的姓氏家谱字辈的最新解析
  • Vitis AI 进阶认知(Torch量化基础+映射+量化参数+对称性+每通道+PTQ+QAT+敏感性)
  • PHP进阶篇(奇怪的知识又增加了)
  • ES6核心特性
  • HTML-表单
  • JavaScript对象详解
  • JAVA之继承和多态
  • Js基础知识(四) - js运行原理与机制
  • Laravel 中的一个后期静态绑定
  • orm2 中文文档 3.1 模型属性
  • windows-nginx-https-本地配置
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 官方解决所有 npm 全局安装权限问题
  • 函数式编程与面向对象编程[4]:Scala的类型关联Type Alias
  • 浅谈web中前端模板引擎的使用
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 回归生活:清理微信公众号
  • 新海诚画集[秒速5センチメートル:樱花抄·春]
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • ​1:1公有云能力整体输出,腾讯云“七剑”下云端
  • ​Redis 实现计数器和限速器的
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • #565. 查找之大编号
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • #前后端分离# 头条发布系统
  • (09)Hive——CTE 公共表达式
  • (6)STL算法之转换
  • (CPU/GPU)粒子继承贴图颜色发射
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (动手学习深度学习)第13章 计算机视觉---图像增广与微调
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (附源码)ssm高校社团管理系统 毕业设计 234162
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • (五十)第 7 章 图(有向图的十字链表存储)
  • (详细文档!)javaswing图书管理系统+mysql数据库
  • (一)Kafka 安全之使用 SASL 进行身份验证 —— JAAS 配置、SASL 配置
  • (转)我也是一只IT小小鸟
  • (自用)网络编程
  • ./configure,make,make install的作用
  • .NET : 在VS2008中计算代码度量值
  • .NET MVC之AOP
  • .Net 路由处理厉害了