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.
2024 lines
54 KiB
2024 lines
54 KiB
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#ifdef UNICODE
|
|
|
|
#define DRIVER_VALUE_ENTRY TEXT("Driver");
|
|
|
|
|
|
BOOL
|
|
IsServiceToBeDisabled(
|
|
IN PVOID NtCompatInfHandle,
|
|
IN LPTSTR ServiceName
|
|
)
|
|
{
|
|
PLIST_ENTRY Next;
|
|
PCOMPATIBILITY_DATA CompData;
|
|
BOOL serviceDisabled = FALSE;
|
|
|
|
//
|
|
// iterate through all compdata structures
|
|
//
|
|
Next = CompatibilityData.Flink;
|
|
if (Next) {
|
|
while ((ULONG_PTR)Next != (ULONG_PTR)&CompatibilityData) {
|
|
CompData = CONTAINING_RECORD(Next, COMPATIBILITY_DATA, ListEntry);
|
|
Next = CompData->ListEntry.Flink;
|
|
//
|
|
// now look for services that match our service name
|
|
//
|
|
if (CompData->Type == TEXT('s') && lstrcmpi (CompData->ServiceName, ServiceName) == 0) {
|
|
//
|
|
// make sure the service is marked to be disabled
|
|
//
|
|
if ((CompData->RegValDataSize == sizeof (DWORD)) &&
|
|
(*(PDWORD)CompData->RegValData == SERVICE_DISABLED)
|
|
) {
|
|
//
|
|
// we found it!
|
|
//
|
|
serviceDisabled = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return serviceDisabled;
|
|
}
|
|
|
|
|
|
BOOL
|
|
IsDriverCopyToBeSkipped(
|
|
IN PVOID NtCompatInfHandle,
|
|
IN LPTSTR ServiceName,
|
|
IN LPTSTR FilePath
|
|
)
|
|
{
|
|
LONG LineCount;
|
|
LONG i;
|
|
LPTSTR SectionName = TEXT("DriversToSkipCopy");
|
|
LPTSTR FileName;
|
|
BOOL DisableCopy;
|
|
|
|
if ((!NtCompatInfHandle) || (!FilePath)) {
|
|
MYASSERT(FALSE);
|
|
return TRUE;
|
|
}
|
|
|
|
FileName = _tcsrchr( FilePath, TEXT('\\') );
|
|
if (!FileName) {
|
|
FileName = FilePath;
|
|
}
|
|
else {
|
|
FileName++;
|
|
}
|
|
|
|
//
|
|
// Check if the driver is listed under [DriversToSkipCopy] in ntcompat.inf.
|
|
//
|
|
|
|
if( (LineCount = InfGetSectionLineCount( NtCompatInfHandle,
|
|
SectionName )) == -1 ) {
|
|
//
|
|
// section doesn't exist.
|
|
//
|
|
return( FALSE );
|
|
}
|
|
|
|
DisableCopy = FALSE;
|
|
for( i = 0; i < LineCount; i++ ) {
|
|
LPTSTR p;
|
|
|
|
p = (LPTSTR)InfGetFieldByIndex( NtCompatInfHandle,
|
|
SectionName,
|
|
i,
|
|
0 );
|
|
|
|
if( p && !lstrcmpi( p, FileName ) ) {
|
|
|
|
DisableCopy = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return( DisableCopy );
|
|
}
|
|
|
|
|
|
BOOL
|
|
LoadHwdbLib (
|
|
OUT HMODULE* HwdbLib,
|
|
OUT PHWDB_ENTRY_POINTS HwdbEntries
|
|
)
|
|
{
|
|
TCHAR pathSupportLib[MAX_PATH];
|
|
HMODULE hwdbLib;
|
|
DWORD rc;
|
|
|
|
if (!FindPathToWinnt32File (S_HWDB_DLL, pathSupportLib, MAX_PATH)) {
|
|
return FALSE;
|
|
}
|
|
|
|
hwdbLib = LoadLibraryEx (pathSupportLib, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
|
|
if (!hwdbLib) {
|
|
return FALSE;
|
|
}
|
|
HwdbEntries->HwdbInitialize = (PHWDBINITIALIZE) GetProcAddress (hwdbLib, S_HWDBAPI_HWDBINITIALIZE);
|
|
HwdbEntries->HwdbTerminate = (PHWDBTERMINATE) GetProcAddress (hwdbLib, S_HWDBAPI_HWDBTERMINATE);
|
|
HwdbEntries->HwdbOpen = (PHWDBOPEN) GetProcAddress (hwdbLib, S_HWDBAPI_HWDBOPEN);
|
|
HwdbEntries->HwdbClose = (PHWDBCLOSE) GetProcAddress (hwdbLib, S_HWDBAPI_HWDBCLOSE);
|
|
HwdbEntries->HwdbHasAnyDriver = (PHWDBHASANYDRIVER) GetProcAddress (hwdbLib, S_HWDBAPI_HWDBHASANYDRIVER);
|
|
|
|
if (!HwdbEntries->HwdbInitialize ||
|
|
!HwdbEntries->HwdbTerminate ||
|
|
!HwdbEntries->HwdbOpen ||
|
|
!HwdbEntries->HwdbClose ||
|
|
!HwdbEntries->HwdbHasAnyDriver
|
|
) {
|
|
ZeroMemory (HwdbEntries, sizeof (*HwdbEntries));
|
|
rc = GetLastError ();
|
|
FreeLibrary (hwdbLib);
|
|
SetLastError (rc);
|
|
return FALSE;
|
|
}
|
|
|
|
*HwdbLib = hwdbLib;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
pAnyPnpIdSupported (
|
|
IN PCTSTR PnpIDs
|
|
)
|
|
{
|
|
HMODULE hwdbLib;
|
|
HANDLE hwdbDatabase;
|
|
HWDB_ENTRY_POINTS hwdbEntries;
|
|
TCHAR hwdbPath[MAX_PATH];
|
|
BOOL unsupported;
|
|
BOOL b = TRUE;
|
|
|
|
if (!FindPathToWinnt32File (S_HWCOMP_DAT, hwdbPath, MAX_PATH)) {
|
|
DynUpdtDebugLog (Winnt32LogWarning, TEXT("%1 not found"), 0, S_HWCOMP_DAT);
|
|
return b;
|
|
}
|
|
|
|
if (!LoadHwdbLib (&hwdbLib, &hwdbEntries)) {
|
|
DebugLog (
|
|
Winnt32LogWarning,
|
|
TEXT("LoadHwdbLib failed (rc=%u)"),
|
|
0,
|
|
GetLastError ()
|
|
);
|
|
return b;
|
|
}
|
|
|
|
if (hwdbEntries.HwdbInitialize (NULL)) {
|
|
hwdbDatabase = hwdbEntries.HwdbOpen (hwdbPath);
|
|
if (hwdbDatabase) {
|
|
b = hwdbEntries.HwdbHasAnyDriver (hwdbDatabase, PnpIDs, &unsupported);
|
|
hwdbEntries.HwdbClose (hwdbDatabase);
|
|
}
|
|
hwdbEntries.HwdbTerminate ();
|
|
}
|
|
|
|
FreeLibrary (hwdbLib);
|
|
|
|
return b;
|
|
}
|
|
|
|
|
|
PTSTR
|
|
pGetDevicePnpIDs (
|
|
IN PCTSTR DeviceRegKey
|
|
)
|
|
{
|
|
LONG rc;
|
|
HKEY deviceKey;
|
|
DWORD type;
|
|
DWORD size1, size2;
|
|
PTSTR pnpIds;
|
|
PTSTR p = NULL;
|
|
|
|
rc = RegOpenKeyEx (
|
|
HKEY_LOCAL_MACHINE,
|
|
DeviceRegKey,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&deviceKey
|
|
);
|
|
if (rc != ERROR_SUCCESS) {
|
|
DebugLog (
|
|
Winnt32LogWarning,
|
|
TEXT("Failed to open device key %s (rc=%u)"),
|
|
0,
|
|
DeviceRegKey,
|
|
rc
|
|
);
|
|
return p;
|
|
}
|
|
|
|
__try {
|
|
size1 = 0;
|
|
rc = RegQueryValueEx (
|
|
deviceKey,
|
|
TEXT("HardwareID"),
|
|
NULL,
|
|
&type,
|
|
NULL,
|
|
&size1
|
|
);
|
|
if (rc == ERROR_SUCCESS) {
|
|
if (type != REG_MULTI_SZ && type != REG_BINARY) {
|
|
size1 = 0;
|
|
DebugLog (
|
|
Winnt32LogWarning,
|
|
TEXT("Unexpected type of %s of %s (type=%u)"),
|
|
0,
|
|
TEXT("HardwareID"),
|
|
DeviceRegKey,
|
|
type
|
|
);
|
|
}
|
|
} else {
|
|
DebugLog (
|
|
Winnt32LogWarning,
|
|
TEXT("Couldn't find value %s of %s (rc=%u)"),
|
|
0,
|
|
TEXT("HardwareID"),
|
|
DeviceRegKey,
|
|
rc
|
|
);
|
|
}
|
|
size2 = 0;
|
|
rc = RegQueryValueEx (
|
|
deviceKey,
|
|
TEXT("CompatibleIDs"),
|
|
NULL,
|
|
&type,
|
|
NULL,
|
|
&size2
|
|
);
|
|
if (rc == ERROR_SUCCESS) {
|
|
if (type != REG_MULTI_SZ && type != REG_BINARY) {
|
|
size2 = 0;
|
|
DebugLog (
|
|
Winnt32LogWarning,
|
|
TEXT("Unexpected type of %s of %s (type=%u)"),
|
|
0,
|
|
TEXT("CompatibleIDs"),
|
|
DeviceRegKey,
|
|
type
|
|
);
|
|
}
|
|
} else {
|
|
DebugLog (
|
|
Winnt32LogWarning,
|
|
TEXT("Couldn't find value %s of %s (rc=%u)"),
|
|
0,
|
|
TEXT("CompatibleIDs"),
|
|
DeviceRegKey,
|
|
rc
|
|
);
|
|
}
|
|
if (size1 + size2 < sizeof (TCHAR)) {
|
|
DebugLog (
|
|
Winnt32LogWarning,
|
|
TEXT("Couldn't get list of PnpIDs for %s"),
|
|
0,
|
|
DeviceRegKey
|
|
);
|
|
__leave;
|
|
}
|
|
pnpIds = MALLOC (size1 + size2);
|
|
if (!pnpIds) {
|
|
__leave;
|
|
}
|
|
pnpIds[0] = 0;
|
|
p = pnpIds;
|
|
|
|
if (size1 >= sizeof (TCHAR)) {
|
|
rc = RegQueryValueEx (
|
|
deviceKey,
|
|
TEXT("HardwareID"),
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)pnpIds,
|
|
&size1
|
|
);
|
|
if (rc == ERROR_SUCCESS) {
|
|
pnpIds += size1 / sizeof (TCHAR) - 1;
|
|
}
|
|
}
|
|
if (size2 >= sizeof (TCHAR)) {
|
|
rc = RegQueryValueEx (
|
|
deviceKey,
|
|
TEXT("CompatibleIDs"),
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)pnpIds,
|
|
&size2
|
|
);
|
|
}
|
|
}
|
|
__finally {
|
|
RegCloseKey (deviceKey);
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
BOOL
|
|
pAllServicedDevicesSupported (
|
|
IN HKEY ServiceKey
|
|
)
|
|
{
|
|
LONG rc;
|
|
HKEY enumSubKey;
|
|
DWORD nextInstance;
|
|
DWORD instance;
|
|
TCHAR buf[20];
|
|
DWORD type;
|
|
DWORD size;
|
|
PTSTR enumSuffixStr;
|
|
HKEY deviceKey;
|
|
PTSTR deviceKeyStr;
|
|
PTSTR pnpIds;
|
|
BOOL unsupported;
|
|
BOOL b = TRUE;
|
|
|
|
rc = RegOpenKeyEx (
|
|
ServiceKey,
|
|
TEXT("Enum"),
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&enumSubKey
|
|
);
|
|
if (rc != ERROR_SUCCESS) {
|
|
DebugLog (
|
|
Winnt32LogWarning,
|
|
TEXT("Failed to open Enum subkey (rc=%u)"),
|
|
0,
|
|
rc
|
|
);
|
|
return b;
|
|
}
|
|
|
|
__try {
|
|
size = sizeof (nextInstance);
|
|
rc = RegQueryValueEx (
|
|
enumSubKey,
|
|
TEXT("NextInstance"),
|
|
NULL,
|
|
&type,
|
|
(LPBYTE)&nextInstance,
|
|
&size
|
|
);
|
|
if (rc != ERROR_SUCCESS) {
|
|
DebugLog (
|
|
Winnt32LogWarning,
|
|
TEXT("Failed to open %s value (rc=%u)"),
|
|
0,
|
|
TEXT("NextInstance"),
|
|
rc
|
|
);
|
|
__leave;
|
|
}
|
|
if (type != REG_DWORD) {
|
|
DebugLog (
|
|
Winnt32LogWarning,
|
|
TEXT("Unexpected value type for %s (type=%u)"),
|
|
0,
|
|
TEXT("NextInstance"),
|
|
type
|
|
);
|
|
__leave;
|
|
}
|
|
|
|
for (instance = 0; b && instance < nextInstance; instance++) {
|
|
wsprintf (buf, TEXT("%lu"), instance);
|
|
rc = RegQueryValueEx (
|
|
enumSubKey,
|
|
buf,
|
|
NULL,
|
|
&type,
|
|
NULL,
|
|
&size
|
|
);
|
|
if (rc != ERROR_SUCCESS || type != REG_SZ) {
|
|
continue;
|
|
}
|
|
enumSuffixStr = MALLOC (size);
|
|
if (!enumSuffixStr) {
|
|
__leave;
|
|
}
|
|
rc = RegQueryValueEx (
|
|
enumSubKey,
|
|
buf,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)enumSuffixStr,
|
|
&size
|
|
);
|
|
if (rc == ERROR_SUCCESS) {
|
|
|
|
size = sizeof ("SYSTEM\\CurrentControlSet\\Enum") + lstrlen (enumSuffixStr) + 1;
|
|
deviceKeyStr = MALLOC (size * sizeof (TCHAR));
|
|
if (!deviceKeyStr) {
|
|
__leave;
|
|
}
|
|
|
|
BuildPathEx (deviceKeyStr, size, TEXT("SYSTEM\\CurrentControlSet\\Enum"), enumSuffixStr);
|
|
|
|
pnpIds = pGetDevicePnpIDs (deviceKeyStr);
|
|
|
|
FREE (deviceKeyStr);
|
|
|
|
if (!pAnyPnpIdSupported (pnpIds)) {
|
|
b = FALSE;
|
|
}
|
|
|
|
FREE (pnpIds);
|
|
}
|
|
|
|
FREE (enumSuffixStr);
|
|
}
|
|
}
|
|
__finally {
|
|
RegCloseKey (enumSubKey);
|
|
}
|
|
|
|
return b;
|
|
}
|
|
|
|
BOOL
|
|
IsInfInLayoutInf(
|
|
IN PCTSTR InfPath
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determine if an INF file is shiped in-box with the operating system.
|
|
This is acomplished by looking up the INF name in the [SourceDisksFiles]
|
|
section of layout.inf
|
|
|
|
Arguments:
|
|
|
|
InfPath - supplies name (may include path) of INF. No checking is done
|
|
to ensure INF lives in %windir%\Inf--this is caller's responsibility.
|
|
|
|
Return Value:
|
|
|
|
If TRUE, this is an in-box INF. If FALSE, it's not an in-box INF, this
|
|
could be an OEM<n>.INF or an inf illegaly copied into the INF directory.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL bInBoxInf = FALSE;
|
|
HINF hInf = INVALID_HANDLE_VALUE;
|
|
UINT SourceId;
|
|
PCTSTR infFileName;
|
|
|
|
if (SetupapiGetSourceFileLocation) {
|
|
|
|
hInf = SetupapiOpenInfFile(TEXT("layout.inf"), NULL, INF_STYLE_WIN4, NULL);
|
|
|
|
if (hInf != INVALID_HANDLE_VALUE) {
|
|
|
|
infFileName = _tcsrchr(InfPath, TEXT('\\') );
|
|
if (infFileName) {
|
|
infFileName++;
|
|
} else {
|
|
infFileName = InfPath;
|
|
}
|
|
|
|
if(SetupapiGetSourceFileLocation(hInf,
|
|
NULL,
|
|
infFileName,
|
|
&SourceId,
|
|
NULL,
|
|
0,
|
|
NULL)) {
|
|
bInBoxInf = TRUE;
|
|
}
|
|
|
|
SetupapiCloseInfFile(hInf);
|
|
}
|
|
}
|
|
|
|
return bInBoxInf;
|
|
}
|
|
|
|
BOOL
|
|
pIsOEMService (
|
|
IN PCTSTR ServiceKeyName,
|
|
OUT PTSTR OemInfPath, OPTIONAL
|
|
IN INT BufferSize OPTIONAL
|
|
)
|
|
{
|
|
ULONG BufferLen = 0;
|
|
PTSTR Buffer = NULL;
|
|
PTSTR p;
|
|
DEVNODE DevNode;
|
|
CONFIGRET cr;
|
|
HKEY hKey;
|
|
TCHAR InfPath[MAX_PATH];
|
|
DWORD dwType, dwSize;
|
|
BOOL IsOemService = FALSE;
|
|
|
|
//
|
|
// See how larger of a buffer we need to hold the list of device
|
|
// instance Ids for this service.
|
|
//
|
|
cr = CM_Get_Device_ID_List_Size(&BufferLen,
|
|
ServiceKeyName,
|
|
CM_GETIDLIST_FILTER_SERVICE);
|
|
|
|
if (cr != CR_SUCCESS) {
|
|
//
|
|
// Encountered an error so just bail out.
|
|
//
|
|
goto clean0;
|
|
}
|
|
|
|
if (BufferLen == 0) {
|
|
//
|
|
// No devices are using this service, so just bail out.
|
|
//
|
|
goto clean0;
|
|
}
|
|
|
|
Buffer = MALLOC(BufferLen*sizeof(TCHAR));
|
|
|
|
if (Buffer == NULL) {
|
|
goto clean0;
|
|
}
|
|
|
|
//
|
|
// Get the list of device instance Ids for this service.
|
|
//
|
|
cr = CM_Get_Device_ID_List(ServiceKeyName,
|
|
Buffer,
|
|
BufferLen,
|
|
CM_GETIDLIST_FILTER_SERVICE | CM_GETIDLIST_DONOTGENERATE);
|
|
|
|
if (cr != CR_SUCCESS) {
|
|
//
|
|
// failed to get the list of devices for this service.
|
|
//
|
|
goto clean0;
|
|
}
|
|
|
|
//
|
|
// Enumerate through the list of devices using this service.
|
|
//
|
|
for (p = Buffer; !IsOemService && *p; p += (lstrlen(p) + 1)) {
|
|
|
|
//
|
|
// Get a DevNode from the device instance Id.
|
|
//
|
|
cr = CM_Locate_DevNode(&DevNode, p, 0);
|
|
|
|
if (cr != CR_SUCCESS) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Open the device's SOFTWARE key so we can get it's INF path.
|
|
//
|
|
cr = CM_Open_DevNode_Key(DevNode,
|
|
KEY_READ,
|
|
0,
|
|
RegDisposition_OpenExisting,
|
|
&hKey,
|
|
CM_REGISTRY_SOFTWARE);
|
|
|
|
if (cr != CR_SUCCESS) {
|
|
//
|
|
// Software key doesn't exist?
|
|
//
|
|
continue;
|
|
}
|
|
|
|
dwType = REG_SZ;
|
|
dwSize = sizeof(InfPath);
|
|
if (RegQueryValueEx(hKey,
|
|
REGSTR_VAL_INFPATH,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)InfPath,
|
|
&dwSize) != ERROR_SUCCESS) {
|
|
//
|
|
// If there is no InfPath in the SOFTWARE key then we don't know
|
|
// what INF this device is using.
|
|
//
|
|
RegCloseKey(hKey);
|
|
continue;
|
|
}
|
|
|
|
if (!IsInfInLayoutInf(InfPath)) {
|
|
|
|
IsOemService = TRUE;
|
|
|
|
if (OemInfPath) {
|
|
StringCchCopy (OemInfPath, BufferSize, InfPath);
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
clean0:
|
|
if (Buffer) {
|
|
FREE(Buffer);
|
|
}
|
|
|
|
return IsOemService;
|
|
}
|
|
|
|
|
|
BOOL
|
|
IsDeviceSupported(
|
|
IN PVOID TxtsetupSifHandle,
|
|
IN HKEY ServiceKey,
|
|
IN LPTSTR ServiceKeyName,
|
|
OUT LPTSTR FileName,
|
|
IN INT CchFileName
|
|
)
|
|
{
|
|
ULONG Error;
|
|
ULONG Type;
|
|
BYTE Buffer[ (MAX_PATH + 1)*sizeof(TCHAR) ];
|
|
PBYTE Data;
|
|
ULONG cbData;
|
|
BOOL b = TRUE;
|
|
LPTSTR DriverPath;
|
|
LPTSTR DriverName;
|
|
LONG LineCount;
|
|
LONG i;
|
|
BOOL DeviceSupported;
|
|
|
|
Data = Buffer;
|
|
cbData = sizeof( Buffer );
|
|
Error = RegQueryValueEx( ServiceKey,
|
|
TEXT("ImagePath"),
|
|
NULL,
|
|
&Type,
|
|
Data,
|
|
&cbData );
|
|
|
|
if( (Error == ERROR_PATH_NOT_FOUND) ||
|
|
(Error == ERROR_FILE_NOT_FOUND) ) {
|
|
//
|
|
// ImagePath does not exist.
|
|
// In this case the driver name is <service name>.sys
|
|
//
|
|
StringCbCopy((PTSTR)Buffer, sizeof(Buffer), ServiceKeyName );
|
|
StringCbCat((PTSTR)Buffer, sizeof(Buffer), TEXT(".sys") );
|
|
Error = ERROR_SUCCESS;
|
|
}
|
|
|
|
if( Error == ERROR_MORE_DATA ) {
|
|
Data = (PBYTE)MALLOC( cbData );
|
|
if( Data == NULL ) {
|
|
//
|
|
// We failed the malloc. Just assume the device
|
|
// isn't supported.
|
|
//
|
|
return( FALSE );
|
|
}
|
|
|
|
Error = RegQueryValueEx( ServiceKey,
|
|
TEXT("ImagePath"),
|
|
NULL,
|
|
&Type,
|
|
Data,
|
|
&cbData );
|
|
}
|
|
|
|
if( Error != ERROR_SUCCESS ) {
|
|
//
|
|
// We can' retrieve the drivers information.
|
|
// Assume that the device is supported
|
|
//
|
|
if( Data != Buffer ) {
|
|
FREE( Data );
|
|
}
|
|
return( TRUE );
|
|
}
|
|
|
|
DriverPath = (LPTSTR)Data;
|
|
|
|
DriverName = _tcsrchr( DriverPath, TEXT('\\') );
|
|
if( DriverName != NULL ) {
|
|
DriverName++;
|
|
} else {
|
|
DriverName = DriverPath;
|
|
}
|
|
|
|
//
|
|
// Search for the driver name on the following sections of txtsetup.sif:
|
|
// [SCSI.load]
|
|
//
|
|
|
|
if( (LineCount = InfGetSectionLineCount( TxtsetupSifHandle,
|
|
TEXT("SCSI.load") )) == -1 ) {
|
|
//
|
|
// We can't retrieve the drivers information.
|
|
// Assume that the device is supported
|
|
//
|
|
if( Data != Buffer ) {
|
|
FREE( Data );
|
|
}
|
|
return( TRUE );
|
|
}
|
|
|
|
DeviceSupported = FALSE;
|
|
for( i = 0; i < LineCount; i++ ) {
|
|
LPTSTR p;
|
|
|
|
p = (LPTSTR)InfGetFieldByIndex( TxtsetupSifHandle,
|
|
TEXT("SCSI.load"),
|
|
i,
|
|
0 );
|
|
if( p == NULL ) {
|
|
continue;
|
|
}
|
|
if( !lstrcmpi( p, DriverName ) ) {
|
|
DeviceSupported = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// NTBUG9: 505624
|
|
// verify if there is inbox support for ALL devices
|
|
// currently supported by this driver
|
|
// If there's any that doesn't have support,
|
|
// then the OEM driver must be migrated
|
|
//
|
|
if (DeviceSupported) {
|
|
|
|
if (pIsOEMService (ServiceKeyName, NULL, 0)) {
|
|
|
|
if (!pAllServicedDevicesSupported (ServiceKey)) {
|
|
DeviceSupported = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if defined(_AMD64_) || defined(_X86_)
|
|
|
|
//
|
|
// one more thing: check if this device is supplied by OEMs via answer file (NTBUG9: 306041)
|
|
//
|
|
if (!DeviceSupported) {
|
|
POEM_BOOT_FILE p;
|
|
for (p = OemBootFiles; p; p = p->Next) {
|
|
if (!lstrcmpi (p->Filename, DriverName)) {
|
|
DeviceSupported = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if( !DeviceSupported ) {
|
|
LPTSTR q;
|
|
|
|
CharLower( DriverPath );
|
|
q = _tcsstr( DriverPath, TEXT("system32") );
|
|
|
|
//Note, since this entire function (IsDeviceSupported) is only called in
|
|
//one place, we assume the FileName pointer points to a buffer of size MAX_PATH
|
|
if( q == NULL ) {
|
|
StringCchCopy( FileName, CchFileName, TEXT("system32\\drivers\\") );
|
|
StringCchCat( FileName, CchFileName, DriverName );
|
|
} else {
|
|
StringCchCopy( FileName, CchFileName, q );
|
|
}
|
|
}
|
|
if( Data != Buffer ) {
|
|
FREE( Data );
|
|
}
|
|
return( DeviceSupported );
|
|
}
|
|
|
|
VOID
|
|
FreeHardwareIdList(
|
|
IN PUNSUPORTED_PNP_HARDWARE_ID HardwareIdList
|
|
)
|
|
{
|
|
PUNSUPORTED_PNP_HARDWARE_ID p, q;
|
|
|
|
p = HardwareIdList;
|
|
while( p != NULL ) {
|
|
FREE( p->Id );
|
|
FREE( p->Service );
|
|
FREE( p->ClassGuid );
|
|
q = p->Next;
|
|
FREE( p );
|
|
p = q;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
FreeFileInfoList(
|
|
IN PUNSUPORTED_DRIVER_FILE_INFO FileInfoList
|
|
)
|
|
{
|
|
PUNSUPORTED_DRIVER_FILE_INFO p, q;
|
|
|
|
p = FileInfoList;
|
|
while( p != NULL ) {
|
|
FREE( p->FileName );
|
|
FREE( p->TargetDirectory );
|
|
q = p->Next;
|
|
FREE( p );
|
|
p = q;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
FreeInstallInfoList(
|
|
IN PUNSUPORTED_DRIVER_INSTALL_INFO InstallInfoList
|
|
)
|
|
{
|
|
PUNSUPORTED_DRIVER_INSTALL_INFO p, q;
|
|
|
|
p = InstallInfoList;
|
|
while( p != NULL ) {
|
|
FREE( p->InfRelPath );
|
|
FREE( p->InfFileName );
|
|
FREE( p->InfOriginalFileName );
|
|
if (p->CatalogRelPath) {
|
|
FREE(p->CatalogRelPath);
|
|
}
|
|
if (p->CatalogFileName) {
|
|
FREE(p->CatalogFileName);
|
|
}
|
|
if (p->CatalogOriginalFileName) {
|
|
FREE(p->CatalogOriginalFileName);
|
|
}
|
|
q = p->Next;
|
|
FREE( p );
|
|
p = q;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
FreeRegistryInfoList(
|
|
IN PUNSUPORTED_DRIVER_REGKEY_INFO RegistryInfoList
|
|
)
|
|
{
|
|
PUNSUPORTED_DRIVER_REGKEY_INFO p, q;
|
|
|
|
p = RegistryInfoList;
|
|
while( p != NULL ) {
|
|
FREE( p->KeyPath );
|
|
q = p->Next;
|
|
FREE( p );
|
|
p = q;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
BuildHardwareIdInfo(
|
|
IN LPTSTR ServiceName,
|
|
OUT PUNSUPORTED_PNP_HARDWARE_ID* HardwareIdList
|
|
)
|
|
{
|
|
ULONG BufferLen;
|
|
DEVNODE DevNode;
|
|
PTSTR Buffer, Service, Id, HwId, DevId;
|
|
PBYTE Value;
|
|
ULONG ValueSize;
|
|
PUNSUPORTED_PNP_HARDWARE_ID TempList, Entry;
|
|
BOOL Result;
|
|
DWORD Type;
|
|
|
|
if (CM_Get_Device_ID_List_Size(&BufferLen,
|
|
ServiceName,
|
|
CM_GETIDLIST_FILTER_SERVICE
|
|
) != CR_SUCCESS ||
|
|
(BufferLen == 0)) {
|
|
|
|
return ( FALSE );
|
|
}
|
|
|
|
Result = TRUE;
|
|
Value = NULL;
|
|
TempList = NULL;
|
|
Buffer = MALLOC(BufferLen * sizeof(TCHAR));
|
|
if (Buffer == NULL) {
|
|
|
|
Result = FALSE;
|
|
goto Clean;
|
|
}
|
|
ValueSize = REGSTR_VAL_MAX_HCID_LEN * sizeof(TCHAR);
|
|
Value = MALLOC(ValueSize);
|
|
if (Value == NULL) {
|
|
|
|
Result = FALSE;
|
|
goto Clean;
|
|
}
|
|
if (CM_Get_Device_ID_List(ServiceName,
|
|
Buffer,
|
|
BufferLen,
|
|
CM_GETIDLIST_FILTER_SERVICE | CM_GETIDLIST_DONOTGENERATE
|
|
) != CR_SUCCESS) {
|
|
|
|
Result = FALSE;
|
|
goto Clean;
|
|
}
|
|
|
|
for (DevId = Buffer; *DevId; DevId += lstrlen(DevId) + 1) {
|
|
|
|
if (CM_Locate_DevNode(&DevNode, DevId, 0) == CR_SUCCESS) {
|
|
|
|
ValueSize = REGSTR_VAL_MAX_HCID_LEN * sizeof(TCHAR);
|
|
if (CM_Get_DevNode_Registry_Property(DevNode, CM_DRP_HARDWAREID, &Type, Value, &ValueSize, 0) == CR_SUCCESS &&
|
|
Type == REG_MULTI_SZ) {
|
|
|
|
for( HwId = (PTSTR)Value;
|
|
( (ULONG_PTR)HwId < (ULONG_PTR)(Value + ValueSize) ) && ( lstrlen( HwId ) );
|
|
HwId += lstrlen( HwId ) + 1 ) {
|
|
|
|
Entry = MALLOC( sizeof( UNSUPORTED_PNP_HARDWARE_ID ) );
|
|
Id = DupString( HwId );
|
|
Service = DupString( ServiceName );
|
|
|
|
if( (Entry == NULL) || (Id == NULL) || (Service == NULL) ) {
|
|
|
|
if( Entry != NULL ) {
|
|
FREE( Entry );
|
|
}
|
|
if( Id != NULL ) {
|
|
FREE( Id );
|
|
}
|
|
if( Service != NULL ) {
|
|
FREE( Service );
|
|
}
|
|
Result = FALSE;
|
|
goto Clean;
|
|
}
|
|
//
|
|
// Add the new entry to the front of the list.
|
|
//
|
|
Entry->Id = Id;
|
|
Entry->Service = Service;
|
|
Entry->ClassGuid = NULL;
|
|
Entry->Next = TempList;
|
|
TempList = Entry;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Clean:
|
|
|
|
if ( Buffer ) {
|
|
|
|
FREE( Buffer );
|
|
}
|
|
if ( Value ) {
|
|
|
|
FREE( Value );
|
|
}
|
|
if (Result == TRUE) {
|
|
|
|
*HardwareIdList = TempList;
|
|
} else if ( TempList ) {
|
|
|
|
FreeHardwareIdList( TempList );
|
|
}
|
|
|
|
return ( Result );
|
|
}
|
|
|
|
|
|
BOOL
|
|
BuildDriverFileInformation(
|
|
IN LPTSTR FilePath,
|
|
OUT PUNSUPORTED_DRIVER_FILE_INFO* FileInfo
|
|
)
|
|
|
|
{
|
|
TCHAR FullPath[ MAX_PATH + 1 ];
|
|
LPTSTR p, q, r;
|
|
PUNSUPORTED_DRIVER_FILE_INFO TempFileInfo = NULL;
|
|
|
|
*FileInfo = NULL;
|
|
StringCchCopy( FullPath, ARRAYSIZE(FullPath), FilePath );
|
|
p = _tcsrchr( FullPath, TEXT('\\') );
|
|
if(!p)
|
|
return FALSE;
|
|
*p = TEXT('\0');
|
|
p++;
|
|
q = DupString( FullPath );
|
|
r = DupString( p );
|
|
TempFileInfo = MALLOC( sizeof( UNSUPORTED_DRIVER_FILE_INFO ) );
|
|
|
|
if( ( q == NULL ) || ( r == NULL ) || ( TempFileInfo == NULL ) ) {
|
|
goto clean0;
|
|
}
|
|
|
|
TempFileInfo->Next = NULL;
|
|
TempFileInfo->FileName = r;
|
|
TempFileInfo->TargetDirectory = q;
|
|
*FileInfo = TempFileInfo;
|
|
return( TRUE );
|
|
|
|
clean0:
|
|
if( q != NULL ) {
|
|
FREE( q );
|
|
}
|
|
if( r != NULL ) {
|
|
FREE( r );
|
|
}
|
|
if( TempFileInfo != NULL ) {
|
|
FREE( TempFileInfo );
|
|
}
|
|
return( FALSE );
|
|
}
|
|
|
|
BOOL
|
|
pDoesCatalogExist (
|
|
IN PTSTR CatalogPath,
|
|
IN PTSTR CatName
|
|
)
|
|
{
|
|
TCHAR path[MAX_PATH];
|
|
|
|
return BuildPath(path, CatalogPath, CatName) && FileExists (path, NULL);
|
|
}
|
|
|
|
BOOL
|
|
BuildDriverInstallInformation(
|
|
IN LPTSTR ServiceKeyName,
|
|
OUT PUNSUPORTED_DRIVER_INSTALL_INFO* InstallInfo
|
|
)
|
|
{
|
|
TCHAR infName[MAX_PATH];
|
|
TCHAR catName[MAX_PATH];
|
|
TCHAR infPath[MAX_PATH];
|
|
TCHAR catalogPath[MAX_PATH];
|
|
LPTSTR p, q, r, s, t, u;
|
|
PUNSUPORTED_DRIVER_INSTALL_INFO TempInstallInfo = NULL;
|
|
DWORD size;
|
|
PSP_INF_INFORMATION info;
|
|
SP_ORIGINAL_FILE_INFO ofi;
|
|
BOOL b = FALSE;
|
|
|
|
if (BUILDNUM() >= NT51) {
|
|
return TRUE;
|
|
}
|
|
if (!pIsOEMService (ServiceKeyName, infName, ARRAYSIZE(infName))) {
|
|
return TRUE;
|
|
}
|
|
|
|
if (!SetupapiGetInfInformation (infName, INFINFO_DEFAULT_SEARCH, NULL, 0, &size)) {
|
|
return FALSE;
|
|
}
|
|
info = (PSP_INF_INFORMATION) MALLOC(size);
|
|
if (!info) {
|
|
return FALSE;
|
|
}
|
|
|
|
__try {
|
|
if (!SetupapiGetInfInformation (infName, INFINFO_DEFAULT_SEARCH, info, size, NULL)) {
|
|
__leave;
|
|
}
|
|
if (!SetupapiQueryInfFileInformation (info, 0, infPath, ARRAYSIZE(infPath), NULL)) {
|
|
__leave;
|
|
}
|
|
//
|
|
// the INF is supposed to be under %windir%
|
|
// reuse a buffer
|
|
//
|
|
size = MyGetWindowsDirectory (catalogPath, ARRAYSIZE(catalogPath));
|
|
if (!size || size >= ARRAYSIZE(catalogPath)) {
|
|
__leave;
|
|
}
|
|
if (_tcsnicmp (infPath, catalogPath, size) || infPath[size] != TEXT('\\')) {
|
|
__leave;
|
|
}
|
|
//
|
|
// then cut the %windir% part and the filename
|
|
//
|
|
p = _tcsrchr (infPath, TEXT('\\'));
|
|
if (!p) {
|
|
__leave;
|
|
}
|
|
*p = 0;
|
|
MoveMemory (infPath, infPath + size + 1, (p + 1 - (infPath + size + 1)) * sizeof (TCHAR));
|
|
|
|
ofi.cbSize = sizeof(ofi);
|
|
if (!SetupapiQueryInfOriginalFileInformation ||
|
|
!SetupapiQueryInfOriginalFileInformation (info, 0, NULL, &ofi)) {
|
|
//
|
|
// use the current INF name
|
|
//
|
|
StringCchCopy (ofi.OriginalInfName, ARRAYSIZE(ofi.OriginalInfName), infName);
|
|
ofi.OriginalCatalogName[0] = 0;
|
|
}
|
|
|
|
b = TRUE;
|
|
}
|
|
__finally {
|
|
FREE(info);
|
|
}
|
|
|
|
if (!b) {
|
|
return b;
|
|
}
|
|
|
|
if (ofi.OriginalCatalogName[0]) {
|
|
//
|
|
// get actual catalog name
|
|
//
|
|
lstrcpy (catName, infName);
|
|
p = _tcsrchr (catName, TEXT('.'));
|
|
if (!p) {
|
|
p = _tcsrchr (catName, 0);
|
|
}
|
|
if (FAILED(StringCchCopy (p, catName + ARRAYSIZE(catName) - p, TEXT(".cat")))) {
|
|
return FALSE;
|
|
}
|
|
//
|
|
// get actual catalog location under %systemroot%
|
|
//
|
|
lstrcpy (catalogPath, TEXT("system32\\CatRoot\\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}"));
|
|
//
|
|
// check if the catalog actually exists
|
|
//
|
|
if (!pDoesCatalogExist (catalogPath, catName)) {
|
|
//
|
|
// just ignore it; driver will be treated as unsigned
|
|
//
|
|
ofi.OriginalCatalogName[0] = 0;
|
|
}
|
|
}
|
|
|
|
if (!ofi.OriginalCatalogName[0]) {
|
|
catName[0] = 0;
|
|
catalogPath[0] = 0;
|
|
}
|
|
|
|
//
|
|
// add the OEM .INF and .CAT files to the list
|
|
//
|
|
|
|
*InstallInfo = NULL;
|
|
p = DupString(infPath);
|
|
q = DupString(infName);
|
|
r = DupString(ofi.OriginalInfName);
|
|
s = catalogPath[0] ? DupString(catalogPath) : NULL;
|
|
t = catName[0] ? DupString(catName) : NULL;
|
|
u = ofi.OriginalCatalogName[0] ? DupString(ofi.OriginalCatalogName) : NULL;
|
|
|
|
TempInstallInfo = MALLOC( sizeof( UNSUPORTED_DRIVER_INSTALL_INFO ) );
|
|
|
|
if(!(p && q && r &&
|
|
(!catalogPath[0] || s) && (!catName[0] || t) && (!ofi.OriginalCatalogName[0] || u) && TempInstallInfo)) {
|
|
goto clean0;
|
|
}
|
|
|
|
TempInstallInfo->Next = NULL;
|
|
TempInstallInfo->InfRelPath = p;
|
|
TempInstallInfo->InfFileName = q;
|
|
TempInstallInfo->InfOriginalFileName = r;
|
|
TempInstallInfo->CatalogRelPath = s;
|
|
TempInstallInfo->CatalogFileName = t;
|
|
TempInstallInfo->CatalogOriginalFileName = u;
|
|
*InstallInfo = TempInstallInfo;
|
|
return( TRUE );
|
|
|
|
clean0:
|
|
if( q != NULL ) {
|
|
FREE( q );
|
|
}
|
|
if( r != NULL ) {
|
|
FREE( r );
|
|
}
|
|
if( s != NULL ) {
|
|
FREE( s );
|
|
}
|
|
if( t != NULL ) {
|
|
FREE( t );
|
|
}
|
|
if( u != NULL ) {
|
|
FREE( u );
|
|
}
|
|
if( TempInstallInfo != NULL ) {
|
|
FREE( TempInstallInfo );
|
|
}
|
|
return( FALSE );
|
|
}
|
|
|
|
BOOL
|
|
BuildDriverRegistryInformation(
|
|
IN LPTSTR ServiceName,
|
|
OUT PUNSUPORTED_DRIVER_REGKEY_INFO* RegInfo
|
|
)
|
|
|
|
{
|
|
TCHAR KeyPath[ MAX_PATH + 1 ];
|
|
LPTSTR p=NULL;
|
|
PUNSUPORTED_DRIVER_REGKEY_INFO TempRegInfo = NULL;
|
|
|
|
*RegInfo = NULL;
|
|
StringCchCopy( KeyPath, ARRAYSIZE(KeyPath), TEXT( "SYSTEM\\CurrentControlSet\\Services\\" ) );
|
|
if (FAILED(StringCchCat( KeyPath, ARRAYSIZE(KeyPath), ServiceName ))) {
|
|
goto clean0;
|
|
}
|
|
|
|
p = DupString( KeyPath );
|
|
TempRegInfo = MALLOC( sizeof( UNSUPORTED_DRIVER_REGKEY_INFO ) );
|
|
|
|
if( ( p == NULL ) || ( TempRegInfo == NULL ) ) {
|
|
goto clean0;
|
|
}
|
|
|
|
TempRegInfo->Next = NULL;
|
|
TempRegInfo->PredefinedKey = HKEY_LOCAL_MACHINE;
|
|
TempRegInfo->KeyPath = p;
|
|
TempRegInfo->MigrateVolatileKeys = FALSE;
|
|
*RegInfo = TempRegInfo;
|
|
return( TRUE );
|
|
|
|
clean0:
|
|
if( p != NULL ) {
|
|
FREE( p );
|
|
}
|
|
if( TempRegInfo != NULL ) {
|
|
FREE( TempRegInfo );
|
|
}
|
|
return( FALSE );
|
|
}
|
|
|
|
VOID
|
|
FreeDriverInformationList(
|
|
IN OUT PUNSUPORTED_DRIVER_INFO* DriverInfo
|
|
)
|
|
{
|
|
while( *DriverInfo != NULL ) {
|
|
PUNSUPORTED_DRIVER_INFO p;
|
|
|
|
p = *DriverInfo;
|
|
*DriverInfo = p->Next;
|
|
|
|
if( p->DriverId != NULL ) {
|
|
FREE( p->DriverId );
|
|
}
|
|
|
|
if( p->KeyList != NULL ) {
|
|
FreeRegistryInfoList( p->KeyList );
|
|
}
|
|
|
|
if( p->FileList != NULL ) {
|
|
FreeFileInfoList( p->FileList );
|
|
}
|
|
|
|
if (p->InstallList) {
|
|
FreeInstallInfoList (p->InstallList);
|
|
}
|
|
|
|
if( p-> HardwareIdsList != NULL ) {
|
|
FreeHardwareIdList( p-> HardwareIdsList );
|
|
}
|
|
FREE( p );
|
|
}
|
|
*DriverInfo = NULL;
|
|
}
|
|
|
|
|
|
BOOL
|
|
BuildDriverInformation(
|
|
IN HKEY ServiceKey,
|
|
IN LPTSTR ServiceName,
|
|
IN LPTSTR FilePath,
|
|
OUT PUNSUPORTED_DRIVER_INFO* DriverInfo
|
|
)
|
|
{
|
|
ULONG Error;
|
|
BOOL b1, b2, b3, b4;
|
|
|
|
PUNSUPORTED_PNP_HARDWARE_ID TempIdInfo = NULL;
|
|
PUNSUPORTED_DRIVER_INFO TempFiltersInfo = NULL;
|
|
PUNSUPORTED_DRIVER_FILE_INFO TempFileInfo = NULL;
|
|
PUNSUPORTED_DRIVER_INSTALL_INFO TempInstallInfo = NULL;
|
|
PUNSUPORTED_DRIVER_REGKEY_INFO TempRegInfo = NULL;
|
|
PUNSUPORTED_DRIVER_INFO TempDriverInfo = NULL;
|
|
|
|
*DriverInfo = NULL;
|
|
//
|
|
// Get hardware id info
|
|
//
|
|
b1 = BuildHardwareIdInfo( ServiceName,
|
|
&TempIdInfo );
|
|
|
|
//
|
|
// Then get the file information
|
|
//
|
|
b2 = BuildDriverFileInformation( FilePath,
|
|
&TempFileInfo );
|
|
|
|
//
|
|
// Then get the install (INF&CAT) information
|
|
//
|
|
b3 = BuildDriverInstallInformation(ServiceName,
|
|
&TempInstallInfo );
|
|
|
|
//
|
|
// Then get the registry information
|
|
//
|
|
b4 = BuildDriverRegistryInformation( ServiceName,
|
|
&TempRegInfo );
|
|
|
|
if( !b1 || !b2 || !b3 || !b4) {
|
|
goto cleanup1;
|
|
}
|
|
|
|
TempDriverInfo = MALLOC( sizeof( UNSUPORTED_DRIVER_INFO ) );
|
|
if( TempDriverInfo == NULL ) {
|
|
goto cleanup1;
|
|
}
|
|
|
|
TempDriverInfo->Next = NULL;
|
|
TempDriverInfo->DriverId = DupString( ServiceName );
|
|
TempDriverInfo->KeyList = TempRegInfo;
|
|
TempDriverInfo->FileList = TempFileInfo;
|
|
TempDriverInfo->InstallList = TempInstallInfo;
|
|
TempDriverInfo->HardwareIdsList = TempIdInfo;
|
|
|
|
|
|
TempDriverInfo->Next = *DriverInfo;
|
|
*DriverInfo = TempDriverInfo;
|
|
return( TRUE );
|
|
|
|
cleanup1:
|
|
|
|
if( TempIdInfo != NULL ) {
|
|
FreeHardwareIdList( TempIdInfo );
|
|
}
|
|
|
|
if( TempFileInfo != NULL ) {
|
|
FreeFileInfoList( TempFileInfo );
|
|
}
|
|
|
|
if( TempInstallInfo != NULL ) {
|
|
FreeInstallInfoList( TempInstallInfo );
|
|
}
|
|
|
|
if( TempRegInfo != NULL ) {
|
|
FreeRegistryInfoList( TempRegInfo );
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
BOOL
|
|
BuildUnsupportedDriverList(
|
|
IN PVOID TxtsetupSifHandle,
|
|
OUT PUNSUPORTED_DRIVER_INFO* DriverList
|
|
)
|
|
|
|
{
|
|
ULONG Error;
|
|
HKEY ScsiKey;
|
|
ULONG SubKeys;
|
|
ULONG i;
|
|
LPTSTR szScsiPath = TEXT("HARDWARE\\DEVICEMAP\\Scsi");
|
|
|
|
|
|
*DriverList = NULL;
|
|
|
|
//
|
|
// Find out if there is a SCSI miniport driver on this machine.
|
|
//
|
|
|
|
Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
szScsiPath,
|
|
0,
|
|
KEY_READ,
|
|
&ScsiKey );
|
|
if( Error != ERROR_SUCCESS ) {
|
|
//
|
|
// Nothing to migrate
|
|
//
|
|
return( TRUE );
|
|
}
|
|
|
|
//
|
|
// Find out the number of subkeys under HKLM\HARDWARE\DEVICEMAP\Scsi.
|
|
//
|
|
|
|
Error = RegQueryInfoKey ( ScsiKey,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&SubKeys,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL );
|
|
|
|
if( (Error != ERROR_SUCCESS) || (SubKeys == 0) ) {
|
|
//
|
|
// If we can't determine the number of subkeys, or if there is no
|
|
// subkey, then there is nothing to migrate, and we assume that all
|
|
// SCSI drivers are supported on NT.
|
|
//
|
|
RegCloseKey( ScsiKey );
|
|
return( TRUE );
|
|
}
|
|
|
|
//
|
|
// Each subkey of HKLM\HARDWARE\DEVICEMAP\Scsi points to a service that controls
|
|
// a SCSI device. We check each one of them to find out the ones that are controlled
|
|
// by a driver that is not on the NT product.
|
|
//
|
|
for( i = 0; i < SubKeys; i++ ) {
|
|
TCHAR SubKeyName[ MAX_PATH + 1 ];
|
|
TCHAR ServiceKeyPath[ MAX_PATH + 1 ];
|
|
ULONG Length;
|
|
FILETIME LastWriteTime;
|
|
HKEY Key;
|
|
BYTE Data[ 512 ];
|
|
ULONG DataSize;
|
|
ULONG Type;
|
|
PUNSUPORTED_DRIVER_INFO DriverInfo, p;
|
|
BOOL DeviceAlreadyFound;
|
|
TCHAR FilePath[ MAX_PATH + 1 ];
|
|
|
|
Length = sizeof( SubKeyName ) / sizeof( TCHAR );
|
|
Error = RegEnumKeyEx( ScsiKey,
|
|
i,
|
|
SubKeyName,
|
|
&Length,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&LastWriteTime );
|
|
|
|
if( Error != ERROR_SUCCESS ) {
|
|
//
|
|
// Ignore this device and assume it is supported.
|
|
//
|
|
continue;
|
|
}
|
|
|
|
Error = RegOpenKeyEx( ScsiKey,
|
|
SubKeyName,
|
|
0,
|
|
KEY_READ,
|
|
&Key );
|
|
if( Error != ERROR_SUCCESS ) {
|
|
//
|
|
// Ignore this device and assume it is supported.
|
|
//
|
|
continue;
|
|
}
|
|
|
|
DataSize = sizeof( Data );
|
|
Error = RegQueryValueEx( Key,
|
|
TEXT("Driver"),
|
|
NULL,
|
|
&Type,
|
|
Data,
|
|
&DataSize );
|
|
|
|
if( Error != ERROR_SUCCESS ) {
|
|
//
|
|
// Ignore this device and assume it is supported.
|
|
//
|
|
RegCloseKey( Key );
|
|
continue;
|
|
}
|
|
RegCloseKey( Key );
|
|
|
|
//
|
|
// Find out if this device is supported on NT 5.0
|
|
//
|
|
StringCchCopy( ServiceKeyPath, ARRAYSIZE(ServiceKeyPath), TEXT("SYSTEM\\CurrentControlSet\\Services\\" ) );
|
|
|
|
if (FAILED(StringCchCat( ServiceKeyPath, ARRAYSIZE(ServiceKeyPath), (LPTSTR)Data )))
|
|
{
|
|
//
|
|
// Assume it is supported, since there is nothing else we can do here.
|
|
//
|
|
continue;
|
|
}
|
|
|
|
Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
ServiceKeyPath,
|
|
0,
|
|
KEY_READ,
|
|
&Key );
|
|
|
|
if( Error != ERROR_SUCCESS ) {
|
|
//
|
|
// Assume it is supported, since there is nothing else we can do here.
|
|
//
|
|
continue;
|
|
}
|
|
|
|
if( IsDeviceSupported( TxtsetupSifHandle,
|
|
Key,
|
|
(LPTSTR)Data,
|
|
FilePath,
|
|
ARRAYSIZE(FilePath)
|
|
) ) {
|
|
RegCloseKey( Key );
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Find out if this device is already in our list
|
|
//
|
|
DeviceAlreadyFound = FALSE;
|
|
for( p = (PUNSUPORTED_DRIVER_INFO)*DriverList; p && !DeviceAlreadyFound; p = p->Next ) {
|
|
if( !lstrcmpi( p->DriverId, (LPTSTR)Data ) ) {
|
|
DeviceAlreadyFound = TRUE;
|
|
}
|
|
}
|
|
if( DeviceAlreadyFound ) {
|
|
RegCloseKey( Key );
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Find out if the device is listed in the section [ServicesToDisable] in dosnet.inf
|
|
//
|
|
if( IsServiceToBeDisabled( NtcompatInf,
|
|
(LPTSTR)Data ) ) {
|
|
RegCloseKey( Key );
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Find out if the file is listed in the [DriversToSkipCopy] section in
|
|
// ntcompat.inf.
|
|
//
|
|
if( IsDriverCopyToBeSkipped( NtcompatInf,
|
|
(LPTSTR)Data,
|
|
FilePath ) ) {
|
|
RegCloseKey( Key );
|
|
continue;
|
|
}
|
|
|
|
|
|
//
|
|
// The driver for this device is not supported and needs to be migrated.
|
|
//
|
|
DriverInfo = NULL;
|
|
|
|
if( !BuildDriverInformation( Key,
|
|
(LPTSTR)Data,
|
|
FilePath,
|
|
&DriverInfo ) ) {
|
|
//
|
|
// If we cannot build the driver information for this device, then
|
|
// we inform the user that we detected an unsupported device, but that
|
|
// we cannot migrate it. The user will have to provide the OEM disk
|
|
// for this device during setupldr or textmode setup phases.
|
|
//
|
|
RegCloseKey( Key );
|
|
FreeDriverInformationList( DriverList );
|
|
return( FALSE );
|
|
}
|
|
|
|
DriverInfo->Next = (PUNSUPORTED_DRIVER_INFO)*DriverList;
|
|
(PUNSUPORTED_DRIVER_INFO)*DriverList = DriverInfo;
|
|
RegCloseKey( Key );
|
|
}
|
|
RegCloseKey( ScsiKey );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
DWORD
|
|
DumpRegInfoToInf(
|
|
IN PUNSUPORTED_DRIVER_REGKEY_INFO RegList,
|
|
IN LPTSTR DriverId,
|
|
IN PINFFILEGEN Context
|
|
)
|
|
|
|
{
|
|
LPTSTR SectionName;
|
|
DWORD Error;
|
|
LPTSTR szAddReg = TEXT("AddReg.");
|
|
PUNSUPORTED_DRIVER_REGKEY_INFO p;
|
|
|
|
Error = ERROR_SUCCESS;
|
|
SectionName = MALLOC( (lstrlen( szAddReg ) + lstrlen( DriverId ) + 1)*sizeof(TCHAR) );
|
|
if( SectionName == NULL ) {
|
|
Error = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto c0;
|
|
}
|
|
lstrcpy( SectionName, szAddReg );
|
|
lstrcat( SectionName, DriverId );
|
|
Error = InfCreateSection( SectionName, &Context );
|
|
|
|
for( p = RegList; p != NULL; p = p->Next ) {
|
|
#if 0
|
|
Error = DumpRegInfoToInfWorker( p->PredefinedKey,
|
|
p->KeyPath,
|
|
Context );
|
|
#endif
|
|
Error = DumpRegKeyToInf( Context,
|
|
p->PredefinedKey,
|
|
p->KeyPath,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE,
|
|
p->MigrateVolatileKeys );
|
|
|
|
if( Error != ERROR_SUCCESS ) {
|
|
goto c0;
|
|
}
|
|
}
|
|
|
|
c0:
|
|
if( SectionName != NULL ) {
|
|
FREE( SectionName );
|
|
}
|
|
return( Error );
|
|
}
|
|
|
|
|
|
DWORD
|
|
DumpFileInfoToInf(
|
|
IN PUNSUPORTED_DRIVER_FILE_INFO FileList,
|
|
IN LPTSTR DriverId,
|
|
IN PINFFILEGEN Context
|
|
)
|
|
|
|
{
|
|
LPTSTR SectionName;
|
|
DWORD Error;
|
|
LPTSTR szFiles = TEXT("Files.");
|
|
PUNSUPORTED_DRIVER_FILE_INFO p;
|
|
TCHAR Line[ MAX_PATH ];
|
|
|
|
Error = ERROR_SUCCESS;
|
|
SectionName = MALLOC( (lstrlen( szFiles ) + lstrlen( DriverId ) + 1)*sizeof(TCHAR) );
|
|
if( SectionName == NULL ) {
|
|
Error = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto c0;
|
|
}
|
|
lstrcpy( SectionName, szFiles );
|
|
lstrcat( SectionName, DriverId );
|
|
Error = InfCreateSection( SectionName, &Context );
|
|
|
|
for( p = FileList; p != NULL; p = p->Next ) {
|
|
StringCchCopy(Line, ARRAYSIZE(Line), p->FileName );
|
|
StringCchCat(Line, ARRAYSIZE(Line), TEXT(",") );
|
|
StringCchCat(Line, ARRAYSIZE(Line), p->TargetDirectory );
|
|
Error = WriteText(Context->FileHandle,MSG_INF_SINGLELINE,Line);
|
|
if( Error != ERROR_SUCCESS ) {
|
|
goto c0;
|
|
}
|
|
}
|
|
|
|
c0:
|
|
if( SectionName != NULL ) {
|
|
FREE( SectionName );
|
|
}
|
|
return( Error );
|
|
}
|
|
|
|
|
|
DWORD
|
|
DumpInstallInfoToAnswerFile (
|
|
IN PUNSUPORTED_DRIVER_INSTALL_INFO InstallInfo,
|
|
IN PCTSTR DriverId
|
|
)
|
|
{
|
|
PUNSUPORTED_DRIVER_INSTALL_INFO p;
|
|
DWORD d;
|
|
INT len;
|
|
PTSTR buffer, append;
|
|
TCHAR number[12];
|
|
|
|
if (!ActualParamFile[0] || !FileExists (ActualParamFile, NULL)) {
|
|
MYASSERT(FALSE);
|
|
return ERROR_FILE_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// start by writing the list of driver sections as
|
|
// [Data]
|
|
// OEMDrivers=<driver-section-1>,<driver-section-2>,...
|
|
//
|
|
|
|
len = 0;
|
|
for (p = InstallInfo; p; p = p->Next) {
|
|
if (len) {
|
|
len++; // for the comma
|
|
}
|
|
len += LENGTHOF("MigDrv.") + lstrlen (DriverId);
|
|
}
|
|
|
|
buffer = MALLOC((len + 1) * sizeof (TCHAR));
|
|
if (!buffer) {
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
append = buffer;
|
|
for (p = InstallInfo; p; p = p->Next) {
|
|
if (append > buffer) {
|
|
*append++ = TEXT(',');
|
|
}
|
|
append += _sntprintf (append, len + 1 - (append - buffer), TEXT("MigDrv.%s"), DriverId);
|
|
}
|
|
|
|
d = ERROR_SUCCESS;
|
|
|
|
if (!WritePrivateProfileString (
|
|
WINNT_DATA,
|
|
WINNT_OEMDRIVERS,
|
|
buffer,
|
|
ActualParamFile
|
|
)) {
|
|
d = GetLastError ();
|
|
}
|
|
|
|
if (d == ERROR_SUCCESS) {
|
|
|
|
//
|
|
// then for each section, write the mig info as in
|
|
// [driver-section]
|
|
// OemDriverPathName=<path> (path to the driver (may use environment variables)
|
|
// OemInfName=<inf name> name of the inf to be installed from the above
|
|
// directory (there can be one or more infs in this directory, so
|
|
// this is a comma separated list)
|
|
// OemDriverFlags=<flags>
|
|
//
|
|
for (p = InstallInfo; p; p = p->Next) {
|
|
|
|
_sntprintf (buffer, len + 1, TEXT("MigDrv.%s"), DriverId);
|
|
_sntprintf (number, ARRAYSIZE(number), TEXT("%u"), SETUP_OEM_MIGRATED_DRIVER);
|
|
|
|
if (!WritePrivateProfileString (
|
|
buffer,
|
|
WINNT_OEMDRIVERS_PATHNAME,
|
|
IsArc() ? LocalSourceWithPlatform : LocalBootDirectory,
|
|
ActualParamFile
|
|
) ||
|
|
!WritePrivateProfileString (
|
|
buffer,
|
|
WINNT_OEMDRIVERS_INFNAME,
|
|
p->InfOriginalFileName ? p->InfOriginalFileName : p->InfFileName,
|
|
ActualParamFile
|
|
) ||
|
|
!WritePrivateProfileString (
|
|
buffer,
|
|
WINNT_OEMDRIVERS_FLAGS,
|
|
number,
|
|
ActualParamFile
|
|
)) {
|
|
d = GetLastError ();
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FREE(buffer);
|
|
|
|
if (d != ERROR_SUCCESS) {
|
|
//
|
|
// try to clean up
|
|
//
|
|
WritePrivateProfileString (
|
|
WINNT_DATA,
|
|
WINNT_OEMDRIVERS,
|
|
TEXT(""),
|
|
ActualParamFile
|
|
);
|
|
}
|
|
|
|
return d;
|
|
}
|
|
|
|
DWORD
|
|
DumpHardwareIdsToInf(
|
|
IN PUNSUPORTED_PNP_HARDWARE_ID HwIdList,
|
|
IN LPTSTR DriverId,
|
|
IN PINFFILEGEN Context
|
|
)
|
|
|
|
{
|
|
LPTSTR SectionName;
|
|
DWORD Error;
|
|
LPTSTR szHardwareIds = TEXT("HardwareIds.");
|
|
PUNSUPORTED_PNP_HARDWARE_ID p;
|
|
LPTSTR Line;
|
|
ULONG Length;
|
|
|
|
Error = ERROR_SUCCESS;
|
|
SectionName = MALLOC( (lstrlen( szHardwareIds ) + lstrlen( DriverId ) + 1)*sizeof( TCHAR ) );
|
|
if( SectionName == NULL ) {
|
|
Error = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto c0;
|
|
}
|
|
lstrcpy( SectionName, szHardwareIds );
|
|
lstrcat( SectionName, DriverId );
|
|
Error = InfCreateSection( SectionName, &Context );
|
|
|
|
for( p = HwIdList; p != NULL; p = p->Next ) {
|
|
Length = (lstrlen( p->Id ) + lstrlen( p->Service ) + 3)*sizeof(TCHAR);
|
|
if( p->ClassGuid ) {
|
|
Length += (lstrlen( p->ClassGuid) + 1 )*sizeof(TCHAR);
|
|
}
|
|
Line = MALLOC( Length );
|
|
if( Line == NULL ) {
|
|
goto c0;
|
|
}
|
|
lstrcpy( Line, p->Id );
|
|
lstrcat( Line, TEXT("=") );
|
|
lstrcat( Line, p->Service );
|
|
if( p->ClassGuid ) {
|
|
lstrcat( Line, TEXT(",") );
|
|
lstrcat( Line, p->ClassGuid );
|
|
}
|
|
Error = WriteText(Context->FileHandle,MSG_INF_SINGLELINE,Line);
|
|
FREE( Line );
|
|
|
|
if( Error != ERROR_SUCCESS ) {
|
|
goto c0;
|
|
}
|
|
}
|
|
|
|
c0:
|
|
if( SectionName != NULL ) {
|
|
FREE( SectionName );
|
|
}
|
|
return( Error );
|
|
}
|
|
|
|
|
|
BOOL
|
|
SaveUnsupportedDriverInfo(
|
|
IN HWND ParentWindow,
|
|
IN LPTSTR FileName,
|
|
IN PUNSUPORTED_DRIVER_INFO DriverList
|
|
)
|
|
{
|
|
HKEY Key;
|
|
DWORD d;
|
|
LONG l = ERROR_SUCCESS;
|
|
TCHAR Path[MAX_PATH];
|
|
PINFFILEGEN InfContext;
|
|
TCHAR SectionName[MAX_PATH];
|
|
PUNSUPORTED_DRIVER_INFO p;
|
|
|
|
#if defined(_AMD64_) || defined(_X86_)
|
|
if(Floppyless) {
|
|
//These are both size MAX_PATH
|
|
lstrcpy(Path,LocalBootDirectory);
|
|
} else {
|
|
Path[0] = FirstFloppyDriveLetter;
|
|
Path[1] = TEXT(':');
|
|
Path[2] = 0;
|
|
}
|
|
#else
|
|
//These are both size MAX_PATH
|
|
lstrcpy(Path,LocalSourceWithPlatform);
|
|
#endif
|
|
|
|
l = InfStart( FileName,
|
|
Path,
|
|
&InfContext);
|
|
|
|
if(l != ERROR_SUCCESS) {
|
|
return(FALSE);
|
|
}
|
|
|
|
for( p = DriverList; p != NULL; p = p->Next ) {
|
|
if( p->KeyList != NULL ) {
|
|
l = DumpRegInfoToInf( p->KeyList,p->DriverId, InfContext );
|
|
if(l != ERROR_SUCCESS) {
|
|
goto c0;
|
|
}
|
|
}
|
|
if( p->FileList ) {
|
|
l = DumpFileInfoToInf( p->FileList, p->DriverId, InfContext );
|
|
if(l != ERROR_SUCCESS) {
|
|
goto c0;
|
|
}
|
|
}
|
|
if (p->InstallList) {
|
|
l = DumpInstallInfoToAnswerFile(p->InstallList, p->DriverId);
|
|
if(l != ERROR_SUCCESS) {
|
|
goto c0;
|
|
}
|
|
}
|
|
|
|
if( p->HardwareIdsList ) {
|
|
l = DumpHardwareIdsToInf( p->HardwareIdsList, p->DriverId, InfContext );
|
|
if(l != ERROR_SUCCESS) {
|
|
goto c0;
|
|
}
|
|
}
|
|
}
|
|
if( DriverList != NULL ) {
|
|
l = InfCreateSection( TEXT("Devices"), &InfContext );
|
|
if(l != NO_ERROR) {
|
|
goto c0;
|
|
}
|
|
for( p = DriverList; p != NULL; p = p->Next ) {
|
|
l = WriteText(InfContext->FileHandle,MSG_INF_SINGLELINE,p->DriverId);
|
|
if(l != ERROR_SUCCESS) {
|
|
goto c0;
|
|
}
|
|
}
|
|
}
|
|
|
|
c0:
|
|
InfEnd( &InfContext );
|
|
if( l != ERROR_SUCCESS ) {
|
|
StringCchCat( Path, ARRAYSIZE(Path), TEXT("\\") );
|
|
if (SUCCEEDED(StringCchCat( Path, ARRAYSIZE(Path), FileName )))
|
|
{
|
|
DeleteFile( Path );
|
|
}
|
|
return( FALSE );
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL
|
|
MigrateUnsupportedNTDrivers(
|
|
IN HWND ParentWindow,
|
|
IN PVOID TxtsetupSifHandle
|
|
)
|
|
|
|
{
|
|
BOOL b;
|
|
PUNSUPORTED_DRIVER_INFO UnsupportedDriverList = NULL;
|
|
|
|
b = BuildUnsupportedDriverList( TxtsetupSif, &UnsupportedDriverList );
|
|
if( !CheckUpgradeOnly && b ) {
|
|
if( UnsupportedDriverList ) {
|
|
b = SaveUnsupportedDriverInfo( ParentWindow, WINNT_UNSUPDRV_INF_FILE, UnsupportedDriverList );
|
|
if( b ) {
|
|
b = AddUnsupportedFilesToCopyList( ParentWindow, UnsupportedDriverList );
|
|
if( !b ) {
|
|
TCHAR Path[ MAX_PATH + 1 ];
|
|
//
|
|
// If we failed to add the files to the copy list, then
|
|
// delete unsupdrv.inf since there is no point in migrating
|
|
// these drivers.
|
|
//
|
|
#if defined(_AMD64_) || defined(_X86_)
|
|
if(Floppyless) {
|
|
//These are both size MAX_PATH
|
|
lstrcpy(Path,LocalBootDirectory);
|
|
} else {
|
|
Path[0] = FirstFloppyDriveLetter;
|
|
Path[1] = TEXT(':');
|
|
Path[2] = 0;
|
|
}
|
|
#else
|
|
//These are both size MAX_PATH
|
|
lstrcpy(Path,LocalSourceWithPlatform);
|
|
#endif
|
|
StringCchCat( Path, ARRAYSIZE(Path), TEXT("\\") );
|
|
if (SUCCEEDED(StringCchCat( Path, ARRAYSIZE(Path), WINNT_UNSUPDRV_INF_FILE )))
|
|
{
|
|
DeleteFile( Path );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
FreeDriverInformationList( &UnsupportedDriverList );
|
|
}
|
|
if( !b ) {
|
|
//
|
|
// Inform the user that unsupported drivers could not be migrated.
|
|
//
|
|
MessageBoxFromMessage( ParentWindow,
|
|
MSG_CANT_MIGRATE_UNSUP_DRIVERS,
|
|
FALSE,
|
|
AppTitleStringId,
|
|
MB_OK | MB_ICONINFORMATION | MB_TASKMODAL
|
|
);
|
|
}
|
|
return( b );
|
|
}
|
|
|
|
#endif
|