Installation, some questions

Hello all.

After reading MSDN about device driver installation I have some general questions about the process. The question is not a question about a problem, but about the idea in general.

Hardware-first installation doesn’t look that complicated. Windows looks for preloaded drivers, then for preinstalled drivers, then dependently on settings and version tries to download drivers and install them silently.

Software-first installation looks a bit more complicated. Accordingly to these articles:

http://msdn.microsoft.com/en-us/library/windows/hardware/ff552293(v=vs.85).aspx , http://msdn.microsoft.com/en-us/library/windows/hardware/ff537895(v=vs.85).aspx , http://msdn.microsoft.com/en-us/library/windows/hardware/ff541091(v=vs.85).aspx

I have to call CMP_WaitNoPendingInstallEvents (if possible) to prevent interfering with possible started hardware-first installation.

The next step is to check if the device is plugged in. Here the 1st question arise. Why should I care about it? Is it another way to do CMP_WaitNoPendingInstallEvents’s job? Or something else?

And few other questions.
As I understand there is at least two layers of API: CM_ API, which is the lowest level API to interact with device tree and SetupDi which probably relies on CM_. The strange thing here is that there is no CM_ API function that creates a device node. devcon uses SetupDi(DIF_REGISTERDEVICE) to create a device node. Is it the only way to do it?

One more thing I don’t get is what code triggers creation of device node in the case of hardware-first installation? I suspect that co or class installer of bus driver does it, but really not sure.

And the last one: are co and class installers called only in the case of using SetupDi API? Or user mode component of PnP calls them in any case?


Thanking In Advance,
Mikae.

On Sun, Feb 24, 2013 at 1:17 PM, wrote:

> After reading MSDN about device driver installation I have some general
> questions about the process. The question is not a question about a
> problem, but about the idea in general.
>

​I might not be an authority on the subject but I’ll try to help.

> Software-first installation looks a bit more complicated. Accordingly to
> these articles:
>
>
> http://msdn.microsoft.com/en-us/library/windows/hardware/ff552293(v=vs.85).aspx,
> http://msdn.microsoft.com/en-us/library/windows/hardware/ff537895(v=vs.85).aspx,
> http://msdn.microsoft.com/en-us/library/windows/hardware/ff541091(v=vs.85).aspx
>
> I have to call CMP_WaitNoPendingInstallEvents (if possible) to prevent
> interfering with possible started hardware-first installation.
>

​I understand this is done to prevent an unfavorable user experience
scenario: user is already in progress of going through the Found New
Hardware wizard. inserts the vendor’s CD, and then the vendor CD’s AutoRun
kicks in and tries to install the driver in parallel.

> The next step is to check if the device is plugged in. Here the 1st
> question arise. Why should I care about it? Is it another way to do
>
>
> CMP_WaitNoPendingInstallEvents’s job?

No.
​Starting with the fact
CMP_WaitNoPendingInstallEvents checks for any other driver installation
process whatsoever, not specifically one for your device.

You do it to branch into three scenarios:

1. Your Hardware ID has non-phantom devnode(s) (i.e. plugged instances)
This covers two cases: update an already-installed driver, and install
a driver for a “question mark” device
Course of action: UpdateDriverForPlugAndPlayDevices

2. Your Hardware ID has phantom devnode(s) (i.e unplugged instances)
Course of action: Follow the recipe in “Determining Whether a Device
Is Plugged In”

3. Your Hardware ID has no devnodes (i.e. was never plugged)
Course of action: Preinstall the driver (so it’ll be available if the
user ever decides to plug such a device)

> And few other questions.
> As I understand there is at least two layers of API: CM_ API, which is the
> lowest level API to interact with device tree and SetupDi which probably
> relies on CM_. The strange thing here is that there is no CM_ API function
> that creates a device node. devcon uses SetupDi(DIF_REGISTERDEVICE) to
> create a device node. Is it the only way to do it?
>

​For PnP devices, you never create devnodes. For a newly-plugged device,
the PnP Manager creates the devnode in kernel ​mode. then communicates it
to a usermode service which launches SetupAPI – you can get a pretty good
idea by watching SetupAPI.dev.log during device installation.

One more thing I don’t get is what code triggers creation of device node in
> the case of hardware-first installation? I suspect that co or class
> installer of bus driver does it, but really not sure.
>

​As I said, the PnP manager does it after enumerating the child devices of
a bus driver.

Drivers themselves actually have no business dealing with devnodes at all.
If you’re curious, there’s a pointer to the devnode somewhere in the
undocumented portion of DEVICE_OBJECT (Windbg !devobj and !devnode would
expose them to you).

And the last one: are co and class installers called only in the case of
> using SetupDi API? Or user mode component of PnP calls them in any case?
>

​There’s plenty of use for SetupDi APIs – e.g. see devcon ​sample in the
Windows DDK.

