594 lines
15 KiB
C++
594 lines
15 KiB
C++
/**************************************************************************\
|
|
* Module Name: ntreg.cpp
|
|
*
|
|
* CRegistrySettings class
|
|
*
|
|
* This class handles getting registry information for display driver
|
|
* information.
|
|
*
|
|
* Copyright (c) Microsoft Corp. 1992-1998 All Rights Reserved
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#include <tchar.h>
|
|
#include "ntreg.hxx"
|
|
#include <devguid.h>
|
|
|
|
#ifdef WINNT
|
|
|
|
|
|
//
|
|
// CRegistrySettings constructor
|
|
//
|
|
|
|
CRegistrySettings::CRegistrySettings(LPTSTR pstrDeviceKey)
|
|
: _hkVideoReg(NULL)
|
|
, _pszDrvName(NULL)
|
|
, _pszKeyName(NULL)
|
|
, _pszDeviceInstanceId(NULL)
|
|
{
|
|
TCHAR szBuffer[MAX_PATH];
|
|
LPTSTR pszPath;
|
|
HKEY hkeyCommon, hkeyDriver;
|
|
DWORD cb;
|
|
LPTSTR pszName = NULL;
|
|
LPTSTR pszEnd;
|
|
|
|
ASSERT(lstrlen(pstrDeviceKey) < MAX_PATH);
|
|
|
|
//
|
|
// Copy the data to local buffer.
|
|
//
|
|
|
|
lstrcpy(szBuffer, pstrDeviceKey);
|
|
|
|
//
|
|
// Initialize the device instance id
|
|
//
|
|
|
|
InitDeviceInstanceID(szBuffer);
|
|
|
|
//
|
|
// At this point, szBuffer has something like:
|
|
// \REGISTRY\Machine\System\ControlSet001\...
|
|
//
|
|
// To use the Win32 registry calls, we have to strip off the \REGISTRY
|
|
// and convert \Machine to HKEY_LOCAL_MACHINE
|
|
//
|
|
|
|
pszPath = SubStrEnd(SZ_REGISTRYMACHINE, szBuffer);
|
|
|
|
//
|
|
// Try to open the registry key
|
|
//
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
pszPath,
|
|
0,
|
|
KEY_READ,
|
|
&_hkVideoReg) != ERROR_SUCCESS) {
|
|
|
|
_hkVideoReg = 0;
|
|
}
|
|
|
|
//
|
|
// Go to the video subkey
|
|
//
|
|
|
|
pszEnd = pszPath + lstrlen(pszPath);
|
|
|
|
while (pszEnd != pszPath && *pszEnd != TEXT('\\')) {
|
|
|
|
pszEnd--;
|
|
}
|
|
|
|
*pszEnd = UNICODE_NULL;
|
|
|
|
lstrcat(pszPath, SZ_COMMON_SUBKEY);
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
pszPath,
|
|
0,
|
|
KEY_READ,
|
|
&hkeyCommon) == ERROR_SUCCESS) {
|
|
|
|
cb = sizeof(szBuffer);
|
|
ZeroMemory(szBuffer, cb);
|
|
|
|
if (RegQueryValueEx(hkeyCommon,
|
|
SZ_SERVICE,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szBuffer,
|
|
&cb) == ERROR_SUCCESS) {
|
|
|
|
//
|
|
// Save the key name
|
|
//
|
|
|
|
_pszKeyName = (LPTSTR)LocalAlloc(LPTR,
|
|
(lstrlen(szBuffer) + 1) * sizeof(TCHAR));
|
|
|
|
if (_pszKeyName != NULL) {
|
|
|
|
lstrcpy(_pszKeyName, szBuffer);
|
|
|
|
lstrcpy(szBuffer, SZ_SERVICES_PATH);
|
|
lstrcat(szBuffer, _pszKeyName);
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
szBuffer,
|
|
0,
|
|
KEY_READ,
|
|
&hkeyDriver) == ERROR_SUCCESS) {
|
|
|
|
cb = sizeof(szBuffer);
|
|
ZeroMemory(szBuffer, cb);
|
|
|
|
if (RegQueryValueEx(hkeyDriver,
|
|
L"ImagePath",
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szBuffer,
|
|
&cb) == ERROR_SUCCESS) {
|
|
|
|
//
|
|
// This is a binary.
|
|
// Extract the name, which will be of the form ...\driver.sys
|
|
//
|
|
|
|
LPTSTR pszDriver, pszDriverEnd;
|
|
|
|
pszDriver = szBuffer;
|
|
pszDriverEnd = pszDriver + lstrlen(pszDriver);
|
|
|
|
while(pszDriverEnd != pszDriver &&
|
|
*pszDriverEnd != TEXT('.')) {
|
|
pszDriverEnd--;
|
|
}
|
|
|
|
*pszDriverEnd = UNICODE_NULL;
|
|
|
|
while(pszDriverEnd != pszDriver &&
|
|
*pszDriverEnd != TEXT('\\')) {
|
|
pszDriverEnd--;
|
|
}
|
|
|
|
//
|
|
// If pszDriver and pszDriverEnd are different, we now
|
|
// have the driver name.
|
|
//
|
|
|
|
if (pszDriverEnd > pszDriver) {
|
|
|
|
pszDriverEnd++;
|
|
pszName = pszDriverEnd;
|
|
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkeyDriver);
|
|
}
|
|
|
|
if (!pszName) {
|
|
|
|
//
|
|
// Something failed trying to get the binary name.just get the device name
|
|
//
|
|
|
|
_pszDrvName = _pszKeyName;
|
|
|
|
} else {
|
|
|
|
_pszDrvName = (LPTSTR)LocalAlloc(LPTR,
|
|
(lstrlen(pszName) + 1) * sizeof(TCHAR));
|
|
|
|
if (_pszDrvName != NULL) {
|
|
|
|
lstrcpy(_pszDrvName, pszName);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkeyCommon);
|
|
}
|
|
}
|
|
|
|
//
|
|
// CRegistrySettings destructor
|
|
//
|
|
|
|
CRegistrySettings::~CRegistrySettings()
|
|
{
|
|
//
|
|
// Close the registry
|
|
//
|
|
|
|
if (_hkVideoReg) {
|
|
RegCloseKey(_hkVideoReg);
|
|
}
|
|
|
|
//
|
|
// Free the strings
|
|
//
|
|
if (_pszKeyName) {
|
|
LocalFree(_pszKeyName);
|
|
}
|
|
|
|
if ((_pszKeyName != _pszDrvName) && _pszDrvName) {
|
|
LocalFree(_pszDrvName);
|
|
}
|
|
|
|
if(_pszDeviceInstanceId) {
|
|
LocalFree(_pszDeviceInstanceId);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Method to get the hardware information fields.
|
|
//
|
|
|
|
VOID
|
|
CRegistrySettings::GetHardwareInformation(
|
|
PDISPLAY_REGISTRY_HARDWARE_INFO pInfo)
|
|
{
|
|
|
|
DWORD cb, dwType;
|
|
DWORD i;
|
|
LONG lRet;
|
|
|
|
LPWSTR pKeyNames[5] = {
|
|
L"HardwareInformation.MemorySize",
|
|
L"HardwareInformation.ChipType",
|
|
L"HardwareInformation.DacType",
|
|
L"HardwareInformation.AdapterString",
|
|
L"HardwareInformation.BiosString"
|
|
};
|
|
|
|
ZeroMemory(pInfo, sizeof(DISPLAY_REGISTRY_HARDWARE_INFO));
|
|
|
|
//
|
|
// Query each entry one after the other.
|
|
//
|
|
|
|
for (i = 0; i < 5; i++) {
|
|
|
|
//
|
|
// query the size of the string
|
|
//
|
|
|
|
cb = 256;
|
|
lRet = RegQueryValueExW(_hkVideoReg,
|
|
pKeyNames[i],
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&cb);
|
|
|
|
if (lRet == ERROR_SUCCESS) {
|
|
|
|
if (i == 0) {
|
|
|
|
ULONG mem;
|
|
|
|
cb = 4;
|
|
|
|
RegQueryValueExW(_hkVideoReg,
|
|
pKeyNames[i],
|
|
NULL,
|
|
&dwType,
|
|
(PUCHAR) (&mem),
|
|
&cb);
|
|
|
|
//
|
|
// If we queried the memory size, we actually have
|
|
// a DWORD. Transform the DWORD to a string
|
|
//
|
|
|
|
// Divide down to Ks
|
|
|
|
mem = mem >> 10;
|
|
|
|
// if a MB multiple, divide again.
|
|
|
|
if ((mem & 0x3FF) != 0) {
|
|
|
|
wsprintf((LPWSTR)pInfo, L"%d KB", mem );
|
|
|
|
} else {
|
|
|
|
wsprintf((LPWSTR)pInfo, L"%d MB", mem >> 10 );
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cb = 256;
|
|
|
|
//
|
|
// get the string
|
|
//
|
|
|
|
RegQueryValueExW(_hkVideoReg,
|
|
pKeyNames[i],
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE) pInfo,
|
|
&cb);
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Put in the default string
|
|
//
|
|
|
|
LoadString(hInstance,
|
|
IDS_UNAVAILABLE,
|
|
(LPWSTR)pInfo,
|
|
256);
|
|
}
|
|
|
|
pInfo = (PDISPLAY_REGISTRY_HARDWARE_INFO)((PUCHAR)pInfo + 256);
|
|
}
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID CRegistrySettings::InitDeviceInstanceID(
|
|
LPTSTR pstrDeviceKey
|
|
)
|
|
{
|
|
HDEVINFO hDevInfo = INVALID_HANDLE_VALUE ;
|
|
SP_DEVINFO_DATA DevInfoData;
|
|
ULONG InstanceIDSize = 0;
|
|
BOOL bSuccess = FALSE;
|
|
LPWSTR pwInterfaceName = NULL;
|
|
LPWSTR pwInstanceID = NULL;
|
|
|
|
ASSERT (pstrDeviceKey != NULL);
|
|
ASSERT (_pszDeviceInstanceId == NULL);
|
|
|
|
if (AllocAndReadInterfaceName(pstrDeviceKey, &pwInterfaceName)) {
|
|
|
|
bSuccess = GetDevInfoDataFromInterfaceName(pwInterfaceName,
|
|
&hDevInfo,
|
|
&DevInfoData);
|
|
if (bSuccess) {
|
|
|
|
InstanceIDSize = 0;
|
|
|
|
bSuccess =
|
|
|
|
((CM_Get_Device_ID_Size(&InstanceIDSize,
|
|
DevInfoData.DevInst,
|
|
0) == CR_SUCCESS) &&
|
|
|
|
((_pszDeviceInstanceId = (LPTSTR)LocalAlloc(LPTR,
|
|
(InstanceIDSize + 1) * sizeof(TCHAR))) != NULL) &&
|
|
|
|
(CM_Get_Device_ID(DevInfoData.DevInst,
|
|
_pszDeviceInstanceId,
|
|
InstanceIDSize,
|
|
0) == CR_SUCCESS));
|
|
|
|
if (!bSuccess) {
|
|
|
|
//
|
|
// Clean-up
|
|
//
|
|
|
|
if (NULL != _pszDeviceInstanceId) {
|
|
LocalFree(_pszDeviceInstanceId);
|
|
_pszDeviceInstanceId = NULL;
|
|
}
|
|
}
|
|
|
|
SetupDiDestroyDeviceInfoList(hDevInfo);
|
|
}
|
|
|
|
LocalFree(pwInterfaceName);
|
|
}
|
|
|
|
if ((!bSuccess) &&
|
|
AllocAndReadInstanceID(pstrDeviceKey, &pwInstanceID)) {
|
|
|
|
#ifdef UNICODE
|
|
_pszDeviceInstanceId = pwInstanceID;
|
|
#else
|
|
SIZE_T cch = wcslen(pwInstanceID) + 1;
|
|
_pszDeviceInstanceId = LocalAlloc(LPTR, cch);
|
|
if (_pszDeviceInstanceId != NULL) {
|
|
WideCharToMultiByte(CP_ACP, 0,
|
|
pwInstanceID, -1,
|
|
_pszDeviceInstanceId,
|
|
cch, NULL, NULL);
|
|
}
|
|
|
|
LocalFree(pwInstanceID);
|
|
#endif
|
|
|
|
}
|
|
|
|
} // InitDeviceInstanceID
|
|
|
|
|
|
BOOL
|
|
CRegistrySettings::GetDevInfoDataFromInterfaceName(
|
|
IN LPWSTR pwInterfaceName,
|
|
OUT HDEVINFO* phDevInfo,
|
|
OUT PSP_DEVINFO_DATA pDevInfoData
|
|
)
|
|
|
|
/*
|
|
|
|
Note: If this function retuns success, the caller is responsible
|
|
to destroy the device info list returned in phDevInfo
|
|
|
|
*/
|
|
|
|
{
|
|
LPWSTR pwDevicePath = NULL;
|
|
HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
|
|
SP_DEVINFO_DATA DevInfoData;
|
|
SP_DEVICE_INTERFACE_DATA InterfaceData;
|
|
PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = NULL;
|
|
DWORD InterfaceIndex = 0;
|
|
DWORD InterfaceSize = 0;
|
|
BOOL bMatch = FALSE;
|
|
|
|
ASSERT (pwInterfaceName != NULL);
|
|
ASSERT (phDevInfo != NULL);
|
|
ASSERT (pDevInfoData != NULL);
|
|
|
|
//
|
|
// Enumerate all display adapter interfaces
|
|
//
|
|
|
|
hDevInfo = SetupDiGetClassDevs(&GUID_DISPLAY_ADAPTER_INTERFACE,
|
|
NULL,
|
|
NULL,
|
|
DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
|
|
|
|
if (hDevInfo == INVALID_HANDLE_VALUE) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
InterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
|
while (SetupDiEnumDeviceInterfaces(hDevInfo,
|
|
NULL,
|
|
&GUID_DISPLAY_ADAPTER_INTERFACE,
|
|
InterfaceIndex,
|
|
&InterfaceData)) {
|
|
|
|
//
|
|
// Get the required size for the interface
|
|
//
|
|
|
|
InterfaceSize = 0;
|
|
SetupDiGetDeviceInterfaceDetail(hDevInfo,
|
|
&InterfaceData,
|
|
NULL,
|
|
0,
|
|
&InterfaceSize,
|
|
NULL);
|
|
|
|
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Alloc memory for the interface
|
|
//
|
|
|
|
pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)
|
|
LocalAlloc(LPTR, InterfaceSize);
|
|
if (pInterfaceDetailData == NULL)
|
|
goto Cleanup;
|
|
|
|
//
|
|
// Get the interface
|
|
//
|
|
|
|
pInterfaceDetailData->cbSize =
|
|
sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
|
|
DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
|
|
|
if (SetupDiGetDeviceInterfaceDetail(hDevInfo,
|
|
&InterfaceData,
|
|
pInterfaceDetailData,
|
|
InterfaceSize,
|
|
&InterfaceSize,
|
|
&DevInfoData)) {
|
|
|
|
//
|
|
// Is the InterfaceName the same as the DevicePath?
|
|
//
|
|
|
|
#ifdef UNICODE
|
|
pwDevicePath = pInterfaceDetailData->DevicePath;
|
|
#else
|
|
{
|
|
SIZE_T cch = strlen(pInterfaceDetailData->DevicePath) + 1;
|
|
pwDevicePath = LocalAlloc(LPTR, cch * sizeof(WCHAR));
|
|
if (pwDevicePath == NULL) {
|
|
goto Cleanup;
|
|
}
|
|
MultiByteToWideChar(CP_ACP, 0,
|
|
pInterfaceDetailData->DevicePath,
|
|
-1, pwDevicePath, cch);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// The first 4 characters of the interface name are different
|
|
// between user mode and kernel mode (e.g. "\\?\" vs "\\.\")
|
|
// Therefore, ignore them.
|
|
//
|
|
|
|
bMatch = (_wcsnicmp(pwInterfaceName + 4,
|
|
pwDevicePath + 4,
|
|
wcslen(pwInterfaceName + 4)) == 0);
|
|
|
|
#ifndef UNICODE
|
|
LocalFree(pwDevicePath);
|
|
pwDevicePath = NULL;
|
|
#endif
|
|
|
|
if (bMatch) {
|
|
|
|
//
|
|
// We found the device
|
|
//
|
|
|
|
*phDevInfo = hDevInfo;
|
|
CopyMemory(pDevInfoData, &DevInfoData, sizeof(SP_DEVINFO_DATA));
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Clean-up
|
|
//
|
|
|
|
LocalFree(pInterfaceDetailData);
|
|
pInterfaceDetailData = NULL;
|
|
|
|
//
|
|
// Next interface ...
|
|
//
|
|
|
|
InterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
|
++InterfaceIndex;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if (pInterfaceDetailData != NULL) {
|
|
LocalFree(pInterfaceDetailData);
|
|
}
|
|
|
|
//
|
|
// Upon success, the caller is responsible to destroy the list
|
|
//
|
|
|
|
if (!bMatch && (hDevInfo != INVALID_HANDLE_VALUE)) {
|
|
SetupDiDestroyDeviceInfoList(hDevInfo);
|
|
}
|
|
|
|
return bMatch;
|
|
}
|
|
|
|
|
|
#endif // WINNT
|
|
|
|
|