张裕 发表于 2024-8-24 01:44:52

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;
} 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_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等于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;
        pDevTpl->DeviceRead(pDeviceInfo);
    }

    if (IsRemoteConnection()) {

        PoSetSystemState(ES_SYSTEM_REQUIRED);

    }

    StartDeviceRead(pDeviceInfo);
}







免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: InputApc()函数是如何调用ProcessKeyboardInput()函数的?