Code Example: Finish-Install Actions in a Co-installer
Note
Features described in this section are not supported in universal or mobile driver packages. See Using a Universal INF File.
In this example, a co-installer performs the following operations to support finish-install actions:
When the co-installer receives a DIF_NEWDEVICEWIZARD_FINISHINSTALL request, it calls the installer-supplied function FinishInstallActionsNeeded to determine whether there are finish-install actions to perform. (The code for the FinishInstallActionsNeeded function is not shown in this example).
If FinishInstallActionsNeeded returns TRUE, the co-installer calls SetupDiGetDeviceInstallParams to retrieve the device installation parameters for the device and then calls SetupDiSetDeviceInstallParams to set the FlagsEx member of the SP_DEVINSTALL_PARAMS structure for the device with the DI_FLAGSEX_FINISHINSTALL_ACTION flag. Setting this flag causes Windows to send a DIF_FINISHINSTALL_ACTION request to all class installers, class co-installers, and device co-installers that are involved in the installation of this device. This request is sent after all installation operations, except the finish-install actions, have completed.
When the co-installer receives a DIF_FINISHINSTALL_ACTION request, the co-installer again calls FinishInstallActionsNeeded to determine whether it has finish-install actions to perform and, if so, performs the finish-install actions. The co-installer notifies the user that finish-install actions are in progress and waits for the finish-install actions to complete before returning from processing the DIF_FINISHINSTALL_ACTION request.
If the finish-install actions succeed, the co-installer notifies the user that finish-install actions succeeded.
If the finish-install actions required a system restart to complete the finish-install actions, the co-installer calls SetupDiGetDeviceInstallParams to retrieve the device installation parameters for the device and then calls SetupDiSetDeviceInstallParams to set the Flags member of the SP_DEVINSTALL_PARAMS structure for the device with the DI_NEEDREBOOT flag. The installer also notifies the user that a system restart is required.
If the finish-install actions fail and the finish-install actions should be attempted again the next time the device is enumerated, the co-installer notifies the user of this situation.
Note Starting in Windows 8 a finish-install action is only run once. Windows will not automatically run it again, especially not the next time the device is enumerated because that is not when finish-install actions are run.
If the finish-install actions fail and the co-installer determines that the finish-install actions cannot succeed, the co-installer notifies the user of this situation.
By default, the co-installer returns NO_ERROR in response to a DIF_FINISHINSTALL_ACTION request if the finish-install actions succeeded, or if the finish-install actions failed and the co-installer determine that the finish-install actions should not be attempted again. The co-installer returns a Win32 error code only if the finish-install actions fail and the finish-install actions should be attempted again the next time the device is enumerated in the context of an administrator.
Note Starting in Windows 8 a finish-install action is only run once. Windows will not automatically run it again, especially not the next time the device is enumerated because that is not when finish-install actions are run.
The following co-installer code example shows the basic structure of co-installer code that implements finish-install actions:
DWORD CALLBACK
SampleCoInstaller(
IN DI_FUNCTION InstallFunction,
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
IN OUT PCOINSTALLER_CONTEXT_DATA Context
)
{
SP_DEVINSTALL_PARAMS DeviceInstallParams;
DWORD ReturnValue = NO_ERROR; // The default return value
switch(InstallFunction)
{
case DIF_NEWDEVICEWIZARD_FINISHINSTALL:
//
// Processing for finish-install wizard pages
//
// Processing for finish-install actions
if (FinishInstallActionsNeeded())
{
// Obtain the device install parameters for the device
// and set the DI_FLAGSEX_FINISHINSTALL_ACTION flag
DeviceInstallParams.cbSize = sizeof(DeviceInstallParams);
if (SetupDiGetDeviceInstallParams(DeviceInfoSet, DeviceInfoData, &DeviceInstallParams))
{
DeviceInstallParams.FlagsEx |= DI_FLAGSEX_FINISHINSTALL_ACTION;
SetupDiSetDeviceInstallParams(DeviceInfoSet, DeviceInfoData, &DeviceInstallParams);
}
}
break;
case DIF_FINISHINSTALL_ACTION:
if (FinishInstallActionsNeeded())
{
//
// Perform the finish-install actions,
// notify the user that finish install actions
// are in progress and wait for
// the finish-install actions to complete
//
// If the finish-install actions succeed, notify the user
//
// If the finish install actions require a system restart:
// notify the user, call SetupDiGetDeviceInstallParams
// to obtain the device install parameters for the device in
// DeviceInstallParams, and call SetupDiSetInstallParams to set
// the DI_NEEDREBOOT flag in DeviceInstallParams.Flags
//
// If the finish install actions failed, but
// should be attempted again: clean up,
// notify the user of the failure, and
// set ReturnValue to an appropriate Win32 error code
//
// If the finish install actions failed and
// should not be attempted again: clean up
// and notify the user of the failure
//
// Starting with Windows 8, a finish-install action
// is only run once. Windows will not automatically
// run it again, especially not the next time
// the device is enumerated because that is not when
// finish-install actions are run.
//
}
break;
}
return ReturnValue;
}