Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

667 lines
20 KiB

  1. /****************************************************************************
  2. *
  3. * File: showinfo.cpp
  4. * Project: DxDiag (DirectX Diagnostic Tool)
  5. * Author: Mike Anderson (manders@microsoft.com)
  6. * Purpose: Gather information about DirectShow on this machine
  7. *
  8. * (C) Copyright 2001 Microsoft Corp. All rights reserved.
  9. *
  10. ****************************************************************************/
  11. #include <windows.h>
  12. #include <stdio.h>
  13. #include <strmif.h> // Generated IDL header file for streams interfaces
  14. #include <uuids.h> // declaration of type GUIDs and well-known clsids
  15. #include <assert.h>
  16. #include "sysinfo.h"
  17. #include "fileinfo.h" // for GetFileVersion
  18. #include "showinfo.h"
  19. /****************************************************************************
  20. *
  21. * Helper IAMFilterData - cut and paste from dshow\h\fil_data.c
  22. *
  23. ****************************************************************************/
  24. /* verify that the <rpcndr.h> version is high enough to compile this file*/
  25. #ifndef __REQUIRED_RPCNDR_H_VERSION__
  26. #define __REQUIRED_RPCNDR_H_VERSION__ 440
  27. #endif
  28. #include "rpc.h"
  29. #include "rpcndr.h"
  30. #ifndef __RPCNDR_H_VERSION__
  31. #error this stub requires an updated version of <rpcndr.h>
  32. #endif // __RPCNDR_H_VERSION__
  33. #ifndef COM_NO_WINDOWS_H
  34. #include "windows.h"
  35. #include "ole2.h"
  36. #endif /*COM_NO_WINDOWS_H*/
  37. #ifndef __fil_data_h__
  38. #define __fil_data_h__
  39. #ifdef __cplusplus
  40. extern "C"{
  41. #endif
  42. /* Forward Declarations */
  43. #ifndef __IAMFilterData_FWD_DEFINED__
  44. #define __IAMFilterData_FWD_DEFINED__
  45. typedef interface IAMFilterData IAMFilterData;
  46. #endif /* __IAMFilterData_FWD_DEFINED__ */
  47. /* header files for imported files */
  48. #include "unknwn.h"
  49. #include "strmif.h"
  50. void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);
  51. void __RPC_USER MIDL_user_free( void __RPC_FAR * );
  52. /* interface __MIDL_itf_fil_data_0000 */
  53. /* [local] */
  54. extern RPC_IF_HANDLE __MIDL_itf_fil_data_0000_v0_0_c_ifspec;
  55. extern RPC_IF_HANDLE __MIDL_itf_fil_data_0000_v0_0_s_ifspec;
  56. #ifndef __IAMFilterData_INTERFACE_DEFINED__
  57. #define __IAMFilterData_INTERFACE_DEFINED__
  58. /* interface IAMFilterData */
  59. /* [unique][uuid][object] */
  60. EXTERN_C const IID IID_IAMFilterData;
  61. #if defined(__cplusplus) && !defined(CINTERFACE)
  62. MIDL_INTERFACE("97f7c4d4-547b-4a5f-8332-536430ad2e4d")
  63. IAMFilterData : public IUnknown
  64. {
  65. public:
  66. virtual HRESULT STDMETHODCALLTYPE ParseFilterData(
  67. /* [size_is][in] */ BYTE __RPC_FAR *rgbFilterData,
  68. /* [in] */ ULONG cb,
  69. /* [out] */ BYTE __RPC_FAR *__RPC_FAR *prgbRegFilter2) = 0;
  70. virtual HRESULT STDMETHODCALLTYPE CreateFilterData(
  71. /* [in] */ REGFILTER2 __RPC_FAR *prf2,
  72. /* [out] */ BYTE __RPC_FAR *__RPC_FAR *prgbFilterData,
  73. /* [out] */ ULONG __RPC_FAR *pcb) = 0;
  74. };
  75. #else /* C style interface */
  76. typedef struct IAMFilterDataVtbl
  77. {
  78. BEGIN_INTERFACE
  79. HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
  80. IAMFilterData __RPC_FAR * This,
  81. /* [in] */ REFIID riid,
  82. /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
  83. ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
  84. IAMFilterData __RPC_FAR * This);
  85. ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
  86. IAMFilterData __RPC_FAR * This);
  87. HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ParseFilterData )(
  88. IAMFilterData __RPC_FAR * This,
  89. /* [size_is][in] */ BYTE __RPC_FAR *rgbFilterData,
  90. /* [in] */ ULONG cb,
  91. /* [out] */ BYTE __RPC_FAR *__RPC_FAR *prgbRegFilter2);
  92. HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CreateFilterData )(
  93. IAMFilterData __RPC_FAR * This,
  94. /* [in] */ REGFILTER2 __RPC_FAR *prf2,
  95. /* [out] */ BYTE __RPC_FAR *__RPC_FAR *prgbFilterData,
  96. /* [out] */ ULONG __RPC_FAR *pcb);
  97. END_INTERFACE
  98. } IAMFilterDataVtbl;
  99. interface IAMFilterData
  100. {
  101. CONST_VTBL struct IAMFilterDataVtbl __RPC_FAR *lpVtbl;
  102. };
  103. #ifdef COBJMACROS
  104. #define IAMFilterData_QueryInterface(This,riid,ppvObject) \
  105. (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
  106. #define IAMFilterData_AddRef(This) \
  107. (This)->lpVtbl -> AddRef(This)
  108. #define IAMFilterData_Release(This) \
  109. (This)->lpVtbl -> Release(This)
  110. #define IAMFilterData_ParseFilterData(This,rgbFilterData,cb,prgbRegFilter2) \
  111. (This)->lpVtbl -> ParseFilterData(This,rgbFilterData,cb,prgbRegFilter2)
  112. #define IAMFilterData_CreateFilterData(This,prf2,prgbFilterData,pcb) \
  113. (This)->lpVtbl -> CreateFilterData(This,prf2,prgbFilterData,pcb)
  114. #endif /* COBJMACROS */
  115. #endif /* C style interface */
  116. HRESULT STDMETHODCALLTYPE IAMFilterData_ParseFilterData_Proxy(
  117. IAMFilterData __RPC_FAR * This,
  118. /* [size_is][in] */ BYTE __RPC_FAR *rgbFilterData,
  119. /* [in] */ ULONG cb,
  120. /* [out] */ BYTE __RPC_FAR *__RPC_FAR *prgbRegFilter2);
  121. void __RPC_STUB IAMFilterData_ParseFilterData_Stub(
  122. IRpcStubBuffer *This,
  123. IRpcChannelBuffer *_pRpcChannelBuffer,
  124. PRPC_MESSAGE _pRpcMessage,
  125. DWORD *_pdwStubPhase);
  126. HRESULT STDMETHODCALLTYPE IAMFilterData_CreateFilterData_Proxy(
  127. IAMFilterData __RPC_FAR * This,
  128. /* [in] */ REGFILTER2 __RPC_FAR *prf2,
  129. /* [out] */ BYTE __RPC_FAR *__RPC_FAR *prgbFilterData,
  130. /* [out] */ ULONG __RPC_FAR *pcb);
  131. void __RPC_STUB IAMFilterData_CreateFilterData_Stub(
  132. IRpcStubBuffer *This,
  133. IRpcChannelBuffer *_pRpcChannelBuffer,
  134. PRPC_MESSAGE _pRpcMessage,
  135. DWORD *_pdwStubPhase);
  136. #endif /* __IAMFilterData_INTERFACE_DEFINED__ */
  137. /* Additional Prototypes for ALL interfaces */
  138. /* end of Additional Prototypes */
  139. #ifdef __cplusplus
  140. }
  141. #endif
  142. #endif
  143. /****************************************************************************
  144. *
  145. * Helper IAMFilterData - cut and paste from dshow\h\fil_data_i.c
  146. *
  147. ****************************************************************************/
  148. #ifdef __cplusplus
  149. extern "C"{
  150. #endif
  151. #ifndef __IID_DEFINED__
  152. #define __IID_DEFINED__
  153. typedef struct _IID
  154. {
  155. unsigned long x;
  156. unsigned short s1;
  157. unsigned short s2;
  158. unsigned char c[8];
  159. } IID;
  160. #endif // __IID_DEFINED__
  161. #ifndef CLSID_DEFINED
  162. #define CLSID_DEFINED
  163. typedef IID CLSID;
  164. #endif // CLSID_DEFINED
  165. const IID IID_IAMFilterData = {0x97f7c4d4,0x547b,0x4a5f,{0x83,0x32,0x53,0x64,0x30,0xad,0x2e,0x4d}};
  166. #ifdef __cplusplus
  167. }
  168. #endif
  169. /****************************************************************************
  170. *
  171. * Forward declaration
  172. *
  173. ****************************************************************************/
  174. HRESULT GenerateFilterList(ShowInfo* pShowInfo);
  175. HRESULT EnumerateFilterPerCategory(ShowInfo* pShowInfo, CLSID* clsid, WCHAR* wszCatName);
  176. HRESULT GetFilterInfo(IMoniker* pMon, IAMFilterData* pFD, FilterInfo* pFilterInfo);
  177. /****************************************************************************
  178. *
  179. * GetBasicShowInfo - Get minimal info on DirectShow
  180. *
  181. ****************************************************************************/
  182. HRESULT GetBasicShowInfo(ShowInfo** ppShowInfo)
  183. {
  184. ShowInfo* pShowInfoNew;
  185. pShowInfoNew = new ShowInfo;
  186. if (pShowInfoNew == NULL)
  187. return E_OUTOFMEMORY;
  188. ZeroMemory(pShowInfoNew, sizeof(ShowInfo));
  189. *ppShowInfo = pShowInfoNew;
  190. return GenerateFilterList(pShowInfoNew);
  191. }
  192. /****************************************************************************
  193. *
  194. * DestroyShowInfo
  195. *
  196. ****************************************************************************/
  197. VOID DestroyShowInfo(ShowInfo* pShowInfo)
  198. {
  199. if (!pShowInfo) return;
  200. if (pShowInfo->m_dwFilters)
  201. {
  202. FilterInfo* pFilterInfo;
  203. FilterInfo* pFilterInfoNext;
  204. pFilterInfo = pShowInfo->m_pFilters;
  205. while(pFilterInfo)
  206. {
  207. pFilterInfoNext = pFilterInfo->m_pFilterInfoNext;
  208. delete pFilterInfo;
  209. pFilterInfo = pFilterInfoNext;
  210. }
  211. }
  212. delete pShowInfo;
  213. }
  214. HRESULT GenerateFilterList(ShowInfo* pShowInfo)
  215. {
  216. HRESULT hr;
  217. ICreateDevEnum* pSysDevEnum = NULL;
  218. IEnumMoniker* pMonEnum = NULL;
  219. IMoniker* pMon = NULL;
  220. ULONG cFetched;
  221. pShowInfo->m_dwFilters = 0;
  222. hr = CoCreateInstance(CLSID_SystemDeviceEnum,
  223. NULL,
  224. CLSCTX_INPROC,
  225. IID_ICreateDevEnum,
  226. (void **)&pSysDevEnum);
  227. if FAILED(hr)
  228. {
  229. return hr;
  230. }
  231. // Use the meta-category that contains a list of all categories.
  232. // This emulates the behavior of Graphedit.
  233. hr = pSysDevEnum->CreateClassEnumerator(CLSID_ActiveMovieCategories, &pMonEnum, 0);
  234. pSysDevEnum->Release();
  235. if FAILED(hr)
  236. {
  237. return hr;
  238. }
  239. // Enumerate over every category
  240. while (hr = pMonEnum->Next(1, &pMon, &cFetched), hr == S_OK)
  241. {
  242. IPropertyBag *pPropBag;
  243. // Associate moniker with a file
  244. hr = pMon->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
  245. if (SUCCEEDED(hr))
  246. {
  247. WCHAR wszCatName[1024] = L"";
  248. CLSID clsidCategory;
  249. VARIANT var;
  250. var.vt = VT_BSTR;
  251. // Get friendly name
  252. hr = pPropBag->Read(L"FriendlyName", &var, 0);
  253. if(SUCCEEDED(hr))
  254. {
  255. wcscpy(wszCatName, var.bstrVal);
  256. SysFreeString(var.bstrVal);
  257. }
  258. // Get CLSID string from property bag
  259. hr = pPropBag->Read(L"CLSID", &var, 0);
  260. if (SUCCEEDED(hr))
  261. {
  262. if (CLSIDFromString(var.bstrVal, &clsidCategory) == S_OK)
  263. {
  264. if (TEXT('\0') == wszCatName[0])
  265. {
  266. wcscpy(wszCatName, var.bstrVal);
  267. }
  268. }
  269. SysFreeString(var.bstrVal);
  270. }
  271. pPropBag->Release();
  272. // Start to enumerate the filters for this one category
  273. hr = EnumerateFilterPerCategory(pShowInfo, &clsidCategory, wszCatName);
  274. }
  275. pMon->Release();
  276. }
  277. pMonEnum->Release();
  278. return hr;
  279. }
  280. HRESULT EnumerateFilterPerCategory(ShowInfo* pShowInfo, CLSID* clsid, WCHAR* wszCatName)
  281. {
  282. HRESULT hr;
  283. ICreateDevEnum* pSysDevEnum = NULL;
  284. IEnumMoniker *pMonEnum = NULL;
  285. IMoniker *pMon = NULL;
  286. ULONG cFetched;
  287. #ifdef RUNNING_VC
  288. // WMP bug 29936: Voxware codec corrupt: MSMS001 : corrupted heap
  289. // This causes this call int3 when inside a debugger so skip
  290. const CLSID clsidACMClassManager = {0x33d9a761,0x90c8,0x11d0,{0xbd,0x43,0x00,0xa0,0xc9,0x11,0xce,0x86}};
  291. if( *clsid == clsidACMClassManager )
  292. return S_OK;
  293. #endif
  294. hr = CoCreateInstance(CLSID_SystemDeviceEnum,
  295. NULL,
  296. CLSCTX_INPROC,
  297. IID_ICreateDevEnum,
  298. (void **)&pSysDevEnum);
  299. if FAILED(hr)
  300. {
  301. return hr;
  302. }
  303. hr = pSysDevEnum->CreateClassEnumerator(*clsid, &pMonEnum, 0);
  304. pSysDevEnum->Release();
  305. if FAILED(hr)
  306. {
  307. return hr;
  308. }
  309. // If there are no filters of a requested category, don't do anything.
  310. if(NULL == pMonEnum)
  311. {
  312. // could added a string to denote an empty category
  313. return S_FALSE;
  314. }
  315. FilterInfo** ppFilterInfo;
  316. FilterInfo* pFilterInfoNew;
  317. ppFilterInfo = &(pShowInfo->m_pFilters);
  318. while (NULL != *ppFilterInfo)
  319. ppFilterInfo = &((*ppFilterInfo)->m_pFilterInfoNext);
  320. // Enumerate all items associated with the moniker
  321. while(pMonEnum->Next(1, &pMon, &cFetched) == S_OK)
  322. {
  323. // get a new record for FilterInfo
  324. pFilterInfoNew = new FilterInfo;
  325. if (pFilterInfoNew == NULL)
  326. {
  327. hr = E_OUTOFMEMORY;
  328. break;
  329. }
  330. ZeroMemory(pFilterInfoNew, sizeof(FilterInfo));
  331. *ppFilterInfo = pFilterInfoNew;
  332. ppFilterInfo = &(pFilterInfoNew->m_pFilterInfoNext);
  333. pShowInfo->m_dwFilters++;
  334. // set category clsid and friendly name
  335. pFilterInfoNew->m_ClsidCat = *clsid;
  336. #ifdef _UNICODE
  337. wcscpy(pFilterInfoNew->m_szCatName, wszCatName);
  338. #else
  339. WideCharToMultiByte(CP_ACP,
  340. 0,
  341. wszCatName,
  342. -1,
  343. pFilterInfoNew->m_szCatName,
  344. sizeof(pFilterInfoNew->m_szCatName),
  345. 0,
  346. 0);
  347. #endif
  348. IPropertyBag *pPropBag;
  349. // associate moniker with a file
  350. hr = pMon->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
  351. if (SUCCEEDED(hr))
  352. {
  353. VARIANT var;
  354. var.vt = VT_BSTR;
  355. // get filter's friendly name
  356. hr = pPropBag->Read(L"FriendlyName", &var, 0);
  357. if (SUCCEEDED(hr))
  358. {
  359. #ifdef _UNICODE
  360. wcscpy(pFilterInfoNew->m_szName, var.bstrVal);
  361. #else
  362. WideCharToMultiByte(CP_ACP,
  363. 0,
  364. var.bstrVal,
  365. -1,
  366. pFilterInfoNew->m_szName,
  367. sizeof(pFilterInfoNew->m_szName),
  368. 0,
  369. 0);
  370. #endif
  371. SysFreeString(var.bstrVal);
  372. }
  373. // get filter's CLSID
  374. hr = pPropBag->Read(L"CLSID", &var, 0);
  375. if(SUCCEEDED(hr))
  376. {
  377. if(CLSIDFromString(var.bstrVal, &(pFilterInfoNew->m_ClsidFilter)) == S_OK)
  378. {
  379. // use the guid if we can't get the friendly name
  380. if (TEXT('\0') == pFilterInfoNew->m_szName[0])
  381. {
  382. #ifdef _UNICODE
  383. wcscpy(pFilterInfoNew->m_szName, var.bstrVal);
  384. #else
  385. WideCharToMultiByte(CP_ACP,
  386. 0,
  387. var.bstrVal,
  388. -1,
  389. pFilterInfoNew->m_szName,
  390. sizeof(pFilterInfoNew->m_szName),
  391. 0,
  392. 0);
  393. #endif
  394. }
  395. }
  396. SysFreeString(var.bstrVal);
  397. }
  398. pPropBag->Release();
  399. }
  400. // start grabbing filter info
  401. IAMFilterData *pFD;
  402. hr = CoCreateInstance(CLSID_FilterMapper,
  403. NULL,
  404. CLSCTX_INPROC_SERVER,
  405. IID_IAMFilterData,
  406. (void **)&pFD);
  407. if(SUCCEEDED(hr))
  408. {
  409. hr = GetFilterInfo(pMon, pFD, pFilterInfoNew);
  410. pFD->Release();
  411. }
  412. else
  413. {
  414. // Must not be on DX8 or above...
  415. }
  416. pMon->Release();
  417. }
  418. pMonEnum->Release();
  419. return hr;
  420. }
  421. HRESULT GetFilterInfo(IMoniker* pMon, IAMFilterData* pFD, FilterInfo* pFilterInfo)
  422. {
  423. HRESULT hr;
  424. IPropertyBag *pPropBag;
  425. hr = pMon->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag);
  426. if(SUCCEEDED(hr))
  427. {
  428. VARIANT varFilData;
  429. varFilData.vt = VT_UI1 | VT_ARRAY;
  430. varFilData.parray = 0; // docs say zero this
  431. BYTE *pbFilterData = NULL;
  432. DWORD dwcbFilterDAta = 0; // 0 if not read
  433. hr = pPropBag->Read(L"FilterData", &varFilData, 0);
  434. if(SUCCEEDED(hr))
  435. {
  436. if( varFilData.vt == (VT_UI1 | VT_ARRAY) )
  437. {
  438. dwcbFilterDAta = varFilData.parray->rgsabound[0].cElements;
  439. if( SUCCEEDED( SafeArrayAccessData(varFilData.parray, (void **)&pbFilterData) ) )
  440. {
  441. BYTE *pb = NULL;
  442. hr = pFD->ParseFilterData(pbFilterData, dwcbFilterDAta, &pb);
  443. if(SUCCEEDED(hr))
  444. {
  445. REGFILTER2** ppRegFilter = (REGFILTER2**)pb;
  446. REGFILTER2* pFil = NULL;
  447. pFil = *ppRegFilter;
  448. if( pFil != NULL && pFil->dwVersion == 2 )
  449. {
  450. pFilterInfo->m_dwMerit = pFil->dwMerit; // set merit
  451. wsprintf(pFilterInfo->m_szVersion, TEXT("v%d"), pFil->dwVersion); // set version
  452. //
  453. // Display the filter's filename
  454. //
  455. // Read filter's CLSID from property bag. This CLSID string will be
  456. // used to find the filter's filename in the registry.
  457. VARIANT varFilterClsid;
  458. varFilterClsid.vt = VT_BSTR;
  459. hr = pPropBag->Read(L"CLSID", &varFilterClsid, 0);
  460. if(SUCCEEDED(hr))
  461. {
  462. TCHAR szKey[512];
  463. // Convert BSTR to string
  464. WCHAR *wszFilterClsid;
  465. TCHAR szFilterClsid[1024];
  466. wszFilterClsid = varFilterClsid.bstrVal;
  467. #ifdef _UNICODE
  468. wcscpy(szFilterClsid, wszFilterClsid);
  469. #else
  470. WideCharToMultiByte(CP_ACP,
  471. 0,
  472. wszFilterClsid,
  473. -1,
  474. szFilterClsid,
  475. sizeof(szFilterClsid),
  476. 0,
  477. 0);
  478. #endif
  479. // Create key name for reading filename registry
  480. wsprintf(szKey, TEXT("Software\\Classes\\CLSID\\%s\\InprocServer32\0"),
  481. szFilterClsid);
  482. // Variables needed for registry query
  483. HKEY hkeyFilter=0;
  484. DWORD dwSize=MAX_PATH;
  485. BYTE szFilename[MAX_PATH];
  486. int rc=0;
  487. // Open the CLSID key that contains information about the filter
  488. rc = RegOpenKey(HKEY_LOCAL_MACHINE, szKey, &hkeyFilter);
  489. if (rc == ERROR_SUCCESS)
  490. {
  491. rc = RegQueryValueEx(hkeyFilter, NULL, // Read (Default) value
  492. NULL, NULL, szFilename, &dwSize);
  493. if (rc == ERROR_SUCCESS)
  494. {
  495. wsprintf(pFilterInfo->m_szFileName, TEXT("%s"), szFilename); // set file name & version
  496. GetFileVersion(pFilterInfo->m_szFileName, pFilterInfo->m_szFileVersion, NULL, NULL, NULL, NULL);
  497. }
  498. rc = RegCloseKey(hkeyFilter);
  499. }
  500. SysFreeString(varFilterClsid.bstrVal);
  501. }
  502. int iPinsInput = 0;
  503. int iPinsOutput = 0;
  504. for(UINT iPin = 0; iPin < pFil->cPins; iPin++)
  505. {
  506. if(pFil->rgPins2[iPin].dwFlags & REG_PINFLAG_B_OUTPUT)
  507. {
  508. iPinsOutput++;
  509. }
  510. else
  511. {
  512. iPinsInput++;
  513. }
  514. }
  515. pFilterInfo->m_dwInputs = iPinsInput; // set input
  516. pFilterInfo->m_dwOutputs = iPinsOutput; // set output
  517. }
  518. CoTaskMemFree( (BYTE*) pFil );
  519. }
  520. SafeArrayUnaccessData(varFilData.parray);
  521. }
  522. }
  523. VariantClear(&varFilData);
  524. }
  525. pPropBag->Release();
  526. }
  527. return hr;
  528. }