windows-nt/Source/XPSP1/NT/base/ntsetup/legacy/dll/hardware.c
2020-09-26 16:20:57 +08:00

1120 lines
25 KiB
C

#include "precomp.h"
#pragma hdrstop
/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
hardware.c
Abstract:
Registry hardware detection
Author:
Sunil Pai (sunilp) April 1992
--*/
#define IDENTIFIER "Identifier"
PCHAR AdaptersTable[] = {
"EisaAdapter",
"MultifunctionAdapter"
};
//=====================================================================
// The following funtions detect information from the registry hardware
// node
//=====================================================================
BOOL
SearchControllerForPeripheral(
IN LPSTR Controller,
IN LPSTR Peripheral,
OUT LPSTR PeripheralPath
)
{
HKEY hKey, hSubKey;
CHAR KeyName[ MAX_PATH ];
CHAR SubKeyName[ MAX_PATH ];
CHAR Class[ MAX_PATH ];
DWORD cbSubKeyName;
DWORD cbClass;
FILETIME FileTime;
UINT Index;
LONG Status;
//
// Open the controller key
//
lstrcpy( KeyName, "Hardware\\Description\\System\\MultifunctionAdapter\\0\\");
lstrcat( KeyName, Controller );
Status = RegOpenKeyEx (
HKEY_LOCAL_MACHINE,
KeyName,
0,
KEY_READ,
&hKey
);
//
// If failed to open it then check for an eisa adapter node
//
if (Status != ERROR_SUCCESS) {
lstrcpy( KeyName, "Hardware\\Description\\System\\EisaAdapter\\0\\");
lstrcat( KeyName, Controller );
Status = RegOpenKeyEx (
HKEY_LOCAL_MACHINE,
KeyName,
0,
KEY_READ,
&hKey
);
}
//
// If the controller wasn't found at all then return FALSE
if ( Status != ERROR_SUCCESS ) {
return FALSE;
}
//
// Enumerate the subkeys for the controller and search the subkeys
// for the peripheral indicated
//
for ( Index = 0 ; ; Index++ ) {
cbSubKeyName = MAX_PATH;
cbClass = MAX_PATH;
Status = RegEnumKeyEx(
hKey,
Index,
SubKeyName,
&cbSubKeyName,
NULL,
Class,
&cbClass,
&FileTime
);
if ( Status != ERROR_SUCCESS ) {
break;
}
//
// Combine the subkey name with the peripheral name and see if it
// exists
//
lstrcat (SubKeyName, "\\");
lstrcat (SubKeyName, Peripheral);
lstrcat (SubKeyName, "\\0");
Status = RegOpenKeyEx (
hKey,
SubKeyName,
0,
KEY_READ,
&hSubKey
);
if (Status == ERROR_SUCCESS) {
RegCloseKey( hSubKey );
RegCloseKey( hKey );
//
// path already has the controller\key entry
lstrcpy (PeripheralPath, Controller);
lstrcat (PeripheralPath, "\\" );
lstrcat (PeripheralPath, SubKeyName);
return( TRUE );
}
}
RegCloseKey( hKey );
return( FALSE );
}
BOOL
GetTypeOfHardware(
LPSTR HardwareAdapterEntry,
LPSTR HardwareType
)
{
BOOL bReturn = FALSE;
PVOID ConfigurationData = NULL;
LPSTR Type = NULL;
CHAR SubKey[MAX_PATH];
LONG Status;
HKEY hKey;
//
// Open the controller key for a multifunction adapter
//
lstrcpy( SubKey, "Hardware\\Description\\System\\MultifunctionAdapter\\0\\");
lstrcat( SubKey, HardwareAdapterEntry );
Status = RegOpenKeyEx (
HKEY_LOCAL_MACHINE,
SubKey,
0,
KEY_READ,
&hKey
);
//
// If failed to open it then check for an eisa adapter node
//
if (Status != ERROR_SUCCESS) {
lstrcpy( SubKey, "Hardware\\Description\\System\\EisaAdapter\\0\\");
lstrcat( SubKey, HardwareAdapterEntry );
Status = RegOpenKeyEx (
HKEY_LOCAL_MACHINE,
SubKey,
0,
KEY_READ,
&hKey
);
}
if ( Status == ERROR_SUCCESS ) {
Type = GetValueEntry( hKey, "Identifier" );
if(Type != NULL) {
//
// Parse the type field to return type
//
lstrcpy ( HardwareType, Type );
SFree( Type );
bReturn = TRUE;
}
RegCloseKey( hKey );
}
return (bReturn);
}
/*
Computer type as a string
*/
CB
GetMyComputerType(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
CB Length;
HKEY hKey;
LPSTR Type = NULL;
LONG Status;
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
#if i386
#define TEMP_COMPUTER "AT/AT COMPATIBLE"
#else
#define TEMP_COMPUTER "JAZZ"
#endif
lstrcpy(ReturnBuffer,TEMP_COMPUTER);
Length = lstrlen(TEMP_COMPUTER) + 1;
//
// Open hardware node
//
Status = RegOpenKeyEx (
HKEY_LOCAL_MACHINE,
"Hardware\\Description\\System",
0,
KEY_READ,
&hKey
);
if ( Status == ERROR_SUCCESS ) {
Type = GetValueEntry( hKey, "Identifier" );
if(Type != NULL) {
//
// Parse the type field to return computer type
//
lstrcpy ( ReturnBuffer, Type );
Length = lstrlen( Type ) + 1;
SFree( Type );
}
RegCloseKey( hKey );
}
return( Length );
}
/*
Video type as a string
*/
CB
GetMyVideoType(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
CHAR HardwareType[80];
INT Length;
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
#define TEMP_VIDEO "VGA"
if ( GetTypeOfHardware(
"DisplayController\\0",
(LPSTR)HardwareType
)
) {
//
// Parse the type field to return Video type
//
lstrcpy ( ReturnBuffer, HardwareType );
Length = lstrlen ( HardwareType ) + 1;
}
else {
//
// In case we cannot detect
//
lstrcpy(ReturnBuffer,TEMP_VIDEO);
Length = lstrlen(TEMP_VIDEO)+1;
}
return (Length);
}
/*
Bus type as a string
*/
CB
GetMyBusType(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
CHAR HardwareType[80];
INT Length;
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
#define TEMP_BUS "ISA"
if ( GetTypeOfHardware(
"",
(LPSTR)HardwareType
)
) {
//
// Parse the type field to return Video type
//
lstrcpy ( ReturnBuffer, HardwareType );
Length = lstrlen ( HardwareType ) + 1;
}
else {
//
// In case we cannot detect
//
lstrcpy(ReturnBuffer,TEMP_BUS);
Length = lstrlen(TEMP_BUS)+1;
}
return (Length);
}
/*
Pointer type as a string
*/
CB
GetMyPointerType(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
CHAR HardwareType[80];
CHAR PeripheralPath[MAX_PATH];
CHAR *Controller[] = {"PointerController", "KeyboardController", "SerialController", NULL};
BOOL PointerNotFound = TRUE;
INT Length, i;
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
#define TEMP_POINTER "NONE"
for (i = 0; Controller[i] != NULL && PointerNotFound; i++ ) {
if ( SearchControllerForPeripheral(
Controller[i],
"PointerPeripheral",
PeripheralPath
)
) {
PointerNotFound = FALSE;
}
}
if ( (PointerNotFound) ||
(!GetTypeOfHardware(
PeripheralPath,
(LPSTR)HardwareType
))
) {
//
// In case we cannot detect
//
lstrcpy(ReturnBuffer,TEMP_POINTER);
Length = lstrlen( TEMP_POINTER )+1;
}
else {
//
// Parse the type field to return display type
//
lstrcpy ( ReturnBuffer, HardwareType );
Length = lstrlen ( HardwareType ) + 1;
}
return (Length);
}
/*
Keyboard type as a string
*/
CB
GetMyKeyboardType(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
CHAR HardwareType[80];
INT Length;
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
#define TEMP_KEYBOARD "PCAT_ENHANCED"
if ( GetTypeOfHardware(
"KeyboardController\\0\\KeyboardPeripheral\\0",
(LPSTR)HardwareType
)
) {
//
// Parse the type field to return keyboard type
//
lstrcpy ( ReturnBuffer, HardwareType );
Length = lstrlen ( HardwareType ) + 1;
}
else {
//
// In case we cannot detect
//
lstrcpy( ReturnBuffer, TEMP_KEYBOARD );
Length = lstrlen( TEMP_KEYBOARD )+1;
}
return (Length);
}
BOOL
GetSetupEntryForHardware(
IN LPSTR Hardware,
OUT LPSTR SelectedHardwareOption
)
{
HKEY hKey;
LONG Status;
LPSTR ValueData;
//
// Open the setup key in the current control set
//
Status = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\control\\setup",
0,
KEY_READ,
&hKey
);
if( Status != ERROR_SUCCESS ) {
return( FALSE );
}
//
// Get the value data of interest
//
if ( ValueData = GetValueEntry( hKey, Hardware ) ) {
lstrcpy( SelectedHardwareOption, ValueData );
SFree( ValueData );
RegCloseKey( hKey );
return( TRUE );
}
else {
RegCloseKey( hKey );
return( FALSE );
}
}
CB
GetSelectedVideo(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
#define SELECTED_VIDEO ""
if( GetSetupEntryForHardware( "Video", ReturnBuffer ) ) {
return( lstrlen( ReturnBuffer ) + 1 );
}
else {
lstrcpy( ReturnBuffer, SELECTED_VIDEO );
return( lstrlen( SELECTED_VIDEO ) + 1 );
}
}
CB
GetSelectedPointer(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
#define SELECTED_POINTER ""
if( GetSetupEntryForHardware( "Pointer", ReturnBuffer ) ) {
return( lstrlen( ReturnBuffer ) + 1 );
}
else {
lstrcpy( ReturnBuffer, SELECTED_POINTER );
return( lstrlen( SELECTED_POINTER ) + 1 );
}
}
CB
GetSelectedKeyboard(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
#define SELECTED_KEYBOARD ""
if( GetSetupEntryForHardware( "Keyboard", ReturnBuffer ) ) {
return( lstrlen( ReturnBuffer ) + 1 );
}
else {
lstrcpy( ReturnBuffer, SELECTED_KEYBOARD );
return( lstrlen( SELECTED_KEYBOARD ) + 1 );
}
}
CB
GetDevicemapValue(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
CB rc = 0;
CHAR DeviceEntry[ MAX_PATH ];
HKEY hKey;
LONG Status;
LPSTR ServicesEntry;
Unused( cbReturnBuffer );
#define DEFAULT_ENTRY ""
if (cArgs != 2) {
return( rc );
}
lstrcpy (ReturnBuffer, DEFAULT_ENTRY);
rc = lstrlen( DEFAULT_ENTRY ) + 1;
//
// HACK FOR VIDEO
// To make inf files from release 1.0 work properly, always return VGA
// so that the old driver is not disabled by the inf file.
//
if (!lstrcmp( Args[ 0 ], "Video" )) {
return rc;
}
//
// Open the devicemap key for the hardware indicated
//
lstrcpy( DeviceEntry, "hardware\\devicemap\\" );
lstrcat( DeviceEntry, Args[ 0 ] );
Status = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
DeviceEntry,
0,
KEY_READ,
&hKey
);
if( Status != ERROR_SUCCESS ) {
return( rc );
}
//
// Read the value entry associated with the hardware
//
lstrcpy( DeviceEntry, Args[1] );
//
// Get the value data associated with this entry
//
if (ServicesEntry = GetValueEntry (hKey, DeviceEntry)) {
LPSTR Entry;
if( (Entry = strstr( ServicesEntry, "Services\\")) != NULL &&
(Entry = strchr( Entry, '\\' )) != NULL &&
*++Entry != '\0'
) {
LPSTR EndOfEntry;
if( (EndOfEntry = strchr( Entry, '\\' )) != NULL ) {
*EndOfEntry = '\0';
}
}
else {
Entry = ServicesEntry;
}
lstrcpy( ReturnBuffer, Entry );
rc = lstrlen( Entry ) + 1;
SFree( ServicesEntry );
}
RegCloseKey( hKey );
return( rc );
}
/*
Bus type as a string
*/
BOOLEAN
IsKeyNameInAdaptersTable(
IN PSTR KeyName
)
{
ULONG Index;
for( Index = 0;
Index < sizeof( AdaptersTable ) / sizeof( PCHAR );
Index++ ) {
if( _stricmp( KeyName, AdaptersTable[ Index ] ) == 0 ) {
return( TRUE );
}
}
return( FALSE );
}
LONG
QueryMyBusTypeListWorker(
IN HKEY ParentKey,
IN PSTR CompleteParentKeyName,
IN BOOLEAN FirstTimeCalled,
IN BOOLEAN GetIdentifierFromParentKey,
OUT PSTR* pReturnBuffer
)
{
ULONG Index;
LONG Status;
PSTR BusTypeList;
*pReturnBuffer = NULL;
BusTypeList = NULL;
if( !GetIdentifierFromParentKey && !IsKeyNameInAdaptersTable( strrchr( CompleteParentKeyName, '\\' ) + 1 ) ) {
return( ERROR_SUCCESS );
}
if( GetIdentifierFromParentKey && !FirstTimeCalled ) {
PSTR TmpString;
ULONG TmpStringSize;
TmpString = GetValueEntry( ParentKey, IDENTIFIER );
if( ( TmpString != NULL ) &&
( ( TmpStringSize = strlen( TmpString ) ) != 0 ) ) {
BusTypeList = SAlloc( TmpStringSize + 3 );
if( BusTypeList == NULL ) {
SFree( TmpString );
return( ERROR_OUTOFMEMORY );
}
lstrcpy( BusTypeList, "\"" );
lstrcat( BusTypeList, TmpString );
lstrcat( BusTypeList, "\"" );
SFree( TmpString );
}
}
//
// Find out whether or not this key has subkeys
//
{
CHAR szClass[ MAX_PATH + 1 ];
ULONG cchClass;
ULONG cSubKeys;
ULONG cchMaxSubkey;
ULONG cchMaxClass;
ULONG cValues;
ULONG cchMaxValueName;
ULONG cbMaxValueData;
ULONG cbSecurityDescriptor;
FILETIME ftLastWriteTime;
cchClass = sizeof( szClass );
Status = RegQueryInfoKey( ParentKey,
szClass,
&cchClass,
NULL,
&cSubKeys,
&cchMaxSubkey,
&cchMaxClass,
&cValues,
&cchMaxValueName,
&cbMaxValueData,
&cbSecurityDescriptor,
&ftLastWriteTime );
if( Status != ERROR_SUCCESS ) {
if( BusTypeList != NULL ) {
SFree( BusTypeList );
}
return( Status );
}
// check for PCMCIA bus first
{
SC_HANDLE hSCManager = OpenSCManager( NULL, SERVICES_ACTIVE_DATABASEA, GENERIC_READ );
if ( hSCManager != NULL )
{
SC_HANDLE hService = OpenService( hSCManager, "Pcmcia", GENERIC_READ );
if ( hService != NULL )
{
SERVICE_STATUS sStatus;
if (QueryServiceStatus( hService, &sStatus ))
{
if ( sStatus.dwCurrentState == SERVICE_RUNNING )
{
PSTR TmpBuffer;
ULONG TmpStringSize;
TmpBuffer = SAlloc( lstrlen("PCMCIA") + 3 );
lstrcpy( TmpBuffer, "\"" );
lstrcat( TmpBuffer, "PCMCIA" );
lstrcat( TmpBuffer, "\"" );
TmpStringSize = strlen( TmpBuffer );
if( BusTypeList == NULL ) {
BusTypeList = TmpBuffer;
} else if( strlen( BusTypeList ) == 0 ) {
SFree( BusTypeList );
BusTypeList = TmpBuffer;
} else {
BusTypeList = SRealloc( BusTypeList, strlen( BusTypeList ) + TmpStringSize + 2 );
strcat( BusTypeList, "," );
strcat( BusTypeList, TmpBuffer );
SFree( TmpBuffer );
}
}
}
CloseServiceHandle(hService);
}
CloseServiceHandle(hSCManager);
}
}
for( Index = 0; Index < cSubKeys; Index++ ) {
HKEY ChildKey;
CHAR ChildKeyName[ MAX_PATH + 1];
CHAR CompleteChildKeyName[ 2*MAX_PATH + 1 ];
PSTR TmpBuffer;
ULONG TmpStringSize;
Status = RegEnumKey( ParentKey,
Index,
ChildKeyName,
sizeof( ChildKeyName ) );
if( Status != ERROR_SUCCESS ) {
continue;
}
//
// Open the child key
//
Status = RegOpenKeyEx( ParentKey,
ChildKeyName,
0,
KEY_READ,
&ChildKey );
if( Status != ERROR_SUCCESS ) {
continue;
}
lstrcpy( CompleteChildKeyName, CompleteParentKeyName );
lstrcat( CompleteChildKeyName, "\\" );
lstrcat( CompleteChildKeyName, ChildKeyName );
//
// Get the identifier from all subkeys, and traverse the subkeys if necessary
//
TmpBuffer = NULL;
Status = QueryMyBusTypeListWorker( ChildKey,
CompleteChildKeyName,
FALSE,
( BOOLEAN )!GetIdentifierFromParentKey,
&TmpBuffer );
if( ( Status == ERROR_SUCCESS ) &&
( TmpBuffer != NULL ) &&
( ( TmpStringSize = strlen( TmpBuffer ) )!= 0 ) ) {
if( BusTypeList == NULL ) {
BusTypeList = TmpBuffer;
} else if( strlen( BusTypeList ) == 0 ) {
SFree( BusTypeList );
BusTypeList = TmpBuffer;
} else {
BusTypeList = SRealloc( BusTypeList, strlen( BusTypeList ) + TmpStringSize + 2 );
strcat( BusTypeList, "," );
strcat( BusTypeList, TmpBuffer );
SFree( TmpBuffer );
}
}
RegCloseKey( ChildKey );
}
}
*pReturnBuffer = BusTypeList;
return( Status );
}
int __cdecl
CompareFunction( const void * String1,
const void * String2
)
{
return( lstrcmpi( *( PSTR * )String1, *( PSTR * )String2 ) );
}
LONG
RemoveDuplicateNamesFromList(
IN PCSTR List,
OUT PSTR* TrimmedList
)
{
PSTR TmpList;
ULONG ElementsInList;
PSTR Pointer;
PSTR* TmpBuffer;
ULONG i;
PSTR p1;
//
// Make a duplicate of the original list.
// This is necessary, since strtok() modifies
// the contents of the buffer that is passed
// as parameter.
//
TmpList = SzDup( (SZ)List );
if( TmpList == NULL ) {
return( ERROR_OUTOFMEMORY );
}
//
// Find out how many items the list contains
//
ElementsInList = 0;
for( Pointer = strtok( TmpList, "," );
Pointer != NULL;
ElementsInList++, Pointer = strtok( NULL, "," ) );
if( ElementsInList < 2 ) {
//
// If list contains less than two items, than there is
// no duplicate item to remove. In this case, just return
// a copy of the original list.
//
*TrimmedList = SzDup( (SZ)List );
if( *TrimmedList == NULL ) {
SFree( TmpList );
return( ERROR_OUTOFMEMORY );
}
return( ERROR_SUCCESS );
}
//
// If the list has more than one item, then it may have duplicates.
// To remove the duplicates, we first need to sort the items in the
// list. The items are sorted using the C runtime qsort().
//
TmpBuffer = SAlloc( ElementsInList*sizeof( PSTR ) );
if( TmpBuffer == NULL ) {
SFree( TmpList );
return( ERROR_OUTOFMEMORY );
}
Pointer = TmpList;
for( i = 0; i < ElementsInList; i++ ) {
TmpBuffer[ i ] = Pointer;
Pointer += strlen( Pointer ) + 1;
}
qsort( TmpBuffer, ElementsInList, sizeof( PSTR ), CompareFunction );
//
// TmpBuffer is now a sorted array of pointers to the items
// in the list.
// Using this array, we build a sorted list of items.
// Since we now that this list's size will allways be less or
// of the original list's size, we allocate a buffer assuming
// maximum size.
//
p1 = SAlloc( lstrlen( List ) + 1 );
if( p1 == NULL ) {
SFree( TmpList );
SFree( TmpBuffer );
return( ERROR_OUTOFMEMORY );
}
//
// Remove the duplicates from the array
//
for( i = 0; i < ElementsInList - 1; i++ ) {
if( lstrcmpi( TmpBuffer[ i ], TmpBuffer[ i + 1] ) == 0 ) {
TmpBuffer[ i ] = NULL;
}
}
//
// Copy the remaining items to the new list
//
*p1 = '\0';
for( i = 0; i < ElementsInList; i++ ) {
if( TmpBuffer[ i ] != NULL ) {
if( lstrlen( p1 ) != 0 ) {
lstrcat( p1, "," );
}
lstrcat( p1, TmpBuffer[i] );
}
}
SFree( TmpList );
SFree( TmpBuffer );
*TrimmedList = p1;
return( ERROR_SUCCESS );
}
CB
GetMyBusTypeList(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
ULONG Status;
HKEY Key;
PSTR KeyName = "HARDWARE\\DESCRIPTION\\System";
PSTR Pointer = NULL;
ULONG ListSize;
PSTR TrimmedList;
Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
KeyName,
0,
KEY_READ,
&Key );
if( Status == ERROR_SUCCESS ) {
Pointer = NULL;
Status = QueryMyBusTypeListWorker( Key,
KeyName,
TRUE,
TRUE,
&Pointer );
}
if((Status != ERROR_SUCCESS) || !Pointer
|| (RemoveDuplicateNamesFromList(Pointer,&TrimmedList) != ERROR_SUCCESS)) {
//
// Failure case.
//
if(cbReturnBuffer >= 3) {
lstrcpy(ReturnBuffer,"{}");
ListSize = 3;
} else {
if(cbReturnBuffer) {
ListSize = 1;
*ReturnBuffer = 0;
} else {
ListSize = 0;
}
}
if(Pointer) {
SFree(Pointer);
}
return(ListSize);
}
SFree(Pointer);
ListSize = lstrlen(TrimmedList) + 3;
if(ListSize <= cbReturnBuffer) {
ReturnBuffer[0] = '{';
lstrcpy(&ReturnBuffer[1],TrimmedList);
ReturnBuffer[ListSize-2] = '}';
ReturnBuffer[ListSize-1] = 0;
}
SFree(TrimmedList);
return(ListSize);
}