-
Notifications
You must be signed in to change notification settings - Fork 369
/
VidMemViaDxDiag.cpp
135 lines (120 loc) · 5.25 KB
/
VidMemViaDxDiag.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//----------------------------------------------------------------------------
// File: VidMemViaDXDiag.cpp
//
// DxDiag internally uses both DirectDraw 7 and WMI and returns the rounded WMI
// value if WMI is available. Otherwise, it returns a rounded DirectDraw 7 value.
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License (MIT).
//-----------------------------------------------------------------------------
#define INITGUID
#include <windows.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <initguid.h>
// dxdiag is not present in the Windows 7.1 SDK used by "v110_xp". Could get it from the legacy DirectX SDK if
// needed for Windows XP
#include <dxdiag.h>
//-----------------------------------------------------------------------------
// Defines, and constants
//-----------------------------------------------------------------------------
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=nullptr; } }
#endif
HRESULT GetDeviceIDFromHMonitor( HMONITOR hm, WCHAR* strDeviceID, int cchDeviceID ); // from vidmemviaddraw.cpp
HRESULT GetVideoMemoryViaDxDiag( HMONITOR hMonitor, DWORD* pdwDisplayMemory )
{
WCHAR strInputDeviceID[512];
GetDeviceIDFromHMonitor( hMonitor, strInputDeviceID, 512 );
HRESULT hr;
HRESULT hrCoInitialize = S_OK;
bool bGotMemory = false;
IDxDiagProvider* pDxDiagProvider = nullptr;
IDxDiagContainer* pDxDiagRoot = nullptr;
IDxDiagContainer* pDevices = nullptr;
IDxDiagContainer* pDevice = nullptr;
WCHAR wszChildName[256];
WCHAR wszPropValue[256];
DWORD dwDeviceCount;
VARIANT var;
*pdwDisplayMemory = 0;
hrCoInitialize = CoInitialize( 0 );
VariantInit( &var );
// CoCreate a IDxDiagProvider*
hr = CoCreateInstance( CLSID_DxDiagProvider,
nullptr,
CLSCTX_INPROC_SERVER,
IID_IDxDiagProvider,
( LPVOID* )&pDxDiagProvider );
if( SUCCEEDED( hr ) ) // if FAILED(hr) then it is likely DirectX 9 is not installed
{
DXDIAG_INIT_PARAMS dxDiagInitParam = {};
dxDiagInitParam.dwSize = sizeof( DXDIAG_INIT_PARAMS );
dxDiagInitParam.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION;
dxDiagInitParam.bAllowWHQLChecks = FALSE;
dxDiagInitParam.pReserved = nullptr;
pDxDiagProvider->Initialize( &dxDiagInitParam );
hr = pDxDiagProvider->GetRootContainer( &pDxDiagRoot );
if( SUCCEEDED( hr ) )
{
hr = pDxDiagRoot->GetChildContainer( L"DxDiag_DisplayDevices", &pDevices );
if( SUCCEEDED( hr ) )
{
hr = pDevices->GetNumberOfChildContainers( &dwDeviceCount );
if( SUCCEEDED( hr ) )
{
for( DWORD iDevice = 0; iDevice < dwDeviceCount; iDevice++ )
{
bool bFound = false;
hr = pDevices->EnumChildContainerNames( iDevice, wszChildName, 256 );
if( SUCCEEDED( hr ) )
{
hr = pDevices->GetChildContainer( wszChildName, &pDevice );
if( SUCCEEDED( hr ) )
{
hr = pDevice->GetProp( L"szKeyDeviceID", &var );
if( SUCCEEDED( hr ) )
{
if( var.vt == VT_BSTR )
{
if( wcsstr( var.bstrVal, strInputDeviceID ) != 0 )
bFound = true;
}
VariantClear( &var );
}
if( bFound )
{
hr = pDevice->GetProp( L"szDisplayMemoryEnglish", &var );
if( SUCCEEDED( hr ) )
{
if( var.vt == VT_BSTR )
{
bGotMemory = true;
wcscpy_s( wszPropValue, 256, var.bstrVal );
// wszPropValue should be something like "256.0 MB" so _wtoi will convert it correctly
*pdwDisplayMemory = _wtoi( wszPropValue );
// Convert from MB to bytes
*pdwDisplayMemory *= 1024 * 1024;
}
VariantClear( &var );
}
}
SAFE_RELEASE( pDevice );
}
}
}
}
SAFE_RELEASE( pDevices );
}
SAFE_RELEASE( pDxDiagRoot );
}
SAFE_RELEASE( pDxDiagProvider );
}
if( SUCCEEDED( hrCoInitialize ) )
CoUninitialize();
if( bGotMemory )
return S_OK;
else
return E_FAIL;
}