Reading USB keyboard through native API

Hi all.

I have a problem to read USB keyboard through native API application.

My application was registered to run before login in “BootExecute” key in registery “Control\Session Manager”, so I have to use only native API application functions.
My application request user to insert password before WINDOWS login.

My code goes like that:

  1. I call NtCreateFile to object “Device\KeyboardClass0”, and it returns successfully with handle to the object.
  2. then I create event with NtCreateEvent and it returns successfully.
  3. then I call NtReadFile with the handle and event.
  4. then I wait on NtWaitForSingleObject for the event to signal me when there is something to read.
  5. when I am signaled I am going to to read the key that was pressed by user.

The problem is that step#5 is never reached, and I am pressing on the USB keyboard keys and nothing happens, as if the keayboard was not pressed.

The same code works fine with PS/2 keyboard, but with USB keayboard I cann’t read anything.

The funny thing is that if I try it on PC that has both PS/2 and USB keyboards,
and I am unplugging the PS/2 keyboard before restart, somehow the USB keyboard works fine.
If I install AVG (or symantec) antivirus, somehow it works.
I can see that with the AVG another KeyboardClass instance is added,
and only from this KeyboardClass instance I can read from the USB keyboard.

My OS is windows XP SP-2.
I use DELL USB keyboard.

Do you have any idea, I am working on it for couple of days,
and I googled it and didn’t find anything.

Thanks,
Barak !

No body knows how ?
It was discussed already ?
Or it is complicated ?

It sounds to me like you are trying to open the keyboard driver itself directly by opening the class device…as I understand it, the Win32 subsystem is supposed to be designed to prevent you from doing something like this. The only application allowed to have a handle to the keyboard class driver is Win32. Are you readking KEYBOARD_INPUT_DATA structures out of the driver or are you using something else?

Have you considered writing a class filter driver instead to get the callbacks you need? It might be overpowered, but if you don’t have any other options a class filter driver will definitely get you all the keystrokes.

–Jason Sanchez> Date: Wed, 31 Oct 2007 03:22:56 -0500> From: xxxxx@safend.com> To: xxxxx@lists.osr.com> Subject: RE:[ntdev] Reading USB keyboard through native API> > > No body knows how ?> It was discussed already ?> Or it is complicated ? > > —> NTDEV is sponsored by OSR> > For our schedule of WDF, WDM, debugging and other seminars visit: > http://www.osr.com/seminars\> > To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer


Help yourself to FREE treats served up daily at the Messenger Caf?. Stop by today.
http://www.cafemessenger.com/info/info_sweetstuff2.html?ocid=TXT_TAGLM_OctWLtagline

Oh yeah, and you should note that a USB keyboard does not use the same i8042prt stuff that a PS2 keyboard does. So if you are opening a device controller for i8042prt, then the reason you can’t see USB keyboards is because USB keyboard data is read by the keyboard class driver (kbdclass.sys).> Date: Wed, 31 Oct 2007 03:22:56 -0500> From: xxxxx@safend.com> To: xxxxx@lists.osr.com> Subject: RE:[ntdev] Reading USB keyboard through native API> > > No body knows how ?> It was discussed already ?> Or it is complicated ? > > —> NTDEV is sponsored by OSR> > For our schedule of WDF, WDM, debugging and other seminars visit: > http://www.osr.com/seminars\> > To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer


Boo!?Scare away worms, viruses and so much more! Try Windows Live OneCare!
http://onecare.live.com/standard/en-us/purchase/trial.aspx?s_cid=wl_hotmailnews

You are assuming there is only one keyboard stack, or at the very least that the physical keyboard is the first keyboard stack. More often then not the terminal services virtual keyboard is the first keyboard (and thus \device\keyboardclass0). What you need to do is open every keyboard that you can, pend an asynchronous read to each and then wait on all of the events for a keypress.

How the keyboard is attached (usb, ps2, virtual) will not matter here since you are just getting a KEYBOARD_INPUT_DATA back.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@safend.com
Sent: Tuesday, October 30, 2007 2:18 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] Reading USB keyboard through native API

