Discussion:
Keyboard filter to simulate keys
(too old to reply)
Mel
2004-09-21 11:53:58 UTC
Permalink
Hello,

I'm new to driver development, in fact I have never written
a real mode sys file nor a driver. Now I have to accomplish the following
task:
A program generates virtual key events to control a directx game.
Because directx directly reads out the keyboard I can't simply use the
WinAPI keybd_event or a simple SendKeys function. So the best way
seems to be to send the keystrokes from my application (can be delphi, c++
or vb)
to the keyboard filter driver that creates the keystroke.

Therefore I register a new keyboardchain filter KbdFilterInit

Then I'd like to feed keys into the keyboard chain to simulate button press
events. Therefore I create KeyData packets.

To process the keyboard chain I implement proper dispatch
function for reading
NTSTATUS
KbdDispatchRead(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)

So my questions are:
Is there already something similar out there that I can use?
Is it possible to create such a driver file without getting 1000s of
blue screens?
What's the easiest way to do this.
How can I send some bytes from my app to the driver? (My app tells the
driver to generate an 'F1' keystroke...)
Is my theory correct?

I hope to get some help from you.
Thanks for any hints
Mel

NTSTATUS
KbdFilterInit(
IN PDRIVER_OBJECT DriverObject
)
/*++

Routine Description:

Create a device object and attaches it to the
first keyboard device chain

Arguments:

DeviceObject - pointer to a device object.

Return Value:

NT Status code

--*/


{
UNICODE_STRING ntUnicodeString;
NTSTATUS ntStatus;
PDEVICE_OBJECT DeviceObject = NULL;

//
// Only hook onto the first keyboard's chain.
//
RtlInitUnicodeString( &ntUnicodeString, L"\\Device\\KeyboardClass0" );
//
// Create device object for the keyboard.
//
ntStatus = IoCreateDevice( DriverObject,
0,
NULL,
FILE_DEVICE_KEYBOARD,
0,
FALSE,
&DeviceObject );

if( !NT_SUCCESS(ntStatus) ) {
JKBD_DbgPrint(("JKBD: Keyboard hook failed to create device!\n"));
return ntStatus;
}
//
// Keyboard uses buffered I/O so we must as well.
//
DeviceObject->Flags |= DO_BUFFERED_IO;
//
// Attach to the keyboard chain.
//
ntStatus = IoAttachDevice( DeviceObject, &ntUnicodeString,
&pGlobalDevExt->KbdDevice );
if( !NT_SUCCESS(ntStatus) ) {
JKBD_DbgPrint(("JKBD: Connect with keyboard failed!\n"));
IoDeleteDevice( DeviceObject );
return ntStatus;
}
pGlobalDevExt->KbdFilterDevice = DeviceObject;

return STATUS_SUCCESS;
}



//
// Create a keyboard packet
//
KeyData = pGlobalDevExt->RawKbdIrp->AssociatedIrp.SystemBuffer;

