1120 lines
25 KiB
C
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);
|
|
}
|