Hi all.

I have a problem to read USB keyboard through native API application.

My application was registered to run before login in “BootExecute” key in registery “Control\Session Manager”, so I have to use only native API application functions.
My application request user to insert password before WINDOWS login.

My code goes like that:

  1. I call NtCreateFile to object “Device\KeyboardClass0”, and it returns successfully with handle to the object.
  2. then I create event with NtCreateEvent and it returns successfully.
  3. then I call NtReadFile with the handle and event.
  4. then I wait on NtWaitForSingleObject for the event to signal me when there is something to read.
  5. when I am signaled I am going to to read the key that was pressed by user.

The problem is that step#5 is never reached, and I am pressing on the USB keyboard keys and nothing happens, as if the keayboard was not pressed.

The same code works fine with PS/2 keyboard, but with USB keayboard I cann’t read anything.

The funny thing is that if I try it on PC that has both PS/2 and USB keyboards,
and I am unplugging the PS/2 keyboard before restart, somehow the USB keyboard works fine.
If I install AVG (or symantec) antivirus, somehow it works.
I can see that with the AVG another KeyboardClass instance is added,
and only from this KeyboardClass instance I can read from the USB keyboard.

My OS is windows XP SP-2.
I use DELL USB keyboard.

Do you have any idea, I am working on it for couple of days,
and I googled it and didn’t find anything.

Thanks,
Barak !


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Thanks Doron and Jason for your replies.

Actually I have tried to create and read from all the available keyborad class instances,
that is - \device\keyboardclassX - where X starts from 0 sequentially until I got 0x34 status return
which indicates “STATUS_OBJECT_NAME_NOT_FOUND”.
But again I can not read the USB keyboard, only the PS/2 keyboard.

Does the USB keyboard hiding somewhere else rather than “\device\keyboardclassX” ?
If so how I can find it ?

Suppose I want to create another keyboard instance like AVG does, how can I do it ?

> Actually I have tried to create and read from all the available keyborad class instances,> that is - \device\keyboardclassX - where X starts from 0 sequentially until I got 0x34 status return> which indicates “STATUS_OBJECT_NAME_NOT_FOUND”.> But again I can not read the USB keyboard, only the PS/2 keyboard.
I think the reason for this might be because, as I mentioned earlier, the way PS/2 keyboards and USB keyboards are handled is different depending on the keyboard. How exactly are you extracting data from the PS/2 keyboard in the first place? Was I and Doron right in that you are reading KEYBOARD_INPUT_DATA values?
> Does the USB keyboard hiding somewhere else rather than “\device\keyboardclassX” ?> If so how I can find it ?
No, ultimately the keyboard stack is topped by the keyboard class driver itself, otherwise the keyboard input would never get to the Win32 subsystem responsible for processing keyboard input. The hardware map is intended to provide keyboard hardware vendors with a lot of flexibility in how they interface with Windows–they could, feasibly, specify something other than the keyboard class driver; however, nearly all keyboards end up using the keyboard class driver because it’s easier.

In a registry editor, go to HKLM/HARDWARE/DEVICEMAP/KeyboardClass and you’ll see all class instances right there. If you look at the value side of the keyboardclass%i keys, you’ll see that they’re all topped by \REGISTRY\MACHINE\SYSTEM\ControlSet%03i\Services\Kbdclass.

My concern, though, is that the Win32 subsystem may be responsible for attaching the USB keyboard to the keyboard class driver. If *this* is the case, then you will have no choice but to try to open the device itself (and not the class driver). If you emulate the services provided by the keyboard class driver, then this approach might work.

Suppose I want to create another keyboard instance like AVG does, how can I do it ?
I think that the only way to create another keyboard instance would be to create a non-device driver in the Keyboard setup class. The class driver will top the stack for your new keyboard instance automatically and the rest should click into place. This, of course, requires you to dirty your hands a bit and write your own driver–which means you’ll need to get a code signing certificate or you’ll have to get it WHQL’ed if you want it to work on Vista.

