2011-09-01 9 views
5

मैं विंडोज के लिए एक कीबोर्ड फिल्टर ड्राइवर लिख रहा हूं और मुझे अपने कस्टम कीस्ट्रोक डेटा को विंडोज संदेश कतार में डालने की आवश्यकता है।कीबोर्ड इंटरप्ट को ट्रिगर या अनुकरण कैसे करें?

NTSTATUS Read(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) 
{ 
    PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; 

    IoCopyCurrentIrpStackLocationToNext(Irp); 
    IoSetCompletionRoutine(Irp, OnReadCompletion, DeviceObject, TRUE, TRUE, TRUE); 
    return IoCallDriver (deviceExtension->pKeyboardDevice, Irp); 
} 

NTSTATUS OnReadCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) 
{ 
// ... 
} 

इस फिल्टर चालक तो जैसे kbdclass ड्राइवर से जुड़ा हुआ है: मैं सभी कुंजियों कि दबाया तो की तरह मेरे ड्राइवर का पढ़ें (में IoSetCompletionRoutine() के लिए OnReadCompletion() कॉलबैक सेट कर रहे हैं) समारोह कब्जा करने के लिए प्रबंधित किया है:

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) 
{ 
// ... 
CCHAR ntNameBuffer[64] = "\\Device\\KeyboardClass0"; 
status = IoAttachDevice(deviceObject, &uKeyboardDeviceName, &DeviceExtension->pKeyboardDevice); 
// ... 

}

तो, मैं सभी कुंजियों OnReadCompletion में दबाया पकड़ कर सकते हैं()। लेकिन मुझे अपनी खुद की जानकारी कुंजीपटल संदेश प्रवाह में डालने की ज़रूरत है। यहां 2 समस्याएं हैं:

  1. OnReadCompletion() केवल एक कुंजी दबाए जाने पर ही लागू होता है। आदर्श रूप से मैं किसी भी तरह से इसे बुलाया जाना चाहूंगा जब कुछ भी दबाया न जाए। क्या मैं इसे किसी तरह से कर सकता हूं? मुझे एक कीबोर्ड बाधा ट्रिगर करने की जरूरत है? मैंने WRITE_PORT_UCHAR() के साथ एक कीबोर्ड पोर्ट (0x60 और 0x64) पर कमांड लिखने का प्रयास किया लेकिन यह काम नहीं कर सका।

  2. मैंने अपने डेटा को ऑनआरड कॉम्प्लेशन() में आईआरपी में डालने की कोशिश की ताकि उदाहरण के लिए एक कुंजी दबाया जा सके जबकि वास्तव में इसे केवल एक बार दबाया गया था। क्या कोई भी उस पर मेरी मदद कर सकता है, क्योंकि निम्नलिखित काम नहीं कर पाए?

    NTSTATUS OnReadCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) 
    { 
        PIO_STACK_LOCATION IrpStackLocation = NULL; 
        INT BufferLength; 
        INT numKeys = 0, i = 0; 
        PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; 
    
        IrpStackLocation = IoGetCurrentIrpStackLocation(Irp); 
        BufferLength = IrpStackLocation->Parameters.Read.Length; 
    
        if(Irp->IoStatus.Status == STATUS_SUCCESS) 
        { 
         PCHAR newSystemBuffer, oldSystemBuffer; 
         PKEYBOARD_INPUT_DATA keys = (PKEYBOARD_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer; 
         numKeys = Irp->IoStatus.Information/sizeof(KEYBOARD_INPUT_DATA); 
         for(i = 0; i < numKeys; i++) 
         { 
           // here we print whatever was pressed 
           DbgPrint("%s -- ScanCode: %x\n", __FUNCTION__, keys[i].MakeCode); 
         } 
         // allocate new buffer twice as big as original 
         newSystemBuffer = ExAllocatePool(NonPagedPool, Irp->IoStatus.Information * 2); 
         // copy existing buffer twice into new buffer 
          RtlCopyMemory(newSystemBuffer, keys, Irp->IoStatus.Information); 
         RtlCopyMemory(newSystemBuffer + Irp->IoStatus.Information, keys, Irp->IoStatus.Information); 
          // assign new buffer to Irp->AssociatedIrp.SystemBuffer 
         oldSystemBuffer = Irp->AssociatedIrp.SystemBuffer; 
         Irp->AssociatedIrp.SystemBuffer = newSystemBuffer; 
          // tell IRP that we now have twice as much data 
         Irp->IoStatus.Information *= 2; 
         // free the old buffer 
          ExFreePool(oldSystemBuffer); 
        } 
    
        if(Irp->PendingReturned) 
         IoMarkIrpPending(Irp); 
    
        return Irp->IoStatus.Status; 
    } 
    

और जब मैं नोटपैड में उदाहरण के लिए परीक्षण करते हैं, सब मैं कीस्ट्रोक प्रति सिर्फ एक पत्र है। मैं वास्तव में हताश हूँ। कृपया सहायता कीजिए!

+0

मैंने आईआरपी सिस्टम बफर में नया डेटा जोड़ने में कामयाब रहा है। यह चाल अलग-अलग कुंजी स्ट्रोक कोड का उपयोग करना था, जैसा ऊपर दिए गए कोड में नहीं है। तो यदि आप मेककोड = 2 (दबाने वाले बटन "1" के बराबर) डालना चाहते हैं, तो इसे ऑनरेड कॉम्प्लेशन(): आरटीएलसीपी मेमरी (नया सिस्टम बफर, चाबियाँ, आईआरपी-> IoStatus.Information) में करें; कुंजी-> मेककोड = 2; आरटीएलसीपी मेमरी (नया सिस्टम बफर + आईआरपी-> IoStatus.Information, कुंजी, आईआरपी-> IoStatus.Information); –

+0

अंतर "कुंजी-> मेककोड = 2;" में है जो दूसरे KEYBOARD_INPUT_DATA संदेश में मेककोड बदलता है। और आपको प्रत्येक कीस्ट्रोक के बाद "1" जोड़ा जाता है, उदाहरण के लिए नोटपैड में। –

+0

तो एकमात्र सवाल यह है कि मैं एक बाधा कैसे ट्रिगर करूं? –

उत्तर

1

चार विकल्प जो मुझे लगता है कि काम करना चाहिए:

1) आप के रूप IRP है कि आप नीचे प्राप्त गुजर करने का विरोध किया, साथ kbdclass चालक कॉल करने के लिए एक नया IRP बना सकते हैं। जब भी आप डेटा डालना चाहते थे तब भी आप मूल आईआरपी पूरा करेंगे, जब भी आपके पास वास्तविक कुंजीस्ट्रोक पास हों।

