मैं विंडोज के लिए एक कीबोर्ड फिल्टर ड्राइवर लिख रहा हूं और मुझे अपने कस्टम कीस्ट्रोक डेटा को विंडोज संदेश कतार में डालने की आवश्यकता है।कीबोर्ड इंटरप्ट को ट्रिगर या अनुकरण कैसे करें?
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 समस्याएं हैं:
OnReadCompletion() केवल एक कुंजी दबाए जाने पर ही लागू होता है। आदर्श रूप से मैं किसी भी तरह से इसे बुलाया जाना चाहूंगा जब कुछ भी दबाया न जाए। क्या मैं इसे किसी तरह से कर सकता हूं? मुझे एक कीबोर्ड बाधा ट्रिगर करने की जरूरत है? मैंने WRITE_PORT_UCHAR() के साथ एक कीबोर्ड पोर्ट (0x60 और 0x64) पर कमांड लिखने का प्रयास किया लेकिन यह काम नहीं कर सका।
मैंने अपने डेटा को ऑनआरड कॉम्प्लेशन() में आईआरपी में डालने की कोशिश की ताकि उदाहरण के लिए एक कुंजी दबाया जा सके जबकि वास्तव में इसे केवल एक बार दबाया गया था। क्या कोई भी उस पर मेरी मदद कर सकता है, क्योंकि निम्नलिखित काम नहीं कर पाए?
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; }
और जब मैं नोटपैड में उदाहरण के लिए परीक्षण करते हैं, सब मैं कीस्ट्रोक प्रति सिर्फ एक पत्र है। मैं वास्तव में हताश हूँ। कृपया सहायता कीजिए!
मैंने आईआरपी सिस्टम बफर में नया डेटा जोड़ने में कामयाब रहा है। यह चाल अलग-अलग कुंजी स्ट्रोक कोड का उपयोग करना था, जैसा ऊपर दिए गए कोड में नहीं है। तो यदि आप मेककोड = 2 (दबाने वाले बटन "1" के बराबर) डालना चाहते हैं, तो इसे ऑनरेड कॉम्प्लेशन(): आरटीएलसीपी मेमरी (नया सिस्टम बफर, चाबियाँ, आईआरपी-> IoStatus.Information) में करें; कुंजी-> मेककोड = 2; आरटीएलसीपी मेमरी (नया सिस्टम बफर + आईआरपी-> IoStatus.Information, कुंजी, आईआरपी-> IoStatus.Information); –
अंतर "कुंजी-> मेककोड = 2;" में है जो दूसरे KEYBOARD_INPUT_DATA संदेश में मेककोड बदलता है। और आपको प्रत्येक कीस्ट्रोक के बाद "1" जोड़ा जाता है, उदाहरण के लिए नोटपैड में। –
तो एकमात्र सवाल यह है कि मैं एक बाधा कैसे ट्रिगर करूं? –