mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 04:34:48 +00:00
- Fix for issue https://github.com/GarageGames/Torque3D/issues/226 - Also extended the card profile reporting to the console to include the graphic card's VRAM.
612 lines
19 KiB
C++
612 lines
19 KiB
C++
//-----------------------------------------------------------------------------
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
// IN THE SOFTWARE.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#define _WIN32_DCOM
|
|
|
|
//#include <comdef.h>
|
|
#include <wbemidl.h>
|
|
//#include <atlconv.h>
|
|
#pragma comment(lib, "comsuppw.lib")
|
|
#pragma comment(lib, "wbemuuid.lib")
|
|
|
|
#include "platformWin32/videoInfo/wmiVideoInfo.h"
|
|
#include "core/util/safeRelease.h"
|
|
#include "console/console.h"
|
|
|
|
// http://www.spectranaut.net/sourcecode/WMI.cpp
|
|
|
|
// Add constructor to GUID.
|
|
struct MYGUID : public GUID
|
|
{
|
|
MYGUID( DWORD a, SHORT b, SHORT c, BYTE d, BYTE e, BYTE f, BYTE g, BYTE h, BYTE i, BYTE j, BYTE k )
|
|
{
|
|
Data1 = a;
|
|
Data2 = b;
|
|
Data3 = c;
|
|
Data4[ 0 ] = d;
|
|
Data4[ 1 ] = e;
|
|
Data4[ 2 ] = f;
|
|
Data4[ 3 ] = g;
|
|
Data4[ 4 ] = h;
|
|
Data4[ 5 ] = i;
|
|
Data4[ 6 ] = j;
|
|
Data4[ 7 ] = k;
|
|
}
|
|
};
|
|
|
|
//------------------------------------------------------------------------------
|
|
// DXGI decls for retrieving device info on Vista. We manually declare that
|
|
// stuff here, so we don't depend on headers and compile on any setup. At
|
|
// run-time, it depends on whether we can successfully load the DXGI DLL; if
|
|
// not, nothing of this here will be used.
|
|
|
|
struct IDXGIObject;
|
|
struct IDXGIFactory;
|
|
struct IDXGIAdapter;
|
|
struct IDXGIOutput;
|
|
|
|
struct DXGI_SWAP_CHAIN_DESC;
|
|
struct DXGI_ADAPTER_DESC;
|
|
|
|
struct IDXGIObject : public IUnknown
|
|
{
|
|
virtual HRESULT STDMETHODCALLTYPE SetPrivateData( REFGUID, UINT, const void* ) = 0;
|
|
virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( REFGUID, const IUnknown* ) = 0;
|
|
virtual HRESULT STDMETHODCALLTYPE GetPrivateData( REFGUID, UINT*, void* ) = 0;
|
|
virtual HRESULT STDMETHODCALLTYPE GetParent( REFIID, void** ) = 0;
|
|
};
|
|
|
|
struct IDXGIFactory : public IDXGIObject
|
|
{
|
|
virtual HRESULT STDMETHODCALLTYPE EnumAdapters( UINT, IDXGIAdapter** ) = 0;
|
|
virtual HRESULT STDMETHODCALLTYPE MakeWindowAssociation( HWND, UINT ) = 0;
|
|
virtual HRESULT STDMETHODCALLTYPE GetWindowAssociation( HWND ) = 0;
|
|
virtual HRESULT STDMETHODCALLTYPE CreateSwapChain( IUnknown*, DXGI_SWAP_CHAIN_DESC* ) = 0;
|
|
virtual HRESULT STDMETHODCALLTYPE CreateSoftwareAdapter( HMODULE, IDXGIAdapter** ) = 0;
|
|
};
|
|
|
|
struct IDXGIAdapter : public IDXGIObject
|
|
{
|
|
virtual HRESULT STDMETHODCALLTYPE EnumOutputs( UINT, IDXGIOutput** ) = 0;
|
|
virtual HRESULT STDMETHODCALLTYPE GetDesc( DXGI_ADAPTER_DESC* ) = 0;
|
|
virtual HRESULT STDMETHODCALLTYPE CheckInterfaceSupport( REFGUID, LARGE_INTEGER* ) = 0;
|
|
};
|
|
|
|
struct DXGI_ADAPTER_DESC
|
|
{
|
|
WCHAR Description[ 128 ];
|
|
UINT VendorId;
|
|
UINT DeviceId;
|
|
UINT SubSysId;
|
|
UINT Revision;
|
|
SIZE_T DedicatedVideoMemory;
|
|
SIZE_T DedicatedSystemMemory;
|
|
SIZE_T SharedSystemMemory;
|
|
LUID AdapterLuid;
|
|
};
|
|
|
|
static MYGUID IID_IDXGIFactory( 0x7b7166ec, 0x21c7, 0x44ae, 0xb2, 0x1a, 0xc9, 0xae, 0x32, 0x1a, 0xe3, 0x69 );
|
|
|
|
//------------------------------------------------------------------------------
|
|
// DXDIAG declarations.
|
|
|
|
struct DXDIAG_INIT_PARAMS
|
|
{
|
|
DWORD dwSize;
|
|
DWORD dwDxDiagHeaderVersion;
|
|
BOOL bAllowWHQLChecks;
|
|
LPVOID pReserved;
|
|
};
|
|
|
|
struct IDxDiagContainer : public IUnknown
|
|
{
|
|
virtual HRESULT STDMETHODCALLTYPE GetNumberOfChildContainers( DWORD* pdwCount ) = 0;
|
|
virtual HRESULT STDMETHODCALLTYPE EnumChildContainerNames( DWORD dwIndex, LPWSTR pwszContainer, DWORD cchContainer ) = 0;
|
|
virtual HRESULT STDMETHODCALLTYPE GetChildContainer( LPCWSTR pwszContainer, IDxDiagContainer** ppInstance ) = 0;
|
|
virtual HRESULT STDMETHODCALLTYPE GetNumberOfProps( DWORD* pdwCount ) = 0;
|
|
virtual HRESULT STDMETHODCALLTYPE EnumPropNames( DWORD dwIndex, LPWSTR pwszPropName, DWORD cchPropName ) = 0;
|
|
virtual HRESULT STDMETHODCALLTYPE GetProp( LPCWSTR pwszPropName, VARIANT* pvarProp ) = 0;
|
|
};
|
|
|
|
struct IDxDiagProvider : public IUnknown
|
|
{
|
|
virtual HRESULT STDMETHODCALLTYPE Initialize( DXDIAG_INIT_PARAMS* pParams ) = 0;
|
|
virtual HRESULT STDMETHODCALLTYPE GetRootContainer( IDxDiagContainer** ppInstance ) = 0;
|
|
};
|
|
|
|
static MYGUID CLSID_DxDiagProvider( 0xA65B8071, 0x3BFE, 0x4213, 0x9A, 0x5B, 0x49, 0x1D, 0xA4, 0x46, 0x1C, 0xA7 );
|
|
static MYGUID IID_IDxDiagProvider( 0x9C6B4CB0, 0x23F8, 0x49CC, 0xA3, 0xED, 0x45, 0xA5, 0x50, 0x00, 0xA6, 0xD2 );
|
|
static MYGUID IID_IDxDiagContainer( 0x7D0F462F, 0x4064, 0x4862, 0xBC, 0x7F, 0x93, 0x3E, 0x50, 0x58, 0xC1, 0x0F );
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
WCHAR *WMIVideoInfo::smPVIQueryTypeToWMIString [] =
|
|
{
|
|
L"MaxNumberControlled", //PVI_NumDevices
|
|
L"Description", //PVI_Description
|
|
L"Name", //PVI_Name
|
|
L"VideoProcessor", //PVI_ChipSet
|
|
L"DriverVersion", //PVI_DriverVersion
|
|
L"AdapterRAM", //PVI_VRAM
|
|
};
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
WMIVideoInfo::WMIVideoInfo()
|
|
: PlatformVideoInfo(),
|
|
mLocator( NULL ),
|
|
mServices( NULL ),
|
|
mComInitialized( false ),
|
|
mDXGIModule( NULL ),
|
|
mDXGIFactory( NULL ),
|
|
mDxDiagProvider( NULL )
|
|
{
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
WMIVideoInfo::~WMIVideoInfo()
|
|
{
|
|
SAFE_RELEASE( mLocator );
|
|
SAFE_RELEASE( mServices );
|
|
|
|
if( mDxDiagProvider )
|
|
SAFE_RELEASE( mDxDiagProvider );
|
|
|
|
if( mDXGIFactory )
|
|
SAFE_RELEASE( mDXGIFactory );
|
|
if( mDXGIModule )
|
|
FreeLibrary( ( HMODULE ) mDXGIModule );
|
|
|
|
if( mComInitialized )
|
|
CoUninitialize();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
bool WMIVideoInfo::_initialize()
|
|
{
|
|
// Init COM
|
|
HRESULT hr = CoInitialize( NULL );
|
|
mComInitialized = SUCCEEDED( hr );
|
|
|
|
if( !mComInitialized )
|
|
return false;
|
|
|
|
bool success = false;
|
|
|
|
success |= _initializeDXGI();
|
|
success |= _initializeDxDiag();
|
|
success |= _initializeWMI();
|
|
|
|
return success;
|
|
}
|
|
|
|
bool WMIVideoInfo::_initializeWMI()
|
|
{
|
|
//// Set security levels
|
|
//hr = CoInitializeSecurity(
|
|
// NULL,
|
|
// -1, // COM authentication
|
|
// NULL, // Authentication services
|
|
// NULL, // Reserved
|
|
// RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
|
|
// RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
|
|
// NULL, // Authentication info
|
|
// EOAC_NONE, // Additional capabilities
|
|
// NULL // Reserved
|
|
// );
|
|
|
|
//if( FAILED( hr ) )
|
|
//{
|
|
// Con::errorf( "WMIVideoInfo: Failed to initialize com security." );
|
|
// return false;
|
|
//}
|
|
|
|
// Obtain the locator to WMI
|
|
HRESULT hr = CoCreateInstance(
|
|
CLSID_WbemLocator,
|
|
0,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IWbemLocator,
|
|
(void**)&mLocator
|
|
);
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
Con::errorf( "WMIVideoInfo: Failed to create instance of IID_IWbemLocator." );
|
|
return false;
|
|
}
|
|
|
|
// Connect to the root\cimv2 namespace with
|
|
// the current user and obtain pointer pSvc
|
|
// to make IWbemServices calls.
|
|
hr = mLocator->ConnectServer(
|
|
BSTR(L"ROOT\\CIMV2"), // Object path of WMI namespace
|
|
NULL, // User name. NULL = current user
|
|
NULL, // User password. NULL = current
|
|
0, // Locale. NULL indicates current
|
|
NULL, // Security flags.
|
|
0, // Authority (e.g. Kerberos)
|
|
0, // Context object
|
|
&mServices // pointer to IWbemServices proxy
|
|
);
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
Con::errorf( "WMIVideoInfo: Connect server failed." );
|
|
return false;
|
|
}
|
|
|
|
|
|
// Set security levels on the proxy
|
|
hr = CoSetProxyBlanket(
|
|
mServices, // Indicates the proxy to set
|
|
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
|
|
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
|
|
NULL, // Server principal name
|
|
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
|
|
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
|
|
NULL, // client identity
|
|
EOAC_NONE // proxy capabilities
|
|
);
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
Con::errorf( "WMIVideoInfo: CoSetProxyBlanket failed" );
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool WMIVideoInfo::_initializeDXGI()
|
|
{
|
|
// Try going for DXGI. Will only succeed on Vista.
|
|
#if 0
|
|
mDXGIModule = ( HMODULE ) LoadLibrary( L"dxgi.dll" );
|
|
if( mDXGIModule != 0 )
|
|
{
|
|
typedef HRESULT (* CreateDXGIFactoryFuncType )( REFIID, void** );
|
|
CreateDXGIFactoryFuncType factoryFunction =
|
|
( CreateDXGIFactoryFuncType ) GetProcAddress( ( HMODULE ) mDXGIModule, "CreateDXGIFactory" );
|
|
|
|
if( factoryFunction && factoryFunction( IID_IDXGIFactory, ( void** ) &mDXGIFactory ) == S_OK )
|
|
return true;
|
|
else
|
|
{
|
|
FreeLibrary( ( HMODULE ) mDXGIModule );
|
|
mDXGIModule = 0;
|
|
}
|
|
}
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
bool WMIVideoInfo::_initializeDxDiag()
|
|
{
|
|
if( CoCreateInstance( CLSID_DxDiagProvider, NULL, CLSCTX_INPROC_SERVER, IID_IDxDiagProvider, ( void** ) &mDxDiagProvider ) == S_OK )
|
|
{
|
|
DXDIAG_INIT_PARAMS params;
|
|
dMemset( ¶ms, 0, sizeof( DXDIAG_INIT_PARAMS ) );
|
|
|
|
params.dwSize = sizeof( DXDIAG_INIT_PARAMS );
|
|
params.dwDxDiagHeaderVersion = 111;
|
|
params.bAllowWHQLChecks = false;
|
|
|
|
HRESULT result = mDxDiagProvider->Initialize( ¶ms );
|
|
if( result != S_OK )
|
|
{
|
|
Con::errorf( "WMIVideoInfo: DxDiag initialization failed (%i)", result );
|
|
SAFE_RELEASE( mDxDiagProvider );
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
Con::printf( "WMIVideoInfo: DxDiag initialized" );
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// http://msdn2.microsoft.com/en-us/library/aa394512.aspx
|
|
//
|
|
// The Win32_VideoController WMI class represents the capabilities and management capacity of the
|
|
// video controller on a computer system running Windows.
|
|
//
|
|
// Starting with Windows Vista, hardware that is not compatible with Windows Display Driver Model (WDDM)
|
|
// returns inaccurate property values for instances of this class.
|
|
//
|
|
// Windows Server 2003, Windows XP, Windows 2000, and Windows NT 4.0: This class is supported.
|
|
//------------------------------------------------------------------------------
|
|
|
|
bool WMIVideoInfo::_queryProperty( const PVIQueryType queryType, const U32 adapterId, String *outValue )
|
|
{
|
|
if( _queryPropertyDXGI( queryType, adapterId, outValue ) )
|
|
return true;
|
|
else if( _queryPropertyDxDiag( queryType, adapterId, outValue ) )
|
|
return true;
|
|
else
|
|
return _queryPropertyWMI( queryType, adapterId, outValue );
|
|
}
|
|
|
|
bool WMIVideoInfo::_queryPropertyDxDiag( const PVIQueryType queryType, const U32 adapterId, String *outValue )
|
|
{
|
|
if( mDxDiagProvider != 0 )
|
|
{
|
|
IDxDiagContainer* rootContainer = 0;
|
|
IDxDiagContainer* displayDevicesContainer = 0;
|
|
IDxDiagContainer* deviceContainer = 0;
|
|
|
|
// Special case to deal with PVI_NumAdapters
|
|
if(queryType == PVI_NumAdapters)
|
|
{
|
|
DWORD count = 0;
|
|
String value;
|
|
|
|
if( mDxDiagProvider->GetRootContainer( &rootContainer ) == S_OK
|
|
&& rootContainer->GetChildContainer( L"DxDiag_DisplayDevices", &displayDevicesContainer ) == S_OK
|
|
&& displayDevicesContainer->GetNumberOfChildContainers( &count ) == S_OK )
|
|
{
|
|
value = String::ToString("%d", count);
|
|
}
|
|
|
|
if( rootContainer )
|
|
SAFE_RELEASE( rootContainer );
|
|
if( displayDevicesContainer )
|
|
SAFE_RELEASE( displayDevicesContainer );
|
|
|
|
*outValue = value;
|
|
return true;
|
|
}
|
|
|
|
WCHAR adapterIdString[ 2 ];
|
|
adapterIdString[ 0 ] = L'0' + adapterId;
|
|
adapterIdString[ 1 ] = L'\0';
|
|
|
|
String value;
|
|
if( mDxDiagProvider->GetRootContainer( &rootContainer ) == S_OK
|
|
&& rootContainer->GetChildContainer( L"DxDiag_DisplayDevices", &displayDevicesContainer ) == S_OK
|
|
&& displayDevicesContainer->GetChildContainer( adapterIdString, &deviceContainer ) == S_OK )
|
|
{
|
|
const WCHAR* propertyName = 0;
|
|
|
|
switch( queryType )
|
|
{
|
|
case PVI_Description:
|
|
propertyName = L"szDescription";
|
|
break;
|
|
|
|
case PVI_Name:
|
|
propertyName = L"szDeviceName";
|
|
break;
|
|
|
|
case PVI_ChipSet:
|
|
propertyName = L"szChipType";
|
|
break;
|
|
|
|
case PVI_DriverVersion:
|
|
propertyName = L"szDriverVersion";
|
|
break;
|
|
|
|
// Don't get VRAM via DxDiag as that won't tell us about the actual amount of dedicated
|
|
// video memory but rather some dedicated+shared RAM value.
|
|
}
|
|
|
|
if( propertyName )
|
|
{
|
|
VARIANT val;
|
|
if( deviceContainer->GetProp( propertyName, &val ) == S_OK )
|
|
switch( val.vt )
|
|
{
|
|
case VT_BSTR:
|
|
value = String( val.bstrVal );
|
|
break;
|
|
|
|
default:
|
|
AssertWarn( false, avar( "WMIVideoInfo: property type '%i' not implemented", val.vt ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
if( rootContainer )
|
|
SAFE_RELEASE( rootContainer );
|
|
if( displayDevicesContainer )
|
|
SAFE_RELEASE( displayDevicesContainer );
|
|
if( deviceContainer )
|
|
SAFE_RELEASE( deviceContainer );
|
|
|
|
if( value.isNotEmpty() )
|
|
{
|
|
// Try to get the DxDiag data into some canonical form. Otherwise, we
|
|
// won't be giving the card profiler much opportunity for matching up
|
|
// its data with profile scripts.
|
|
|
|
switch( queryType )
|
|
{
|
|
case PVI_ChipSet:
|
|
if( value.compare( "ATI", 3, String::NoCase ) == 0 )
|
|
value = "ATI Technologies Inc.";
|
|
else if( value.compare( "NVIDIA", 6, String::NoCase ) == 0 )
|
|
value = "NVIDIA";
|
|
else if( value.compare( "INTEL", 5, String::NoCase ) == 0 )
|
|
value = "INTEL";
|
|
else if( value.compare( "MATROX", 6, String::NoCase ) == 0 )
|
|
value = "MATROX";
|
|
break;
|
|
|
|
case PVI_Description:
|
|
if( value.compare( "ATI ", 4, String::NoCase ) == 0 )
|
|
{
|
|
value = value.substr( 4, value.length() - 4 );
|
|
if( value.compare( " Series", 7, String::NoCase | String::Right ) == 0 )
|
|
value = value.substr( 0, value.length() - 7 );
|
|
}
|
|
else if( value.compare( "NVIDIA ", 7, String::NoCase ) == 0 )
|
|
value = value.substr( 7, value.length() - 7 );
|
|
else if( value.compare( "INTEL ", 6, String::NoCase ) == 0 )
|
|
value = value.substr( 6, value.length() - 6 );
|
|
else if( value.compare( "MATROX ", 7, String::NoCase ) == 0 )
|
|
value = value.substr( 7, value.length() - 7 );
|
|
break;
|
|
}
|
|
|
|
*outValue = value;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool WMIVideoInfo::_queryPropertyDXGI( const PVIQueryType queryType, const U32 adapterId, String *outValue )
|
|
{
|
|
#if 0
|
|
if( mDXGIFactory )
|
|
{
|
|
IDXGIAdapter* adapter;
|
|
if( mDXGIFactory->EnumAdapters( adapterId, &adapter ) != S_OK )
|
|
return false;
|
|
|
|
DXGI_ADAPTER_DESC desc;
|
|
if( adapter->GetDesc( &desc ) != S_OK )
|
|
{
|
|
adapter->Release();
|
|
return false;
|
|
}
|
|
|
|
String value;
|
|
switch( queryType )
|
|
{
|
|
case PVI_Description:
|
|
value = String( desc.Description );
|
|
break;
|
|
|
|
case PVI_Name:
|
|
value = String( avar( "%i", desc.DeviceId ) );
|
|
break;
|
|
|
|
case PVI_VRAM:
|
|
value = String( avar( "%i", desc.DedicatedVideoMemory / 1048576 ) );
|
|
break;
|
|
|
|
//RDTODO
|
|
}
|
|
|
|
adapter->Release();
|
|
*outValue = value;
|
|
return true;
|
|
}
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
bool WMIVideoInfo::_queryPropertyWMI( const PVIQueryType queryType, const U32 adapterId, String *outValue )
|
|
{
|
|
if( mServices == NULL )
|
|
return false;
|
|
|
|
BSTR bstrWQL = SysAllocString(L"WQL");
|
|
BSTR bstrPath = SysAllocString(L"select * from Win32_VideoController");
|
|
IEnumWbemClassObject* enumerator;
|
|
|
|
// Use the IWbemServices pointer to make requests of WMI
|
|
HRESULT hr = mServices->ExecQuery(bstrWQL, bstrPath, WBEM_FLAG_FORWARD_ONLY, NULL, &enumerator);
|
|
|
|
if( FAILED( hr ) )
|
|
return false;
|
|
|
|
IWbemClassObject *adapter = NULL;
|
|
ULONG uReturned;
|
|
|
|
// Get the appropriate adapter.
|
|
for ( S32 i = 0; i <= adapterId; i++ )
|
|
{
|
|
hr = enumerator->Next(WBEM_INFINITE, 1, &adapter, &uReturned );
|
|
|
|
if ( FAILED( hr ) || uReturned == 0 )
|
|
{
|
|
enumerator->Release();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Now get the property
|
|
VARIANT v;
|
|
hr = adapter->Get( smPVIQueryTypeToWMIString[queryType], 0, &v, NULL, NULL );
|
|
|
|
bool result = SUCCEEDED( hr );
|
|
|
|
if ( result )
|
|
{
|
|
switch( v.vt )
|
|
{
|
|
case VT_I4:
|
|
{
|
|
LONG longVal = v.lVal;
|
|
|
|
if( queryType == PVI_VRAM )
|
|
{
|
|
longVal = longVal >> 20; // Convert to megabytes
|
|
|
|
// While this value is reported as a signed integer, it is possible
|
|
// for video cards to have 2GB or more. In those cases the signed
|
|
// bit is set and will give us a negative number. Treating this
|
|
// as unsigned will allows us to handle video cards with up to
|
|
// 4GB of memory. After that we'll need a new solution from Microsoft.
|
|
*outValue = String::ToString( (U32)longVal );
|
|
}
|
|
else
|
|
{
|
|
*outValue = String::ToString( (S32)longVal );
|
|
}
|
|
break;
|
|
}
|
|
|
|
case VT_UI4:
|
|
{
|
|
*outValue = String::ToString( (U32)v.ulVal );
|
|
break;
|
|
}
|
|
|
|
case VT_BSTR:
|
|
{
|
|
*outValue = String( v.bstrVal );
|
|
break;
|
|
}
|
|
case VT_LPSTR:
|
|
case VT_LPWSTR:
|
|
break;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
// Cleanup
|
|
adapter->Release();
|
|
enumerator->Release();
|
|
|
|
return result;
|
|
} |