–Jason Sanchez


Peek-a-boo FREE Tricks & Treats for You!
http://www.reallivemoms.com?ocid=TXT_TAGHM&loc=us

>In a registry editor, go to HKLM/HARDWARE/DEVICEMAP/KeyboardClass and you’ll see all class instances right there. If you look at the value side of the keyboardclass%i

keys, you’ll see that they’re all topped by \REGISTRY\MACHINE\SYSTEM\ControlSet%03i\Services\Kbdclass.
while there are entries in DeviceMap, this is no longer the supported way of finding and enumerating keyboards. In the pnp world, you enumerate instances of the keyboard device interface using setupapi calls. This is the weird case where we don’t have native apis to do this, but then again, writing a native app is pretty much unsupported to begin with.

My concern, though, is that the Win32 subsystem may be responsible for attaching the USB keyboard to the keyboard class driver. If *this* is the case, then you will have no
choice but to try to open the device itself (and not the class driver). If you emulate the services provided by the keyboard class driver, then this approach might work.
This is pure speculation and completely false. The raw input thread (RIT), the part of win32 that reads raw keyboard input just enumerates instances of the keyboard device interface, opens them and reads from them. The pnp manager takes care of layering the drivers and loading class drivers on top of stacks (just like the rest of the pnp stack).

To reiterate there is no difference between a usb or ps2 (Bluetooth or IR or virtual or etc etc…) keyboard when you open the device interface or well known symbolic link name and send reads.

d

From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Jason Sanchez
Sent: Wednesday, October 31, 2007 8:28 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Reading USB keyboard through native API

Actually I have tried to create and read from all the available keyborad class instances,
that is - \device\keyboardclassX - where X starts from 0 sequentially until I got 0x34 status return
which indicates “STATUS_OBJECT_NAME_NOT_FOUND”.
But again I can not read the USB keyboard, only the PS/2 keyboard.

I think the reason for this might be because, as I mentioned earlier, the way PS/2 keyboards and USB keyboards are handled is different depending on the keyboard. How exactly are you extracting data from the PS/2 keyboard in the first place? Was I and Doron right in that you are reading KEYBOARD_INPUT_DATA values?

Does the USB keyboard hiding somewhere else rather than “\device\keyboardclassX” ?
If so how I can find it ?

No, ultimately the keyboard stack is topped by the keyboard class driver itself, otherwise the keyboard input would never get to the Win32 subsystem responsible for processing keyboard input. The hardware map is intended to provide keyboard hardware vendors with a lot of flexibility in how they interface with Windows–they could, feasibly, specify something other than the keyboard class driver; however, nearly all keyboards end up using the keyboard class driver because it’s easier.

In a registry editor, go to HKLM/HARDWARE/DEVICEMAP/KeyboardClass and you’ll see all class instances right there. If you look at the value side of the keyboardclass%i keys, you’ll see that they’re all topped by \REGISTRY\MACHINE\SYSTEM\ControlSet%03i\Services\Kbdclass.

My concern, though, is that the Win32 subsystem may be responsible for attaching the USB keyboard to the keyboard class driver. If *this* is the case, then you will have no choice but to try to open the device itself (and not the class driver). If you emulate the services provided by the keyboard class driver, then this approach might work.

Suppose I want to create another keyboard instance like AVG does, how can I do it ?

I think that the only way to create another keyboard instance would be to create a non-device driver in the Keyboard setup class. The class driver will top the stack for your new keyboard instance automatically and the rest should click into place. This, of course, requires you to dirty your hands a bit and write your own driver–which means you’ll need to get a code signing certificate or you’ll have to get it WHQL’ed if you want it to work on Vista.

–Jason Sanchez


Peek-a-boo FREE Tricks & Treats for You! Get 'em!http:

NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer</http:>

> This is pure speculation and completely false. The raw input thread (RIT), the part of win32 that reads raw keyboard input just enumerates instances of the keyboard device interface, opens them and reads from them.

