C++ Windows 7 Get Symbolic Names of Installed drivers - c++

I have an application, that needs to talk to a piece of custom hardware. I know roughly the format that the driver will register a symbolic name, however based on some physical switches on the card, the card will have a somewhat dynamic name. My question is is there way to find the registered symbolic name, or find the driver and create the symbolic name.
My application use the symbolic name for operations like CreateFile(), WriteFile(), etc.
Update
The driver is PNP, so it really only makes the one subkey under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\V70QT\, and I will have potentially more than 1 card. I thought for a second there, that I could use this registry key
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\V70QT\Enum]
"Count"=dword:00000001
"NextInstance"=dword:00000001
"0"="PCI\\VEN_10B5&DEV_2021&SUBSYS_202110B5&REV_03\\4&33c89357&0&08F0"
Because the symbolic key name gets built in a format similar to V70QTX_Y, where X is the card ID (switches on hardware), and Y is the channel (irrelevant here). I thought I could build the name up using the "NextInstance" value however that will not work, as the card could have a switch ID of like 4, and be the first instance.

If your driver shows up under [HKLM\System\CurrentControlSet\Services], it would simply be a matter of enumerating the subkeys there.

Related

Associate HID Touch Device with Pnp Monitor

I am developing a tool that displays a status about various hardware components on a system we use at work. Currently, we have 16 touch screen monitors (all by 3M) plugged in to a Windows 10 box. I need to verify that any given monitor has an associated touch screen recognized by windows. This is to assess the system for any hardware malfunctions i.e. bad cable, bad USB port, bad Monitor, etc. We see this more than we would like to admit, usually where a monitor's display will be working fine but the USB controller on either end drops out and needs to be reset by unplugging/plugging back in
Unfortunately my code posting will be limited due to work constraints.
I can enumerate all of the monitors plugged in to the system via winapi's EnumDisplayDevices and EnumerateDisplayMonitors. I am able to build a list of all the HID touch screen devices using HIDApi.
From here I have no direction on where to go to link these two things together, if it is even possible. My first thought was the HID device information should have some sort of identifier shared by the results of calling the EnumDisplayDevices and EnumerateDisplayMonitors, but I have not found this to be the case. Another possibility would be to compare the coordinates/size of a monitor to a region that one of the touch controllers is responsible for. Again, not sure if that is possible.
In short, is there a way to associate a Touch device with it's corresponding monitor via c++?
I think you were just lucky that this driver suffix matched your monitor configuration. In my Windows 10 multi-monitor setup I get wrong displays when I look them up with this number in the driver entry as you described.
A reliable way for associating a HID device with a display seems to be:
Call GetRawInputDeviceList() to obtain the HID devices
Call GetRawInputDeviceInfo() with RIDI_DEVICEINFO to determine Usage and UsagePage
Call GetRawInputDeviceInfo() with RIDI_DEVICENAME to get a device string in the form \\\\?\\HID#VID_0EEF&PID_7200&Col01#6&152cc7f9&1&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
Query the registry for the mapping table at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wisp\Pen\Digimon and look up the display device name. In my case the HID names are all prefixed with 20- there but the remaining part seems to match the name queried by GetRawInputDeviceInfo() exactly. As a fallback method in case there is no match, I also parse the middle part as Clay Brooks described in his answer.
Call EnumDisplayDevices() with a null pointer for lpDevice and 0 for dwFlags in a loop until the function returns zero.
Within each loop iteration, call EnumDisplayDevices() again with the current device as lpDevice and EDD_GET_DEVICE_INTERFACE_NAME for dwFlags and observe that it returns a DeviceID in the form \\\\?\\DISPLAY#ELO2243#5&607b301&0&UID24833#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
Loop until a HID <-> display match is found and take the DeviceName returned by the "outer" EnumDisplayDevices() call which should be something like \\.\DISPLAY3
After the suggestions in the comments and looking deeper into the registry, I've found a way to link Touch controllers to a monitor.
Using HIDApi, you can poll the system and find a list of all the Touch Controllers you need to monitor. I filtered by the VID of the monitors we are using. A sample return value for the path looks something like this:
"\\?\hid#vid_0596&pid_0520&col02#8&33d9e616&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030}"
The bold part can be used to link to the entries in HKLM/Software/Microsoft/Wisp/Pen/Digimon. An example entry is this:
"\\?\HID#VID_0596&PID_0520&Col03#8&33d9e616&0&0002#{4d1e55b2-f16f-11cf-88cb-001111000030}" "\\?\DISPLAY#MSY1C2B#7&1083071f&0&UID524#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}"
The first bold matches the data found through HIDApi and the second set of bolding, the monitor name and a UID, is listed in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\DISPLAY. Under here you can use the combination of monitor name and UID to find the Driver entry. Below is a sample driver entry:
{4d36e96e-e325-11ce-bfc1-08002be10318}\0010
The last bold number can then be used to match up with a DeviceID returned from EnumDisplayDevices(). Below is a sample DeviceID:
"MONITOR\MSY1C2B\{4d36e96e-e325-11ce-bfc1-08002be10318}\0010".
Then you can use this bolded section to match up to names of monitors returned from EnumDisplayMonitors().

