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 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
27 #include "dxdiag_private.h"
36 #include "wine/fil_data.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(dxdiag
);
45 static HRESULT
build_information_tree(IDxDiagContainerImpl_Container
**pinfo_root
);
46 static void free_information_tree(IDxDiagContainerImpl_Container
*node
);
48 struct IDxDiagProviderImpl
50 IDxDiagProvider IDxDiagProvider_iface
;
53 DXDIAG_INIT_PARAMS params
;
54 IDxDiagContainerImpl_Container
*info_root
;
57 static inline IDxDiagProviderImpl
*impl_from_IDxDiagProvider(IDxDiagProvider
*iface
)
59 return CONTAINING_RECORD(iface
, IDxDiagProviderImpl
, IDxDiagProvider_iface
);
62 /* IDxDiagProvider IUnknown parts follow: */
63 static HRESULT WINAPI
IDxDiagProviderImpl_QueryInterface(IDxDiagProvider
*iface
, REFIID riid
,
66 IDxDiagProviderImpl
*This
= impl_from_IDxDiagProvider(iface
);
68 if (!ppobj
) return E_INVALIDARG
;
70 if (IsEqualGUID(riid
, &IID_IUnknown
)
71 || IsEqualGUID(riid
, &IID_IDxDiagProvider
)) {
72 IUnknown_AddRef(iface
);
77 WARN("(%p)->(%s,%p),not found\n",This
,debugstr_guid(riid
),ppobj
);
82 static ULONG WINAPI
IDxDiagProviderImpl_AddRef(IDxDiagProvider
*iface
)
84 IDxDiagProviderImpl
*This
= impl_from_IDxDiagProvider(iface
);
85 ULONG refCount
= InterlockedIncrement(&This
->ref
);
87 TRACE("(%p)->(ref before=%lu)\n", This
, refCount
- 1);
94 static ULONG WINAPI
IDxDiagProviderImpl_Release(IDxDiagProvider
*iface
)
96 IDxDiagProviderImpl
*This
= impl_from_IDxDiagProvider(iface
);
97 ULONG refCount
= InterlockedDecrement(&This
->ref
);
99 TRACE("(%p)->(ref before=%lu)\n", This
, refCount
+ 1);
102 free_information_tree(This
->info_root
);
103 HeapFree(GetProcessHeap(), 0, This
);
106 DXDIAGN_UnlockModule();
111 /* IDxDiagProvider Interface follow: */
112 static HRESULT WINAPI
IDxDiagProviderImpl_Initialize(IDxDiagProvider
*iface
,
113 DXDIAG_INIT_PARAMS
*pParams
)
115 IDxDiagProviderImpl
*This
= impl_from_IDxDiagProvider(iface
);
118 TRACE("(%p,%p)\n", iface
, pParams
);
120 if (NULL
== pParams
) {
123 if (pParams
->dwSize
!= sizeof(DXDIAG_INIT_PARAMS
) ||
124 pParams
->dwDxDiagHeaderVersion
!= DXDIAG_DX9_SDK_VERSION
) {
128 if (!This
->info_root
)
130 hr
= build_information_tree(&This
->info_root
);
136 memcpy(&This
->params
, pParams
, pParams
->dwSize
);
140 static HRESULT WINAPI
IDxDiagProviderImpl_GetRootContainer(IDxDiagProvider
*iface
,
141 IDxDiagContainer
**ppInstance
)
143 IDxDiagProviderImpl
*This
= impl_from_IDxDiagProvider(iface
);
145 TRACE("(%p,%p)\n", iface
, ppInstance
);
147 if (FALSE
== This
->init
) {
148 return CO_E_NOTINITIALIZED
;
151 return DXDiag_CreateDXDiagContainer(&IID_IDxDiagContainer
, This
->info_root
,
152 &This
->IDxDiagProvider_iface
, (void **)ppInstance
);
155 static const IDxDiagProviderVtbl DxDiagProvider_Vtbl
=
157 IDxDiagProviderImpl_QueryInterface
,
158 IDxDiagProviderImpl_AddRef
,
159 IDxDiagProviderImpl_Release
,
160 IDxDiagProviderImpl_Initialize
,
161 IDxDiagProviderImpl_GetRootContainer
164 HRESULT
DXDiag_CreateDXDiagProvider(LPCLASSFACTORY iface
, LPUNKNOWN punkOuter
, REFIID riid
, LPVOID
*ppobj
) {
165 IDxDiagProviderImpl
* provider
;
167 TRACE("(%p, %s, %p)\n", punkOuter
, debugstr_guid(riid
), ppobj
);
170 if (punkOuter
) return CLASS_E_NOAGGREGATION
;
172 provider
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDxDiagProviderImpl
));
173 if (NULL
== provider
) return E_OUTOFMEMORY
;
174 provider
->IDxDiagProvider_iface
.lpVtbl
= &DxDiagProvider_Vtbl
;
175 provider
->ref
= 0; /* will be inited with QueryInterface */
176 return IDxDiagProviderImpl_QueryInterface(&provider
->IDxDiagProvider_iface
, riid
, ppobj
);
179 static void free_property_information(IDxDiagContainerImpl_Property
*prop
)
181 VariantClear(&prop
->vProp
);
182 HeapFree(GetProcessHeap(), 0, prop
->propName
);
183 HeapFree(GetProcessHeap(), 0, prop
);
186 static void free_information_tree(IDxDiagContainerImpl_Container
*node
)
188 IDxDiagContainerImpl_Container
*ptr
, *cursor2
;
193 HeapFree(GetProcessHeap(), 0, node
->contName
);
195 LIST_FOR_EACH_ENTRY_SAFE(ptr
, cursor2
, &node
->subContainers
, IDxDiagContainerImpl_Container
, entry
)
197 IDxDiagContainerImpl_Property
*prop
, *prop_cursor2
;
199 LIST_FOR_EACH_ENTRY_SAFE(prop
, prop_cursor2
, &ptr
->properties
, IDxDiagContainerImpl_Property
, entry
)
201 list_remove(&prop
->entry
);
202 free_property_information(prop
);
205 list_remove(&ptr
->entry
);
206 free_information_tree(ptr
);
209 HeapFree(GetProcessHeap(), 0, node
);
212 static IDxDiagContainerImpl_Container
*allocate_information_node(const WCHAR
*name
)
214 IDxDiagContainerImpl_Container
*ret
;
216 ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ret
));
222 ret
->contName
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name
) + 1) * sizeof(*name
));
225 HeapFree(GetProcessHeap(), 0, ret
);
228 lstrcpyW(ret
->contName
, name
);
231 list_init(&ret
->subContainers
);
232 list_init(&ret
->properties
);
237 static IDxDiagContainerImpl_Property
*allocate_property_information(const WCHAR
*name
)
239 IDxDiagContainerImpl_Property
*ret
;
241 ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ret
));
245 ret
->propName
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name
) + 1) * sizeof(*name
));
248 HeapFree(GetProcessHeap(), 0, ret
);
251 lstrcpyW(ret
->propName
, name
);
256 static inline void add_subcontainer(IDxDiagContainerImpl_Container
*node
, IDxDiagContainerImpl_Container
*subCont
)
258 list_add_tail(&node
->subContainers
, &subCont
->entry
);
259 ++node
->nSubContainers
;
262 static inline HRESULT
add_bstr_property(IDxDiagContainerImpl_Container
*node
, const WCHAR
*propName
, const WCHAR
*str
)
264 IDxDiagContainerImpl_Property
*prop
;
267 prop
= allocate_property_information(propName
);
269 return E_OUTOFMEMORY
;
271 bstr
= SysAllocString(str
);
274 free_property_information(prop
);
275 return E_OUTOFMEMORY
;
278 V_VT(&prop
->vProp
) = VT_BSTR
;
279 V_BSTR(&prop
->vProp
) = bstr
;
281 list_add_tail(&node
->properties
, &prop
->entry
);
287 static inline HRESULT
add_ui4_property(IDxDiagContainerImpl_Container
*node
, const WCHAR
*propName
, DWORD data
)
289 IDxDiagContainerImpl_Property
*prop
;
291 prop
= allocate_property_information(propName
);
293 return E_OUTOFMEMORY
;
295 V_VT(&prop
->vProp
) = VT_UI4
;
296 V_UI4(&prop
->vProp
) = data
;
298 list_add_tail(&node
->properties
, &prop
->entry
);
304 static inline HRESULT
add_i4_property(IDxDiagContainerImpl_Container
*node
, const WCHAR
*propName
, LONG data
)
306 IDxDiagContainerImpl_Property
*prop
;
308 prop
= allocate_property_information(propName
);
310 return E_OUTOFMEMORY
;
312 V_VT(&prop
->vProp
) = VT_I4
;
313 V_I4(&prop
->vProp
) = data
;
315 list_add_tail(&node
->properties
, &prop
->entry
);
321 static inline HRESULT
add_bool_property(IDxDiagContainerImpl_Container
*node
, const WCHAR
*propName
, BOOL data
)
323 IDxDiagContainerImpl_Property
*prop
;
325 prop
= allocate_property_information(propName
);
327 return E_OUTOFMEMORY
;
329 V_VT(&prop
->vProp
) = VT_BOOL
;
330 V_BOOL(&prop
->vProp
) = data
? VARIANT_TRUE
: VARIANT_FALSE
;
332 list_add_tail(&node
->properties
, &prop
->entry
);
338 static inline HRESULT
add_ull_as_bstr_property(IDxDiagContainerImpl_Container
*node
, const WCHAR
*propName
, ULONGLONG data
)
340 IDxDiagContainerImpl_Property
*prop
;
343 prop
= allocate_property_information(propName
);
345 return E_OUTOFMEMORY
;
347 V_VT(&prop
->vProp
) = VT_UI8
;
348 V_UI8(&prop
->vProp
) = data
;
350 hr
= VariantChangeType(&prop
->vProp
, &prop
->vProp
, 0, VT_BSTR
);
353 free_property_information(prop
);
357 list_add_tail(&node
->properties
, &prop
->entry
);
363 /* Copied from programs/taskkill/taskkill.c. */
364 static DWORD
*enumerate_processes(DWORD
*list_count
)
366 DWORD
*pid_list
, alloc_bytes
= 1024 * sizeof(*pid_list
), needed_bytes
;
368 pid_list
= HeapAlloc(GetProcessHeap(), 0, alloc_bytes
);
376 if (!EnumProcesses(pid_list
, alloc_bytes
, &needed_bytes
))
378 HeapFree(GetProcessHeap(), 0, pid_list
);
382 /* EnumProcesses can't signal an insufficient buffer condition, so the
383 * only way to possibly determine whether a larger buffer is required
384 * is to see whether the written number of bytes is the same as the
385 * buffer size. If so, the buffer will be reallocated to twice the
387 if (alloc_bytes
!= needed_bytes
)
391 realloc_list
= HeapReAlloc(GetProcessHeap(), 0, pid_list
, alloc_bytes
);
394 HeapFree(GetProcessHeap(), 0, pid_list
);
397 pid_list
= realloc_list
;
400 *list_count
= needed_bytes
/ sizeof(*pid_list
);
404 /* Copied from programs/taskkill/taskkill.c. */
405 static BOOL
get_process_name_from_pid(DWORD pid
, WCHAR
*buf
, DWORD chars
)
411 process
= OpenProcess(PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
, FALSE
, pid
);
415 if (!EnumProcessModules(process
, &module
, sizeof(module
), &required_size
))
417 CloseHandle(process
);
421 if (!GetModuleBaseNameW(process
, module
, buf
, chars
))
423 CloseHandle(process
);
427 CloseHandle(process
);
431 /* dxdiagn's detection scheme is simply to look for a process called conf.exe. */
432 static BOOL
is_netmeeting_running(void)
435 DWORD
*pid_list
= enumerate_processes(&list_count
);
440 WCHAR process_name
[MAX_PATH
];
442 for (i
= 0; i
< list_count
; i
++)
444 if (get_process_name_from_pid(pid_list
[i
], process_name
, ARRAY_SIZE(process_name
)) &&
445 !lstrcmpW(L
"conf.exe", process_name
))
447 HeapFree(GetProcessHeap(), 0, pid_list
);
451 HeapFree(GetProcessHeap(), 0, pid_list
);
457 static HRESULT
fill_language_information(IDxDiagContainerImpl_Container
*node
)
459 WCHAR system_lang
[80], regional_setting
[100], user_lang
[80], language_str
[300];
462 /* szLanguagesLocalized */
463 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SNATIVELANGNAME
, system_lang
, ARRAY_SIZE(system_lang
));
464 LoadStringW(dxdiagn_instance
, IDS_REGIONAL_SETTING
, regional_setting
, ARRAY_SIZE(regional_setting
));
465 GetLocaleInfoW(LOCALE_USER_DEFAULT
, LOCALE_SNATIVELANGNAME
, user_lang
, ARRAY_SIZE(user_lang
));
467 swprintf(language_str
, ARRAY_SIZE(language_str
), L
"%s (%s: %s)", system_lang
, regional_setting
,
470 hr
= add_bstr_property(node
, L
"szLanguagesLocalized", language_str
);
474 /* szLanguagesEnglish */
475 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SENGLANGUAGE
, system_lang
, ARRAY_SIZE(system_lang
));
476 GetLocaleInfoW(LOCALE_USER_DEFAULT
, LOCALE_SENGLANGUAGE
, user_lang
, ARRAY_SIZE(user_lang
));
478 swprintf(language_str
, ARRAY_SIZE(language_str
), L
"%s (%s: %s)", system_lang
,
479 L
"Regional Setting", user_lang
);
481 hr
= add_bstr_property(node
, L
"szLanguagesEnglish", language_str
);
488 static HRESULT
fill_datetime_information(IDxDiagContainerImpl_Container
*node
)
491 WCHAR date_str
[80], time_str
[80], datetime_str
[200];
494 GetLocalTime(&curtime
);
496 GetTimeFormatW(LOCALE_NEUTRAL
, 0, &curtime
, L
"HH':'mm':'ss", time_str
, ARRAY_SIZE(time_str
));
498 /* szTimeLocalized */
499 GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &curtime
, NULL
, date_str
, ARRAY_SIZE(date_str
));
501 swprintf(datetime_str
, ARRAY_SIZE(datetime_str
), L
"%s, %s", date_str
, time_str
);
503 hr
= add_bstr_property(node
, L
"szTimeLocalized", datetime_str
);
508 GetDateFormatW(LOCALE_NEUTRAL
, 0, &curtime
, L
"M'/'d'/'yyyy", date_str
, ARRAY_SIZE(date_str
));
510 swprintf(datetime_str
, ARRAY_SIZE(datetime_str
), L
"%s, %s", date_str
, time_str
);
512 hr
= add_bstr_property(node
, L
"szTimeEnglish", datetime_str
);
519 static HRESULT
fill_os_string_information(IDxDiagContainerImpl_Container
*node
, OSVERSIONINFOW
*info
)
521 static const WCHAR
*prop_list
[] =
523 L
"szOSLocalized", L
"szOSExLocalized", L
"szOSExLongLocalized",
524 L
"szOSEnglish", L
"szOSExEnglish", L
"szOSExLongEnglish"
529 /* FIXME: OS detection should be performed, and localized OS strings
530 * should contain translated versions of the "build" phrase. */
531 for (i
= 0; i
< ARRAY_SIZE(prop_list
); i
++)
533 hr
= add_bstr_property(node
, prop_list
[i
], L
"Windows XP Professional");
541 static HRESULT
fill_processor_information(IDxDiagContainerImpl_Container
*node
)
543 IWbemLocator
*wbem_locator
;
544 IWbemServices
*wbem_service
;
545 IWbemClassObject
*wbem_class
;
546 IEnumWbemClassObject
*wbem_enum
;
547 VARIANT cpu_name
, cpu_no
, clock_speed
;
548 WCHAR print_buf
[200];
553 hr
= CoCreateInstance(&CLSID_WbemLocator
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IWbemLocator
, (void**)&wbem_locator
);
557 bstr
= SysAllocString(L
"\\\\.\\root\\cimv2");
559 IWbemLocator_Release(wbem_locator
);
560 return E_OUTOFMEMORY
;
562 hr
= IWbemLocator_ConnectServer(wbem_locator
, bstr
, NULL
, NULL
, NULL
, 0, NULL
, NULL
, &wbem_service
);
563 IWbemLocator_Release(wbem_locator
);
568 bstr
= SysAllocString(L
"Win32_Processor");
570 IWbemServices_Release(wbem_service
);
571 return E_OUTOFMEMORY
;
573 hr
= IWbemServices_CreateInstanceEnum(wbem_service
, bstr
, WBEM_FLAG_SYSTEM_ONLY
, NULL
, &wbem_enum
);
574 IWbemServices_Release(wbem_service
);
579 hr
= IEnumWbemClassObject_Next(wbem_enum
, 1000, 1, &wbem_class
, &no
);
580 IEnumWbemClassObject_Release(wbem_enum
);
584 hr
= IWbemClassObject_Get(wbem_class
, L
"NumberOfLogicalProcessors", 0, &cpu_no
, NULL
, NULL
);
586 IWbemClassObject_Release(wbem_class
);
589 hr
= IWbemClassObject_Get(wbem_class
, L
"MaxClockSpeed", 0, &clock_speed
, NULL
, NULL
);
591 IWbemClassObject_Release(wbem_class
);
594 hr
= IWbemClassObject_Get(wbem_class
, L
"Name", 0, &cpu_name
, NULL
, NULL
);
595 IWbemClassObject_Release(wbem_class
);
599 swprintf(print_buf
, ARRAY_SIZE(print_buf
), L
"%s(%d CPUs), ~%dMHz",
600 V_BSTR(&cpu_name
), V_I4(&cpu_no
), V_I4(&clock_speed
));
601 VariantClear(&cpu_name
);
602 VariantClear(&cpu_no
);
603 VariantClear(&clock_speed
);
605 return add_bstr_property(node
, L
"szProcessorEnglish", print_buf
);
608 static HRESULT
build_systeminfo_tree(IDxDiagContainerImpl_Container
*node
)
613 DWORD count
, usedpage_mb
, availpage_mb
;
614 WCHAR buffer
[MAX_PATH
], computer_name
[MAX_COMPUTERNAME_LENGTH
+ 1], print_buf
[200], localized_pagefile_fmt
[200];
617 hr
= add_ui4_property(node
, L
"dwDirectXVersionMajor", 9);
621 hr
= add_ui4_property(node
, L
"dwDirectXVersionMinor", 0);
625 hr
= add_bstr_property(node
, L
"szDirectXVersionLetter", L
"c");
629 hr
= add_bstr_property(node
, L
"szDirectXVersionEnglish", L
"4.09.0000.0904");
633 hr
= add_bstr_property(node
, L
"szDirectXVersionLongEnglish", L
"= \"DirectX 9.0c (4.09.0000.0904)");
637 hr
= add_bool_property(node
, L
"bDebug", FALSE
);
641 hr
= add_bool_property(node
, L
"bNECPC98", FALSE
);
645 msex
.dwLength
= sizeof(msex
);
646 GlobalMemoryStatusEx(&msex
);
648 hr
= add_ull_as_bstr_property(node
, L
"ullPhysicalMemory", msex
.ullTotalPhys
);
652 hr
= add_ull_as_bstr_property(node
, L
"ullUsedPageFile", msex
.ullTotalPageFile
- msex
.ullAvailPageFile
);
656 hr
= add_ull_as_bstr_property(node
, L
"ullAvailPageFile", msex
.ullAvailPageFile
);
660 hr
= add_bool_property(node
, L
"bNetMeetingRunning", is_netmeeting_running());
664 info
.dwOSVersionInfoSize
= sizeof(info
);
665 GetVersionExW(&info
);
667 hr
= add_ui4_property(node
, L
"dwOSMajorVersion", info
.dwMajorVersion
);
671 hr
= add_ui4_property(node
, L
"dwOSMinorVersion", info
.dwMinorVersion
);
675 hr
= add_ui4_property(node
, L
"dwOSBuildNumber", info
.dwBuildNumber
);
679 hr
= add_ui4_property(node
, L
"dwOSPlatformID", info
.dwPlatformId
);
683 hr
= add_bstr_property(node
, L
"szCSDVersion", info
.szCSDVersion
);
687 /* FIXME: Roundoff should not be done with truncated division. */
688 swprintf(print_buf
, ARRAY_SIZE(print_buf
), L
"%I64uMB RAM", msex
.ullTotalPhys
/ (1024 * 1024));
689 hr
= add_bstr_property(node
, L
"szPhysicalMemoryEnglish", print_buf
);
693 usedpage_mb
= (DWORD
)((msex
.ullTotalPageFile
- msex
.ullAvailPageFile
) / (1024 * 1024));
694 availpage_mb
= (DWORD
)(msex
.ullAvailPageFile
/ (1024 * 1024));
695 LoadStringW(dxdiagn_instance
, IDS_PAGE_FILE_FORMAT
, localized_pagefile_fmt
,
696 ARRAY_SIZE(localized_pagefile_fmt
));
697 args
[0] = usedpage_mb
;
698 args
[1] = availpage_mb
;
699 FormatMessageW(FORMAT_MESSAGE_FROM_STRING
|FORMAT_MESSAGE_ARGUMENT_ARRAY
, localized_pagefile_fmt
,
700 0, 0, print_buf
, ARRAY_SIZE(print_buf
), (va_list *)args
);
702 hr
= add_bstr_property(node
, L
"szPageFileLocalized", print_buf
);
706 swprintf(print_buf
, ARRAY_SIZE(print_buf
), L
"%uMB used, %uMB available", usedpage_mb
, availpage_mb
);
708 hr
= add_bstr_property(node
, L
"szPageFileEnglish", print_buf
);
712 GetWindowsDirectoryW(buffer
, MAX_PATH
);
714 hr
= add_bstr_property(node
, L
"szWindowsDir", buffer
);
718 count
= ARRAY_SIZE(computer_name
);
719 if (!GetComputerNameW(computer_name
, &count
))
722 hr
= add_bstr_property(node
, L
"szMachineNameLocalized", computer_name
);
726 hr
= add_bstr_property(node
, L
"szMachineNameEnglish", computer_name
);
730 hr
= add_bstr_property(node
, L
"szSystemManufacturerEnglish", L
"");
734 hr
= add_bstr_property(node
, L
"szSystemModelEnglish", L
"");
738 hr
= add_bstr_property(node
, L
"szBIOSEnglish", L
"");
742 hr
= fill_processor_information(node
);
746 hr
= add_bstr_property(node
, L
"szSetupParamEnglish", L
"Not present");
750 hr
= add_bstr_property(node
, L
"szDxDiagVersion", L
"");
754 hr
= fill_language_information(node
);
758 hr
= fill_datetime_information(node
);
762 hr
= fill_os_string_information(node
, &info
);
769 /* The logic from pixelformat_for_depth() in dlls/wined3d/utils.c is reversed. */
770 static DWORD
depth_for_pixelformat(D3DFORMAT format
)
774 case D3DFMT_P8
: return 8;
775 case D3DFMT_X1R5G5B5
: return 15;
776 case D3DFMT_R5G6B5
: return 16;
777 /* This case will fail to distinguish an original bpp of 24. */
778 case D3DFMT_X8R8G8B8
: return 32;
780 FIXME("Unknown D3DFORMAT %d, returning 32 bpp\n", format
);
785 static BOOL
get_texture_memory(GUID
*adapter
, DWORD
*available_mem
)
787 IDirectDraw7
*pDirectDraw
;
791 hr
= DirectDrawCreateEx(adapter
, (void **)&pDirectDraw
, &IID_IDirectDraw7
, NULL
);
794 dd_caps
.dwCaps
= DDSCAPS_LOCALVIDMEM
| DDSCAPS_VIDEOMEMORY
;
795 dd_caps
.dwCaps2
= dd_caps
.dwCaps3
= dd_caps
.u1
.dwCaps4
= 0;
796 hr
= IDirectDraw7_GetAvailableVidMem(pDirectDraw
, &dd_caps
, available_mem
, NULL
);
797 IDirectDraw7_Release(pDirectDraw
);
805 static const WCHAR
*vendor_id_to_manufacturer_string(DWORD vendor_id
)
815 {0x1002, L
"ATI Technologies Inc."},
818 {0x1af4, L
"Red Hat"},
819 {0x8086, L
"Intel Corporation"},
822 for (i
= 0; i
< ARRAY_SIZE(vendors
); ++i
)
824 if (vendors
[i
].id
== vendor_id
)
825 return vendors
[i
].name
;
828 FIXME("Unknown PCI vendor ID 0x%04lx.\n", vendor_id
);
833 static HRESULT
fill_display_information_d3d(IDxDiagContainerImpl_Container
*node
)
835 IDxDiagContainerImpl_Container
*display_adapter
;
837 IDirect3D9
*pDirect3D9
;
841 pDirect3D9
= Direct3DCreate9(D3D_SDK_VERSION
);
845 count
= IDirect3D9_GetAdapterCount(pDirect3D9
);
846 for (index
= 0; index
< count
; index
++)
848 D3DADAPTER_IDENTIFIER9 adapter_info
;
849 D3DDISPLAYMODE adapter_mode
;
850 D3DCAPS9 device_caps
;
851 DWORD available_mem
= 0;
854 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"%u", index
);
855 display_adapter
= allocate_information_node(buffer
);
856 if (!display_adapter
)
862 add_subcontainer(node
, display_adapter
);
864 hr
= IDirect3D9_GetAdapterIdentifier(pDirect3D9
, index
, 0, &adapter_info
);
867 WCHAR driverW
[sizeof(adapter_info
.Driver
)];
868 WCHAR descriptionW
[sizeof(adapter_info
.Description
)];
869 WCHAR devicenameW
[sizeof(adapter_info
.DeviceName
)];
871 MultiByteToWideChar(CP_ACP
, 0, adapter_info
.Driver
, -1, driverW
, ARRAY_SIZE(driverW
));
872 MultiByteToWideChar(CP_ACP
, 0, adapter_info
.Description
, -1, descriptionW
,
873 ARRAY_SIZE(descriptionW
));
874 MultiByteToWideChar(CP_ACP
, 0, adapter_info
.DeviceName
, -1, devicenameW
,
875 ARRAY_SIZE(devicenameW
));
877 hr
= add_bstr_property(display_adapter
, L
"szDriverName", driverW
);
881 hr
= add_bstr_property(display_adapter
, L
"szDescription", descriptionW
);
885 hr
= add_bstr_property(display_adapter
, L
"szDeviceName", devicenameW
);
889 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"%u.%u.%04u.%04u",
890 HIWORD(adapter_info
.DriverVersion
.u
.HighPart
), LOWORD(adapter_info
.DriverVersion
.u
.HighPart
),
891 HIWORD(adapter_info
.DriverVersion
.u
.LowPart
), LOWORD(adapter_info
.DriverVersion
.u
.LowPart
));
893 hr
= add_bstr_property(display_adapter
, L
"szDriverVersion", buffer
);
897 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"0x%04x", adapter_info
.VendorId
);
898 hr
= add_bstr_property(display_adapter
, L
"szVendorId", buffer
);
902 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"0x%04x", adapter_info
.DeviceId
);
903 hr
= add_bstr_property(display_adapter
, L
"szDeviceId", buffer
);
907 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"0x%08x", adapter_info
.SubSysId
);
908 hr
= add_bstr_property(display_adapter
, L
"szSubSysId", buffer
);
912 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"0x%04x", adapter_info
.Revision
);
913 hr
= add_bstr_property(display_adapter
, L
"szRevisionId", buffer
);
917 StringFromGUID2(&adapter_info
.DeviceIdentifier
, buffer
, 39);
918 hr
= add_bstr_property(display_adapter
, L
"szDeviceIdentifier", buffer
);
922 hr
= add_bstr_property(display_adapter
, L
"szManufacturer",
923 vendor_id_to_manufacturer_string(adapter_info
.VendorId
));
928 hr
= IDirect3D9_GetAdapterDisplayMode(pDirect3D9
, index
, &adapter_mode
);
931 hr
= add_ui4_property(display_adapter
, L
"dwWidth", adapter_mode
.Width
);
935 hr
= add_ui4_property(display_adapter
, L
"dwHeight", adapter_mode
.Height
);
939 hr
= add_ui4_property(display_adapter
, L
"dwRefreshRate", adapter_mode
.RefreshRate
);
943 hr
= add_ui4_property(display_adapter
, L
"dwBpp", depth_for_pixelformat(adapter_mode
.Format
));
947 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"%d x %d (%d bit) (%dHz)", adapter_mode
.Width
,
948 adapter_mode
.Height
, depth_for_pixelformat(adapter_mode
.Format
),
949 adapter_mode
.RefreshRate
);
951 hr
= add_bstr_property(display_adapter
, L
"szDisplayModeLocalized", buffer
);
955 hr
= add_bstr_property(display_adapter
, L
"szDisplayModeEnglish", buffer
);
960 hr
= add_bstr_property(display_adapter
, L
"szKeyDeviceKey", L
"");
964 hr
= add_bstr_property(display_adapter
, L
"szKeyDeviceID", L
"");
968 hr
= add_bstr_property(display_adapter
, L
"szChipType", L
"");
972 hr
= add_bstr_property(display_adapter
, L
"szDACType", L
"");
976 hr
= add_bstr_property(display_adapter
, L
"szRevision", L
"");
980 if (!get_texture_memory(&adapter_info
.DeviceIdentifier
, &available_mem
))
981 WARN("get_texture_memory helper failed\n");
983 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"%.1f MB", available_mem
/ 1000000.0f
);
985 hr
= add_bstr_property(display_adapter
, L
"szDisplayMemoryLocalized", buffer
);
989 hr
= add_bstr_property(display_adapter
, L
"szDisplayMemoryEnglish", buffer
);
993 hr
= IDirect3D9_GetDeviceCaps(pDirect3D9
, index
, D3DDEVTYPE_HAL
, &device_caps
);
994 hardware_accel
= SUCCEEDED(hr
);
996 hr
= add_bool_property(display_adapter
, L
"b3DAccelerationEnabled", hardware_accel
);
1000 hr
= add_bool_property(display_adapter
, L
"b3DAccelerationExists", hardware_accel
);
1004 hr
= add_bool_property(display_adapter
, L
"bDDAccelerationEnabled", hardware_accel
);
1008 hr
= add_bool_property(display_adapter
, L
"bNoHardware", FALSE
);
1012 hr
= add_bool_property(display_adapter
, L
"bCanRenderWindow", TRUE
);
1016 hr
= add_bstr_property(display_adapter
, L
"szMonitorName", L
"Generic PnP Monitor");
1020 hr
= add_bstr_property(display_adapter
, L
"szMonitorMaxRes", L
"Failed to get parameter");
1024 hr
= add_bstr_property(display_adapter
, L
"szDriverAttributes", L
"Final Retail");
1028 hr
= add_bstr_property(display_adapter
, L
"szDriverLanguageEnglish", L
"English");
1032 hr
= add_bstr_property(display_adapter
, L
"szDriverLanguageLocalized", L
"English");
1036 hr
= add_bstr_property(display_adapter
, L
"szDriverDateEnglish", L
"1/1/2016 10:00:00");
1040 hr
= add_bstr_property(display_adapter
, L
"szDriverDateLocalized", L
"1/1/2016 10:00:00 AM");
1044 hr
= add_i4_property(display_adapter
, L
"lDriverSize", 10 * 1024 * 1024);
1048 hr
= add_bstr_property(display_adapter
, L
"szMiniVdd", L
"n/a");
1052 hr
= add_bstr_property(display_adapter
, L
"szMiniVddDateLocalized", L
"n/a");
1056 hr
= add_bstr_property(display_adapter
, L
"szMiniVddDateEnglish", L
"n/a");
1060 hr
= add_i4_property(display_adapter
, L
"lMiniVddSize", 0);
1064 hr
= add_bstr_property(display_adapter
, L
"szVdd", L
"n/a");
1068 hr
= add_bool_property(display_adapter
, L
"bDriverBeta", FALSE
);
1072 hr
= add_bool_property(display_adapter
, L
"bDriverDebug", FALSE
);
1076 hr
= add_bool_property(display_adapter
, L
"bDriverSigned", TRUE
);
1080 hr
= add_bool_property(display_adapter
, L
"bDriverSignedValid", TRUE
);
1084 hr
= add_bstr_property(display_adapter
, L
"szDriverSignDate", L
"n/a");
1088 hr
= add_ui4_property(display_adapter
, L
"dwDDIVersion", 11);
1092 hr
= add_bstr_property(display_adapter
, L
"szDDIVersionEnglish", L
"11");
1096 hr
= add_bstr_property(display_adapter
, L
"szDDIVersionLocalized", L
"11");
1100 hr
= add_ui4_property(display_adapter
, L
"iAdapter", index
);
1104 hr
= add_ui4_property(display_adapter
, L
"dwWHQLLevel", 0);
1111 IDirect3D9_Release(pDirect3D9
);
1115 static HRESULT
fill_display_information_fallback(IDxDiagContainerImpl_Container
*node
)
1117 static const WCHAR
*empty_properties
[] =
1119 L
"szDeviceIdentifier", L
"szVendorId", L
"szDeviceId", L
"szKeyDeviceKey",
1120 L
"szKeyDeviceID", L
"szDriverName", L
"szDriverVersion", L
"szSubSysId",
1121 L
"szRevisionId", L
"szManufacturer", L
"szChipType", L
"szDACType", L
"szRevision"
1124 IDxDiagContainerImpl_Container
*display_adapter
;
1126 IDirectDraw7
*pDirectDraw
;
1128 DISPLAY_DEVICEW disp_dev
;
1129 DDSURFACEDESC2 surface_descr
;
1133 display_adapter
= allocate_information_node(L
"0");
1134 if (!display_adapter
)
1135 return E_OUTOFMEMORY
;
1137 add_subcontainer(node
, display_adapter
);
1139 disp_dev
.cb
= sizeof(disp_dev
);
1140 if (EnumDisplayDevicesW( NULL
, 0, &disp_dev
, 0 ))
1142 hr
= add_bstr_property(display_adapter
, L
"szDeviceName", disp_dev
.DeviceName
);
1146 hr
= add_bstr_property(display_adapter
, L
"szDescription", disp_dev
.DeviceString
);
1151 /* Silently ignore a failure from DirectDrawCreateEx. */
1152 hr
= DirectDrawCreateEx(NULL
, (void **)&pDirectDraw
, &IID_IDirectDraw7
, NULL
);
1156 dd_caps
.dwCaps
= DDSCAPS_LOCALVIDMEM
| DDSCAPS_VIDEOMEMORY
;
1157 dd_caps
.dwCaps2
= dd_caps
.dwCaps3
= dd_caps
.u1
.dwCaps4
= 0;
1158 hr
= IDirectDraw7_GetAvailableVidMem(pDirectDraw
, &dd_caps
, &tmp
, NULL
);
1161 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"%.1f MB", tmp
/ 1000000.0f
);
1163 hr
= add_bstr_property(display_adapter
, L
"szDisplayMemoryLocalized", buffer
);
1167 hr
= add_bstr_property(display_adapter
, L
"szDisplayMemoryEnglish", buffer
);
1172 surface_descr
.dwSize
= sizeof(surface_descr
);
1173 hr
= IDirectDraw7_GetDisplayMode(pDirectDraw
, &surface_descr
);
1176 if (surface_descr
.dwFlags
& DDSD_WIDTH
)
1178 hr
= add_ui4_property(display_adapter
, L
"dwWidth", surface_descr
.dwWidth
);
1183 if (surface_descr
.dwFlags
& DDSD_HEIGHT
)
1185 hr
= add_ui4_property(display_adapter
, L
"dwHeight", surface_descr
.dwHeight
);
1190 if (surface_descr
.dwFlags
& DDSD_PIXELFORMAT
)
1192 hr
= add_ui4_property(display_adapter
, L
"dwBpp",
1193 surface_descr
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
);
1199 hr
= add_ui4_property(display_adapter
, L
"dwRefreshRate", 60);
1203 for (tmp
= 0; tmp
< ARRAY_SIZE(empty_properties
); tmp
++)
1205 hr
= add_bstr_property(display_adapter
, empty_properties
[tmp
], L
"");
1212 IDirectDraw7_Release(pDirectDraw
);
1216 static HRESULT
build_displaydevices_tree(IDxDiagContainerImpl_Container
*node
)
1220 /* Try to use Direct3D to obtain the required information first. */
1221 hr
= fill_display_information_d3d(node
);
1225 return fill_display_information_fallback(node
);
1230 IDxDiagContainerImpl_Container
*cont
;
1235 static LPWSTR
guid_to_string(LPWSTR lpwstr
, REFGUID lpcguid
)
1237 wsprintfW(lpwstr
, L
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", lpcguid
->Data1
, lpcguid
->Data2
,
1238 lpcguid
->Data3
, lpcguid
->Data4
[0], lpcguid
->Data4
[1], lpcguid
->Data4
[2], lpcguid
->Data4
[3], lpcguid
->Data4
[4],
1239 lpcguid
->Data4
[5], lpcguid
->Data4
[6], lpcguid
->Data4
[7]);
1244 BOOL CALLBACK
dsound_enum(LPGUID guid
, LPCWSTR desc
, LPCWSTR module
, LPVOID context
)
1246 struct enum_context
*enum_ctx
= context
;
1247 IDxDiagContainerImpl_Container
*device
;
1249 const WCHAR
*p
, *name
;
1251 /* the default device is enumerated twice, one time without GUID */
1252 if (!guid
) return TRUE
;
1254 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"%u", enum_ctx
->index
);
1255 device
= allocate_information_node(buffer
);
1258 enum_ctx
->hr
= E_OUTOFMEMORY
;
1262 add_subcontainer(enum_ctx
->cont
, device
);
1264 guid_to_string(buffer
, guid
);
1265 enum_ctx
->hr
= add_bstr_property(device
, L
"szGuidDeviceID", buffer
);
1266 if (FAILED(enum_ctx
->hr
))
1269 enum_ctx
->hr
= add_bstr_property(device
, L
"szDescription", desc
);
1270 if (FAILED(enum_ctx
->hr
))
1273 enum_ctx
->hr
= add_bstr_property(device
, L
"szDriverPath", module
);
1274 if (FAILED(enum_ctx
->hr
))
1278 if ((p
= wcsrchr(name
, '\\'))) name
= p
+ 1;
1279 if ((p
= wcsrchr(name
, '/'))) name
= p
+ 1;
1281 enum_ctx
->hr
= add_bstr_property(device
, L
"szDriverName", name
);
1282 if (FAILED(enum_ctx
->hr
))
1289 static HRESULT
build_directsound_tree(IDxDiagContainerImpl_Container
*node
)
1291 struct enum_context enum_ctx
;
1292 IDxDiagContainerImpl_Container
*cont
;
1294 cont
= allocate_information_node(L
"DxDiag_SoundDevices");
1296 return E_OUTOFMEMORY
;
1298 add_subcontainer(node
, cont
);
1300 enum_ctx
.cont
= cont
;
1304 DirectSoundEnumerateW(dsound_enum
, &enum_ctx
);
1305 if (FAILED(enum_ctx
.hr
))
1308 cont
= allocate_information_node(L
"DxDiag_SoundCaptureDevices");
1310 return E_OUTOFMEMORY
;
1312 add_subcontainer(node
, cont
);
1314 enum_ctx
.cont
= cont
;
1318 DirectSoundCaptureEnumerateW(dsound_enum
, &enum_ctx
);
1319 if (FAILED(enum_ctx
.hr
))
1325 static HRESULT
build_directmusic_tree(IDxDiagContainerImpl_Container
*node
)
1330 static HRESULT
build_directinput_tree(IDxDiagContainerImpl_Container
*node
)
1335 static HRESULT
build_directplay_tree(IDxDiagContainerImpl_Container
*node
)
1340 static HRESULT
build_systemdevices_tree(IDxDiagContainerImpl_Container
*node
)
1345 static HRESULT
fill_file_description(IDxDiagContainerImpl_Container
*node
, const WCHAR
*szFilePath
, const WCHAR
*szFileName
)
1349 WCHAR szVersion_v
[1024];
1351 void *pVersionInfo
= NULL
;
1352 BOOL boolret
= FALSE
;
1354 VS_FIXEDFILEINFO
*pFileInfo
;
1356 TRACE("Filling container %p for %s in %s\n", node
,
1357 debugstr_w(szFileName
), debugstr_w(szFilePath
));
1359 szFile
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
) * (lstrlenW(szFilePath
) +
1360 lstrlenW(szFileName
) + 2 /* slash + terminator */));
1362 return E_OUTOFMEMORY
;
1364 lstrcpyW(szFile
, szFilePath
);
1365 lstrcatW(szFile
, L
"\\");
1366 lstrcatW(szFile
, szFileName
);
1368 retval
= GetFileVersionInfoSizeW(szFile
, &hdl
);
1371 pVersionInfo
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, retval
);
1378 if (GetFileVersionInfoW(szFile
, 0, retval
, pVersionInfo
) &&
1379 VerQueryValueW(pVersionInfo
, L
"\\", (void **)&pFileInfo
, &uiLength
))
1383 hr
= add_bstr_property(node
, L
"szPath", szFile
);
1387 hr
= add_bstr_property(node
, L
"szName", szFileName
);
1391 hr
= add_bool_property(node
, L
"bExists", boolret
);
1397 swprintf(szVersion_v
, ARRAY_SIZE(szVersion_v
), L
"%u.%02u.%04u.%04u",
1398 HIWORD(pFileInfo
->dwFileVersionMS
), LOWORD(pFileInfo
->dwFileVersionMS
),
1399 HIWORD(pFileInfo
->dwFileVersionLS
), LOWORD(pFileInfo
->dwFileVersionLS
));
1401 TRACE("Found version as (%s)\n", debugstr_w(szVersion_v
));
1403 hr
= add_bstr_property(node
, L
"szVersion", szVersion_v
);
1407 hr
= add_bstr_property(node
, L
"szAttributes", L
"Final Retail");
1411 hr
= add_bstr_property(node
, L
"szLanguageEnglish", L
"English");
1415 hr
= add_ui4_property(node
, L
"dwFileTimeHigh", pFileInfo
->dwFileDateMS
);
1419 hr
= add_ui4_property(node
, L
"dwFileTimeLow", pFileInfo
->dwFileDateLS
);
1423 hr
= add_bool_property(node
, L
"bBeta",
1424 ((pFileInfo
->dwFileFlags
& pFileInfo
->dwFileFlagsMask
) & VS_FF_PRERELEASE
) != 0);
1428 hr
= add_bool_property(node
, L
"bDebug",
1429 ((pFileInfo
->dwFileFlags
& pFileInfo
->dwFileFlagsMask
) & VS_FF_DEBUG
) != 0);
1436 HeapFree(GetProcessHeap(), 0, pVersionInfo
);
1437 HeapFree(GetProcessHeap(), 0, szFile
);
1441 static HRESULT
build_directxfiles_tree(IDxDiagContainerImpl_Container
*node
)
1443 static const WCHAR dlls
[][15] =
1468 WCHAR szFilePath
[MAX_PATH
];
1471 GetSystemDirectoryW(szFilePath
, MAX_PATH
);
1473 for (i
= 0; i
< ARRAY_SIZE(dlls
); i
++)
1476 IDxDiagContainerImpl_Container
*file_container
;
1478 swprintf(szFileID
, ARRAY_SIZE(szFileID
), L
"%d", i
);
1480 file_container
= allocate_information_node(szFileID
);
1481 if (!file_container
)
1482 return E_OUTOFMEMORY
;
1484 hr
= fill_file_description(file_container
, szFilePath
, dlls
[i
]);
1487 free_information_tree(file_container
);
1491 add_subcontainer(node
, file_container
);
1497 static HRESULT
read_property_names(IPropertyBag
*pPropBag
, VARIANT
*friendly_name
, VARIANT
*clsid_name
)
1501 VariantInit(friendly_name
);
1502 VariantInit(clsid_name
);
1504 hr
= IPropertyBag_Read(pPropBag
, L
"FriendlyName", friendly_name
, 0);
1508 hr
= IPropertyBag_Read(pPropBag
, L
"CLSID", clsid_name
, 0);
1511 VariantClear(friendly_name
);
1518 static HRESULT
fill_filter_data_information(IDxDiagContainerImpl_Container
*subcont
, BYTE
*pData
, ULONG cb
)
1521 IFilterMapper2
*pFileMapper
= NULL
;
1522 IAMFilterData
*pFilterData
= NULL
;
1524 REGFILTER2
*pRF
= NULL
;
1527 DWORD dwNOutputs
= 0;
1528 DWORD dwNInputs
= 0;
1530 hr
= CoCreateInstance(&CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC
, &IID_IFilterMapper2
,
1531 (void **)&pFileMapper
);
1535 hr
= IFilterMapper2_QueryInterface(pFileMapper
, &IID_IAMFilterData
, (void **)&pFilterData
);
1539 hr
= IAMFilterData_ParseFilterData(pFilterData
, pData
, cb
, &ppRF
);
1542 pRF
= ((REGFILTER2
**)ppRF
)[0];
1544 swprintf(bufferW
, ARRAY_SIZE(bufferW
), L
"v%d", pRF
->dwVersion
);
1545 hr
= add_bstr_property(subcont
, L
"szVersion", bufferW
);
1549 if (pRF
->dwVersion
== 1)
1551 for (j
= 0; j
< pRF
->cPins
; j
++)
1552 if (pRF
->rgPins
[j
].bOutput
)
1557 else if (pRF
->dwVersion
== 2)
1559 for (j
= 0; j
< pRF
->cPins2
; j
++)
1560 if (pRF
->rgPins2
[j
].dwFlags
& REG_PINFLAG_B_OUTPUT
)
1566 hr
= add_ui4_property(subcont
, L
"dwInputs", dwNInputs
);
1570 hr
= add_ui4_property(subcont
, L
"dwOutputs", dwNOutputs
);
1574 hr
= add_ui4_property(subcont
, L
"dwMerit", pRF
->dwMerit
);
1581 if (pFilterData
) IAMFilterData_Release(pFilterData
);
1582 if (pFileMapper
) IFilterMapper2_Release(pFileMapper
);
1587 static HRESULT
fill_filter_container(IDxDiagContainerImpl_Container
*subcont
, IMoniker
*pMoniker
)
1590 IPropertyBag
*pPropFilterBag
= NULL
;
1592 VARIANT friendly_name
;
1596 VariantInit(&friendly_name
);
1597 VariantInit(&clsid_name
);
1600 hr
= IMoniker_BindToStorage(pMoniker
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&pPropFilterBag
);
1604 hr
= read_property_names(pPropFilterBag
, &friendly_name
, &clsid_name
);
1608 TRACE("Name = %s\n", debugstr_w(V_BSTR(&friendly_name
)));
1609 TRACE("CLSID = %s\n", debugstr_w(V_BSTR(&clsid_name
)));
1611 hr
= add_bstr_property(subcont
, L
"szName", V_BSTR(&friendly_name
));
1615 hr
= add_bstr_property(subcont
, L
"ClsidFilter", V_BSTR(&clsid_name
));
1619 hr
= IPropertyBag_Read(pPropFilterBag
, L
"FilterData", &v
, NULL
);
1623 hr
= SafeArrayAccessData(V_ARRAY(&v
), (void **)&pData
);
1627 hr
= fill_filter_data_information(subcont
, pData
, V_ARRAY(&v
)->rgsabound
->cElements
);
1628 SafeArrayUnaccessData(V_ARRAY(&v
));
1635 VariantClear(&clsid_name
);
1636 VariantClear(&friendly_name
);
1637 if (pPropFilterBag
) IPropertyBag_Release(pPropFilterBag
);
1642 static HRESULT
build_directshowfilters_tree(IDxDiagContainerImpl_Container
*node
)
1646 ICreateDevEnum
*pCreateDevEnum
;
1647 IEnumMoniker
*pEmCat
= NULL
;
1648 IMoniker
*pMCat
= NULL
;
1649 IEnumMoniker
*pEnum
= NULL
;
1651 hr
= CoCreateInstance(&CLSID_SystemDeviceEnum
, NULL
, CLSCTX_INPROC_SERVER
,
1652 &IID_ICreateDevEnum
, (void **)&pCreateDevEnum
);
1656 hr
= ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum
, &CLSID_ActiveMovieCategories
, &pEmCat
, 0);
1660 while (IEnumMoniker_Next(pEmCat
, 1, &pMCat
, NULL
) == S_OK
)
1664 IPropertyBag
*pPropBag
;
1666 IMoniker
*pMoniker
= NULL
;
1668 hr
= IMoniker_BindToStorage(pMCat
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&pPropBag
);
1671 IMoniker_Release(pMCat
);
1675 hr
= read_property_names(pPropBag
, &vCatName
, &vCatClsid
);
1676 IPropertyBag_Release(pPropBag
);
1679 IMoniker_Release(pMCat
);
1683 hr
= CLSIDFromString(V_BSTR(&vCatClsid
), &clsidCat
);
1686 IMoniker_Release(pMCat
);
1687 VariantClear(&vCatClsid
);
1688 VariantClear(&vCatName
);
1692 hr
= ICreateDevEnum_CreateClassEnumerator(pCreateDevEnum
, &clsidCat
, &pEnum
, 0);
1695 IMoniker_Release(pMCat
);
1696 VariantClear(&vCatClsid
);
1697 VariantClear(&vCatName
);
1701 TRACE("Enumerating class %s\n", debugstr_guid(&clsidCat
));
1703 while (IEnumMoniker_Next(pEnum
, 1, &pMoniker
, NULL
) == S_OK
)
1706 IDxDiagContainerImpl_Container
*subcont
;
1708 swprintf(bufferW
, ARRAY_SIZE(bufferW
), L
"%d", i
);
1709 subcont
= allocate_information_node(bufferW
);
1713 IMoniker_Release(pMoniker
);
1717 hr
= add_bstr_property(subcont
, L
"szCatName", V_BSTR(&vCatName
));
1720 free_information_tree(subcont
);
1721 IMoniker_Release(pMoniker
);
1725 hr
= add_bstr_property(subcont
, L
"ClsidCat", V_BSTR(&vCatClsid
));
1728 free_information_tree(subcont
);
1729 IMoniker_Release(pMoniker
);
1733 hr
= fill_filter_container(subcont
, pMoniker
);
1734 IMoniker_Release(pMoniker
);
1737 WARN("Skipping invalid filter\n");
1738 free_information_tree(subcont
);
1743 add_subcontainer(node
, subcont
);
1747 IEnumMoniker_Release(pEnum
);
1748 IMoniker_Release(pMCat
);
1749 VariantClear(&vCatClsid
);
1750 VariantClear(&vCatName
);
1757 if (pEmCat
) IEnumMoniker_Release(pEmCat
);
1758 ICreateDevEnum_Release(pCreateDevEnum
);
1762 static HRESULT
build_logicaldisks_tree(IDxDiagContainerImpl_Container
*node
)
1767 static HRESULT
build_information_tree(IDxDiagContainerImpl_Container
**pinfo_root
)
1772 HRESULT (*initfunc
)(IDxDiagContainerImpl_Container
*);
1775 {L
"DxDiag_SystemInfo", build_systeminfo_tree
},
1776 {L
"DxDiag_DisplayDevices", build_displaydevices_tree
},
1777 {L
"DxDiag_DirectSound", build_directsound_tree
},
1778 {L
"DxDiag_DirectMusic", build_directmusic_tree
},
1779 {L
"DxDiag_DirectInput", build_directinput_tree
},
1780 {L
"DxDiag_DirectPlay", build_directplay_tree
},
1781 {L
"DxDiag_SystemDevices", build_systemdevices_tree
},
1782 {L
"DxDiag_DirectXFiles", build_directxfiles_tree
},
1783 {L
"DxDiag_DirectShowFilters", build_directshowfilters_tree
},
1784 {L
"DxDiag_LogicalDisks", build_logicaldisks_tree
},
1787 IDxDiagContainerImpl_Container
*info_root
;
1790 info_root
= allocate_information_node(NULL
);
1792 return E_OUTOFMEMORY
;
1794 for (index
= 0; index
< ARRAY_SIZE(root_children
); index
++)
1796 IDxDiagContainerImpl_Container
*node
;
1799 node
= allocate_information_node(root_children
[index
].name
);
1802 free_information_tree(info_root
);
1803 return E_OUTOFMEMORY
;
1806 hr
= root_children
[index
].initfunc(node
);
1809 free_information_tree(node
);
1810 free_information_tree(info_root
);
1814 add_subcontainer(info_root
, node
);
1817 *pinfo_root
= info_root
;