Fusion360-Addons/usr/Src/Core/3D/DXDiagNVUtil.cpp
2021-10-31 19:39:29 +01:00

771 lines
24 KiB
C++

/*********************************************************************NVMH4****
Path: SDK\LIBS\src\NV_D3DCommon
File: DXDiagNVUtil.cpp
Copyright NVIDIA Corporation 2002
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED
*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS
BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES
WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS)
ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
Comments:
See the DXDiagNVUtil.h file for additional comments
******************************************************************************/
#define INITGUID // to define _CLSID_DxDiagProvider, _IID_IDxDiagProvider
#include "3d\DxDiagNVUtil.h"
#include <io.h> // for _filelength()
#include <direct.h> // for getcwd()
#include <stdio.h> // for L text macro
#include <dxdiag.h>
#include <math.h>
#pragma comment( lib, "dxguid.lib" )
// use #if 1 to turn trace messages on
#if 0
#define TRACE0(v) v
#else
#define TRACE0(v) {}
#endif
// use as an alternative to wcstombs()
string DXDiagNVUtil::WStringToString( const wstring * in_pwstring )
{
if( in_pwstring == NULL )
return( "" );
return( lpcwstrToString( in_pwstring->c_str() ));
}
string DXDiagNVUtil::WStringToString( wstring & in_wstring )
{
return( lpcwstrToString( in_wstring.c_str() ));
}
string DXDiagNVUtil::lpcwstrToString( const LPCWSTR in_lpcwstr )
{
//@ consider using windows.h WideCharToMultiByte(..)
char * mbBuf;
size_t sz;
sz = 2 * wcslen( in_lpcwstr );
mbBuf = new char[sz];
wcstombs( mbBuf, in_lpcwstr, sz ); // convert the string
string outstr;
outstr = mbBuf;
SAFE_ARRAY_DELETE( mbBuf );
return( outstr );
}
HRESULT DXDiagNVUtil::GetChildByIndex( IDxDiagContainer * pParent,
DWORD dwIndex,
IDxDiagContainer ** ppChild )
{
HRESULT hr = S_OK;
FAIL_IF_NULL( pParent );
FAIL_IF_NULL( ppChild );
// We need to look up the child by name, not by index, so first
// get the name of the child at the appropriate index.
// Get a single child container name, writing the name to wstr
WCHAR wstr[256];
hr = pParent->EnumChildContainerNames( dwIndex, wstr, 256 );
RET_VAL_IF_FAILED( hr );
// Now get the child container by name
hr = pParent->GetChildContainer( wstr, ppChild );
return( hr );
}
HRESULT DXDiagNVUtil::GetNumDisplayDevices( DWORD * out_pdwNumAdapters )
{
HRESULT hr = S_OK;
MSGVARNAME_AND_FAIL_IF_NULL( m_pDxDiagRoot );
MSGVARNAME_AND_FAIL_IF_NULL( out_pdwNumAdapters );
IDxDiagContainer * pChild;
hr = GetChildContainer( L"DxDiag_DisplayDevices", & pChild );
MSG_AND_RET_VAL_IF( FAILED(hr), "GetNumDisplayDevices() Couldn't get display devices container!\n", hr );
hr = pChild->GetNumberOfChildContainers( out_pdwNumAdapters );
MSG_AND_BREAK_IF( FAILED(hr), "GetNumDisplayDevices() Couldn't get number of child containers!\n" );
SAFE_RELEASE( pChild );
return( hr );
}
HRESULT DXDiagNVUtil::GetDisplayDeviceNode( DWORD dwDeviceIndex, IDxDiagContainer ** ppNode )
{
// fill *ppNode with pointer to the display device at index nDevice of the DXDiag_DisplayDevices container
// you must SAFE_RELEASE( *ppNode ) outside of this function.
HRESULT hr = S_OK;
FAIL_IF_NULL( ppNode );
IDxDiagContainer * pDevicesNode;
hr = GetChildContainer( L"DxDiag_DisplayDevices", & pDevicesNode );
MSG_AND_RET_VAL_IF( FAILED(hr), "GetDisplayDeviceNode() couldn't get devices node!\n", hr );
// Get the device at the appropriate index
hr = GetChildByIndex( pDevicesNode, dwDeviceIndex, ppNode );
SAFE_RELEASE( pDevicesNode );
return( hr );
}
HRESULT DXDiagNVUtil::GetDisplayDeviceDescription( DWORD dwDevice, wstring * pwstrName )
{
HRESULT hr = S_OK;
MSGVARNAME_AND_FAIL_IF_NULL( m_pDxDiagRoot );
MSGVARNAME_AND_FAIL_IF_NULL( pwstrName );
IDxDiagContainer * pDisplayDevice;
hr = GetDisplayDeviceNode( dwDevice, &pDisplayDevice );
RET_VAL_IF_FAILED( hr );
FAIL_IF_NULL( pDisplayDevice );
// Get the device's name:
hr = GetProperty( pDisplayDevice, L"szDescription", pwstrName );
MSG_IF( FAILED(hr), "GetDisplayDeviceName() Couldn't get device's name property!\n");
SAFE_RELEASE( pDisplayDevice );
return( hr );
}
HRESULT DXDiagNVUtil::GetDisplayDeviceNVDriverVersion( DWORD dwDevice, float * fVersion )
{
HRESULT hr = S_OK;
FAIL_IF_NULL( fVersion );
*fVersion = 0.0f;
wstring wstr;
hr = GetDisplayDeviceDriverVersionStr( dwDevice, & wstr );
MSG_IF( FAILED(hr), "GetDisplayDeviceNVDriverVersion() couldn't get driver version string\n");
RET_VAL_IF_FAILED(hr);
// nv driver string will be something like: "6.14.0010.5216"
// where the #s we care about are the last digits
size_t pos;
pos = wstr.find_last_of( '.' );
wstr.erase( 0, pos );
//FMsgW(L"wstr: %s\n", wstr.c_str() );
// decode the string
// multiply by 100 to convert .5216 into 52.16
*fVersion = (float) _wtof( wstr.c_str() ) * 100.0f;
return( hr );
}
HRESULT DXDiagNVUtil::GetDisplayDeviceDriverVersionStr( DWORD dwDevice, wstring * pwstrVers )
{
HRESULT hr = S_OK;
FAIL_IF_NULL( pwstrVers );
hr = GetDisplayDeviceProp( dwDevice, L"szDriverVersion", pwstrVers );
MSG_IF( FAILED(hr), "GetDisplayDeviceName() Couldn't get device's driver version string!\n");
return( hr );
}
HRESULT DXDiagNVUtil::GetDisplayDeviceMemoryInMB( DWORD dwDevice, int * pDisplayMemory )
{
HRESULT hr = S_OK;
FAIL_IF_NULL( pDisplayMemory );
*pDisplayMemory = 0;
wstring wstr;
hr = GetDisplayDeviceProp( dwDevice, L"szDisplayMemoryEnglish", &wstr );
MSG_IF( FAILED(hr), "GetDisplayDeviceMemoryInMB() Couldn't get the property string!\n");
// decode the value to an int
// assume 1st string is the integer number
int nMem;
int num_fields;
num_fields = swscanf( wstr.c_str(), L"%d", &nMem );
if( num_fields != 1 )
{
FMsg("GetDisplayDeviceMemoryInMB error scanning memory string description!\n");
return( E_FAIL );
}
*pDisplayMemory = nMem;
return( hr );
}
HRESULT DXDiagNVUtil::GetDisplayDeviceProp( DWORD dwDevice, LPCWSTR prop_name, wstring * pwstrProp )
{
HRESULT hr = S_OK;
FAIL_IF_NULL( prop_name );
FAIL_IF_NULL( pwstrProp );
*pwstrProp = L"";
IDxDiagContainer * pDisplayDevice;
hr = GetDisplayDeviceNode( dwDevice, &pDisplayDevice );
RET_VAL_IF_FAILED( hr );
FAIL_IF_NULL( pDisplayDevice );
hr = GetProperty( pDisplayDevice, prop_name, pwstrProp );
MSG_IF( FAILED(hr), "GetDisplayDeviceProp() Couldn't get the property string!\n");
return( hr );
}
HRESULT DXDiagNVUtil::GetPhysicalMemoryInMB( float * out_pfMemory )
{
HRESULT hr = S_OK;
FAIL_IF_NULL( out_pfMemory );
wstring property;
hr = GetProperty( L"DxDiag_SystemInfo", L"ullPhysicalMemory", &property );
float mem = (float) _wtof( property.c_str() );
// convert bytes to MB
mem = mem / (1024 * 1024);
*out_pfMemory = mem;
return( hr );
}
HRESULT DXDiagNVUtil::GetDisplayDeviceAGPMemoryStatus( DWORD dwDeviceIndex, wstring * pwstrAGPEnabled,
wstring * pwstrAGPExists, wstring * pwstrAGPStatus )
{
HRESULT hr = S_OK;
FAIL_IF_NULL( m_pDxDiagRoot );
FAIL_IF_NULL( pwstrAGPEnabled );
FAIL_IF_NULL( pwstrAGPExists );
FAIL_IF_NULL( pwstrAGPStatus );
*pwstrAGPEnabled = L"";
*pwstrAGPExists = L"";
*pwstrAGPStatus = L"";
hr = GetDisplayDeviceProp( dwDeviceIndex, L"bAGPEnabled", pwstrAGPEnabled );
hr = GetDisplayDeviceProp( dwDeviceIndex, L"szAGPStatusEnglish", pwstrAGPStatus );
wstring property;
hr = GetDisplayDeviceProp( dwDeviceIndex, L"bAGPExistenceValid", &property );
if( SUCCEEDED(hr) && property == L"true" )
{
hr = GetDisplayDeviceProp( dwDeviceIndex, L"bAGPExists", pwstrAGPExists );
}
return( hr );
}
HRESULT DXDiagNVUtil::GetDebugLevels( wstring * pwstrLevels )
{
HRESULT hr = S_OK;
FAIL_IF_NULL( pwstrLevels );
*pwstrLevels = L"";
wstring propval;
hr = GetProperty( L"DxDiag_SystemInfo", L"nD3DDebugLevel", &propval );
pwstrLevels->append( L"D3DDebugLevel = "); pwstrLevels->append( propval ); pwstrLevels->append(L"\n");
hr = GetProperty( L"DxDiag_SystemInfo", L"nDDrawDebugLevel", &propval );
pwstrLevels->append( L"DDrawDebugLevel = "); pwstrLevels->append( propval ); pwstrLevels->append(L"\n");
hr = GetProperty( L"DxDiag_SystemInfo", L"nDIDebugLevel", &propval );
pwstrLevels->append( L"DIDebugLevel = "); pwstrLevels->append( propval ); pwstrLevels->append(L"\n");
hr = GetProperty( L"DxDiag_SystemInfo", L"nDMusicDebugLevel", &propval );
pwstrLevels->append( L"DMusicDebugLevel = "); pwstrLevels->append( propval ); pwstrLevels->append(L"\n");
hr = GetProperty( L"DxDiag_SystemInfo", L"nDPlayDebugLevel", &propval );
pwstrLevels->append( L"DPlayDebugLevel = "); pwstrLevels->append( propval ); pwstrLevels->append(L"\n");
hr = GetProperty( L"DxDiag_SystemInfo", L"nDSoundDebugLevel", &propval );
pwstrLevels->append( L"DSoundDebugLevel = "); pwstrLevels->append( propval ); pwstrLevels->append(L"\n");
hr = GetProperty( L"DxDiag_SystemInfo", L"nDShowDebugLevel", &propval );
pwstrLevels->append( L"DShowDebugLevel = "); pwstrLevels->append( propval ); pwstrLevels->append(L"\n");
return( hr );
}
HRESULT DXDiagNVUtil::GetDirectXVersion( DWORD * pdwDirectXVersionMajor,
DWORD * pdwDirectXVersionMinor,
TCHAR * pcDirectXVersionLetter )
{
HRESULT hr = S_OK;
FAIL_IF_NULL( m_pDxDiagRoot );
FAIL_IF_NULL( pdwDirectXVersionMajor );
FAIL_IF_NULL( pdwDirectXVersionMinor );
FAIL_IF_NULL( pcDirectXVersionLetter );
wstring propval;
GetProperty( L"DxDiag_SystemInfo", L"dwDirectXVersionMajor", &propval );
*pdwDirectXVersionMajor = _wtoi( propval.c_str() );
GetProperty( L"DxDiag_SystemInfo", L"dwDirectXVersionMinor", &propval );
*pdwDirectXVersionMinor = _wtoi( propval.c_str() );
GetProperty( L"DxDiag_SystemInfo", L"szDirectXVersionLetter", &propval );
string str;
str = WStringToString( &propval );
if( str.length() > 0 )
*pcDirectXVersionLetter = str.at(0);
else
*pcDirectXVersionLetter = ' ';
return( hr );
}
//------------------------------------------------------------------------
// Get the property at pContainer by name
// Decode the VARIANT property to a string and return the string
HRESULT DXDiagNVUtil::GetProperty( IDxDiagContainer * pContainer, LPCWSTR property_name, wstring * out_value )
{
HRESULT hr = S_OK;
FAIL_IF_NULL( pContainer );
FAIL_IF_NULL( property_name );
FAIL_IF_NULL( out_value );
WCHAR wszPropValue[256];
VARIANT var;
VariantInit( &var );
hr = pContainer->GetProp( property_name, &var );
if( SUCCEEDED(hr) )
{
// Switch according to the type. There's 4 different types:
switch( var.vt )
{
case VT_UI4:
swprintf( wszPropValue, L"%d", var.ulVal );
break;
case VT_I4:
swprintf( wszPropValue, L"%d", var.lVal );
break;
case VT_BOOL:
swprintf( wszPropValue, L"%s", (var.boolVal) ? L"true" : L"false" );
break;
case VT_BSTR:
wcsncpy( wszPropValue, var.bstrVal, 255 );
wszPropValue[255] = 0;
break;
}
// copy string to the output string
(*out_value) = wszPropValue;
}
else
{
FMsgW(L"GetProperty( cont, prop, val ) Couldn't get prop [%s]\n", property_name );
//char mbBuf[512];
//wcstombs( mbBuf, property_name, 512 );
//FMsg("GetProperty( cont, prop, val ) Couldn't get prop [%s]\n", mbBuf );
}
VariantClear( &var );
return( hr );
}
HRESULT DXDiagNVUtil::GetProperty( LPCWSTR container_name0,
LPCWSTR property_name,
wstring * out_value )
{
HRESULT hr = S_OK;
IDxDiagContainer * pContainer;
hr = GetChildContainer( container_name0, &pContainer );
TRACE0( MSG_IF( FAILED(hr), "GetProperty(cn,pn,&v) GetChildContainer(<1>) failed!\n" ));
RET_VAL_IF_FAILED( hr );
FAIL_IF_NULL( pContainer );
hr = GetProperty( pContainer, property_name, out_value );
TRACE0( MSG_IF( FAILED(hr), "GetProperty(<1>) pContainer->GetProperty(c,n,v) failed!\n"));
SAFE_RELEASE( pContainer );
return( hr );
}
HRESULT DXDiagNVUtil::GetProperty( LPCWSTR container_name0,
LPCWSTR container_name1,
LPCWSTR property_name,
wstring * out_value )
{
HRESULT hr = S_OK;
IDxDiagContainer * pContainer;
hr = GetChildContainer( container_name0, container_name1, &pContainer );
MSG_AND_RET_VAL_IF( FAILED(hr), "GetProperty(cn,cn,pn,&v) couldn't get child container!\n", hr );
hr = GetProperty( pContainer, property_name, out_value );
MSG_AND_RET_VAL_IF( FAILED(hr), "GetProperty(cn,cn,pn,&v) couldn't get container property!\n", hr );
SAFE_RELEASE( pContainer );
return( hr );
}
HRESULT DXDiagNVUtil::GetProperty( LPCWSTR container_name0,
LPCWSTR container_name1,
LPCWSTR container_name2,
LPCWSTR property_name,
wstring * out_value )
{
HRESULT hr = S_OK;
FAIL_IF_NULL( out_value );
IDxDiagContainer * pContainer;
hr = GetChildContainer( container_name0, container_name1, container_name2, &pContainer );
MSG_AND_RET_VAL_IF( FAILED(hr), "GetProperty(cn,cn,cn,pn,&v) couldn't get child container!\n", hr );
hr = GetProperty( pContainer, property_name, out_value );
MSG_AND_RET_VAL_IF( FAILED(hr), "GetProperty(cn,cn,cn,pn,&v) couldn't get container property!\n", hr );
SAFE_RELEASE( pContainer );
return( hr );
}
//------------------------------
HRESULT DXDiagNVUtil::GetChildContainer( LPCWSTR name0, IDxDiagContainer ** ppChild )
{
// you must release *ppChild on your own when you're done with it
HRESULT hr = S_OK;
MSGVARNAME_AND_FAIL_IF_NULL( m_pDxDiagRoot );
MSGVARNAME_AND_FAIL_IF_NULL( ppChild );
hr = m_pDxDiagRoot->GetChildContainer( name0, ppChild );
TRACE0( MSG_IF( FAILED(hr), "GetChildContainer(<1>) m_pDxDiagRoot->GetChildContainer() failed\n" ));
RET_VAL_IF_FAILED( hr );
FAIL_IF_NULL( *ppChild );
return( hr );
}
HRESULT DXDiagNVUtil::GetChildContainer( LPCWSTR name0,
LPCWSTR name1,
IDxDiagContainer ** ppChild )
{
// intermediate children are released before returning
// you only have to release() *ppChild
HRESULT hr = S_OK;
IDxDiagContainer * pChild;
hr = GetChildContainer( name0, &pChild );
TRACE0( MSG_IF( FAILED(hr), "GetChildContainer(<2>) GetChildContainer(<1>) failed\n" ) );
RET_VAL_IF_FAILED( hr );
FAIL_IF_NULL( pChild );
hr = pChild->GetChildContainer( name1, ppChild );
TRACE0( MSG_IF( FAILED(hr), "GetChildContainer(<2>) IDxDiagContainer->GetChildContainer() failed\n" ) );
SAFE_RELEASE( pChild ); // release the intermediate
return( hr );
}
HRESULT DXDiagNVUtil::GetChildContainer( LPCWSTR name0,
LPCWSTR name1,
LPCWSTR name2,
IDxDiagContainer ** ppChild )
{
// intermediate children are released before returning
// you only have to release() *ppChild
HRESULT hr = S_OK;
IDxDiagContainer * pChild;
hr = GetChildContainer( name0, name1, &pChild );
TRACE0( MSG_IF( FAILED(hr), "GetChildContainer(<3>) GetChildContainer(<2>) failed\n" ) );
RET_VAL_IF_FAILED( hr );
FAIL_IF_NULL( pChild );
hr = pChild->GetChildContainer( name2, ppChild );
TRACE0( MSG_IF( FAILED(hr), "GetChildContainer(<3>) IDxDiagContainer->GetChildContainer() failed\n" ) );
SAFE_RELEASE( pChild ); // release the intermediate
return( hr );
}
// public interface to display all node and subnode names
HRESULT DXDiagNVUtil::ListAllDXDiagPropertyNames()
{
HRESULT hr = S_OK;
hr = ListAllDXDiagPropertyNames( m_pDxDiagRoot );
return( hr );
}
HRESULT DXDiagNVUtil::ListAllDXDiagPropertyNames( IDxDiagContainer * pDxDiagContainer,
WCHAR* wszParentName )
{
// Recurse through all properties and child properties,
// outputting their names via OutputDebugString(..)
// Start this by calling with the root IDxDiagContainer and a NULL string ptr.
//
// This function can take a while to complete.
//
// Adapted from DXSDK example file DxDiagOutput.cpp
HRESULT hr = S_OK;
FAIL_IF_NULL( pDxDiagContainer );
DWORD dwPropCount;
DWORD dwPropIndex;
WCHAR wszPropName[256];
DWORD dwChildCount;
DWORD dwChildIndex;
WCHAR wszChildName[256];
IDxDiagContainer* pChildContainer = NULL;
const bool bGetPropertyValue = false;
hr = pDxDiagContainer->GetNumberOfProps( &dwPropCount );
if( SUCCEEDED(hr) )
{
// Print each property in this container
for( dwPropIndex = 0; dwPropIndex < dwPropCount; dwPropIndex++ )
{
hr = pDxDiagContainer->EnumPropNames( dwPropIndex, wszPropName, 256 );
if( SUCCEEDED( hr ) )
{
if( bGetPropertyValue )
{
wstring propval;
hr = GetProperty( pDxDiagContainer, wszPropName, & propval );
FMsgW(L"%35s : prop \"%s\" = %s\n", wszParentName, wszPropName, propval.c_str() );
}
else
{
// otherwise, just list the property name and parent container info
FMsgW(L"%35s : prop \"%s\"\n", wszParentName, wszPropName );
}
}
}
}
// Recursivly call this function for each of its child containers
hr = pDxDiagContainer->GetNumberOfChildContainers( &dwChildCount );
if( SUCCEEDED(hr) )
{
for( dwChildIndex = 0; dwChildIndex < dwChildCount; dwChildIndex++ )
{
hr = pDxDiagContainer->EnumChildContainerNames( dwChildIndex, wszChildName, 256 );
if( SUCCEEDED(hr) )
{
hr = pDxDiagContainer->GetChildContainer( wszChildName, &pChildContainer );
if( SUCCEEDED(hr) )
{
// wszFullChildName isn't needed but is used for text output
WCHAR wszFullChildName[256];
// Append child name to parent and pass down in the recursion
// as full parent name.
if( wszParentName )
swprintf( wszFullChildName, L"%s.%s", wszParentName, wszChildName );
else
swprintf( wszFullChildName, L"%s", wszChildName );
// recurse
ListAllDXDiagPropertyNames( pChildContainer, wszFullChildName );
SAFE_RELEASE( pChildContainer );
}
}
}
}
return( hr );
}
// Recurse through all properties and child properties, outputting their names
// to the file.
// This function is slow and takes a while to output all the nodes, so it can be
// called with a sub-node initial argument if you only care about a small part of the
// COM data structure tree.
// Adapted from DXSDK example file DxDiagOutput.cpp
// pOpenTextFile Must be a file opened for writing text
// Call this with NULL 2nd and 3rd args to start from the top of the node structure.
HRESULT DXDiagNVUtil::ListAllDXDiagPropertyNamesToTxtFile( FILE * pOpenTextFile,
bool bGetPropertyValues,
IDxDiagContainer * pDxDiagContainer,
WCHAR * wszParentName )
{
HRESULT hr = S_OK;
FAIL_IF_NULL( pOpenTextFile );
if( pDxDiagContainer == NULL )
pDxDiagContainer = m_pDxDiagRoot;
FAIL_IF_NULL( pDxDiagContainer );
DWORD dwPropCount;
DWORD dwPropIndex;
WCHAR wszPropName[256];
DWORD dwChildCount;
DWORD dwChildIndex;
WCHAR wszChildName[256];
IDxDiagContainer* pChildContainer = NULL;
string strParentName, strPropName, strPropVal;
wstring wstrParentName, wstrPropName;
hr = pDxDiagContainer->GetNumberOfProps( &dwPropCount );
if( SUCCEEDED(hr) )
{
if( wszParentName != NULL )
wstrParentName = wszParentName;
else
wstrParentName = L"";
strParentName = WStringToString( wstrParentName );
// Print each property in this container
for( dwPropIndex = 0; dwPropIndex < dwPropCount; dwPropIndex++ )
{
hr = pDxDiagContainer->EnumPropNames( dwPropIndex, wszPropName, 256 );
if( wszPropName != NULL )
wstrPropName = wszPropName;
else
wstrPropName = L"";
strPropName = WStringToString( wstrPropName );
if( SUCCEEDED( hr ) )
{
if( bGetPropertyValues )
{
wstring wstrPropVal;
hr = GetProperty( pDxDiagContainer, wszPropName, & wstrPropVal );
strPropVal = WStringToString( wstrPropVal );
fprintf( pOpenTextFile, "%35s : prop \"%s\" = %s\n", strParentName.c_str(), strPropName.c_str(), strPropVal.c_str() );
}
else
{
// otherwise, just list the property name and parent container info
fprintf( pOpenTextFile, "%35s : prop \"%s\"\n", strParentName.c_str(), strPropName.c_str() );
}
}
}
}
// Recursivly call this function for each of its child containers
hr = pDxDiagContainer->GetNumberOfChildContainers( &dwChildCount );
if( SUCCEEDED(hr) )
{
for( dwChildIndex = 0; dwChildIndex < dwChildCount; dwChildIndex++ )
{
hr = pDxDiagContainer->EnumChildContainerNames( dwChildIndex, wszChildName, 256 );
if( SUCCEEDED(hr) )
{
hr = pDxDiagContainer->GetChildContainer( wszChildName, &pChildContainer );
if( SUCCEEDED(hr) )
{
// wszFullChildName isn't needed but is used for text output
WCHAR wszFullChildName[256];
// Append child name to parent and pass down in the recursion
// as full parent name.
if( wszParentName )
swprintf( wszFullChildName, L"%s.%s", wszParentName, wszChildName );
else
swprintf( wszFullChildName, L"%s", wszChildName );
// recurse
ListAllDXDiagPropertyNamesToTxtFile( pOpenTextFile, bGetPropertyValues,
pChildContainer, wszFullChildName );
SAFE_RELEASE( pChildContainer );
}
}
}
}
return( hr );
}
HRESULT DXDiagNVUtil::InitIDxDiagContainer()
{
// Call FreeIDxDiagContainer() to clean up things done here
HRESULT hr;
if( m_pDxDiagRoot != NULL )
{
FMsg("DXDiagNVUtil::InitIDxDiagContainer already initialized!\n");
return( S_OK );
}
// Init COM. COM may fail if its already been inited with a different
// concurrency model. And if it fails you shouldn't release it.
hr = CoInitialize(NULL);
m_bCleanupCOM = SUCCEEDED(hr);
// Get an IDxDiagProvider
hr = CoCreateInstance( CLSID_DxDiagProvider,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDxDiagProvider,
(LPVOID*) &m_pDxDiagProvider );
if( SUCCEEDED(hr) )
{
// Fill out a DXDIAG_INIT_PARAMS struct
DXDIAG_INIT_PARAMS dxDiagInitParam;
ZeroMemory( &dxDiagInitParam, sizeof(DXDIAG_INIT_PARAMS) );
dxDiagInitParam.dwSize = sizeof(DXDIAG_INIT_PARAMS);
dxDiagInitParam.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION;
dxDiagInitParam.bAllowWHQLChecks = false;
dxDiagInitParam.pReserved = NULL;
// Init the m_m_pDxDiagProvider
hr = m_pDxDiagProvider->Initialize( &dxDiagInitParam );
if( SUCCEEDED(hr) )
{
// Get the DxDiag root container
hr = m_pDxDiagProvider->GetRootContainer( & m_pDxDiagRoot );
if( FAILED(hr) )
{
FMsg("Couldn't GetRootContainer from DxDiagProvider!\n");
assert( false );
FreeIDxDiagContainer();
return( hr );
}
}
else
{
FMsg("Couldn't Initialize DxDiagProvider!\n");
assert( false );
FreeIDxDiagContainer();
return( hr );
}
}
else
{
FMsg("Couldn't initialize COM!\n");
assert( false );
FreeIDxDiagContainer();
return( hr );
}
return( hr );
}
HRESULT DXDiagNVUtil::FreeIDxDiagContainer()
{
HRESULT hr = S_OK;
SAFE_RELEASE( m_pDxDiagProvider );
SAFE_RELEASE( m_pDxDiagRoot );
if( m_bCleanupCOM )
{
CoUninitialize();
m_bCleanupCOM = false;
}
return( hr );
}