Use Hidden WMI Classes and PowerShell to Discover HID Info

Doctor Scripto

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using two WMI classes from the root\wmi namespace to reveal additional HID hardware information.

Microsoft Scripting Guy, Ed Wilson, is here. Well, the Scripting Wife and I returned from Europe yesterday. It is good to be home, but we will miss our friends and all the great food. I fell in love with several new types of food that I have absolutely no hopes of ever finding in Charlotte, North Carolina. While there is a pretty good German restaurant in Charlotte, I have yet to find a Danish, Swedish, Norwegian, Swiss, Polish, Czech, or even Swiss restaurant in Charlotte. Major bummer to be sure. Oh, well. Stay in touch with the Scripting Wife on either Facebook or Twitter because she is already talking about planning a return trip to areas we missed on this trip. We only had three weeks after all.  

Revisiting WMI mouse & keyboard discovery

On the flight from Frankfurt to Charlotte yesterday, I had time (indeed plenty of time) to spend playing around with Windows PowerShell. (I mean one can only watch so many boring movies on a 5-inch screen that bounces every time the person in front of you moves. In my case, the number was exactly 0.) In all fairness, they did have good Jazz music programing, and so I put my headphones, fired up the Windows PowerShell ISE, and began playing.

Last week, I wrote Use PowerShell and WMI to Find Wireless Keyboard & Mouse about using WMI to identify a wireless mouse and keyboard attached to my system.

So, I was playing around with a function called Get-NameSpace, which I wrote for my new Microsoft Press Windows PowerShell 3.0 Step by Step book, and I decided to investigate additional namespaces for mouse and keyboard information.

Note   The Root\Cimv2 namespace is well documented on MSDN, and the classes there are supported for general use. Classes from other namespaces not documented on MSDN are not supported.

Just because a WMI class is not supported does not mean that it will not work—it only means that I cannot call up Microsoft support for assistance if the thing breaks, quits working, or behaves erratically. With this caveat in place, I begin my investigation.

Note   After things settle down, I intend to add the Get-NameSpace to my HSG*WMI*module.

Get-WMINameSpace Function

Function Get-WmiNameSpace