Identify the drive of a program on Windows

I have a Windows program coded in C++. To get the drive's serial number of the computer's drive, I run "wmic path win32_physicalmedia get SerialNumber" in the program with _popen().
However, the computers that run the program may have many drives, and USB drives also appear in the list.
How can I do to know which of the drives has the program I'm running? Thanks!
Assuming you still want to do it with WMI: first of all you need some code to read WMI properties in C++. No need to repeat here, you can find it in Getting CPU ID code from C# to be in C++.
When you have that code you can stat to work with disks. First of all you need to remember how Windows organize disks:
Each physical disk (Win32_DiskDrive) is made by partitions (Win32_DiskPartition).
Each partition (Win32_DiskPartition) is a logical disk (Win32_LogicalDisk).
Mapping between each other is done with Win32_DiskDriveToDiskPartition and Win32_LogicalDiskToPartition.
You already know where you're running then you can do this mapping:
Fetch from Win32_LogicalDisk the one where DeviceID property matches drive you're running on:
DeviceID=C:
Query Win32_LogicalDiskToPartition and pick Antecedent for which Dependent has ID you previously found:
\\REPETTI\root\cimv2:Win32_DiskPartition.DeviceID="Disk #1, Partition #1" \\REPETTI\root\cimv2:Win32_LogicalDisk.DeviceID="C:"
Now you should query partitions in Win32_DiskPartition to find the one where DeviceID is Disk #1, Partition #1 however also Win32_DiskDriveToDiskPartition uses DeviceID for this mapping then you can directly query Win32_DiskDriveToDiskPartition to match given ID:
\\REPETTI\root\cimv2:Win32_DiskDrive.DeviceID="\\.\PHYSICALDRIVE1" \\REPETTI\root\cimv2:Win32_DiskPartition.DeviceID="Disk #1, Partition #1"
Now you just need to query Win32_DiskDrive searching for device ID \\.\PHYSICALDRIVE1:
WDC WDxxx ATA Device \\.\PHYSICALDRIVE1 WDC WDxxx ATA Device
And you can get its serial number (in this case same property is available both in Win32_PhysicalMedia and Win32_DiskDrive otherwise you should search by its Caption).
Without WMI
If you have to do it without WMI then it's little bit more tricky.
First of all you need to figure out which physical drive contains your logical drive_ you may follow How to list physical disks?.
When you have physical drive name easiest way is CreateFile() to open drive and get information with DeviceIoControl() sending S.M.A.R.T. commands. Don't think it's always so easy: with many drives it'll fail and you need administrative rights. Unfortunately there isn't a single perfect solution then you need to try different approaches. AFAIK best and most exhaustive code to handle this is written by Lynn McGuire for its DiskId32 utility.

How to get memory range used by a specific device with WMI (Windows Management Instrumentation)

How can I get the resources used by a specific device (in particular, the memory range) of a specific device knowing it's name and/or DeviceID and/or the Pci bus number, Device number and function number?
For example, I want to know what memory range an Intel AHCI Controller uses. With the query "SELECT * FROM Win32_IDEController WHERE Name LIKE\"%ahci%\"" I can get some info like the complete name, device id, and other informations. Then I thought that using the complete name or device id I could select the memory range used by the device using the class "Win32_DeviceMemoryAddress". However, this class does not have any useful attributes that I can set to get the memory range associated with the AHCI controller. Name, Caption and description all return a string with the starting address and ending address.
Thanks in advance.
Don't know how to do it with WMI, but in this link, under "Get Device Resource", the author claims that CM_Get_Next_Res_Des provides this information. Getting there, though, is not simple... that's exactly what I'm trying to accomplish right now... will contribute further details when I get there...