2) आपके पास दो डिवाइस हो सकते हैं, दूसरा कीबोर्ड डिवाइस हो सकता है। फिर आप उन्हें जोड़ने के लिए कीस्ट्रोक और कीबोर्ड डिवाइस को हटाने के लिए kbdclass फ़िल्टर का उपयोग करेंगे।

3) आप एमएसडीएन नमूना चालक केबीएफल्टर के समान कीबोर्ड ड्राइवरों के लिए ऊपरी फ़िल्टर होने के लिए अपने ड्राइवर को फिर से डिजाइन कर सकते हैं।

4) आपके पास दो डिवाइस हो सकते हैं, दूसरा कीबोर्ड डिवाइसों में से एक या अधिक के लिए ऊपरी फ़िल्टर हो सकता है। आप keystrokes को हटाने के लिए kbdclass फ़िल्टर का उपयोग करेंगे और उन्हें जोड़ने के लिए कीबोर्ड डिवाइस फ़िल्टर का उपयोग करेंगे।

मुझे लगता है कि पहला विकल्प सबसे अच्छा होगा, लेकिन मैं कोई विशेषज्ञ नहीं हूं।

+0

उत्तर के लिए धन्यवाद, दोस्त! लेकिन अगर मैं शब्दावली को समझता हूं तो मेरा चालक एक फ़िल्टर ड्राइवर है। यह ठीक है Kbdfiltr क्या करता है। मुझे पता चला कि फ़िल्टर फ़िल्टर में आईआरपी को संशोधित करने के आपके पास दो विकल्प हैं। सबसे पहले जब ओएस कीबोर्ड चालक स्टैक को पढ़ता है। यह पढ़ा आपके ड्राइवर द्वारा कब्जा कर लिया जाता है। आप तुरंत जवाब दे सकते हैं, इस प्रकार ओएस को कीस्ट्रोक भेज रहे हैं जिन्हें कभी दबाया नहीं गया है। यदि आप ऐसा नहीं करते हैं तो यह पढ़ना ढेर के नीचे हो जाता है और जब तक उपयोगकर्ता कुंजी दबाता है तब तक अवरुद्ध हो जाता है। फिर आईआरपी ढेर को ऊपर ले जाता है और आपके ड्राइवर द्वारा फिर से कब्जा कर लिया जा सकता है और संशोधित किया जा सकता है। –

+0

तो आप आईआरपी को दो मौकों पर संशोधित कर सकते हैं। लेकिन जब यह ढेर के नीचे एक ड्राइवर द्वारा अवरुद्ध हो जाता है तो आप कुछ भी नहीं कर सकते हैं और वापस आने तक प्रतीक्षा कर सकते हैं। यही समस्या है। क्योंकि यदि मेरे पास आईओसीएलटी के माध्यम से डेटा आया है जो मुझे डालने की ज़रूरत है तो मुझे आईआरपी में डालने का मौका पाने के लिए एक कीस्ट्रोक की प्रतीक्षा करने की आवश्यकता है। –

+0

किसी दूसरे कीबोर्ड के बारे में आपके दूसरे विचार के रूप में - क्या आपका मतलब है कि वास्तव में कंप्यूटर पर दूसरे कीबोर्ड को कनेक्ट करना या एक गैर-मौजूदा डिवाइस पर फ़िल्टर ड्राइवर बनाना, जैसे \\ डिवाइस \\ कीबोर्ड क्लास 1? –

संबंधित मुद्दे