当前位置: 首页 > 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);

}


http://www.mrgr.cn/news/3504.html

相关文章:

  • Android 架构模式之 MVP
  • Linux --- 文件系统
  • reactive 和 ref 的区别和联系
  • 二十二、状态模式
  • 【Orb-Slam3学习】 ORBextractor类主要成员函数调用关系
  • windows C++- Com技术简介(上)
  • MySql高级视频笔记
  • csdn狗都不用-测试再次解释
  • 共享内存及网络通信
  • 白骑士的计算机名词解析之各种“面向”
  • 【QT文件操作】---xml文件读取
  • 火山引擎AI创新巡展:豆包比友商便宜98%,行业落地探索,2000人座无虚席,PPT值得拍照收藏
  • CSS的:host伪类:精确定位于Web组件的指南
  • 谷歌浏览器-network中请求的query string parmeters和request payload的区别
  • 如何为PDF文件设置打开密码以保护文档安全
  • HarmonyOS NEXT - 数据持久化存储(key,value进行AES加密处理)
  • Linux内核实践(一)驱动DS18B20传感器的完整流程解析(涵盖字符设备、单总线、设备树等)
  • 国外代理IP选择:IP池的大小有何影响
  • 面试高频-深拷贝和浅拷贝
  • C/C++控制台贪吃蛇游戏的实现