source: trunk/DirectShowSpy/FilterGraphHelper.h @ 801

Last change on this file since 801 was 624, checked in by roman, 8 years ago

Fixed small glitch in helper UI; added missing CLSID to UnregisterTreatAsClasses? export

File size: 141.1 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2008-2015
3// Created by Roman Ryltsov roman@alax.info, http://alax.info
4//
5// This source code is published to complement DirectShowSpy developer powertoy
6// and demonstrate the internal use of APIs and tricks powering the tool. It is
7// allowed to freely re-use the portions of the code in other projects, commercial
8// or otherwise (provided that you don’t pretend that you wrote the original tool).
9//
10// Please keep in mind that DirectShowSpy is a developer tool, it is strongly recommended
11// that it is not shipped with release grade software. It is allowed to distribute
12// DirectShowSpy if only it is not registered with Windows by default and either
13// used privately, or registered on specific throubleshooting request. The advice applies
14// to hooking methods used by DirectShowSpy in general as well.
15
16#pragma once
17
18#include "rofiles.h"
19#include "rodshow.h"
20#include "Module_i.h"
21#include "Common.h"
22#include "RunPropertyBag.h"
23#include "RunEvent.h"
24
25INT_PTR DoFilterGraphListPropertySheetModal(HWND hParentWindow = GetActiveWindow(), COptions* pOptions = NULL);
26
27HRESULT FilterGraphHelper_DoPropertyFrameModal(LONG nParentWindowHandle);
28HRESULT FilterGraphHelper_DoFilterGraphListModal(LONG nParentWindowHandle);
29HRESULT FilterGraphHelper_OpenGraphStudioNext(LONG nParentWindowHandle, LPCWSTR pszMonikerDisplayName, VARIANT_BOOL* pbResult);
30HRESULT FilterGraphHelper_OpenGraphEdit(LONG nParentWindowHandle, LPCWSTR pszMonikerDisplayName, VARIANT_BOOL* pbResult);
31
32VOID MediaSampleTrace_Reset(DWORD nProcessIdentifier);
33CString MediaSampleTrace_Get(DWORD nProcessIdentifier);
34CComPtr<IUnknown> MediaSampleTrace_Lock();
35
36////////////////////////////////////////////////////////////
37// CRunPropertyBagPropertyPage
38
39class ATL_NO_VTABLE CRunPropertyBagPropertyPage :
40        public CComObjectRootEx<CComSingleThreadModel>,
41        public CComCoClass<CRunPropertyBagPropertyPage, &__uuidof(RunPropertyBagPropertyPage)>,
42        public COlePropertyPageT<CRunPropertyBagPropertyPage>,
43        public CDialogResize<CRunPropertyBagPropertyPage>
44{
45public:
46        enum { IDR = IDR_GENERIC_RUNPROPERTYBAG_PROPERTYPAGE };
47        enum { IDD = IDD_GENERIC_RUNPROPERTYBAG };
48
49BEGIN_COM_MAP(CRunPropertyBagPropertyPage)
50        COM_INTERFACE_ENTRY(IPropertyPage2)
51        COM_INTERFACE_ENTRY(IPropertyPage)
52END_COM_MAP()
53
54BEGIN_MSG_MAP_EX(CRunPropertyBagPropertyPage)
55        CHAIN_MSG_MAP(COlePropertyPage)
56        CHAIN_MSG_MAP(CDialogResize<CRunPropertyBagPropertyPage>)
57        MSG_WM_INITDIALOG(OnInitDialog)
58        MSG_WM_DESTROY(OnDestroy)
59        COMMAND_ID_HANDLER_EX(IDC_GENERIC_RUNPROPERTYBAG_REFRESH, OnRefresh)
60        COMMAND_ID_HANDLER_EX(IDC_GENERIC_RUNPROPERTYBAG_COPY, OnCopy)
61        COMMAND_ID_HANDLER_EX(IDC_GENERIC_RUNPROPERTYBAG_SAVEAS, OnSaveAs)
62        REFLECT_NOTIFICATIONS()
63END_MSG_MAP()
64
65BEGIN_DLGRESIZE_MAP(CRunPropertyBagPropertyPage)
66        DLGRESIZE_CONTROL(IDC_GENERIC_RUNPROPERTYBAG_INTRODUCTION, DLSZ_SIZE_X)
67        DLGRESIZE_CONTROL(IDC_GENERIC_RUNPROPERTYBAG_TEXT, DLSZ_SIZE_X | DLSZ_SIZE_Y)
68        DLGRESIZE_CONTROL(IDC_GENERIC_RUNPROPERTYBAG_REFRESH, DLSZ_MOVE_Y)
69        DLGRESIZE_CONTROL(IDC_GENERIC_RUNPROPERTYBAG_COPY, DLSZ_MOVE_Y)
70        DLGRESIZE_CONTROL(IDC_GENERIC_RUNPROPERTYBAG_SAVEAS, DLSZ_MOVE_Y)
71END_DLGRESIZE_MAP()
72
73private:
74        BOOL m_bActivating;
75        CRoEdit m_TextEdit;
76        CFont m_TextFont;
77        CButton m_CopyButton;
78        CButton m_SaveAsButton;
79        CRoMapT<INT_PTR, BOOL> m_ChangeMap;
80
81public:
82// CRunPropertyBagPropertyPage
83        static CString GetObjectFriendlyName()
84        {
85                return _StringHelper::GetLine(IDR, 2);
86        }
87        static HRESULT WINAPI UpdateRegistry(BOOL bRegister)
88        {
89                _Z2(atlTraceRegistrar, 2, _T("bRegister %d\n"), bRegister);
90                return DefaultUpdateRegistry(bRegister);
91        }
92        CRunPropertyBagPropertyPage()
93        {
94                _Z4_THIS();
95        }
96        ~CRunPropertyBagPropertyPage()
97        {
98                _Z4_THIS();
99        }
100        VOID UpdateControls()
101        {
102                const INT nLextLength = m_TextEdit.GetWindowTextLength();
103                m_CopyButton.EnableWindow(nLextLength > 0);
104                m_SaveAsButton.EnableWindow(nLextLength > 0);
105        }
106        VOID UpdateText()
107        {
108                CString sText;
109                _A(GetObjectCount() == 1);
110                m_TextEdit.SetValue(CRunPropertyBagHelper::GetPropertyBagText(GetObject(0)));
111        }
112
113// Window Message Handler
114        LRESULT OnInitDialog(HWND, LPARAM)
115        {
116                m_bActivating = TRUE;
117                _ATLTRY
118                {
119                        CWaitCursor WaitCursor;
120                        m_TextEdit = GetDlgItem(IDC_GENERIC_RUNPROPERTYBAG_TEXT);
121                        CLogFont TextFont;
122                        CFontHandle(AtlGetDefaultGuiFont()).GetLogFont(TextFont);
123                        _tcsncpy_s(TextFont.lfFaceName, _T("Courier New"), _TRUNCATE);
124                        TextFont.SetHeight(8);
125                        m_TextFont = TextFont.CreateFontIndirect();
126                        m_TextEdit.SetFont(m_TextFont);
127                        //m_RefreshButton = GetDlgItem(IDC_GENERIC_RUNEVENT_REFRESH);
128                        m_CopyButton = GetDlgItem(IDC_GENERIC_RUNPROPERTYBAG_COPY);
129                        m_SaveAsButton = GetDlgItem(IDC_GENERIC_RUNPROPERTYBAG_SAVEAS);
130                        DlgResize_Init(FALSE);
131                        _A(GetObjectCount() >= 1);
132                        //const CComQIPtr<IRunPropertyBagAware> pRunPropertyBagAware = GetObject(0);
133                        //__D(pRunPropertyBagAware, E_NOINTERFACE);
134                        UpdateText();
135                        UpdateControls();
136                        m_ChangeMap.RemoveAll();
137                        m_bActivating = FALSE;
138                }
139                _ATLCATCH(Exception)
140                {
141                        AtlExceptionMessageBox(m_hWnd, Exception);
142                        for(CWindow Window = GetWindow(GW_CHILD); Window.IsWindow(); Window = Window.GetWindow(GW_HWNDNEXT))
143                                Window.EnableWindow(FALSE);
144                }
145                return TRUE;
146        }
147        LRESULT OnDestroy()
148        {
149                return 0;
150        }
151        LRESULT OnRefresh(UINT, INT, HWND)
152        {
153                CWaitCursor WaitCursor;
154                UpdateText();
155                UpdateControls();
156                return 0;
157        }
158        LRESULT OnCopy(UINT, INT, HWND)
159        {
160                SetClipboardText(m_hWnd, m_TextEdit.GetValue());
161                MessageBeep(MB_OK);     
162                return 0;
163        }
164        LRESULT OnSaveAs(UINT, INT, HWND)
165        {
166                static const COMDLG_FILTERSPEC g_pFilter[] = 
167                {
168                        { _T("Text Files"), _T("*.txt") },
169                        { _T("BZip2 Compressed Text Files"), _T("*.txt.bz2") },
170                        { _T("All Files"), _T("*.*") },
171                };
172                CPath sPath = _CommonDialogHelper::QuerySavePath(m_hWnd, g_pFilter, _T("txt"));
173                if(!_tcslen(sPath))
174                        return 0;
175                CAtlFile File;
176                __C(File.Create(sPath, GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS));
177                _ATLTRY
178                {
179                        CStringA sText = Utf8StringFromString(CStringW(m_TextEdit.GetValue()));
180                        static const BYTE g_pnByteOrderMark[] = { 0xEF, 0xBB, 0xBF, 0x00 };
181                        sText.Insert(0, (LPCSTR) g_pnByteOrderMark);
182                        if(_tcsicmp(GetPathExtension(sPath), _T(".bz2")) == 0)
183                        {
184                                CLocalObjectPtr<CBzip2Item> pItem;
185                                pItem->SetRawData((const BYTE*) (LPCSTR) sText, sText.GetLength());
186                                CHeapPtr<BYTE> pnData;
187                                SIZE_T nDataSize = 0;
188                                pItem->GetData(pnData, nDataSize);
189                                __C(File.Write(pnData, (DWORD) nDataSize));
190                        } else
191                                __C(File.Write(sText, (DWORD) sText.GetLength()));
192                }
193                _ATLCATCHALL()
194                {
195                        File.Close();
196                        _W(DeleteFile(sPath));
197                        _ATLRETHROW;
198                }
199                MessageBeep(MB_OK);     
200                return 0;
201        }
202
203// COlePropertyPageT, IRoPropertyPageT, IPropertyPage2, IPropertyPage
204        STDMETHOD(Apply)()
205        {
206                _Z4(atlTraceCOM, 4, _T("...\n"));
207                _ATLTRY
208                {
209                        //if(!m_ChangeMap.IsEmpty())
210                        {
211                                //CWaitCursor WaitCursor;
212                                //m_ChangeMap.RemoveAll();
213                                SetDirty(FALSE);
214                        }
215                }
216                _ATLCATCH(Exception)
217                {
218                        _C(Exception);
219                }
220                return S_OK;
221        }
222};
223
224OBJECT_ENTRY_AUTO(__uuidof(RunPropertyBagPropertyPage), CRunPropertyBagPropertyPage)
225
226////////////////////////////////////////////////////////////
227// CRunEventPropertyPage
228
229class ATL_NO_VTABLE CRunEventPropertyPage :
230        public CComObjectRootEx<CComSingleThreadModel>,
231        public CComCoClass<CRunEventPropertyPage, &__uuidof(RunEventPropertyPage)>,
232        public COlePropertyPageT<CRunEventPropertyPage>,
233        public CDialogResize<CRunEventPropertyPage>
234{
235public:
236        enum { IDR = IDR_GENERIC_RUNEVENT_PROPERTYPAGE };
237        enum { IDD = IDD_GENERIC_RUNEVENT };
238
239BEGIN_COM_MAP(CRunEventPropertyPage)
240        COM_INTERFACE_ENTRY(IPropertyPage2)
241        COM_INTERFACE_ENTRY(IPropertyPage)
242END_COM_MAP()
243
244BEGIN_MSG_MAP_EX(CRunEventPropertyPage)
245        CHAIN_MSG_MAP(COlePropertyPage)
246        CHAIN_MSG_MAP(CDialogResize<CRunEventPropertyPage>)
247        MSG_WM_INITDIALOG(OnInitDialog)
248        MSG_WM_DESTROY(OnDestroy)
249        COMMAND_HANDLER_EX(IDC_GENERIC_RUNEVENT_CAPTURE, BN_CLICKED, OnCaptureButtonClicked)
250        COMMAND_ID_HANDLER_EX(IDC_GENERIC_RUNEVENT_REFRESH, OnRefresh)
251        COMMAND_ID_HANDLER_EX(IDC_GENERIC_RUNEVENT_COPY, OnCopy)
252        COMMAND_ID_HANDLER_EX(IDC_GENERIC_RUNEVENT_SAVEAS, OnSaveAs)
253        REFLECT_NOTIFICATIONS()
254END_MSG_MAP()
255
256BEGIN_DLGRESIZE_MAP(CRunEventPropertyPage)
257        DLGRESIZE_CONTROL(IDC_GENERIC_RUNEVENT_CAPTURE, DLSZ_SIZE_X)
258        DLGRESIZE_CONTROL(IDC_GENERIC_RUNEVENT_TEXT, DLSZ_SIZE_X | DLSZ_SIZE_Y)
259        DLGRESIZE_CONTROL(IDC_GENERIC_RUNEVENT_REFRESH, DLSZ_MOVE_Y)
260        DLGRESIZE_CONTROL(IDC_GENERIC_RUNEVENT_COPY, DLSZ_MOVE_Y)
261        DLGRESIZE_CONTROL(IDC_GENERIC_RUNEVENT_SAVEAS, DLSZ_MOVE_Y)
262END_DLGRESIZE_MAP()
263
264public:
265
266private:
267        BOOL m_bActivating;
268        CButton m_CaptureButton;
269        CRoEdit m_TextEdit;
270        CButton m_RefreshButton;
271        CButton m_CopyButton;
272        CButton m_SaveAsButton;
273        CRoMapT<INT_PTR, BOOL> m_ChangeMap;
274
275public:
276// CRunEventPropertyPage
277        static CString GetObjectFriendlyName()
278        {
279                return _StringHelper::GetLine(IDR, 2);
280        }
281        static HRESULT WINAPI UpdateRegistry(BOOL bRegister)
282        {
283                _Z2(atlTraceRegistrar, 2, _T("bRegister %d\n"), bRegister);
284                return DefaultUpdateRegistry(bRegister);
285        }
286        CRunEventPropertyPage()
287        {
288                _Z4_THIS();
289        }
290        ~CRunEventPropertyPage()
291        {
292                _Z4_THIS();
293        }
294        VOID UpdateControls()
295        {
296                const BOOL bCapture = m_CaptureButton.GetCheck();
297                //m_TextEdit.EnableWindow(bCapture);
298                m_RefreshButton.EnableWindow(bCapture);
299                const INT nLextLength = m_TextEdit.GetWindowTextLength();
300                m_CopyButton.EnableWindow(nLextLength > 0);
301                m_SaveAsButton.EnableWindow(nLextLength > 0);
302        }
303        VOID Refresh()
304        {
305                const CComQIPtr<IRunEventAware> pRunEventAware = GetObject(0);
306                if(!pRunEventAware)
307                        return;
308                CComVariantArray vValue;
309                __C(pRunEventAware->get_Value(&vValue));
310                CString sText;
311                _ATLTRY
312                {
313                        if(vValue.vt > VT_NULL)
314                        {
315                                CRoArrayT<CComVariantArray> Array;
316                                vValue.ToElementArray(Array);
317                                for(SIZE_T nIndex = 0; nIndex < Array.GetCount(); nIndex++)
318                                {
319                                        CRunEventHelper::CEvents::CItem Item;
320                                        if(!Item.SetAsVariant(Array[nIndex]))
321                                                continue;
322                                        sText.AppendFormat(_T("%d") _T("\t") _T("%hs"), (LONG) (Item.m_nTime / 10000i64), Item.m_pszText);
323                                        sText.Append(_T("\r\n"));
324                                }
325                        }
326                }
327                _ATLCATCHALL()
328                {
329                        _Z_EXCEPTION();
330                }
331                m_TextEdit.SetValue(sText);
332        }
333
334// Window Message Handler
335        LRESULT OnInitDialog(HWND, LPARAM)
336        {
337                m_bActivating = TRUE;
338                _ATLTRY
339                {
340                        m_CaptureButton = GetDlgItem(IDC_GENERIC_RUNEVENT_CAPTURE);
341                        m_TextEdit = GetDlgItem(IDC_GENERIC_RUNEVENT_TEXT);
342                        m_RefreshButton = GetDlgItem(IDC_GENERIC_RUNEVENT_REFRESH);
343                        m_CopyButton = GetDlgItem(IDC_GENERIC_RUNEVENT_COPY);
344                        m_SaveAsButton = GetDlgItem(IDC_GENERIC_RUNEVENT_SAVEAS);
345                        DlgResize_Init(FALSE);
346                        //m_OutputSampleTimeEdit = GetDlgItem(IDC_SUSPENSIONFILTER_SAMPLE_OUTPUTTIME);
347                        _A(GetObjectCount() >= 1);
348                        const CComQIPtr<IRunEventAware> pRunEventAware = GetObject(0);
349                        __D(pRunEventAware, E_NOINTERFACE);
350                        VARIANT_BOOL bCapture = ATL_VARIANT_FALSE;
351                        __C(pRunEventAware->get_Capture(&bCapture));
352                        m_CaptureButton.SetCheck(bCapture != ATL_VARIANT_FALSE);
353                        if(bCapture != ATL_VARIANT_FALSE)
354                                Refresh();
355                        UpdateControls();
356                        m_ChangeMap.RemoveAll();
357                        m_bActivating = FALSE;
358                }
359                _ATLCATCH(Exception)
360                {
361                        AtlExceptionMessageBox(m_hWnd, Exception);
362                        for(CWindow Window = GetWindow(GW_CHILD); Window.IsWindow(); Window = Window.GetWindow(GW_HWNDNEXT))
363                                Window.EnableWindow(FALSE);
364                }
365                return TRUE;
366        }
367        LRESULT OnDestroy()
368        {
369                return 0;
370        }
371        LRESULT OnCaptureButtonClicked(UINT, INT, HWND)
372        {
373                CWaitCursor WaitCursor;
374                const CComQIPtr<IRunEventAware> pRunEventAware = GetObject(0);
375                if(pRunEventAware)
376                        _ATLTRY
377                        {
378                                const BOOL bCapture = m_CaptureButton.GetCheck();
379                                __C(pRunEventAware->put_Capture(bCapture ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE));
380                        }
381                        _ATLCATCHALL()
382                        {
383                                _Z_EXCEPTION();
384                        }
385                UpdateControls();
386                return 0;
387        }
388        LRESULT OnRefresh(UINT, INT, HWND)
389        {
390                CWaitCursor WaitCursor;
391                Refresh();
392                UpdateControls();
393                return 0;
394        }
395        LRESULT OnCopy(UINT, INT, HWND)
396        {
397                SetClipboardText(m_hWnd, m_TextEdit.GetValue());
398                MessageBeep(MB_OK);     
399                return 0;
400        }
401        LRESULT OnSaveAs(UINT, INT, HWND)
402        {
403                static const COMDLG_FILTERSPEC g_pFilter[] = 
404                {
405                        { _T("Text Files"), _T("*.txt") },
406                        { _T("BZip2 Compressed Text Files"), _T("*.txt.bz2") },
407                        { _T("All Files"), _T("*.*") },
408                };
409                CPath sPath = _CommonDialogHelper::QuerySavePath(m_hWnd, g_pFilter, _T("txt"));
410                if(!_tcslen(sPath))
411                        return 0;
412                CAtlFile File;
413                __C(File.Create(sPath, GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS));
414                _ATLTRY
415                {
416                        CStringA sText = Utf8StringFromString(CStringW(m_TextEdit.GetValue()));
417                        static const BYTE g_pnByteOrderMark[] = { 0xEF, 0xBB, 0xBF, 0x00 };
418                        sText.Insert(0, (LPCSTR) g_pnByteOrderMark);
419                        if(_tcsicmp(GetPathExtension(sPath), _T(".bz2")) == 0)
420                        {
421                                CLocalObjectPtr<CBzip2Item> pItem;
422                                pItem->SetRawData((const BYTE*) (LPCSTR) sText, sText.GetLength());
423                                CHeapPtr<BYTE> pnData;
424                                SIZE_T nDataSize = 0;
425                                pItem->GetData(pnData, nDataSize);
426                                __C(File.Write(pnData, (DWORD) nDataSize));
427                        } else
428                                __C(File.Write(sText, (DWORD) sText.GetLength()));
429                }
430                _ATLCATCHALL()
431                {
432                        File.Close();
433                        _W(DeleteFile(sPath));
434                        _ATLRETHROW;
435                }
436                MessageBeep(MB_OK);     
437                return 0;
438        }
439
440// COlePropertyPageT, IRoPropertyPageT, IPropertyPage2, IPropertyPage
441        STDMETHOD(Apply)()
442        {
443                _Z4(atlTraceCOM, 4, _T("...\n"));
444                _ATLTRY
445                {
446                        //if(!m_ChangeMap.IsEmpty())
447                        {
448                                //CWaitCursor WaitCursor;
449                                //m_ChangeMap.RemoveAll();
450                                SetDirty(FALSE);
451                        }
452                }
453                _ATLCATCH(Exception)
454                {
455                        _C(Exception);
456                }
457                return S_OK;
458        }
459};
460
461OBJECT_ENTRY_AUTO(__uuidof(RunEventPropertyPage), CRunEventPropertyPage)
462
463////////////////////////////////////////////////////////////
464// CFilterGraphHelper
465
466class ATL_NO_VTABLE CFilterGraphHelper :
467        public CComObjectRootEx<CComMultiThreadModelNoCS>,
468        public CComCoClass<CFilterGraphHelper, &__uuidof(FilterGraphHelper)>,
469        public IProvideClassInfo2Impl<&__uuidof(FilterGraphHelper), &IID_NULL>,
470        public IDispatchImpl<IFilterGraphHelper>,
471        public CModuleVersionInformationT<CFilterGraphHelper>
472{
473public:
474        enum { IDR = IDR_FILTERGRAPHHELPER };
475
476//DECLARE_REGISTRY_RESOURCEID(IDR)
477
478BEGIN_COM_MAP(CFilterGraphHelper)
479        COM_INTERFACE_ENTRY(IProvideClassInfo2)
480        COM_INTERFACE_ENTRY(IProvideClassInfo)
481        COM_INTERFACE_ENTRY(IFilterGraphHelper)
482        COM_INTERFACE_ENTRY_IID(__uuidof(IDispatch), IFilterGraphHelper)
483        COM_INTERFACE_ENTRY(IModuleVersionInformation)
484END_COM_MAP()
485
486public:
487
488        ////////////////////////////////////////////////////////
489        // CProcessData
490
491        class CProcessData
492        {
493        public:
494                CStringW m_sDisplayName;
495                DWORD m_nIdentifier;
496                CPath m_sImagePath;
497
498        public:
499        // CProcessData
500                CProcessData() :
501                        m_nIdentifier(0)
502                {
503                }
504        };
505
506        ////////////////////////////////////////////////////////
507        // CPropertyFrameDialog
508
509        class CPropertyFrameDialog :
510                public CDialogImpl<CPropertyFrameDialog>,
511                public CDialogResize<CPropertyFrameDialog>,
512                public CDialogWithAcceleratorsT<CPropertyFrameDialog>
513        {
514        public:
515                enum { IDD = IDD_FILTERGRAPHHELPER_PROPERTYFRAME };
516
517        BEGIN_MSG_MAP_EX(CPropertyFrameDialog)
518                //CHAIN_MSG_MAP(CDialogImpl<CPropertyFrameDialog>)
519                CHAIN_MSG_MAP(CDialogResize<CPropertyFrameDialog>)
520                MSG_WM_INITDIALOG(OnInitDialog)
521                MSG_WM_DESTROY(OnDestroy)
522                MSG_TVN_GETINFOTIP(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TREE, OnTreeViewGetInfoTip)
523                MSG_TVN_SELCHANGED(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TREE, OnTreeViewSelChanged)
524                MSG_TVN_ITEMEXPANDING(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TREE, OnTreeViewItemExplanding)
525                MSG_TVN_DBLCLK(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TREE, OnTreeViewDblClk)
526                NOTIFY_HANDLER_EX(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_REFRESH, CRoHyperStatic::NC_ANCHORCLICKED, OnRefreshAnchorClicked)
527                NOTIFY_HANDLER_EX(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_COPY, CRoHyperStatic::NC_ANCHORCLICKED, OnCopyAnchorClicked)
528                NOTIFY_HANDLER_EX(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_SAVEAS, CRoHyperStatic::NC_ANCHORCLICKED, OnSaveAsAnchorClicked)
529                MSG_WM_SYSCOMMAND(OnSysCommand)
530                COMMAND_ID_HANDLER_EX(IDOK, OnOk)
531                COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel)
532                COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_APPLY, OnApply)
533                COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TREE_WALKUP, OnTreeWalkUp)
534                COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_ACTION_OPENGSN, OnActionCommand)
535                COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_ACTION_OPENGE, OnActionCommand)
536                COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_ACTION_OPENLIST, OnActionCommand)
537                REFLECT_NOTIFICATIONS()
538        END_MSG_MAP()
539
540        BEGIN_DLGRESIZE_MAP(CPropertyFrameDialog)
541                DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TREE, DLSZ_SIZE_Y)
542                DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TEXT, DLSZ_SIZE_X | DLSZ_SIZE_Y)
543                DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_REFRESH, DLSZ_MOVE_Y)
544                DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_COPY, DLSZ_MOVE_Y)
545                DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_SAVEAS, DLSZ_MOVE_Y)
546                DLGRESIZE_CONTROL(IDOK, DLSZ_MOVE_X | DLSZ_MOVE_Y)
547                DLGRESIZE_CONTROL(IDCANCEL, DLSZ_MOVE_X | DLSZ_MOVE_Y)
548                DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_APPLY, DLSZ_MOVE_X | DLSZ_MOVE_Y)
549        END_DLGRESIZE_MAP()
550
551        public:
552
553                ////////////////////////////////////////////////////
554                // CPropertyPageSite
555
556                class ATL_NO_VTABLE CPropertyPageSite :
557                        public CComObjectRootEx<CComSingleThreadModel>,
558                        public IPropertyPageSite
559                {
560                        friend class CPropertyFrameDialog;
561
562                public:
563
564                BEGIN_COM_MAP(CPropertyPageSite)
565                        COM_INTERFACE_ENTRY(IPropertyPageSite)
566                END_COM_MAP()
567
568                private:
569                        CPropertyFrameDialog* m_pOwner;
570                        CComPtr<IUnknown> m_pUnknown;
571                        CComPtr<IPropertyPage> m_pPropertyPage;
572                        CString m_sTitle;
573                        DWORD m_nStatus;
574
575                public:
576                // CPropertyPageSite
577                        CPropertyPageSite() :
578                                m_pOwner(NULL)
579                        {
580                        }
581                        VOID Initialize(CPropertyFrameDialog* pOwner, IUnknown* pUnknown, IPropertyPage* pPropertyPage)
582                        {
583                                _A(pOwner && pUnknown && pPropertyPage);
584                                _A(!m_pOwner);
585                                m_pOwner = pOwner;
586                                m_pUnknown = pUnknown;
587                                m_pPropertyPage = pPropertyPage;
588                                __C(pPropertyPage->SetObjects(1, &m_pUnknown.p));
589                                PROPPAGEINFO Information;
590                                ZeroMemory(&Information, sizeof Information);
591                                Information.cb = sizeof Information;
592                                __C(pPropertyPage->GetPageInfo(&Information));
593                                CStringW sTitle = Information.pszTitle;
594                                CoTaskMemFree(Information.pszTitle);
595                                CoTaskMemFree(Information.pszDocString);
596                                CoTaskMemFree(Information.pszHelpFile);
597                                m_sTitle = CString(sTitle);
598                                m_nStatus = 0;
599                                __C(pPropertyPage->SetPageSite(this));
600                        }
601                        VOID Terminate()
602                        {
603                                if(m_pPropertyPage)
604                                {
605                                        _V(m_pPropertyPage->SetPageSite(NULL));
606                                        m_pPropertyPage.Release();
607                                }
608                                m_pUnknown.Release();
609                                m_pOwner = NULL;
610                        }
611                        BOOL IsDirty()
612                        {
613                                return m_nStatus & PROPPAGESTATUS_DIRTY;
614                        }
615
616                // IPropertyPageSite
617                        STDMETHOD(OnStatusChange)(DWORD nFlags)
618                        {
619                                _Z4(atlTraceCOM, 4, _T("nFlags 0x%x\n"), nFlags);
620                                m_nStatus = nFlags;
621                                m_pOwner->HandleStatusChange(this);
622                                return S_OK;
623                        }
624                        STDMETHOD(GetLocaleID)(LCID* pLocaleIdentifier)
625                        {
626                                _Z4(atlTraceCOM, 4, _T("...\n"));
627                                pLocaleIdentifier;
628                                return E_NOTIMPL;
629                        }
630                        STDMETHOD(GetPageContainer)(IUnknown** ppUnknown)
631                        {
632                                _Z4(atlTraceCOM, 4, _T("...\n"));
633                                ppUnknown;
634                                return E_NOTIMPL;
635                        }
636                        STDMETHOD(TranslateAccelerator)(MSG* pMessage)
637                        {
638                                _Z4(atlTraceCOM, 4, _T("...\n"));
639                                pMessage;
640                                return E_NOTIMPL;
641                        }
642                };
643
644                ////////////////////////////////////////////////////
645                // CMemoryAllocatorDialog
646
647                class CMemoryAllocatorDialog :
648                        public CDialogImpl<CMemoryAllocatorDialog>,
649                        public CDialogResize<CMemoryAllocatorDialog>
650                {
651                public:
652                        enum { IDD = IDD_FILTERGRAPHHELPER_MEMORYALLOCATOR };
653
654                BEGIN_MSG_MAP_EX(CMemoryAllocatorDialog)
655                        //CHAIN_MSG_MAP(CDialogImpl<CMemoryAllocatorDialog>)
656                        CHAIN_MSG_MAP(CDialogResize<CMemoryAllocatorDialog>)
657                        MSG_WM_INITDIALOG(OnInitDialog)
658                        MSG_LVN_GETDISPINFO(IDC_FILTERGRAPHHELPER_MEMORYALLOCATOR_LIST, OnListViewGetDispInfo)
659                        MSG_LVN_GETINFOTIP(IDC_FILTERGRAPHHELPER_MEMORYALLOCATOR_LIST, OnListViewGetInfoTip)
660                        COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_MEMORYALLOCATOR_REFRESH, OnRefresh)
661                        REFLECT_NOTIFICATIONS()
662                END_MSG_MAP()
663
664                BEGIN_DLGRESIZE_MAP(CMemoryAllocatorDialog)
665                        DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_MEMORYALLOCATOR_LIST, DLSZ_SIZE_X | DLSZ_SIZE_Y)
666                        DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_MEMORYALLOCATOR_REFRESH, DLSZ_MOVE_Y)
667                END_DLGRESIZE_MAP()
668
669                public:
670
671                        ////////////////////////////////////////////////
672                        // CMemoryAllocatorData
673
674                        class CMemoryAllocatorData
675                        {
676                        public:
677                                LONG_PTR m_nIdentifier;
678                                CString m_sNames;
679                                HRESULT m_nMemAllocatorResult;
680                                LONG m_nBufferCount;
681                                LONG m_nBufferSize;
682                                LONG m_nBufferAlign;
683                                LONG m_nBufferPrefix;
684                                HRESULT m_nMemAllocatorCallbackTempResult;
685                                LONG m_nFreeBufferCount;
686
687                        public:
688                        // CMemoryAllocatorData
689                                VOID Initialize(CRoArrayT<CComVariantArray>& Array)
690                                {
691                                        SIZE_T nIndex = 0;
692                                        __D(nIndex + 2 + 1 + 1 <= Array.GetCount(), E_UNNAMED);
693                                        m_nIdentifier = Array[nIndex++].GetAsType(VT_I4).lVal;
694                                        m_sNames = Array[nIndex++].GetAsType(VT_BSTR).bstrVal;
695                                        m_nMemAllocatorResult = Array[nIndex++].GetAsType(VT_I4).lVal;
696                                        if(SUCCEEDED(m_nMemAllocatorResult))
697                                        {
698                                                __D(nIndex + 4 <= Array.GetCount(), E_UNNAMED);
699                                                m_nBufferCount = Array[nIndex++].GetAsType(VT_I4).lVal;
700                                                m_nBufferSize = Array[nIndex++].GetAsType(VT_I4).lVal;
701                                                m_nBufferAlign = Array[nIndex++].GetAsType(VT_I4).lVal;
702                                                m_nBufferPrefix = Array[nIndex++].GetAsType(VT_I4).lVal;
703                                        }
704                                        m_nMemAllocatorCallbackTempResult = Array[nIndex++].GetAsType(VT_I4).lVal;
705                                        if(SUCCEEDED(m_nMemAllocatorCallbackTempResult))
706                                        {
707                                                __D(nIndex + 1 <= Array.GetCount(), E_UNNAMED);
708                                                m_nFreeBufferCount = Array[nIndex++].GetAsType(VT_I4).lVal;
709                                        }
710                                }
711                        };
712
713                private:
714                        CPropertyFrameDialog* m_pOwner;
715                        BOOL m_bActivating;
716                        CStatic m_TitleStatic;
717                        CFont m_TitleFont;
718                        CRoListViewT<CMemoryAllocatorData, CRoListControlDataTraitsT> m_ListView;
719                        CButton m_RefreshButton;
720                        CRoMapT<INT_PTR, BOOL> m_ChangeMap;
721
722                public:
723                // CMemoryAllocatorDialog
724                        VOID UpdateListView()
725                        {
726                                CWindowRedraw ListViewRedraw(m_ListView);
727                                CRoArrayT<INT> ValidItemArray;
728                                _ATLTRY
729                                {
730                                        const CComQIPtr<IFilterGraphMemoryAllocatorData> pFilterGraphMemoryAllocatorData = m_pOwner->m_Owner.m_pFilterGraph;
731                                        if(pFilterGraphMemoryAllocatorData)
732                                        {
733                                                CComVariantArray vValue;
734                                                __C(pFilterGraphMemoryAllocatorData->get_Value(&vValue));
735                                                if(vValue.vt > VT_NULL)
736                                                {
737                                                        CRoArrayT<CComVariantArray> ItemArray;
738                                                        vValue.ToElementArray(ItemArray);
739                                                        for(auto&& vItemValue: ItemArray)
740                                                        {
741                                                                CRoArrayT<CComVariantArray> ItemItemArray;
742                                                                vItemValue.ToElementArray(ItemItemArray);
743                                                                // SUGG: Reuse existing list view items instead of full list replacement
744                                                                CMemoryAllocatorData Data;
745                                                                Data.Initialize(ItemItemArray);
746                                                                const INT nItem = m_ListView.InsertItem(m_ListView.GetItemCount(), Data);
747                                                                ValidItemArray.Add(nItem);
748                                                        }
749                                                }
750                                        }
751                                }
752                                _ATLCATCHALL()
753                                {
754                                        m_ListView.DeleteAllItems();
755                                        ValidItemArray.RemoveAll();
756                                        _ATLRETHROW;
757                                }
758                                for(INT nItem = m_ListView.GetItemCount() - 1; nItem >= 0; nItem--)
759                                        if(!ValidItemArray.FindFirst(nItem))
760                                                m_ListView.DeleteItem(nItem);
761                        }
762
763                // Window Message Handler
764                        LRESULT OnInitDialog(HWND, LPARAM lParam)
765                        {
766                                m_pOwner = (CPropertyFrameDialog*) lParam;
767                                m_bActivating = TRUE;
768                                _ATLTRY
769                                {
770                                        CWaitCursor WaitCursor;
771                                        m_TitleStatic = GetDlgItem(IDC_FILTERGRAPHHELPER_MEMORYALLOCATOR_TITLE);
772                                        CreateTitleFont(m_TitleFont, m_TitleStatic);
773                                        m_ListView.Initialize(GetDlgItem(IDC_FILTERGRAPHHELPER_MEMORYALLOCATOR_LIST));
774                                        m_RefreshButton = GetDlgItem(IDC_FILTERGRAPHHELPER_MEMORYALLOCATOR_REFRESH);
775                                        DlgResize_Init(FALSE, FALSE);
776                                        _ATLTRY
777                                        {
778                                                UpdateListView();
779                                        }
780                                        _ATLCATCHALL()
781                                        {
782                                                _Z_EXCEPTION();
783                                        }
784                                        m_bActivating = FALSE;
785                                }
786                                _ATLCATCH(Exception)
787                                {
788                                        for(CWindow Window = GetWindow(GW_CHILD); Window; Window = Window.GetWindow(GW_HWNDNEXT))
789                                                Window.EnableWindow(FALSE);
790                                        AtlExceptionMessageBox(m_hWnd, Exception);
791                                }
792                                return TRUE;
793                        }
794                        LRESULT OnListViewGetDispInfo(NMLVDISPINFO* pHeader)
795                        {
796                                const CMemoryAllocatorData& Data = m_ListView.DataFromParameter(pHeader->item.lParam);
797                                if(pHeader->item.mask & LVIF_TEXT)
798                                {
799                                        CString& sTextBuffer = m_ListView.GetTextBufferString(TRUE);
800                                        switch(pHeader->item.iSubItem)
801                                        {
802                                        case 1: // Buffer Count
803                                                if(SUCCEEDED(Data.m_nMemAllocatorResult))
804                                                        sTextBuffer = _StringHelper::FormatNumber(Data.m_nBufferCount);
805                                                break;
806                                        case 2: // Free Buffer Count
807                                                if(SUCCEEDED(Data.m_nMemAllocatorCallbackTempResult))
808                                                        sTextBuffer = _StringHelper::FormatNumber(Data.m_nFreeBufferCount);
809                                                break;
810                                        case 3: // Buffer Size
811                                                if(SUCCEEDED(Data.m_nMemAllocatorResult))
812                                                        sTextBuffer = _StringHelper::FormatNumber(Data.m_nBufferSize);
813                                                break;
814                                        default: // Name
815                                                sTextBuffer = Data.m_sNames;
816                                        }
817                                        pHeader->item.pszText = m_ListView.GetTextBuffer();
818                                }
819                                return 0;
820                        }
821                        LRESULT OnListViewGetInfoTip(NMLVGETINFOTIP* pHeader)
822                        {
823                                const CMemoryAllocatorData& Data = m_ListView.GetItemData(pHeader->iItem);
824                                CString& sTextBuffer = m_ListView.GetTextBufferString(TRUE);
825                                //sTextBuffer.AppendFormat(_T("Identifier: 0x%08X") _T("\r\n"), Data.m_nIdentifier);
826                                if(SUCCEEDED(Data.m_nMemAllocatorResult))
827                                {
828                                        sTextBuffer.AppendFormat(_T("Buffer Count: %s") _T("\r\n"), _StringHelper::FormatNumber(Data.m_nBufferCount));
829                                        sTextBuffer.AppendFormat(_T("Buffer Size: %s (%s total)") _T("\r\n"), _StringHelper::FormatNumber(Data.m_nBufferSize), _StringHelper::FormatNumber(Data.m_nBufferCount * Data.m_nBufferSize));
830                                        if(Data.m_nBufferAlign > 1)
831                                                sTextBuffer.AppendFormat(_T("Buffer Alignment: %s") _T("\r\n"), _StringHelper::FormatNumber(Data.m_nBufferAlign));
832                                        if(Data.m_nBufferPrefix > 0)
833                                                sTextBuffer.AppendFormat(_T("Buffer Prefix: %s") _T("\r\n"), _StringHelper::FormatNumber(Data.m_nBufferPrefix));
834                                } else
835                                        sTextBuffer.AppendFormat(_T("IMemAllocator: %s") _T("\r\n"), Ds::FormatResult(Data.m_nMemAllocatorResult, _T("Error 0x%08X")));
836                                if(SUCCEEDED(Data.m_nMemAllocatorCallbackTempResult))
837                                {
838                                        sTextBuffer.AppendFormat(_T("Free Buffer Count: %s") _T("\r\n"), _StringHelper::FormatNumber(Data.m_nFreeBufferCount));
839                                } else
840                                        sTextBuffer.AppendFormat(_T("IMemAllocatorCallbackTemp: %s") _T("\r\n"), Ds::FormatResult(Data.m_nMemAllocatorCallbackTempResult, _T("Error 0x%08X")));
841                                CString sNames = Data.m_sNames;
842                                sNames.Replace(_T(", "), _T("|"));
843                                CRoArrayT<CString> Array;
844                                _StringHelper::Split(sNames, _T('|'), Array);
845                                if(!Array.IsEmpty())
846                                {
847                                        sTextBuffer.Append(_T("\r\n") _T("Pin Connections:") _T("\r\n"));
848                                        for(auto&& sName: Array)
849                                        {
850                                                sTextBuffer.AppendFormat(_T("  ") _T("%s") _T("\r\n"), sName);
851                                        }
852                                }
853                                sTextBuffer.TrimRight(_T("\t\n\r ."));
854                                #pragma region Clipboard Copy
855                                if(GetKeyState(VK_CONTROL) < 0 && GetKeyState(VK_SHIFT) < 0)
856                                        _ATLTRY
857                                        {
858                                                SetClipboardText(m_hWnd, sTextBuffer);
859                                                MessageBeep(MB_OK);
860                                        }
861                                        _ATLCATCHALL()
862                                        {
863                                                _Z_EXCEPTION();
864                                                MessageBeep(MB_ICONERROR);
865                                        }
866                                #pragma endregion
867                                _tcsncpy_s(pHeader->pszText, pHeader->cchTextMax, m_ListView.GetTextBuffer(), _TRUNCATE);
868                                return 0;
869                        }
870                        LRESULT OnRefresh(UINT, INT, HWND)
871                        {
872                                UpdateListView();
873                                return 0;
874                        }
875                };
876
877                ////////////////////////////////////////////////////
878                // CActionDialog
879
880                class CActionDialog :
881                        public CDialogImpl<CActionDialog>,
882                        public CDialogResize<CActionDialog>
883                {
884                public:
885                        enum { IDD = IDD_FILTERGRAPHHELPER_ACTION };
886
887                BEGIN_MSG_MAP_EX(CActionDialog)
888                        //CHAIN_MSG_MAP(CDialogImpl<CActionDialog>)
889                        CHAIN_MSG_MAP(CDialogResize<CActionDialog>)
890                        MSG_WM_INITDIALOG(OnInitDialog)
891                        COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_ACTION_SAVEAS, OnSaveAs)
892                        COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_ACTION_OPENGSN, OnOpenGsn)
893                        COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_ACTION_OPENGE, OnOpenGe)
894                        COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_ACTION_OPENLIST, OnOpenList)
895                        REFLECT_NOTIFICATIONS()
896                END_MSG_MAP()
897
898                BEGIN_DLGRESIZE_MAP(CActionDialog)
899                        //DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_ACTION_, DLSZ_SIZE_X | DLSZ_SIZE_Y)
900                END_DLGRESIZE_MAP()
901
902                private:
903                        CPropertyFrameDialog* m_pOwner;
904                        BOOL m_bActivating;
905                        CStatic m_TitleStatic;
906                        CFont m_TitleFont;
907                        CButton m_SaveAsButton;
908                        CRoHyperStatic m_SaveAsDescriptionStatic;
909                        CButton m_OpenGsnButton;
910                        CRoHyperStatic m_OpenGsnDescriptionStatic;
911                        CButton m_OpenGeButton;
912                        CRoHyperStatic m_OpenGeDescriptionStatic;
913                        CButton m_OpenListButton;
914                        CRoHyperStatic m_OpenListDescriptionStatic;
915                        CStringW m_sFilterGraphMonikerDisplayName;
916                        CRoMapT<INT_PTR, BOOL> m_ChangeMap;
917
918                public:
919                // CActionDialog
920
921                // Window Message Handler
922                        LRESULT OnInitDialog(HWND, LPARAM lParam)
923                        {
924                                m_pOwner = (CPropertyFrameDialog*) lParam;
925                                m_bActivating = TRUE;
926                                _ATLTRY
927                                {
928                                        CWaitCursor WaitCursor;
929                                        m_TitleStatic = GetDlgItem(IDC_FILTERGRAPHHELPER_ACTION_TITLE);
930                                        CreateTitleFont(m_TitleFont, m_TitleStatic);
931                                        m_SaveAsButton = GetDlgItem(IDC_FILTERGRAPHHELPER_ACTION_SAVEAS);
932                                        _W(m_SaveAsDescriptionStatic.SubclassWindow(GetDlgItem(IDC_FILTERGRAPHHELPER_ACTION_SAVEASDESCRIPTION)));
933                                        m_OpenGsnButton = GetDlgItem(IDC_FILTERGRAPHHELPER_ACTION_OPENGSN);
934                                        _W(m_OpenGsnDescriptionStatic.SubclassWindow(GetDlgItem(IDC_FILTERGRAPHHELPER_ACTION_OPENGSNDESCRIPTION)));
935                                        m_OpenGeButton = GetDlgItem(IDC_FILTERGRAPHHELPER_ACTION_OPENGE);
936                                        _W(m_OpenGeDescriptionStatic.SubclassWindow(GetDlgItem(IDC_FILTERGRAPHHELPER_ACTION_OPENGEDESCRIPTION)));
937                                        m_OpenListButton = GetDlgItem(IDC_FILTERGRAPHHELPER_ACTION_OPENLIST);
938                                        _W(m_OpenListDescriptionStatic.SubclassWindow(GetDlgItem(IDC_FILTERGRAPHHELPER_ACTION_OPENLISTDESCRIPTION)));
939                                        //DlgResize_Init(FALSE, FALSE);
940                                        _ATLTRY
941                                        {
942                                                m_sFilterGraphMonikerDisplayName.Empty();
943                                                const CComQIPtr<ISpy> pSpy = m_pOwner->m_Owner.GetFilterGraph();
944                                                if(pSpy)
945                                                {
946                                                        CComBSTR sFilterGraphMonikerDisplayName;
947                                                        __C(pSpy->get_MonikerDisplayName(&sFilterGraphMonikerDisplayName));
948                                                        m_sFilterGraphMonikerDisplayName = sFilterGraphMonikerDisplayName;
949                                                }
950                                        }
951                                        _ATLCATCHALL()
952                                        {
953                                                _Z_EXCEPTION();
954                                        }
955                                        const BOOL bMonikerDisplayNameAvailable = !m_sFilterGraphMonikerDisplayName.IsEmpty();
956                                        m_OpenGsnButton.EnableWindow(bMonikerDisplayNameAvailable);
957                                        m_OpenGsnDescriptionStatic.EnableWindow(bMonikerDisplayNameAvailable);
958                                        m_OpenGeButton.EnableWindow(bMonikerDisplayNameAvailable);
959                                        m_OpenGeDescriptionStatic.EnableWindow(bMonikerDisplayNameAvailable);
960                                        m_bActivating = FALSE;
961                                }
962                                _ATLCATCH(Exception)
963                                {
964                                        for(CWindow Window = GetWindow(GW_CHILD); Window; Window = Window.GetWindow(GW_HWNDNEXT))
965                                                Window.EnableWindow(FALSE);
966                                        AtlExceptionMessageBox(m_hWnd, Exception);
967                                }
968                                return TRUE;
969                        }
970                        LRESULT OnSaveAs(UINT, INT, HWND)
971                        {
972                                static const COMDLG_FILTERSPEC g_pFilter[] = 
973                                {
974                                        { _T("GraphEdit Files"), _T("*.grf") },
975                                        { _T("All Files"), _T("*.*") },
976                                };
977                                CPath sPath = _CommonDialogHelper::QuerySavePath(m_hWnd, g_pFilter, _T("grf"));
978                                if(_tcslen(sPath) == 0)
979                                        return 0;
980                                #pragma region Save
981                                // NOTE: See http://msdn.microsoft.com/en-us/library/windows/desktop/dd377551
982                                const CComQIPtr<IPersistStream> pPersistStream = m_pOwner->m_Owner.GetFilterGraph();
983                                __D(pPersistStream, E_NOINTERFACE);
984                                CComPtr<IStorage> pStorage;
985                                {
986                                        __C(StgCreateDocfile(CStringW(sPath), STGM_CREATE | STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage));
987                                        CComPtr<IStream> pStream;
988                                        __C(pStorage->CreateStream(L"ActiveMovieGraph", STGM_WRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream));
989                                        __C(pPersistStream->Save(pStream, TRUE));
990                                }
991                                __C(pStorage->Commit(STGC_DEFAULT));
992                                #pragma endregion
993                                MessageBeep(MB_OK);
994                                return 0;
995                        }
996                        LRESULT OnOpenGsn(UINT, INT, HWND)
997                        {
998                                OpenMonikerWithGsn(m_sFilterGraphMonikerDisplayName, m_hWnd);
999                                return 0;
1000                        }
1001                        LRESULT OnOpenGe(UINT, INT, HWND)
1002                        {
1003                                OpenMonikerWithGe(m_sFilterGraphMonikerDisplayName, m_hWnd);
1004                                return 0;
1005                        }
1006                        LRESULT OnOpenList(UINT, INT, HWND)
1007                        {
1008                                DoFilterGraphListPropertySheetModal(m_hWnd, &m_pOwner->m_Owner.m_Options);
1009                                return 0;
1010                        }
1011                };
1012
1013                ////////////////////////////////////////////////////
1014                // CEmailLogDialog
1015
1016                class CEmailLogDialog :
1017                        public CDialogImpl<CEmailLogDialog>,
1018                        public CDialogResize<CEmailLogDialog>
1019                {
1020                public:
1021                        enum { IDD = IDD_FILTERGRAPHHELPER_EMAIL_LOG };
1022
1023                BEGIN_MSG_MAP_EX(CEmailLogDialog)
1024                        //CHAIN_MSG_MAP(CDialogImpl<CEmailLogDialog>)
1025                        CHAIN_MSG_MAP(CDialogResize<CEmailLogDialog>)
1026                        MSG_WM_INITDIALOG(OnInitDialog)
1027                        MSG_LVN_GETDISPINFO(IDC_FILTERGRAPHHELPER_EMAIL_LOG_FILE, OnFileListViewGetDispInfo)
1028                        //MSG_LVN_GETINFOTIP()
1029                        MSG_LVN_ITEMCHANGED(IDC_FILTERGRAPHHELPER_EMAIL_LOG_FILE, OnFileListViewItemChanged)
1030                        //COMMAND_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_LOG_TRUNCATE, CBN_CHANGE, OnChanged)
1031                        //COMMAND_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_LOG_DELETE, CBN_CHANGE, OnChanged)
1032                        REFLECT_NOTIFICATIONS()
1033                END_MSG_MAP()
1034
1035                BEGIN_DLGRESIZE_MAP(CEmailLogDialog)
1036                        DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_EMAIL_LOG_FILE, DLSZ_SIZE_X | DLSZ_SIZE_Y)
1037                        DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_EMAIL_LOG_TRUNCATETITLE, DLSZ_MOVE_Y)
1038                        DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_EMAIL_LOG_TRUNCATE, DLSZ_MOVE_Y)
1039                        DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_EMAIL_LOG_DELETETITLE, DLSZ_MOVE_Y)
1040                        DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_EMAIL_LOG_DELETE, DLSZ_MOVE_Y)
1041                END_DLGRESIZE_MAP()
1042
1043                public:
1044
1045                        ////////////////////////////////////////////////
1046                        // CFileData
1047
1048                        class CFileData
1049                        {
1050                        public:
1051                                UINT m_nLocation;
1052                                CPath m_sPath;
1053                                ULONGLONG m_nSize;
1054                                FILETIME m_UpdateTime;
1055
1056                        public:
1057                        // CFileData
1058                                CFileData(UINT nLocation, LPCTSTR pszDirectory, WIN32_FIND_DATA FindData)
1059                                {
1060                                        m_nLocation = nLocation;
1061                                        m_sPath.Combine(pszDirectory, FindData.cFileName);
1062                                        m_nSize = ((ULONGLONG) FindData.nFileSizeHigh << 32) + FindData.nFileSizeLow;
1063                                        m_UpdateTime = FindData.ftLastWriteTime;
1064                                }
1065                                FILETIME GetLocalUpdateTime() const
1066                                {
1067                                        FILETIME UpdateTime;
1068                                        _W(FileTimeToLocalFileTime(&m_UpdateTime, &UpdateTime));
1069                                        return UpdateTime;
1070                                }
1071                        };
1072
1073                        ////////////////////////////////////////////////
1074                        // CFileDataSortTraits
1075
1076                        class CFileDataSortTraits :
1077                                public CDefaultSortTraitsT<CFileData>
1078                        {
1079                        public:
1080                        // CFileDataSortTraits
1081                                static INT_PTR CompareElements(const CFileData& FileData1, const CFileData& FileData2, PARAMETERARGUMENT Parameter)
1082                                {
1083                                        const INT nLocation = FileData1.m_nLocation - FileData2.m_nLocation;
1084                                        if(nLocation)
1085                                                return nLocation;
1086                                        return _tcsicmp(FindFileName(FileData1.m_sPath), FindFileName(FileData2.m_sPath));
1087                                }
1088                        };
1089
1090                        ////////////////////////////////////////////////
1091                        // CFileDataArray
1092
1093                        class CFileDataArray :
1094                                public CRoArrayT<CFileData>
1095                        {
1096                        public:
1097                        // CFileDataArray
1098                                static BOOL CompareLocation(const CFileData& FileData, UINT nLocation)
1099                                {
1100                                        return FileData.m_nLocation == nLocation;
1101                                }
1102                                SIZE_T GetCountForLocation(UINT nLocation)
1103                                {
1104                                        return GetCountThatT<UINT>(&CFileDataArray::CompareLocation, nLocation);
1105                                }
1106                        };
1107
1108                        ////////////////////////////////////////////////
1109                        // CSelectedFileData
1110
1111                        class CSelectedFileData
1112                        {
1113                        public:
1114                                CPath m_sPath;
1115                                CString m_sName;
1116
1117                        public:
1118                        // CSelectedFileData
1119                        };
1120
1121                private:
1122                        CPropertyFrameDialog* m_pOwner;
1123                        BOOL m_bActivating;
1124                        CStatic m_TitleStatic;
1125                        CFont m_TitleFont;
1126                        CRoListViewT<CFileData, CRoListControlDataTraitsT> m_FileListView;
1127                        INT m_nFileListViewGroupViewEnabled;
1128                        CRoComboBoxT<> m_TruncateComboBox;
1129                        CRoComboBoxT<> m_DeleteComboBox;
1130                        CRoMapT<INT_PTR, BOOL> m_ChangeMap;
1131
1132                public:
1133                // CEmailLogDialog
1134                        CEmailLogDialog()
1135                        {
1136                        }
1137                        VOID UpdateControls()
1138                        {
1139                        }
1140                        VOID InitializeFileListView()
1141                        {
1142                                CWindowRedraw FileListViewRedraw(m_FileListView);
1143                                m_FileListView.DeleteAllItems();
1144                                m_FileListView.RemoveAllGroups();
1145                                #pragma region File
1146                                CFileDataArray FileDataArray;
1147                                static DWORD g_pnLocations[] = 
1148                                {
1149                                        CSIDL_COMMON_APPDATA,
1150                                        CSIDL_APPDATA,
1151                                };
1152                                for(SIZE_T nLocationIndex = 0; nLocationIndex < DIM(g_pnLocations); nLocationIndex++)
1153                                        _ATLTRY
1154                                        {
1155                                                TCHAR pszDirectory[MAX_PATH] = { 0 };
1156                                                if(!SHGetSpecialFolderPath(NULL, pszDirectory, g_pnLocations[nLocationIndex], FALSE))
1157                                                        continue;
1158                                                CFindFiles FindFiles;
1159                                                for(BOOL bFound = FindFiles.FindFirstFile(pszDirectory, _T("*.*")); bFound; bFound = FindFiles.FindNextFile())
1160                                                {
1161                                                        const WIN32_FIND_DATA& Data = FindFiles.GetFindData();
1162                                                        if(Data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1163                                                                continue; // Directory
1164                                                        LPCTSTR pszExtension = FindExtension(Data.cFileName);
1165                                                        if(!pszExtension || !(_tcsicmp(pszExtension, _T(".log")) == 0 || _tcsicmp(pszExtension, _T(".dmp")) == 0))
1166                                                                continue; // Extension Mismatch
1167                                                        FileDataArray.Add(CFileData((UINT) nLocationIndex, pszDirectory, Data));
1168                                                }
1169                                        }
1170                                        _ATLCATCHALL()
1171                                        {
1172                                                _Z_EXCEPTION();
1173                                        }
1174                                _SortHelper::QuickSort<CFileDataSortTraits>(FileDataArray);
1175                                if(m_nFileListViewGroupViewEnabled >= 0)
1176                                {
1177                                        if(FileDataArray.GetCountForLocation(0))
1178                                                m_FileListView.InsertGroup(0, 0, _T("Local Machine (Common AppData)"));
1179                                        if(FileDataArray.GetCountForLocation(1))
1180                                                m_FileListView.InsertGroup(1, 1, _T("Current User (AppData)"));
1181                                }
1182                                CPath sPrivateLogFileName = FindFileName(GetModulePath());
1183                                sPrivateLogFileName.RenameExtension(_T(".log"));
1184                                for(SIZE_T nIndex = 0; nIndex < FileDataArray.GetCount(); nIndex++)
1185                                {
1186                                        CFileData& FileData = FileDataArray[nIndex];
1187                                        INT nItem;
1188                                        if(m_nFileListViewGroupViewEnabled >= 0)
1189                                                nItem = m_FileListView.InsertGroupItem(m_FileListView.GetItemCount(), FileData.m_nLocation, FileData);
1190                                        else
1191                                                nItem = m_FileListView.InsertItem(m_FileListView.GetItemCount(), FileData);
1192                                        if(_tcsicmp(FindFileName(FileData.m_sPath), sPrivateLogFileName) == 0)
1193                                                m_FileListView.SetCheckState(nItem, TRUE);
1194                                }
1195                        }
1196                        SIZE_T GetFiles(CRoArrayT<CSelectedFileData>& Array)
1197                        {
1198                                _A(Array.IsEmpty());
1199                                for(INT nItem = 0; nItem < m_FileListView.GetItemCount(); nItem++)
1200                                {
1201                                        if(!m_FileListView.GetCheckState(nItem))
1202                                                continue;
1203                                        const CFileData& FileData = m_FileListView.GetItemData(nItem);
1204                                        CSelectedFileData SelectedFileData;
1205                                        SelectedFileData.m_sPath = FileData.m_sPath;
1206                                        CPath sName = FindFileName(FileData.m_sPath);
1207                                        if(FileData.m_nLocation == 1)
1208                                        {
1209                                                CString sExtention = FindExtension(sName);
1210                                                sName.RemoveExtension();
1211                                                sName = (LPCTSTR) AtlFormatString(_T("%s (%s)%s"), sName, _T("Current User"), sExtention);
1212                                        }
1213                                        SelectedFileData.m_sName = (LPCTSTR) sName;
1214                                        Array.Add(SelectedFileData);
1215                                }
1216                                return Array.GetCount();
1217                        }
1218                        ULONGLONG GetTruncateSize()
1219                        {
1220                                static const ULONGLONG g_pnTruncateSizes[] = 
1221                                {
1222                                         1i64 << 20, //  1 MB
1223                                        10i64 << 20, // 10 MB
1224                                        25i64 << 20, // 25 MB
1225                                        50i64 << 20, // 50 MB
1226                                };
1227                                const INT nItem = m_TruncateComboBox.GetCurSel();
1228                                _A(nItem >= 0 && nItem < DIM(g_pnTruncateSizes));
1229                                return g_pnTruncateSizes[nItem];
1230                        }
1231                        BOOL GetDelete()
1232                        {
1233                                return m_DeleteComboBox.GetCurSel() == 1;
1234                        }
1235
1236                // Window Message Handler
1237                        LRESULT OnInitDialog(HWND, LPARAM lParam)
1238                        {
1239                                m_pOwner = (CPropertyFrameDialog*) lParam;
1240                                m_bActivating = TRUE;
1241                                _ATLTRY
1242                                {
1243                                        CWaitCursor WaitCursor;
1244                                        m_TitleStatic = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_LOG_TITLE);
1245                                        CreateTitleFont(m_TitleFont, m_TitleStatic);
1246                                        m_FileListView.Initialize(GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_LOG_FILE));
1247                                        m_nFileListViewGroupViewEnabled = m_FileListView.EnableGroupView(TRUE);
1248                                        if(!m_nFileListViewGroupViewEnabled)
1249                                                m_nFileListViewGroupViewEnabled = m_FileListView.IsGroupViewEnabled() ? 1 : -1;
1250                                        m_TruncateComboBox.Initialize(GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_LOG_TRUNCATE));
1251                                        m_DeleteComboBox.Initialize(GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_LOG_DELETE));
1252                                        DlgResize_Init(FALSE, FALSE);
1253                                        InitializeFileListView();
1254                                        m_FileListView.SetColumnWidth(3, LVSCW_AUTOSIZE);
1255                                        m_TruncateComboBox.SetCurSel(2);
1256                                        m_DeleteComboBox.SetCurSel(0);
1257                                        UpdateControls();
1258                                        m_bActivating = FALSE;
1259                                }
1260                                _ATLCATCH(Exception)
1261                                {
1262                                        for(CWindow Window = GetWindow(GW_CHILD); Window; Window = Window.GetWindow(GW_HWNDNEXT))
1263                                                Window.EnableWindow(FALSE);
1264                                        AtlExceptionMessageBox(m_hWnd, Exception);
1265                                }
1266                                return TRUE;
1267                        }
1268                        LRESULT OnChanged(UINT, INT_PTR nIdentifier, HWND)
1269                        {
1270                                if(m_bActivating)
1271                                        return 0;
1272                                m_ChangeMap[nIdentifier] = TRUE;
1273                                UpdateControls();
1274                                return 0;
1275                        }
1276                        LRESULT OnChanged(NMHDR* pHeader)
1277                        {
1278                                return OnChanged(pHeader->code, pHeader->idFrom, pHeader->hwndFrom);
1279                        }
1280                        LRESULT OnFileListViewGetDispInfo(NMLVDISPINFO* pHeader)
1281                        {
1282                                const CFileData& FileData = m_FileListView.DataFromParameter(pHeader->item.lParam);
1283                                if(pHeader->item.mask & LVIF_TEXT)
1284                                {
1285                                        CString& sTextBuffer = m_FileListView.GetTextBufferString(TRUE);
1286                                        switch(pHeader->item.iSubItem)
1287                                        {
1288                                        case 1: // Size
1289                                                sTextBuffer = _StringHelper::FormatNumber((LONGLONG) FileData.m_nSize);
1290                                                break;
1291                                        case 2: // Update Time
1292                                                sTextBuffer = _StringHelper::FormatDateTime(FileData.GetLocalUpdateTime());
1293                                                break;
1294                                        case 3: // Directory
1295                                                sTextBuffer = (LPCTSTR) GetPathDirectory(FileData.m_sPath);
1296                                                break;
1297                                        default: // File Name
1298                                                sTextBuffer = FindFileName(FileData.m_sPath);
1299                                        }
1300                                        pHeader->item.pszText = m_FileListView.GetTextBuffer();
1301                                }
1302                                return 0;
1303                        }
1304                        LRESULT OnFileListViewItemChanged(NMLISTVIEW* pHeader)
1305                        {
1306                                return m_FileListView.OnReflectedItemChanged(pHeader);
1307                        }
1308                };
1309
1310                ////////////////////////////////////////////////////
1311                // CEmailDialog
1312
1313                class CEmailDialog :
1314                        public CDialogImpl<CEmailDialog>,
1315                        public CDialogResize<CEmailDialog>
1316                {
1317                public:
1318                        enum { IDD = IDD_FILTERGRAPHHELPER_EMAIL };
1319
1320                BEGIN_MSG_MAP_EX(CEmailDialog)
1321                        //CHAIN_MSG_MAP(CDialogImpl<CEmailDialog>)
1322                        CHAIN_MSG_MAP(CDialogResize<CEmailDialog>)
1323                        MSG_WM_INITDIALOG(OnInitDialog)
1324                        MSG_WM_DESTROY(OnDestroy)
1325                        MSG_WM_SHOWWINDOW(OnShowWindow)
1326                        COMMAND_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_FROM, EN_CHANGE, OnChanged)
1327                        COMMAND_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_TO, EN_CHANGE, OnChanged)
1328                        COMMAND_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_METHOD, CBN_SELENDOK, OnChanged)
1329                        COMMAND_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_HOST, EN_CHANGE, OnChanged)
1330                        COMMAND_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_USERNAME, EN_CHANGE, OnChanged)
1331                        COMMAND_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_PASSWORD, EN_CHANGE, OnChanged)
1332                        COMMAND_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_BODY, EN_CHANGE, OnChanged)
1333                        COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_SEND, OnSend)
1334                        NOTIFY_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_CLEANUP, CRoHyperStatic::NC_ANCHORCLICKED, OnCleanupStaticAnchorClicked)
1335                        REFLECT_NOTIFICATIONS()
1336                ALT_MSG_MAP(IDC_FILTERGRAPHHELPER_EMAIL_FROM)
1337                        MSG_WM_PASTE(OnFromEditPaste)
1338                END_MSG_MAP()
1339
1340                BEGIN_DLGRESIZE_MAP(CEmailDialog)
1341                        DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_EMAIL_BODY, DLSZ_SIZE_X | DLSZ_SIZE_Y)
1342                        DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_EMAIL_SEND, DLSZ_MOVE_X | DLSZ_MOVE_Y)
1343                        DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_EMAIL_CLEANUP, DLSZ_MOVE_Y)
1344                END_DLGRESIZE_MAP()
1345
1346                private:
1347                        CPropertyFrameDialog* m_pOwner;
1348                        BOOL m_bActivating;
1349                        CStatic m_TitleStatic;
1350                        CFont m_TitleFont;
1351                        CContainedWindowT<CRoEdit> m_FromEdit;
1352                        CRoEdit m_ToEdit;
1353                        CRoComboBoxT<> m_MethodComboBox;
1354                        CRoEdit m_HostEdit;
1355                        CRoEdit m_UsernameEdit;
1356                        CRoEdit m_PasswordEdit;
1357                        CRoEdit m_BodyEdit;
1358                        CButton m_SendButton;
1359                        CRoHyperStatic m_CleanupStatic;
1360                        CString m_sFilterGraphText;
1361                        CRoMapT<INT_PTR, BOOL> m_ChangeMap;
1362
1363                public:
1364                // CEmailDialog
1365                        CEmailDialog() :
1366                                m_FromEdit(this, IDC_FILTERGRAPHHELPER_EMAIL_FROM)
1367                        {
1368                        }
1369                        BOOL InitializeControlsFromMessageString(const CString& sMessageString)
1370                        {
1371                                _ATLTRY
1372                                {
1373                                        CObjectPtr<CMessage> pMessage;
1374                                        pMessage.Construct();
1375                                        pMessage->LoadTypeInfo(IDR_EMAILTOOLS);
1376                                        pMessage->SetAsString(CStringA(sMessageString));
1377                                        #pragma region Sender and Recipients
1378                                        CComBSTR sSender, sToRecipients;
1379                                        __C(pMessage->get_Sender(&sSender));
1380                                        __C(pMessage->get_ToRecipients(&sToRecipients));
1381                                        m_FromEdit.SetValue(CString(sSender));
1382                                        m_ToEdit.SetValue(CString(sToRecipients));
1383                                        #pragma endregion
1384                                        CComBSTR sAuthMethods;
1385                                        __C(pMessage->get_AuthMethods(&sAuthMethods));
1386                                        VARIANT_BOOL bSecureSocketsLayer, bTransportLayerSecurity;
1387                                        __C(pMessage->get_SecureSocketsLayer(&bSecureSocketsLayer));
1388                                        __C(pMessage->get_TransportLayerSecurity(&bTransportLayerSecurity));
1389                                        #pragma region Host and Port
1390                                        CComBSTR sHost;
1391                                        __C(pMessage->get_ServerHost(&sHost));
1392                                        LONG nPort = 0;
1393                                        __C(pMessage->get_ServerPort(&nPort));
1394                                        CString sHostT(sHost);
1395                                        if(nPort)
1396                                                sHostT += AtlFormatString(_T(":%d"), nPort);
1397                                        m_HostEdit.SetValue(sHostT);
1398                                        #pragma endregion
1399                                        #pragma region User Name and Password
1400                                        CComBSTR sAuthName, sAuthPassword;
1401                                        __C(pMessage->get_AuthName(&sAuthName));
1402                                        __C(pMessage->get_AuthPassword(&sAuthPassword));
1403                                        m_UsernameEdit.SetValue(CString(sAuthName));
1404                                        m_PasswordEdit.SetValue(CString(sAuthPassword));
1405                                        #pragma endregion
1406                                        m_MethodComboBox.SetCurSel(0);
1407                                        if(bTransportLayerSecurity != ATL_VARIANT_FALSE && sHostT.CompareNoCase(_T("smtp.gmail.com")) == 0)
1408                                        {
1409                                                //m_MethodComboBox.SetCurSel(0);
1410                                        } else
1411                                        {
1412                                                if(bTransportLayerSecurity != ATL_VARIANT_FALSE)
1413                                                        m_MethodComboBox.SetCurSel(1);
1414                                                else if(bSecureSocketsLayer != ATL_VARIANT_FALSE)
1415                                                        m_MethodComboBox.SetCurSel(2);
1416                                                else if(CString(sAuthMethods).CompareNoCase(_T("cram-md5")) == 0)
1417                                                        m_MethodComboBox.SetCurSel(3);
1418                                                else if(!CString(sAuthName).IsEmpty())
1419                                                        m_MethodComboBox.SetCurSel(4);
1420                                                else
1421                                                        m_MethodComboBox.SetCurSel(5);
1422                                        }
1423                                }
1424                                _ATLCATCHALL()
1425                                {
1426                                        _Z_EXCEPTION();
1427                                        return FALSE;
1428                                }
1429                                return TRUE;
1430                        }
1431                        VOID InitializeControlsFromRegistry()
1432                        {
1433                                const CString sMessageString = _RegKeyHelper::QueryStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, _T("Email Message Template"));
1434                                if(sMessageString.IsEmpty())
1435                                        return;
1436                                InitializeControlsFromMessageString(sMessageString);
1437                        }
1438                        VOID InitializeBody()
1439                        {
1440                                CString sText;
1441                                sText += _T("(add notes here; graph data will be appended below)") _T("\r\n") _T("\r\n");
1442                                sText += _T("* * *") _T("\r\n") _T("\r\n");
1443                                #define I FormatIdentifier
1444                                #pragma region System
1445                                {
1446                                        sText += _T("# System") _T("\r\n") _T("\r\n");
1447                                        OSVERSIONINFOEX Version;
1448                                        ZeroMemory(&Version, sizeof Version);
1449                                        Version.dwOSVersionInfoSize = sizeof Version;
1450                                        #pragma warning(disable: 4996) // 'GetVersionExW': was declared deprecated
1451                                        GetVersionEx((OSVERSIONINFO*) &Version);
1452                                        #pragma warning(default: 4996)
1453                                        #pragma region Version
1454                                        CRoArrayT<CString> VersionArray;
1455                                        VersionArray.Add(AtlFormatString(_T("%s Build %s"), I(AtlFormatString(_T("%d.%d"), Version.dwMajorVersion, Version.dwMinorVersion)), I(Version.dwBuildNumber)));
1456                                        switch((Version.dwMajorVersion << 16) + Version.dwMinorVersion)
1457                                        {
1458                                        case 0x00050001: 
1459                                                VersionArray.Add(_T("Windows XP"));
1460                                                break;
1461                                        case 0x00050002: 
1462                                                if(Version.wProductType != VER_NT_WORKSTATION)
1463                                                        VersionArray.Add(_T("Windows Server 2003"));
1464                                                break;
1465                                        case 0x00060000: 
1466                                                if(Version.wProductType == VER_NT_WORKSTATION)
1467                                                        VersionArray.Add(_T("Windows Vista"));
1468                                                else
1469                                                        VersionArray.Add(_T("Windows Server 2008"));
1470                                                break;
1471                                        case 0x00060001: 
1472                                                if(Version.wProductType == VER_NT_WORKSTATION)
1473                                                        VersionArray.Add(_T("Windows 7"));
1474                                                else
1475                                                        VersionArray.Add(_T("Windows Server 2008 R2"));
1476                                                break;
1477                                        case 0x00060002: 
1478                                                if(Version.wProductType == VER_NT_WORKSTATION)
1479                                                        VersionArray.Add(_T("Windows 8"));
1480                                                else
1481                                                        VersionArray.Add(_T("Windows Server 2012"));
1482                                                break;
1483                                        }
1484                                        if(_tcslen(Version.szCSDVersion))
1485                                                VersionArray.Add(Version.szCSDVersion);
1486                                        if(Version.wServicePackMajor)
1487                                                VersionArray.Add(AtlFormatString(_T("Service Pack %s"), I(AtlFormatString(_T("%d.%d"), Version.wServicePackMajor, Version.wServicePackMinor))));
1488                                        //Version.wSuiteMask, Version.wProductType
1489                                        sText += AtlFormatString(_T(" * ") _T("Version: %s") _T("\r\n"), _StringHelper::Join(VersionArray, _T("; ")));
1490                                        #pragma endregion
1491                                        sText += AtlFormatString(_T(" * ") _T("Computer Name: %s") _T("\r\n"), I(GetComputerName()));
1492                                        TCHAR pszUserName[256] = { 0 };
1493                                        DWORD nUserNameLength = DIM(pszUserName);
1494                                        GetUserName(pszUserName, &nUserNameLength);
1495                                        CString sUserName(pszUserName);
1496                                        BOOL bAdministrator = FALSE;
1497                                        bool bIsMember = FALSE;
1498                                        if(CAccessToken().CheckTokenMembership(Sids::Admins(), &bIsMember) && bIsMember)
1499                                                bAdministrator = TRUE;
1500                                        sText += AtlFormatString(_T(" * ") _T("User Name: %s %s") _T("\r\n"), I(sUserName), bAdministrator ? _T("(Administrator)") : _T(""));
1501                                        SYSTEM_INFO SystemInformation;
1502                                        GetSystemInfo(&SystemInformation);
1503                                        #pragma region Architecture
1504                                        CString sArchitecture;
1505                                        switch(SystemInformation.wProcessorArchitecture)
1506                                        {
1507                                        case PROCESSOR_ARCHITECTURE_INTEL:
1508                                                sArchitecture = I(_T("x86"));
1509                                                break;
1510                                        case PROCESSOR_ARCHITECTURE_AMD64:
1511                                                sArchitecture = I(_T("AMD/Intel x64"));
1512                                                break;
1513                                        case PROCESSOR_ARCHITECTURE_IA64:
1514                                                sArchitecture = I(_T("Intel Itanium"));
1515                                                break;
1516                                        default:
1517                                                sArchitecture = I(SystemInformation.wProcessorArchitecture, _T("0x%04X"));
1518                                        }
1519                                        #if defined(_WIN64)
1520                                                sText += AtlFormatString(_T(" * ") _T("Architecture: %s (x64 Application)") _T("\r\n"), sArchitecture);
1521                                        #else
1522                                                sText += AtlFormatString(_T(" * ") _T("Architecture: %s") _T("\r\n"), sArchitecture);
1523                                        #endif // defined(_WIN64)
1524                                        #pragma endregion
1525                                        sText += AtlFormatString(_T(" * ") _T("Processors: %s, Active Mask %s") _T("\r\n"), I(SystemInformation.dwNumberOfProcessors), I((DWORD) SystemInformation.dwActiveProcessorMask, _T("0x%X")));
1526                                        sText += AtlFormatString(_T(" * ") _T("Page Size: %s") _T("\r\n"), I(SystemInformation.dwPageSize, _T("0x%X")));
1527                                        sText += AtlFormatString(_T(" * ") _T("Application Address Space: %s..%s") _T("\r\n"), I(SystemInformation.lpMinimumApplicationAddress), I(SystemInformation.lpMaximumApplicationAddress));
1528                                        #pragma region Memory
1529                                        MEMORYSTATUSEX MemoryStatus = { sizeof MemoryStatus };
1530                                        _W(GlobalMemoryStatusEx(&MemoryStatus));
1531                                        sText += AtlFormatString(_T(" * ") _T("Physical Memory: %s MB") _T("\r\n"), I(_StringHelper::FormatNumber((LONG) (MemoryStatus.ullTotalPhys >> 20))));
1532                                        sText += AtlFormatString(_T(" * ") _T("Committed Memory Limit: %s MB") _T("\r\n"), I(_StringHelper::FormatNumber((LONG) (MemoryStatus.ullTotalPageFile >> 20))));
1533                                        #pragma endregion
1534                                }
1535                                #pragma endregion
1536                                sText += AtlFormatString(_T(" * ") _T("Module Version: %s") _T("\r\n"), I(_VersionInfoHelper::GetVersionString(_VersionInfoHelper::GetFileVersion(_VersionInfoHelper::GetModulePath()))));
1537                                SYSTEMTIME LocalTime;
1538                                GetLocalTime(&LocalTime);
1539                                sText += AtlFormatString(_T(" * ") _T("Local Time: %s") _T("\r\n"), I(_StringHelper::FormatDateTime(&LocalTime)));
1540                                sText += _T("\r\n");
1541                                #undef I
1542                                m_BodyEdit.SetValue(sText);
1543                        }
1544                        VOID UpdateControls()
1545                        {
1546                                BOOL bAllowSend = TRUE;
1547                                if(m_ToEdit.GetValue().Trim().IsEmpty())
1548                                        bAllowSend = FALSE;
1549                                const INT nMethod = m_MethodComboBox.GetCurSel();
1550                                m_HostEdit.GetWindow(GW_HWNDPREV).EnableWindow(nMethod != 0); // Google Mail
1551                                m_HostEdit.EnableWindow(nMethod != 0); // Google Mail
1552                                m_UsernameEdit.GetWindow(GW_HWNDPREV).EnableWindow(nMethod != 5); // No Authentication
1553                                m_UsernameEdit.EnableWindow(nMethod != 5); // No Authentication
1554                                m_PasswordEdit.GetWindow(GW_HWNDPREV).EnableWindow(nMethod != 5); // No Authentication
1555                                m_PasswordEdit.EnableWindow(nMethod != 5); // No Authentication
1556                                if(nMethod != 0) // Google Mail
1557                                        if(m_HostEdit.GetValue().Trim().IsEmpty())
1558                                                bAllowSend = FALSE;
1559                                if(nMethod != 5) // No Authentication
1560                                {
1561                                        if(m_UsernameEdit.GetValue().Trim().IsEmpty())
1562                                                bAllowSend = FALSE;
1563                                        if(m_PasswordEdit.GetValue().Trim().IsEmpty())
1564                                                bAllowSend = FALSE;
1565                                }
1566                                m_SendButton.EnableWindow(bAllowSend);
1567                        }
1568                        static CString GetComputerName()
1569                        {
1570                                TCHAR pszComputerName[256] = { 0 };
1571                                DWORD nComputerNameLength = DIM(pszComputerName);
1572                                ::GetComputerName(pszComputerName, &nComputerNameLength);
1573                                return pszComputerName;
1574                        }
1575
1576                // Window Message Handler
1577                        LRESULT OnInitDialog(HWND, LPARAM lParam)
1578                        {
1579                                m_pOwner = (CPropertyFrameDialog*) lParam;
1580                                m_bActivating = TRUE;
1581                                _ATLTRY
1582                                {
1583                                        CWaitCursor WaitCursor;
1584                                        m_TitleStatic = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_TITLE);
1585                                        CreateTitleFont(m_TitleFont, m_TitleStatic);
1586                                        _W(m_FromEdit.SubclassWindow(GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_FROM)));
1587                                        m_ToEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_TO);
1588                                        m_MethodComboBox.Initialize(GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_METHOD));
1589                                        m_MethodComboBox.SetCurSel(0);
1590                                        m_HostEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_HOST);
1591                                        m_UsernameEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_USERNAME);
1592                                        m_PasswordEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_PASSWORD);
1593                                        m_BodyEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_BODY);
1594                                        m_BodyEdit.SetFont(m_pOwner->m_TextFont);
1595                                        m_SendButton = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_SEND);
1596                                        _W(m_CleanupStatic.SubclassWindow(GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_CLEANUP)));
1597                                        DlgResize_Init(FALSE, FALSE);
1598                                        InitializeControlsFromRegistry();
1599                                        InitializeBody();
1600                                        m_sFilterGraphText = m_pOwner->m_Owner.GetText();
1601                                        UpdateControls();
1602                                        m_bActivating = FALSE;
1603                                }
1604                                _ATLCATCH(Exception)
1605                                {
1606                                        for(CWindow Window = GetWindow(GW_CHILD); Window; Window = Window.GetWindow(GW_HWNDNEXT))
1607                                                Window.EnableWindow(FALSE);
1608                                        AtlExceptionMessageBox(m_hWnd, Exception);
1609                                }
1610                                return TRUE;
1611                        }
1612                        LRESULT OnDestroy()
1613                        {
1614                                return 0;
1615                        }
1616                        LRESULT OnShowWindow(BOOL bShowing, INT)
1617                        {
1618                                if(bShowing && !m_ChangeMap.Lookup(IDC_FILTERGRAPHHELPER_EMAIL_BODY))
1619                                        InitializeBody();
1620                                return 0;
1621                        }
1622                        LRESULT OnChanged(UINT, INT_PTR nIdentifier, HWND)
1623                        {
1624                                if(m_bActivating)
1625                                        return 0;
1626                                m_ChangeMap[nIdentifier] = TRUE;
1627                                UpdateControls();
1628                                return 0;
1629                        }
1630                        LRESULT OnChanged(NMHDR* pHeader)
1631                        {
1632                                return OnChanged(pHeader->code, pHeader->idFrom, pHeader->hwndFrom);
1633                        }
1634                        LRESULT OnFromEditPaste()
1635                        {
1636                                _ATLTRY
1637                                {
1638                                        CString sText;
1639                                        if(GetClipboardText(m_hWnd, sText))
1640                                        {
1641                                                const INT nLength = sText.GetLength();
1642                                                if(nLength >= 128 && nLength < 8192)
1643                                                {
1644                                                        sText.Trim();
1645                                                        const BOOL bResult = InitializeControlsFromMessageString(sText);
1646                                                        UpdateControls();
1647                                                        if(bResult)
1648                                                                return 0;
1649                                                }
1650                                        }
1651                                }
1652                                _ATLCATCHALL()
1653                                {
1654                                        MessageBeep(MB_ICONERROR);
1655                                }
1656                                return 0;
1657                        }
1658                        LRESULT OnSend(UINT, INT, HWND)
1659                        {
1660                                CWaitCursor WaitCursor;
1661                                CObjectPtr<CMessage> pMessage;
1662                                pMessage.Construct();
1663                                #pragma region Setup
1664                                pMessage->LoadTypeInfo(IDR_EMAILTOOLS);
1665                                __C(pMessage->put_Sender(CComBSTR(m_FromEdit.GetValue())));
1666                                __C(pMessage->put_ToRecipients(CComBSTR(m_ToEdit.GetValue())));
1667                                // NOTE:
1668                                // 0 Google Mail (SMTP, TLS Connection)
1669                                // 1 SMTP, TLS Connection, Plain Text Authentication (TLS, PLAIN)
1670                                // 2 SMTP, SSL Connection, Plain Text Authentication (SSL, PLAIN)
1671                                // 3 SMTP, Digest Authentication (CRAM-MD5)
1672                                // 4 SMTP, Plain Text Authentication (PLAIN)
1673                                // 5 SMTP, No Authentication
1674                                const INT nMethod = m_MethodComboBox.GetCurSel();
1675                                __C(pMessage->put_SecureSocketsLayer((nMethod == 2) ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE));
1676                                __C(pMessage->put_TransportLayerSecurity((nMethod < 2) ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE));
1677                                if(nMethod != 5)
1678                                {
1679                                        __C(pMessage->put_AuthMethods(CComBSTR(_T("plain"))));
1680                                        __C(pMessage->put_AuthName(CComBSTR(m_UsernameEdit.GetValue())));
1681                                        __C(pMessage->put_AuthPassword(CComBSTR(m_PasswordEdit.GetValue())));
1682                                }
1683                                switch(nMethod)
1684                                {
1685                                case 0:
1686                                        __C(pMessage->put_ServerHost(CComBSTR(_T("smtp.gmail.com"))));
1687                                        break;
1688                                default:
1689                                        CString sHost = m_HostEdit.GetValue();
1690                                        sHost.Trim();
1691                                        const INT nPortPosition = sHost.Find(_T(":"));
1692                                        if(nPortPosition >= 0)
1693                                        {
1694                                                INT nPort;
1695                                                __D(AtlStringToInteger(sHost.Mid(nPortPosition + 1), nPort), E_UNNAMED);
1696                                                __C(pMessage->put_ServerPort(nPort));
1697                                                sHost = sHost.Left(nPortPosition);
1698                                        }
1699                                        __C(pMessage->put_ServerHost(CComBSTR(sHost)));
1700                                        break;
1701                                }
1702                                switch(nMethod)
1703                                {
1704                                case 3:
1705                                        __C(pMessage->put_AuthMethods(CComBSTR(_T("cram-md5"))));
1706                                        break;
1707                                }
1708                                #pragma endregion
1709                                CStringA sMessageString = pMessage->GetAsString();
1710                                CString sText = m_BodyEdit.GetValue();
1711                                sText.TrimRight(_T("\t\n\r "));
1712                                sText += _T("\r\n") _T("\r\n") _T("* * *") _T("\r\n") _T("\r\n");
1713                                sText += m_sFilterGraphText;
1714                                __C(pMessage->put_Body(CComBSTR(sText)));
1715                                CString sSubject = AtlFormatString(_T("DirectShow Filter Graph from %s by %s"), GetComputerName(), AtlLoadString(IDS_PROJNAME));
1716                                __C(pMessage->put_Subject(CComBSTR(sSubject)));
1717                                #pragma region Attachment
1718                                CRoArrayT<CPath> DeletePathArray;
1719                                CRoArrayT<CString> FailurePathArray;
1720                                {
1721                                        CEmailLogDialog& EmailLogDialog = m_pOwner->m_EmailLogDialog;
1722                                        CRoArrayT<CEmailLogDialog::CSelectedFileData> Array;
1723                                        if(EmailLogDialog.GetFiles(Array))
1724                                        {
1725                                                const ULONGLONG nTruncateSize = EmailLogDialog.GetTruncateSize();
1726                                                const BOOL bDelete = EmailLogDialog.GetDelete();
1727                                                for(SIZE_T nIndex = 0; nIndex < Array.GetCount(); nIndex++)
1728                                                {
1729                                                        CEmailLogDialog::CSelectedFileData& FileData = Array[nIndex];
1730                                                        _ATLTRY
1731                                                        {
1732                                                                CLocalObjectPtr<CBzip2Item> pItem;
1733                                                                pItem->LoadFromFile(FileData.m_sPath, nTruncateSize);
1734                                                                CHeapPtr<BYTE> pnData;
1735                                                                SIZE_T nDataSize;
1736                                                                pItem->GetData(pnData, nDataSize);
1737                                                                if(nDataSize)
1738                                                                {
1739                                                                        CObjectPtr<CMessage::CComAttachment> pAttachment = pMessage->GetAttachments()->Add();
1740                                                                        _ATLTRY
1741                                                                        {
1742                                                                                pAttachment->SetType(L"application/bzip2");
1743                                                                                pAttachment->SetDisposition(L"attachment");
1744                                                                                pAttachment->SetName(CStringW(FileData.m_sName + _T(".bz2")));
1745                                                                                CLocalObjectPtr<CUnmanagedMemoryStream> pStream;
1746                                                                                pStream->Initialize(pnData, nDataSize);
1747                                                                                pAttachment->LoadFromStream(pStream);
1748                                                                        }
1749                                                                        _ATLCATCHALL()
1750                                                                        {
1751                                                                                _V(pMessage->GetAttachments()->Remove(pAttachment));
1752                                                                                _ATLRETHROW;
1753                                                                        }
1754                                                                }
1755                                                                if(bDelete)
1756                                                                        DeletePathArray.Add(FileData.m_sPath);
1757                                                        }
1758                                                        _ATLCATCHALL()
1759                                                        {
1760                                                                _Z_EXCEPTION();
1761                                                                FailurePathArray.Add((LPCTSTR) FileData.m_sPath);
1762                                                        }
1763                                                }
1764                                        }
1765                                }
1766                                #pragma endregion
1767                                __C(pMessage->Send());
1768                                for(SIZE_T nIndex = 0; nIndex < DeletePathArray.GetCount(); nIndex++)
1769                                        DeleteFile(DeletePathArray[nIndex]);
1770                                _RegKeyHelper::SetStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, _T("Email Message Template"), CString(sMessageString));
1771                                if(!FailurePathArray.IsEmpty())
1772                                {
1773                                        const CString sMessage = AtlFormatString(_T("It was unable to attach the following files:") _T("\r\n\r\n") _T("%s"), _StringHelper::Join(FailurePathArray, _T("\r\n")));
1774                                        AtlMessageBoxEx(m_hWnd, (LPCTSTR) sMessage, IDS_WARNING, MB_ICONWARNING | MB_OK);
1775                                }
1776                                AtlOptionalMessageBoxEx(m_hWnd, _T("CFilterGraphHelper::CPropertyFrameDialog::CEmailDialog::CredentialsSaved"), _T("The email was sent.") _T("\r\n\r\n") _T("The credentials were written into registry for further reuse. Use Erase Cached Credentials link to delete them from registry."), IDS_INFORMATION, MB_ICONINFORMATION | MB_OK);
1777                                MessageBeep(MB_OK);
1778                                return 0;
1779                        }
1780                        LRESULT OnCleanupStaticAnchorClicked(NMHDR*)
1781                        {
1782                                _RegKeyHelper::DeleteValue(HKEY_CURRENT_USER, REGISTRY_ROOT, _T("Email Message Template"));
1783                                AtlOptionalMessageBoxEx(m_hWnd, _T("CFilterGraphHelper::CPropertyFrameDialog::CEmailDialog::SavedCredentialsDeleted"), _T("Cached email credentials were removed from registry."), IDS_INFORMATION, MB_ICONINFORMATION | MB_OK);
1784                                MessageBeep(MB_OK);
1785                                return 0;
1786                        }
1787                };
1788
1789                ////////////////////////////////////////////////////
1790                // CData
1791
1792                class CData
1793                {
1794                public:
1795
1796                        /////////////////////////////////////////////////////////
1797                        // TYPE
1798
1799                        typedef enum _TYPE
1800                        {
1801                                TYPE_UNKNOWN = 0,
1802                                TYPE_FILTERS,
1803                                TYPE_FILTER,
1804                                TYPE_FILTERPROPERTYPAGE,
1805                                TYPE_SERVICES,
1806                                TYPE_SERVICEPROPERTYPAGE,
1807                                TYPE_MEMORYALLOCATOR,
1808                                TYPE_ACTION,
1809                                TYPE_EMAIL,
1810                                TYPE_EMAIL_LOG,
1811                        } TYPE;
1812
1813                public:
1814                        TYPE m_Type;
1815                        CComPtr<IBaseFilter> m_pBaseFilter;
1816                        CLSID m_BaseFilterClassIdentifier;
1817                        CString m_sBaseFilterClassDescription;
1818                        CString m_sBaseFilterModulePath;
1819                        CLSID m_PropertyPageClassIdentifier;
1820                        CComPtr<IPropertyPage> m_pPropertyPage;
1821                        CObjectPtr<CPropertyPageSite> m_pSite;
1822                        BOOL m_bSiteActivated;
1823
1824                public:
1825                // CData
1826                        CData(TYPE Type = TYPE_UNKNOWN) :
1827                                m_Type(Type),
1828                                m_BaseFilterClassIdentifier(CLSID_NULL),
1829                                m_PropertyPageClassIdentifier(CLSID_NULL)
1830                        {
1831                        }
1832                        CData(IBaseFilter* pBaseFilter) :
1833                                m_Type(TYPE_FILTER),
1834                                m_pBaseFilter(pBaseFilter),
1835                                m_BaseFilterClassIdentifier(CLSID_NULL),
1836                                m_PropertyPageClassIdentifier(CLSID_NULL)
1837                        {
1838                                _ATLTRY
1839                                {
1840                                        CLSID ClassIdentifier = CLSID_NULL;
1841                                        if(SUCCEEDED(pBaseFilter->GetClassID(&ClassIdentifier)) && ClassIdentifier != CLSID_NULL)
1842                                        {
1843                                                m_BaseFilterClassIdentifier = ClassIdentifier;
1844                                                const CString sClassIdentifier(_PersistHelper::StringFromIdentifier(ClassIdentifier));
1845                                                m_sBaseFilterClassDescription = _RegKeyHelper::QueryStringValue(HKEY_CLASSES_ROOT, AtlFormatString(_T("CLSID\\%s"), sClassIdentifier));
1846                                                m_sBaseFilterModulePath = _RegKeyHelper::QueryStringValue(HKEY_CLASSES_ROOT, AtlFormatString(_T("CLSID\\%s\\InprocServer32"), sClassIdentifier));
1847                                        }
1848                                }
1849                                _ATLCATCHALL()
1850                                {
1851                                        _Z_EXCEPTION();
1852                                }
1853                        }
1854                        CData(IBaseFilter* pBaseFilter, const CLSID& PropertyPageClassIdentifier, IPropertyPage* pPropertyPage) :
1855                                m_Type(TYPE_FILTERPROPERTYPAGE),
1856                                m_pBaseFilter(pBaseFilter),
1857                                m_BaseFilterClassIdentifier(CLSID_NULL),
1858                                m_PropertyPageClassIdentifier(PropertyPageClassIdentifier),
1859                                m_pPropertyPage(pPropertyPage),
1860                                m_bSiteActivated(FALSE)
1861                        {
1862                                _A(pPropertyPage);
1863                        }
1864                        CData(IPropertyPage* pPropertyPage) :
1865                                m_Type(TYPE_SERVICEPROPERTYPAGE),
1866                                m_BaseFilterClassIdentifier(CLSID_NULL),
1867                                m_PropertyPageClassIdentifier(CLSID_NULL),
1868                                m_pPropertyPage(pPropertyPage),
1869                                m_bSiteActivated(FALSE)
1870                        {
1871                                _A(pPropertyPage);
1872                        }
1873                        CString GetPropertyPageTitle() const
1874                        {
1875                                if(!m_pPropertyPage)
1876                                        return _T("");
1877                                PROPPAGEINFO PageInformation;
1878                                ZeroMemory(&PageInformation, sizeof PageInformation);
1879                                PageInformation.cb = sizeof PageInformation;
1880                                __C(m_pPropertyPage->GetPageInfo(&PageInformation));
1881                                CString sTitle(PageInformation.pszTitle);
1882                                CoTaskMemFree(PageInformation.pszTitle);
1883                                CoTaskMemFree(PageInformation.pszDocString);
1884                                CoTaskMemFree(PageInformation.pszHelpFile);
1885                                return sTitle;
1886                        }
1887                };
1888
1889                ////////////////////////////////////////////////////
1890                // CObjectPropertyPage
1891
1892                class CObjectPropertyPage
1893                {
1894                public:
1895                        CComPtr<IUnknown> m_pUnknown;
1896                        CComPtr<IPropertyPage> m_pPropertyPage;
1897
1898                public:
1899                // CObjectPropertyPage
1900                        CObjectPropertyPage()
1901                        {
1902                        }
1903                        CObjectPropertyPage(IUnknown* pUnknown, IPropertyPage* pPropertyPage) :
1904                                m_pUnknown(pUnknown),
1905                                m_pPropertyPage(pPropertyPage)
1906                        {
1907                        }
1908                };
1909
1910                typedef CRoArrayT<CObjectPropertyPage> CObjectPropertyPageArray;
1911
1912        private:
1913                CFilterGraphHelper& m_Owner;
1914                BOOL m_bActivating; 
1915                CRoTreeViewT<CData, CRoListControlDataTraitsT> m_TreeView;
1916                CTreeItem m_FiltersItem;
1917                CTreeItem m_MemoryAllocatorItem;
1918                CTreeItem m_ActionItem;
1919                CTreeItem m_EmailItem;
1920                CTreeItem m_EmailLogItem;
1921                CTabCtrl m_Tab;
1922                CRoEdit m_TextEdit;
1923                CRect m_TextPosition;
1924                CFont m_TextFont;
1925                CRoHyperStatic m_RefreshStatic;
1926                CRoHyperStatic m_CopyStatic;
1927                CRoHyperStatic m_SaveAsStatic;
1928                CButton m_OkButton;
1929                CButton m_CancelButton;
1930                CButton m_ApplyButton;
1931                CObjectPtr<CPropertyPageSite> m_pCurrentSite;
1932                CMemoryAllocatorDialog m_MemoryAllocatorDialog;
1933                CActionDialog m_ActionDialog;
1934                CEmailDialog m_EmailDialog;
1935                CEmailLogDialog m_EmailLogDialog;
1936
1937                static VOID CreateTitleFont(CFont& Font, HWND hStaticWindow = NULL)
1938                {
1939                        _A(!Font);
1940                        CLogFont LogFont;
1941                        LogFont.SetHeight(12);
1942                        LogFont.lfWeight = FW_BOLD;
1943                        _tcsncpy_s(LogFont.lfFaceName, _T("Verdana"), _TRUNCATE);
1944                        _W(Font.CreateFontIndirect(&LogFont));
1945                        if(hStaticWindow)
1946                                CStatic(hStaticWindow).SetFont(Font);
1947                }
1948                VOID ShowText(BOOL bVisible, BOOL bStaticVisible = FALSE)
1949                {
1950                        m_TextEdit.ShowWindow(bVisible ? SW_SHOW : SW_HIDE);
1951                        bStaticVisible &= bVisible;
1952                        m_RefreshStatic.ShowWindow(bStaticVisible ? SW_SHOW : SW_HIDE);
1953                        m_CopyStatic.ShowWindow(bStaticVisible ? SW_SHOW : SW_HIDE);
1954                        m_SaveAsStatic.ShowWindow(bStaticVisible ? SW_SHOW : SW_HIDE);
1955                }
1956
1957        public:
1958        // CPropertyFrameDialog
1959                CPropertyFrameDialog(CFilterGraphHelper* pOwner) :
1960                        m_Owner(*pOwner)
1961                {
1962                }
1963                CRect GetTextEditPosition() const
1964                {
1965                        CRect Position;
1966                        _W(m_TextEdit.GetWindowRect(Position));
1967                        _W(ScreenToClient(Position));
1968                        return Position;
1969                }
1970                VOID UpdateTree()
1971                {
1972                        CWindowRedraw TreeViewRedraw(m_TreeView);
1973                        m_TreeView.DeleteAllItems();
1974                        CTreeItem LastItem;
1975                        #pragma region Filter
1976                        CTreeItem FiltersItem = m_TreeView.InsertItem(NULL, NULL, CData(CData::TYPE_FILTERS), _T("Filters"));
1977                        _FilterGraphHelper::CFilterArray FilterArray;
1978                        _FilterGraphHelper::GetGraphFilters(m_Owner.m_pFilterGraph, FilterArray);
1979                        CTreeItem PreviousFilterItem;
1980                        for(SIZE_T nIndex = 0; nIndex < FilterArray.GetCount(); nIndex++)
1981                        {
1982                                const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nIndex];
1983                                CData Data(pBaseFilter);
1984                                CString sText(_FilterGraphHelper::GetFilterName(pBaseFilter));
1985                                if(!Data.m_sBaseFilterClassDescription.IsEmpty() && sText.Find(Data.m_sBaseFilterClassDescription) < 0)
1986                                        sText += AtlFormatString(_T(" (%s)"), Data.m_sBaseFilterClassDescription);
1987                                CTreeItem FilterItem = m_TreeView.InsertItem(FiltersItem, PreviousFilterItem, Data, sText);
1988                                PreviousFilterItem = FilterItem;
1989                                #pragma region Property Page
1990                                const CComQIPtr<ISpecifyPropertyPages> pSpecifyPropertyPages = pBaseFilter;
1991                                if(!pSpecifyPropertyPages)
1992                                        continue;
1993                                _ATLTRY
1994                                {
1995                                        CAUUID Pages;
1996                                        ZeroMemory(&Pages, sizeof Pages);
1997                                        __C(pSpecifyPropertyPages->GetPages(&Pages));
1998                                        CComHeapPtr<CLSID> pClassIdentifiers;
1999                                        pClassIdentifiers.Attach(Pages.pElems);
2000                                        CTreeItem PreviousPageItem;
2001                                        for(UINT nPageIndex = 0; nPageIndex < Pages.cElems; nPageIndex++)
2002                                        {
2003                                                const CLSID& ClassIdentifier = pClassIdentifiers[nPageIndex];
2004                                                if(ClassIdentifier == CLSID_NULL)
2005                                                        continue; // Fake
2006                                                _ATLTRY
2007                                                {
2008                                                        CComPtr<IPropertyPage> pPropertyPage;
2009                                                        const HRESULT nCoCreateInstanceResult = pPropertyPage.CoCreateInstance(ClassIdentifier);
2010                                                        _A(SUCCEEDED(nCoCreateInstanceResult) || nCoCreateInstanceResult == REGDB_E_CLASSNOTREG);
2011                                                        if(nCoCreateInstanceResult == REGDB_E_CLASSNOTREG)
2012                                                                continue; // Missing [Optional] Page
2013                                                        __C(nCoCreateInstanceResult);
2014                                                        CData Data(pBaseFilter, ClassIdentifier, pPropertyPage);
2015                                                        Data.m_pSite.Construct()->Initialize(this, pBaseFilter, pPropertyPage);
2016                                                        CTreeItem PageItem = m_TreeView.InsertItem(FilterItem, PreviousPageItem, Data, Data.GetPropertyPageTitle());
2017                                                        PreviousPageItem = PageItem;
2018                                                }
2019                                                _ATLCATCHALL()
2020                                                {
2021                                                        _Z_EXCEPTION();
2022                                                }
2023                                        }
2024                                        m_TreeView.Expand(FilterItem);
2025                                }
2026                                _ATLCATCHALL()
2027                                {
2028                                        _Z_EXCEPTION();
2029                                }
2030                                #pragma endregion
2031                        }
2032                        m_TreeView.Expand(FiltersItem);
2033                        m_FiltersItem.m_hTreeItem = FiltersItem;
2034                        m_FiltersItem.m_pTreeView = &m_TreeView;
2035                        LastItem = FiltersItem;
2036                        #pragma endregion
2037                        #pragma region Services
2038                        _ATLTRY
2039                        {
2040                                CObjectPropertyPageArray ObjectPropertyPageArray;
2041                                const CComQIPtr<IServiceProvider> pServiceProvider = m_Owner.m_pFilterGraph;
2042                                if(pServiceProvider)
2043                                {
2044                                        #pragma region RunPropertyBagAware
2045                                        CComPtr<IRunPropertyBagAware> pRunPropertyBagAware;
2046                                        if(SUCCEEDED(pServiceProvider->QueryService<IRunPropertyBagAware>(__uuidof(IRunPropertyBagAware), &pRunPropertyBagAware)))
2047                                                _ATLTRY
2048                                                {
2049                                                        _A(pRunPropertyBagAware);
2050                                                        CObjectPtr<CRunPropertyBagPropertyPage> pRunPropertyBagPropertyPage;
2051                                                        pRunPropertyBagPropertyPage.Construct();
2052                                                        ObjectPropertyPageArray.Add(CObjectPropertyPage(pRunPropertyBagAware, pRunPropertyBagPropertyPage));
2053                                                }
2054                                                _ATLCATCHALL()
2055                                                {
2056                                                        _Z_EXCEPTION();
2057                                                }
2058                                        #pragma endregion
2059                                        #pragma region RunEventAware
2060                                        CComPtr<IRunEventAware> pRunEventAware;
2061                                        if(SUCCEEDED(pServiceProvider->QueryService<IRunEventAware>(__uuidof(IRunEventAware), &pRunEventAware)))
2062                                                _ATLTRY
2063                                                {
2064                                                        _A(pRunEventAware);
2065                                                        CObjectPtr<CRunEventPropertyPage> pRunEventPropertyPage;
2066                                                        pRunEventPropertyPage.Construct();
2067                                                        ObjectPropertyPageArray.Add(CObjectPropertyPage(pRunEventAware, pRunEventPropertyPage));
2068                                                }
2069                                                _ATLCATCHALL()
2070                                                {
2071                                                        _Z_EXCEPTION();
2072                                                }
2073                                        #pragma endregion
2074                                }
2075                                if(!ObjectPropertyPageArray.IsEmpty())
2076                                {
2077                                        CTreeItem ServicesItem = m_TreeView.InsertItem(NULL, LastItem, CData(CData::TYPE_SERVICES), _T("Services"));
2078                                        LastItem = ServicesItem;
2079                                        CTreeItem PreviousServiceItem;
2080                                        for(auto&& ObjectPropertyPage: ObjectPropertyPageArray)
2081                                        {
2082                                                CData Data(ObjectPropertyPage.m_pPropertyPage);
2083                                                Data.m_pSite.Construct()->Initialize(this, ObjectPropertyPage.m_pUnknown, ObjectPropertyPage.m_pPropertyPage);
2084                                                CTreeItem ServiceItem = m_TreeView.InsertItem(ServicesItem, PreviousServiceItem, Data, Data.GetPropertyPageTitle());
2085                                                PreviousServiceItem = ServiceItem;
2086                                        }
2087                                        m_TreeView.Expand(ServicesItem);
2088                                }
2089                        }
2090                        _ATLCATCHALL()
2091                        {
2092                                _Z_EXCEPTION();
2093                        }
2094                        #pragma endregion
2095                        #pragma region Other
2096                        CTreeItem MemoryAllocatorItem = m_TreeView.InsertItem(NULL, LastItem, CData(CData::TYPE_MEMORYALLOCATOR), _T("Memory Allocators"));
2097                        m_MemoryAllocatorItem.m_hTreeItem = MemoryAllocatorItem;
2098                        m_MemoryAllocatorItem.m_pTreeView = &m_TreeView;
2099                        CTreeItem ActionItem = m_TreeView.InsertItem(NULL, MemoryAllocatorItem, CData(CData::TYPE_ACTION), _T("Action"));
2100                        m_ActionItem.m_hTreeItem = ActionItem;
2101                        m_ActionItem.m_pTreeView = &m_TreeView;
2102                        CTreeItem EmailItem = m_TreeView.InsertItem(NULL, ActionItem, CData(CData::TYPE_EMAIL), _T("Email"));
2103                        m_EmailItem.m_hTreeItem = EmailItem;
2104                        m_EmailItem.m_pTreeView = &m_TreeView;
2105                        CTreeItem EmailLogItem = m_TreeView.InsertItem(EmailItem, NULL, CData(CData::TYPE_EMAIL_LOG), _T("Log Files"));
2106                        m_EmailLogItem.m_hTreeItem = EmailLogItem;
2107                        m_EmailLogItem.m_pTreeView = &m_TreeView;
2108                        #pragma endregion
2109                        m_TreeView.Expand(EmailItem);
2110                }
2111                VOID HideCurrentSite()
2112                {
2113                        if(!m_pCurrentSite)
2114                                return;
2115                        if(m_pCurrentSite->m_pPropertyPage)
2116                                __C(m_pCurrentSite->m_pPropertyPage->Show(SW_HIDE));
2117                        m_pCurrentSite.Release();
2118                }
2119                VOID HandleStatusChange(CPropertyPageSite* pPropertyPageSite)
2120                {
2121                        _A(pPropertyPageSite);
2122                        m_ApplyButton.EnableWindow(pPropertyPageSite->IsDirty());
2123                }
2124                VOID Apply()
2125                {
2126                        if(!m_pCurrentSite || !m_pCurrentSite->m_pPropertyPage)
2127                                return;
2128                        __C(m_pCurrentSite->m_pPropertyPage->Apply());
2129                        HandleStatusChange(m_pCurrentSite);
2130                }
2131                INT_PTR DoModal(HWND hParentWindow = GetActiveWindow())
2132                {
2133                        return CDialogWithAccelerators::DoModal(hParentWindow);
2134                }
2135
2136        // CDialogResize
2137                VOID DlgResize_UpdateLayout(INT nWidth, INT nHeight)
2138                {
2139                        __super::DlgResize_UpdateLayout(nWidth, nHeight);
2140                        const CRect Position = GetTextEditPosition();
2141                        if(m_pCurrentSite && m_pCurrentSite->m_pPropertyPage)
2142                                _V(m_pCurrentSite->m_pPropertyPage->Move(Position));
2143                        _W(m_MemoryAllocatorDialog.SetWindowPos(NULL, Position, SWP_NOZORDER | SWP_NOACTIVATE));
2144                        _W(m_ActionDialog.SetWindowPos(NULL, Position, SWP_NOZORDER | SWP_NOACTIVATE));
2145                        _W(m_EmailDialog.SetWindowPos(NULL, Position, SWP_NOZORDER | SWP_NOACTIVATE));
2146                        _W(m_EmailLogDialog.SetWindowPos(NULL, Position, SWP_NOZORDER | SWP_NOACTIVATE));
2147                }
2148
2149        // CDialogWithAcceleratorsT
2150                BOOL TranslateAccelerator(MSG* pMessage)
2151                {
2152                        CTreeItem TreeItem = m_TreeView.GetSelectedItem();
2153                        if(TreeItem)
2154                        {
2155                                CData& Data = m_TreeView.GetItemData(TreeItem);
2156                                if(Data.m_Type == CData::TYPE_FILTERPROPERTYPAGE)
2157                                {
2158                                        if(Data.m_pPropertyPage)
2159                                                if(Data.m_pPropertyPage->TranslateAccelerator(pMessage) == S_OK)
2160                                                        return TRUE;
2161                                }
2162                        }
2163                        return __super::TranslateAccelerator(pMessage);
2164                }
2165
2166        // Window Message Handler
2167                LRESULT OnInitDialog(HWND, LPARAM)
2168                {
2169                        m_bActivating = TRUE;
2170                        _ATLTRY
2171                        {
2172                                CWaitCursor WaitCursor;
2173                                CAboutDialog::UpdateCaption(*this);
2174                                #pragma region System Menu
2175                                CMenuHandle Menu = GetSystemMenu(FALSE);
2176                                _W(Menu.AppendMenu(MF_SEPARATOR));
2177                                _W(Menu.AppendMenu(MF_STRING, ID_APP_ABOUT, _T("&About...")));
2178                                #pragma endregion
2179                                #pragma region Icon
2180                                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_COLOR, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)), TRUE);
2181                                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_COLOR, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)), FALSE);
2182                                #pragma endregion
2183                                m_TreeView.Initialize(GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TREE));
2184                                m_TextEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TEXT);
2185                                CRect TextPosition;
2186                                _W(m_TextEdit.GetWindowRect(TextPosition));
2187                                _W(ScreenToClient(TextPosition));
2188                                m_TextPosition = TextPosition;
2189                                CLogFont TextFont;
2190                                CFontHandle(AtlGetDefaultGuiFont()).GetLogFont(TextFont);
2191                                _tcsncpy_s(TextFont.lfFaceName, _T("Courier New"), _TRUNCATE);
2192                                TextFont.SetHeight(8);
2193                                m_TextFont = TextFont.CreateFontIndirect();
2194                                m_TextEdit.SetFont(m_TextFont);
2195                                m_RefreshStatic.SubclassWindow(GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_REFRESH));
2196                                m_CopyStatic.SubclassWindow(GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_COPY));
2197                                m_SaveAsStatic.SubclassWindow(GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_SAVEAS));
2198                                CRoHyperStatic::ArrangeHorizontally(&m_RefreshStatic, &m_CopyStatic, &m_SaveAsStatic, NULL);
2199                                m_OkButton = GetDlgItem(IDOK);
2200                                m_CancelButton = GetDlgItem(IDCANCEL);
2201                                m_ApplyButton = GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_APPLY);
2202                                __E(m_MemoryAllocatorDialog.Create(m_hWnd, (LPARAM) this));
2203                                __E(m_ActionDialog.Create(m_hWnd, (LPARAM) this));
2204                                __E(m_EmailDialog.Create(m_hWnd, (LPARAM) this));
2205                                __E(m_EmailLogDialog.Create(m_hWnd, (LPARAM) this));
2206                                DlgResize_Init(TRUE);
2207                                UpdateTree();
2208                                m_FiltersItem.Select();
2209                                m_FiltersItem.EnsureVisible();
2210                                CRect Position;
2211                                _W(GetWindowRect(Position));
2212                                Position.right += Position.Width() / 2;
2213                                Position.bottom += Position.Width() / 4;
2214                                _W(SetWindowPos(NULL, Position, SWP_NOMOVE | SWP_NOZORDER));
2215                                _W(CenterWindow());
2216                                m_bActivating = FALSE;
2217                        }
2218                        _ATLCATCH(Exception)
2219                        {
2220                                for(CWindow Window = GetWindow(GW_CHILD); Window; Window = Window.GetWindow(GW_HWNDNEXT))
2221                                        Window.EnableWindow(FALSE);
2222                                AtlExceptionMessageBox(m_hWnd, Exception);
2223                        }
2224                        return TRUE;
2225                }
2226                LRESULT OnDestroy()
2227                {
2228                        #pragma region Deactivate and Terminate Sites
2229                        for(POSITION Position = m_TreeView.GetDataList().GetHeadPosition(); Position; m_TreeView.GetDataList().GetNext(Position))
2230                        {
2231                                CData& Data = m_TreeView.GetDataList().GetAt(Position);
2232                                if(!Data.m_pSite)
2233                                        continue;
2234                                if(Data.m_bSiteActivated)
2235                                {
2236                                        const HRESULT nDeactivateResult = Data.m_pPropertyPage->Deactivate();
2237                                        _Z35_DSHRESULT(nDeactivateResult);
2238                                        Data.m_bSiteActivated = FALSE;
2239                                }
2240                                Data.m_pSite->Terminate();
2241                        }
2242                        #pragma endregion
2243                        return 0;
2244                }
2245                LRESULT OnTreeViewGetInfoTip(NMTVGETINFOTIP* pHeader)
2246                {
2247                        _A(pHeader);
2248                        if(!pHeader->hItem) 
2249                                return 0;
2250                        CData& Data = m_TreeView.GetItemData(pHeader->hItem);
2251                        CString sInfoTip;
2252                        if(Data.m_pBaseFilter)
2253                        {
2254                                if(!Data.m_pPropertyPage)
2255                                {
2256                                        sInfoTip.AppendFormat(_T("Name: %ls") _T("\r\n"), _FilterGraphHelper::GetFilterName(Data.m_pBaseFilter));
2257                                        if(Data.m_BaseFilterClassIdentifier != CLSID_NULL)
2258                                                sInfoTip.AppendFormat(_T("Class Identifier: %ls") _T("\r\n"), _PersistHelper::StringFromIdentifier(Data.m_BaseFilterClassIdentifier));
2259                                        if(!Data.m_sBaseFilterClassDescription.IsEmpty())
2260                                                sInfoTip.AppendFormat(_T("Class Description: %s") _T("\r\n"), Data.m_sBaseFilterClassDescription);
2261                                        if(!Data.m_sBaseFilterModulePath.IsEmpty())
2262                                                sInfoTip.AppendFormat(_T("Module Path: %s") _T("\r\n"), Data.m_sBaseFilterModulePath);
2263                                } else
2264                                {
2265                                        // TODO: ...
2266                                }
2267                        }
2268                        sInfoTip.TrimRight(_T("\t\n\r "));
2269                        _tcsncpy_s(pHeader->pszText, pHeader->cchTextMax, sInfoTip, _TRUNCATE);
2270                        #pragma region Clipboard Copy
2271                        if(GetKeyState(VK_CONTROL) < 0 && GetKeyState(VK_SHIFT) < 0)
2272                                _ATLTRY
2273                                {
2274                                        SetClipboardText(m_hWnd, sInfoTip);
2275                                        MessageBeep(MB_OK);
2276                                }
2277                                _ATLCATCHALL()
2278                                {
2279                                        _Z_EXCEPTION();
2280                                        MessageBeep(MB_ICONERROR);
2281                                }
2282                        #pragma endregion
2283                        return 0;
2284                }
2285                LRESULT OnTreeViewSelChanged(NMTREEVIEW* pHeader)
2286                {
2287                        _A(pHeader);
2288                        #pragma region Tree Item
2289                        CTreeItem TreeItem(pHeader->itemNew.hItem);
2290                        if(TreeItem)
2291                        {
2292                                CData& Data = m_TreeView.GetItemData(TreeItem);
2293                                if(Data.m_Type != CData::TYPE_MEMORYALLOCATOR)
2294                                        m_MemoryAllocatorDialog.ShowWindow(SW_HIDE);
2295                                if(Data.m_Type != CData::TYPE_ACTION)
2296                                        m_ActionDialog.ShowWindow(SW_HIDE);
2297                                if(Data.m_Type != CData::TYPE_EMAIL)
2298                                        m_EmailDialog.ShowWindow(SW_HIDE);
2299                                if(Data.m_Type != CData::TYPE_EMAIL_LOG)
2300                                        m_EmailLogDialog.ShowWindow(SW_HIDE);
2301                                #pragma region Filter
2302                                if(Data.m_pBaseFilter)
2303                                {
2304                                        #pragma region Property Page
2305                                        if(Data.m_pPropertyPage)
2306                                        {
2307                                                ShowText(FALSE);
2308                                                if(Data.m_pSite != m_pCurrentSite)
2309                                                        HideCurrentSite();
2310                                                if(!Data.m_bSiteActivated)
2311                                                {
2312                                                        __C(Data.m_pPropertyPage->Activate(m_hWnd, GetTextEditPosition(), TRUE));
2313                                                        Data.m_bSiteActivated = TRUE;
2314                                                } else
2315                                                        __C(Data.m_pPropertyPage->Move(GetTextEditPosition()));
2316                                                __C(Data.m_pPropertyPage->Show(SW_SHOWNORMAL));
2317                                                m_pCurrentSite = Data.m_pSite;
2318                                                HandleStatusChange(m_pCurrentSite);
2319                                        } else
2320                                        #pragma endregion
2321                                        #pragma region Text
2322                                        {
2323                                                CWaitCursor WaitCursor;
2324                                                HideCurrentSite();
2325                                                ShowText(TRUE, FALSE);
2326                                                CString sText;
2327                                                sText += AtlFormatString(_T("## ") _T("Filter %ls") _T("\r\n") _T("\r\n"), _FilterGraphHelper::GetFilterName(Data.m_pBaseFilter));
2328                                                sText += m_Owner.GetFilterText(Data.m_pBaseFilter);
2329                                                sText += _T("\r\n");
2330                                                #pragma region Connection
2331                                                _FilterGraphHelper::CPinArray InputPinArray, OutputPinArray;
2332                                                _FilterGraphHelper::GetFilterPins(Data.m_pBaseFilter, PINDIR_INPUT, InputPinArray);
2333                                                _FilterGraphHelper::GetFilterPins(Data.m_pBaseFilter, PINDIR_OUTPUT, OutputPinArray);
2334                                                if(!InputPinArray.IsEmpty() || !OutputPinArray.IsEmpty())
2335                                                {
2336                                                        sText += AtlFormatString(_T("## ") _T("Connections") _T("\r\n") _T("\r\n"));
2337                                                        if(!InputPinArray.IsEmpty())
2338                                                        {
2339                                                                sText += AtlFormatString(_T("### ") _T("Input") _T("\r\n") _T("\r\n"));
2340                                                                for(SIZE_T nPinIndex = 0; nPinIndex < InputPinArray.GetCount(); nPinIndex++)
2341                                                                {
2342                                                                        const CComPtr<IPin>& pInputPin = InputPinArray[nPinIndex];
2343                                                                        const CComPtr<IPin> pOutputPin = _FilterGraphHelper::GetPeerPin(pInputPin);
2344                                                                        if(!pOutputPin)
2345                                                                                continue;
2346                                                                        sText += AtlFormatString(_T(" * ") _T("%s") _T("\r\n"), m_Owner.GetConnectionText(pOutputPin, pInputPin));
2347                                                                }
2348                                                                sText += _T("\r\n");
2349                                                        }
2350                                                        if(!OutputPinArray.IsEmpty())
2351                                                        {
2352                                                                sText += AtlFormatString(_T("### ") _T("Output") _T("\r\n") _T("\r\n"));
2353                                                                for(SIZE_T nPinIndex = 0; nPinIndex < OutputPinArray.GetCount(); nPinIndex++)
2354                                                                {
2355                                                                        const CComPtr<IPin>& pOutputPin = OutputPinArray[nPinIndex];
2356                                                                        const CComPtr<IPin> pInputPin = _FilterGraphHelper::GetPeerPin(pOutputPin);
2357                                                                        if(!pInputPin)
2358                                                                                continue;
2359                                                                        sText += AtlFormatString(_T(" * ") _T("%s") _T("\r\n"), m_Owner.GetConnectionText(pOutputPin, pInputPin));
2360                                                                }
2361                                                                sText += _T("\r\n");
2362                                                        }
2363                                                }
2364                                                #pragma endregion
2365                                                #pragma region Media Type
2366                                                _FilterGraphHelper::CPinArray PinArray;
2367                                                if(_FilterGraphHelper::GetFilterPins(Data.m_pBaseFilter, PinArray))
2368                                                {
2369                                                        sText += AtlFormatString(_T("## ") _T("Media Types") _T("\r\n") _T("\r\n"));
2370                                                        for(SIZE_T nPinIndex = 0; nPinIndex < PinArray.GetCount(); nPinIndex++)
2371                                                        {
2372                                                                const CComPtr<IPin>& pPin = PinArray[nPinIndex];
2373                                                                CString sPinText = AtlFormatString(_T("%s"), FormatIdentifier(_FilterGraphHelper::GetPinFullName(pPin)));
2374                                                                const CComPtr<IPin> pPeerPin = _FilterGraphHelper::GetPeerPin(pPin);
2375                                                                if(pPeerPin)
2376                                                                        sPinText += AtlFormatString(_T(", %s"), FormatIdentifier(_FilterGraphHelper::GetPinFullName(pPeerPin)));
2377                                                                sText += AtlFormatString(_T("%d. ") _T("%s") _T("\r\n"), 1 + nPinIndex, sPinText);
2378                                                                _ATLTRY
2379                                                                {
2380                                                                        CMediaType pMediaType;
2381                                                                        if(pPeerPin)
2382                                                                                pMediaType = _FilterGraphHelper::GetPinMediaType(pPin);
2383                                                                        else
2384                                                                                pMediaType = _FilterGraphHelper::EnumerateFirstPinMediaType(pPin);
2385                                                                        if(!pMediaType)
2386                                                                                continue;
2387                                                                        sText += m_Owner.GetMediaTypeText(pMediaType);
2388                                                                }
2389                                                                _ATLCATCHALL()
2390                                                                {
2391                                                                        _Z_EXCEPTION();
2392                                                                }
2393                                                        }
2394                                                        sText += _T("\r\n");
2395                                                }
2396                                                #pragma endregion
2397                                                #pragma region Runtime Property Bag
2398                                                _ATLTRY
2399                                                {
2400                                                        const CString sPropertyBagText = CRunPropertyBagHelper::GetPropertyBagText(Data.m_pBaseFilter, CComQIPtr<ISpy>(m_Owner.m_pFilterGraph));
2401                                                        if(!sPropertyBagText.IsEmpty())
2402                                                        {
2403                                                                sText += AtlFormatString(_T("## ") _T("Runtime Properties") _T("\r\n") _T("\r\n"));
2404                                                                sText += sPropertyBagText;
2405                                                                sText += _T("\r\n");
2406                                                        }
2407                                                }
2408                                                _ATLCATCHALL()
2409                                                {
2410                                                        _Z_EXCEPTION();
2411                                                }
2412                                                #pragma endregion
2413                                                m_TextEdit.SetValue(sText);
2414                                                m_ApplyButton.EnableWindow(FALSE);
2415                                        }
2416                                        #pragma endregion
2417                                } else
2418                                #pragma endregion
2419                                #pragma region Service Property Page
2420                                if(Data.m_pPropertyPage)
2421                                {
2422                                        ShowText(FALSE);
2423                                        if(Data.m_pSite != m_pCurrentSite)
2424                                                HideCurrentSite();
2425                                        if(!Data.m_bSiteActivated)
2426                                        {
2427                                                __C(Data.m_pPropertyPage->Activate(m_hWnd, GetTextEditPosition(), TRUE));
2428                                                Data.m_bSiteActivated = TRUE;
2429                                        } else
2430                                                __C(Data.m_pPropertyPage->Move(GetTextEditPosition()));
2431                                        __C(Data.m_pPropertyPage->Show(SW_SHOWNORMAL));
2432                                        m_pCurrentSite = Data.m_pSite;
2433                                        HandleStatusChange(m_pCurrentSite);
2434                                } else
2435                                #pragma endregion
2436                                #pragma region Other
2437                                {
2438                                        CWaitCursor WaitCursor;
2439                                        HideCurrentSite();
2440                                        switch(Data.m_Type)
2441                                        {
2442                                        #pragma region TYPE_MEMORYALLOCATOR
2443                                        case CData::TYPE_MEMORYALLOCATOR:
2444                                                ShowText(FALSE);
2445                                                _W(m_MemoryAllocatorDialog.SetWindowPos(NULL, GetTextEditPosition(), SWP_NOZORDER | SWP_SHOWWINDOW));
2446                                                break;
2447                                        #pragma endregion
2448                                        #pragma region TYPE_ACTION
2449                                        case CData::TYPE_ACTION:
2450                                                ShowText(FALSE);
2451                                                _W(m_ActionDialog.SetWindowPos(NULL, GetTextEditPosition(), SWP_NOZORDER | SWP_SHOWWINDOW));
2452                                                break;
2453                                        #pragma endregion
2454                                        #pragma region TYPE_EMAIL
2455                                        case CData::TYPE_EMAIL:
2456                                                ShowText(FALSE);
2457                                                _W(m_EmailDialog.SetWindowPos(NULL, GetTextEditPosition(), SWP_NOZORDER | SWP_SHOWWINDOW));
2458                                                break;
2459                                        #pragma endregion
2460                                        #pragma region TYPE_EMAIL_LOG
2461                                        case CData::TYPE_EMAIL_LOG:
2462                                                ShowText(FALSE);
2463                                                _W(m_EmailLogDialog.SetWindowPos(NULL, GetTextEditPosition(), SWP_NOZORDER | SWP_SHOWWINDOW));
2464                                                break;
2465                                        #pragma endregion
2466                                        default:
2467                                                UpdateText();
2468                                                ShowText(TRUE, TRUE);
2469                                                m_MemoryAllocatorDialog.ShowWindow(SW_HIDE);
2470                                                m_ActionDialog.ShowWindow(SW_HIDE);
2471                                                m_EmailDialog.ShowWindow(SW_HIDE);
2472                                                m_EmailLogDialog.ShowWindow(SW_HIDE);
2473                                        }
2474                                        m_ApplyButton.EnableWindow(FALSE);
2475                                }
2476                                #pragma endregion
2477                        } else
2478                        #pragma endregion
2479                        #pragma region No Tree Item
2480                        {
2481                                HideCurrentSite();
2482                                ShowText(FALSE);
2483                                m_MemoryAllocatorDialog.ShowWindow(SW_HIDE);
2484                                m_ActionDialog.ShowWindow(SW_HIDE);
2485                                m_EmailDialog.ShowWindow(SW_HIDE);
2486                                m_EmailLogDialog.ShowWindow(SW_HIDE);
2487                                m_ApplyButton.EnableWindow(FALSE);
2488                        }
2489                        #pragma endregion
2490                        return 0;
2491                }
2492                LRESULT OnTreeViewItemExplanding(NMTREEVIEW* pHeader)
2493                {
2494                        if(pHeader->action == TVE_COLLAPSE)
2495                                return TRUE; // Prevent Collapsing
2496                        return 0;
2497                }
2498                LRESULT OnTreeViewDblClk(NMHDR*)
2499                {
2500                        CTreeItem TreeItem = m_TreeView.GetSelectedItem();
2501                        if(!TreeItem)
2502                                return 0;
2503                        CData& Data = m_TreeView.GetItemData(TreeItem);
2504                        if(!Data.m_pBaseFilter)
2505                                return 0;
2506                        COlePropertyFrameDialog Dialog(Data.m_pBaseFilter);
2507                        if(!Dialog.SetObjectPages())
2508                                return 0;
2509                        Dialog.DoModal(m_hWnd);
2510                        return 0;
2511                }
2512                VOID UpdateText()
2513                {
2514                        m_TextEdit.SetValue(m_Owner.GetText());
2515                        const INT nTextLength = m_TextEdit.GetWindowTextLength();
2516                        //m_RefreshStatic.EnableWindow(TRUE);
2517                        m_CopyStatic.EnableWindow(nTextLength > 0);
2518                        m_SaveAsStatic.EnableWindow(nTextLength > 0);
2519                }
2520                LRESULT OnRefreshAnchorClicked(NMHDR*)
2521                {
2522                        UpdateText();
2523                        MessageBeep(MB_OK);
2524                        return 0;
2525                }
2526                LRESULT OnCopyAnchorClicked(NMHDR*)
2527                {
2528                        SetClipboardText(m_hWnd, m_TextEdit.GetValue());
2529                        MessageBeep(MB_OK);
2530                        return 0;
2531                }
2532                LRESULT OnSaveAsAnchorClicked(NMHDR*)
2533                {
2534                        static const COMDLG_FILTERSPEC g_pFilter[] = 
2535                        {
2536                                { _T("Markdown Files"), _T("*.md") },
2537                                { _T("Text Files"), _T("*.txt") },
2538                                { _T("BZip2 Compressed Markdown Files"), _T("*.md.bz2") },
2539                                { _T("All Files"), _T("*.*") },
2540                        };
2541                        CPath sPath = _CommonDialogHelper::QuerySavePath(m_hWnd, g_pFilter, _T("md"));
2542                        if(!_tcslen(sPath))
2543                                return 0;
2544                        CAtlFile File;
2545                        __C(File.Create(sPath, GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS));
2546                        _ATLTRY
2547                        {
2548                                CStringA sText = Utf8StringFromString(CStringW(m_TextEdit.GetValue()));
2549                                static const BYTE g_pnByteOrderMark[] = { 0xEF, 0xBB, 0xBF, 0x00 };
2550                                sText.Insert(0, (LPCSTR) g_pnByteOrderMark);
2551                                if(_tcsicmp(GetPathExtension(sPath), _T(".bz2")) == 0)
2552                                {
2553                                        CLocalObjectPtr<CBzip2Item> pItem;
2554                                        pItem->SetRawData((const BYTE*) (LPCSTR) sText, sText.GetLength());
2555                                        CHeapPtr<BYTE> pnData;
2556                                        SIZE_T nDataSize = 0;
2557                                        pItem->GetData(pnData, nDataSize);
2558                                        __C(File.Write(pnData, (DWORD) nDataSize));
2559                                } else
2560                                        __C(File.Write(sText, (DWORD) sText.GetLength()));
2561                        }
2562                        _ATLCATCHALL()
2563                        {
2564                                File.Close();
2565                                _W(DeleteFile(sPath));
2566                                _ATLRETHROW;
2567                        }
2568                        MessageBeep(MB_OK);     
2569                        return 0;
2570                }
2571                LRESULT OnSysCommand(UINT nCommand, CPoint)
2572                {
2573                        switch(nCommand)
2574                        {
2575                        case ID_APP_ABOUT:
2576                                {
2577                                        CAboutDialog Dialog;
2578                                        Dialog.DoModal(m_hWnd);
2579                                }
2580                                break;
2581                        default:
2582                                SetMsgHandled(FALSE);
2583                        }
2584                        return 0;
2585                }
2586                LRESULT OnOk(UINT, INT nIdentifier, HWND)
2587                {
2588                        _ATLTRY
2589                        {
2590                                #pragma region Apply All
2591                                for(POSITION Position = m_TreeView.GetDataList().GetHeadPosition(); Position; m_TreeView.GetDataList().GetNext(Position))
2592                                {
2593                                        CData& Data = m_TreeView.GetDataList().GetAt(Position);
2594                                        if(!Data.m_pSite)
2595                                                continue;
2596                                        _A(Data.m_pPropertyPage);
2597                                        if(Data.m_bSiteActivated && Data.m_pSite->IsDirty())
2598                                                __C(Data.m_pPropertyPage->Apply());
2599                                }
2600                                #pragma endregion
2601                        }
2602                        _ATLCATCH(Exception)
2603                        {
2604                                _Z_ATLEXCEPTION(Exception);
2605                                AtlMessageBoxEx(m_hWnd, (LPCTSTR) Ds::FormatResult(Exception), IDS_ERROR, MB_ICONERROR | MB_OK);
2606                                return 0;
2607                        }
2608                        EndDialog(nIdentifier);
2609                        return 0;
2610                }
2611                LRESULT OnCancel(UINT, INT nIdentifier, HWND)
2612                {
2613                        EndDialog(nIdentifier);
2614                        return 0;
2615                }
2616                LRESULT OnApply(UINT, INT, HWND)
2617                {
2618                        _ATLTRY
2619                        {
2620                                Apply();
2621                        }
2622                        _ATLCATCH(Exception)
2623                        {
2624                                _Z_ATLEXCEPTION(Exception);
2625                                AtlMessageBoxEx(m_hWnd, (LPCTSTR) Ds::FormatResult(Exception), IDS_ERROR, MB_ICONERROR | MB_OK);
2626                        }
2627                        return 0;
2628                }
2629                LRESULT OnTreeWalkUp(UINT, INT, HWND)
2630                {
2631                        CTreeItem TreeItem = m_TreeView.GetSelectedItem();
2632                        CTreeItem ParentTreeItem = TreeItem.GetParent();
2633                        if(!ParentTreeItem)
2634                                return 0;
2635                        m_TreeView.SetFocus();
2636                        m_TreeView.Select(ParentTreeItem, TVGN_CARET);
2637                        return 0;
2638                }
2639                LRESULT OnActionCommand(UINT, INT nIdentifier, HWND)
2640                {
2641                        return m_ActionDialog.SendMessage(WM_COMMAND, nIdentifier);
2642                }
2643        };
2644
2645private:
2646        mutable CRoCriticalSection m_DataCriticalSection;
2647        CProcessData m_ProcessData;
2648        CComPtr<IFilterGraph> m_pFilterGraph;
2649        COptions m_Options;
2650
2651public:
2652// CFilterGraphHelper
2653        static HRESULT WINAPI UpdateRegistry(BOOL bRegister)
2654        {
2655                _Z2(atlTraceRegistrar, 2, _T("bRegister %d\n"), bRegister);
2656                _ATLTRY
2657                {
2658                        UpdateRegistryFromResource<CFilterGraphHelper>(bRegister);
2659                }
2660                _ATLCATCH(Exception)
2661                {
2662                        _C(Exception);
2663                }
2664                return S_OK;
2665        }
2666        CFilterGraphHelper()
2667        {
2668                _Z4_THIS();
2669        }
2670        ~CFilterGraphHelper()
2671        {
2672                _Z4_THIS();
2673        }
2674        static CString FormatIdentifier(LPCSTR pszValue)
2675        {
2676                CString sText;
2677                if(pszValue && *pszValue)
2678                {
2679                        sText = _T("``");
2680                        sText.Insert(1, CString(pszValue));
2681                }
2682                return sText;
2683        }
2684        static CString FormatIdentifier(LPCWSTR pszValue)
2685        {
2686                CString sText;
2687                if(pszValue && *pszValue)
2688                {
2689                        sText = _T("``");
2690                        sText.Insert(1, CString(pszValue));
2691                }
2692                return sText;
2693        }
2694        static CString FormatIdentifier(LONG nValue)
2695        {
2696                CString sText;
2697                sText = _T("``");
2698                sText.Insert(1, _StringHelper::FormatNumber(nValue));
2699                return sText;
2700        }
2701        static CString FormatIdentifier(ULONG nValue)
2702        {
2703                return FormatIdentifier((LONG) nValue);
2704        }
2705        static CString FormatIdentifier(BOOL nValue)
2706        {
2707                return FormatIdentifier((LONG) nValue);
2708        }
2709        static CString FormatIdentifier(LONGLONG nValue)
2710        {
2711                CString sText;
2712                sText = _T("``");
2713                sText.Insert(1, _StringHelper::FormatNumber(nValue));
2714                return sText;
2715        }
2716        static CString FormatIdentifier(LONG nValue, LPCTSTR pszFormat)
2717        {
2718                CString sText;
2719                sText = _T("``");
2720                sText.Insert(1, AtlFormatString(pszFormat, nValue));
2721                return sText;
2722        }
2723        static CString FormatIdentifier(const VOID* pvValue, LPCTSTR pszFormat = _T("0x%p"))
2724        {
2725                CString sText;
2726                sText = _T("``");
2727                sText.Insert(1, AtlFormatString(pszFormat, pvValue));
2728                return sText;
2729        }
2730        #define I FormatIdentifier
2731        static CString FormatPhysicalConnectorType(PhysicalConnectorType Value)
2732        {
2733                struct 
2734                {
2735                        PhysicalConnectorType Value;
2736                        LPCSTR pszName;
2737                } g_pMap[] = 
2738                {
2739                        #define A(x) { x, #x },
2740                        A(PhysConn_Video_Tuner)
2741                        A(PhysConn_Video_Composite)
2742                        A(PhysConn_Video_SVideo)
2743                        A(PhysConn_Video_RGB)
2744                        A(PhysConn_Video_YRYBY)
2745                        A(PhysConn_Video_SerialDigital)
2746                        A(PhysConn_Video_ParallelDigital)
2747                        A(PhysConn_Video_SCSI)
2748                        A(PhysConn_Video_AUX)
2749                        A(PhysConn_Video_1394)
2750                        A(PhysConn_Video_USB)
2751                        A(PhysConn_Video_VideoDecoder)
2752                        A(PhysConn_Video_VideoEncoder)
2753                        A(PhysConn_Video_SCART)
2754                        A(PhysConn_Video_Black)
2755                        A(PhysConn_Audio_Tuner)
2756                        A(PhysConn_Audio_Line)
2757                        A(PhysConn_Audio_Mic)
2758                        A(PhysConn_Audio_AESDigital)
2759                        A(PhysConn_Audio_SPDIFDigital)
2760                        A(PhysConn_Audio_SCSI)
2761                        A(PhysConn_Audio_AUX)
2762                        A(PhysConn_Audio_1394)
2763                        A(PhysConn_Audio_USB)
2764                        A(PhysConn_Audio_AudioDecoder)
2765                        #undef A
2766                };
2767                for(SIZE_T nIndex = 0; nIndex < DIM(g_pMap); nIndex++)
2768                        if(g_pMap[nIndex].Value == Value)
2769                                return CString(g_pMap[nIndex].pszName);
2770                return AtlFormatString(_T("0x%04X"), Value);
2771        }
2772        static CString FormatPins(_FilterGraphHelper::CPinArray& PinArray)
2773        {
2774                CRoArrayT<CString> Array;
2775                for(SIZE_T nIndex  = 0; nIndex < PinArray.GetCount(); nIndex++)
2776                {
2777                        const CComPtr<IPin>& pPin = PinArray[nIndex];
2778                        CString sText = I(_FilterGraphHelper::GetPinName(pPin));
2779                        const CComPtr<IPin> pPeerPin = _FilterGraphHelper::GetPeerPin(pPin);
2780                        if(pPeerPin)
2781                                sText += AtlFormatString(_T(" (%s)"), I(_FilterGraphHelper::GetPinFullName(pPeerPin)));
2782                        Array.Add(sText);
2783                }
2784                return _StringHelper::Join(Array, _T(", "));
2785        }
2786        static CString GetFilterText(IBaseFilter* pBaseFilter, const CProcessData* pProcessData, IReferenceClock* pFilterGraphReferenceClock = NULL)
2787        {
2788                CString sText;
2789                #pragma region COM
2790                CString sPath;
2791                const CStringW sClassIdentifierString = _FilterGraphHelper::GetFilterClassIdentifierString(pBaseFilter);
2792                if(!sClassIdentifierString.IsEmpty())
2793                {
2794                        CLSID ClassIdentifier = CLSID_NULL;
2795                        const BOOL bClassIdentifierAvailable = _PersistHelper::ClassIdentifierFromString(sClassIdentifierString, ClassIdentifier);
2796                        if(bClassIdentifierAvailable && ClassIdentifier != CLSID_NULL)
2797                        {
2798                                sText += AtlFormatString(_T(" * ") _T("Class: %s %s") _T("\r\n"), I(sClassIdentifierString), I(_FilterGraphHelper::GetFilterClassDescription(pBaseFilter)));
2799                                _ATLTRY
2800                                {
2801                                        sPath = _RegKeyHelper::QueryStringValue(HKEY_CLASSES_ROOT, AtlFormatString(_T("CLSID\\%ls\\InprocServer32"), sClassIdentifierString));
2802                                        if(!sPath.IsEmpty())
2803                                        {
2804                                                sText += AtlFormatString(_T(" * ") _T("Inproc Server: %s") _T("\r\n"), I(sPath));
2805                                                const ULONGLONG nProductVersion = _VersionInfoHelper::GetProductVersion(sPath);
2806                                                if(nProductVersion && (nProductVersion + 1))
2807                                                        sText += AtlFormatString(_T(" * ") _T("Product Version: %s") _T("\r\n"), I(_VersionInfoHelper::GetVersionString(nProductVersion)));
2808                                                const ULONGLONG nFileVersion = _VersionInfoHelper::GetFileVersion(sPath);
2809                                                if(nFileVersion && (nFileVersion + 1))
2810                                                        sText += AtlFormatString(_T(" * ") _T("File Version: %s") _T("\r\n"), I(_VersionInfoHelper::GetVersionString(nFileVersion)));
2811                                        }
2812                                }
2813                                _ATLCATCHALL()
2814                                {
2815                                        _Z_EXCEPTION();
2816                                }
2817                        }
2818                }
2819                if(_tcslen(sPath) == 0 && pProcessData && pProcessData->m_nIdentifier == GetCurrentProcessId())
2820                        _ATLTRY
2821                        {
2822                                const VOID* pvVirtualTable = *((const VOID**) pBaseFilter);
2823                                MEMORY_BASIC_INFORMATION Information;
2824                                if(VirtualQueryEx(GetCurrentProcess(), pvVirtualTable, &Information, sizeof Information))
2825                                {
2826                                        TCHAR pszPath[MAX_PATH] = { 0 };
2827                                        if(GetModuleFileName((HMODULE) Information.AllocationBase, pszPath, DIM(pszPath)))
2828                                        {
2829                                                sPath = pszPath;
2830                                                sText += AtlFormatString(_T(" * ") _T("Virtual Table Location: %s") _T("\r\n"), I(sPath));
2831                                                const ULONGLONG nProductVersion = _VersionInfoHelper::GetProductVersion(sPath);
2832                                                if(nProductVersion && (nProductVersion + 1))
2833                                                        sText += AtlFormatString(_T(" * ") _T("Product Version: %s") _T("\r\n"), I(_VersionInfoHelper::GetVersionString(nProductVersion)));
2834                                                const ULONGLONG nFileVersion = _VersionInfoHelper::GetFileVersion(sPath);
2835                                                if(nFileVersion && (nFileVersion + 1))
2836                                                        sText += AtlFormatString(_T(" * ") _T("File Version: %s") _T("\r\n"), I(_VersionInfoHelper::GetVersionString(nFileVersion)));
2837                                        }
2838                                }
2839                        }
2840                        _ATLCATCHALL()
2841                        {
2842                                _Z_EXCEPTION();
2843                        }
2844                #pragma endregion
2845                #pragma region Pin
2846                _FilterGraphHelper::CPinArray InputPinArray;
2847                if(_FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_INPUT, InputPinArray))
2848                        sText += AtlFormatString(_T(" * ") _T("Input Pins: %s") _T("\r\n"), FormatPins(InputPinArray));
2849                _FilterGraphHelper::CPinArray OutputPinArray;
2850                if(_FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_OUTPUT, OutputPinArray))
2851                        sText += AtlFormatString(_T(" * ") _T("Output Pins: %s") _T("\r\n"), FormatPins(OutputPinArray));
2852                #pragma endregion
2853                #pragma region IReferenceClock
2854                const CComQIPtr<IReferenceClock> pReferenceClock = pBaseFilter;
2855                if(pReferenceClock)
2856                {
2857                        CRoArrayT<CString> Array;
2858                        Array.Add(I(_T("Available")));
2859                        if(pReferenceClock == pFilterGraphReferenceClock)
2860                                Array.Add(I(_T("Selected")));
2861                        sText += AtlFormatString(_T(" * ") _T("Reference Clock: %s") _T("\r\n"), _StringHelper::Join(Array, _T(", ")));
2862                }
2863                #pragma endregion
2864                #pragma region IFileSourceFilter
2865                const CComQIPtr<IFileSourceFilter> pFileSourceFilter = pBaseFilter;
2866                if(pFileSourceFilter)
2867                        _ATLTRY
2868                        {
2869                                CComHeapPtr<OLECHAR> pszFileName;
2870                                CMediaType pMediaType;
2871                                pMediaType.Allocate(MEDIATYPE_NULL, MEDIASUBTYPE_NULL);
2872                                const HRESULT nGetCurFileResult = pFileSourceFilter->GetCurFile(&pszFileName, pMediaType);
2873                                _Z45_DSHRESULT(nGetCurFileResult);
2874                                if(SUCCEEDED(nGetCurFileResult))
2875                                        sText += AtlFormatString(_T(" * ") _T("File Source: %s") _T("\r\n"), I(pszFileName));
2876                        }
2877                        _ATLCATCHALL()
2878                        {
2879                                _Z_EXCEPTION();
2880                        }
2881                #pragma endregion
2882                #pragma region IFileSinkFilter
2883                const CComQIPtr<IFileSinkFilter> pFileSinkFilter = pBaseFilter;
2884                if(pFileSinkFilter)
2885                        _ATLTRY
2886                        {
2887                                CComHeapPtr<OLECHAR> pszFileName;
2888                                CMediaType pMediaType;
2889                                pMediaType.Allocate(MEDIATYPE_NULL, MEDIASUBTYPE_NULL);
2890                                const HRESULT nGetCurFileResult = pFileSinkFilter->GetCurFile(&pszFileName, pMediaType);
2891                                _Z45_DSHRESULT(nGetCurFileResult);
2892                                if(SUCCEEDED(nGetCurFileResult))
2893                                        sText += AtlFormatString(_T(" * ") _T("File Sink: %s") _T("\r\n"), I(pszFileName));
2894                        }
2895                        _ATLCATCHALL()
2896                        {
2897                                _Z_EXCEPTION();
2898                        }
2899                #pragma endregion
2900                #pragma region IMediaSeeking
2901                const CComQIPtr<IMediaSeeking> pMediaSeeking = pBaseFilter;
2902                if(pMediaSeeking)
2903                        _ATLTRY
2904                        {
2905                                sText += AtlFormatString(_T(" * ") _T("Media Seeking/Position") _T("\r\n"));
2906                                DWORD nCapabilities = 0;
2907                                if(SUCCEEDED(pMediaSeeking->GetCapabilities(&nCapabilities)))
2908                                        sText += AtlFormatString(_T("  * ") _T("Capabilities: %s") _T("\r\n"), I(AtlFormatString(_T("0x%X"), nCapabilities)));
2909                                LONGLONG nDuration = 0, nPosition = 0, nStopPosition = 0;
2910                                if(SUCCEEDED(pMediaSeeking->GetDuration(&nDuration)))
2911                                        sText += AtlFormatString(_T("  * ") _T("Duration: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime((DOUBLE) nDuration / 1E7)), I(_StringHelper::FormatNumber((DOUBLE) nDuration / 1E7, 3)));
2912                                if(SUCCEEDED(pMediaSeeking->GetCurrentPosition(&nPosition)))
2913                                        sText += AtlFormatString(_T("  * ") _T("Position: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime((DOUBLE) nPosition / 1E7)), I(_StringHelper::FormatNumber((DOUBLE) nPosition / 1E7, 3)));
2914                                if(SUCCEEDED(pMediaSeeking->GetStopPosition(&nStopPosition)))
2915                                        sText += AtlFormatString(_T("  * ") _T("Stop Position: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime((DOUBLE) nStopPosition / 1E7)), I(_StringHelper::FormatNumber((DOUBLE) nStopPosition / 1E7, 3)));
2916                                DOUBLE fRate = 1.0;
2917                                if(SUCCEEDED(pMediaSeeking->GetRate(&fRate)))
2918                                        sText += AtlFormatString(_T("  * ") _T("Rate: %s") _T("\r\n"), I(_StringHelper::FormatNumber(fRate, 3)));
2919                                LONGLONG nPreroll = 0;
2920                                if(SUCCEEDED(pMediaSeeking->GetPreroll(&nPreroll)) && nPreroll)
2921                                        sText += AtlFormatString(_T("  * ") _T("Preroll: %s seconds") _T("\r\n"), I(_StringHelper::FormatNumber((DOUBLE) nPreroll / 1E7, 3)));
2922                        }
2923                        _ATLCATCHALL()
2924                        {
2925                                _Z_EXCEPTION();
2926                        }
2927                #pragma endregion
2928                #pragma region IAMCrossbar
2929                const CComQIPtr<IAMCrossbar> pAmCrossbar = pBaseFilter;
2930                if(pAmCrossbar)
2931                        _ATLTRY
2932                        {
2933                                sText += AtlFormatString(_T(" * ") _T("Crossbar:") _T("\r\n"));
2934                                LONG nOutputPinCount = 0, nInputPinCount = 0;
2935                                __C(pAmCrossbar->get_PinCounts(&nOutputPinCount, &nInputPinCount));
2936                                sText += AtlFormatString(_T("  * ") _T("Pins: %s Input, %s Output") _T("\r\n"), I(nInputPinCount), I(nOutputPinCount));
2937                                #pragma region Input
2938                                for(LONG nInputPinIndex = 0; nInputPinIndex < nInputPinCount; nInputPinIndex++)
2939                                        _ATLTRY
2940                                        {
2941                                                CRoArrayT<CString> Array;
2942                                                LONG nRelatedPinIndex = -1;
2943                                                LONG nPhysicalType = 0; // PhysicalConnectorType
2944                                                __C(pAmCrossbar->get_CrossbarPinInfo(TRUE, nInputPinIndex, &nRelatedPinIndex, &nPhysicalType));
2945                                                if(nRelatedPinIndex >= 0)
2946                                                        Array.Add(AtlFormatString(_T("Related %s"), I(nRelatedPinIndex)));
2947                                                Array.Add(AtlFormatString(_T("Physical Type %s"), I(FormatPhysicalConnectorType((PhysicalConnectorType) nPhysicalType))));
2948                                                sText += AtlFormatString(_T("  * ") _T("Input Pin %s: %s") _T("\r\n"), I(nInputPinIndex), _StringHelper::Join(Array, _T("; ")));
2949                                        }
2950                                        _ATLCATCHALL()
2951                                        {
2952                                                _Z_EXCEPTION();
2953                                        }
2954                                #pragma endregion
2955                                #pragma region Output
2956                                for(LONG nOutputPinIndex = 0; nOutputPinIndex < nOutputPinCount; nOutputPinIndex++)
2957                                        _ATLTRY
2958                                        {
2959                                                CRoArrayT<CString> Array;
2960                                                LONG nRelatedPinIndex = -1;
2961                                                LONG nPhysicalType = 0; // PhysicalConnectorType
2962                                                __C(pAmCrossbar->get_CrossbarPinInfo(FALSE, nOutputPinIndex, &nRelatedPinIndex, &nPhysicalType));
2963                                                if(nRelatedPinIndex >= 0)
2964                                                        Array.Add(AtlFormatString(_T("Related %s"), I(nRelatedPinIndex)));
2965                                                if(nPhysicalType > 0)
2966                                                        Array.Add(AtlFormatString(_T("Physical Type %s"), I(FormatPhysicalConnectorType((PhysicalConnectorType) nPhysicalType))));
2967                                                LONG nRoutedInputPinIndex = -1;
2968                                                const HRESULT nGetIsRoutedToResult = pAmCrossbar->get_IsRoutedTo(nOutputPinIndex, &nRoutedInputPinIndex);
2969                                                _A(nGetIsRoutedToResult == S_OK || nRoutedInputPinIndex == -1);
2970                                                if(nRoutedInputPinIndex >= 0)
2971                                                        Array.Add(AtlFormatString(_T("Routed to Input Pin %s"), I(nRoutedInputPinIndex)));
2972                                                CRoArrayT<CString> PinArray;
2973                                                for(LONG nInputPinIndex = 0; nInputPinIndex < nInputPinCount; nInputPinIndex++)
2974                                                {
2975                                                        const HRESULT nCanRouteResult = pAmCrossbar->CanRoute(nOutputPinIndex, nInputPinIndex);
2976                                                        if(nCanRouteResult == S_OK)
2977                                                                PinArray.Add(I(nInputPinIndex));
2978                                                }
2979                                                if(!PinArray.IsEmpty())
2980                                                        Array.Add(AtlFormatString(_T("Routeable to Input Pins %s"), _StringHelper::Join(PinArray, _T(", "))));
2981                                                sText += AtlFormatString(_T("  * ") _T("Output Pin %s: %s") _T("\r\n"), I(nOutputPinIndex), _StringHelper::Join(Array, _T("; ")));
2982                                        }
2983                                        _ATLCATCHALL()
2984                                        {
2985                                                _Z_EXCEPTION();
2986                                        }
2987                                #pragma endregion
2988                        }
2989                        _ATLCATCHALL()
2990                        {
2991                                _Z_EXCEPTION();
2992                        }
2993                #pragma endregion
2994                return sText;
2995        }
2996        static CString GetConnectionText(IPin* pOutputPin, IPin* pInputPin)
2997        {
2998                _A(pOutputPin && pInputPin);
2999                CString sText = AtlFormatString(_T("%s - %s"), I(_FilterGraphHelper::GetPinFullName(pOutputPin)), I(_FilterGraphHelper::GetPinFullName(pInputPin)));
3000                _ATLTRY
3001                {
3002                        const CMediaType pMediaType = _FilterGraphHelper::GetPinMediaType(pOutputPin);
3003                        if(pMediaType)
3004                        {
3005                                CStringW sMajorType = _FilterGraphHelper::FormatMajorType(pMediaType->majortype);
3006                                CStringW sSubtype;
3007                                if(pMediaType->subtype != MEDIASUBTYPE_NULL)
3008                                        sSubtype = _FilterGraphHelper::FormatSubtype(pMediaType->majortype, pMediaType->subtype);
3009                                CRoArrayT<CString> Array;
3010                                Array.Add(I(sMajorType));
3011                                if(!sSubtype.IsEmpty())
3012                                        Array.Add(I(sSubtype));
3013                                #pragma region MEDIATYPE_Video
3014                                if(pMediaType->majortype == MEDIATYPE_Video)
3015                                {
3016                                        const CVideoInfoHeader2 VideoInfoHeader2 = pMediaType.GetCompatibleVideoInfoHeader2();
3017                                        const CSize Extent = VideoInfoHeader2.GetExtent();
3018                                        if(Extent.cx || Extent.cy)
3019                                                Array.Add(AtlFormatString(_T("%s x %s"), I(Extent.cx), I(Extent.cy)));
3020                                        if(VideoInfoHeader2.AvgTimePerFrame > 0)
3021                                                Array.Add(AtlFormatString(_T("%s frames/sec"), I(_StringHelper::FormatNumber(1E7 / VideoInfoHeader2.AvgTimePerFrame, 3))));
3022                                } else
3023                                #pragma endregion
3024                                #pragma region MEDIATYPE_Audio
3025                                if(pMediaType->majortype == MEDIATYPE_Audio)
3026                                {
3027                                        const CWaveFormatEx* pWaveFormatEx = pMediaType.GetWaveFormatEx();
3028                                        if(pWaveFormatEx)
3029                                        {
3030                                                if(pWaveFormatEx->nSamplesPerSec)
3031                                                        Array.Add(AtlFormatString(_T("%s Hz"), I(pWaveFormatEx->nSamplesPerSec)));
3032                                                if(pWaveFormatEx->nChannels)
3033                                                        Array.Add(AtlFormatString(_T("%s channels"), I(pWaveFormatEx->nChannels)));
3034                                                if(pWaveFormatEx->wBitsPerSample)
3035                                                        Array.Add(AtlFormatString(_T("%s bits"), I(pWaveFormatEx->wBitsPerSample)));
3036                                        }
3037                                }
3038                                #pragma endregion
3039                                sText += AtlFormatString(_T(" (%s)"), _StringHelper::Join(Array, _T(", ")));
3040                        }
3041                }
3042                _ATLCATCHALL()
3043                {
3044                        _Z_EXCEPTION();
3045                }
3046                return sText;
3047        }
3048        static CString GetMediaTypeText(const CMediaType& pMediaType)
3049        {
3050                CString sText;
3051                #pragma region AM_MEDIA_TYPE
3052                #define J(x) I(pMediaType->x)
3053                #define K1(x) sText += AtlFormatString(_T(" * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
3054                sText += AtlFormatString(_T(" * ") _T("Data: %s") _T("\r\n"), I(AtlFormatData((const BYTE*) (const AM_MEDIA_TYPE*) pMediaType, sizeof *pMediaType).TrimRight()));
3055                sText += AtlFormatString(_T(" * ") _T("`majortype`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatMajorType(pMediaType->majortype)));
3056                if(pMediaType->subtype != MEDIASUBTYPE_NULL)
3057                        sText += AtlFormatString(_T(" * ") _T("`subtype`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatSubtype(pMediaType->majortype, pMediaType->subtype)));
3058                K1(bFixedSizeSamples);
3059                K1(bTemporalCompression);
3060                K1(lSampleSize);
3061                if(pMediaType->formattype != GUID_NULL)
3062                        sText += AtlFormatString(_T(" * ") _T("`formattype`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatFormatType(pMediaType->formattype)));
3063                if(pMediaType->pUnk)
3064                        sText += AtlFormatString(_T(" * ") _T("`pUnk`: %s") _T("\r\n"), I(AtlFormatString(_T("0x%p"), pMediaType->pUnk)));
3065                if(pMediaType->cbFormat)
3066                {
3067                        K1(cbFormat);
3068                        if(pMediaType->pbFormat)
3069                                sText += AtlFormatString(_T(" * ") _T("Format Data, `pbFormat`: %s") _T("\r\n"), I(AtlFormatData(pMediaType->pbFormat, pMediaType->cbFormat).TrimRight()));
3070                }
3071                #undef J
3072                #undef K1
3073                #pragma endregion
3074                const BYTE* pnExtraData = NULL;
3075                SIZE_T nExtraDataSize = 0;
3076                #pragma region FORMAT_VideoInfo
3077                if(pMediaType->formattype == FORMAT_VideoInfo)
3078                {
3079                        sText += AtlFormatString(_T(" * ") _T("As `VIDEOINFOHEADER`:") _T("\r\n"));
3080                        const VIDEOINFOHEADER* pVideoInfoHeader = (const VIDEOINFOHEADER*) pMediaType->pbFormat;
3081                        #define J(x) I(pVideoInfoHeader->x)
3082                        #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
3083                        sText += AtlFormatString(_T("  * ") _T("`rcSource`: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcSource.left), J(rcSource.top), J(rcSource.right), J(rcSource.bottom));
3084                        sText += AtlFormatString(_T("  * ") _T("`rcTarget`: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcTarget.left), J(rcTarget.top), J(rcTarget.right), J(rcTarget.bottom));
3085                        K1(dwBitRate);
3086                        K1(dwBitErrorRate);
3087                        sText += AtlFormatString(_T("  * ") _T("`AvgTimePerFrame`: %s units") _T("\r\n"), I(_FilterGraphHelper::FormatReferenceTime(pVideoInfoHeader->AvgTimePerFrame)));
3088                        K1(bmiHeader.biSize);
3089                        K1(bmiHeader.biWidth);
3090                        K1(bmiHeader.biHeight);
3091                        K1(bmiHeader.biPlanes);
3092                        K1(bmiHeader.biBitCount);
3093                        sText += AtlFormatString(_T("  * ") _T("`bmiHeader.biCompression`: %s") _T("\r\n"), I(_FilterGraphHelper::GetFourccCodeString(pVideoInfoHeader->bmiHeader.biCompression)));
3094                        K1(bmiHeader.biSizeImage);
3095                        K1(bmiHeader.biXPelsPerMeter);
3096                        K1(bmiHeader.biYPelsPerMeter);
3097                        K1(bmiHeader.biClrUsed);
3098                        K1(bmiHeader.biClrImportant);
3099                        #undef J
3100                        #undef K1
3101                        nExtraDataSize = pMediaType->cbFormat - sizeof *pVideoInfoHeader;
3102                } else
3103                #pragma endregion
3104                #pragma region FORMAT_VideoInfo2
3105                if(pMediaType->formattype == FORMAT_VideoInfo2)
3106                {
3107                        sText += AtlFormatString(_T(" * ") _T("As `VIDEOINFOHEADER2`:") _T("\r\n"));
3108                        const VIDEOINFOHEADER2* pVideoInfoHeader2 = (const VIDEOINFOHEADER2*) pMediaType->pbFormat;
3109                        #define J(x) I(pVideoInfoHeader2->x)
3110                        #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
3111                        #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pVideoInfoHeader2->x, y))
3112                        sText += AtlFormatString(_T("  * ") _T("rcSource: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcSource.left), J(rcSource.top), J(rcSource.right), J(rcSource.bottom));
3113                        sText += AtlFormatString(_T("  * ") _T("rcTarget: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcTarget.left), J(rcTarget.top), J(rcTarget.right), J(rcTarget.bottom));
3114                        K1(dwBitRate);
3115                        K1(dwBitErrorRate);
3116                        sText += AtlFormatString(_T("  * ") _T("`AvgTimePerFrame`: %s units") _T("\r\n"), I(_FilterGraphHelper::FormatReferenceTime(pVideoInfoHeader2->AvgTimePerFrame)));
3117                        K2(dwInterlaceFlags, _T("0x%X"));
3118                        K2(dwCopyProtectFlags, _T("0x%X"));
3119                        K1(dwPictAspectRatioX);
3120                        K1(dwPictAspectRatioY);
3121                        K2(dwControlFlags, _T("0x%X"));
3122                        K1(bmiHeader.biSize);
3123                        K1(bmiHeader.biWidth);
3124                        K1(bmiHeader.biHeight);
3125                        K1(bmiHeader.biPlanes);
3126                        K1(bmiHeader.biBitCount);
3127                        sText += AtlFormatString(_T("  * ") _T("`bmiHeader.biCompression`: %s") _T("\r\n"), I(_FilterGraphHelper::GetFourccCodeString(pVideoInfoHeader2->bmiHeader.biCompression)));
3128                        K1(bmiHeader.biSizeImage);
3129                        K1(bmiHeader.biXPelsPerMeter);
3130                        K1(bmiHeader.biYPelsPerMeter);
3131                        K1(bmiHeader.biClrUsed);
3132                        K1(bmiHeader.biClrImportant);
3133                        #undef J
3134                        #undef K1
3135                        #undef K2
3136                        nExtraDataSize = pMediaType->cbFormat - sizeof *pVideoInfoHeader2;
3137                        if(nExtraDataSize)
3138                        {
3139                                sText += AtlFormatString(_T("  * ") _T("Extra Data: (%d bytes)") _T("\r\n"), nExtraDataSize);
3140                                nExtraDataSize = 0;
3141                        }
3142                } else
3143                #pragma endregion
3144                #pragma region FORMAT_MPEG2Video
3145                if(pMediaType->formattype == FORMAT_MPEG2Video)
3146                {
3147                        sText += AtlFormatString(_T(" * ") _T("As `MPEG2VIDEOINFO`:") _T("\r\n"));
3148                        const MPEG2VIDEOINFO* pMpeg2VideoInfo = (const MPEG2VIDEOINFO*) pMediaType->pbFormat;
3149                        #define J(x) I(pMpeg2VideoInfo->x)
3150                        #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
3151                        #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pMpeg2VideoInfo->x, y))
3152                        sText += AtlFormatString(_T("  * ") _T("`hdr.rcSource`: (%s, %s) - (%s, %s)") _T("\r\n"), J(hdr.rcSource.left), J(hdr.rcSource.top), J(hdr.rcSource.right), J(hdr.rcSource.bottom));
3153                        sText += AtlFormatString(_T("  * ") _T("`hdr.rcTarget`: (%s, %s) - (%s, %s)") _T("\r\n"), J(hdr.rcTarget.left), J(hdr.rcTarget.top), J(hdr.rcTarget.right), J(hdr.rcTarget.bottom));
3154                        K1(hdr.dwBitRate);
3155                        K1(hdr.dwBitErrorRate);
3156                        sText += AtlFormatString(_T("  * ") _T("`hdr.AvgTimePerFrame`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatReferenceTime(pMpeg2VideoInfo->hdr.AvgTimePerFrame)));
3157                        K2(hdr.dwInterlaceFlags, _T("0x%X"));
3158                        K2(hdr.dwCopyProtectFlags, _T("0x%X"));
3159                        K1(hdr.dwPictAspectRatioX);
3160                        K1(hdr.dwPictAspectRatioY);
3161                        K2(hdr.dwControlFlags, _T("0x%X"));
3162                        K1(hdr.bmiHeader.biSize);
3163                        K1(hdr.bmiHeader.biWidth);
3164                        K1(hdr.bmiHeader.biHeight);
3165                        K1(hdr.bmiHeader.biPlanes);
3166                        K1(hdr.bmiHeader.biBitCount);
3167                        sText += AtlFormatString(_T("  * ") _T("`hdr.bmiHeader.biCompression`: %s") _T("\r\n"), I(_FilterGraphHelper::GetFourccCodeString(pMpeg2VideoInfo->hdr.bmiHeader.biCompression)));
3168                        K1(hdr.bmiHeader.biSizeImage);
3169                        K1(hdr.bmiHeader.biXPelsPerMeter);
3170                        K1(hdr.bmiHeader.biYPelsPerMeter);
3171                        K1(hdr.bmiHeader.biClrUsed);
3172                        K1(hdr.bmiHeader.biClrImportant);
3173                        K2(dwStartTimeCode, _T("0x%08X"));
3174                        K1(cbSequenceHeader);
3175                        K1(dwProfile);
3176                        K1(dwLevel);
3177                        K2(dwFlags, _T("0x%08X"));
3178                        #undef J
3179                        #undef K1
3180                        #undef K2
3181                        #undef J
3182                        nExtraDataSize = pMediaType->cbFormat - (sizeof *pMpeg2VideoInfo - sizeof pMpeg2VideoInfo->dwSequenceHeader);
3183                } else
3184                #pragma endregion
3185                #pragma region FORMAT_WaveFormatEx
3186                if(pMediaType->formattype == FORMAT_WaveFormatEx)
3187                {
3188                        const WAVEFORMATEX* pWaveFormatEx = (const WAVEFORMATEX*) pMediaType->pbFormat;
3189                        if(pWaveFormatEx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
3190                        {
3191                                const WAVEFORMATEXTENSIBLE* pWaveFormatExtensible = (const WAVEFORMATEXTENSIBLE*) pMediaType->pbFormat;
3192                                #define J(x) I(pWaveFormatExtensible->x)
3193                                #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
3194                                #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pWaveFormatExtensible->x, y))
3195                                sText += AtlFormatString(_T(" * ") _T("As `WAVEFORMATEXTENSIBLE`:") _T("\r\n"));
3196                                K2(Format.wFormatTag, _T("0x%02X"));
3197                                K1(Format.nChannels);
3198                                K1(Format.nSamplesPerSec);
3199                                K1(Format.nAvgBytesPerSec);
3200                                K1(Format.nBlockAlign);
3201                                K1(Format.wBitsPerSample);
3202                                K1(Format.cbSize);
3203                                K1(Samples.wValidBitsPerSample);
3204                                K2(dwChannelMask, _T("0x%02X"));
3205                                sText += AtlFormatString(_T("  * ") _T("`SubFormat`: %s") _T("\r\n"), I(_PersistHelper::StringFromIdentifier(pWaveFormatExtensible->SubFormat)));
3206                                #undef J
3207                                #undef K1
3208                                #undef K2
3209                                nExtraDataSize = pWaveFormatEx->cbSize - (sizeof *pWaveFormatExtensible - sizeof *pWaveFormatEx);
3210                        } else
3211                        {
3212                                #define J(x) I(pWaveFormatEx->x)
3213                                #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
3214                                #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pWaveFormatEx->x, y))
3215                                K2(wFormatTag, _T("0x%02X"));
3216                                K1(nChannels);
3217                                K1(nSamplesPerSec);
3218                                K1(nAvgBytesPerSec);
3219                                K1(nBlockAlign);
3220                                K1(wBitsPerSample);
3221                                K1(cbSize);
3222                                #undef J
3223                                #undef K1
3224                                #undef K2
3225                                nExtraDataSize = pWaveFormatEx->cbSize;
3226                        }
3227                }
3228                #pragma endregion
3229                #pragma region Extra Data
3230                if(nExtraDataSize)
3231                {
3232                        if(!pnExtraData)
3233                        {
3234                                if(nExtraDataSize > pMediaType->cbFormat)
3235                                        nExtraDataSize = pMediaType->cbFormat;
3236                                pnExtraData = pMediaType->pbFormat + pMediaType->cbFormat - nExtraDataSize;
3237                        }
3238                        const SSIZE_T nExtraDataExcessSize = (pnExtraData + nExtraDataSize) - (pMediaType->pbFormat + pMediaType->cbFormat);
3239                        if(nExtraDataExcessSize > 0)
3240                                nExtraDataSize -= min((SIZE_T) nExtraDataExcessSize, nExtraDataSize);
3241                        sText += AtlFormatString(_T("  * ") _T("Extra Data: %s") _T("\r\n"), I(AtlFormatData(pnExtraData, nExtraDataSize).TrimRight()));
3242                }
3243                #pragma endregion
3244                return sText;
3245        }
3246        static CString GetText(IFilterGraph* pFilterGraph, const CProcessData* pProcessData = NULL)
3247        {
3248                if(!pFilterGraph)
3249                        return (LPCTSTR) NULL;
3250                const CComQIPtr<IServiceProvider> pServiceProvider = pFilterGraph;
3251                const CComQIPtr<ISpy> pSpy = pFilterGraph;
3252                CString sText;
3253                sText += AtlFormatString(_T("# ") _T("Filter Graph") _T("\r\n") _T("\r\n"));
3254                #pragma region Graph Parameters
3255                if(pProcessData)
3256                        sText += AtlFormatString(_T("* ") _T("Process: %s (%s) %s") _T("\r\n"), I(pProcessData->m_nIdentifier), I(pProcessData->m_nIdentifier, _T("0x%X")), I(FindFileName(pProcessData->m_sImagePath)));
3257                #pragma region IMediaControl
3258                OAFilterState State = (OAFilterState) -1;
3259                const CComQIPtr<IMediaControl> pMediaControl = pFilterGraph;
3260                if(pMediaControl)
3261                        _ATLTRY
3262                        {
3263                                const HRESULT nGetStateResult = pMediaControl->GetState(0, &State);
3264                                _Z45_DSHRESULT(nGetStateResult);
3265                                static const LPCTSTR g_ppszStates[] = { _T("Stopped"), _T("Paused"), _T("Running"), };
3266                                if(SUCCEEDED(nGetStateResult) && (SIZE_T) State < DIM(g_ppszStates))
3267                                        sText += AtlFormatString(_T("* ") _T("State: %s") _T("\r\n"), I(g_ppszStates[(SIZE_T) State]));
3268                        }
3269                        _ATLCATCHALL()
3270                        {
3271                                _Z_EXCEPTION();
3272                        }
3273                #pragma endregion
3274                #pragma region IMediaPosition
3275                const CComQIPtr<IMediaPosition> pMediaPosition = pFilterGraph;
3276                if(pMediaPosition)
3277                        _ATLTRY
3278                        {
3279                                DOUBLE fDuration = 0, fPosition = 0;
3280                                const HRESULT nGetDurationResult = pMediaPosition->get_Duration(&fDuration);
3281                                _Z45_DSHRESULT(nGetDurationResult);
3282                                if(fDuration > 0)
3283                                {
3284                                        sText += AtlFormatString(_T("* ") _T("Duration: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime(fDuration)), I(_StringHelper::FormatNumber(fDuration, 3)));
3285                                        const HRESULT nCurrentPositionResult = pMediaPosition->get_CurrentPosition(&fPosition);
3286                                        _Z45_DSHRESULT(nCurrentPositionResult);
3287                                        if(SUCCEEDED(nCurrentPositionResult))
3288                                                sText += AtlFormatString(_T("* ") _T("Position: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime(fPosition)), I(_StringHelper::FormatNumber(fPosition, 3)));
3289                                }
3290                        }
3291                        _ATLCATCHALL()
3292                        {
3293                                _Z_EXCEPTION();
3294                        }
3295                #pragma endregion
3296                if(pProcessData)
3297                {
3298                        if(!pProcessData->m_sDisplayName.IsEmpty())
3299                                sText += AtlFormatString(_T("* ") _T("Display Name: %s") _T("\r\n"), I(pProcessData->m_sDisplayName));
3300                        if(_tcslen(pProcessData->m_sImagePath))
3301                        {
3302                                const CString sDirectory = (LPCTSTR) GetPathDirectory(pProcessData->m_sImagePath);
3303                                if(!sDirectory.IsEmpty())
3304                                        sText += AtlFormatString(_T("* ") _T("Process Directory: %s") _T("\r\n"), I(sDirectory));
3305                        }
3306                }
3307                const CComQIPtr<IMediaFilter> pMediaFilter = pFilterGraph;
3308                CComPtr<IReferenceClock> pFilterGraphReferenceClock;
3309                const HRESULT nGetSyncSourceResult = pMediaFilter->GetSyncSource(&pFilterGraphReferenceClock);
3310                _Z45_DSHRESULT(nGetSyncSourceResult);
3311                sText += _T("\r\n");
3312                #pragma endregion
3313                #pragma region Filter
3314                _FilterGraphHelper::CFilterArray FilterArray;
3315                _FilterGraphHelper::GetGraphFilters(pFilterGraph, FilterArray);
3316                if(!FilterArray.IsEmpty())
3317                {
3318                        sText += AtlFormatString(_T("## ") _T("Filters") _T("\r\n") _T("\r\n"));
3319                        for(SIZE_T nIndex = 0; nIndex < FilterArray.GetCount(); nIndex++)
3320                                _ATLTRY
3321                                {
3322                                        const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nIndex];
3323                                        sText += AtlFormatString(_T("%d. ") _T("%ls") _T("\r\n"), nIndex + 1, _FilterGraphHelper::GetFilterName(pBaseFilter));
3324                                        sText += GetFilterText(pBaseFilter, pProcessData, pFilterGraphReferenceClock);
3325                                }
3326                                _ATLCATCHALL()
3327                                {
3328                                        _Z_EXCEPTION();
3329                                }
3330                        sText += _T("\r\n");
3331                        #pragma region Connection
3332                        sText += AtlFormatString(_T("## ") _T("Connections") _T("\r\n") _T("\r\n"));
3333                        INT nConnectionIndex = 0;
3334                        for(auto&& pBaseFilter: FilterArray)
3335                        {
3336                                _FilterGraphHelper::CPinArray PinArray;
3337                                _FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_OUTPUT, PinArray);
3338                                for(auto&& pOutputPin: PinArray)
3339                                {
3340                                        const CComPtr<IPin> pInputPin = _FilterGraphHelper::GetPeerPin(pOutputPin);
3341                                        if(!pInputPin)
3342                                                continue;
3343                                        sText += AtlFormatString(_T("%d. ") _T("%s") _T("\r\n"), ++nConnectionIndex, GetConnectionText(pOutputPin, pInputPin));
3344                                }
3345                        }
3346                        sText += _T("\r\n");
3347                        #pragma endregion
3348                        #pragma region Media Type
3349                        sText += AtlFormatString(_T("## ") _T("Media Types") _T("\r\n") _T("\r\n"));
3350                        INT nGlobalPinIndex = 0;
3351                        CRoListT<CComPtr<IPin>> PinList;
3352                        for(SIZE_T nFilterIndex = 0; nFilterIndex < FilterArray.GetCount(); nFilterIndex++)
3353                        {
3354                                const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nFilterIndex];
3355                                _FilterGraphHelper::CPinArray PinArray;
3356                                _FilterGraphHelper::GetFilterPins(pBaseFilter, PinArray);
3357                                for(SIZE_T nPinIndex = 0; nPinIndex < PinArray.GetCount(); nPinIndex++)
3358                                {
3359                                        const CComPtr<IPin>& pPin = PinArray[nPinIndex];
3360                                        if(PinList.FindFirst(pPin))
3361                                                continue;
3362                                        PinList.AddTail(pPin);
3363                                        CString sPinText = AtlFormatString(_T("%s"), I(_FilterGraphHelper::GetPinFullName(pPin)));
3364                                        const CComPtr<IPin> pPeerPin = _FilterGraphHelper::GetPeerPin(pPin);
3365                                        if(pPeerPin)
3366                                        {
3367                                                PinList.AddTail(pPeerPin);
3368                                                sPinText += AtlFormatString(_T(", %s"), I(_FilterGraphHelper::GetPinFullName(pPeerPin)));
3369                                        }
3370                                        sText += AtlFormatString(_T("%d. ") _T("%s") _T("\r\n"), ++nGlobalPinIndex, sPinText);
3371                                        _ATLTRY
3372                                        {
3373                                                CMediaType pMediaType;
3374                                                if(pPeerPin)
3375                                                        pMediaType = _FilterGraphHelper::GetPinMediaType(pPin);
3376                                                else
3377                                                        pMediaType = _FilterGraphHelper::EnumerateFirstPinMediaType(pPin);
3378                                                if(!pMediaType)
3379                                                        continue;
3380                                                sText += GetMediaTypeText(pMediaType);
3381                                        }
3382                                        _ATLCATCHALL()
3383                                        {
3384                                                _Z_EXCEPTION();
3385                                        }
3386                                }
3387                        }
3388                        sText += _T("\r\n");
3389                        #pragma endregion
3390                        if(State > State_Stopped)
3391                        {
3392                                #pragma region Memory Allocator
3393                                INT nConnectionIndex = 0;
3394                                for(auto&& pBaseFilter: FilterArray)
3395                                {
3396                                        _FilterGraphHelper::CPinArray PinArray;
3397                                        _FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_INPUT, PinArray);
3398                                        for(auto&& pInputPin: PinArray)
3399                                        {
3400                                                _ATLTRY
3401                                                {
3402                                                        const CComQIPtr<IMemInputPin> pMemInputPin = pInputPin;
3403                                                        if(!pMemInputPin)
3404                                                                continue; // No IMemInputPin
3405                                                        const CComPtr<IPin> pOutputPin = _FilterGraphHelper::GetPeerPin(pInputPin);
3406                                                        if(!pOutputPin)
3407                                                                continue; // Not Connected
3408                                                        CComPtr<IMemAllocator> pMemAllocator;
3409                                                        pMemInputPin->GetAllocator(&pMemAllocator);
3410                                                        if(!pMemAllocator)
3411                                                                continue; // No Memory Allocator
3412                                                        ALLOCATOR_PROPERTIES Properties;
3413                                                        const HRESULT nGetPropertiesResult = pMemAllocator->GetProperties(&Properties);
3414                                                        _Z45_DSHRESULT(nGetPropertiesResult);
3415                                                        if(FAILED(nGetPropertiesResult))
3416                                                                continue; // No Memory Allocator Properties
3417                                                        const CComQIPtr<IMemAllocatorCallbackTemp> pMemAllocatorCallbackTemp = pMemAllocator;
3418                                                        BOOL bFreeCountAvailable;
3419                                                        LONG nFreeCount;
3420                                                        if(pMemAllocatorCallbackTemp)
3421                                                        {
3422                                                                const HRESULT nGetFreeCountResult = pMemAllocatorCallbackTemp->GetFreeCount(&nFreeCount);
3423                                                                _Z45_DSHRESULT(nGetFreeCountResult);
3424                                                                bFreeCountAvailable = SUCCEEDED(nGetFreeCountResult);
3425                                                        } else
3426                                                                bFreeCountAvailable = FALSE;
3427                                                        CString sConnectionText = AtlFormatString(_T("%s - %s"), I(_FilterGraphHelper::GetPinFullName(pInputPin)), I(_FilterGraphHelper::GetPinFullName(pOutputPin)));
3428                                                        sConnectionText += _T(": ");
3429                                                        CRoArrayT<CString> Array;
3430                                                        Array.Add(AtlFormatString(_T("%s buffers"), I(Properties.cBuffers)));
3431                                                        if(bFreeCountAvailable)
3432                                                                Array.Add(AtlFormatString(_T("%s free buffers"), I(nFreeCount)));
3433                                                        Array.Add(AtlFormatString(_T("%s bytes per buffer"), I(Properties.cbBuffer)));
3434                                                        if(Properties.cbAlign > 1)
3435                                                                Array.Add(AtlFormatString(_T("%s byte alignment"), I(Properties.cbAlign)));
3436                                                        if(Properties.cbPrefix > 0)
3437                                                                Array.Add(AtlFormatString(_T("%s byte prefix"), I(Properties.cbPrefix)));
3438                                                        sConnectionText += _StringHelper::Join(Array, _T(", "));
3439                                                        if(!nConnectionIndex)
3440                                                                sText += AtlFormatString(_T("## ") _T("Memory Allocators") _T("\r\n") _T("\r\n"));
3441                                                        sText += AtlFormatString(_T("%d. ") _T("%s") _T("\r\n"), ++nConnectionIndex, sConnectionText);
3442                                                }
3443                                                _ATLCATCHALL()
3444                                                {
3445                                                        _Z_EXCEPTION();
3446                                                }
3447                                        }
3448                                }
3449                                if(nConnectionIndex)
3450                                        sText += _T("\r\n");
3451                                #pragma endregion
3452                        }
3453                        #pragma region IMediaSeeking
3454                        BOOL bMediaSeekingHeaderAdded = FALSE;
3455                        for(SIZE_T nFilterIndex = 0; nFilterIndex < FilterArray.GetCount(); nFilterIndex++)
3456                        {
3457                                const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nFilterIndex];
3458                                _FilterGraphHelper::CPinArray PinArray;
3459                                _FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_OUTPUT, PinArray);
3460                                for(SIZE_T nPinIndex = 0; nPinIndex < PinArray.GetCount(); nPinIndex++)
3461                                {
3462                                        const CComPtr<IPin>& pOutputPin = PinArray[nPinIndex];
3463                                        const CComQIPtr<IMediaSeeking> pMediaSeeking = pOutputPin;
3464                                        if(!pMediaSeeking)
3465                                                continue;
3466                                        if(!bMediaSeekingHeaderAdded)
3467                                        {
3468                                                sText += AtlFormatString(_T("## ") _T("Media Seeking/Position") _T("\r\n") _T("\r\n"));
3469                                                bMediaSeekingHeaderAdded = TRUE;
3470                                        }
3471                                        sText += AtlFormatString(_T("* ") _T("Pin: %s") _T("\r\n"), I(_FilterGraphHelper::GetPinFullName(pOutputPin)));
3472                                        _ATLTRY
3473                                        {
3474                                                DWORD nCapabilities = 0;
3475                                                if(SUCCEEDED(pMediaSeeking->GetCapabilities(&nCapabilities)))
3476                                                        sText += AtlFormatString(_T(" * ") _T("Capabilities: %s") _T("\r\n"), I(AtlFormatString(_T("0x%X"), nCapabilities)));
3477                                                LONGLONG nDuration = 0, nPosition = 0, nStopPosition = 0;
3478                                                if(SUCCEEDED(pMediaSeeking->GetDuration(&nDuration)))
3479                                                        sText += AtlFormatString(_T(" * ") _T("Duration: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime((DOUBLE) nDuration / 1E7)), I(_StringHelper::FormatNumber((DOUBLE) nDuration / 1E7, 3)));
3480                                                if(SUCCEEDED(pMediaSeeking->GetCurrentPosition(&nPosition)))
3481                                                        sText += AtlFormatString(_T(" * ") _T("Position: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime((DOUBLE) nPosition / 1E7)), I(_StringHelper::FormatNumber((DOUBLE) nPosition / 1E7, 3)));
3482                                                if(SUCCEEDED(pMediaSeeking->GetStopPosition(&nStopPosition)))
3483                                                        sText += AtlFormatString(_T(" * ") _T("Stop Position: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime((DOUBLE) nStopPosition / 1E7)), I(_StringHelper::FormatNumber((DOUBLE) nStopPosition / 1E7, 3)));
3484                                                DOUBLE fRate = 1.0;
3485                                                if(SUCCEEDED(pMediaSeeking->GetRate(&fRate)))
3486                                                        sText += AtlFormatString(_T(" * ") _T("Rate: %s") _T("\r\n"), I(_StringHelper::FormatNumber(fRate, 3)));
3487                                                LONGLONG nPreroll = 0;
3488                                                if(SUCCEEDED(pMediaSeeking->GetPreroll(&nPreroll)) && nPreroll)
3489                                                        sText += AtlFormatString(_T(" * ") _T("Preroll: %s seconds") _T("\r\n"), I(_StringHelper::FormatNumber((DOUBLE) nPreroll / 1E7, 3)));
3490                                        }
3491                                        _ATLCATCHALL()
3492                                        {
3493                                                _Z_EXCEPTION();
3494                                        }
3495                                }
3496                        }
3497                        if(bMediaSeekingHeaderAdded)
3498                                sText += _T("\r\n");
3499                        #pragma endregion
3500                        #pragma region Runtime Property Bag
3501                        const CString sRunPropertyBagHeader = AtlFormatString(_T("## ") _T("Runtime Properties") _T("\r\n") _T("\r\n"));
3502                        BOOL bRunPropertyBagHeaderAdded = FALSE;
3503                        {
3504                                const CString sPropertyBagText = CRunPropertyBagHelper::GetPropertyBagText(pFilterGraph, pSpy);
3505                                if(!sPropertyBagText.IsEmpty())
3506                                {
3507                                        sText += sRunPropertyBagHeader;
3508                                        bRunPropertyBagHeaderAdded = TRUE;
3509                                        sText += sPropertyBagText;
3510                                        sText += _T("\r\n");
3511                                }
3512                        }
3513                        for(auto&& pBaseFilter: FilterArray)
3514                        {
3515                                _ATLTRY
3516                                {
3517                                        const CString sPropertyBagText = CRunPropertyBagHelper::GetPropertyBagText(pBaseFilter, pSpy);
3518                                        if(sPropertyBagText.IsEmpty())
3519                                                continue;
3520                                        if(!bRunPropertyBagHeaderAdded)
3521                                        {
3522                                                sText += sRunPropertyBagHeader;
3523                                                bRunPropertyBagHeaderAdded = TRUE;
3524                                        }
3525                                        sText += AtlFormatString(_T("### ") _T("Filter: %ls") _T("\r\n") _T("\r\n"), _FilterGraphHelper::GetFilterName(pBaseFilter));
3526                                        sText += sPropertyBagText;
3527                                        sText += _T("\r\n");
3528                                }
3529                                _ATLCATCHALL()
3530                                {
3531                                        _Z_EXCEPTION();
3532                                }
3533                        }
3534                        #pragma endregion
3535                }
3536                #pragma endregion
3537                #pragma region Clock
3538                {
3539                        sText += AtlFormatString(_T("## ") _T("Clock") _T("\r\n") _T("\r\n"));
3540                        CComPtr<IReferenceClock> pCurrentReferenceClock;
3541                        _ATLTRY
3542                        {
3543                                const CComQIPtr<IMediaFilter> pMediaFilter = pFilterGraph;
3544                                if(pMediaFilter)
3545                                        __C(pMediaFilter->GetSyncSource(&pCurrentReferenceClock));
3546                        }
3547                        _ATLCATCHALL()
3548                        {
3549                                _Z_EXCEPTION();
3550                        }
3551                        CStringW sCurrentName;
3552                        for(auto&& pBaseFilter: FilterArray)
3553                        {
3554                                const CComQIPtr<IReferenceClock> pReferenceClock = pBaseFilter;
3555                                if(!pReferenceClock)
3556                                        continue;
3557                                const CStringW sName = _FilterGraphHelper::GetFilterName(pBaseFilter);
3558                                CRoArrayT<CString> Array;
3559                                _ATLTRY
3560                                {
3561                                        if(pCurrentReferenceClock == pReferenceClock)
3562                                        {
3563                                                sCurrentName = sName;
3564                                                Array.Add(_T("Current"));
3565                                        }
3566                                        Array.Add(I(pReferenceClock));
3567                                        REFERENCE_TIME nTime = 0;
3568                                        __C(pReferenceClock->GetTime(&nTime));
3569                                        Array.Add(I(_FilterGraphHelper::FormatReferenceTime(nTime)));
3570                                        Array.Add(I(AtlFormatString(_T("0x%I64X"), nTime)));
3571                                }
3572                                _ATLCATCHALL()
3573                                {
3574                                        _Z_EXCEPTION();
3575                                }
3576                                sText += AtlFormatString(_T(" * ") _T("%s (%s)") _T("\r\n"), I(sName), _StringHelper::Join(Array, _T(", ")));
3577                        }
3578                        if(pCurrentReferenceClock)
3579                        {
3580                                if(sCurrentName.IsEmpty())
3581                                {
3582                                        CRoArrayT<CString> Array;
3583                                        _ATLTRY
3584                                        {
3585                                                Array.Add(I(pCurrentReferenceClock));
3586                                                REFERENCE_TIME nTime = 0;
3587                                                __C(pCurrentReferenceClock->GetTime(&nTime));
3588                                                Array.Add(I(_FilterGraphHelper::FormatReferenceTime(nTime)));
3589                                                Array.Add(I(AtlFormatString(_T("0x%I64X"), nTime)));
3590                                        }
3591                                        _ATLCATCHALL()
3592                                        {
3593                                                _Z_EXCEPTION();
3594                                        }
3595                                        sText += AtlFormatString(_T(" * ") _T("Current: External (%s)") _T("\r\n"), _StringHelper::Join(Array, _T(", ")));
3596                                }
3597                        } else
3598                                sText += AtlFormatString(_T(" * ") _T("Current: None") _T("\r\n"));
3599                        sText += _T("\r\n");
3600                }
3601                #pragma endregion
3602                return sText;
3603        }
3604        #undef I
3605        CComPtr<IFilterGraph> GetFilterGraph() const
3606        {
3607                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
3608                return m_pFilterGraph;
3609        }
3610        VOID SetFilterGraph(IFilterGraph* pFilterGraph, CProcessData* pProcessData = NULL) 
3611        {
3612                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
3613                if(!pProcessData)
3614                {
3615                        m_ProcessData = CProcessData();
3616                        const CComQIPtr<ISpyEx> pSpyEx = pFilterGraph;
3617                        if(pSpyEx)
3618                                m_ProcessData.m_nIdentifier = GetCurrentProcessId();
3619                } else
3620                        m_ProcessData = *pProcessData;
3621                m_pFilterGraph = pFilterGraph;
3622        }
3623        BOOL SetFilterGraph(IUnknown* pFilterGraphUnknown, CProcessData* pProcessData = NULL) 
3624        {
3625                CComQIPtr<IFilterGraph> pFilterGraph;
3626                if(pFilterGraphUnknown)
3627                {
3628                        pFilterGraph = pFilterGraphUnknown;
3629                        if(!pFilterGraph)
3630                        {
3631                                const CComQIPtr<IBaseFilter> pBaseFilter = pFilterGraphUnknown;
3632                                if(!pBaseFilter)
3633                                {
3634                                        const CComQIPtr<IPin> pPin = pFilterGraphUnknown;
3635                                        if(pPin)
3636                                                pFilterGraph = _FilterGraphHelper::GetFilterGraph(_FilterGraphHelper::GetPinFilter(pPin));
3637                                } else
3638                                        pFilterGraph = _FilterGraphHelper::GetFilterGraph(pBaseFilter);
3639                        }
3640                }
3641                SetFilterGraph(pFilterGraph, pProcessData);
3642                return pFilterGraph != NULL;
3643        }
3644        CString GetFilterText(IBaseFilter* pBaseFilter) const
3645        {
3646                return GetFilterText(pBaseFilter, m_ProcessData.m_nIdentifier ? &m_ProcessData : NULL);
3647        }
3648        CString GetText() const
3649        {
3650                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
3651                return GetText(m_pFilterGraph, m_ProcessData.m_nIdentifier ? &m_ProcessData : NULL);
3652        }
3653        static LPCTSTR GetPlatformName()
3654        {
3655                #if defined(_WIN64)
3656                        return _T("x64");
3657                #else
3658                        return _T("Win32");
3659                #endif // defined(_WIN64)
3660        }
3661        static BOOL OpenMonikerWithGsn(LPCWSTR pszMonikerDisplayName, HWND hParentWindow = GetActiveWindow())
3662        {
3663                _A(pszMonikerDisplayName);
3664                static const LPCTSTR g_pszValueName = _T("GraphStudioNext Path");
3665                static const LPCTSTR g_pszFileName = _T("graphstudionext.exe");
3666                const CString sValueName = AtlFormatString(_T("%s (%s)"), g_pszValueName, GetPlatformName());
3667                CString sPath = _RegKeyHelper::QueryStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, sValueName);
3668                if(!FileExists(sPath))
3669                        sPath.Empty();
3670                #pragma region Current Directory
3671                if(sPath.IsEmpty())
3672                {
3673                        sPath = (LPCTSTR) Combine(GetPathDirectory(GetModulePath()), g_pszFileName);
3674                        if(!FileExists(sPath))
3675                                sPath.Empty();
3676                }
3677                #pragma endregion
3678                #pragma region Application Registry
3679                if(sPath.IsEmpty())
3680                {
3681                        #if defined(_WIN64)
3682                                static const LPCTSTR g_pszValueName = _T("exeLocation64");
3683                        #else
3684                                static const LPCTSTR g_pszValueName = _T("exeLocation");
3685                        #endif // defined(_WIN64)
3686                        sPath = _RegKeyHelper::QueryStringValue(HKEY_CURRENT_USER, _T("Software\\MONOGRAM\\GraphStudioNext"), g_pszValueName);
3687                        if(!FileExists(sPath))
3688                                sPath.Empty();
3689                }
3690                #pragma endregion
3691                if(sPath.IsEmpty())
3692                {
3693                        static const COMDLG_FILTERSPEC g_pFilter[] = 
3694                        {
3695                                { _T("Executable Files"), _T("*.exe") },
3696                                { _T("All Files"), _T("*.*") },
3697                        };
3698                        sPath = (LPCTSTR) _CommonDialogHelper::QueryOpenPath(hParentWindow, g_pFilter, _T("exe"), g_pszFileName);
3699                        if(sPath.IsEmpty())
3700                                return FALSE;
3701                        _RegKeyHelper::SetStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, sValueName, sPath);
3702                }
3703                CWaitCursor WaitCursor;
3704                CString sParameters = AtlFormatString(_T("-a \"%ls\""), pszMonikerDisplayName);
3705                SHELLEXECUTEINFO Infomation;
3706                ZeroMemory(&Infomation, sizeof Infomation);
3707                Infomation.cbSize = sizeof Infomation;
3708                Infomation.lpFile = sPath;
3709                Infomation.lpParameters = sParameters;
3710                Infomation.nShow = SW_SHOWNORMAL;
3711                __E(ShellExecuteEx(&Infomation));
3712                return TRUE;
3713        }
3714        static BOOL OpenMonikerWithGe(LPCWSTR pszMonikerDisplayName, HWND hParentWindow = GetActiveWindow())
3715        {
3716                static const LPCTSTR g_pszValueName = _T("GraphEdit Path");
3717                static const LPCTSTR g_pszFileName = _T("graphedt.exe");
3718                const CString sValueName = AtlFormatString(_T("%s (%s)"), g_pszValueName, GetPlatformName());
3719                CString sPath = _RegKeyHelper::QueryStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, sValueName);
3720                if(!FileExists(sPath))
3721                        sPath.Empty();
3722                #pragma region Current Directory
3723                if(sPath.IsEmpty())
3724                {
3725                        sPath = (LPCTSTR) Combine(GetPathDirectory(GetModulePath()), g_pszFileName);
3726                        if(!FileExists(sPath))
3727                                sPath.Empty();
3728                }
3729                #pragma endregion
3730                // SUGG: Look for Windows SDK
3731                if(sPath.IsEmpty())
3732                {
3733                        static const COMDLG_FILTERSPEC g_pFilter[] = 
3734                        {
3735                                { _T("Executable Files"), _T("*.exe") },
3736                                { _T("All Files"), _T("*.*") },
3737                        };
3738                        sPath = (LPCTSTR) _CommonDialogHelper::QueryOpenPath(hParentWindow, g_pFilter, _T("exe"), g_pszFileName);
3739                        if(sPath.IsEmpty())
3740                                return FALSE;
3741                        _RegKeyHelper::SetStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, sValueName, sPath);
3742                }
3743                CStringW sFilterGraphMonikerDisplayName = pszMonikerDisplayName;
3744                const INT nSeparatorPosition = sFilterGraphMonikerDisplayName.Find(L';');
3745                if(nSeparatorPosition >= 0)
3746                        sFilterGraphMonikerDisplayName = sFilterGraphMonikerDisplayName.Left(nSeparatorPosition);
3747                CWaitCursor WaitCursor;
3748                CString sParameters = AtlFormatString(_T("-a %ls"), sFilterGraphMonikerDisplayName);
3749                SHELLEXECUTEINFO Infomation;
3750                ZeroMemory(&Infomation, sizeof Infomation);
3751                Infomation.cbSize = sizeof Infomation;
3752                Infomation.lpFile = sPath;
3753                Infomation.lpParameters = sParameters;
3754                Infomation.nShow = SW_SHOWNORMAL;
3755                __E(ShellExecuteEx(&Infomation));
3756                return TRUE;
3757        }
3758
3759// IFilterGraphHelper
3760        STDMETHOD(get_FilterGraph)(IUnknown** ppFilterGraphUnknown) override
3761        {
3762                _Z4(atlTraceCOM, 4, _T("...\n"));
3763                _ATLTRY
3764                {
3765                        __D(ppFilterGraphUnknown, E_POINTER);
3766                        *ppFilterGraphUnknown = GetFilterGraph().Detach();
3767                }
3768                _ATLCATCH(Exception)
3769                {
3770                        _C(Exception);
3771                }
3772                return S_OK;
3773        }
3774        STDMETHOD(put_FilterGraph)(IUnknown* pFilterGraphUnknown) override
3775        {
3776                _Z4(atlTraceCOM, 4, _T("pFilterGraphUnknown 0x%p\n"), pFilterGraphUnknown);
3777                _ATLTRY
3778                {
3779                        if(!SetFilterGraph(pFilterGraphUnknown))
3780                                return S_FALSE;
3781                }
3782                _ATLCATCH(Exception)
3783                {
3784                        _C(Exception);
3785                }
3786                return S_OK;
3787        }
3788        STDMETHOD(get_Text)(BSTR* psText) override
3789        {
3790                _Z4(atlTraceCOM, 4, _T("...\n"));
3791                _ATLTRY
3792                {
3793                        __D(psText, E_POINTER);
3794                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
3795                        *psText = CComBSTR(GetText(m_pFilterGraph)).Detach();
3796                }
3797                _ATLCATCH(Exception)
3798                {
3799                        _C(Exception);
3800                }
3801                return S_OK;
3802        }
3803        STDMETHOD(DoPropertyFrameModal)(LONG nParentWindowHandle) override
3804        {
3805                _Z4(atlTraceCOM, 4, _T("nParentWindowHandle 0x%08X\n"), nParentWindowHandle);
3806                _ATLTRY
3807                {
3808                        CWindow ParentWindow = (HWND) (LONG_PTR) nParentWindowHandle;
3809                        if(!ParentWindow)
3810                                ParentWindow = GetActiveWindow();
3811                        //__D(!ParentWindow || ParentWindow.IsWindow(), E_INVALIDARG);
3812                        const CComQIPtr<IFilterGraph2> pFilterGraph2 = GetFilterGraph();
3813                        __D(pFilterGraph2, E_NOINTERFACE);
3814                        CPropertyFrameDialog PropertyFrameDialog(this);
3815                        PropertyFrameDialog.DoModal(ParentWindow);
3816                }
3817                _ATLCATCH(Exception)
3818                {
3819                        _C(Exception);
3820                }
3821                return S_OK;
3822        }
3823        STDMETHOD(DoFilterGraphListModal)(LONG nParentWindowHandle) override
3824        {
3825                _Z4(atlTraceCOM, 4, _T("nParentWindowHandle 0x%08X\n"), nParentWindowHandle);
3826                _ATLTRY
3827                {
3828                        CWindow ParentWindow = (HWND) (LONG_PTR) nParentWindowHandle;
3829                        if(!ParentWindow)
3830                                ParentWindow = GetActiveWindow();
3831                        //__D(!ParentWindow || ParentWindow.IsWindow(), E_INVALIDARG);
3832                        DoFilterGraphListPropertySheetModal(ParentWindow, &m_Options);
3833                }
3834                _ATLCATCH(Exception)
3835                {
3836                        _C(Exception);
3837                }
3838                return S_OK;
3839        }
3840        STDMETHOD(OpenGraphStudioNext)(LONG nParentWindowHandle, BSTR sMonikerDisplayName, VARIANT_BOOL* pbResult) override
3841        {
3842                _Z4(atlTraceCOM, 4, _T("nParentWindowHandle 0x%08X, sMonikerDisplayName \"%s\"\n"), nParentWindowHandle, CString(sMonikerDisplayName));
3843                _ATLTRY
3844                {
3845                        __D(sMonikerDisplayName && *sMonikerDisplayName, E_INVALIDARG);
3846                        CWindow ParentWindow = (HWND) (LONG_PTR) nParentWindowHandle;
3847                        if(!ParentWindow)
3848                                ParentWindow = GetActiveWindow();
3849                        //__D(!ParentWindow || ParentWindow.IsWindow(), E_INVALIDARG);
3850                        const BOOL bResult = OpenMonikerWithGsn(sMonikerDisplayName, ParentWindow);
3851                        if(pbResult)
3852                                *pbResult = bResult ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE;
3853                }
3854                _ATLCATCH(Exception)
3855                {
3856                        _C(Exception);
3857                }
3858                return S_OK;
3859        }
3860        STDMETHOD(OpenGraphEdit)(LONG nParentWindowHandle, BSTR sMonikerDisplayName, VARIANT_BOOL* pbResult) override
3861        {
3862                _Z4(atlTraceCOM, 4, _T("nParentWindowHandle 0x%08X, sMonikerDisplayName \"%s\"\n"), nParentWindowHandle, CString(sMonikerDisplayName));
3863                _ATLTRY
3864                {
3865                        __D(sMonikerDisplayName && *sMonikerDisplayName, E_INVALIDARG);
3866                        CWindow ParentWindow = (HWND) (LONG_PTR) nParentWindowHandle;
3867                        if(!ParentWindow)
3868                                ParentWindow = GetActiveWindow();
3869                        //__D(!ParentWindow || ParentWindow.IsWindow(), E_INVALIDARG);
3870                        const BOOL bResult = OpenMonikerWithGe(sMonikerDisplayName, ParentWindow);
3871                        if(pbResult)
3872                                *pbResult = bResult ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE;
3873                }
3874                _ATLCATCH(Exception)
3875                {
3876                        _C(Exception);
3877                }
3878                return S_OK;
3879        }
3880        STDMETHOD(get_Options)(VARIANT* pvOptions) override
3881        {
3882                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
3883                _ATLTRY
3884                {
3885                        __D(pvOptions, E_POINTER);
3886                        VariantInit(pvOptions);
3887                        __C(m_Options.GetVariant().Detach(pvOptions));
3888                }
3889                _ATLCATCH(Exception)
3890                {
3891                        _C(Exception);
3892                }
3893                return S_OK;
3894        }
3895        STDMETHOD(put_Options)(VARIANT vOptions) override
3896        {
3897                _Z4(atlTraceCOM, 4, _T("this 0x%p, vOptions.vt %s\n"), this, reinterpret_cast<CComVariantArray&>(vOptions).FormatType());
3898                _ATLTRY
3899                {
3900                        m_Options.SetVariant(vOptions);
3901                }
3902                _ATLCATCH(Exception)
3903                {
3904                        _C(Exception);
3905                }
3906                return S_OK;
3907        }
3908        STDMETHOD(ResetMediaSampleTrace)(VARIANT vProcessIdentifier) override
3909        {
3910                _Z4(atlTraceCOM, 4, _T("this 0x%p, vProcessIdentifier %s\n"), this, reinterpret_cast<CComVariantArray&>(vProcessIdentifier).Format(TRUE));
3911                _ATLTRY
3912                {
3913                        DWORD nProcessIdentifier = 0;
3914                        if(vProcessIdentifier.vt > VT_NULL)
3915                                nProcessIdentifier = (DWORD) reinterpret_cast<CComVariantArray&>(vProcessIdentifier).GetAsType(VT_I4).lVal;
3916                        MediaSampleTrace_Reset(nProcessIdentifier);
3917                }
3918                _ATLCATCH(Exception)
3919                {
3920                        _C(Exception);
3921                }
3922                return S_OK;
3923        }
3924        STDMETHOD(LockMediaSampleTrace)(IUnknown** ppLockUnknown) override
3925        {
3926                _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this);
3927                _ATLTRY
3928                {
3929                        __D(ppLockUnknown, E_POINTER);
3930                        *ppLockUnknown = MediaSampleTrace_Lock().Detach();
3931                }
3932                _ATLCATCH(Exception)
3933                {
3934                        _C(Exception);
3935                }
3936                return S_OK;
3937        }
3938        STDMETHOD(GetMediaSampleTrace)(VARIANT vProcessIdentifier, BSTR* psText) override
3939        {
3940                _Z4(atlTraceCOM, 4, _T("this 0x%p, vProcessIdentifier %s\n"), this, reinterpret_cast<CComVariantArray&>(vProcessIdentifier).Format(TRUE));
3941                _ATLTRY
3942                {
3943                        __D(psText, E_POINTER);
3944                        DWORD nProcessIdentifier = 0;
3945                        if(vProcessIdentifier.vt > VT_NULL)
3946                                nProcessIdentifier = (DWORD) reinterpret_cast<CComVariantArray&>(vProcessIdentifier).GetAsType(VT_I4).lVal;
3947                        *psText = CComBSTR(MediaSampleTrace_Get(nProcessIdentifier)).Detach();
3948                }
3949                _ATLCATCH(Exception)
3950                {
3951                        _C(Exception);
3952                }
3953                return S_OK;
3954        }
3955};
3956
3957OBJECT_ENTRY_AUTO(__uuidof(FilterGraphHelper), CFilterGraphHelper)
3958
3959inline HRESULT FilterGraphHelper_DoPropertyFrameModal(LONG nParentWindowHandle, IUnknown* pFilterGraphUnknown)
3960{
3961        CLocalObjectPtr<CFilterGraphHelper> pFilterGraphHelper;
3962        pFilterGraphHelper->SetFilterGraph(pFilterGraphUnknown);
3963        return pFilterGraphHelper->DoPropertyFrameModal(nParentWindowHandle);
3964}
3965inline HRESULT FilterGraphHelper_DoFilterGraphListModal(LONG nParentWindowHandle)
3966{
3967        CLocalObjectPtr<CFilterGraphHelper> pFilterGraphHelper;
3968        return pFilterGraphHelper->DoFilterGraphListModal(nParentWindowHandle);
3969}
3970inline HRESULT FilterGraphHelper_OpenGraphStudioNext(LONG nParentWindowHandle, LPCWSTR pszMonikerDisplayName, VARIANT_BOOL* pbResult)
3971{
3972        CLocalObjectPtr<CFilterGraphHelper> pFilterGraphHelper;
3973        return pFilterGraphHelper->OpenGraphStudioNext(nParentWindowHandle, CComBSTR(pszMonikerDisplayName), pbResult);
3974}
3975inline HRESULT FilterGraphHelper_OpenGraphEdit(LONG nParentWindowHandle, LPCWSTR pszMonikerDisplayName, VARIANT_BOOL* pbResult)
3976{
3977        CLocalObjectPtr<CFilterGraphHelper> pFilterGraphHelper;
3978        return pFilterGraphHelper->OpenGraphEdit(nParentWindowHandle, CComBSTR(pszMonikerDisplayName), pbResult);
3979}
Note: See TracBrowser for help on using the repository browser.