RtlZeroMemory(KeyData, 2*sizeof(KEYBOARD_INPUT_DATA));
KeyData[numKeys].Flags = 0; //down
KeyData[numKeys+1].Flags = 1; //up
KeyData[numKeys].MakeCode = 0x1e; // character a
KeyData[numKeys+1].MakeCode = 0x1e; // character a
numKeys += 2;
KeyData += numKeys*sizeof(KEYBOARD_INPUT_DATA);
pGlobalDevExt->RawKbdIrp->IoStatus.Status = STATUS_SUCCESS;
pGlobalDevExt->RawKbdIrp->IoStatus.Information =
numKeys*sizeof(KEYBOARD_INPUT_DATA);
pGlobalDevExt->RawKbdIrpPending = FALSE;
IoCompleteRequest(pGlobalDevExt->RawKbdIrp, IO_KEYBOARD_INCREMENT);
Arkady Frenkel
2004-09-21 12:36:37 UTC
Permalink
Look at DDK\DDKXP\src\input\kbfiltr example and how
app talk to driver with IOCTL (
http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q262305 )
Arkady
Post by Mel
Hello,
I'm new to driver development, in fact I have never written
a real mode sys file nor a driver. Now I have to accomplish the following
A program generates virtual key events to control a directx game.
Because directx directly reads out the keyboard I can't simply use the
WinAPI keybd_event or a simple SendKeys function. So the best way
seems to be to send the keystrokes from my application (can be delphi, c++
or vb)
to the keyboard filter driver that creates the keystroke.
Therefore I register a new keyboardchain filter KbdFilterInit
Then I'd like to feed keys into the keyboard chain to simulate button press
events. Therefore I create KeyData packets.
To process the keyboard chain I implement proper dispatch
function for reading
NTSTATUS
KbdDispatchRead(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
Is there already something similar out there that I can use?
Is it possible to create such a driver file without getting 1000s of
blue screens?
What's the easiest way to do this.
How can I send some bytes from my app to the driver? (My app tells the
driver to generate an 'F1' keystroke...)
Is my theory correct?
I hope to get some help from you.
Thanks for any hints
Mel
NTSTATUS
KbdFilterInit(
IN PDRIVER_OBJECT DriverObject
)
/*++
Create a device object and attaches it to the
first keyboard device chain
DeviceObject - pointer to a device object.
NT Status code
--*/
{
UNICODE_STRING ntUnicodeString;
NTSTATUS ntStatus;
PDEVICE_OBJECT DeviceObject = NULL;
//
// Only hook onto the first keyboard's chain.
//
RtlInitUnicodeString( &ntUnicodeString, L"\\Device\\KeyboardClass0" );
//
// Create device object for the keyboard.
//
ntStatus = IoCreateDevice( DriverObject,
0,
NULL,
FILE_DEVICE_KEYBOARD,
0,
FALSE,
&DeviceObject );
if( !NT_SUCCESS(ntStatus) ) {
JKBD_DbgPrint(("JKBD: Keyboard hook failed to create device!\n"));
return ntStatus;
}
//
// Keyboard uses buffered I/O so we must as well.
//
DeviceObject->Flags |= DO_BUFFERED_IO;
//
// Attach to the keyboard chain.
//
ntStatus = IoAttachDevice( DeviceObject, &ntUnicodeString,
&pGlobalDevExt->KbdDevice );
if( !NT_SUCCESS(ntStatus) ) {
JKBD_DbgPrint(("JKBD: Connect with keyboard failed!\n"));
IoDeleteDevice( DeviceObject );
return ntStatus;
}
pGlobalDevExt->KbdFilterDevice = DeviceObject;
return STATUS_SUCCESS;
}
//
// Create a keyboard packet
//
KeyData = pGlobalDevExt->RawKbdIrp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(KeyData, 2*sizeof(KEYBOARD_INPUT_DATA));
KeyData[numKeys].Flags = 0; //down
KeyData[numKeys+1].Flags = 1; //up
KeyData[numKeys].MakeCode = 0x1e; // character a
KeyData[numKeys+1].MakeCode = 0x1e; // character a
numKeys += 2;
KeyData += numKeys*sizeof(KEYBOARD_INPUT_DATA);
pGlobalDevExt->RawKbdIrp->IoStatus.Status = STATUS_SUCCESS;
pGlobalDevExt->RawKbdIrp->IoStatus.Information =
numKeys*sizeof(KEYBOARD_INPUT_DATA);
pGlobalDevExt->RawKbdIrpPending = FALSE;
IoCompleteRequest(pGlobalDevExt->RawKbdIrp,
IO_KEYBOARD_INCREMENT);
Doron Holan [MS]
2004-09-21 15:23:32 UTC
Permalink
which OS do you need this to work on? if it is win2k and forward, you can
just use SendInput() from user mode.

d
--
Please do not send e-mail directly to this alias. this alias is for
newsgroup purposes only.
This posting is provided "AS IS" with no warranties, and confers no rights.
Post by Mel
Hello,
I'm new to driver development, in fact I have never written
a real mode sys file nor a driver. Now I have to accomplish the following
A program generates virtual key events to control a directx game.
Because directx directly reads out the keyboard I can't simply use the
WinAPI keybd_event or a simple SendKeys function. So the best way
seems to be to send the keystrokes from my application (can be delphi, c++
or vb)
to the keyboard filter driver that creates the keystroke.
Therefore I register a new keyboardchain filter KbdFilterInit
Then I'd like to feed keys into the keyboard chain to simulate button press
events. Therefore I create KeyData packets.
To process the keyboard chain I implement proper dispatch
function for reading
NTSTATUS
KbdDispatchRead(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
Is there already something similar out there that I can use?
Is it possible to create such a driver file without getting 1000s of
blue screens?
What's the easiest way to do this.
How can I send some bytes from my app to the driver? (My app tells the
driver to generate an 'F1' keystroke...)
Is my theory correct?
I hope to get some help from you.
Thanks for any hints
Mel
NTSTATUS
KbdFilterInit(
IN PDRIVER_OBJECT DriverObject
)
/*++
Create a device object and attaches it to the
first keyboard device chain
DeviceObject - pointer to a device object.
NT Status code
--*/
{
UNICODE_STRING ntUnicodeString;
NTSTATUS ntStatus;
PDEVICE_OBJECT DeviceObject = NULL;
//
// Only hook onto the first keyboard's chain.
//
RtlInitUnicodeString( &ntUnicodeString, L"\\Device\\KeyboardClass0" );
//
// Create device object for the keyboard.
//
ntStatus = IoCreateDevice( DriverObject,
0,
NULL,
FILE_DEVICE_KEYBOARD,
0,
FALSE,
&DeviceObject );
if( !NT_SUCCESS(ntStatus) ) {
JKBD_DbgPrint(("JKBD: Keyboard hook failed to create device!\n"));
return ntStatus;
}
//
// Keyboard uses buffered I/O so we must as well.
//
DeviceObject->Flags |= DO_BUFFERED_IO;
//
// Attach to the keyboard chain.
//
ntStatus = IoAttachDevice( DeviceObject, &ntUnicodeString,
&pGlobalDevExt->KbdDevice );
if( !NT_SUCCESS(ntStatus) ) {
JKBD_DbgPrint(("JKBD: Connect with keyboard failed!\n"));
IoDeleteDevice( DeviceObject );
return ntStatus;
}
pGlobalDevExt->KbdFilterDevice = DeviceObject;
return STATUS_SUCCESS;
}
//
// Create a keyboard packet
//
KeyData = pGlobalDevExt->RawKbdIrp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(KeyData, 2*sizeof(KEYBOARD_INPUT_DATA));
KeyData[numKeys].Flags = 0; //down
KeyData[numKeys+1].Flags = 1; //up
KeyData[numKeys].MakeCode = 0x1e; // character a
KeyData[numKeys+1].MakeCode = 0x1e; // character a
numKeys += 2;
KeyData += numKeys*sizeof(KEYBOARD_INPUT_DATA);
pGlobalDevExt->RawKbdIrp->IoStatus.Status = STATUS_SUCCESS;
pGlobalDevExt->RawKbdIrp->IoStatus.Information =
numKeys*sizeof(KEYBOARD_INPUT_DATA);
pGlobalDevExt->RawKbdIrpPending = FALSE;
IoCompleteRequest(pGlobalDevExt->RawKbdIrp, IO_KEYBOARD_INCREMENT);
Mel
2004-09-21 20:16:13 UTC
Permalink
Thanks for your help.
SendInput sounds really easy, too easy.
Some forums mention that directx really reads
the keyboard events directly from the keyboard
and things like keybd_event or SendInput wont work.

There is a way to hook the Directx Api function SendDeviceData and
inject keystrokes there. But therefgore you have to replace the directx dll
with your own.

I work with win2k and winxp.

Thanks for your tips.
-Mel

"Doron Holan [MS]" <***@nospam.microsoft.com> wrote in message news:OfLi17%***@TK2MSFTNGP15.phx.gbl...
which OS do you need this to work on? if it is win2k and forward, you can
just use SendInput() from user mode.

d
--
Please do not send e-mail directly to this alias. this alias is for
newsgroup purposes only.
This posting is provided "AS IS" with no warranties, and confers no rights.
Post by Mel
Hello,
I'm new to driver development, in fact I have never written
a real mode sys file nor a driver. Now I have to accomplish the following
A program generates virtual key events to control a directx game.
Because directx directly reads out the keyboard I can't simply use the
WinAPI keybd_event or a simple SendKeys function. So the best way
seems to be to send the keystrokes from my application (can be delphi, c++
or vb)
to the keyboard filter driver that creates the keystroke.
Therefore I register a new keyboardchain filter KbdFilterInit
Then I'd like to feed keys into the keyboard chain to simulate button press
events. Therefore I create KeyData packets.
To process the keyboard chain I implement proper dispatch
function for reading
NTSTATUS
KbdDispatchRead(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
Is there already something similar out there that I can use?
Is it possible to create such a driver file without getting 1000s of
blue screens?
What's the easiest way to do this.
How can I send some bytes from my app to the driver? (My app tells the
driver to generate an 'F1' keystroke...)
Is my theory correct?
I hope to get some help from you.
Thanks for any hints
Mel
NTSTATUS
KbdFilterInit(
IN PDRIVER_OBJECT DriverObject
)
/*++
Create a device object and attaches it to the
first keyboard device chain
DeviceObject - pointer to a device object.
NT Status code
--*/
{
UNICODE_STRING ntUnicodeString;
NTSTATUS ntStatus;
PDEVICE_OBJECT DeviceObject = NULL;
//
// Only hook onto the first keyboard's chain.
//
RtlInitUnicodeString( &ntUnicodeString, L"\\Device\\KeyboardClass0" );
//
// Create device object for the keyboard.
//
ntStatus = IoCreateDevice( DriverObject,
0,
NULL,
FILE_DEVICE_KEYBOARD,
0,
FALSE,
&DeviceObject );
if( !NT_SUCCESS(ntStatus) ) {
JKBD_DbgPrint(("JKBD: Keyboard hook failed to create device!\n"));
return ntStatus;
}
//
// Keyboard uses buffered I/O so we must as well.
//
DeviceObject->Flags |= DO_BUFFERED_IO;
//
// Attach to the keyboard chain.
//
ntStatus = IoAttachDevice( DeviceObject, &ntUnicodeString,
&pGlobalDevExt->KbdDevice );
if( !NT_SUCCESS(ntStatus) ) {
JKBD_DbgPrint(("JKBD: Connect with keyboard failed!\n"));
IoDeleteDevice( DeviceObject );
return ntStatus;
}
pGlobalDevExt->KbdFilterDevice = DeviceObject;
return STATUS_SUCCESS;
}
//
// Create a keyboard packet
//
KeyData = pGlobalDevExt->RawKbdIrp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(KeyData, 2*sizeof(KEYBOARD_INPUT_DATA));
KeyData[numKeys].Flags = 0; //down
KeyData[numKeys+1].Flags = 1; //up
KeyData[numKeys].MakeCode = 0x1e; // character a
KeyData[numKeys+1].MakeCode = 0x1e; // character a
numKeys += 2;
KeyData += numKeys*sizeof(KEYBOARD_INPUT_DATA);
pGlobalDevExt->RawKbdIrp->IoStatus.Status = STATUS_SUCCESS;
pGlobalDevExt->RawKbdIrp->IoStatus.Information =
numKeys*sizeof(KEYBOARD_INPUT_DATA);
pGlobalDevExt->RawKbdIrpPending = FALSE;
IoCompleteRequest(pGlobalDevExt->RawKbdIrp, IO_KEYBOARD_INCREMENT);
Ray Trent
2004-09-21 22:59:56 UTC
Permalink
Well, don't believe everything you read here (including this :-).

SendInput works fine with DirectInput on 2k and XP.

Of course, it may be possible to create a situation where it doesn't
work, like some app opening a *specific* keyboard instead of the
meta-keyboard GUID_SysKeyboard (I haven't verified this scenario). But
even with a filter, you're going to have that problem, because you can't
send your keys to *all* keyboards with a filter, just to one particular
one (otherwise you'd end up with duplicate key presses, which you
probably don't want).
Post by Mel
Thanks for your help.
SendInput sounds really easy, too easy.
Some forums mention that directx really reads
the keyboard events directly from the keyboard
and things like keybd_event or SendInput wont work.
There is a way to hook the Directx Api function SendDeviceData and
inject keystrokes there. But therefgore you have to replace the directx dll
with your own.
I work with win2k and winxp.
Thanks for your tips.
-Mel
which OS do you need this to work on? if it is win2k and forward, you can
just use SendInput() from user mode.
d
--
../ray\..

Please remove ".spamblock" from my email address if you need to contact
me outside the newsgroup.
Doron Holan [MS]
2004-09-22 03:32:25 UTC
Permalink
ray's right. SendInput() will work just fine for you. no need for a
driver.

d
--
Please do not send e-mail directly to this alias. this alias is for
newsgroup purposes only.
This posting is provided "AS IS" with no warranties, and confers no rights.
Post by Ray Trent
Well, don't believe everything you read here (including this :-).
SendInput works fine with DirectInput on 2k and XP.
Of course, it may be possible to create a situation where it doesn't work,
like some app opening a *specific* keyboard instead of the meta-keyboard
GUID_SysKeyboard (I haven't verified this scenario). But even with a
filter, you're going to have that problem, because you can't send your
keys to *all* keyboards with a filter, just to one particular one
(otherwise you'd end up with duplicate key presses, which you probably
don't want).
Post by Mel
Thanks for your help.
SendInput sounds really easy, too easy.
Some forums mention that directx really reads
the keyboard events directly from the keyboard
and things like keybd_event or SendInput wont work.
There is a way to hook the Directx Api function SendDeviceData and
inject keystrokes there. But therefgore you have to replace the directx dll
with your own.
I work with win2k and winxp.
Thanks for your tips.
-Mel
which OS do you need this to work on? if it is win2k and forward, you can
just use SendInput() from user mode.
d
--
../ray\..
Please remove ".spamblock" from my email address if you need to contact me
outside the newsgroup.
Mel
2004-09-22 21:08:35 UTC
Permalink
Thanks for your opinions. I will implement the SendInput option,
this really saves me a lot of work.
In one or two days I will know if it works with DirectX or not.

Thanks
Mel


"Doron Holan [MS]" <***@nospam.microsoft.com> wrote in message news:OfLi17%***@TK2MSFTNGP15.phx.gbl...
which OS do you need this to work on? if it is win2k and forward, you can
just use SendInput() from user mode.

d
--
Please do not send e-mail directly to this alias. this alias is for
newsgroup purposes only.
This posting is provided "AS IS" with no warranties, and confers no rights.
Post by Mel
Hello,
I'm new to driver development, in fact I have never written
a real mode sys file nor a driver. Now I have to accomplish the following
A program generates virtual key events to control a directx game.
Because directx directly reads out the keyboard I can't simply use the
WinAPI keybd_event or a simple SendKeys function. So the best way
seems to be to send the keystrokes from my application (can be delphi, c++
or vb)
to the keyboard filter driver that creates the keystroke.
Therefore I register a new keyboardchain filter KbdFilterInit
Then I'd like to feed keys into the keyboard chain to simulate button press
events. Therefore I create KeyData packets.
To process the keyboard chain I implement proper dispatch
function for reading
NTSTATUS
KbdDispatchRead(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
Is there already something similar out there that I can use?
Is it possible to create such a driver file without getting 1000s of
blue screens?
What's the easiest way to do this.
How can I send some bytes from my app to the driver? (My app tells the
driver to generate an 'F1' keystroke...)
Is my theory correct?
I hope to get some help from you.
Thanks for any hints
Mel
NTSTATUS
KbdFilterInit(
IN PDRIVER_OBJECT DriverObject
)
/*++
Create a device object and attaches it to the
first keyboard device chain
DeviceObject - pointer to a device object.
NT Status code
--*/
{
UNICODE_STRING ntUnicodeString;
NTSTATUS ntStatus;
PDEVICE_OBJECT DeviceObject = NULL;
//
// Only hook onto the first keyboard's chain.
//
RtlInitUnicodeString( &ntUnicodeString, L"\\Device\\KeyboardClass0" );
//
// Create device object for the keyboard.
//
ntStatus = IoCreateDevice( DriverObject,
0,
NULL,
FILE_DEVICE_KEYBOARD,
0,
FALSE,
&DeviceObject );
if( !NT_SUCCESS(ntStatus) ) {
JKBD_DbgPrint(("JKBD: Keyboard hook failed to create device!\n"));
return ntStatus;
}
//
// Keyboard uses buffered I/O so we must as well.
//
DeviceObject->Flags |= DO_BUFFERED_IO;
//
// Attach to the keyboard chain.
//
ntStatus = IoAttachDevice( DeviceObject, &ntUnicodeString,
&pGlobalDevExt->KbdDevice );
if( !NT_SUCCESS(ntStatus) ) {
JKBD_DbgPrint(("JKBD: Connect with keyboard failed!\n"));
IoDeleteDevice( DeviceObject );
return ntStatus;
}
pGlobalDevExt->KbdFilterDevice = DeviceObject;
return STATUS_SUCCESS;
}
//
// Create a keyboard packet
//
KeyData = pGlobalDevExt->RawKbdIrp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(KeyData, 2*sizeof(KEYBOARD_INPUT_DATA));
KeyData[numKeys].Flags = 0; //down
KeyData[numKeys+1].Flags = 1; //up
KeyData[numKeys].MakeCode = 0x1e; // character a
KeyData[numKeys+1].MakeCode = 0x1e; // character a
numKeys += 2;
KeyData += numKeys*sizeof(KEYBOARD_INPUT_DATA);
pGlobalDevExt->RawKbdIrp->IoStatus.Status = STATUS_SUCCESS;
pGlobalDevExt->RawKbdIrp->IoStatus.Information =
numKeys*sizeof(KEYBOARD_INPUT_DATA);
pGlobalDevExt->RawKbdIrpPending = FALSE;
IoCompleteRequest(pGlobalDevExt->RawKbdIrp, IO_KEYBOARD_INCREMENT);
Loading...