CreateFile to open an MS-DOS device created in another terminal session

I have a (sort of a filter) driver that should communicate with user-mode components. It creates a device object by calling IoCreateDevice, and then it creates a so-called MS-DOS symbolic link for it by IoCreateSymbolicLink, to make it possible to access it from user-mode code (by CreateFile). This is a standard technique more-or-less. The driver creates a symbolic link of the form \DosDevices\mydevicename, whereas the user-mode code opens a file named \\.\mydevicename.
Now, the problems start when the driver creates a device in the context of a terminal server session. The created symbolic link actually belongs to the local session directory, whereas my user-mode service runs under system account in "zero session", and it "sees" symbolic links that belong to global directory.
It's mentioned in the documentation that usually there's no problem, because drivers mostly create device objects in the context of DriverEntry or AddDevice functions, which are guaranteed to run under system account. But my case is different. And I don't want to change this, what I really need is to be able to create/destroy device objects in the context of arbitrary thread, belonging to any session.
According to the documentation there's a way to solve this. The driver may insist to create a symbolic link belonging to the global directory, by naming it this way: \DosDevices\Global\mydevicename. Moreover, if the user-mode code happens to run under some account, it may also insist to look for the link in the global directory, by naming the file this way: \\.\Global\mydevicename. Though this is not required usually, if the symbol doesn't exist in local directory, it's automatically checked in the global directory.
I've tried this trick: it doesn't work for me. I'm using Windows 2008R2, 64-bit. No success so far. I'm consistently able to open devices created in the system account, but unable to open devices created in another sessions (the error code is "file not found"). I've tried all the combinations and variations of specifying \Global in kernel/user mode - so far the result is the same.
This makes me suspect that there's one more level of symbol isolation. Perhaps using \Global creates a symbolic link that is global session-wide, but still not system-wide.
Does this make sense? Is there a way to create a system-wide symbolic link? Or is there a way to open a file whose symbolic link belongs to another session?
EDIT:
Thanks to #Hans Passant. I've tried WinObj utility to actually see which devices and symbolic links the driver actually creates.
Everything seems ok at the first glance. I see all my devices under \Device directory, and all the symbolic links are under \GLOBAL??. Symbolic links point to correct device names.
One thing is weird however. Trying to see the device properties from within WinObj: for devices created in zero session this works ok, but for devices created in other sessions WinObj responds with an error:
Error opening \Device\mydevicename: The system cannot find the file specified.
So, it displays this device object in its list, but OTOH it's "not found" when trying to open it.
Very strange. But this explains my problem. But this is really strange.
Any ideas? Thanks in advance.
There is a \Sessions\N\DosDevices\ path, where N is a session number. I didn't try that but it should work.
Also I noticed that subst and network drive mapping create symbolic links in \Sessions\0\DosDevices\ID\, where ID is a session id. So you can check that path too.

Name mapping -- \\.\PhysicalDrive to \\.\SCSI

I'm developing in windows with C/C++ and I want to know is it possible to get an apropriate \\.\SCSI device name by \\.\PhysicalDrive ?..
For example, it's wonderful to know how to get that \\.\PhysicalDrive0 is the same that \\.\SCSI0.
Look at the code which I posted in my answer to the question. The author of the question had changed the text of the question so many time and the last version of text clear nor really what the original problem was.
In the example, which C source code you can download here, I show how to get many kind of information about the local drive using different Windows API. The important thing which you need is that some name conversion like DeviceType and DeviceNumber (received by IOCTL_STORAGE_GET_DEVICE_NUMBER) like the following
DeviceType: 7, DeviceNumber: 5, PartitionNumber: 1
are unique in the operation system and can be used to identify the same devices. The reference to the statement you can find in the documentation of IOCTL_STORAGE_GET_DEVICE_NUMBER control code:
The values in the
STORAGE_DEVICE_NUMBER structure are
guaranteed to remain unchanged until
the device is removed or the system is
restarted. It is not guaranteed to be
persistent across device restarts or
system restarts.
In the way you can compare \\.\SCSI0 devices and \\.\PhysicalDrive0 and find out the correspondence.