​Also, a SetupDi API​ is used in every user app to find the device instance
path when opening a device.

>user is already in progress of going through the Found New Hardware wizard.

AFAIR, Windows turns off autorun when starting Found New Hardware wizard. There is an option that a user runs installation by himself though.

  1. Your Hardware ID has non-phantom devnode(s) (i.e. plugged instances)
    This covers two cases: update an already-installed driver, and install
    a driver for a “question mark” device
    Course of action: UpdateDriverForPlugAndPlayDevices

But we already checked that no installation occurs with CMP_WaitNoPendingInstallEvents function. Why should we do it again?

???For PnP devices, you never create devnodes. For a newly-plugged device,
the PnP Manager creates the devnode in kernel ???mode. then communicates it
to a usermode service which launches SetupAPI – you can get a pretty good
idea by watching SetupAPI.dev.log during device installation.

Ah, so we need SetupDi(DIF_REGISTERDEVICE) only for non-PnP devices. Kernel PnP will create device node by itself.

???There’s plenty of use for SetupDi APIs – e.g. see devcon ??=8Bsample in the
Windows DDK.

I asked slightly different thing. It is not a problem to find examples of using SetupDi, but I would like to have a kind of general understanding of the process.

For now I know that user mode PnP (umpnpmgr.dll inside services.exe) interacts with kernel PnP through NtGetPlugPlayEvent and NtPlugPlayControl native APIs. You told me, that user mode PnP doesn’t create device nodes. As I understand user mode PnP exposes itself through CM_ API (RPC is used as transport). I thought that SetupDi is layered on top of CM_ API, so CM_ should have a function to create device nodes. (Though CM_ is implemented in SetupApi.dll nowdays).

Another question is if co-installers will be called in the case of using CM_ API. I just think that all these co/class installers scheme is implemented in SetupDi, not CM_, but not really sure.

Also, a SetupDi API??? is used in every user app to find the device instance
path when opening a device.

Didn’t get this sentence. Did you mean that SetupDi is involved in NtCreateFile?

On Sun, Feb 24, 2013 at 5:47 PM, wrote:

> >1. Your Hardware ID has non-phantom devnode(s) (i.e. plugged instances)
>
> This covers two cases: update an already-installed driver, and install
> >a driver for a “question mark” device
> > Course of action: UpdateDriverForPlugAndPlayDevices
>
> But we already checked that no installation occurs with
>
>
> CMP_WaitNoPendingInstallEvents function. Why should we do it again?
>

CMP_WaitNoPendingInstallEvents checks no installation is currently in
process.

I’m talking about determining the state in a completely idle system. The
question:

For a given Hardware ID, does the system
1) have non-phantom devnodes, and
2) have phandom devnodes.

This has nothing to do with an in-progress driver installation, which might
be an in-progress installation of a totally unrelated driver.

> For now I know that user mode PnP (umpnpmgr.dll inside services.exe)
> interacts with kernel PnP through NtGetPlugPlayEvent and NtPlugPlayControl
> native APIs. You told me, that user mode PnP doesn’t create device nodes.
> As I understand user mode PnP exposes itself through CM_ API (RPC is used
> as transport). I thought that SetupDi is layered on top of CM_ API, so CM_
> should have a function to create device nodes. (Though CM_ is implemented
> in SetupApi.dll nowdays).
>

​That sounds legit, but to be sure, I’d read one of the NT Internals books
on the subject, probably written by someone with source access :slight_smile:

> Another question is if co-installers will be called in the case of using
> CM_ API. I just think that all these co/class installers scheme is
> implemented in SetupDi, not CM_, but not really sure.
>

​I’m not really versed​ in this, but looking at the PnP Configuration
Manager API, I see nothing to do with installing INFs at all, so I suspect
CoInstallers belong to a higher API level (e.g. the device installation
API).

> >Also, a SetupDi API??? is used in every user app to find the device
> instance
> >path when opening a device.
>
> Didn’t get this sentence. Did you mean that SetupDi is involved in
> NtCreateFile?
>

​I mean finding the device path to pass to CreateFile / NtCreateFile, by
using SetupDi functions, i.e. what you see in the sample code here:
http://msdn.microsoft.com/en-us/library/windows/hardware/ff540174(v=vs.85).aspx#filehandle

(Hm, there used to be another MSDN article showing how to do this, not
specific to WinUSB, but I can’t find it now.)

>CMP_WaitNoPendingInstallEvents checks no installation is currently in

process.

Ok.


I’m talking about determining the state in a completely idle system. The
question:

For a given Hardware ID, does the system
1) have non-phantom devnodes, and
2) have phandom devnodes.

This has nothing to do with an in-progress driver installation, which might
be an in-progress installation of a totally unrelated driver.

Well, it looks I’ve got how it works. The doc is a bit vague about it. If UpdateDriverForPlugAndPlayDevices returns true, then I have to stop installation – it is already in progress. No need to preinstall the driver, it is already done by UpdateDriverForPlugAndPlayDevices.

Interesting thing what happens if UpdateDriverForPlugAndPlayDevices returns false, we check phantom nodes, call preinstallation and sly user inserts the device?


???I’m not really versed??? in this, but looking at the PnP Configuration
Manager API, I see nothing to do with installing INFs at all, so I suspect
CoInstallers belong to a higher API level (e.g. the device installation
API).

The point here is to know if ejecting device using CM_ notifies co-installers.

On Sun, Feb 24, 2013 at 10:12 PM, wrote:

> Interesting thing what happens if UpdateDriverForPlugAndPlayDevices
> returns false, we check phantom nodes, call preinstallation and sly user
> inserts the device?
>

​I don’t think ​CMP_WaitNoPendingInstallEvents is intended for locking,
otherwise it’d be an acquire-release-lock API :slight_smile: It’s merely offered to
avoid confusing user experiences, not to ensure security or integrity.
You’re taking it for more than it is.

For example, in my apps, I use CMP_WaitNoPendingInstallEvents to wait for
driver installations to “settle down”. For example, say I’m waiting for a
USB disk drive to be plugged, so I RegisterDeviceNotification (for
GUID_DEVINTERFACE_USB_DEVICE) and wait for a WM_DEVICECHANGE. When plugged,
I receive notification (about the USB Mass Storage device) but I know more
is coming (the volume child devices are being enumerated) so I do
CMP_WaitNoPendingInstallEvents instead of probing the newly added volumes
as they come (which is, too, an option).

> The point here is to know if ejecting device using CM_ notifies
> co-installers.
>

Since MSDN discourages you whenever possible from using CM in lieu of
SetupDi, you’d think SetupDi provides co-installer support and CM skips it,
right? However, I cannot find any such claim in the MSDN.

BTW, about CM_Request_Device_Eject – I don’t see any co-installer DIF code
for an "eject’ event:
http://msdn.microsoft.com/en-us/library/windows/hardware/ff549793(v=vs.85).aspx

>???I don’t think ???CMP_WaitNoPendingInstallEvents is intended for locking,

otherwise it’d be an acquire-release-lock API :slight_smile: It’s merely offered to
avoid confusing user experiences, not to ensure security or integrity.
You’re taking it for more than it is.

Well, I suspect it. I just try to understand why should I call this function. What will happen if I will not do it? For sure a lot of questions like this have a very short answer: “Just because you have to”. But it always interesting to understand what’s going on inside.

Since MSDN discourages you whenever possible from using CM in lieu of
SetupDi, you’d think SetupDi provides co-installer support and CM skips it,
right? However, I cannot find any such claim in the MSDN.

Exactly. I didn’t find anything about it in MSDN too. It just an assumption. Don’t know why does MS discourage CM_ – for some serious reasons like missing calls to co/class installers or just for great justice.

I also have feeling that CM_ appeared earlier than SetupDi. And then SetupDi was layered above CM_. cfgmgr32.dll just forwards all exports to SetupDi.dll now. But if so, there must be CM_ call for creation of device node, like SetipDi(DIF_REGISTERDEVICE) does. It couldn’t be removed because of backward compatibility.

BTW, about CM_Request_Device_Eject – I don’t see any co-installer DIF code
for an "eject’ event:
http://msdn.microsoft.com/en-us/library/windows/hardware/ff549793(v=vs.85).aspx

This is also a bit strange. Anyway, I could use MSDN description of installation process for projects, the question arose just because of curiosity.

xxxxx@yahoo.com wrote:

I also have feeling that CM_ appeared earlier than SetupDi. And then SetupDi was layered above CM_. cfgmgr32.dll just forwards all exports to SetupDi.dll now. But if so, there must be CM_ call for creation of device node, like SetipDi(DIF_REGISTERDEVICE) does. It couldn’t be removed because of backward compatibility.

Absolutely correct. The CM_ functions arrived with the introduction of
plug-and-play in Windows 95 and are common across all of the systems.
The SetupDi functions arrived in Windows 2000 and are NT-only.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Tim, thank you for response.

Well, quick disassembly of SetupDiCallClassInstaller (and the name of the function) shows that co installers are called by SetupDiCallClassInstaller. I also found CM_ for device node creation, though it is not documented for now days.

From WinDDK\7600.16385.1\src\setup\devcon\cmds.cpp:

/*

Callback for use by Enable/Disable/Restart
Invokes DIF_PROPERTYCHANGE with correct parameters
uses SetupDiCallClassInstaller so cannot be done for remote devices
Don’t use CM_xxx API’s, they bypass class/co-installers and this is bad.

*/