mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3413 lines
109 KiB
3413 lines
109 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1997 - 1999
|
|
//
|
|
// File: search.c
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "newdevp.h"
|
|
#include <infstr.h>
|
|
|
|
typedef struct _DirectoryNameList {
|
|
struct _DirectoryNameList *Next;
|
|
UNICODE_STRING DirectoryName;
|
|
WCHAR NameBuffer[1];
|
|
} DIRNAMES, *PDIRNAMES;
|
|
|
|
|
|
// CDM exports (there is no public header)
|
|
typedef
|
|
BOOL
|
|
(*PFNCDMINTERNETAVAILABLE)(
|
|
void
|
|
);
|
|
|
|
WCHAR StarDotStar[]=L"*.*";
|
|
|
|
|
|
BOOL
|
|
IsSearchCanceled(
|
|
PNEWDEVWIZ NewDevWiz
|
|
)
|
|
{
|
|
DWORD Result;
|
|
|
|
//
|
|
// If the caller doesn't pass us a cancel event then that just means they can't
|
|
// cancel the search.
|
|
//
|
|
if (!NewDevWiz->CancelEvent) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
Result = WaitForSingleObject(NewDevWiz->CancelEvent, 0);
|
|
|
|
//
|
|
// If Result is WAIT_OBJECT_0 then someone set the event. This means that
|
|
// we should cancel the driver search.
|
|
//
|
|
if (Result == WAIT_OBJECT_0) {
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
GetDriverSearchPolicy(
|
|
PULONG SearchPolicy
|
|
)
|
|
{
|
|
HKEY hKey;
|
|
DWORD CurrentPolicy;
|
|
ULONG cbData;
|
|
OSVERSIONINFOEX info;
|
|
|
|
//
|
|
// Assume that all search locations are valid.
|
|
//
|
|
*SearchPolicy = 0;
|
|
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER,
|
|
TEXT("Software\\Policies\\Microsoft\\Windows\\DriverSearching"),
|
|
0,
|
|
KEY_READ,
|
|
&hKey
|
|
) == ERROR_SUCCESS) {
|
|
|
|
//
|
|
// Check if we can search the CD
|
|
//
|
|
CurrentPolicy = 0;
|
|
cbData = sizeof(CurrentPolicy);
|
|
if ((RegQueryValueEx(hKey,
|
|
TEXT("DontSearchCD"),
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)&CurrentPolicy,
|
|
&cbData
|
|
) == ERROR_SUCCESS) &&
|
|
(CurrentPolicy)) {
|
|
|
|
*SearchPolicy |= SEARCH_CDROM;
|
|
}
|
|
|
|
//
|
|
// Check if we can search the Floppies
|
|
//
|
|
CurrentPolicy = 0;
|
|
cbData = sizeof(CurrentPolicy);
|
|
if ((RegQueryValueEx(hKey,
|
|
TEXT("DontSearchFloppies"),
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)&CurrentPolicy,
|
|
&cbData
|
|
) == ERROR_SUCCESS) &&
|
|
(CurrentPolicy)) {
|
|
|
|
*SearchPolicy |= SEARCH_FLOPPY;
|
|
}
|
|
|
|
//
|
|
// Check if we can search Windows Update. Note that on DataCenter
|
|
// machines we never search Windows Update.
|
|
//
|
|
info.dwOSVersionInfoSize = sizeof(info);
|
|
if (GetVersionEx((POSVERSIONINFOW)&info) &&
|
|
(info.wSuiteMask & VER_SUITE_DATACENTER)) {
|
|
//
|
|
// This is a DataCenter machine so don't search Windows Update.
|
|
//
|
|
*SearchPolicy |= SEARCH_INET;
|
|
*SearchPolicy |= SEARCH_INET_IF_CONNECTED;
|
|
} else {
|
|
CurrentPolicy = 0;
|
|
cbData = sizeof(CurrentPolicy);
|
|
if ((RegQueryValueEx(hKey,
|
|
TEXT("DontSearchWindowsUpdate"),
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)&CurrentPolicy,
|
|
&cbData
|
|
) == ERROR_SUCCESS) &&
|
|
(CurrentPolicy)) {
|
|
|
|
*SearchPolicy |= SEARCH_INET;
|
|
*SearchPolicy |= SEARCH_INET_IF_CONNECTED;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check if we can search locally
|
|
//
|
|
CurrentPolicy = 0;
|
|
cbData = sizeof(CurrentPolicy);
|
|
if ((RegQueryValueEx(hKey,
|
|
TEXT("DontSearchLocally"),
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)&CurrentPolicy,
|
|
&cbData
|
|
) == ERROR_SUCCESS) &&
|
|
(CurrentPolicy)) {
|
|
|
|
*SearchPolicy |= (SEARCH_DEFAULT | SEARCH_DEFAULT_EXCLUDE_OLD_INET);
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
DWORD
|
|
GetWUDriverRank(
|
|
PNEWDEVWIZ NewDevWiz,
|
|
LPTSTR HardwareId
|
|
)
|
|
{
|
|
DWORD Rank = 0xFFFF;
|
|
TCHAR TempBuffer[REGSTR_VAL_MAX_HCID_LEN];
|
|
ULONG TempBufferLen;
|
|
LPTSTR TempBufferPos;
|
|
int RankCounter;
|
|
|
|
//
|
|
// First of all we will start off with a Rank of 0xFFFF which is the worst possible.
|
|
//
|
|
// We will assume that WU will only return an INF Hardware Id match to us. This means
|
|
// that if we match against one of the device's HardwareIds then Rank will be between
|
|
// 0x0000 and 0x0999. Otherwise if we match against one of the device's Compatible Ids
|
|
// then the Rank will be between 0x2000 and 0x2999.
|
|
//
|
|
ZeroMemory(TempBuffer, sizeof(TempBuffer));
|
|
TempBufferLen = sizeof(TempBuffer);
|
|
if (CM_Get_DevInst_Registry_Property(NewDevWiz->DeviceInfoData.DevInst,
|
|
CM_DRP_HARDWAREID,
|
|
NULL,
|
|
TempBuffer,
|
|
&TempBufferLen,
|
|
0
|
|
) == CR_SUCCESS) {
|
|
|
|
if (TempBufferLen > 2 * sizeof(TCHAR)) {
|
|
|
|
RankCounter = 0x0000;
|
|
for (TempBufferPos = TempBuffer;
|
|
*TempBufferPos;
|
|
TempBufferPos += (lstrlen(TempBufferPos) + 1), RankCounter++) {
|
|
|
|
if (!lstrcmpi(TempBufferPos, HardwareId)) {
|
|
|
|
//
|
|
// Matched against a Hardware Id
|
|
//
|
|
Rank = RankCounter;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Rank == 0xFFFF) {
|
|
|
|
//
|
|
// We didn't match against a HardwareId so let's go through the Compatible Ids
|
|
//
|
|
ZeroMemory(TempBuffer, sizeof(TempBuffer));
|
|
TempBufferLen = sizeof(TempBuffer);
|
|
if (CM_Get_DevInst_Registry_Property(NewDevWiz->DeviceInfoData.DevInst,
|
|
CM_DRP_COMPATIBLEIDS,
|
|
NULL,
|
|
TempBuffer,
|
|
&TempBufferLen,
|
|
0
|
|
) == CR_SUCCESS) {
|
|
|
|
if (TempBufferLen > 2 * sizeof(TCHAR)) {
|
|
|
|
RankCounter = 0x2000;
|
|
for (TempBufferPos = TempBuffer;
|
|
*TempBufferPos;
|
|
TempBufferPos += (lstrlen(TempBufferPos) + 1), RankCounter++) {
|
|
|
|
if (!lstrcmpi(TempBufferPos, HardwareId)) {
|
|
|
|
//
|
|
// Matcheds against a compatible Id
|
|
//
|
|
Rank = RankCounter;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return Rank;
|
|
}
|
|
|
|
BOOL
|
|
IsWUDriverBetter(
|
|
PNEWDEVWIZ NewDevWiz,
|
|
LPTSTR HardwareId,
|
|
LPTSTR DriverVer
|
|
)
|
|
{
|
|
BOOL bWUDriverIsBetter = FALSE;
|
|
DWORD WURank;
|
|
SP_DRVINFO_DATA DriverInfoData;
|
|
SP_DRVINSTALL_PARAMS DriverInstallParams;
|
|
FILETIME WUFileTime;
|
|
|
|
//
|
|
// WU must at least give us a Hardware Id to compare against.
|
|
//
|
|
if (!HardwareId) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// If we can't get the selected driver then return TRUE. This will
|
|
// usually happen if we did not find a local driver.
|
|
//
|
|
DriverInfoData.cbSize = sizeof(DriverInfoData);
|
|
if (!SetupDiGetSelectedDriver(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DriverInfoData
|
|
)) {
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Get the Driver Install Params so we can get the Rank of the selected (best)
|
|
// driver.
|
|
//
|
|
DriverInstallParams.cbSize = sizeof(DriverInstallParams);
|
|
if (!SetupDiGetDriverInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DriverInfoData,
|
|
&DriverInstallParams
|
|
)) {
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Get the Rank of the HardwareId that WU returned to us.
|
|
//
|
|
WURank = GetWUDriverRank(NewDevWiz, HardwareId);
|
|
|
|
if (WURank < DriverInstallParams.Rank) {
|
|
|
|
bWUDriverIsBetter = TRUE;
|
|
|
|
} else if (WURank == DriverInstallParams.Rank) {
|
|
|
|
//
|
|
// Need to compare the DriverDates.
|
|
//
|
|
if (pSetupGetDriverDate(DriverVer,
|
|
&WUFileTime
|
|
)) {
|
|
|
|
//
|
|
// If CompareFileTime returns 1 then the best driver date is larger. If
|
|
// it returns 0 or -1 then the dates are the same or the WUFileTime is
|
|
// better, which means we should download this driver.
|
|
//
|
|
if (CompareFileTime(&DriverInfoData.DriverDate, &WUFileTime) != 1) {
|
|
|
|
bWUDriverIsBetter = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// default is that the Best driver found is better than the WUDriver.
|
|
//
|
|
|
|
return bWUDriverIsBetter;
|
|
}
|
|
|
|
BOOL
|
|
SearchWindowsUpdateCache(
|
|
PNEWDEVWIZ NewDevWiz
|
|
)
|
|
{
|
|
ULONG SearchPolicy = 0;
|
|
FIND_MATCHING_DRIVER_PROC pfnFindMatchingDriver;
|
|
DOWNLOADINFO DownloadInfo;
|
|
WUDRIVERINFO WUDriverInfo;
|
|
TCHAR DeviceInstanceId[MAX_DEVICE_ID_LEN];
|
|
BOOL FoundBetterDriver = FALSE;
|
|
|
|
//
|
|
// Verify that this user is allowed to search Windows Update before we continue.
|
|
//
|
|
GetDriverSearchPolicy(&SearchPolicy);
|
|
|
|
if (SearchPolicy & SEARCH_INET) {
|
|
//
|
|
// This user is NOT allowed to search Windows Update!
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Check if the search has been canceled.
|
|
//
|
|
if (IsSearchCanceled(NewDevWiz)) {
|
|
goto clean0;
|
|
}
|
|
|
|
//
|
|
// Load the Cdm DLL and open a context handle if needed. If we can't then
|
|
// bail out.
|
|
//
|
|
if (!OpenCdmContextIfNeeded(&NewDevWiz->hCdmInstance,
|
|
&NewDevWiz->hCdmContext
|
|
)) {
|
|
goto clean0;
|
|
}
|
|
|
|
//
|
|
// Check if the search has been canceled.
|
|
//
|
|
if (IsSearchCanceled(NewDevWiz)) {
|
|
goto clean0;
|
|
}
|
|
|
|
pfnFindMatchingDriver = (FIND_MATCHING_DRIVER_PROC)GetProcAddress(NewDevWiz->hCdmInstance,
|
|
"FindMatchingDriver"
|
|
);
|
|
|
|
if (!pfnFindMatchingDriver) {
|
|
goto clean0;
|
|
}
|
|
//
|
|
// First select the best driver in the list of drivers we have built so far
|
|
//
|
|
SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV,
|
|
NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData
|
|
);
|
|
|
|
//
|
|
// Fill in the DOWNLOADINFO structure to pass to CDM.DLL
|
|
//
|
|
ZeroMemory(&DownloadInfo, sizeof(DownloadInfo));
|
|
DownloadInfo.dwDownloadInfoSize = sizeof(DOWNLOADINFO);
|
|
DownloadInfo.lpFile = NULL;
|
|
|
|
DeviceInstanceId[0] = TEXT('\0');
|
|
CM_Get_Device_ID(NewDevWiz->DeviceInfoData.DevInst,
|
|
DeviceInstanceId,
|
|
SIZECHARS(DeviceInstanceId),
|
|
0
|
|
);
|
|
|
|
DownloadInfo.lpDeviceInstanceID = (LPCTSTR)DeviceInstanceId;
|
|
|
|
GetVersionEx((OSVERSIONINFO*)&DownloadInfo.OSVersionInfo);
|
|
|
|
//
|
|
// Set dwArchitecture to PROCESSOR_ARCHITECTURE_UNKNOWN, this
|
|
// causes Windows Update to get the architecture of the machine
|
|
// itself.
|
|
//
|
|
DownloadInfo.dwArchitecture = PROCESSOR_ARCHITECTURE_UNKNOWN;
|
|
DownloadInfo.dwFlags = 0;
|
|
DownloadInfo.dwClientID = 0;
|
|
DownloadInfo.localid = 0;
|
|
|
|
//
|
|
// Fill in the WUDRIVERINFO structure to pass to CDM.DLL
|
|
//
|
|
ZeroMemory(&WUDriverInfo, sizeof(WUDriverInfo));
|
|
WUDriverInfo.dwStructSize = sizeof(WUDRIVERINFO);
|
|
|
|
//
|
|
// Check if the search has been canceled.
|
|
//
|
|
if (IsSearchCanceled(NewDevWiz)) {
|
|
goto clean0;
|
|
}
|
|
|
|
if (pfnFindMatchingDriver(NewDevWiz->hCdmContext,
|
|
&DownloadInfo,
|
|
&WUDriverInfo
|
|
)) {
|
|
|
|
//
|
|
// Check to see if the WU Driver is better than the best selected
|
|
// driver.
|
|
//
|
|
FoundBetterDriver = IsWUDriverBetter(NewDevWiz,
|
|
WUDriverInfo.wszHardwareID,
|
|
WUDriverInfo.wszDriverVer
|
|
);
|
|
}
|
|
|
|
clean0:
|
|
;
|
|
|
|
|
|
return FoundBetterDriver;
|
|
}
|
|
|
|
BOOL
|
|
FixUpDriverListForInet(
|
|
PNEWDEVWIZ NewDevWiz
|
|
)
|
|
/*++
|
|
If the best driver is an old Internet driver then it must also be the
|
|
currently installed driver. If it is not the currently installed driver
|
|
then we will mark it with DNF_BAD_DRIVER and call DIF_SELECTBESTCOMPATDRV
|
|
again. We will keep doing this until the best driver is either NOT a Internet
|
|
driver, or it is the currently installed driver.
|
|
|
|
One issue here is if the class installer does not pay attention to the DNF_BAD_DRIVER
|
|
flag and returns it as the best driver anyway. If this happens then we will return
|
|
FALSE which will cause us to re-build the list filtering out all Old Internet drivers.
|
|
|
|
--*/
|
|
{
|
|
BOOL bReturn = TRUE;
|
|
SP_DRVINFO_DATA DriverInfoData;
|
|
SP_DRVINSTALL_PARAMS DriverInstallParams;
|
|
DWORD NumberOfDrivers = 0;
|
|
DWORD NumberOfIterations = 0;
|
|
|
|
ZeroMemory(&DriverInfoData, sizeof(SP_DRVINFO_DATA));
|
|
DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
|
|
|
|
while (SetupDiEnumDriverInfo(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
DriverType,
|
|
NumberOfDrivers++,
|
|
&DriverInfoData)) {
|
|
;
|
|
}
|
|
|
|
//
|
|
// We need to do this over and over again until we get a non Internet Driver or
|
|
// the currently installed driver.
|
|
//
|
|
while (NumberOfIterations++ <= NumberOfDrivers) {
|
|
|
|
//
|
|
// Get the best selected driver
|
|
//
|
|
if (SetupDiGetSelectedDriver(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DriverInfoData
|
|
))
|
|
{
|
|
//
|
|
// If it is the currently installed driver then we are fine
|
|
//
|
|
if (IsInstalledDriver(NewDevWiz, &DriverInfoData)) {
|
|
|
|
break;
|
|
}
|
|
|
|
ZeroMemory(&DriverInstallParams, sizeof(SP_DRVINSTALL_PARAMS));
|
|
DriverInstallParams.cbSize = sizeof(SP_DRVINSTALL_PARAMS);
|
|
|
|
if (SetupDiGetDriverInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DriverInfoData,
|
|
&DriverInstallParams)) {
|
|
|
|
if (DriverInstallParams.Flags & DNF_OLD_INET_DRIVER) {
|
|
|
|
//
|
|
// If the best driver is already marked with DNF_BAD_DRIVER then we
|
|
// have a class installer that is picking a Bad driver as the best.
|
|
// This is not a good idea, so this API will return FALSE which will
|
|
// cause the entire driver list to get re-built filtering out all
|
|
// Old Internet drivers.
|
|
//
|
|
if (DriverInstallParams.Flags & DNF_BAD_DRIVER) {
|
|
|
|
bReturn = FALSE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// The best driver is an OLD Internet driver, so mark it
|
|
// with DNF_BAD_DRIVER and call DIF_SELECTBESTCOMPATDRV
|
|
//
|
|
else {
|
|
|
|
DriverInstallParams.Flags = DNF_BAD_DRIVER;
|
|
|
|
if (!SetupDiSetDriverInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DriverInfoData,
|
|
&DriverInstallParams
|
|
)) {
|
|
|
|
//
|
|
// If the API fails then just break;
|
|
//
|
|
break;
|
|
}
|
|
|
|
if (!SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV,
|
|
NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData
|
|
)) {
|
|
|
|
//
|
|
// If the API fails then just break;
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
|
|
//
|
|
// The selected driver is not an Internet driver so were good.
|
|
//
|
|
break;
|
|
}
|
|
} else {
|
|
|
|
//
|
|
// If the API fails then just break
|
|
//
|
|
break;
|
|
}
|
|
} else {
|
|
|
|
//
|
|
// If the API fails then just break
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we went through every driver and we still haven't selected a best one then the
|
|
// class installer is probably removing the DNF_BAD_DRIVER flag and keeps choose the
|
|
// same Old Internet driver over and over again. If this happens then we will just
|
|
// return FALSE which will cause us to rebuild the driver list without any old Internet
|
|
// drivers and then select the best driver.
|
|
//
|
|
if (NumberOfIterations > NumberOfDrivers) {
|
|
|
|
bReturn = FALSE;
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
void
|
|
DoDriverSearchInSpecifiedLocations(
|
|
HWND hWnd,
|
|
PNEWDEVWIZ NewDevWiz,
|
|
ULONG SearchOptions,
|
|
DWORD DriverType
|
|
)
|
|
/*++
|
|
|
|
|
|
--*/
|
|
{
|
|
SP_DEVINSTALL_PARAMS DeviceInstallParams;
|
|
|
|
//
|
|
// Set the Device Install Params to set the parent window handle.
|
|
//
|
|
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
|
|
if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
))
|
|
{
|
|
DeviceInstallParams.hwndParent = hWnd;
|
|
|
|
if (SearchOptions & SEARCH_DEFAULT_EXCLUDE_OLD_INET) {
|
|
|
|
DeviceInstallParams.FlagsEx |= DI_FLAGSEX_EXCLUDE_OLD_INET_DRIVERS;
|
|
}
|
|
|
|
SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
);
|
|
}
|
|
|
|
|
|
//
|
|
// Search any single INFs (this only comes in through the UpdateDriverForPlugAndPlayDevices
|
|
// API. We don't need to update the UI in this case since this is currently always a silent
|
|
// install (upgrade).
|
|
//
|
|
if (!IsSearchCanceled(NewDevWiz) && (SearchOptions & SEARCH_SINGLEINF)) {
|
|
|
|
SP_DRVINFO_DATA DrvInfoData;
|
|
|
|
SetDriverPath(NewDevWiz, NewDevWiz->SingleInfPath);
|
|
|
|
//
|
|
// OR in the DI_ENUMSINGLEINF flag so that we only look at this specific INF
|
|
//
|
|
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
|
|
if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
))
|
|
{
|
|
DeviceInstallParams.Flags |= DI_ENUMSINGLEINF;
|
|
|
|
SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
);
|
|
}
|
|
|
|
//
|
|
// Build up the list in this specific INF file
|
|
//
|
|
SetupDiBuildDriverInfoList(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
DriverType
|
|
);
|
|
|
|
//
|
|
// Clear the DI_ENUMSINGLEINF flag in case we build from the default
|
|
// INF path next.
|
|
//
|
|
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
|
|
if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
))
|
|
{
|
|
DeviceInstallParams.Flags &= ~DI_ENUMSINGLEINF;
|
|
|
|
SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
);
|
|
}
|
|
|
|
//
|
|
// At this point we should have a list of drivers in the INF that the caller
|
|
// of the UpdateDriverForPlugAndPlayDevices specified. If the list is empty
|
|
// then the INF they passed us cannot be used on the Hardware Id that they
|
|
// passed in. In this case we will SetLastError to ERROR_DI_BAD_PATH.
|
|
//
|
|
ZeroMemory(&DrvInfoData, sizeof(SP_DRVINFO_DATA));
|
|
DrvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
|
|
|
|
if (!SetupDiEnumDriverInfo(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
DriverType,
|
|
0,
|
|
&DrvInfoData
|
|
)) {
|
|
|
|
//
|
|
// We wern't able to find any drivers in the specified INF that match
|
|
// the specified hardware ID.
|
|
//
|
|
NewDevWiz->LastError = ERROR_DI_BAD_PATH;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Get the currently installed driver for this device only
|
|
//
|
|
if (!IsSearchCanceled(NewDevWiz) && (SearchOptions & SEARCH_CURRENTDRIVER)) {
|
|
|
|
//
|
|
// When getting the currently installed driver we don't need to set
|
|
// the DriverPath because setupapi will figure that out.
|
|
//
|
|
// Set the DI_FLAGSEX_INSTALLEDDRIVER flag to let setupapi know that we
|
|
// just want the installed driver added to the list.
|
|
//
|
|
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
|
|
if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
))
|
|
{
|
|
DeviceInstallParams.Flags |= DI_FLAGSEX_INSTALLEDDRIVER;
|
|
|
|
SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
);
|
|
}
|
|
|
|
SetupDiBuildDriverInfoList(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
DriverType
|
|
);
|
|
|
|
//
|
|
// Clear the DI_FLAGSEX_INSTALLEDDRIVER flag now that we have added
|
|
// the installed driver to the list.
|
|
//
|
|
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
|
|
if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
))
|
|
{
|
|
DeviceInstallParams.Flags &= ~DI_FLAGSEX_INSTALLEDDRIVER;
|
|
|
|
SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Search the default INF path
|
|
//
|
|
if (!IsSearchCanceled(NewDevWiz) &&
|
|
((SearchOptions & SEARCH_DEFAULT) ||
|
|
(SearchOptions & SEARCH_DEFAULT_EXCLUDE_OLD_INET)))
|
|
|
|
{
|
|
SetDriverPath(NewDevWiz, NULL);
|
|
|
|
SetupDiBuildDriverInfoList(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
DriverType
|
|
);
|
|
}
|
|
|
|
//
|
|
// Search any extra paths that the user specified in the wizard
|
|
//
|
|
if (!IsSearchCanceled(NewDevWiz) && (SearchOptions & SEARCH_DIRECTORY))
|
|
{
|
|
SetDriverPath(NewDevWiz, NewDevWiz->BrowsePath);
|
|
|
|
SetupDiBuildDriverInfoList(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
DriverType
|
|
);
|
|
}
|
|
|
|
|
|
//
|
|
// Search any Windows Update paths.
|
|
//
|
|
if (!IsSearchCanceled(NewDevWiz) && (SearchOptions & SEARCH_WINDOWSUPDATE))
|
|
{
|
|
BOOL bOldInetDriversAllowed = TRUE;
|
|
|
|
SetDriverPath(NewDevWiz, NewDevWiz->BrowsePath);
|
|
|
|
//
|
|
// We need to OR in the DI_FLAGSEX_INET_DRIVER flag so that setupapi will
|
|
// mark in the INFs PNF that it is from the Internet. This is important
|
|
// because we don't want to ever use an Internet INF again since we don't
|
|
// have the drivers locally.
|
|
//
|
|
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
|
|
if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
))
|
|
{
|
|
//
|
|
// When searching using Windows Update we must allow old Internet drivers. We need
|
|
// to do this since it is posible to backup old Internet drivers and then reinstall
|
|
// them.
|
|
//
|
|
bOldInetDriversAllowed = (DeviceInstallParams.FlagsEx & DI_FLAGSEX_EXCLUDE_OLD_INET_DRIVERS)
|
|
? FALSE : TRUE;
|
|
|
|
DeviceInstallParams.FlagsEx |= DI_FLAGSEX_INET_DRIVER;
|
|
DeviceInstallParams.FlagsEx &= ~DI_FLAGSEX_EXCLUDE_OLD_INET_DRIVERS;
|
|
|
|
|
|
SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
);
|
|
}
|
|
|
|
SetupDiBuildDriverInfoList(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
DriverType
|
|
);
|
|
|
|
if (!bOldInetDriversAllowed) {
|
|
|
|
//
|
|
// Old Internet drivers were not allowed so we need to reset the DI_FLAGSEX_EXLCUED_OLD_INET_DRIVERS
|
|
// FlagsEx
|
|
//
|
|
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
|
|
if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
))
|
|
{
|
|
DeviceInstallParams.FlagsEx |= DI_FLAGSEX_EXCLUDE_OLD_INET_DRIVERS;
|
|
|
|
SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Search all floppy drives
|
|
//
|
|
if (!IsSearchCanceled(NewDevWiz) && (SearchOptions & SEARCH_FLOPPY) )
|
|
{
|
|
UINT DriveNumber=0;
|
|
|
|
while (!IsSearchCanceled(NewDevWiz) &&
|
|
(DriveNumber = GetNextDriveByType(DRIVE_REMOVABLE, ++DriveNumber)))
|
|
{
|
|
SearchDriveForDrivers(NewDevWiz, DRIVE_REMOVABLE, DriveNumber);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Search all CD-ROM drives
|
|
//
|
|
if (!IsSearchCanceled(NewDevWiz) && (SearchOptions & SEARCH_CDROM))
|
|
{
|
|
UINT DriveNumber=0;
|
|
|
|
while (!IsSearchCanceled(NewDevWiz) &&
|
|
(DriveNumber = GetNextDriveByType(DRIVE_CDROM, ++DriveNumber)))
|
|
{
|
|
SearchDriveForDrivers(NewDevWiz, DRIVE_CDROM, DriveNumber);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Search the Internet using CDM.DLL, only if the machine is currently connected
|
|
// to the Internet and CDM.DLL says it has the best driver.
|
|
//
|
|
if (!IsSearchCanceled(NewDevWiz) && (SearchOptions & SEARCH_INET_IF_CONNECTED)) {
|
|
|
|
//
|
|
// If the machine is connected to the Internet and the WU cache says it has
|
|
// a better driver then set the SEARCH_INET flag to get the driver from CDM.DLL
|
|
//
|
|
if (IsInternetAvailable(&NewDevWiz->hCdmInstance) &&
|
|
IsConnectedToInternet() &&
|
|
SearchWindowsUpdateCache(NewDevWiz)) {
|
|
|
|
SearchOptions |= SEARCH_INET;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Search the Internet using CDM.DLL
|
|
//
|
|
if (!IsSearchCanceled(NewDevWiz) && (SearchOptions & SEARCH_INET))
|
|
{
|
|
SetDriverPath(NewDevWiz, NULL);
|
|
|
|
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
|
|
if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
))
|
|
{
|
|
DeviceInstallParams.FlagsEx |= DI_FLAGSEX_DRIVERLIST_FROM_URL;
|
|
|
|
SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
);
|
|
}
|
|
|
|
SetupDiBuildDriverInfoList(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
SPDIT_COMPATDRIVER
|
|
);
|
|
|
|
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
|
|
if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
))
|
|
{
|
|
DeviceInstallParams.FlagsEx &= ~DI_FLAGSEX_DRIVERLIST_FROM_URL;
|
|
|
|
SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
DoDriverSearch(
|
|
HWND hWnd,
|
|
PNEWDEVWIZ NewDevWiz,
|
|
ULONG SearchOptions,
|
|
DWORD DriverType,
|
|
BOOL bAppendToExistingDriverList
|
|
)
|
|
{
|
|
ULONG SearchPolicy;
|
|
SP_DRVINFO_DATA DriverInfoData;
|
|
SP_DEVINSTALL_PARAMS DeviceInstallParams;
|
|
|
|
//
|
|
// The first thing that we do in this code is to Reset the CancelEvent in case it was set
|
|
// previously.
|
|
//
|
|
if (NewDevWiz->CancelEvent) {
|
|
ResetEvent(NewDevWiz->CancelEvent);
|
|
}
|
|
|
|
//
|
|
// Make sure that we filter out the locations that this user is not allowed to search.
|
|
//
|
|
SearchPolicy = 0;
|
|
GetDriverSearchPolicy(&SearchPolicy);
|
|
|
|
SearchOptions &= ~SearchPolicy;
|
|
|
|
//
|
|
// If the user does not want to append to the existing list then delete the
|
|
// current driver list.
|
|
//
|
|
if (!bAppendToExistingDriverList) {
|
|
|
|
SetupDiDestroyDriverInfoList(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
SPDIT_COMPATDRIVER
|
|
);
|
|
|
|
SetupDiDestroyDriverInfoList(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
SPDIT_CLASSDRIVER
|
|
);
|
|
}
|
|
|
|
//
|
|
// Clear out the selected driver
|
|
//
|
|
SetupDiSetSelectedDriver(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// Set the DI_FLAGSEX_APPENDDRIVERLIST since we will be building a big
|
|
// list.
|
|
//
|
|
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
|
|
if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
))
|
|
{
|
|
DeviceInstallParams.FlagsEx |= DI_FLAGSEX_APPENDDRIVERLIST;
|
|
SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
);
|
|
}
|
|
|
|
//
|
|
// Build up the list of drivers based on the SearchOptions
|
|
//
|
|
DoDriverSearchInSpecifiedLocations(hWnd, NewDevWiz, SearchOptions, DriverType);
|
|
|
|
//
|
|
//Pick the best driver from the list we just created
|
|
//
|
|
SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV,
|
|
NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData
|
|
);
|
|
|
|
if (!IsSearchCanceled(NewDevWiz))
|
|
{
|
|
//
|
|
// We don't allow old Windows Update drivers to be the Best driver
|
|
// unless it is also the Currently installed driver. So, if the Best
|
|
// driver is an Windows Update driver and not the currently installed driver
|
|
// then we need to re-compute the best driver after marking the node as
|
|
// BAD.
|
|
//
|
|
// The worst case is that a bad class installer keeps choosing a bad internet
|
|
// driver again and again. If this is the case then FixUpDriverListForInet
|
|
// will return FALSE and we will re-do the driver search and filter out all
|
|
// of the Old Internet drivers.
|
|
//
|
|
if (!FixUpDriverListForInet(NewDevWiz)) {
|
|
|
|
//
|
|
// Re-build the entire driver list and filter out all Old Internet drivers
|
|
//
|
|
SearchOptions &= ~SEARCH_DEFAULT;
|
|
SearchOptions |= SEARCH_DEFAULT_EXCLUDE_OLD_INET;
|
|
|
|
DoDriverSearchInSpecifiedLocations(hWnd, NewDevWiz, SearchOptions, DriverType);
|
|
|
|
//
|
|
//Pick the best driver from the list we just created
|
|
//
|
|
SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV,
|
|
NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData
|
|
);
|
|
}
|
|
|
|
//
|
|
// Update the NewDevWiz->ClassGuidSelected with the class of the selected driver.
|
|
//
|
|
if (!IsEqualGUID(&NewDevWiz->DeviceInfoData.ClassGuid, &GUID_NULL)) {
|
|
|
|
NewDevWiz->ClassGuidSelected = &NewDevWiz->DeviceInfoData.ClassGuid;
|
|
}
|
|
|
|
//
|
|
// Note whether we found multiple drivers or not.
|
|
//
|
|
DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
|
|
if (SetupDiEnumDriverInfo(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
SPDIT_COMPATDRIVER,
|
|
1,
|
|
&DriverInfoData
|
|
)) {
|
|
|
|
NewDevWiz->MultipleDriversFound = TRUE;
|
|
|
|
} else {
|
|
|
|
NewDevWiz->MultipleDriversFound = FALSE;
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// Clear the DI_FLAGSEX_APPENDDRIVERLIST flag from the Device Install Params.
|
|
//
|
|
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
|
|
if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
))
|
|
{
|
|
DeviceInstallParams.FlagsEx &= ~DI_FLAGSEX_APPENDDRIVERLIST;
|
|
SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
);
|
|
}
|
|
}
|
|
|
|
void
|
|
CancelDriverSearch(
|
|
PNEWDEVWIZ NewDevWiz
|
|
)
|
|
{
|
|
//
|
|
// First verify that there is a driver search going on by checking that the
|
|
// NewDevWiz->DriverSearchThread is not NULL
|
|
//
|
|
if (NewDevWiz->DriverSearchThread) {
|
|
|
|
if (NewDevWiz->CancelEvent) {
|
|
|
|
//
|
|
// Set the Cancel Event to that the DoDriverSearch() API knows to stop searching.
|
|
//
|
|
SetEvent(NewDevWiz->CancelEvent);
|
|
}
|
|
|
|
//
|
|
// Tell cdm.dll to stop it's current operation
|
|
//
|
|
CdmCancelCDMOperation(NewDevWiz->hCdmInstance);
|
|
|
|
//
|
|
// Tell setupapi.dll to stop it's current driver info search
|
|
//
|
|
SetupDiCancelDriverInfoSearch(NewDevWiz->hDeviceInfo);
|
|
|
|
//
|
|
// We should always have a window handle if the user was able to cancel.
|
|
//
|
|
if (NewDevWiz->hWnd) {
|
|
|
|
MSG Msg;
|
|
DWORD WaitReturn;
|
|
|
|
//
|
|
// And finaly, wait for the NewDevWiz->DriverSearchThread to terminate
|
|
//
|
|
while ((WaitReturn = MsgWaitForMultipleObjects(1,
|
|
&NewDevWiz->DriverSearchThread,
|
|
FALSE,
|
|
INFINITE,
|
|
QS_ALLINPUT
|
|
))
|
|
== WAIT_OBJECT_0 + 1) {
|
|
|
|
while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) {
|
|
|
|
if (!IsDialogMessage(NewDevWiz->hWnd, &Msg)) {
|
|
|
|
TranslateMessage(&Msg);
|
|
DispatchMessage(&Msg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
SetDriverPath(
|
|
PNEWDEVWIZ NewDevWiz,
|
|
PCTSTR DriverPath
|
|
)
|
|
{
|
|
SP_DEVINSTALL_PARAMS DeviceInstallParams;
|
|
SP_DRVINFO_DATA DriverInfoData;
|
|
|
|
DeviceInstallParams.cbSize = sizeof(DeviceInstallParams);
|
|
SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
);
|
|
|
|
wcscpy(DeviceInstallParams.DriverPath, DriverPath ? DriverPath : L"");
|
|
|
|
SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DeviceInstallParams
|
|
);
|
|
}
|
|
|
|
void
|
|
SearchDirectoryForDrivers(
|
|
PNEWDEVWIZ NewDevWiz,
|
|
PCTSTR Directory
|
|
)
|
|
{
|
|
HANDLE FindHandle;
|
|
PDIRNAMES DirNamesHead=NULL;
|
|
PDIRNAMES DirNames, Next;
|
|
PWCHAR AppendSub;
|
|
ULONG Len;
|
|
WIN32_FIND_DATAW FindData;
|
|
WCHAR SubDirName[MAX_PATH+sizeof(WCHAR)];
|
|
|
|
if (IsSearchCanceled(NewDevWiz)) {
|
|
return;
|
|
}
|
|
|
|
Len = wcslen(Directory);
|
|
memcpy(SubDirName, Directory, Len*sizeof(WCHAR));
|
|
AppendSub = SubDirName + Len;
|
|
|
|
|
|
//
|
|
// See if there are is anything (files, subdirs) in this dir.
|
|
//
|
|
*AppendSub = L'\\';
|
|
memcpy(AppendSub+1, StarDotStar, sizeof(StarDotStar));
|
|
|
|
FindHandle = FindFirstFileW(SubDirName, &FindData);
|
|
|
|
|
|
if (FindHandle == INVALID_HANDLE_VALUE) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// There might be inf files so invoke setup to look.
|
|
//
|
|
*AppendSub = L'\0';
|
|
SetDriverPath(NewDevWiz, Directory);
|
|
SetupDiBuildDriverInfoList(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
SPDIT_COMPATDRIVER
|
|
);
|
|
|
|
//
|
|
// find all of the subdirs, and save them in a temporary buffer,
|
|
// so that we can close the find handle *before* going recursive.
|
|
//
|
|
do {
|
|
|
|
if (IsSearchCanceled(NewDevWiz)) {
|
|
break;
|
|
}
|
|
|
|
if ((FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
|
wcscmp(FindData.cFileName, L".") &&
|
|
wcscmp(FindData.cFileName, L".."))
|
|
{
|
|
USHORT ulLen;
|
|
|
|
ulLen = (USHORT)wcslen(FindData.cFileName) * sizeof(WCHAR);
|
|
DirNames = malloc(sizeof(DIRNAMES) + ulLen);
|
|
if (!DirNames) {
|
|
return;
|
|
}
|
|
|
|
DirNames->DirectoryName.Length = ulLen;
|
|
DirNames->DirectoryName.MaximumLength = ulLen + sizeof(WCHAR);
|
|
DirNames->DirectoryName.Buffer = DirNames->NameBuffer;
|
|
memcpy(DirNames->NameBuffer, FindData.cFileName, ulLen + sizeof(WCHAR));
|
|
|
|
DirNames->Next = DirNamesHead;
|
|
DirNamesHead = DirNames;
|
|
|
|
}
|
|
|
|
} while (FindNextFileW(FindHandle, &FindData));
|
|
|
|
FindClose(FindHandle);
|
|
|
|
if (!DirNamesHead) {
|
|
return;
|
|
}
|
|
|
|
*AppendSub++ = L'\\';
|
|
|
|
Next = DirNamesHead;
|
|
while (Next) {
|
|
|
|
DirNames = Next;
|
|
|
|
memcpy(AppendSub,
|
|
DirNames->DirectoryName.Buffer,
|
|
DirNames->DirectoryName.Length + sizeof(WCHAR)
|
|
);
|
|
|
|
Next= DirNames->Next;
|
|
free(DirNames);
|
|
SearchDirectoryForDrivers(NewDevWiz, SubDirName);
|
|
}
|
|
}
|
|
|
|
void
|
|
SearchDriveForDrivers(
|
|
PNEWDEVWIZ NewDevWiz,
|
|
UINT DriveType,
|
|
UINT DriveNumber
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will return whether or not the specified media should be
|
|
searched for drivers, and it will return the path where the search should
|
|
start.
|
|
|
|
First the specified driver will be checked for an autorun.inf file. If there
|
|
is an autorun.inf with a [DeviceInstall] section that contains a DriverPath=
|
|
value then we will start the search at the path specified by DriverPath=.
|
|
If the [DeviceInstall] section does not contain any DriverPath= values then
|
|
the entire drive will be skipped. This is a good way for CD's that do not
|
|
contain drivers to be excluded from the driver search.
|
|
|
|
If there is no [DeviceInstall] section of the autorun.inf, or there is no
|
|
autorun.inf then the following rules apply.
|
|
|
|
- DRIVE_REMOVABLE - search the entire drive if the drive root is A: or B:,
|
|
otherwise don't search this media.
|
|
|
|
- DRIVE_CDROM - search the entire media if the size is less than 1Gig.
|
|
This means if the media is a CD then we will search the
|
|
entire CD, but if it is another larger media source, like a
|
|
DVD then we will not. We need to search the entire CD for
|
|
backwards compatibility even through it takes quite a while.
|
|
|
|
Arguments:
|
|
|
|
NewDevWiz - NEWDEVWIZ structure.
|
|
|
|
DriveType - specifies the type of drive this is, usually DRIVE_REMOVABLE
|
|
or DRIVE_CDROM.
|
|
|
|
DriveNumber - number specifiy the drive to search: 0 for A:, 1 for B:, etc.
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
TCHAR szAutoRunFile[MAX_PATH];
|
|
TCHAR szSectionName[MAX_PATH];
|
|
TCHAR szDriverPath[MAX_PATH];
|
|
TCHAR szSearchPath[MAX_PATH];
|
|
TCHAR DriveRoot[]=TEXT("a:");
|
|
HINF hInf = INVALID_HANDLE_VALUE;
|
|
INFCONTEXT Context;
|
|
UINT ErrorLine;
|
|
UINT PrevMode;
|
|
|
|
DriveRoot[0] = DriveNumber - 1 + DriveRoot[0];
|
|
|
|
PrevMode = SetErrorMode(0);
|
|
SetErrorMode(PrevMode | SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
|
|
|
|
try {
|
|
//
|
|
// First check the media for a autorun.inf that contains a [DeviceInstall]
|
|
// section with a DriverPath= value.
|
|
//
|
|
lstrcpy(szAutoRunFile, DriveRoot);
|
|
ConcatenatePaths(szAutoRunFile, TEXT("autorun.inf"), MAX_PATH, NULL);
|
|
szSectionName[0] = TEXT('\0');
|
|
|
|
hInf = SetupOpenInfFile(szAutoRunFile, NULL, INF_STYLE_OLDNT, &ErrorLine);
|
|
|
|
if (hInf != INVALID_HANDLE_VALUE) {
|
|
lstrcpy(szSectionName, TEXT("DeviceInstall"));
|
|
//
|
|
// First try the decorated section.
|
|
//
|
|
if (!GetProcessorExtension(szDriverPath, SIZECHARS(szDriverPath)) ||
|
|
(lstrcat(szSectionName, TEXT(".")) == NULL) ||
|
|
(lstrcat(szSectionName, szDriverPath) == NULL) ||
|
|
(SetupGetLineCount(hInf, szSectionName) == -1)) {
|
|
//
|
|
// Decorated section does not exist so try the undecorated section.
|
|
//
|
|
lstrcpy(szSectionName, TEXT("DeviceInstall"));
|
|
if (SetupGetLineCount(hInf, szSectionName) == -1) {
|
|
//
|
|
// There is no [DeviceInstall] section in this autorun.inf
|
|
//
|
|
szSectionName[0] = TEXT('\0');
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// If szSectionName is not 0 then we have a [DeviceInstall] section. Enumerate
|
|
// this section looking for all of the DriverPath= lines.
|
|
//
|
|
if (szSectionName[0] != TEXT('\0')) {
|
|
if (SetupFindFirstLine(hInf, szSectionName, TEXT("DriverPath"), &Context)) {
|
|
do {
|
|
//
|
|
// Process the DriverPath= line.
|
|
//
|
|
if (SetupGetStringField(&Context,
|
|
1,
|
|
szDriverPath,
|
|
sizeof(szDriverPath),
|
|
NULL)) {
|
|
//
|
|
// Search this location recursively.
|
|
//
|
|
lstrcpyn(szSearchPath, DriveRoot, SIZECHARS(szSearchPath));
|
|
ConcatenatePaths(szSearchPath, szDriverPath, SIZECHARS(szSearchPath), NULL);
|
|
SearchDirectoryForDrivers(NewDevWiz, (PCTSTR)szSearchPath);
|
|
}
|
|
} while (SetupFindNextMatchLine(&Context, TEXT("DriverPath"), &Context));
|
|
}
|
|
|
|
//
|
|
// If we had a valid [DeviceInstall] section then we are done.
|
|
//
|
|
goto clean0;
|
|
}
|
|
|
|
//
|
|
// At this point there either was no autorun.inf, or it didn't contain a
|
|
// [DeviceInstall] section or the [DeviceInstall] section didn't contain
|
|
// a DriverPath, so just do the default behavior.
|
|
//
|
|
if (DriveType == DRIVE_REMOVABLE) {
|
|
//
|
|
// We only search A: and B: removable drives by default.
|
|
//
|
|
if ((lstrcmpi(DriveRoot, TEXT("a:")) == 0) ||
|
|
(lstrcmpi(DriveRoot, TEXT("b:")) == 0)) {
|
|
//
|
|
// This is probably a floppy disk since it is A: or B: so search
|
|
// the drive.
|
|
//
|
|
lstrcpyn(szSearchPath, DriveRoot, SIZECHARS(szSearchPath));
|
|
SearchDirectoryForDrivers(NewDevWiz, (PCTSTR)szSearchPath);
|
|
}
|
|
}
|
|
|
|
if (DriveType == DRIVE_CDROM) {
|
|
//
|
|
// For DRIVE_CDROM drives we will check the media size and if it is
|
|
// less than 1Gig then we will assume it is a CD media and search it
|
|
// recursively, otherwise we won't search the drive by default.
|
|
//
|
|
ULARGE_INTEGER FreeBytesAvailable;
|
|
ULARGE_INTEGER TotalNumberOfBytes;
|
|
|
|
if (GetDiskFreeSpaceEx(DriveRoot,
|
|
&FreeBytesAvailable,
|
|
&TotalNumberOfBytes,
|
|
NULL) &&
|
|
(FreeBytesAvailable.HighPart == 0) &&
|
|
(FreeBytesAvailable.LowPart <= 0x40000000)) {
|
|
//
|
|
// There is less than 1Gig of stuff on this disk so it is probably
|
|
// a CD, so search the entire thing.
|
|
//
|
|
lstrcpyn(szSearchPath, DriveRoot, SIZECHARS(szSearchPath));
|
|
SearchDirectoryForDrivers(NewDevWiz, (PCTSTR)szSearchPath);
|
|
}
|
|
}
|
|
} except(NdwUnhandledExceptionFilter(GetExceptionInformation())) {
|
|
;
|
|
}
|
|
|
|
clean0:
|
|
|
|
SetErrorMode(PrevMode);
|
|
|
|
if (hInf != INVALID_HANDLE_VALUE) {
|
|
SetupCloseInfFile(hInf);
|
|
}
|
|
}
|
|
|
|
WCHAR szINFDIR[]=L"\\inf\\";
|
|
|
|
BOOL
|
|
IsSelectedDriver(
|
|
PNEWDEVWIZ NewDevWiz,
|
|
PSP_DRVINFO_DATA DriverInfoData
|
|
)
|
|
/*++
|
|
|
|
--*/
|
|
{
|
|
SP_DRVINFO_DETAIL_DATA DriverInfoDetailData;
|
|
SP_DRVINFO_DATA SelectedDriverInfoData;
|
|
SP_DRVINFO_DETAIL_DATA SelectedDriverInfoDetailData;
|
|
|
|
SelectedDriverInfoData.cbSize = sizeof(SelectedDriverInfoData);
|
|
if (!SetupDiGetSelectedDriver(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&SelectedDriverInfoData
|
|
)) {
|
|
|
|
//
|
|
// If we can't get the selected driver then just return FALSE
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Compare the SP_DRVINFO_DATA->Descriptions fields
|
|
//
|
|
if (wcscmp(DriverInfoData->Description, SelectedDriverInfoData.Description)) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Compare the SP_DRVINFO_DATA->MfgName fields
|
|
//
|
|
if (wcscmp(DriverInfoData->MfgName, SelectedDriverInfoData.MfgName)) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Compare the SP_DRVINFO_DATA->ProviderName fields
|
|
//
|
|
if (wcscmp(DriverInfoData->ProviderName, SelectedDriverInfoData.ProviderName)) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Get the SP_DRVINFO_DATAIL_DATA structures for both drivers
|
|
//
|
|
DriverInfoDetailData.cbSize = sizeof(DriverInfoDetailData);
|
|
if (!SetupDiGetDriverInfoDetail(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
DriverInfoData,
|
|
&DriverInfoDetailData,
|
|
sizeof(DriverInfoDetailData),
|
|
NULL
|
|
)
|
|
&&
|
|
GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
SelectedDriverInfoDetailData.cbSize = sizeof(SelectedDriverInfoDetailData);
|
|
if (!SetupDiGetDriverInfoDetail(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&SelectedDriverInfoData,
|
|
&SelectedDriverInfoDetailData,
|
|
sizeof(SelectedDriverInfoDetailData),
|
|
NULL
|
|
)
|
|
&&
|
|
GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Compare the SP_DRVINFO_DETAIL_DATA->InfFileName fields
|
|
//
|
|
if (wcscmp(DriverInfoDetailData.InfFileName, SelectedDriverInfoDetailData.InfFileName)) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Compare the SP_DRVINFO_DETAIL_DATA->SectionName fields
|
|
//
|
|
if (wcscmp(DriverInfoDetailData.SectionName, SelectedDriverInfoDetailData.SectionName)) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Compare the SP_DRVINFO_DETAIL_DATA->DrvDescription fields
|
|
//
|
|
if (wcscmp(DriverInfoDetailData.DrvDescription, SelectedDriverInfoDetailData.DrvDescription)) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// All of the above comparisons worked so this must be the selected driver
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
IsInstalledDriver(
|
|
PNEWDEVWIZ NewDevWiz,
|
|
PSP_DRVINFO_DATA DriverInfoData OPTIONAL
|
|
)
|
|
/*++
|
|
Determines if the currently selected driver is the
|
|
currently installed driver. By comparing DriverInfoData
|
|
and DriverInfoDetailData.
|
|
|
|
--*/
|
|
{
|
|
BOOL bReturn;
|
|
HKEY hDevRegKey;
|
|
DWORD cbData, Len;
|
|
PWCHAR pwch;
|
|
SP_DRVINFO_DATA SelectedDriverInfoData;
|
|
PSP_DRVINFO_DATA BestDriverInfoData;
|
|
SP_DRVINFO_DETAIL_DATA DriverInfoDetailData;
|
|
TCHAR Buffer[MAX_PATH*2];
|
|
PVOID pvBuffer=Buffer;
|
|
|
|
//
|
|
// Use the PSP_DRVINFO_DATA that was passed in. If one wasn't passed in the get the
|
|
// selected driver.
|
|
//
|
|
if (DriverInfoData) {
|
|
|
|
BestDriverInfoData = DriverInfoData;
|
|
|
|
} else {
|
|
|
|
SelectedDriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
|
|
if (SetupDiGetSelectedDriver(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&SelectedDriverInfoData
|
|
)) {
|
|
|
|
BestDriverInfoData = &SelectedDriverInfoData;
|
|
|
|
} else {
|
|
|
|
//
|
|
// If there is no currently selected driver then it can't be the installed one
|
|
//
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
bReturn = FALSE;
|
|
|
|
//
|
|
// Open a reg key to the driver specific location
|
|
//
|
|
hDevRegKey = SetupDiOpenDevRegKey(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
DICS_FLAG_GLOBAL,
|
|
0,
|
|
DIREG_DRV,
|
|
KEY_READ
|
|
);
|
|
|
|
if (hDevRegKey == INVALID_HANDLE_VALUE) {
|
|
|
|
goto SIIDExit;
|
|
}
|
|
|
|
|
|
//
|
|
// Compare Description, Manufacturer, and Provider Name.
|
|
// These are the three unique "keys" within a single inf file.
|
|
// Fetch the drvinfo, drvdetailinfo for the selected device.
|
|
//
|
|
|
|
//
|
|
// If the Device Description isn't the same, its a different driver.
|
|
//
|
|
if (!SetupDiGetDeviceRegistryProperty(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
SPDRP_DEVICEDESC,
|
|
NULL, // regdatatype
|
|
pvBuffer,
|
|
sizeof(Buffer),
|
|
NULL
|
|
)) {
|
|
|
|
*Buffer = TEXT('\0');
|
|
}
|
|
|
|
if (wcscmp(BestDriverInfoData->Description, Buffer)) {
|
|
|
|
goto SIIDExit;
|
|
}
|
|
|
|
|
|
//
|
|
// If the Manufacturer Name isn't the same, its different
|
|
//
|
|
|
|
if (!SetupDiGetDeviceRegistryProperty(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
SPDRP_MFG,
|
|
NULL, // regdatatype
|
|
pvBuffer,
|
|
sizeof(Buffer),
|
|
NULL
|
|
)) {
|
|
|
|
*Buffer = TEXT('\0');
|
|
}
|
|
|
|
if (wcscmp(BestDriverInfoData->MfgName, Buffer)) {
|
|
|
|
goto SIIDExit;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// If the Provider Name isn't the same, its different
|
|
//
|
|
|
|
cbData = sizeof(Buffer);
|
|
if (RegQueryValueEx(hDevRegKey,
|
|
REGSTR_VAL_PROVIDER_NAME,
|
|
NULL,
|
|
NULL,
|
|
pvBuffer,
|
|
&cbData
|
|
) != ERROR_SUCCESS) {
|
|
|
|
*Buffer = TEXT('\0');
|
|
}
|
|
|
|
if (wcscmp(BestDriverInfoData->ProviderName, Buffer)) {
|
|
|
|
goto SIIDExit;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Check the InfName, InfSection and DriverDesc
|
|
// NOTE: the installed infName will not contain the path to the default windows
|
|
// inf directory. If the same inf name has been found for the selected driver
|
|
// from another location besides the default inf search path, then it will
|
|
// contain a path, and is treated as a *different* driver.
|
|
//
|
|
|
|
|
|
DriverInfoDetailData.cbSize = sizeof(DriverInfoDetailData);
|
|
if (!SetupDiGetDriverInfoDetail(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
BestDriverInfoData,
|
|
&DriverInfoDetailData,
|
|
sizeof(DriverInfoDetailData),
|
|
NULL
|
|
)
|
|
&&
|
|
GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
|
|
|
goto SIIDExit;
|
|
}
|
|
|
|
|
|
|
|
Len = GetWindowsDirectory(Buffer, MAX_PATH);
|
|
if (Len && Len < MAX_PATH) {
|
|
|
|
pwch = Buffer + Len - 1;
|
|
if (*pwch != L'\\') {
|
|
|
|
pwch++;
|
|
}
|
|
|
|
wcscpy(pwch, szINFDIR);
|
|
pwch += sizeof(szINFDIR)/sizeof(WCHAR) - 1;
|
|
|
|
cbData = MAX_PATH*sizeof(WCHAR);
|
|
if (RegQueryValueEx(hDevRegKey,
|
|
REGSTR_VAL_INFPATH,
|
|
NULL,
|
|
NULL,
|
|
(PVOID)pwch,
|
|
&cbData
|
|
) != ERROR_SUCCESS )
|
|
{
|
|
*Buffer = TEXT('\0');
|
|
}
|
|
|
|
if (_wcsicmp( DriverInfoDetailData.InfFileName, Buffer)) {
|
|
|
|
goto SIIDExit;
|
|
}
|
|
|
|
} else {
|
|
|
|
goto SIIDExit;
|
|
}
|
|
|
|
|
|
|
|
cbData = sizeof(Buffer);
|
|
if (RegQueryValueEx(hDevRegKey,
|
|
REGSTR_VAL_INFSECTION,
|
|
NULL,
|
|
NULL,
|
|
pvBuffer,
|
|
&cbData
|
|
) != ERROR_SUCCESS ) {
|
|
|
|
*Buffer = TEXT('\0');
|
|
}
|
|
|
|
if (wcscmp(DriverInfoDetailData.SectionName, Buffer)) {
|
|
|
|
goto SIIDExit;
|
|
}
|
|
|
|
|
|
cbData = sizeof(Buffer);
|
|
if (RegQueryValueEx(hDevRegKey,
|
|
REGSTR_VAL_DRVDESC,
|
|
NULL,
|
|
NULL,
|
|
pvBuffer,
|
|
&cbData
|
|
) != ERROR_SUCCESS ) {
|
|
|
|
*Buffer = TEXT('\0');
|
|
}
|
|
|
|
if (wcscmp(DriverInfoDetailData.DrvDescription, Buffer)) {
|
|
|
|
goto SIIDExit;
|
|
}
|
|
|
|
|
|
bReturn = TRUE;
|
|
|
|
|
|
|
|
SIIDExit:
|
|
|
|
if (hDevRegKey != INVALID_HANDLE_VALUE) {
|
|
|
|
RegCloseKey(hDevRegKey);
|
|
}
|
|
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
BOOL
|
|
IsDriverNodeInteractiveInstall(
|
|
PNEWDEVWIZ NewDevWiz,
|
|
PSP_DRVINFO_DATA DriverInfoData
|
|
)
|
|
/*++
|
|
|
|
This function checks to see if the given PSP_DRVINFO_DATA is listed as a
|
|
InteractiveInstall in the [ControlFlags] section of the INF.
|
|
|
|
Return Value:
|
|
|
|
TRUE if the driver node is InteractiveInstall, FALSE otherwise.
|
|
|
|
--*/
|
|
{
|
|
BOOL b;
|
|
DWORD Err;
|
|
DWORD DriverInfoDetailDataSize;
|
|
HINF hInf;
|
|
INFCONTEXT InfContext;
|
|
TCHAR szBuffer[MAX_PATH];
|
|
DWORD i;
|
|
LPTSTR p;
|
|
PSP_DRVINFO_DETAIL_DATA pDriverInfoDetailData;
|
|
|
|
//
|
|
// Get the SP_DRVINFO_DETAIL_DATA so we can get the list of hardware and
|
|
// compatible Ids for this device.
|
|
//
|
|
b = SetupDiGetDriverInfoDetail(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
DriverInfoData,
|
|
NULL,
|
|
0,
|
|
&DriverInfoDetailDataSize
|
|
);
|
|
|
|
Err = GetLastError();
|
|
|
|
//
|
|
// The above call to get the driver info detail data should never succeed because the
|
|
// buffer will always be too small (we're just interested in sizeing the buffer
|
|
// at this point).
|
|
//
|
|
if (b || (Err != ERROR_INSUFFICIENT_BUFFER)) {
|
|
|
|
//
|
|
// For some reason the SetupDiGetDriverInfoDetail API failed...so return FALSE.
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Now that we know how big of a buffer we need to hold the driver info details,
|
|
// allocate the buffer and retrieve the information.
|
|
//
|
|
pDriverInfoDetailData = malloc(DriverInfoDetailDataSize);
|
|
|
|
if (!pDriverInfoDetailData) {
|
|
return FALSE;
|
|
}
|
|
|
|
pDriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
|
|
|
|
if (!SetupDiGetDriverInfoDetail(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
DriverInfoData,
|
|
pDriverInfoDetailData,
|
|
DriverInfoDetailDataSize,
|
|
NULL)) {
|
|
|
|
free(pDriverInfoDetailData);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// At this point we have all of the hardware and compatible IDs for this driver node.
|
|
// Now we need to open up the INF and see if any of them are referenced in an
|
|
// "InteractiveInstall" control flag entry.
|
|
//
|
|
hInf = SetupOpenInfFile(pDriverInfoDetailData->InfFileName,
|
|
NULL,
|
|
INF_STYLE_WIN4,
|
|
NULL
|
|
);
|
|
|
|
if (hInf == INVALID_HANDLE_VALUE) {
|
|
|
|
//
|
|
// For some reason we couldn't open the INF!
|
|
//
|
|
free(pDriverInfoDetailData);
|
|
return FALSE;
|
|
}
|
|
|
|
b = FALSE;
|
|
|
|
//
|
|
// Look at each InteractiveInstall line in the INF's [ControlFlags] section...
|
|
//
|
|
if (SetupFindFirstLine(hInf, INFSTR_CONTROLFLAGS_SECTION, INFSTR_KEY_INTERACTIVEINSTALL, &InfContext)) {
|
|
|
|
do {
|
|
//
|
|
// and within each line, examine each value...
|
|
//
|
|
for (i = 1;
|
|
SetupGetStringField(&InfContext, i, szBuffer, sizeof(szBuffer) / sizeof(TCHAR), NULL);
|
|
i++) {
|
|
//
|
|
// Check to see if this ID matches up with one of the driver node's hardware
|
|
// or compatible IDs.
|
|
//
|
|
for (p = pDriverInfoDetailData->HardwareID; *p; p+= (lstrlen(p) + 1)) {
|
|
|
|
if (!lstrcmpi(p, szBuffer)) {
|
|
//
|
|
// We found a match, this device is marked with
|
|
// InteractiveInstall.
|
|
//
|
|
b = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
} while (SetupFindNextMatchLine(&InfContext, INFSTR_KEY_INTERACTIVEINSTALL, &InfContext));
|
|
}
|
|
|
|
SetupCloseInfFile(hInf);
|
|
free(pDriverInfoDetailData);
|
|
|
|
return b;
|
|
}
|
|
|
|
BOOL
|
|
IsDriverAutoInstallable(
|
|
PNEWDEVWIZ NewDevWiz,
|
|
PSP_DRVINFO_DATA BestDriverInfoData
|
|
)
|
|
/*++
|
|
|
|
A driver (the selected driver) is considered auto installable if the following are TRUE:
|
|
|
|
- It is not a printer
|
|
- This must be a NDWTYPE_FOUNDNEW or NDWTYPE_UPDATE InstallType.
|
|
- There is no "InteractiveInstall" key in the [ControlFlags] section for any of the
|
|
Hardware or Compatible IDs of this device.
|
|
- There are no other drivers in the list that have the same or better Ranks or Dates then
|
|
the selected driver.
|
|
- If this is an Update Driver case the selected driver must not be the current driver
|
|
|
|
The reason for this function is that in the Found New Hardware case we want to automatically
|
|
install the best driver we find. We can't do that in the case where we have multiple drivers
|
|
that have the same Rank as the best driver found. The problem is that there are certain cases
|
|
where a user MUST choose the driver in these cases and so we can't automatically make the decision
|
|
for them. If this API does return FALSE that just means that the user will have to hit Next
|
|
on one extra wizard page.
|
|
|
|
Return Value:
|
|
|
|
TRUE if this device/driver is auto installable.
|
|
FALSE if this device/driver is NOT auto installable. This means that we will stop on the install
|
|
page and the user will have to hit Next to proceede.
|
|
|
|
--*/
|
|
{
|
|
DWORD BestRank;
|
|
DWORD DriverIndex;
|
|
DWORD BestRankCount = 0;
|
|
FILETIME BestDriverDate;
|
|
DWORDLONG BestDriverVersion;
|
|
TCHAR BestProviderName[LINE_LEN];
|
|
SP_DRVINFO_DATA DriverInfoData;
|
|
SP_DRVINSTALL_PARAMS DriverInstallParams;
|
|
|
|
//
|
|
// We only do Auto Installs if this is a NDWTYPE_FOUNDNEW or NDWTYPE_UPDATE install
|
|
//
|
|
if ((NewDevWiz->InstallType != NDWTYPE_FOUNDNEW) &&
|
|
(NewDevWiz->InstallType != NDWTYPE_UPDATE)) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// We need to special case printers as usuall.
|
|
//
|
|
if (IsEqualGUID(&NewDevWiz->DeviceInfoData.ClassGuid, &GUID_DEVCLASS_PRINTER)) {
|
|
//
|
|
// This is a printer, so if there is more than one printer driver node
|
|
// in the list, this isn't auto-installable.
|
|
//
|
|
DriverInfoData.cbSize = sizeof(DriverInfoData);
|
|
if (SetupDiEnumDriverInfo(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
SPDIT_COMPATDRIVER,
|
|
1,
|
|
&DriverInfoData
|
|
)) {
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check if the best driver is listed in the INF as InteractiveInstall. If
|
|
// it is, and there is more than one driver in the list, then this driver
|
|
// is not auto-installable.
|
|
//
|
|
if (IsDriverNodeInteractiveInstall(NewDevWiz, BestDriverInfoData)) {
|
|
//
|
|
// The best driver is marked as InteractiveInstall. If there is more
|
|
// than one driver in the list then this driver is NOT auto-installable.
|
|
//
|
|
DriverInfoData.cbSize = sizeof(DriverInfoData);
|
|
if (SetupDiEnumDriverInfo(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
SPDIT_COMPATDRIVER,
|
|
1,
|
|
&DriverInfoData
|
|
)) {
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// First get the Rank of the selected driver.
|
|
//
|
|
DriverInstallParams.cbSize = sizeof(DriverInstallParams);
|
|
if (!SetupDiGetDriverInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
BestDriverInfoData,
|
|
&DriverInstallParams
|
|
)) {
|
|
|
|
//
|
|
// If we can't get the Rank of the best driver then just return FALSE
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Remember the Rank and DriverDate of the selected (best) driver.
|
|
//
|
|
BestRank = DriverInstallParams.Rank;
|
|
memcpy(&BestDriverDate, &BestDriverInfoData->DriverDate, sizeof(BestDriverDate));
|
|
BestDriverVersion = BestDriverInfoData->DriverVersion;
|
|
lstrcpy(BestProviderName, BestDriverInfoData->ProviderName);
|
|
|
|
DriverInfoData.cbSize = sizeof(DriverInfoData);
|
|
DriverIndex = 0;
|
|
while (SetupDiEnumDriverInfo(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
SPDIT_COMPATDRIVER,
|
|
DriverIndex++,
|
|
&DriverInfoData
|
|
)) {
|
|
|
|
DriverInstallParams.cbSize = sizeof(DriverInstallParams);
|
|
if (SetupDiGetDriverInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DriverInfoData,
|
|
&DriverInstallParams
|
|
)) {
|
|
|
|
//
|
|
// Don't bother doing the comparison if this driver is marked as a BAD driver
|
|
//
|
|
if (!(DriverInstallParams.Flags & DNF_BAD_DRIVER) &&
|
|
!(DriverInstallParams.Flags & DNF_OLD_INET_DRIVER)) {
|
|
//
|
|
// Check if the current driver node is identical enough to the
|
|
// best driver that setupapi picked, so that we need the user
|
|
// to manually pick the one to install. This should be very
|
|
// rare that the user would ever need to make this choice.
|
|
//
|
|
if (DriverInstallParams.Rank < BestRank) {
|
|
//
|
|
// We found another driver node in the list that has a
|
|
// better (smaller) rank then the best driver.
|
|
//
|
|
BestRankCount++;
|
|
|
|
} else if ((DriverInstallParams.Rank == BestRank) &&
|
|
(CompareFileTime(&DriverInfoData.DriverDate, &BestDriverDate) == 1)) {
|
|
//
|
|
// We found another driver node in the list that has the
|
|
// same rank as the best driver and it has a newer driver
|
|
// date.
|
|
//
|
|
BestRankCount++;
|
|
|
|
} else if ((DriverInstallParams.Rank == BestRank) &&
|
|
(CompareFileTime(&DriverInfoData.DriverDate, &BestDriverDate) == 0)) {
|
|
//
|
|
// We found another driver node in the list that has the
|
|
// same rank as the best driver and the driver dates are
|
|
// the same.
|
|
// Check the provider names and if they are the same, then
|
|
// check which driver has the larger version, otherwise
|
|
// the driver version is meaningless so the user will have
|
|
// to make the choice.
|
|
//
|
|
if (lstrcmpi(BestProviderName, DriverInfoData.ProviderName) == 0) {
|
|
//
|
|
// Since the provider names are the same if the current
|
|
// driver node has a better, or the same, version as the
|
|
// best driver then the user will have to manually pick
|
|
// which driver they want.
|
|
//
|
|
if (DriverInfoData.DriverVersion >= BestDriverVersion) {
|
|
BestRankCount++;
|
|
}
|
|
} else {
|
|
//
|
|
// The provider names are different, which means the
|
|
// driver version information is meaningless, so the
|
|
// user will have to pick which driver they want.
|
|
//
|
|
BestRankCount++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// If BestRankCount is 2 or more than that means we have multiple drivers with the same or better
|
|
// Rank as the best driver.
|
|
//
|
|
if (BestRankCount >= 2) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// If we are in a NDWTYPE_UPDATE install then we need to make sure that the selected driver is not
|
|
// the current driver.
|
|
//
|
|
if ((NewDevWiz->InstallType == NDWTYPE_UPDATE) &&
|
|
IsInstalledDriver(NewDevWiz, BestDriverInfoData)) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// If we have come this far then that means
|
|
// - we're not dealing with a printer
|
|
// - this is either a NDWTYPE_FOUNDNEW or NDWTYPE_UPDATE install
|
|
// - this is not an "InteractiveInstall"
|
|
// - no other driver has the same or better rank then the selected driver.
|
|
// - if this is a NDWTYPE_UPDATE then the selected driver is not the current driver.
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
DriverSearchThreadProc(
|
|
LPVOID lpVoid
|
|
)
|
|
/*++
|
|
|
|
Description:
|
|
|
|
In the Wizard, we must do the driver search in a separate thread so that the user has the option
|
|
to cancel out.
|
|
|
|
--*/
|
|
{
|
|
PNEWDEVWIZ NewDevWiz = (PNEWDEVWIZ)lpVoid;
|
|
|
|
//
|
|
// Do the driver search.
|
|
//
|
|
DoDriverSearch(NewDevWiz->hWnd,
|
|
NewDevWiz,
|
|
NewDevWiz->SearchOptions,
|
|
SPDIT_COMPATDRIVER,
|
|
FALSE
|
|
);
|
|
|
|
|
|
//
|
|
// Post a message to the window to let it know that we are finished with the search
|
|
//
|
|
PostMessage(NewDevWiz->hWnd, WUM_SEARCHDRIVERS, TRUE, GetLastError());
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
INT_PTR CALLBACK
|
|
DriverSearchingDlgProc(
|
|
HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
PNEWDEVWIZ NewDevWiz;
|
|
TCHAR PropSheetHeaderTitle[MAX_PATH];
|
|
|
|
if (message == WM_INITDIALOG) {
|
|
|
|
LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
|
|
NewDevWiz = (PNEWDEVWIZ)lppsp->lParam;
|
|
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)NewDevWiz);
|
|
return TRUE;
|
|
}
|
|
|
|
NewDevWiz = (PNEWDEVWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
|
|
switch(message) {
|
|
|
|
case WM_NOTIFY:
|
|
switch (((NMHDR FAR *)lParam)->code) {
|
|
|
|
case PSN_SETACTIVE: {
|
|
HICON hicon;
|
|
int PrevPage;
|
|
|
|
SetDriverDescription(hDlg, IDC_DRVUPD_DRVDESC, NewDevWiz);
|
|
|
|
hicon = NULL;
|
|
if (NewDevWiz->ClassGuidSelected &&
|
|
SetupDiLoadClassIcon(NewDevWiz->ClassGuidSelected, &hicon, NULL))
|
|
{
|
|
hicon = (HICON)SendDlgItemMessage(hDlg, IDC_CLASSICON, STM_SETICON, (WPARAM)hicon, 0L);
|
|
}
|
|
|
|
else {
|
|
|
|
SetupDiLoadClassIcon(&GUID_DEVCLASS_UNKNOWN, &hicon, NULL);
|
|
hicon = (HICON)SendDlgItemMessage(hDlg, IDC_CLASSICON, STM_SETICON, (WPARAM)hicon, 0L);
|
|
}
|
|
|
|
if (hicon) {
|
|
|
|
DestroyIcon(hicon);
|
|
}
|
|
|
|
PrevPage = NewDevWiz->PrevPage;
|
|
NewDevWiz->PrevPage = IDD_NEWDEVWIZ_SEARCHING;
|
|
NewDevWiz->ExitDetect = FALSE;
|
|
|
|
|
|
//
|
|
// if coming from IDD_NEWDEVWIZ_INTRO or IDD_NEWDEVWIZ_ADVANCEDSEARCH
|
|
// page then begin driver search
|
|
//
|
|
if ((PrevPage == IDD_NEWDEVWIZ_INTRO) ||
|
|
(PrevPage == IDD_NEWDEVWIZ_ADVANCEDSEARCH) ||
|
|
(PrevPage == IDD_NEWDEVWIZ_WUPROMPT)) {
|
|
|
|
DWORD ThreadId;
|
|
|
|
LoadString(hNewDev, IDS_NEWDEVWIZ_SEARCHING, PropSheetHeaderTitle, SIZECHARS(PropSheetHeaderTitle));
|
|
|
|
PropSheet_SetHeaderTitle(GetParent(hDlg),
|
|
PropSheet_IdToIndex(GetParent(hDlg), IDD_NEWDEVWIZ_SEARCHING),
|
|
PropSheetHeaderTitle
|
|
);
|
|
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK);
|
|
|
|
ShowWindow(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH), SW_SHOW);
|
|
Animate_Open(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH), MAKEINTRESOURCE(IDA_SEARCHING));
|
|
Animate_Play(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH), 0, -1, -1);
|
|
|
|
|
|
NewDevWiz->CurrCursor = NewDevWiz->IdcAppStarting;
|
|
SetCursor(NewDevWiz->CurrCursor);
|
|
|
|
NewDevWiz->hWnd = hDlg;
|
|
|
|
//
|
|
// Start up a separate thread to do the driver search on.
|
|
// When the driver searching is complete the DriverSearchThreadProc
|
|
// will post us a WUM_SEARCHDRIVERS message.
|
|
//
|
|
NewDevWiz->DriverSearchThread = CreateThread(NULL,
|
|
0,
|
|
(LPTHREAD_START_ROUTINE)DriverSearchThreadProc,
|
|
(LPVOID)NewDevWiz,
|
|
0,
|
|
&ThreadId
|
|
);
|
|
}
|
|
|
|
//
|
|
// if coming back from DRVUPD_FINISH page, search is done,
|
|
// so wait for instructions from user.
|
|
//
|
|
else {
|
|
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case PSN_WIZNEXT:
|
|
|
|
NewDevWiz->EnterInto = IDD_NEWDEVWIZ_INSTALLDEV;
|
|
|
|
if (NewDevWiz->DoAutoInstall) {
|
|
//
|
|
// This is the case where we found a better driver (or a driver in the
|
|
// Found New Hardware case) and so we will just do an AutoInstall.
|
|
//
|
|
SetDlgMsgResult(hDlg, message, IDD_NEWDEVWIZ_INSTALLDEV);
|
|
|
|
} else if (NewDevWiz->CurrentDriverIsSelected) {
|
|
//
|
|
// This is the case where the current driver is the best driver.
|
|
//
|
|
SetDlgMsgResult(hDlg, message, IDD_NEWDEVWIZ_USECURRENT_FINISH);
|
|
|
|
} else if (NewDevWiz->NoDriversFound) {
|
|
//
|
|
// This is the case where we could not find any drivers for this device.
|
|
//
|
|
//
|
|
// If we could not find any drivers for this device then we have two choices,
|
|
// we either take the user to the Windows Update prompting wizard page,
|
|
// or take them directly to the no driver found finish page. We will only
|
|
// take them to the Windows Update prompting page if the AlreadySearchedInet
|
|
// BOOL is FALSE and the machine is NOT currently connected to the Internet.
|
|
//
|
|
if (!IsInternetAvailable(&NewDevWiz->hCdmInstance) ||
|
|
NewDevWiz->AlreadySearchedWU ||
|
|
IsConnectedToInternet()) {
|
|
|
|
SetDlgMsgResult(hDlg, message, IDD_NEWDEVWIZ_NODRIVER_FINISH);
|
|
|
|
} else {
|
|
|
|
SetDlgMsgResult(hDlg, message, IDD_NEWDEVWIZ_WUPROMPT);
|
|
}
|
|
} else {
|
|
//
|
|
// If we aren't doing an AutoInstall and this is NOT the current driver or
|
|
// NO driver case, then we need to jump to the page that lists out the drivers.
|
|
//
|
|
SetDlgMsgResult(hDlg, message, IDD_NEWDEVWIZ_LISTDRIVERS);
|
|
}
|
|
|
|
break;
|
|
|
|
case PSN_WIZBACK:
|
|
if (NewDevWiz->ExitDetect) {
|
|
SetDlgMsgResult(hDlg, message, -1);
|
|
break;
|
|
}
|
|
|
|
NewDevWiz->CurrentDriverIsSelected = FALSE;
|
|
NewDevWiz->ExitDetect = TRUE;
|
|
NewDevWiz->CurrCursor = NewDevWiz->IdcWait;
|
|
SetCursor(NewDevWiz->CurrCursor);
|
|
CancelDriverSearch(NewDevWiz);
|
|
NewDevWiz->CurrCursor = NULL;
|
|
EnableWindow(GetDlgItem(GetParent(hDlg), IDCANCEL), TRUE);
|
|
SetDlgMsgResult(hDlg, message, NewDevWiz->EnterFrom);
|
|
Animate_Stop(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH));
|
|
break;
|
|
|
|
case PSN_QUERYCANCEL:
|
|
if (NewDevWiz->ExitDetect) {
|
|
|
|
SetDlgMsgResult(hDlg, message, TRUE);
|
|
break;
|
|
}
|
|
|
|
NewDevWiz->ExitDetect = TRUE;
|
|
NewDevWiz->CurrCursor = NewDevWiz->IdcWait;
|
|
SetCursor(NewDevWiz->CurrCursor);
|
|
CancelDriverSearch(NewDevWiz);
|
|
NewDevWiz->CurrCursor = NULL;
|
|
SetDlgMsgResult(hDlg, message, FALSE);
|
|
break;
|
|
|
|
case PSN_RESET:
|
|
Animate_Stop(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH));
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case WM_DESTROY:
|
|
CancelDriverSearch(NewDevWiz);
|
|
break;
|
|
|
|
|
|
case WUM_SEARCHDRIVERS: {
|
|
|
|
SP_DRVINFO_DATA DriverInfoData;
|
|
|
|
Animate_Stop(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH));
|
|
ShowWindow(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH), SW_HIDE);
|
|
|
|
NewDevWiz->CurrCursor = NULL;
|
|
SetCursor(NewDevWiz->IdcArrow);
|
|
|
|
if (NewDevWiz->ExitDetect) {
|
|
|
|
break;
|
|
}
|
|
|
|
DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
|
|
if (SetupDiGetSelectedDriver(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DriverInfoData
|
|
))
|
|
{
|
|
//
|
|
// We basically have three cases when we find a driver for the device.
|
|
// 1) The driver is autoinstallable. This means we jump directly to the install page.
|
|
// 2) The driver is the current driver. This means we don't reinstall the driver.
|
|
// 3) We have muliple drivers or the drivers aren't autoinstallable. This means we
|
|
// show a list of the drivers to the user and make them pick.
|
|
//
|
|
NewDevWiz->NoDriversFound = FALSE;
|
|
|
|
//
|
|
// If this driver is Auto Installable then we will skip stoping at the Install
|
|
// confirmation page.
|
|
//
|
|
NewDevWiz->DoAutoInstall = IsDriverAutoInstallable(NewDevWiz, &DriverInfoData);
|
|
|
|
//
|
|
// If the selected driver is the currently installed driver then jump to the currently
|
|
// installed driver finish page.
|
|
//
|
|
if (IsInstalledDriver(NewDevWiz, &DriverInfoData)) {
|
|
|
|
NewDevWiz->CurrentDriverIsSelected = TRUE;
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// This is the case where we could not get a selected driver because we didn't
|
|
// find any drivers in the driver search.
|
|
//
|
|
NewDevWiz->NoDriversFound = TRUE;
|
|
}
|
|
|
|
//
|
|
// Auto Jump to the next page.
|
|
//
|
|
PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
|
|
break;
|
|
}
|
|
|
|
|
|
case WM_SETCURSOR:
|
|
if (NewDevWiz->CurrCursor) {
|
|
|
|
SetCursor(NewDevWiz->CurrCursor);
|
|
break;
|
|
}
|
|
|
|
// fall thru to return(FALSE);
|
|
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
} // end of switch on message
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT_PTR CALLBACK
|
|
WUPromptDlgProc(
|
|
HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
static int pEnterFrom;
|
|
static DWORD dwWizCase = 0;
|
|
HICON hicon;
|
|
|
|
PNEWDEVWIZ NewDevWiz = (PNEWDEVWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
|
|
switch (message) {
|
|
|
|
case WM_INITDIALOG: {
|
|
LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
|
|
NewDevWiz = (PNEWDEVWIZ)lppsp->lParam;
|
|
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)NewDevWiz);
|
|
|
|
//
|
|
// Set the Initial radio button state to connect to the Internet.
|
|
//
|
|
CheckRadioButton(hDlg,
|
|
IDC_WU_SEARCHINET,
|
|
IDC_WU_NOSEARCH,
|
|
IDC_WU_SEARCHINET
|
|
);
|
|
|
|
pEnterFrom = NewDevWiz->EnterFrom;
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
hicon = (HICON)LOWORD(SendDlgItemMessage(hDlg, IDC_CLASSICON, STM_GETICON, 0, 0));
|
|
if (hicon) {
|
|
|
|
DestroyIcon(hicon);
|
|
}
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
|
|
switch (((NMHDR FAR *)lParam)->code) {
|
|
|
|
case PSN_SETACTIVE:
|
|
NewDevWiz->PrevPage = IDD_NEWDEVWIZ_WUPROMPT;
|
|
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
|
|
|
|
hicon = NULL;
|
|
if (NewDevWiz->ClassGuidSelected &&
|
|
SetupDiLoadClassIcon(NewDevWiz->ClassGuidSelected, &hicon, NULL))
|
|
{
|
|
hicon = (HICON)SendDlgItemMessage(hDlg, IDC_CLASSICON, STM_SETICON, (WPARAM)hicon, 0L);
|
|
}
|
|
|
|
else {
|
|
|
|
SetupDiLoadClassIcon(&GUID_DEVCLASS_UNKNOWN, &hicon, NULL);
|
|
hicon = (HICON)SendDlgItemMessage(hDlg, IDC_CLASSICON, STM_SETICON, (WPARAM)hicon, 0L);
|
|
}
|
|
|
|
if (hicon) {
|
|
|
|
DestroyIcon(hicon);
|
|
}
|
|
|
|
SetDriverDescription(hDlg, IDC_DRVUPD_DRVDESC, NewDevWiz);
|
|
break;
|
|
|
|
case PSN_RESET:
|
|
break;
|
|
|
|
case PSN_WIZNEXT:
|
|
NewDevWiz->AlreadySearchedWU = TRUE;
|
|
NewDevWiz->EnterFrom = IDD_NEWDEVWIZ_WUPROMPT;
|
|
|
|
//
|
|
// Set the SEARCH_INET search option and go to the searching
|
|
// wizard page.
|
|
//
|
|
if (IsDlgButtonChecked(hDlg, IDC_WU_SEARCHINET)) {
|
|
|
|
NewDevWiz->SearchOptions = SEARCH_INET;
|
|
|
|
SetDlgMsgResult(hDlg, message, IDD_NEWDEVWIZ_SEARCHING);
|
|
|
|
} else {
|
|
SetDlgMsgResult(hDlg, message, IDD_NEWDEVWIZ_NODRIVER_FINISH);
|
|
}
|
|
break;
|
|
|
|
case PSN_WIZBACK:
|
|
NewDevWiz->AlreadySearchedWU = FALSE;
|
|
SetDlgMsgResult(hDlg, message, pEnterFrom);
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
void
|
|
FillDriversList(
|
|
HWND hwndList,
|
|
PNEWDEVWIZ NewDevWiz,
|
|
int SignedIconIndex,
|
|
int UnsignedIconIndex
|
|
)
|
|
{
|
|
int IndexDriver;
|
|
int SelectedDriver;
|
|
int lvIndex;
|
|
LV_ITEM lviItem;
|
|
BOOL FoundInstalledDriver;
|
|
BOOL FoundSelectedDriver;
|
|
SP_DRVINFO_DATA DriverInfoData;
|
|
SP_DRVINFO_DETAIL_DATA DriverInfoDetailData;
|
|
SP_DRVINSTALL_PARAMS DriverInstallParams;
|
|
|
|
SendMessage(hwndList, WM_SETREDRAW, FALSE, 0L);
|
|
ListView_DeleteAllItems(hwndList);
|
|
ListView_SetExtendedListViewStyle(hwndList, LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT);
|
|
|
|
IndexDriver = 0;
|
|
SelectedDriver = 0;
|
|
DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
|
|
DriverInfoDetailData.cbSize = sizeof(DriverInfoDetailData);
|
|
|
|
FoundInstalledDriver = FALSE;
|
|
FoundSelectedDriver = FALSE;
|
|
while (SetupDiEnumDriverInfo(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
SPDIT_COMPATDRIVER,
|
|
IndexDriver,
|
|
&DriverInfoData
|
|
)) {
|
|
|
|
//
|
|
// Get the DriverInstallParams so we can see if we got this driver from the Internet
|
|
//
|
|
DriverInstallParams.cbSize = sizeof(SP_DRVINSTALL_PARAMS);
|
|
if (SetupDiGetDriverInstallParams(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DriverInfoData,
|
|
&DriverInstallParams)) {
|
|
//
|
|
// Don't show old Internet drivers because we don't have the files locally
|
|
// anymore to install these! Also don't show BAD drivers.
|
|
//
|
|
if ((DriverInstallParams.Flags & DNF_OLD_INET_DRIVER) ||
|
|
(DriverInstallParams.Flags & DNF_BAD_DRIVER)) {
|
|
|
|
IndexDriver++;
|
|
continue;
|
|
}
|
|
|
|
lviItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
|
|
lviItem.iItem = IndexDriver;
|
|
lviItem.iSubItem = 0;
|
|
lviItem.pszText = DriverInfoData.Description;
|
|
lviItem.lParam = 0;
|
|
lviItem.iImage = (DriverInstallParams.Flags & DNF_INF_IS_SIGNED)
|
|
? SignedIconIndex
|
|
: UnsignedIconIndex;
|
|
|
|
//
|
|
// If this is the currently installed driver then set the DRIVER_LIST_CURRENT_DRIVER
|
|
// flag in the lParam.
|
|
//
|
|
if (!FoundInstalledDriver &&
|
|
(NewDevWiz->InstallType == NDWTYPE_UPDATE) &&
|
|
IsInstalledDriver(NewDevWiz, &DriverInfoData)) {
|
|
|
|
lviItem.lParam |= DRIVER_LIST_CURRENT_DRIVER;
|
|
}
|
|
|
|
//
|
|
// If this is the selected driver then set the DRIVER_LIST_SELECTED_DRIVER
|
|
// flag in the lParam
|
|
//
|
|
if (!FoundSelectedDriver &&
|
|
IsSelectedDriver(NewDevWiz, &DriverInfoData)) {
|
|
|
|
lviItem.lParam |= DRIVER_LIST_SELECTED_DRIVER;
|
|
SelectedDriver = IndexDriver;
|
|
}
|
|
|
|
if (DriverInstallParams.Flags & DNF_INF_IS_SIGNED) {
|
|
lviItem.lParam |= DRIVER_LIST_SIGNED_DRIVER;
|
|
}
|
|
|
|
lvIndex = ListView_InsertItem(hwndList, &lviItem);
|
|
|
|
if (DriverInfoData.DriverVersion != 0) {
|
|
|
|
ULARGE_INTEGER Version;
|
|
TCHAR VersionString[LINE_LEN];
|
|
|
|
Version.QuadPart = DriverInfoData.DriverVersion;
|
|
|
|
wsprintf(VersionString, TEXT("%0d.%0d.%0d.%0d"),
|
|
HIWORD(Version.HighPart), LOWORD(Version.HighPart),
|
|
HIWORD(Version.LowPart), LOWORD(Version.LowPart));
|
|
|
|
ListView_SetItemText(hwndList, lvIndex, 1, VersionString);
|
|
|
|
} else {
|
|
|
|
ListView_SetItemText(hwndList, lvIndex, 1, szUnknown);
|
|
}
|
|
|
|
ListView_SetItemText(hwndList, lvIndex, 2, DriverInfoData.MfgName);
|
|
|
|
|
|
if (DriverInstallParams.Flags & DNF_INET_DRIVER) {
|
|
|
|
//
|
|
// Driver is from the Internet
|
|
//
|
|
TCHAR WindowsUpdate[MAX_PATH];
|
|
LoadString(hNewDev, IDS_DEFAULT_INTERNET_HOST, WindowsUpdate, SIZECHARS(WindowsUpdate));
|
|
ListView_SetItemText(hwndList, lvIndex, 3, WindowsUpdate);
|
|
|
|
} else {
|
|
|
|
//
|
|
// Driver is not from the Internet
|
|
//
|
|
if (SetupDiGetDriverInfoDetail(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DriverInfoData,
|
|
&DriverInfoDetailData,
|
|
sizeof(DriverInfoDetailData),
|
|
NULL
|
|
)
|
|
||
|
|
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
|
|
|
ListView_SetItemText(hwndList, lvIndex, 3, DriverInfoDetailData.InfFileName);
|
|
|
|
} else {
|
|
ListView_SetItemText(hwndList, lvIndex, 3, TEXT(""));
|
|
}
|
|
}
|
|
}
|
|
|
|
IndexDriver++;
|
|
}
|
|
|
|
//
|
|
// Select the SelectedDriver item in the list and scroll it into view
|
|
// since this is the best driver in the list.
|
|
//
|
|
ListView_SetItemState(hwndList,
|
|
SelectedDriver,
|
|
LVIS_SELECTED|LVIS_FOCUSED,
|
|
LVIS_SELECTED|LVIS_FOCUSED
|
|
);
|
|
|
|
ListView_EnsureVisible(hwndList, SelectedDriver, FALSE);
|
|
ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE_USEHEADER);
|
|
ListView_SetColumnWidth(hwndList, 1, LVSCW_AUTOSIZE_USEHEADER);
|
|
ListView_SetColumnWidth(hwndList, 2, LVSCW_AUTOSIZE_USEHEADER);
|
|
ListView_SetColumnWidth(hwndList, 3, LVSCW_AUTOSIZE_USEHEADER);
|
|
|
|
SendMessage(hwndList, WM_SETREDRAW, TRUE, 0L);
|
|
}
|
|
|
|
BOOL
|
|
SelectDriverFromList(
|
|
HWND hwndList,
|
|
PNEWDEVWIZ NewDevWiz
|
|
)
|
|
{
|
|
int lvSelected;
|
|
SP_DRVINFO_DATA DriverInfoData;
|
|
LVITEM lvi;
|
|
|
|
DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
|
|
lvSelected = ListView_GetNextItem(hwndList,
|
|
-1,
|
|
LVNI_SELECTED
|
|
);
|
|
|
|
if (SetupDiEnumDriverInfo(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
SPDIT_COMPATDRIVER,
|
|
lvSelected,
|
|
&DriverInfoData
|
|
))
|
|
{
|
|
SetupDiSetSelectedDriver(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DriverInfoData
|
|
);
|
|
}
|
|
|
|
//
|
|
// if there is no selected driver call DIF_SELECTBESTCOMPATDRV.
|
|
//
|
|
|
|
if (!SetupDiGetSelectedDriver(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
&DriverInfoData
|
|
))
|
|
{
|
|
if (SetupDiEnumDriverInfo(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
SPDIT_COMPATDRIVER,
|
|
0,
|
|
&DriverInfoData
|
|
))
|
|
{
|
|
//
|
|
//Pick the best driver from the list we just created
|
|
//
|
|
SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV,
|
|
NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData
|
|
);
|
|
}
|
|
|
|
else
|
|
{
|
|
SetupDiSetSelectedDriver(NewDevWiz->hDeviceInfo,
|
|
&NewDevWiz->DeviceInfoData,
|
|
NULL
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Return TRUE if the selected driver in the list is the current driver, otherwise return FALSE
|
|
//
|
|
ZeroMemory(&lvi, sizeof(lvi));
|
|
lvi.iItem = lvSelected;
|
|
lvi.mask = LVIF_PARAM;
|
|
|
|
if (ListView_GetItem(hwndList, &lvi) &&
|
|
(lvi.lParam & DRIVER_LIST_CURRENT_DRIVER)) {
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
INT_PTR CALLBACK
|
|
ListDriversDlgProc(
|
|
HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
PNEWDEVWIZ NewDevWiz = (PNEWDEVWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
static int pEnterFrom;
|
|
static HIMAGELIST himl = NULL;
|
|
static int SignedIconIndex, UnsignedIconIndex;
|
|
|
|
switch (message) {
|
|
|
|
case WM_INITDIALOG: {
|
|
|
|
HWND hwndParentDlg;
|
|
HWND hwndList;
|
|
LV_COLUMN lvcCol;
|
|
LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
|
|
TCHAR Buffer[64];
|
|
HFONT hfont;
|
|
LOGFONT LogFont;
|
|
|
|
NewDevWiz = (PNEWDEVWIZ)lppsp->lParam;
|
|
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)NewDevWiz);
|
|
|
|
pEnterFrom = NewDevWiz->EnterFrom;
|
|
|
|
//
|
|
// Create the normal and bold fonts
|
|
//
|
|
hfont = (HFONT)SendMessage(GetDlgItem(hDlg, IDC_SIGNED_TEXT), WM_GETFONT, 0, 0);
|
|
GetObject(hfont, sizeof(LogFont), &LogFont);
|
|
NewDevWiz->hfontTextNormal = CreateFontIndirect(&LogFont);
|
|
|
|
hfont = (HFONT)SendMessage(GetDlgItem(hDlg, IDC_SIGNED_TEXT), WM_GETFONT, 0, 0);
|
|
GetObject(hfont, sizeof(LogFont), &LogFont);
|
|
LogFont.lfWeight = FW_BOLD;
|
|
NewDevWiz->hfontTextBold = CreateFontIndirect(&LogFont);
|
|
|
|
hwndList = GetDlgItem(hDlg, IDC_LISTDRIVERS_LISTVIEW);
|
|
|
|
//
|
|
// Create the image list that contains the signed and not signed icons.
|
|
//
|
|
himl = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
|
|
GetSystemMetrics(SM_CYSMICON),
|
|
ILC_MASK |
|
|
(GetWindowLong(GetParent(hDlg), GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
|
|
? ILC_MIRROR
|
|
: 0,
|
|
1,
|
|
1);
|
|
|
|
//
|
|
// Associate the image list with the list view.
|
|
//
|
|
if (himl) {
|
|
HICON hIcon;
|
|
|
|
ImageList_SetBkColor(himl, GetSysColor(COLOR_WINDOW));
|
|
|
|
//
|
|
// Add the signed and unsigned icons to the imagelist.
|
|
//
|
|
if ((hIcon = LoadIcon(hNewDev, MAKEINTRESOURCE(IDI_BLANK))) != NULL) {
|
|
UnsignedIconIndex = ImageList_AddIcon(himl, hIcon);
|
|
}
|
|
|
|
if ((hIcon = LoadIcon(hNewDev, MAKEINTRESOURCE(IDI_SIGNED))) != NULL) {
|
|
SignedIconIndex = ImageList_AddIcon(himl, hIcon);
|
|
}
|
|
|
|
ListView_SetImageList(hwndList,
|
|
himl,
|
|
LVSIL_SMALL
|
|
);
|
|
}
|
|
|
|
//
|
|
// Insert columns for listview.
|
|
// 0 == device name
|
|
// 1 == version
|
|
// 2 == manufacturer
|
|
// 3 == INF location
|
|
//
|
|
lvcCol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
|
|
lvcCol.fmt = LVCFMT_LEFT;
|
|
lvcCol.pszText = Buffer;
|
|
|
|
lvcCol.iSubItem = 0;
|
|
LoadString(hNewDev, IDS_DRIVERDESC, Buffer, SIZECHARS(Buffer));
|
|
ListView_InsertColumn(hwndList, 0, &lvcCol);
|
|
|
|
lvcCol.iSubItem = 1;
|
|
LoadString(hNewDev, IDS_DRIVERVERSION, Buffer, SIZECHARS(Buffer));
|
|
ListView_InsertColumn(hwndList, 1, &lvcCol);
|
|
|
|
lvcCol.iSubItem = 2;
|
|
LoadString(hNewDev, IDS_DRIVERMFG, Buffer, SIZECHARS(Buffer));
|
|
ListView_InsertColumn(hwndList, 2, &lvcCol);
|
|
|
|
lvcCol.iSubItem = 3;
|
|
LoadString(hNewDev, IDS_DRIVERINF, Buffer, SIZECHARS(Buffer));
|
|
ListView_InsertColumn(hwndList, 3, &lvcCol);
|
|
|
|
SendMessage(hwndList,
|
|
LVM_SETEXTENDEDLISTVIEWSTYLE,
|
|
LVS_EX_FULLROWSELECT,
|
|
LVS_EX_FULLROWSELECT
|
|
);
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
if (NewDevWiz->hfontTextNormal ) {
|
|
DeleteObject(NewDevWiz->hfontTextNormal);
|
|
NewDevWiz->hfontTextBigBold = NULL;
|
|
}
|
|
|
|
if (NewDevWiz->hfontTextBold ) {
|
|
DeleteObject(NewDevWiz->hfontTextBold);
|
|
NewDevWiz->hfontTextBold = NULL;
|
|
}
|
|
|
|
if (himl) {
|
|
ImageList_Destroy(himl);
|
|
}
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
|
|
switch (((NMHDR FAR *)lParam)->code) {
|
|
|
|
case PSN_SETACTIVE: {
|
|
int PrevPage;
|
|
HICON hicon;
|
|
|
|
PrevPage = NewDevWiz->PrevPage;
|
|
NewDevWiz->PrevPage = IDD_NEWDEVWIZ_LISTDRIVERS;
|
|
|
|
SetDriverDescription(hDlg, IDC_DRVUPD_DRVDESC, NewDevWiz);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_SIGNED_ICON), SW_HIDE);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_SIGNED_TEXT), SW_HIDE);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_SIGNED_LINK), SW_HIDE);
|
|
|
|
hicon = NULL;
|
|
if (NewDevWiz->ClassGuidSelected &&
|
|
SetupDiLoadClassIcon(NewDevWiz->ClassGuidSelected, &hicon, NULL)) {
|
|
hicon = (HICON)SendDlgItemMessage(hDlg, IDC_CLASSICON, STM_SETICON, (WPARAM)hicon, 0L);
|
|
} else {
|
|
SetupDiLoadClassIcon(&GUID_DEVCLASS_UNKNOWN, &hicon, NULL);
|
|
SendDlgItemMessage(hDlg, IDC_CLASSICON, STM_SETICON, (WPARAM)hicon, 0L);
|
|
}
|
|
|
|
if (hicon) {
|
|
DestroyIcon(hicon);
|
|
}
|
|
|
|
//
|
|
// Fill the list view
|
|
//
|
|
FillDriversList(GetDlgItem(hDlg, IDC_LISTDRIVERS_LISTVIEW),
|
|
NewDevWiz,
|
|
SignedIconIndex,
|
|
UnsignedIconIndex);
|
|
|
|
}
|
|
break;
|
|
|
|
case PSN_RESET:
|
|
break;
|
|
|
|
case PSN_WIZBACK:
|
|
SetDlgMsgResult(hDlg, message, pEnterFrom);
|
|
break;
|
|
|
|
case PSN_WIZNEXT:
|
|
|
|
NewDevWiz->EnterFrom = IDD_NEWDEVWIZ_LISTDRIVERS;
|
|
|
|
if (SelectDriverFromList(GetDlgItem(hDlg, IDC_LISTDRIVERS_LISTVIEW), NewDevWiz)) {
|
|
|
|
NewDevWiz->EnterInto = IDD_NEWDEVWIZ_USECURRENT_FINISH;
|
|
SetDlgMsgResult(hDlg, message, IDD_NEWDEVWIZ_USECURRENT_FINISH);
|
|
|
|
} else {
|
|
|
|
NewDevWiz->EnterInto = IDD_NEWDEVWIZ_INSTALLDEV;
|
|
SetDlgMsgResult(hDlg, message, IDD_NEWDEVWIZ_INSTALLDEV);
|
|
}
|
|
break;
|
|
|
|
case LVN_ITEMCHANGED: {
|
|
|
|
LPNM_LISTVIEW lpnmlv = (LPNM_LISTVIEW)lParam;
|
|
int StringId = 0;
|
|
int DigitalSignatureSignedId = 0;
|
|
HICON hIcon = NULL;
|
|
|
|
if ((lpnmlv->uChanged & LVIF_STATE)) {
|
|
if (lpnmlv->uNewState & LVIS_SELECTED) {
|
|
//
|
|
// lParam & DRIVER_LIST_CURRENT_DRIVER means this is the currently installed driver.
|
|
// lParam & DRIVER_LIST_SELECTED_DRIVER means this is the selected/best driver.
|
|
//
|
|
if (lpnmlv->lParam & DRIVER_LIST_CURRENT_DRIVER) {
|
|
StringId = IDS_DRIVER_CURR;
|
|
}
|
|
|
|
DigitalSignatureSignedId = (lpnmlv->lParam & DRIVER_LIST_SIGNED_DRIVER)
|
|
? IDS_DRIVER_IS_SIGNED
|
|
: IDS_DRIVER_NOT_SIGNED;
|
|
|
|
hIcon = LoadImage(hNewDev,
|
|
(lpnmlv->lParam & DRIVER_LIST_SIGNED_DRIVER)
|
|
? MAKEINTRESOURCE(IDI_SIGNED)
|
|
: MAKEINTRESOURCE(IDI_WARN),
|
|
IMAGE_ICON,
|
|
GetSystemMetrics(SM_CXSMICON),
|
|
GetSystemMetrics(SM_CYSMICON),
|
|
0
|
|
);
|
|
|
|
if (NewDevWiz->hfontTextNormal && NewDevWiz->hfontTextBold) {
|
|
SetWindowFont(GetDlgItem(hDlg, IDC_SIGNED_TEXT),
|
|
(lpnmlv->lParam & DRIVER_LIST_SIGNED_DRIVER)
|
|
? NewDevWiz->hfontTextNormal
|
|
: NewDevWiz->hfontTextBold,
|
|
TRUE
|
|
);
|
|
}
|
|
|
|
ShowWindow(GetDlgItem(hDlg, IDC_SIGNED_ICON), SW_SHOW);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_SIGNED_TEXT), SW_SHOW);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_SIGNED_LINK), SW_SHOW);
|
|
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
|
|
|
|
} else {
|
|
ShowWindow(GetDlgItem(hDlg, IDC_SIGNED_ICON), SW_HIDE);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_SIGNED_TEXT), SW_HIDE);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_SIGNED_LINK), SW_HIDE);
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK);
|
|
}
|
|
|
|
if (!StringId) {
|
|
SetDlgItemText(hDlg, IDC_NDW_TEXT, TEXT(""));
|
|
} else {
|
|
SetDlgText(hDlg, IDC_NDW_TEXT, StringId, StringId);
|
|
}
|
|
|
|
if (!DigitalSignatureSignedId) {
|
|
SetDlgItemText(hDlg, IDC_SIGNED_TEXT, TEXT(""));
|
|
} else {
|
|
SetDlgText(hDlg, IDC_SIGNED_TEXT, DigitalSignatureSignedId, DigitalSignatureSignedId);
|
|
}
|
|
|
|
if (hIcon) {
|
|
hIcon = (HICON)SendDlgItemMessage(hDlg,
|
|
IDC_SIGNED_ICON,
|
|
STM_SETICON,
|
|
(WPARAM)hIcon,
|
|
0L
|
|
);
|
|
}
|
|
|
|
if (hIcon) {
|
|
DestroyIcon(hIcon);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case NM_RETURN:
|
|
case NM_CLICK:
|
|
if((((LPNMHDR)lParam)->idFrom) == IDC_SIGNED_LINK) {
|
|
ShellExecute(hDlg,
|
|
TEXT("open"),
|
|
TEXT("HELPCTR.EXE"),
|
|
TEXT("HELPCTR.EXE -url hcp://services/subsite?node=TopLevelBucket_4/Hardware&topic=MS-ITS%3A%25HELP_LOCATION%25%5Csysdm.chm%3A%3A/logo_testing.htm"),
|
|
NULL,
|
|
SW_SHOWNORMAL
|
|
);
|
|
}
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
INT_PTR CALLBACK
|
|
UseCurrentDlgProc(
|
|
HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
PNEWDEVWIZ NewDevWiz = (PNEWDEVWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
|
|
switch (message) {
|
|
|
|
case WM_INITDIALOG: {
|
|
LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
|
|
NewDevWiz = (PNEWDEVWIZ)lppsp->lParam;
|
|
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)NewDevWiz);
|
|
|
|
if (NewDevWiz->hfontTextBigBold) {
|
|
|
|
SetWindowFont(GetDlgItem(hDlg, IDC_FINISH_MSG1), NewDevWiz->hfontTextBigBold, TRUE);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
|
|
switch (((NMHDR FAR *)lParam)->code) {
|
|
|
|
case PSN_SETACTIVE:
|
|
NewDevWiz->PrevPage = IDD_NEWDEVWIZ_USECURRENT_FINISH;
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_FINISH);
|
|
break;
|
|
|
|
case PSN_RESET:
|
|
break;
|
|
|
|
case PSN_WIZBACK:
|
|
NewDevWiz->CurrentDriverIsSelected = FALSE;
|
|
SetDlgMsgResult(hDlg, message, NewDevWiz->EnterFrom);
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
INT_PTR
|
|
InitNoDriversDlgProc(
|
|
HWND hDlg,
|
|
PNEWDEVWIZ NewDevWiz
|
|
)
|
|
{
|
|
if (NewDevWiz->hfontTextBigBold) {
|
|
SetWindowFont(GetDlgItem(hDlg, IDC_FINISH_MSG1), NewDevWiz->hfontTextBigBold, TRUE);
|
|
}
|
|
|
|
if (NDWTYPE_UPDATE == NewDevWiz->InstallType) {
|
|
ShowWindow(GetDlgItem(hDlg, IDC_FINISH_MSG3), SW_HIDE);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_HELPCENTER_ICON), SW_HIDE);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_HELPCENTER_TEXT), SW_HIDE);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_FINISH_PROMPT), SW_HIDE);
|
|
|
|
} else {
|
|
|
|
CheckDlgButton(hDlg, IDC_FINISH_PROMPT, BST_CHECKED);
|
|
|
|
//
|
|
// If this user has the policy set to not send the Hardware Id to Windows
|
|
// Update then don't put in the text about launching help center.
|
|
//
|
|
if (GetLogPnPIdPolicy() == FALSE) {
|
|
ShowWindow(GetDlgItem(hDlg, IDC_FINISH_MSG3), SW_HIDE);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_HELPCENTER_ICON), SW_HIDE);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_HELPCENTER_TEXT), SW_HIDE);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT_PTR CALLBACK
|
|
NoDriverDlgProc(
|
|
HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
PNEWDEVWIZ NewDevWiz = (PNEWDEVWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
HICON hicon;
|
|
|
|
switch (message) {
|
|
|
|
case WM_INITDIALOG: {
|
|
LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
|
|
NewDevWiz = (PNEWDEVWIZ)lppsp->lParam;
|
|
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)NewDevWiz);
|
|
|
|
InitNoDriversDlgProc(hDlg, NewDevWiz);
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
|
|
switch (((NMHDR FAR *)lParam)->code) {
|
|
|
|
case PSN_SETACTIVE:
|
|
NewDevWiz->PrevPage = IDD_NEWDEVWIZ_USECURRENT_FINISH;
|
|
|
|
//
|
|
// Set the Help Center icon next to the text
|
|
//
|
|
hicon = LoadImage(hNewDev,
|
|
MAKEINTRESOURCE(IDI_HELPCENTER),
|
|
IMAGE_ICON,
|
|
GetSystemMetrics(SM_CXSMICON),
|
|
GetSystemMetrics(SM_CYSMICON),
|
|
0
|
|
);
|
|
|
|
if (hicon) {
|
|
hicon = (HICON)SendDlgItemMessage(hDlg, IDC_HELPCENTER_ICON, STM_SETICON, (WPARAM)hicon, 0L);
|
|
}
|
|
|
|
if (hicon) {
|
|
DestroyIcon(hicon);
|
|
}
|
|
|
|
//
|
|
// Set the Info icon next to the text
|
|
//
|
|
hicon = LoadImage(hNewDev,
|
|
MAKEINTRESOURCE(IDI_INFO),
|
|
IMAGE_ICON,
|
|
GetSystemMetrics(SM_CXSMICON),
|
|
GetSystemMetrics(SM_CYSMICON),
|
|
0
|
|
);
|
|
|
|
if (hicon) {
|
|
hicon = (HICON)SendDlgItemMessage(hDlg, IDC_INFO_ICON, STM_SETICON, (WPARAM)hicon, 0L);
|
|
}
|
|
|
|
if (hicon) {
|
|
DestroyIcon(hicon);
|
|
}
|
|
|
|
if (NewDevWiz->InstallType == NDWTYPE_FOUNDNEW) {
|
|
SetTimer(hDlg, INSTALL_COMPLETE_CHECK_TIMERID, INSTALL_COMPLETE_CHECK_TIMEOUT, NULL);
|
|
}
|
|
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_FINISH);
|
|
break;
|
|
|
|
case PSN_RESET:
|
|
KillTimer(hDlg, INSTALL_COMPLETE_CHECK_TIMERID);
|
|
break;
|
|
|
|
case PSN_WIZFINISH:
|
|
KillTimer(hDlg, INSTALL_COMPLETE_CHECK_TIMERID);
|
|
|
|
if (IsDlgButtonChecked(hDlg, IDC_FINISH_PROMPT)) {
|
|
InstallNullDriver(hDlg,
|
|
NewDevWiz,
|
|
(NewDevWiz->Capabilities & CM_DEVCAP_RAWDEVICEOK)
|
|
? FALSE : TRUE
|
|
);
|
|
|
|
} else {
|
|
NewDevWiz->LastError = ERROR_CANCELLED;
|
|
}
|
|
|
|
//
|
|
// Set the BOOL that tells us to call CDM which will launch HelpCenter
|
|
// if we are in the Found New Hardware Wizard and if the user has the
|
|
// policy set to TRUE.
|
|
//
|
|
if ((NewDevWiz->InstallType == NDWTYPE_FOUNDNEW) &&
|
|
GetLogPnPIdPolicy()) {
|
|
|
|
NewDevWiz->CallHelpCenter = TRUE;
|
|
}
|
|
break;
|
|
|
|
case PSN_WIZBACK:
|
|
NewDevWiz->CurrentDriverIsSelected = FALSE;
|
|
SetDlgMsgResult(hDlg, message, NewDevWiz->EnterFrom);
|
|
KillTimer(hDlg, INSTALL_COMPLETE_CHECK_TIMERID);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
if (INSTALL_COMPLETE_CHECK_TIMERID == wParam) {
|
|
if (IsInstallComplete(NewDevWiz->hDeviceInfo, &NewDevWiz->DeviceInfoData)) {
|
|
PropSheet_PressButton(GetParent(hDlg), PSBTN_CANCEL);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|