#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); }