Are you sure about this? Of course, once a read is recieved by the vendor driver itself, it’s going to get serviced the way one expects (otherwise it wouldn’t interface properly with the class driver), but this isn’t my point. I’m trying to show that the keyboard class driver sits right above the vendor driver, and that the way Win32 does it, all reads go through the class driver on their way down to the vendor driver. Here’s a quote from MSDN:

“Windows uses Kbdclass as the class driver for all keyboard devices that are installed in a system. The Windows Win32 subsystem opens all keyboard devices for its exclusive use. Applications cannot open the keyboard devices operated by Kbdclass.”

This is a little unclear. It seems to be saying that Win32 directly opens the keyboard devices themselves, but in reality, it’s the case that Win32 opens all the keyboard devices via the kbdclass device. If this weren’t the case, then keyboard class filter drivers that are installed as upper filters of the kbdclass service simply wouldn’t work as IOCTLs IRP_MJ_READs would go to the device, bypassing the class driver. There is more evidence that this is the case, too. Take the IOCTL_KEYBOARD_SET_INDICATORS internal IOCTL as an example. here’s a quote:

“If there is a grandmaster device, Kbdclass normally sets the keyboard indicators of all the subordinate class devices to a global setting. This operation is controlled by the registry entry value SendOutputToAllPorts under the key HKLM\Services\CurrentControlSet\Kbdclass|Parameters. If SendOutputToAllPorts is nonzero, Kdbclass sets all subordinate class devices to a gobal setting. Otherwise, Kbdclass sets only the device whose unit ID is zero.”

But what has me speculating is this: What does it mean that applications cannot open the keyboard devices operated by kbdclass? Does it mean that they actually cannot, and that attempts to open such devices will result in an access denial? Or is it one of those soft restrictions that are intended to discourage, but there is nothing in place to prevent it from happening should a programmer decide to do it?

In any case, I’m still somewhat skeptical that Device\KeyboardClass0 is a symbolic link to the vendor driver itself. If this opens the class driver, AND USB keyboards aren’t getting any input to the thread, then the class driver cannot be present at the top of the device stack for the USB keyboard, which means that the PNP manager cannot be the only agent responsible for setting up the keyboard class driver as the parent device to USB keyboards.


Help yourself to FREE treats served up daily at the Messenger Caf?. Stop by today.
http://www.cafemessenger.com/info/info_sweetstuff2.html?ocid=TXT_TAGLM_OctWLtagline

Yes, I am sure. I owned kbdclass, mouclass, i8042prt, kbdhid, mouhid…essentially the entire input stack for many years.

This is a little unclear. It seems to be saying that Win32 directly opens the keyboard devices themselves, but in reality, it’s the case that Win32 opens all the keyboard devices >via the kbdclass device.
You are a bit confused here. while there are many drivers in the stack, they are treated as one device stack. Just b/c there is a port driver and kbdclass layered on top of does not mean they are separately addressable. Yes a vendor driver could combine the functionality of a keyboard port and the class driver and support the kbdclass top level interfaces, but in 10 years I have never seen anyone have the need to do this.

“If there is a grandmaster device, Kbdclass normally sets the keyboard indicators of all the subordinate class devices to a global setting. This operation is controlled by the >registry entry value SendOutputToAllPorts under the key HKLM\Services\CurrentControlSet\Kbdclass|Parameters. If SendOutputToAllPorts is nonzero, >Kdbclass sets all subordinate class devices to a gobal setting. Otherwise, Kbdclass sets only the device whose unit ID is zero.”
Grandmaster mode is an NT4 legacy behavior that has not been supported since win2k. grandmaster mode creates a single addressable device object (\device\keyboardclass0) and then layers an anonymous (unnamed) device object on each keyboard port, multiplexing i/o in both directions. Nothing in this quote applies to a pnp device stack