{

 Param(

  $nameSpace = “root”,

  $computer = “localhost”

 )

 Get-WmiObject -class __NameSpace -computer $computer `

 -namespace $namespace -ErrorAction “SilentlyContinue” |

 Foreach-Object `

 -Process `

   {

     $subns = Join-Path -Path $_.__namespace -ChildPath $_.name

     if($subns -notmatch ‘directory’) {$subns}

     $namespaces += $subns + “`r`n”

     Get-WmiNameSpace -namespace $subNS -computer $computer

   }

} #end Get-WmiNameSpace

 When I run the Get-WmiNameSpace function, I am presented with an extensive listing of new WMI namespaces existing on my computer running Windows 8. The partial listing appears in the following image.

Image of command output

As I look over the listing, I find a couple of namespaces that seem like they might be interesting. The first one is Root\Hardware. I use the following command to see if I can find anything related to a mouse or to a keyboard. As shown here, I found nothing.

PS C:\> Get-CimClass *mouse* -Namespace root\hardware

PS C:\> Get-CimClass *keyboard* -Namespace root\hardware

PS C:\> 

I could also have used the Windows PowerShell 2.0 syntax, but the results are the same.

PS C:\> Get-WmiObject -List *mouse* -Namespace root\hardware

PS C:\> Get-WmiObject -List *keyboard* -Namespace root\hardware

PS C:\> 

After exploring several other namespaces, I decided to go where I felt I would find success—the Root\WMI namespace. Once I queried there, I found several classes I could use.

PS C:\> “*mouse*”,”*keyboard*” | % {Get-CimClass $_ -Namespace root\WMI}

   NameSpace: ROOT/wmi

CimClassName                        CimClassMethods      CimClassProperties   

————                        —————      ——————   

MSMouse                             {}                   {}                   

MSMouse_ClassInformation            {}                   {Active, DeviceId, …

MSMouse_PortInformation             {}                   {Active, Buttons, C…

MSKeyboard                          {}                   {}                   

MSKeyboard_ExtendedID               {}                   {Active, InstanceNa…

MSKeyboard_PortInformation          {}                   {Active, ConnectorT…

MSKeyboard_ClassInformation         {}                   {Active, DeviceId, …

Notice that the MSMouse and MSKeyboard classes do not expose any properties in the CimClassProperties column. I verified this by using WbemTest as shown here.

Image of Object editor for MSMouse

Basically, the MSMouse class is an abstract class, but it does not have the abstract qualifier. I confirmed this by seeing first there are no instances (I pressed the Instances button). Then I pressed the Derived button, and saw there are two WMI classes derived from the MSMouse class (same thing for MSKeyboard). The derived classes are shown here.

Image of Query Result for MSMouse

Now that I have found the WMI classes that I want to query, I have a couple of choices. If I use the Get-CimInstance cmdlet, I need to supply each class: MSMouse_ClassInformation and MSMouse_PortInformation. But if I use the Get-WmiObject cmdlet, I can take advantage of another unsupported trick. Remember, I said the MSMouse and MSKeyboard classes are abstract? It is not supported to query abstract classes, and the Get-CimInstance cmdlet enforces this ban. However, the Get-WmiObject cmdlet does not. Therefore, when I query an abstract class, the query automatically routes to the two derived classes, and it is from there the answer returns.

Here is the query—I passed the results to the HasWmivalue function from my HSG*WMI* module to filter out empty and system properties.

PS C:\> gwmi msmouse -Namespace root\wmi | ? instancename -match ‘hid’ | haswmivalue

\\EDLT\root\wmi:MSMouse_PortInformation.InstanceName=”HID\\{00001124-0000-1000-8000-00805f9b34fb}_VID&0002

045e_PID&0702&Col02\\9&da0cc6e&0&0001_0″

==========================================================================================================

========================================

 

Name                           Value                                                                     

—-                           —–                                                                     

Active                         True                                                                      

Buttons                        5                                                                         

ConnectorType                  2                                                                          

DataQueueSize                  2                                                                         

InstanceName                   HID\{00001124-0000-1000-8000-00805f9b34fb}_VID&0002045e_PID&0702&Col02\9…

\\EDLT\root\wmi:MSMouse_ClassInformation.InstanceName=”HID\\{00001124-0000-1000-8000-00805f9b34fb}_VID&000

2045e_PID&0702&Col02\\9&da0cc6e&0&0001_0″

==========================================================================================================

=========================================

Active                         True                                                                      

DeviceId                       18446738026718451632                                                      

InstanceName                   HID\{00001124-0000-1000-8000-00805f9b34fb}_VID&0002045e_PID&0702&Col02\9…

 I can do the same thing with the MSKeyboard class. The MSKeyboard WMI class does contain the abstract qualifier, as shown here.

Image of Object editor for MSKeyboard

In addition, instead of only two classes derived from the abstract, there are three, as shown in the WbemTest tool.

Image of Query Result for MSKeyboard

Therefore, when I query the abstract MSKeyboard WMI class, three classes report information instead of just the two that report from the MSMouse class. The output from the command is shown here.

PS C:\> gwmi mskeyboard -Namespace root\wmi | ? instancename -match ‘hid’ | haswmivalue

\\EDLT\root\wmi:MSKeyboard_ClassInformation.InstanceName=”HID\\{00001124-0000-1000-8000-00805f9b34fb}_VID&00020

45e_PID&0762&Col01\\9&5c4d6fc&0&0000_0″

===============================================================================================================

=======================================

 

Name                           Value                                                                          

—-                           —–                                                                           

Active                         True                                                                           

DeviceId                       18446738026714008784                                                           

InstanceName                   HID\{00001124-0000-1000-8000-00805f9b34fb}_VID&0002045e_PID&0762&Col01\9&5c4d…

\\EDLT\root\wmi:MSKeyboard_ExtendedID.InstanceName=”HID\\{00001124-0000-1000-8000-00805f9b34fb}_VID&0002045e_PI

D&0762&Col01\\9&5c4d6fc&0&0000_0″

===============================================================================================================

=================================

Active                         True                                                                            

InstanceName                   HID\{00001124-0000-1000-8000-00805f9b34fb}_VID&0002045e_PID&0762&Col01\9&5c4d…

Type                           81                                                                             

\\EDLT\root\wmi:MSKeyboard_PortInformation.InstanceName=”HID\\{00001124-0000-1000-8000-00805f9b34fb}_VID&000204

5e_PID&0762&Col01\\9&5c4d6fc&0&0000_0″

===============================================================================================================

======================================

Active                         True                                                                           

ConnectorType                  2                                                                               

DataQueueSize                  1                                                                              

FunctionKeys                   12                                                                             

Indicators                     3                                                                              

InstanceName                   HID\{00001124-0000-1000-8000-00805f9b34fb}_VID&0002045e_PID&0762&Col01\9&5c4d…

Well, that is all for now. Join me tomorrow for more cool Windows PowerShell stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

0 comments

Discussion is closed.

Feedback usabilla icon