source: trunk/DirectShowSpy/FilterGraphHelper.h @ 376

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

Changed year to 2015; Added Copy and Save As links in graph text, RunTime? property pages

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