But what has me speculating is this: What does it mean that applications cannot open the keyboard devices operated by kbdclass? Does it mean that they actually cannot,
and that attempts to open such devices will result in an access denial? Or is it one of those soft restrictions that are intended to discourage, but there is nothing in place to >prevent it from happening should a programmer decide to do it?
The source for kbdclass is in the wdk. No need to speculate, everything is there for you to see. This is an enforced restriction. Note that this restriction is for read access. If you do not request read access, none of the quote applies. There can be only one reader, that would be the RIT.

In any case, I’m still somewhat skeptical that Device\KeyboardClass0 is a symbolic link to the vendor driver itself. If this opens the class driver, AND USB keyboards aren’t
getting any input to the thread, then the class driver cannot be present at the top of the device stack for the USB keyboard, which means that the PNP manager cannot be the >only agent responsible for setting up the keyboard class driver as the parent device to USB keyboards.
Sorry, but I have no idea where you are getting this from. Connect a debugger (I think this would work in livekd even), run “!devnode 0 1 kbdhid” and then “!devstack [pdo]” on the PDo reported by !devnode. \Device\KeyboardClass0 is not a symbolic link, it is the name of a device object. Usb keyboards are no different than any other connected device. the output of !devstack will show you this. this is a sample stack for a ps2 mouse (http://blogs.msdn.com/doronh/archive/2006/03/15/552301.aspx)

0: kd> !devstack 8213c3d0
!DevObj !DrvObj !DevExt ObjectName
8213b030 \Driver\Mouclass 8213b0e8 PointerClass0 <–in a keyboard stack, this would be \Driver\kbdclass and the object name would be KeyboardClassX
8213c250 \DRIVER\VERIFIER 8213c308 <– ignore verifier devices for this discussion

8213c3d0 \Driver\i8042prt 8213c488 <– this would be \Driver\kbdhid for a usb keyboard, not that the device has no name
8213c820 \DRIVER\VERIFIER 8213c8d8
822923e8 \Driver\ACPI 822b2270 00000050
!DevNode 8228f4c8 :
DeviceInst is “ACPI\PNP0F13\4&1506bb2e&0”
ServiceName is “i8042prt”
d

From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Jason Sanchez
Sent: Wednesday, October 31, 2007 9:40 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Reading USB keyboard through native API

This is pure speculation and completely false. The raw input thread (RIT), the part of win32 that reads raw keyboard input just enumerates instances of the keyboard device interface, opens them and reads from them.

Are you sure about this? Of course, once a read is recieved by the vendor driver itself, it’s going to get serviced the way one expects (otherwise it wouldn’t interface properly with the class driver), but this isn’t my point. I’m trying to show that the keyboard class driver sits right above the vendor driver, and that the way Win32 does it, all reads go through the class driver on their way down to the vendor driver. Here’s a quote from MSDN:

“Windows uses Kbdclass as the class driver for all keyboard devices that are installed in a system. The Windows Win32 subsystem opens all keyboard devices for its exclusive use. Applications cannot open the keyboard devices operated by Kbdclass.”

This is a little unclear. It seems to be saying that Win32 directly opens the keyboard devices themselves, but in reality, it’s the case that Win32 opens all the keyboard devices via the kbdclass device. If this weren’t the case, then keyboard class filter drivers that are installed as upper filters of the kbdclass service simply wouldn’t work as IOCTLs IRP_MJ_READs would go to the device, bypassing the class driver. There is more evidence that this is the case, too. Take the IOCTL_KEYBOARD_SET_INDICATORS internal IOCTL as an example. here’s a quote:

“If there is a grandmaster device, Kbdclass normally sets the keyboard indicators of all the subordinate class devices to a global setting. This operation is controlled by the registry entry value SendOutputToAllPorts under the key HKLM\Services\CurrentControlSet\Kbdclass|Parameters. If SendOutputToAllPorts is nonzero, Kdbclass sets all subordinate class devices to a gobal setting. Otherwise, Kbdclass sets only the device whose unit ID is zero.”

But what has me speculating is this: What does it mean that applications cannot open the keyboard devices operated by kbdclass? Does it mean that they actually cannot, and that attempts to open such devices will result in an access denial? Or is it one of those soft restrictions that are intended to discourage, but there is nothing in place to prevent it from happening should a programmer decide to do it?

In any case, I’m still somewhat skeptical that Device\KeyboardClass0 is a symbolic link to the vendor driver itself. If this opens the class driver, AND USB keyboards aren’t getting any input to the thread, then the class driver cannot be present at the top of the device stack for the USB keyboard, which means that the PNP manager cannot be the only agent responsible for setting up the keyboard class driver as the parent device to USB keyboards.


Help yourself to FREE treats served up daily at the Messenger Caf?. Stop by today!http:

NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer</http:>

> Yes, I am sure. I owned kbdclass, mouclass, i8042prt, kbdhid, mouhid?essentially the entire input stack for many years.

Wow! I’m sorry, I had no idea. In my haste to come up with an answer, I forgot that real people are responsible for writing this kind of stuff (the @microsoft.com should have given me a clue, but I wasn’t paying attention). I actually made the same mistake with Tim in another thread–I probably should have learned my lesson then. Were you the one who designed the various structures like KEYBOARD_INPUT_DATA that are used by these drivers, or did you inherit these?

Grandmaster mode is an NT4 legacy behavior that has not been supported since win2k. grandmaster mode creates a single addressable device object (\device\keyboardclass0) and then layers an anonymous (unnamed) device object on each keyboard port, multiplexing i/o in both directions. Nothing in this quote applies to a pnp device stack

Ah, that makes sense. I should get a second keyboard sometime and play around with the indicator lights a bit and see what happens with the IRPs that get traded back and forth. So are there cases in which an upper filter on the kbdclass driver would miss user input? Sorry if my questions seem a bit naive to you, but it was my understanding that all reads go through the keyboard class driver on their way up to Win32.

Sorry, but I have no idea where you are getting this from. Connect a debugger (I think this would work in livekd even), run ?!devnode 0 1 kbdhid? and then ?!devstack [pdo]? on the PDo reported by !devnode. \Device\KeyboardClass0 is not a symbolic link, it is the name of a device object. Usb keyboards are no different than any other connected device. the output of !devstack will show you this. this is a sample stack for a ps2 mouse (http://blogs.msdn.com/doronh/archive/2006/03/15/552301.aspx)

Looks like you’re correct. Does one of the \Device\KeyboardClass%i correspond to an installed USB keyboard? If so, why isn’t any input being read?

PS:
Just so you know, this isn’t ultra-sarcasm. I don’t have any problem admitting where I’m beat, or when someone has a superior knowledge of something than I do. I know a bit about keyboard input, but my knowledge is obviously trumped by the person who wrote it, haha.


Climb to the top of the charts!? Play Star Shuffle:? the word scramble challenge with star power.
http://club.live.com/star_shuffle.aspx?icid=starshuffle_wlmailtextlink_oct

I have noticed a funny thing.
When my native application tries to ->NtCreateFile “Device\KeyboardClassX” object in loop
it recognizes only 1 valid KeyboardClass instance ->“Device\KeyboardClass0”.
Tring to ->NtCreateFile to object “Device\KeyboardClass1”, returns status of 0xC0000034L.

But after login
the registry “HKLM\SYSTEM\CurrentControlSet\Services\Kbdclass\Enum”
indicates of existence of 2 KeyboardClass instances:
0 with “Root\RDP_KBD\0000”
1 with “HID\Vid_413c&Pid_2003\7&2c08ad4&0&0000”

I think I need to connect to the second instance and the problem is that before login it doesn’t exist.

What do you think ?

Hmm. That’s interesting. It looks like that particular key isn’t being filled until after the Win32 subsystem is loaded–or perhaps something else to do with the input thread.

I don’t know of the way to get devices in a particular setup class without the use of the SetupApi. I’m not sure how the SetupApi interrogates the registry, or if there is something device-related which isn’t stored in the registry. Whatever the case may be, though, it looks to me like the Enum key for kbdclass is not actually filled by kbdclass.

The only option I can think of–and what would definitely work–would be to make an upper filter driver for the keyboard class driver. If you want an example of how to do this, you can look at the kbdfltr sample in the DDK. It advertises that it works only for i8042prt drivers, but if you remove the i8042prt stuff from it it will work just fine on USB keyboards.

Though perhaps there is a better way of doing this that I’m missing.

–Jason S.> Date: Thu, 1 Nov 2007 05:48:28 -0500> From: xxxxx@safend.com> To: xxxxx@lists.osr.com> Subject: RE:[ntdev] Reading USB keyboard through native API>> > I have noticed a funny thing.> When my native application tries to ->NtCreateFile “Device\KeyboardClassX” object in loop> it recognizes only 1 valid KeyboardClass instance ->“Device\KeyboardClass0”.> Tring to ->NtCreateFile to object “Device\KeyboardClass1”, returns status of 0xC0000034L.> > But after login> the registry “HKLM\SYSTEM\CurrentControlSet\Services\Kbdclass\Enum” > indicates of existence of 2 KeyboardClass instances:> 0 with “Root\RDP_KBD\0000”> 1 with “HID\Vid_413c&Pid_2003\7&2c08ad4&0&0000”> > I think I need to connect to the second instance and the problem is that before login it doesn’t exist.> > What do you think ? > > —> NTDEV is sponsored by OSR> > For our schedule of WDF, WDM, debugging and other seminars visit: > http://www.osr.com/seminars\> > To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer


Peek-a-boo FREE Tricks & Treats for You!
http://www.reallivemoms.com?ocid=TXT_TAGHM&loc=us

.

Thank you all.
I have found the reason.

Windows System just need more time to register the USB keyboard class instance.
I took a few seconds pause before trying to open KeyboardClass instances,
and all the instances were right there ready for me to use.
So now I can read both USB and/or PS/2 keyboards through native mode application.

Barak !

The enum key under the hklm.…\services<service> key is filled in by the OS, not the driver. Note that each pnp driver gets similar values.

d

From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Jason Sanchez
Sent: Thursday, November 01, 2007 4:58 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Reading USB keyboard through native API

Hmm. That’s interesting. It looks like that particular key isn’t being filled until after the Win32 subsystem is loaded–or perhaps something else to do with the input thread.

I don’t know of the way to get devices in a particular setup class without the use of the SetupApi. I’m not sure how the SetupApi interrogates the registry, or if there is something device-related which isn’t stored in the registry. Whatever the case may be, though, it looks to me like the Enum key for kbdclass is not actually filled by kbdclass.

The only option I can think of–and what would definitely work–would be to make an upper filter driver for the keyboard class driver. If you want an example of how to do this, you can look at the kbdfltr sample in the DDK. It advertises that it works only for i8042prt drivers, but if you remove the i8042prt stuff from it it will work just fine on USB keyboards.

Though perhaps there is a better way of doing this that I’m missing.

–Jason S.

> Date: Thu, 1 Nov 2007 05:48:28 -0500
> From: xxxxx@safend.com
> To: xxxxx@lists.osr.com
> Subject: RE:[ntdev] Reading USB keyboard through native API
>
>
> I have noticed a funny thing.
> When my native application tries to ->NtCreateFile “Device\KeyboardClassX” object in loop
> it recognizes only 1 valid KeyboardClass instance ->“Device\KeyboardClass0”.
> Tring to ->NtCreateFile to object “Device\KeyboardClass1”, returns status of 0xC0000034L.
>
> But after login
> the registry “HKLM\SYSTEM\CurrentControlSet\Services\Kbdclass\Enum”
> indicates of existence of 2 KeyboardClass instances:
> 0 with “Root\RDP_KBD\0000”
> 1 with “HID\Vid_413c&Pid_2003\7&2c08ad4&0&0000”
>
> I think I need to connect to the second instance and the problem is that before login it doesn’t exist.
>
> What do you think ?
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

________________________________
Peek-a-boo FREE Tricks & Treats for You! Get 'em!http:

NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer</http:>

I inherited the drivers during the windows2000 dev cycle. I had to add pnp/power/wmi etc to all of these drivers.

Ah, that makes sense. I should get a second keyboard sometime and play around with the indicator lights a bit and see what happens with the IRPs that get traded back and forth.
There is no magic here, keyboard reports the indicator light make scan code, the raw input thread then sends the set indicators IOCTL to each known keyboard. Kbdclass does not mux out the ioctl here, the RIT does.

So are there cases in which an upper filter on the kbdclass driver would miss user input? Sorry if my questions seem a bit naive to you, but it was my understanding that all reads go through the keyboard class driver on their way up to Win32.
I think you are confused about device objects and instance. If there is a class upper filter like kbdclass, that filter must create a device object for every keyboard on the machine during its AddDevice routine. Each of these devices will be attached to a diff keyboard. As long as the device is installed in the keyboards class, they upper filter will see the input.

d

From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Jason Sanchez
Sent: Thursday, November 01, 2007 12:31 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Reading USB keyboard through native API

Yes, I am sure. I owned kbdclass, mouclass, i8042prt, kbdhid, mouhid…essentially the entire input stack for many years.

Wow! I’m sorry, I had no idea. In my haste to come up with an answer, I forgot that real people are responsible for writing this kind of stuff (the @microsoft.com should have given me a clue, but I wasn’t paying attention). I actually made the same mistake with Tim in another thread–I probably should have learned my lesson then. Were you the one who designed the various structures like KEYBOARD_INPUT_DATA that are used by these drivers, or did you inherit these?

Grandmaster mode is an NT4 legacy behavior that has not been supported since win2k. grandmaster mode creates a single addressable device object (\device\keyboardclass0) and then layers an anonymous (unnamed) device object on each keyboard port, multiplexing i/o in both directions. Nothing in this quote applies to a pnp device stack

Ah, that makes sense. I should get a second keyboard sometime and play around with the indicator lights a bit and see what happens with the IRPs that get traded back and forth. So are there cases in which an upper filter on the kbdclass driver would miss user input? Sorry if my questions seem a bit naive to you, but it was my understanding that all reads go through the keyboard class driver on their way up to Win32.

Sorry, but I have no idea where you are getting this from. Connect a debugger (I think this would work in livekd even), run “!devnode 0 1 kbdhid” and then “!devstack [pdo]” on the PDo reported by !devnode. \Device\KeyboardClass0 is not a symbolic link, it is the name of a device object. Usb keyboards are no different than any other connected device. the output of !devstack will show you this. this is a sample stack for a ps2 mouse (http://blogs.msdn.com/doronh/archive/2006/03/15/552301.aspx)

Looks like you’re correct. Does one of the \Device\KeyboardClass%i correspond to an installed USB keyboard? If so, why isn’t any input being read?

PS:
Just so you know, this isn’t ultra-sarcasm. I don’t have any problem admitting where I’m beat, or when someone has a superior knowledge of something than I do. I know a bit about keyboard input, but my knowledge is obviously trumped by the person who wrote it, haha.


Climb to the top of the charts! Play Star Shuffle: the word scramble challenge with star power. Play Now!http:

NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer</http:>

>The enum key under the hklm.…\services<service> key is filled in by the OS,
not
>the driver. Note that each pnp driver gets similar values.

BTW - what is the need of this key? it is since NT4 IIRC.


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

I used to know :wink: … but I have since forgotten since it has not affected me in my work nor have I had a need to debug an issue with it :P.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Maxim S. Shatskih
Sent: Thursday, November 01, 2007 3:57 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Reading USB keyboard through native API

The enum key under the hklm.…\services<service> key is filled in by the OS,
not
>the driver. Note that each pnp driver gets similar values.

BTW - what is the need of this key? it is since NT4 IIRC.


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer