2 * IDxDiagProvider Implementation
4 * Copyright 2004-2005 Raphael Junqueira
5 * Copyright 2010 Andrew Nguyen
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "dxdiag_private.h"
34 #include "wine/fil_data.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(dxdiag
);
43 static HRESULT
build_information_tree(IDxDiagContainerImpl_Container
**pinfo_root
);
44 static void free_information_tree(IDxDiagContainerImpl_Container
*node
);
46 struct IDxDiagProviderImpl
48 IDxDiagProvider IDxDiagProvider_iface
;
51 DXDIAG_INIT_PARAMS params
;
52 IDxDiagContainerImpl_Container
*info_root
;
55 static inline IDxDiagProviderImpl
*impl_from_IDxDiagProvider(IDxDiagProvider
*iface
)
57 return CONTAINING_RECORD(iface
, IDxDiagProviderImpl
, IDxDiagProvider_iface
);
60 /* IDxDiagProvider IUnknown parts follow: */
61 static HRESULT WINAPI
IDxDiagProviderImpl_QueryInterface(IDxDiagProvider
*iface
, REFIID riid
,
64 IDxDiagProviderImpl
*This
= impl_from_IDxDiagProvider(iface
);
66 if (!ppobj
) return E_INVALIDARG
;
68 if (IsEqualGUID(riid
, &IID_IUnknown
)
69 || IsEqualGUID(riid
, &IID_IDxDiagProvider
)) {
70 IUnknown_AddRef(iface
);
71 *ppobj
= &This
->IDxDiagProvider_iface
;
75 WARN("(%p)->(%s,%p),not found\n",This
,debugstr_guid(riid
),ppobj
);
80 static ULONG WINAPI
IDxDiagProviderImpl_AddRef(IDxDiagProvider
*iface
)
82 IDxDiagProviderImpl
*This
= impl_from_IDxDiagProvider(iface
);
83 ULONG refCount
= InterlockedIncrement(&This
->ref
);
85 TRACE("(%p)->(ref before=%lu)\n", This
, refCount
- 1);
92 static ULONG WINAPI
IDxDiagProviderImpl_Release(IDxDiagProvider
*iface
)
94 IDxDiagProviderImpl
*This
= impl_from_IDxDiagProvider(iface
);
95 ULONG refCount
= InterlockedDecrement(&This
->ref
);
97 TRACE("(%p)->(ref before=%lu)\n", This
, refCount
+ 1);
100 free_information_tree(This
->info_root
);
101 HeapFree(GetProcessHeap(), 0, This
);
104 DXDIAGN_UnlockModule();
109 /* IDxDiagProvider Interface follow: */
110 static HRESULT WINAPI
IDxDiagProviderImpl_Initialize(IDxDiagProvider
*iface
,
111 DXDIAG_INIT_PARAMS
*pParams
)
113 IDxDiagProviderImpl
*This
= impl_from_IDxDiagProvider(iface
);
116 TRACE("(%p,%p)\n", iface
, pParams
);
118 if (NULL
== pParams
) {
121 if (pParams
->dwSize
!= sizeof(DXDIAG_INIT_PARAMS
) ||
122 pParams
->dwDxDiagHeaderVersion
!= DXDIAG_DX9_SDK_VERSION
) {
126 if (!This
->info_root
)
128 hr
= build_information_tree(&This
->info_root
);
134 memcpy(&This
->params
, pParams
, pParams
->dwSize
);
138 static HRESULT WINAPI
IDxDiagProviderImpl_GetRootContainer(IDxDiagProvider
*iface
,
139 IDxDiagContainer
**ppInstance
)
141 IDxDiagProviderImpl
*This
= impl_from_IDxDiagProvider(iface
);
143 TRACE("(%p,%p)\n", iface
, ppInstance
);
145 if (FALSE
== This
->init
) {
146 return CO_E_NOTINITIALIZED
;
149 return DXDiag_CreateDXDiagContainer(&IID_IDxDiagContainer
, This
->info_root
,
150 &This
->IDxDiagProvider_iface
, (void **)ppInstance
);
153 static const IDxDiagProviderVtbl DxDiagProvider_Vtbl
=
155 IDxDiagProviderImpl_QueryInterface
,
156 IDxDiagProviderImpl_AddRef
,
157 IDxDiagProviderImpl_Release
,
158 IDxDiagProviderImpl_Initialize
,
159 IDxDiagProviderImpl_GetRootContainer
162 HRESULT
DXDiag_CreateDXDiagProvider(LPCLASSFACTORY iface
, LPUNKNOWN punkOuter
, REFIID riid
, LPVOID
*ppobj
) {
163 IDxDiagProviderImpl
* provider
;
165 TRACE("(%p, %s, %p)\n", punkOuter
, debugstr_guid(riid
), ppobj
);
168 if (punkOuter
) return CLASS_E_NOAGGREGATION
;
170 provider
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDxDiagProviderImpl
));
171 if (NULL
== provider
) return E_OUTOFMEMORY
;
172 provider
->IDxDiagProvider_iface
.lpVtbl
= &DxDiagProvider_Vtbl
;
173 provider
->ref
= 0; /* will be inited with QueryInterface */
174 return IDxDiagProviderImpl_QueryInterface(&provider
->IDxDiagProvider_iface
, riid
, ppobj
);
177 static void free_property_information(IDxDiagContainerImpl_Property
*prop
)
179 VariantClear(&prop
->vProp
);
180 HeapFree(GetProcessHeap(), 0, prop
->propName
);
181 HeapFree(GetProcessHeap(), 0, prop
);
184 static void free_information_tree(IDxDiagContainerImpl_Container
*node
)
186 IDxDiagContainerImpl_Container
*ptr
, *cursor2
;
191 HeapFree(GetProcessHeap(), 0, node
->contName
);
193 LIST_FOR_EACH_ENTRY_SAFE(ptr
, cursor2
, &node
->subContainers
, IDxDiagContainerImpl_Container
, entry
)
195 IDxDiagContainerImpl_Property
*prop
, *prop_cursor2
;
197 LIST_FOR_EACH_ENTRY_SAFE(prop
, prop_cursor2
, &ptr
->properties
, IDxDiagContainerImpl_Property
, entry
)
199 list_remove(&prop
->entry
);
200 free_property_information(prop
);
203 list_remove(&ptr
->entry
);
204 free_information_tree(ptr
);
207 HeapFree(GetProcessHeap(), 0, node
);
210 static IDxDiagContainerImpl_Container
*allocate_information_node(const WCHAR
*name
)
212 IDxDiagContainerImpl_Container
*ret
;
214 ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ret
));
220 ret
->contName
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name
) + 1) * sizeof(*name
));
223 HeapFree(GetProcessHeap(), 0, ret
);
226 lstrcpyW(ret
->contName
, name
);
229 list_init(&ret
->subContainers
);
230 list_init(&ret
->properties
);
235 static IDxDiagContainerImpl_Property
*allocate_property_information(const WCHAR
*name
)
237 IDxDiagContainerImpl_Property
*ret
;
239 ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ret
));
243 ret
->propName
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name
) + 1) * sizeof(*name
));
246 HeapFree(GetProcessHeap(), 0, ret
);
249 lstrcpyW(ret
->propName
, name
);
254 static inline void add_subcontainer(IDxDiagContainerImpl_Container
*node
, IDxDiagContainerImpl_Container
*subCont
)
256 list_add_tail(&node
->subContainers
, &subCont
->entry
);
257 ++node
->nSubContainers
;
260 static inline HRESULT
add_bstr_property(IDxDiagContainerImpl_Container
*node
, const WCHAR
*propName
, const WCHAR
*str
)
262 IDxDiagContainerImpl_Property
*prop
;
265 prop
= allocate_property_information(propName
);
267 return E_OUTOFMEMORY
;
269 bstr
= SysAllocString(str
);
272 free_property_information(prop
);
273 return E_OUTOFMEMORY
;
276 V_VT(&prop
->vProp
) = VT_BSTR
;
277 V_BSTR(&prop
->vProp
) = bstr
;
279 list_add_tail(&node
->properties
, &prop
->entry
);
285 static inline HRESULT
add_ui4_property(IDxDiagContainerImpl_Container
*node
, const WCHAR
*propName
, DWORD data
)
287 IDxDiagContainerImpl_Property
*prop
;
289 prop
= allocate_property_information(propName
);
291 return E_OUTOFMEMORY
;
293 V_VT(&prop
->vProp
) = VT_UI4
;
294 V_UI4(&prop
->vProp
) = data
;
296 list_add_tail(&node
->properties
, &prop
->entry
);
302 static inline HRESULT
add_i4_property(IDxDiagContainerImpl_Container
*node
, const WCHAR
*propName
, LONG data
)
304 IDxDiagContainerImpl_Property
*prop
;
306 prop
= allocate_property_information(propName
);
308 return E_OUTOFMEMORY
;
310 V_VT(&prop
->vProp
) = VT_I4
;
311 V_I4(&prop
->vProp
) = data
;
313 list_add_tail(&node
->properties
, &prop
->entry
);
319 static inline HRESULT
add_bool_property(IDxDiagContainerImpl_Container
*node
, const WCHAR
*propName
, BOOL data
)
321 IDxDiagContainerImpl_Property
*prop
;
323 prop
= allocate_property_information(propName
);
325 return E_OUTOFMEMORY
;
327 V_VT(&prop
->vProp
) = VT_BOOL
;
328 V_BOOL(&prop
->vProp
) = data
? VARIANT_TRUE
: VARIANT_FALSE
;
330 list_add_tail(&node
->properties
, &prop
->entry
);
336 static inline HRESULT
add_ull_as_bstr_property(IDxDiagContainerImpl_Container
*node
, const WCHAR
*propName
, ULONGLONG data
)
338 IDxDiagContainerImpl_Property
*prop
;
341 prop
= allocate_property_information(propName
);
343 return E_OUTOFMEMORY
;
345 V_VT(&prop
->vProp
) = VT_UI8
;
346 V_UI8(&prop
->vProp
) = data
;
348 hr
= VariantChangeType(&prop
->vProp
, &prop
->vProp
, 0, VT_BSTR
);
351 free_property_information(prop
);
355 list_add_tail(&node
->properties
, &prop
->entry
);
361 /* Copied from programs/taskkill/taskkill.c. */
362 static DWORD
*enumerate_processes(DWORD
*list_count
)
364 DWORD
*pid_list
, alloc_bytes
= 1024 * sizeof(*pid_list
), needed_bytes
;
366 pid_list
= HeapAlloc(GetProcessHeap(), 0, alloc_bytes
);
374 if (!EnumProcesses(pid_list
, alloc_bytes
, &needed_bytes
))
376 HeapFree(GetProcessHeap(), 0, pid_list
);
380 /* EnumProcesses can't signal an insufficient buffer condition, so the
381 * only way to possibly determine whether a larger buffer is required
382 * is to see whether the written number of bytes is the same as the
383 * buffer size. If so, the buffer will be reallocated to twice the
385 if (alloc_bytes
!= needed_bytes
)
389 realloc_list
= HeapReAlloc(GetProcessHeap(), 0, pid_list
, alloc_bytes
);
392 HeapFree(GetProcessHeap(), 0, pid_list
);
395 pid_list
= realloc_list
;
398 *list_count
= needed_bytes
/ sizeof(*pid_list
);
402 /* Copied from programs/taskkill/taskkill.c. */
403 static BOOL
get_process_name_from_pid(DWORD pid
, WCHAR
*buf
, DWORD chars
)
409 process
= OpenProcess(PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
, FALSE
, pid
);
413 if (!EnumProcessModules(process
, &module
, sizeof(module
), &required_size
))
415 CloseHandle(process
);
419 if (!GetModuleBaseNameW(process
, module
, buf
, chars
))
421 CloseHandle(process
);
425 CloseHandle(process
);
429 /* dxdiagn's detection scheme is simply to look for a process called conf.exe. */
430 static BOOL
is_netmeeting_running(void)
433 DWORD
*pid_list
= enumerate_processes(&list_count
);
438 WCHAR process_name
[MAX_PATH
];
440 for (i
= 0; i
< list_count
; i
++)
442 if (get_process_name_from_pid(pid_list
[i
], process_name
, ARRAY_SIZE(process_name
)) &&
443 !lstrcmpW(L
"conf.exe", process_name
))
445 HeapFree(GetProcessHeap(), 0, pid_list
);
449 HeapFree(GetProcessHeap(), 0, pid_list
);
455 static HRESULT
fill_language_information(IDxDiagContainerImpl_Container
*node
)
457 WCHAR system_lang
[80], regional_setting
[100], user_lang
[80], language_str
[300];
460 /* szLanguagesLocalized */
461 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SNATIVELANGNAME
, system_lang
, ARRAY_SIZE(system_lang
));
462 LoadStringW(dxdiagn_instance
, IDS_REGIONAL_SETTING
, regional_setting
, ARRAY_SIZE(regional_setting
));
463 GetLocaleInfoW(LOCALE_USER_DEFAULT
, LOCALE_SNATIVELANGNAME
, user_lang
, ARRAY_SIZE(user_lang
));
465 swprintf(language_str
, ARRAY_SIZE(language_str
), L
"%s (%s: %s)", system_lang
, regional_setting
,
468 hr
= add_bstr_property(node
, L
"szLanguagesLocalized", language_str
);
472 /* szLanguagesEnglish */
473 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SENGLANGUAGE
, system_lang
, ARRAY_SIZE(system_lang
));
474 GetLocaleInfoW(LOCALE_USER_DEFAULT
, LOCALE_SENGLANGUAGE
, user_lang
, ARRAY_SIZE(user_lang
));
476 swprintf(language_str
, ARRAY_SIZE(language_str
), L
"%s (%s: %s)", system_lang
,
477 L
"Regional Setting", user_lang
);
479 hr
= add_bstr_property(node
, L
"szLanguagesEnglish", language_str
);
486 static HRESULT
fill_datetime_information(IDxDiagContainerImpl_Container
*node
)
489 WCHAR date_str
[80], time_str
[80], datetime_str
[200];
492 GetLocalTime(&curtime
);
494 GetTimeFormatW(LOCALE_NEUTRAL
, 0, &curtime
, L
"HH':'mm':'ss", time_str
, ARRAY_SIZE(time_str
));
496 /* szTimeLocalized */
497 GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &curtime
, NULL
, date_str
, ARRAY_SIZE(date_str
));
499 swprintf(datetime_str
, ARRAY_SIZE(datetime_str
), L
"%s, %s", date_str
, time_str
);
501 hr
= add_bstr_property(node
, L
"szTimeLocalized", datetime_str
);
506 GetDateFormatW(LOCALE_NEUTRAL
, 0, &curtime
, L
"M'/'d'/'yyyy", date_str
, ARRAY_SIZE(date_str
));
508 swprintf(datetime_str
, ARRAY_SIZE(datetime_str
), L
"%s, %s", date_str
, time_str
);
510 hr
= add_bstr_property(node
, L
"szTimeEnglish", datetime_str
);
517 static HRESULT
fill_os_string_information(IDxDiagContainerImpl_Container
*node
, OSVERSIONINFOW
*info
)
519 static const WCHAR
*prop_list
[] =
521 L
"szOSLocalized", L
"szOSExLocalized", L
"szOSExLongLocalized",
522 L
"szOSEnglish", L
"szOSExEnglish", L
"szOSExLongEnglish"
527 /* FIXME: OS detection should be performed, and localized OS strings
528 * should contain translated versions of the "build" phrase. */
529 for (i
= 0; i
< ARRAY_SIZE(prop_list
); i
++)
531 hr
= add_bstr_property(node
, prop_list
[i
], L
"Windows XP Professional");
539 static HRESULT
fill_processor_information(IDxDiagContainerImpl_Container
*node
)
541 IWbemLocator
*wbem_locator
;
542 IWbemServices
*wbem_service
;
543 IWbemClassObject
*wbem_class
;
544 IEnumWbemClassObject
*wbem_enum
;
545 VARIANT cpu_name
, cpu_no
, clock_speed
;
546 WCHAR print_buf
[200];
551 hr
= CoCreateInstance(&CLSID_WbemLocator
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IWbemLocator
, (void**)&wbem_locator
);
555 bstr
= SysAllocString(L
"\\\\.\\root\\cimv2");
557 IWbemLocator_Release(wbem_locator
);
558 return E_OUTOFMEMORY
;
560 hr
= IWbemLocator_ConnectServer(wbem_locator
, bstr
, NULL
, NULL
, NULL
, 0, NULL
, NULL
, &wbem_service
);
561 IWbemLocator_Release(wbem_locator
);
566 bstr
= SysAllocString(L
"Win32_Processor");
568 IWbemServices_Release(wbem_service
);
569 return E_OUTOFMEMORY
;
571 hr
= IWbemServices_CreateInstanceEnum(wbem_service
, bstr
, WBEM_FLAG_SYSTEM_ONLY
, NULL
, &wbem_enum
);
572 IWbemServices_Release(wbem_service
);
577 hr
= IEnumWbemClassObject_Next(wbem_enum
, 1000, 1, &wbem_class
, &no
);
578 IEnumWbemClassObject_Release(wbem_enum
);
582 hr
= IWbemClassObject_Get(wbem_class
, L
"NumberOfLogicalProcessors", 0, &cpu_no
, NULL
, NULL
);
584 IWbemClassObject_Release(wbem_class
);
587 hr
= IWbemClassObject_Get(wbem_class
, L
"MaxClockSpeed", 0, &clock_speed
, NULL
, NULL
);
589 IWbemClassObject_Release(wbem_class
);
592 hr
= IWbemClassObject_Get(wbem_class
, L
"Name", 0, &cpu_name
, NULL
, NULL
);
593 IWbemClassObject_Release(wbem_class
);
597 swprintf(print_buf
, ARRAY_SIZE(print_buf
), L
"%s(%d CPUs), ~%dMHz",
598 V_BSTR(&cpu_name
), V_I4(&cpu_no
), V_I4(&clock_speed
));
599 VariantClear(&cpu_name
);
600 VariantClear(&cpu_no
);
601 VariantClear(&clock_speed
);
603 return add_bstr_property(node
, L
"szProcessorEnglish", print_buf
);
606 static HRESULT
build_systeminfo_tree(IDxDiagContainerImpl_Container
*node
)
611 DWORD count
, usedpage_mb
, availpage_mb
;
612 WCHAR buffer
[MAX_PATH
], computer_name
[MAX_COMPUTERNAME_LENGTH
+ 1], print_buf
[200], localized_pagefile_fmt
[200];
615 hr
= add_ui4_property(node
, L
"dwDirectXVersionMajor", 9);
619 hr
= add_ui4_property(node
, L
"dwDirectXVersionMinor", 0);
623 hr
= add_bstr_property(node
, L
"szDirectXVersionLetter", L
"c");
627 hr
= add_bstr_property(node
, L
"szDirectXVersionEnglish", L
"4.09.0000.0904");
631 hr
= add_bstr_property(node
, L
"szDirectXVersionLongEnglish", L
"= \"DirectX 9.0c (4.09.0000.0904)");
635 hr
= add_bool_property(node
, L
"bDebug", FALSE
);
639 hr
= add_bool_property(node
, L
"bNECPC98", FALSE
);
643 msex
.dwLength
= sizeof(msex
);
644 GlobalMemoryStatusEx(&msex
);
646 hr
= add_ull_as_bstr_property(node
, L
"ullPhysicalMemory", msex
.ullTotalPhys
);
650 hr
= add_ull_as_bstr_property(node
, L
"ullUsedPageFile", msex
.ullTotalPageFile
- msex
.ullAvailPageFile
);
654 hr
= add_ull_as_bstr_property(node
, L
"ullAvailPageFile", msex
.ullAvailPageFile
);
658 hr
= add_bool_property(node
, L
"bNetMeetingRunning", is_netmeeting_running());
662 info
.dwOSVersionInfoSize
= sizeof(info
);
663 GetVersionExW(&info
);
665 hr
= add_ui4_property(node
, L
"dwOSMajorVersion", info
.dwMajorVersion
);
669 hr
= add_ui4_property(node
, L
"dwOSMinorVersion", info
.dwMinorVersion
);
673 hr
= add_ui4_property(node
, L
"dwOSBuildNumber", info
.dwBuildNumber
);
677 hr
= add_ui4_property(node
, L
"dwOSPlatformID", info
.dwPlatformId
);
681 hr
= add_bstr_property(node
, L
"szCSDVersion", info
.szCSDVersion
);
685 /* FIXME: Roundoff should not be done with truncated division. */
686 swprintf(print_buf
, ARRAY_SIZE(print_buf
), L
"%I64uMB RAM", msex
.ullTotalPhys
/ (1024 * 1024));
687 hr
= add_bstr_property(node
, L
"szPhysicalMemoryEnglish", print_buf
);
691 usedpage_mb
= (DWORD
)((msex
.ullTotalPageFile
- msex
.ullAvailPageFile
) / (1024 * 1024));
692 availpage_mb
= (DWORD
)(msex
.ullAvailPageFile
/ (1024 * 1024));
693 LoadStringW(dxdiagn_instance
, IDS_PAGE_FILE_FORMAT
, localized_pagefile_fmt
,
694 ARRAY_SIZE(localized_pagefile_fmt
));
695 args
[0] = usedpage_mb
;
696 args
[1] = availpage_mb
;
697 FormatMessageW(FORMAT_MESSAGE_FROM_STRING
|FORMAT_MESSAGE_ARGUMENT_ARRAY
, localized_pagefile_fmt
,
698 0, 0, print_buf
, ARRAY_SIZE(print_buf
), (va_list *)args
);
700 hr
= add_bstr_property(node
, L
"szPageFileLocalized", print_buf
);
704 swprintf(print_buf
, ARRAY_SIZE(print_buf
), L
"%uMB used, %uMB available", usedpage_mb
, availpage_mb
);
706 hr
= add_bstr_property(node
, L
"szPageFileEnglish", print_buf
);
710 GetWindowsDirectoryW(buffer
, MAX_PATH
);
712 hr
= add_bstr_property(node
, L
"szWindowsDir", buffer
);
716 count
= ARRAY_SIZE(computer_name
);
717 if (!GetComputerNameW(computer_name
, &count
))
720 hr
= add_bstr_property(node
, L
"szMachineNameLocalized", computer_name
);
724 hr
= add_bstr_property(node
, L
"szMachineNameEnglish", computer_name
);
728 hr
= add_bstr_property(node
, L
"szSystemManufacturerEnglish", L
"");
732 hr
= add_bstr_property(node
, L
"szSystemModelEnglish", L
"");
736 hr
= add_bstr_property(node
, L
"szBIOSEnglish", L
"");
740 hr
= fill_processor_information(node
);
744 hr
= add_bstr_property(node
, L
"szSetupParamEnglish", L
"Not present");
748 hr
= add_bstr_property(node
, L
"szDxDiagVersion", L
"");
752 hr
= fill_language_information(node
);
756 hr
= fill_datetime_information(node
);
760 hr
= fill_os_string_information(node
, &info
);
767 /* The logic from pixelformat_for_depth() in dlls/wined3d/utils.c is reversed. */
768 static DWORD
depth_for_pixelformat(D3DFORMAT format
)
772 case D3DFMT_P8
: return 8;
773 case D3DFMT_X1R5G5B5
: return 15;
774 case D3DFMT_R5G6B5
: return 16;
775 /* This case will fail to distinguish an original bpp of 24. */
776 case D3DFMT_X8R8G8B8
: return 32;
778 FIXME("Unknown D3DFORMAT %d, returning 32 bpp\n", format
);
783 static BOOL
get_texture_memory(GUID
*adapter
, DWORD
*available_mem
)
785 IDirectDraw7
*pDirectDraw
;
789 hr
= DirectDrawCreateEx(adapter
, (void **)&pDirectDraw
, &IID_IDirectDraw7
, NULL
);
792 dd_caps
.dwCaps
= DDSCAPS_LOCALVIDMEM
| DDSCAPS_VIDEOMEMORY
;
793 dd_caps
.dwCaps2
= dd_caps
.dwCaps3
= dd_caps
.dwCaps4
= 0;
794 hr
= IDirectDraw7_GetAvailableVidMem(pDirectDraw
, &dd_caps
, available_mem
, NULL
);
795 IDirectDraw7_Release(pDirectDraw
);
803 static const WCHAR
*vendor_id_to_manufacturer_string(DWORD vendor_id
)
813 {0x1002, L
"ATI Technologies Inc."},
816 {0x1af4, L
"Red Hat"},
817 {0x8086, L
"Intel Corporation"},
820 for (i
= 0; i
< ARRAY_SIZE(vendors
); ++i
)
822 if (vendors
[i
].id
== vendor_id
)
823 return vendors
[i
].name
;
826 FIXME("Unknown PCI vendor ID 0x%04lx.\n", vendor_id
);
831 static HRESULT
fill_display_information_d3d(IDxDiagContainerImpl_Container
*node
)
833 IDxDiagContainerImpl_Container
*display_adapter
;
835 IDirect3D9
*pDirect3D9
;
839 pDirect3D9
= Direct3DCreate9(D3D_SDK_VERSION
);
843 count
= IDirect3D9_GetAdapterCount(pDirect3D9
);
844 for (index
= 0; index
< count
; index
++)
846 D3DADAPTER_IDENTIFIER9 adapter_info
;
847 D3DDISPLAYMODE adapter_mode
;
848 D3DCAPS9 device_caps
;
849 DWORD available_mem
= 0;
852 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"%u", index
);
853 display_adapter
= allocate_information_node(buffer
);
854 if (!display_adapter
)
860 add_subcontainer(node
, display_adapter
);
862 hr
= IDirect3D9_GetAdapterIdentifier(pDirect3D9
, index
, 0, &adapter_info
);
865 WCHAR driverW
[sizeof(adapter_info
.Driver
)];
866 WCHAR descriptionW
[sizeof(adapter_info
.Description
)];
867 WCHAR devicenameW
[sizeof(adapter_info
.DeviceName
)];
869 MultiByteToWideChar(CP_ACP
, 0, adapter_info
.Driver
, -1, driverW
, ARRAY_SIZE(driverW
));
870 MultiByteToWideChar(CP_ACP
, 0, adapter_info
.Description
, -1, descriptionW
,
871 ARRAY_SIZE(descriptionW
));
872 MultiByteToWideChar(CP_ACP
, 0, adapter_info
.DeviceName
, -1, devicenameW
,
873 ARRAY_SIZE(devicenameW
));
875 hr
= add_bstr_property(display_adapter
, L
"szDriverName", driverW
);
879 hr
= add_bstr_property(display_adapter
, L
"szDescription", descriptionW
);
883 hr
= add_bstr_property(display_adapter
, L
"szDeviceName", devicenameW
);
887 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"%u.%u.%04u.%04u",
888 HIWORD(adapter_info
.DriverVersion
.HighPart
), LOWORD(adapter_info
.DriverVersion
.HighPart
),
889 HIWORD(adapter_info
.DriverVersion
.LowPart
), LOWORD(adapter_info
.DriverVersion
.LowPart
));
891 hr
= add_bstr_property(display_adapter
, L
"szDriverVersion", buffer
);
895 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"0x%04x", adapter_info
.VendorId
);
896 hr
= add_bstr_property(display_adapter
, L
"szVendorId", buffer
);
900 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"0x%04x", adapter_info
.DeviceId
);
901 hr
= add_bstr_property(display_adapter
, L
"szDeviceId", buffer
);
905 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"0x%08x", adapter_info
.SubSysId
);
906 hr
= add_bstr_property(display_adapter
, L
"szSubSysId", buffer
);
910 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"0x%04x", adapter_info
.Revision
);
911 hr
= add_bstr_property(display_adapter
, L
"szRevisionId", buffer
);
915 StringFromGUID2(&adapter_info
.DeviceIdentifier
, buffer
, 39);
916 hr
= add_bstr_property(display_adapter
, L
"szDeviceIdentifier", buffer
);
920 hr
= add_bstr_property(display_adapter
, L
"szManufacturer",
921 vendor_id_to_manufacturer_string(adapter_info
.VendorId
));
926 hr
= IDirect3D9_GetAdapterDisplayMode(pDirect3D9
, index
, &adapter_mode
);
929 hr
= add_ui4_property(display_adapter
, L
"dwWidth", adapter_mode
.Width
);
933 hr
= add_ui4_property(display_adapter
, L
"dwHeight", adapter_mode
.Height
);
937 hr
= add_ui4_property(display_adapter
, L
"dwRefreshRate", adapter_mode
.RefreshRate
);
941 hr
= add_ui4_property(display_adapter
, L
"dwBpp", depth_for_pixelformat(adapter_mode
.Format
));
945 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"%d x %d (%d bit) (%dHz)", adapter_mode
.Width
,
946 adapter_mode
.Height
, depth_for_pixelformat(adapter_mode
.Format
),
947 adapter_mode
.RefreshRate
);
949 hr
= add_bstr_property(display_adapter
, L
"szDisplayModeLocalized", buffer
);
953 hr
= add_bstr_property(display_adapter
, L
"szDisplayModeEnglish", buffer
);
958 hr
= add_bstr_property(display_adapter
, L
"szKeyDeviceKey", L
"");
962 hr
= add_bstr_property(display_adapter
, L
"szKeyDeviceID", L
"");
966 hr
= add_bstr_property(display_adapter
, L
"szChipType", L
"");
970 hr
= add_bstr_property(display_adapter
, L
"szDACType", L
"");
974 hr
= add_bstr_property(display_adapter
, L
"szRevision", L
"");
978 if (!get_texture_memory(&adapter_info
.DeviceIdentifier
, &available_mem
))
979 WARN("get_texture_memory helper failed\n");
981 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"%.1f MB", available_mem
/ 1000000.0f
);
983 hr
= add_bstr_property(display_adapter
, L
"szDisplayMemoryLocalized", buffer
);
987 hr
= add_bstr_property(display_adapter
, L
"szDisplayMemoryEnglish", buffer
);
991 hr
= IDirect3D9_GetDeviceCaps(pDirect3D9
, index
, D3DDEVTYPE_HAL
, &device_caps
);
992 hardware_accel
= SUCCEEDED(hr
);
994 hr
= add_bool_property(display_adapter
, L
"b3DAccelerationEnabled", hardware_accel
);
998 hr
= add_bool_property(display_adapter
, L
"b3DAccelerationExists", hardware_accel
);
1002 hr
= add_bool_property(display_adapter
, L
"bDDAccelerationEnabled", hardware_accel
);
1006 hr
= add_bool_property(display_adapter
, L
"bNoHardware", FALSE
);
1010 hr
= add_bool_property(display_adapter
, L
"bCanRenderWindow", TRUE
);
1014 hr
= add_bstr_property(display_adapter
, L
"szMonitorName", L
"Generic PnP Monitor");
1018 hr
= add_bstr_property(display_adapter
, L
"szMonitorMaxRes", L
"Failed to get parameter");
1022 hr
= add_bstr_property(display_adapter
, L
"szDriverAttributes", L
"Final Retail");
1026 hr
= add_bstr_property(display_adapter
, L
"szDriverLanguageEnglish", L
"English");
1030 hr
= add_bstr_property(display_adapter
, L
"szDriverLanguageLocalized", L
"English");
1034 hr
= add_bstr_property(display_adapter
, L
"szDriverDateEnglish", L
"1/1/2016 10:00:00");
1038 hr
= add_bstr_property(display_adapter
, L
"szDriverDateLocalized", L
"1/1/2016 10:00:00 AM");
1042 hr
= add_i4_property(display_adapter
, L
"lDriverSize", 10 * 1024 * 1024);
1046 hr
= add_bstr_property(display_adapter
, L
"szMiniVdd", L
"n/a");
1050 hr
= add_bstr_property(display_adapter
, L
"szMiniVddDateLocalized", L
"n/a");
1054 hr
= add_bstr_property(display_adapter
, L
"szMiniVddDateEnglish", L
"n/a");
1058 hr
= add_i4_property(display_adapter
, L
"lMiniVddSize", 0);
1062 hr
= add_bstr_property(display_adapter
, L
"szVdd", L
"n/a");
1066 hr
= add_bool_property(display_adapter
, L
"bDriverBeta", FALSE
);
1070 hr
= add_bool_property(display_adapter
, L
"bDriverDebug", FALSE
);
1074 hr
= add_bool_property(display_adapter
, L
"bDriverSigned", TRUE
);
1078 hr
= add_bool_property(display_adapter
, L
"bDriverSignedValid", TRUE
);
1082 hr
= add_bstr_property(display_adapter
, L
"szDriverSignDate", L
"n/a");
1086 hr
= add_ui4_property(display_adapter
, L
"dwDDIVersion", 11);
1090 hr
= add_bstr_property(display_adapter
, L
"szDDIVersionEnglish", L
"11");
1094 hr
= add_bstr_property(display_adapter
, L
"szDDIVersionLocalized", L
"11");
1098 hr
= add_ui4_property(display_adapter
, L
"iAdapter", index
);
1102 hr
= add_ui4_property(display_adapter
, L
"dwWHQLLevel", 0);
1109 IDirect3D9_Release(pDirect3D9
);
1113 static HRESULT
fill_display_information_fallback(IDxDiagContainerImpl_Container
*node
)
1115 static const WCHAR
*empty_properties
[] =
1117 L
"szDeviceIdentifier", L
"szVendorId", L
"szDeviceId", L
"szKeyDeviceKey",
1118 L
"szKeyDeviceID", L
"szDriverName", L
"szDriverVersion", L
"szSubSysId",
1119 L
"szRevisionId", L
"szManufacturer", L
"szChipType", L
"szDACType", L
"szRevision"
1122 IDxDiagContainerImpl_Container
*display_adapter
;
1124 IDirectDraw7
*pDirectDraw
;
1126 DISPLAY_DEVICEW disp_dev
;
1127 DDSURFACEDESC2 surface_descr
;
1131 display_adapter
= allocate_information_node(L
"0");
1132 if (!display_adapter
)
1133 return E_OUTOFMEMORY
;
1135 add_subcontainer(node
, display_adapter
);
1137 disp_dev
.cb
= sizeof(disp_dev
);
1138 if (EnumDisplayDevicesW( NULL
, 0, &disp_dev
, 0 ))
1140 hr
= add_bstr_property(display_adapter
, L
"szDeviceName", disp_dev
.DeviceName
);
1144 hr
= add_bstr_property(display_adapter
, L
"szDescription", disp_dev
.DeviceString
);
1149 /* Silently ignore a failure from DirectDrawCreateEx. */
1150 hr
= DirectDrawCreateEx(NULL
, (void **)&pDirectDraw
, &IID_IDirectDraw7
, NULL
);
1154 dd_caps
.dwCaps
= DDSCAPS_LOCALVIDMEM
| DDSCAPS_VIDEOMEMORY
;
1155 dd_caps
.dwCaps2
= dd_caps
.dwCaps3
= dd_caps
.dwCaps4
= 0;
1156 hr
= IDirectDraw7_GetAvailableVidMem(pDirectDraw
, &dd_caps
, &tmp
, NULL
);
1159 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"%.1f MB", tmp
/ 1000000.0f
);
1161 hr
= add_bstr_property(display_adapter
, L
"szDisplayMemoryLocalized", buffer
);
1165 hr
= add_bstr_property(display_adapter
, L
"szDisplayMemoryEnglish", buffer
);
1170 surface_descr
.dwSize
= sizeof(surface_descr
);
1171 hr
= IDirectDraw7_GetDisplayMode(pDirectDraw
, &surface_descr
);
1174 if (surface_descr
.dwFlags
& DDSD_WIDTH
)
1176 hr
= add_ui4_property(display_adapter
, L
"dwWidth", surface_descr
.dwWidth
);
1181 if (surface_descr
.dwFlags
& DDSD_HEIGHT
)
1183 hr
= add_ui4_property(display_adapter
, L
"dwHeight", surface_descr
.dwHeight
);
1188 if (surface_descr
.dwFlags
& DDSD_PIXELFORMAT
)
1190 hr
= add_ui4_property(display_adapter
, L
"dwBpp",
1191 surface_descr
.ddpfPixelFormat
.dwRGBBitCount
);
1197 hr
= add_ui4_property(display_adapter
, L
"dwRefreshRate", 60);
1201 for (tmp
= 0; tmp
< ARRAY_SIZE(empty_properties
); tmp
++)
1203 hr
= add_bstr_property(display_adapter
, empty_properties
[tmp
], L
"");
1210 IDirectDraw7_Release(pDirectDraw
);
1214 static HRESULT
build_displaydevices_tree(IDxDiagContainerImpl_Container
*node
)
1218 /* Try to use Direct3D to obtain the required information first. */
1219 hr
= fill_display_information_d3d(node
);
1223 return fill_display_information_fallback(node
);
1228 IDxDiagContainerImpl_Container
*cont
;
1233 static LPWSTR
guid_to_string(LPWSTR lpwstr
, REFGUID lpcguid
)
1235 wsprintfW(lpwstr
, L
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", lpcguid
->Data1
, lpcguid
->Data2
,
1236 lpcguid
->Data3
, lpcguid
->Data4
[0], lpcguid
->Data4
[1], lpcguid
->Data4
[2], lpcguid
->Data4
[3], lpcguid
->Data4
[4],
1237 lpcguid
->Data4
[5], lpcguid
->Data4
[6], lpcguid
->Data4
[7]);
1242 BOOL CALLBACK
dsound_enum(LPGUID guid
, LPCWSTR desc
, LPCWSTR module
, LPVOID context
)
1244 struct enum_context
*enum_ctx
= context
;
1245 IDxDiagContainerImpl_Container
*device
;
1247 const WCHAR
*p
, *name
;
1249 /* the default device is enumerated twice, one time without GUID */
1250 if (!guid
) return TRUE
;
1252 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"%u", enum_ctx
->index
);
1253 device
= allocate_information_node(buffer
);
1256 enum_ctx
->hr
= E_OUTOFMEMORY
;
1260 add_subcontainer(enum_ctx
->cont
, device
);
1262 guid_to_string(buffer
, guid
);
1263 enum_ctx
->hr
= add_bstr_property(device
, L
"szGuidDeviceID", buffer
);
1264 if (FAILED(enum_ctx
->hr
))
1267 enum_ctx
->hr
= add_bstr_property(device
, L
"szDescription", desc
);
1268 if (FAILED(enum_ctx
->hr
))
1271 enum_ctx
->hr
= add_bstr_property(device
, L
"szDriverPath", module
);
1272 if (FAILED(enum_ctx
->hr
))
1276 if ((p
= wcsrchr(name
, '\\'))) name
= p
+ 1;
1277 if ((p
= wcsrchr(name
, '/'))) name
= p
+ 1;
1279 enum_ctx
->hr
= add_bstr_property(device
, L
"szDriverName", name
);
1280 if (FAILED(enum_ctx
->hr
))
1287 static HRESULT
build_directsound_tree(IDxDiagContainerImpl_Container
*node
)
1289 struct enum_context enum_ctx
;
1290 IDxDiagContainerImpl_Container
*cont
;
1292 cont
= allocate_information_node(L
"DxDiag_SoundDevices");
1294 return E_OUTOFMEMORY
;
1296 add_subcontainer(node
, cont
);
1298 enum_ctx
.cont
= cont
;
1302 DirectSoundEnumerateW(dsound_enum
, &enum_ctx
);
1303 if (FAILED(enum_ctx
.hr
))
1306 cont
= allocate_information_node(L
"DxDiag_SoundCaptureDevices");
1308 return E_OUTOFMEMORY
;
1310 add_subcontainer(node
, cont
);
1312 enum_ctx
.cont
= cont
;
1316 DirectSoundCaptureEnumerateW(dsound_enum
, &enum_ctx
);
1317 if (FAILED(enum_ctx
.hr
))
1323 static HRESULT
build_directmusic_tree(IDxDiagContainerImpl_Container
*node
)
1328 static HRESULT
build_directinput_tree(IDxDiagContainerImpl_Container
*node
)
1333 static HRESULT
build_directplay_tree(IDxDiagContainerImpl_Container
*node
)
1338 static HRESULT
build_systemdevices_tree(IDxDiagContainerImpl_Container
*node
)
1343 static HRESULT
fill_file_description(IDxDiagContainerImpl_Container
*node
, const WCHAR
*szFilePath
, const WCHAR
*szFileName
)
1347 WCHAR szVersion_v
[1024];
1349 void *pVersionInfo
= NULL
;
1350 BOOL boolret
= FALSE
;
1352 VS_FIXEDFILEINFO
*pFileInfo
;
1354 TRACE("Filling container %p for %s in %s\n", node
,
1355 debugstr_w(szFileName
), debugstr_w(szFilePath
));
1357 szFile
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
) * (lstrlenW(szFilePath
) +
1358 lstrlenW(szFileName
) + 2 /* slash + terminator */));
1360 return E_OUTOFMEMORY
;
1362 lstrcpyW(szFile
, szFilePath
);
1363 lstrcatW(szFile
, L
"\\");
1364 lstrcatW(szFile
, szFileName
);
1366 retval
= GetFileVersionInfoSizeW(szFile
, &hdl
);
1369 pVersionInfo
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, retval
);
1376 if (GetFileVersionInfoW(szFile
, 0, retval
, pVersionInfo
) &&
1377 VerQueryValueW(pVersionInfo
, L
"\\", (void **)&pFileInfo
, &uiLength
))
1381 hr
= add_bstr_property(node
, L
"szPath", szFile
);
1385 hr
= add_bstr_property(node
, L
"szName", szFileName
);
1389 hr
= add_bool_property(node
, L
"bExists", boolret
);
1395 swprintf(szVersion_v
, ARRAY_SIZE(szVersion_v
), L
"%u.%02u.%04u.%04u",
1396 HIWORD(pFileInfo
->dwFileVersionMS
), LOWORD(pFileInfo
->dwFileVersionMS
),
1397 HIWORD(pFileInfo
->dwFileVersionLS
), LOWORD(pFileInfo
->dwFileVersionLS
));
1399 TRACE("Found version as (%s)\n", debugstr_w(szVersion_v
));
1401 hr
= add_bstr_property(node
, L
"szVersion", szVersion_v
);
1405 hr
= add_bstr_property(node
, L
"szAttributes", L
"Final Retail");
1409 hr
= add_bstr_property(node
, L
"szLanguageEnglish", L
"English");
1413 hr
= add_ui4_property(node
, L
"dwFileTimeHigh", pFileInfo
->dwFileDateMS
);
1417 hr
= add_ui4_property(node
, L
"dwFileTimeLow", pFileInfo
->dwFileDateLS
);
1421 hr
= add_bool_property(node
, L
"bBeta",
1422 ((pFileInfo
->dwFileFlags
& pFileInfo
->dwFileFlagsMask
) & VS_FF_PRERELEASE
) != 0);
1426 hr
= add_bool_property(node
, L
"bDebug",
1427 ((pFileInfo
->dwFileFlags
& pFileInfo
->dwFileFlagsMask
) & VS_FF_DEBUG
) != 0);
1434 HeapFree(GetProcessHeap(), 0, pVersionInfo
);
1435 HeapFree(GetProcessHeap(), 0, szFile
);
1439 static HRESULT
build_directxfiles_tree(IDxDiagContainerImpl_Container
*node
)
1441 static const WCHAR dlls
[][15] =
1466 WCHAR szFilePath
[MAX_PATH
];
1469 GetSystemDirectoryW(szFilePath
, MAX_PATH
);
1471 for (i
= 0; i
< ARRAY_SIZE(dlls
); i
++)
1474 IDxDiagContainerImpl_Container
*file_container
;
1476 swprintf(szFileID
, ARRAY_SIZE(szFileID
), L
"%d", i
);
1478 file_container
= allocate_information_node(szFileID
);
1479 if (!file_container
)
1480 return E_OUTOFMEMORY
;
1482 hr
= fill_file_description(file_container
, szFilePath
, dlls
[i
]);
1485 free_information_tree(file_container
);
1489 add_subcontainer(node
, file_container
);
1495 static HRESULT
read_property_names(IPropertyBag
*pPropBag
, VARIANT
*friendly_name
, VARIANT
*clsid_name
)
1499 VariantInit(friendly_name
);
1500 VariantInit(clsid_name
);
1502 hr
= IPropertyBag_Read(pPropBag
, L
"FriendlyName", friendly_name
, 0);
1506 hr
= IPropertyBag_Read(pPropBag
, L
"CLSID", clsid_name
, 0);
1509 VariantClear(friendly_name
);
1516 static HRESULT
fill_filter_data_information(IDxDiagContainerImpl_Container
*subcont
, BYTE
*pData
, ULONG cb
)
1519 IFilterMapper2
*pFileMapper
= NULL
;
1520 IAMFilterData
*pFilterData
= NULL
;
1522 REGFILTER2
*pRF
= NULL
;
1525 DWORD dwNOutputs
= 0;
1526 DWORD dwNInputs
= 0;
1528 hr
= CoCreateInstance(&CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC
, &IID_IFilterMapper2
,
1529 (void **)&pFileMapper
);
1533 hr
= IFilterMapper2_QueryInterface(pFileMapper
, &IID_IAMFilterData
, (void **)&pFilterData
);
1537 hr
= IAMFilterData_ParseFilterData(pFilterData
, pData
, cb
, &ppRF
);
1540 pRF
= ((REGFILTER2
**)ppRF
)[0];
1542 swprintf(bufferW
, ARRAY_SIZE(bufferW
), L
"v%d", pRF
->dwVersion
);
1543 hr
= add_bstr_property(subcont
, L
"szVersion", bufferW
);
1547 if (pRF
->dwVersion
== 1)
1549 for (j
= 0; j
< pRF
->cPins
; j
++)
1550 if (pRF
->rgPins
[j
].bOutput
)
1555 else if (pRF
->dwVersion
== 2)
1557 for (j
= 0; j
< pRF
->cPins2
; j
++)
1558 if (pRF
->rgPins2
[j
].dwFlags
& REG_PINFLAG_B_OUTPUT
)
1564 hr
= add_ui4_property(subcont
, L
"dwInputs", dwNInputs
);
1568 hr
= add_ui4_property(subcont
, L
"dwOutputs", dwNOutputs
);
1572 hr
= add_ui4_property(subcont
, L
"dwMerit", pRF
->dwMerit
);
1579 if (pFilterData
) IAMFilterData_Release(pFilterData
);
1580 if (pFileMapper
) IFilterMapper2_Release(pFileMapper
);
1585 static HRESULT
fill_filter_container(IDxDiagContainerImpl_Container
*subcont
, IMoniker
*pMoniker
)
1588 IPropertyBag
*pPropFilterBag
= NULL
;
1590 VARIANT friendly_name
;
1594 VariantInit(&friendly_name
);
1595 VariantInit(&clsid_name
);
1598 hr
= IMoniker_BindToStorage(pMoniker
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&pPropFilterBag
);
1602 hr
= read_property_names(pPropFilterBag
, &friendly_name
, &clsid_name
);
1606 TRACE("Name = %s\n", debugstr_w(V_BSTR(&friendly_name
)));
1607 TRACE("CLSID = %s\n", debugstr_w(V_BSTR(&clsid_name
)));
1609 hr
= add_bstr_property(subcont
, L
"szName", V_BSTR(&friendly_name
));
1613 hr
= add_bstr_property(subcont
, L
"ClsidFilter", V_BSTR(&clsid_name
));
1617 hr
= IPropertyBag_Read(pPropFilterBag
, L
"FilterData", &v
, NULL
);
1621 hr
= SafeArrayAccessData(V_ARRAY(&v
), (void **)&pData
);
1625 hr
= fill_filter_data_information(subcont
, pData
, V_ARRAY(&v
)->rgsabound
->cElements
);
1626 SafeArrayUnaccessData(V_ARRAY(&v
));
1633 VariantClear(&clsid_name
);
1634 VariantClear(&friendly_name
);
1635 if (pPropFilterBag
) IPropertyBag_Release(pPropFilterBag
);
1640 static HRESULT
build_directshowfilters_tree(IDxDiagContainerImpl_Container
*node
)
1644 ICreateDevEnum
*pCreateDevEnum
;
1645 IEnumMoniker
*pEmCat
= NULL
;
1646 IMoniker
*pMCat
= NULL
;
1647 IEnumMoniker
*pEnum
= NULL
;
1649 hr
= CoCreateInstance(&CLSID_SystemDeviceEnum
, NULL
, CLSCTX_INPROC_SERVER
,
1650 &IID_ICreateDevEnum
, (void **)&pCreateDevEnum
);
1654 hr
= ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum
, &CLSID_ActiveMovieCategories
, &pEmCat
, 0);
1658 while (IEnumMoniker_Next(pEmCat
, 1, &pMCat
, NULL
) == S_OK
)
1662 IPropertyBag
*pPropBag
;
1664 IMoniker
*pMoniker
= NULL
;
1666 hr
= IMoniker_BindToStorage(pMCat
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&pPropBag
);
1669 IMoniker_Release(pMCat
);
1673 hr
= read_property_names(pPropBag
, &vCatName
, &vCatClsid
);
1674 IPropertyBag_Release(pPropBag
);
1677 IMoniker_Release(pMCat
);
1681 hr
= CLSIDFromString(V_BSTR(&vCatClsid
), &clsidCat
);
1684 IMoniker_Release(pMCat
);
1685 VariantClear(&vCatClsid
);
1686 VariantClear(&vCatName
);
1690 hr
= ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum
, &clsidCat
, &pEnum
, 0);
1693 IMoniker_Release(pMCat
);
1694 VariantClear(&vCatClsid
);
1695 VariantClear(&vCatName
);
1699 TRACE("Enumerating class %s\n", debugstr_guid(&clsidCat
));
1701 while (IEnumMoniker_Next(pEnum
, 1, &pMoniker
, NULL
) == S_OK
)
1704 IDxDiagContainerImpl_Container
*subcont
;
1706 swprintf(bufferW
, ARRAY_SIZE(bufferW
), L
"%d", i
);
1707 subcont
= allocate_information_node(bufferW
);
1711 IMoniker_Release(pMoniker
);
1715 hr
= add_bstr_property(subcont
, L
"szCatName", V_BSTR(&vCatName
));
1718 free_information_tree(subcont
);
1719 IMoniker_Release(pMoniker
);
1723 hr
= add_bstr_property(subcont
, L
"ClsidCat", V_BSTR(&vCatClsid
));
1726 free_information_tree(subcont
);
1727 IMoniker_Release(pMoniker
);
1731 hr
= fill_filter_container(subcont
, pMoniker
);
1732 IMoniker_Release(pMoniker
);
1735 WARN("Skipping invalid filter\n");
1736 free_information_tree(subcont
);
1741 add_subcontainer(node
, subcont
);
1745 IEnumMoniker_Release(pEnum
);
1746 IMoniker_Release(pMCat
);
1747 VariantClear(&vCatClsid
);
1748 VariantClear(&vCatName
);
1755 if (pEmCat
) IEnumMoniker_Release(pEmCat
);
1756 ICreateDevEnum_Release(pCreateDevEnum
);
1760 static HRESULT
build_logicaldisks_tree(IDxDiagContainerImpl_Container
*node
)
1765 static HRESULT
build_information_tree(IDxDiagContainerImpl_Container
**pinfo_root
)
1770 HRESULT (*initfunc
)(IDxDiagContainerImpl_Container
*);
1773 {L
"DxDiag_SystemInfo", build_systeminfo_tree
},
1774 {L
"DxDiag_DisplayDevices", build_displaydevices_tree
},
1775 {L
"DxDiag_DirectSound", build_directsound_tree
},
1776 {L
"DxDiag_DirectMusic", build_directmusic_tree
},
1777 {L
"DxDiag_DirectInput", build_directinput_tree
},
1778 {L
"DxDiag_DirectPlay", build_directplay_tree
},
1779 {L
"DxDiag_SystemDevices", build_systemdevices_tree
},
1780 {L
"DxDiag_DirectXFiles", build_directxfiles_tree
},
1781 {L
"DxDiag_DirectShowFilters", build_directshowfilters_tree
},
1782 {L
"DxDiag_LogicalDisks", build_logicaldisks_tree
},
1785 IDxDiagContainerImpl_Container
*info_root
;
1788 info_root
= allocate_information_node(NULL
);
1790 return E_OUTOFMEMORY
;
1792 for (index
= 0; index
< ARRAY_SIZE(root_children
); index
++)
1794 IDxDiagContainerImpl_Container
*node
;
1797 node
= allocate_information_node(root_children
[index
].name
);
1800 free_information_tree(info_root
);
1801 return E_OUTOFMEMORY
;
1804 hr
= root_children
[index
].initfunc(node
);
1807 free_information_tree(node
);
1808 free_information_tree(info_root
);
1812 add_subcontainer(info_root
, node
);
1815 *pinfo_root
= info_root
;