/**************************************************************************\ * 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 "priv.h" #include #include "ntreg.hxx" #include // // CRegistrySettings constructor // CRegistrySettings::CRegistrySettings(LPTSTR pstrDeviceKey) : _hkVideoReg(NULL) , _pszDrvName(NULL) , _pszKeyName(NULL) , _pszDeviceInstanceId(NULL) , _dwDevInst(0) { 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(HINST_THISDLL, 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) { _dwDevInst = DevInfoData.DevInst; } else { // // 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; } HKEY CRegistrySettings::OpenDrvRegKey() { HKEY hkDriver = (HKEY)INVALID_HANDLE_VALUE; HDEVINFO hDevInfo = INVALID_HANDLE_VALUE; SP_DEVINFO_DATA did; DWORD index = 0; if (_dwDevInst == 0) { goto Fallout; } hDevInfo = SetupDiGetClassDevs((LPGUID) &GUID_DEVCLASS_DISPLAY, NULL, NULL, 0); if (hDevInfo == INVALID_HANDLE_VALUE) { goto Fallout; } ZeroMemory(&did, sizeof(SP_DEVINFO_DATA)); did.cbSize = sizeof(SP_DEVINFO_DATA); while (SetupDiEnumDeviceInfo(hDevInfo, index, &did)) { if (did.DevInst == _dwDevInst) { hkDriver = SetupDiOpenDevRegKey(hDevInfo, &did, DICS_FLAG_GLOBAL, 0, DIREG_DRV , KEY_ALL_ACCESS); break; } did.cbSize = sizeof(SP_DEVINFO_DATA); index++; } Fallout: if (hDevInfo != INVALID_HANDLE_VALUE) { SetupDiDestroyDeviceInfoList(hDevInfo); } return hkDriver; }