source: trunk/DirectShowSpy/FilterGraphHelper.h @ 432

Last change on this file since 432 was 432, checked in by roman, 9 years ago

VS2013 related updates; use of CSIDL_LOCAL_APPDATA instead of CSIDL_APPDATA for fallback log writes; added bitness and privilege indication in all captions

File size: 139.5 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                                        #pragma warning(disable: 4996) // 'GetVersionExW': was declared deprecated
1449                                        GetVersionEx((OSVERSIONINFO*) &Version);
1450                                        #pragma warning(default: 4996)
1451                                        #pragma region Version
1452                                        CRoArrayT<CString> VersionArray;
1453                                        VersionArray.Add(AtlFormatString(_T("%s Build %s"), I(AtlFormatString(_T("%d.%d"), Version.dwMajorVersion, Version.dwMinorVersion)), I(Version.dwBuildNumber)));
1454                                        switch((Version.dwMajorVersion << 16) + Version.dwMinorVersion)
1455                                        {
1456                                        case 0x00050001: 
1457                                                VersionArray.Add(_T("Windows XP"));
1458                                                break;
1459                                        case 0x00050002: 
1460                                                if(Version.wProductType != VER_NT_WORKSTATION)
1461                                                        VersionArray.Add(_T("Windows Server 2003"));
1462                                                break;
1463                                        case 0x00060000: 
1464                                                if(Version.wProductType == VER_NT_WORKSTATION)
1465                                                        VersionArray.Add(_T("Windows Vista"));
1466                                                else
1467                                                        VersionArray.Add(_T("Windows Server 2008"));
1468                                                break;
1469                                        case 0x00060001: 
1470                                                if(Version.wProductType == VER_NT_WORKSTATION)
1471                                                        VersionArray.Add(_T("Windows 7"));
1472                                                else
1473                                                        VersionArray.Add(_T("Windows Server 2008 R2"));
1474                                                break;
1475                                        case 0x00060002: 
1476                                                if(Version.wProductType == VER_NT_WORKSTATION)
1477                                                        VersionArray.Add(_T("Windows 8"));
1478                                                else
1479                                                        VersionArray.Add(_T("Windows Server 2012"));
1480                                                break;
1481                                        }
1482                                        if(_tcslen(Version.szCSDVersion))
1483                                                VersionArray.Add(Version.szCSDVersion);
1484                                        if(Version.wServicePackMajor)
1485                                                VersionArray.Add(AtlFormatString(_T("Service Pack %s"), I(AtlFormatString(_T("%d.%d"), Version.wServicePackMajor, Version.wServicePackMinor))));
1486                                        //Version.wSuiteMask, Version.wProductType
1487                                        sText += AtlFormatString(_T(" * ") _T("Version: %s") _T("\r\n"), _StringHelper::Join(VersionArray, _T("; ")));
1488                                        #pragma endregion
1489                                        sText += AtlFormatString(_T(" * ") _T("Computer Name: %s") _T("\r\n"), I(GetComputerName()));
1490                                        TCHAR pszUserName[256] = { 0 };
1491                                        DWORD nUserNameLength = DIM(pszUserName);
1492                                        GetUserName(pszUserName, &nUserNameLength);
1493                                        CString sUserName(pszUserName);
1494                                        BOOL bAdministrator = FALSE;
1495                                        bool bIsMember = FALSE;
1496                                        if(CAccessToken().CheckTokenMembership(Sids::Admins(), &bIsMember) && bIsMember)
1497                                                bAdministrator = TRUE;
1498                                        sText += AtlFormatString(_T(" * ") _T("User Name: %s %s") _T("\r\n"), I(sUserName), bAdministrator ? _T("(Administrator)") : _T(""));
1499                                        SYSTEM_INFO SystemInformation;
1500                                        GetSystemInfo(&SystemInformation);
1501                                        #pragma region Architecture
1502                                        CString sArchitecture;
1503                                        switch(SystemInformation.wProcessorArchitecture)
1504                                        {
1505                                        case PROCESSOR_ARCHITECTURE_INTEL:
1506                                                sArchitecture = I(_T("x86"));
1507                                                break;
1508                                        case PROCESSOR_ARCHITECTURE_AMD64:
1509                                                sArchitecture = I(_T("AMD/Intel x64"));
1510                                                break;
1511                                        case PROCESSOR_ARCHITECTURE_IA64:
1512                                                sArchitecture = I(_T("Intel Itanium"));
1513                                                break;
1514                                        default:
1515                                                sArchitecture = I(SystemInformation.wProcessorArchitecture, _T("0x%04X"));
1516                                        }
1517                                        #if defined(_WIN64)
1518                                                sText += AtlFormatString(_T(" * ") _T("Architecture: %s (x64 Application)") _T("\r\n"), sArchitecture);
1519                                        #else
1520                                                sText += AtlFormatString(_T(" * ") _T("Architecture: %s") _T("\r\n"), sArchitecture);
1521                                        #endif // defined(_WIN64)
1522                                        #pragma endregion
1523                                        sText += AtlFormatString(_T(" * ") _T("Processors: %s, Active Mask %s") _T("\r\n"), I(SystemInformation.dwNumberOfProcessors), I((DWORD) SystemInformation.dwActiveProcessorMask, _T("0x%X")));
1524                                        sText += AtlFormatString(_T(" * ") _T("Page Size: %s") _T("\r\n"), I(SystemInformation.dwPageSize, _T("0x%X")));
1525                                        sText += AtlFormatString(_T(" * ") _T("Application Address Space: %s..%s") _T("\r\n"), I(SystemInformation.lpMinimumApplicationAddress), I(SystemInformation.lpMaximumApplicationAddress));
1526                                        #pragma region Memory
1527                                        MEMORYSTATUSEX MemoryStatus = { sizeof MemoryStatus };
1528                                        _W(GlobalMemoryStatusEx(&MemoryStatus));
1529                                        sText += AtlFormatString(_T(" * ") _T("Physical Memory: %s MB") _T("\r\n"), I(_StringHelper::FormatNumber((LONG) (MemoryStatus.ullTotalPhys >> 20))));
1530                                        sText += AtlFormatString(_T(" * ") _T("Committed Memory Limit: %s MB") _T("\r\n"), I(_StringHelper::FormatNumber((LONG) (MemoryStatus.ullTotalPageFile >> 20))));
1531                                        #pragma endregion
1532                                }
1533                                #pragma endregion
1534                                sText += AtlFormatString(_T(" * ") _T("Module Version: %s") _T("\r\n"), I(_VersionInfoHelper::GetVersionString(_VersionInfoHelper::GetFileVersion(_VersionInfoHelper::GetModulePath()))));
1535                                SYSTEMTIME LocalTime;
1536                                GetLocalTime(&LocalTime);
1537                                sText += AtlFormatString(_T(" * ") _T("Local Time: %s") _T("\r\n"), I(_StringHelper::FormatDateTime(&LocalTime)));
1538                                sText += _T("\r\n");
1539                                #undef I
1540                                m_BodyEdit.SetValue(sText);
1541                        }
1542                        VOID UpdateControls()
1543                        {
1544                                BOOL bAllowSend = TRUE;
1545                                if(m_ToEdit.GetValue().Trim().IsEmpty())
1546                                        bAllowSend = FALSE;
1547                                const INT nMethod = m_MethodComboBox.GetCurSel();
1548                                m_HostEdit.GetWindow(GW_HWNDPREV).EnableWindow(nMethod != 0); // Google Mail
1549                                m_HostEdit.EnableWindow(nMethod != 0); // Google Mail
1550                                m_UsernameEdit.GetWindow(GW_HWNDPREV).EnableWindow(nMethod != 5); // No Authentication
1551                                m_UsernameEdit.EnableWindow(nMethod != 5); // No Authentication
1552                                m_PasswordEdit.GetWindow(GW_HWNDPREV).EnableWindow(nMethod != 5); // No Authentication
1553                                m_PasswordEdit.EnableWindow(nMethod != 5); // No Authentication
1554                                if(nMethod != 0) // Google Mail
1555                                        if(m_HostEdit.GetValue().Trim().IsEmpty())
1556                                                bAllowSend = FALSE;
1557                                if(nMethod != 5) // No Authentication
1558                                {
1559                                        if(m_UsernameEdit.GetValue().Trim().IsEmpty())
1560                                                bAllowSend = FALSE;
1561                                        if(m_PasswordEdit.GetValue().Trim().IsEmpty())
1562                                                bAllowSend = FALSE;
1563                                }
1564                                m_SendButton.EnableWindow(bAllowSend);
1565                        }
1566                        static CString GetComputerName()
1567                        {
1568                                TCHAR pszComputerName[256] = { 0 };
1569                                DWORD nComputerNameLength = DIM(pszComputerName);
1570                                ::GetComputerName(pszComputerName, &nComputerNameLength);
1571                                return pszComputerName;
1572                        }
1573
1574                // Window Message Handler
1575                        LRESULT OnInitDialog(HWND, LPARAM lParam)
1576                        {
1577                                m_pOwner = (CPropertyFrameDialog*) lParam;
1578                                m_bActivating = TRUE;
1579                                _ATLTRY
1580                                {
1581                                        CWaitCursor WaitCursor;
1582                                        m_TitleStatic = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_TITLE);
1583                                        CreateTitleFont(m_TitleFont, m_TitleStatic);
1584                                        _W(m_FromEdit.SubclassWindow(GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_FROM)));
1585                                        m_ToEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_TO);
1586                                        m_MethodComboBox.Initialize(GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_METHOD));
1587                                        m_MethodComboBox.SetCurSel(0);
1588                                        m_HostEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_HOST);
1589                                        m_UsernameEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_USERNAME);
1590                                        m_PasswordEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_PASSWORD);
1591                                        m_BodyEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_BODY);
1592                                        m_BodyEdit.SetFont(m_pOwner->m_TextFont);
1593                                        m_SendButton = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_SEND);
1594                                        _W(m_CleanupStatic.SubclassWindow(GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_CLEANUP)));
1595                                        DlgResize_Init(FALSE, FALSE);
1596                                        InitializeControlsFromRegistry();
1597                                        InitializeBody();
1598                                        m_sFilterGraphText = m_pOwner->m_Owner.GetText();
1599                                        UpdateControls();
1600                                        m_bActivating = FALSE;
1601                                }
1602                                _ATLCATCH(Exception)
1603                                {
1604                                        for(CWindow Window = GetWindow(GW_CHILD); Window; Window = Window.GetWindow(GW_HWNDNEXT))
1605                                                Window.EnableWindow(FALSE);
1606                                        AtlExceptionMessageBox(m_hWnd, Exception);
1607                                }
1608                                return TRUE;
1609                        }
1610                        LRESULT OnDestroy()
1611                        {
1612                                return 0;
1613                        }
1614                        LRESULT OnShowWindow(BOOL bShowing, INT)
1615                        {
1616                                if(bShowing && !m_ChangeMap.Lookup(IDC_FILTERGRAPHHELPER_EMAIL_BODY))
1617                                        InitializeBody();
1618                                return 0;
1619                        }
1620                        LRESULT OnChanged(UINT, INT_PTR nIdentifier, HWND)
1621                        {
1622                                if(m_bActivating)
1623                                        return 0;
1624                                m_ChangeMap[nIdentifier] = TRUE;
1625                                UpdateControls();
1626                                return 0;
1627                        }
1628                        LRESULT OnChanged(NMHDR* pHeader)
1629                        {
1630                                return OnChanged(pHeader->code, pHeader->idFrom, pHeader->hwndFrom);
1631                        }
1632                        LRESULT OnFromEditPaste()
1633                        {
1634                                _ATLTRY
1635                                {
1636                                        CString sText;
1637                                        if(GetClipboardText(m_hWnd, sText))
1638                                        {
1639                                                const INT nLength = sText.GetLength();
1640                                                if(nLength >= 128 && nLength < 8192)
1641                                                {
1642                                                        sText.Trim();
1643                                                        const BOOL bResult = InitializeControlsFromMessageString(sText);
1644                                                        UpdateControls();
1645                                                        if(bResult)
1646                                                                return 0;
1647                                                }
1648                                        }
1649                                }
1650                                _ATLCATCHALL()
1651                                {
1652                                        MessageBeep(MB_ICONERROR);
1653                                }
1654                                return 0;
1655                        }
1656                        LRESULT OnSend(UINT, INT, HWND)
1657                        {
1658                                CWaitCursor WaitCursor;
1659                                CObjectPtr<CMessage> pMessage;
1660                                pMessage.Construct();
1661                                #pragma region Setup
1662                                pMessage->LoadTypeInfo(IDR_EMAILTOOLS);
1663                                __C(pMessage->put_Sender(CComBSTR(m_FromEdit.GetValue())));
1664                                __C(pMessage->put_ToRecipients(CComBSTR(m_ToEdit.GetValue())));
1665                                // NOTE:
1666                                // 0 Google Mail (SMTP, TLS Connection)
1667                                // 1 SMTP, TLS Connection, Plain Text Authentication (TLS, PLAIN)
1668                                // 2 SMTP, SSL Connection, Plain Text Authentication (SSL, PLAIN)
1669                                // 3 SMTP, Digest Authentication (CRAM-MD5)
1670                                // 4 SMTP, Plain Text Authentication (PLAIN)
1671                                // 5 SMTP, No Authentication
1672                                const INT nMethod = m_MethodComboBox.GetCurSel();
1673                                __C(pMessage->put_SecureSocketsLayer((nMethod == 2) ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE));
1674                                __C(pMessage->put_TransportLayerSecurity((nMethod < 2) ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE));
1675                                if(nMethod != 5)
1676                                {
1677                                        __C(pMessage->put_AuthMethods(CComBSTR(_T("plain"))));
1678                                        __C(pMessage->put_AuthName(CComBSTR(m_UsernameEdit.GetValue())));
1679                                        __C(pMessage->put_AuthPassword(CComBSTR(m_PasswordEdit.GetValue())));
1680                                }
1681                                switch(nMethod)
1682                                {
1683                                case 0:
1684                                        __C(pMessage->put_ServerHost(CComBSTR(_T("smtp.gmail.com"))));
1685                                        break;
1686                                default:
1687                                        CString sHost = m_HostEdit.GetValue();
1688                                        sHost.Trim();
1689                                        const INT nPortPosition = sHost.Find(_T(":"));
1690                                        if(nPortPosition >= 0)
1691                                        {
1692                                                INT nPort;
1693                                                __D(AtlStringToInteger(sHost.Mid(nPortPosition + 1), nPort), E_UNNAMED);
1694                                                __C(pMessage->put_ServerPort(nPort));
1695                                                sHost = sHost.Left(nPortPosition);
1696                                        }
1697                                        __C(pMessage->put_ServerHost(CComBSTR(sHost)));
1698                                        break;
1699                                }
1700                                switch(nMethod)
1701                                {
1702                                case 3:
1703                                        __C(pMessage->put_AuthMethods(CComBSTR(_T("cram-md5"))));
1704                                        break;
1705                                }
1706                                #pragma endregion
1707                                CStringA sMessageString = pMessage->GetAsString();
1708                                CString sText = m_BodyEdit.GetValue();
1709                                sText.TrimRight(_T("\t\n\r "));
1710                                sText += _T("\r\n") _T("\r\n") _T("* * *") _T("\r\n") _T("\r\n");
1711                                sText += m_sFilterGraphText;
1712                                __C(pMessage->put_Body(CComBSTR(sText)));
1713                                CString sSubject = AtlFormatString(_T("DirectShow Filter Graph from %s by %s"), GetComputerName(), AtlLoadString(IDS_PROJNAME));
1714                                __C(pMessage->put_Subject(CComBSTR(sSubject)));
1715                                #pragma region Attachment
1716                                CRoArrayT<CPath> DeletePathArray;
1717                                CRoArrayT<CString> FailurePathArray;
1718                                {
1719                                        CEmailLogDialog& EmailLogDialog = m_pOwner->m_EmailLogDialog;
1720                                        CRoArrayT<CEmailLogDialog::CSelectedFileData> Array;
1721                                        if(EmailLogDialog.GetFiles(Array))
1722                                        {
1723                                                const ULONGLONG nTruncateSize = EmailLogDialog.GetTruncateSize();
1724                                                const BOOL bDelete = EmailLogDialog.GetDelete();
1725                                                for(SIZE_T nIndex = 0; nIndex < Array.GetCount(); nIndex++)
1726                                                {
1727                                                        CEmailLogDialog::CSelectedFileData& FileData = Array[nIndex];
1728                                                        _ATLTRY
1729                                                        {
1730                                                                CLocalObjectPtr<CBzip2Item> pItem;
1731                                                                pItem->LoadFromFile(FileData.m_sPath, nTruncateSize);
1732                                                                CHeapPtr<BYTE> pnData;
1733                                                                SIZE_T nDataSize;
1734                                                                pItem->GetData(pnData, nDataSize);
1735                                                                if(nDataSize)
1736                                                                {
1737                                                                        CObjectPtr<CMessage::CComAttachment> pAttachment = pMessage->GetAttachments()->Add();
1738                                                                        _ATLTRY
1739                                                                        {
1740                                                                                pAttachment->SetType(L"application/bzip2");
1741                                                                                pAttachment->SetDisposition(L"attachment");
1742                                                                                pAttachment->SetName(CStringW(FileData.m_sName + _T(".bz2")));
1743                                                                                CLocalObjectPtr<CUnmanagedMemoryStream> pStream;
1744                                                                                pStream->Initialize(pnData, nDataSize);
1745                                                                                pAttachment->LoadFromStream(pStream);
1746                                                                        }
1747                                                                        _ATLCATCHALL()
1748                                                                        {
1749                                                                                _V(pMessage->GetAttachments()->Remove(pAttachment));
1750                                                                                _ATLRETHROW;
1751                                                                        }
1752                                                                }
1753                                                                if(bDelete)
1754                                                                        DeletePathArray.Add(FileData.m_sPath);
1755                                                        }
1756                                                        _ATLCATCHALL()
1757                                                        {
1758                                                                _Z_EXCEPTION();
1759                                                                FailurePathArray.Add((LPCTSTR) FileData.m_sPath);
1760                                                        }
1761                                                }
1762                                        }
1763                                }
1764                                #pragma endregion
1765                                __C(pMessage->Send());
1766                                for(SIZE_T nIndex = 0; nIndex < DeletePathArray.GetCount(); nIndex++)
1767                                        DeleteFile(DeletePathArray[nIndex]);
1768                                _RegKeyHelper::SetStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, _T("Email Message Template"), CString(sMessageString));
1769                                if(!FailurePathArray.IsEmpty())
1770                                {
1771                                        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")));
1772                                        AtlMessageBoxEx(m_hWnd, (LPCTSTR) sMessage, IDS_WARNING, MB_ICONWARNING | MB_OK);
1773                                }
1774                                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);
1775                                MessageBeep(MB_OK);
1776                                return 0;
1777                        }
1778                        LRESULT OnCleanupStaticAnchorClicked(NMHDR*)
1779                        {
1780                                _RegKeyHelper::DeleteValue(HKEY_CURRENT_USER, REGISTRY_ROOT, _T("Email Message Template"));
1781                                AtlOptionalMessageBoxEx(m_hWnd, _T("CFilterGraphHelper::CPropertyFrameDialog::CEmailDialog::SavedCredentialsDeleted"), _T("Cached email credentials were removed from registry."), IDS_INFORMATION, MB_ICONINFORMATION | MB_OK);
1782                                MessageBeep(MB_OK);
1783                                return 0;
1784                        }
1785                };
1786
1787                ////////////////////////////////////////////////////
1788                // CData
1789
1790                class CData
1791                {
1792                public:
1793
1794                        /////////////////////////////////////////////////////////
1795                        // TYPE
1796
1797                        typedef enum _TYPE
1798                        {
1799                                TYPE_UNKNOWN = 0,
1800                                TYPE_FILTERS,
1801                                TYPE_FILTER,
1802                                TYPE_FILTERPROPERTYPAGE,
1803                                TYPE_SERVICES,
1804                                TYPE_SERVICEPROPERTYPAGE,
1805                                TYPE_MEMORYALLOCATOR,
1806                                TYPE_ACTION,
1807                                TYPE_EMAIL,
1808                                TYPE_EMAIL_LOG,
1809                        } TYPE;
1810
1811                public:
1812                        TYPE m_Type;
1813                        CComPtr<IBaseFilter> m_pBaseFilter;
1814                        CLSID m_BaseFilterClassIdentifier;
1815                        CString m_sBaseFilterClassDescription;
1816                        CString m_sBaseFilterModulePath;
1817                        CLSID m_PropertyPageClassIdentifier;
1818                        CComPtr<IPropertyPage> m_pPropertyPage;
1819                        CObjectPtr<CPropertyPageSite> m_pSite;
1820                        BOOL m_bSiteActivated;
1821
1822                public:
1823                // CData
1824                        CData(TYPE Type = TYPE_UNKNOWN) :
1825                                m_Type(Type),
1826                                m_BaseFilterClassIdentifier(CLSID_NULL),
1827                                m_PropertyPageClassIdentifier(CLSID_NULL)
1828                        {
1829                        }
1830                        CData(IBaseFilter* pBaseFilter) :
1831                                m_Type(TYPE_FILTER),
1832                                m_pBaseFilter(pBaseFilter),
1833                                m_BaseFilterClassIdentifier(CLSID_NULL),
1834                                m_PropertyPageClassIdentifier(CLSID_NULL)
1835                        {
1836                                _ATLTRY
1837                                {
1838                                        CLSID ClassIdentifier = CLSID_NULL;
1839                                        if(SUCCEEDED(pBaseFilter->GetClassID(&ClassIdentifier)) && ClassIdentifier != CLSID_NULL)
1840                                        {
1841                                                m_BaseFilterClassIdentifier = ClassIdentifier;
1842                                                const CString sClassIdentifier(_PersistHelper::StringFromIdentifier(ClassIdentifier));
1843                                                m_sBaseFilterClassDescription = _RegKeyHelper::QueryStringValue(HKEY_CLASSES_ROOT, AtlFormatString(_T("CLSID\\%s"), sClassIdentifier));
1844                                                m_sBaseFilterModulePath = _RegKeyHelper::QueryStringValue(HKEY_CLASSES_ROOT, AtlFormatString(_T("CLSID\\%s\\InprocServer32"), sClassIdentifier));
1845                                        }
1846                                }
1847                                _ATLCATCHALL()
1848                                {
1849                                        _Z_EXCEPTION();
1850                                }
1851                        }
1852                        CData(IBaseFilter* pBaseFilter, const CLSID& PropertyPageClassIdentifier, IPropertyPage* pPropertyPage) :
1853                                m_Type(TYPE_FILTERPROPERTYPAGE),
1854                                m_pBaseFilter(pBaseFilter),
1855                                m_BaseFilterClassIdentifier(CLSID_NULL),
1856                                m_PropertyPageClassIdentifier(PropertyPageClassIdentifier),
1857                                m_pPropertyPage(pPropertyPage),
1858                                m_bSiteActivated(FALSE)
1859                        {
1860                                _A(pPropertyPage);
1861                        }
1862                        CData(IPropertyPage* pPropertyPage) :
1863                                m_Type(TYPE_SERVICEPROPERTYPAGE),
1864                                m_BaseFilterClassIdentifier(CLSID_NULL),
1865                                m_PropertyPageClassIdentifier(CLSID_NULL),
1866                                m_pPropertyPage(pPropertyPage),
1867                                m_bSiteActivated(FALSE)
1868                        {
1869                                _A(pPropertyPage);
1870                        }
1871                        CString GetPropertyPageTitle() const
1872                        {
1873                                if(!m_pPropertyPage)
1874                                        return _T("");
1875                                PROPPAGEINFO PageInformation;
1876                                ZeroMemory(&PageInformation, sizeof PageInformation);
1877                                PageInformation.cb = sizeof PageInformation;
1878                                __C(m_pPropertyPage->GetPageInfo(&PageInformation));
1879                                CString sTitle(PageInformation.pszTitle);
1880                                CoTaskMemFree(PageInformation.pszTitle);
1881                                CoTaskMemFree(PageInformation.pszDocString);
1882                                CoTaskMemFree(PageInformation.pszHelpFile);
1883                                return sTitle;
1884                        }
1885                };
1886
1887                ////////////////////////////////////////////////////
1888                // CObjectPropertyPage
1889
1890                class CObjectPropertyPage
1891                {
1892                public:
1893                        CComPtr<IUnknown> m_pUnknown;
1894                        CComPtr<IPropertyPage> m_pPropertyPage;
1895
1896                public:
1897                // CObjectPropertyPage
1898                        CObjectPropertyPage()
1899                        {
1900                        }
1901                        CObjectPropertyPage(IUnknown* pUnknown, IPropertyPage* pPropertyPage) :
1902                                m_pUnknown(pUnknown),
1903                                m_pPropertyPage(pPropertyPage)
1904                        {
1905                        }
1906                };
1907
1908                typedef CRoArrayT<CObjectPropertyPage> CObjectPropertyPageArray;
1909
1910        private:
1911                CFilterGraphHelper& m_Owner;
1912                BOOL m_bActivating; 
1913                CRoTreeViewT<CData, CRoListControlDataTraitsT> m_TreeView;
1914                CTreeItem m_FiltersItem;
1915                CTreeItem m_MemoryAllocatorItem;
1916                CTreeItem m_ActionItem;
1917                CTreeItem m_EmailItem;
1918                CTreeItem m_EmailLogItem;
1919                CTabCtrl m_Tab;
1920                CRoEdit m_TextEdit;
1921                CRect m_TextPosition;
1922                CFont m_TextFont;
1923                CRoHyperStatic m_RefreshStatic;
1924                CRoHyperStatic m_CopyStatic;
1925                CRoHyperStatic m_SaveAsStatic;
1926                CButton m_OkButton;
1927                CButton m_CancelButton;
1928                CButton m_ApplyButton;
1929                CObjectPtr<CPropertyPageSite> m_pCurrentSite;
1930                CMemoryAllocatorDialog m_MemoryAllocatorDialog;
1931                CActionDialog m_ActionDialog;
1932                CEmailDialog m_EmailDialog;
1933                CEmailLogDialog m_EmailLogDialog;
1934
1935                static VOID CreateTitleFont(CFont& Font, HWND hStaticWindow = NULL)
1936                {
1937                        _A(!Font);
1938                        CLogFont LogFont;
1939                        LogFont.SetHeight(12);
1940                        LogFont.lfWeight = FW_BOLD;
1941                        _tcsncpy_s(LogFont.lfFaceName, _T("Verdana"), _TRUNCATE);
1942                        _W(Font.CreateFontIndirect(&LogFont));
1943                        if(hStaticWindow)
1944                                CStatic(hStaticWindow).SetFont(Font);
1945                }
1946                VOID ShowText(BOOL bVisible, BOOL bStaticVisible = FALSE)
1947                {
1948                        m_TextEdit.ShowWindow(bVisible ? SW_SHOW : SW_HIDE);
1949                        bStaticVisible &= bVisible;
1950                        m_RefreshStatic.ShowWindow(bStaticVisible ? SW_SHOW : SW_HIDE);
1951                        m_CopyStatic.ShowWindow(bStaticVisible ? SW_SHOW : SW_HIDE);
1952                        m_SaveAsStatic.ShowWindow(bStaticVisible ? SW_SHOW : SW_HIDE);
1953                }
1954
1955        public:
1956        // CPropertyFrameDialog
1957                CPropertyFrameDialog(CFilterGraphHelper* pOwner) :
1958                        m_Owner(*pOwner)
1959                {
1960                }
1961                CRect GetTextEditPosition() const
1962                {
1963                        CRect Position;
1964                        _W(m_TextEdit.GetWindowRect(Position));
1965                        _W(ScreenToClient(Position));
1966                        return Position;
1967                }
1968                VOID UpdateTree()
1969                {
1970                        CWindowRedraw TreeViewRedraw(m_TreeView);
1971                        m_TreeView.DeleteAllItems();
1972                        CTreeItem LastItem;
1973                        #pragma region Filter
1974                        CTreeItem FiltersItem = m_TreeView.InsertItem(NULL, NULL, CData(CData::TYPE_FILTERS), _T("Filters"));
1975                        _FilterGraphHelper::CFilterArray FilterArray;
1976                        _FilterGraphHelper::GetGraphFilters(m_Owner.m_pFilterGraph, FilterArray);
1977                        CTreeItem PreviousFilterItem;
1978                        for(SIZE_T nIndex = 0; nIndex < FilterArray.GetCount(); nIndex++)
1979                        {
1980                                const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nIndex];
1981                                CData Data(pBaseFilter);
1982                                CString sText(_FilterGraphHelper::GetFilterName(pBaseFilter));
1983                                if(!Data.m_sBaseFilterClassDescription.IsEmpty() && sText.Find(Data.m_sBaseFilterClassDescription) < 0)
1984                                        sText += AtlFormatString(_T(" (%s)"), Data.m_sBaseFilterClassDescription);
1985                                CTreeItem FilterItem = m_TreeView.InsertItem(FiltersItem, PreviousFilterItem, Data, sText);
1986                                PreviousFilterItem = FilterItem;
1987                                #pragma region Property Page
1988                                const CComQIPtr<ISpecifyPropertyPages> pSpecifyPropertyPages = pBaseFilter;
1989                                if(!pSpecifyPropertyPages)
1990                                        continue;
1991                                _ATLTRY
1992                                {
1993                                        CAUUID Pages;
1994                                        ZeroMemory(&Pages, sizeof Pages);
1995                                        __C(pSpecifyPropertyPages->GetPages(&Pages));
1996                                        CComHeapPtr<CLSID> pClassIdentifiers;
1997                                        pClassIdentifiers.Attach(Pages.pElems);
1998                                        CTreeItem PreviousPageItem;
1999                                        for(UINT nPageIndex = 0; nPageIndex < Pages.cElems; nPageIndex++)
2000                                        {
2001                                                const CLSID& ClassIdentifier = pClassIdentifiers[nPageIndex];
2002                                                if(ClassIdentifier == CLSID_NULL)
2003                                                        continue; // Fake
2004                                                _ATLTRY
2005                                                {
2006                                                        CComPtr<IPropertyPage> pPropertyPage;
2007                                                        const HRESULT nCoCreateInstanceResult = pPropertyPage.CoCreateInstance(ClassIdentifier);
2008                                                        _A(SUCCEEDED(nCoCreateInstanceResult) || nCoCreateInstanceResult == REGDB_E_CLASSNOTREG);
2009                                                        if(nCoCreateInstanceResult == REGDB_E_CLASSNOTREG)
2010                                                                continue; // Missing [Optional] Page
2011                                                        __C(nCoCreateInstanceResult);
2012                                                        CData Data(pBaseFilter, ClassIdentifier, pPropertyPage);
2013                                                        Data.m_pSite.Construct()->Initialize(this, pBaseFilter, pPropertyPage);
2014                                                        CTreeItem PageItem = m_TreeView.InsertItem(FilterItem, PreviousPageItem, Data, Data.GetPropertyPageTitle());
2015                                                        PreviousPageItem = PageItem;
2016                                                }
2017                                                _ATLCATCHALL()
2018                                                {
2019                                                        _Z_EXCEPTION();
2020                                                }
2021                                        }
2022                                        m_TreeView.Expand(FilterItem);
2023                                }
2024                                _ATLCATCHALL()
2025                                {
2026                                        _Z_EXCEPTION();
2027                                }
2028                                #pragma endregion
2029                        }
2030                        m_TreeView.Expand(FiltersItem);
2031                        m_FiltersItem.m_hTreeItem = FiltersItem;
2032                        m_FiltersItem.m_pTreeView = &m_TreeView;
2033                        LastItem = FiltersItem;
2034                        #pragma endregion
2035                        #pragma region Services
2036                        _ATLTRY
2037                        {
2038                                CObjectPropertyPageArray ObjectPropertyPageArray;
2039                                const CComQIPtr<IServiceProvider> pServiceProvider = m_Owner.m_pFilterGraph;
2040                                if(pServiceProvider)
2041                                {
2042                                        #pragma region RunPropertyBagAware
2043                                        CComPtr<IRunPropertyBagAware> pRunPropertyBagAware;
2044                                        if(SUCCEEDED(pServiceProvider->QueryService<IRunPropertyBagAware>(__uuidof(IRunPropertyBagAware), &pRunPropertyBagAware)))
2045                                                _ATLTRY
2046                                                {
2047                                                        _A(pRunPropertyBagAware);
2048                                                        CObjectPtr<CRunPropertyBagPropertyPage> pRunPropertyBagPropertyPage;
2049                                                        pRunPropertyBagPropertyPage.Construct();
2050                                                        ObjectPropertyPageArray.Add(CObjectPropertyPage(pRunPropertyBagAware, pRunPropertyBagPropertyPage));
2051                                                }
2052                                                _ATLCATCHALL()
2053                                                {
2054                                                        _Z_EXCEPTION();
2055                                                }
2056                                        #pragma endregion
2057                                        #pragma region RunEventAware
2058                                        CComPtr<IRunEventAware> pRunEventAware;
2059                                        if(SUCCEEDED(pServiceProvider->QueryService<IRunEventAware>(__uuidof(IRunEventAware), &pRunEventAware)))
2060                                                _ATLTRY
2061                                                {
2062                                                        _A(pRunEventAware);
2063                                                        CObjectPtr<CRunEventPropertyPage> pRunEventPropertyPage;
2064                                                        pRunEventPropertyPage.Construct();
2065                                                        ObjectPropertyPageArray.Add(CObjectPropertyPage(pRunEventAware, pRunEventPropertyPage));
2066                                                }
2067                                                _ATLCATCHALL()
2068                                                {
2069                                                        _Z_EXCEPTION();
2070                                                }
2071                                        #pragma endregion
2072                                }
2073                                if(!ObjectPropertyPageArray.IsEmpty())
2074                                {
2075                                        CTreeItem ServicesItem = m_TreeView.InsertItem(NULL, LastItem, CData(CData::TYPE_SERVICES), _T("Services"));
2076                                        LastItem = ServicesItem;
2077                                        CTreeItem PreviousServiceItem;
2078                                        for(auto&& ObjectPropertyPage: ObjectPropertyPageArray)
2079                                        {
2080                                                CData Data(ObjectPropertyPage.m_pPropertyPage);
2081                                                Data.m_pSite.Construct()->Initialize(this, ObjectPropertyPage.m_pUnknown, ObjectPropertyPage.m_pPropertyPage);
2082                                                CTreeItem ServiceItem = m_TreeView.InsertItem(ServicesItem, PreviousServiceItem, Data, Data.GetPropertyPageTitle());
2083                                                PreviousServiceItem = ServiceItem;
2084                                        }
2085                                        m_TreeView.Expand(ServicesItem);
2086                                }
2087                        }
2088                        _ATLCATCHALL()
2089                        {
2090                                _Z_EXCEPTION();
2091                        }
2092                        #pragma endregion
2093                        #pragma region Other
2094                        CTreeItem MemoryAllocatorItem = m_TreeView.InsertItem(NULL, LastItem, CData(CData::TYPE_MEMORYALLOCATOR), _T("Memory Allocators"));
2095                        m_MemoryAllocatorItem.m_hTreeItem = MemoryAllocatorItem;
2096                        m_MemoryAllocatorItem.m_pTreeView = &m_TreeView;
2097                        CTreeItem ActionItem = m_TreeView.InsertItem(NULL, MemoryAllocatorItem, CData(CData::TYPE_ACTION), _T("Action"));
2098                        m_ActionItem.m_hTreeItem = ActionItem;
2099                        m_ActionItem.m_pTreeView = &m_TreeView;
2100                        CTreeItem EmailItem = m_TreeView.InsertItem(NULL, ActionItem, CData(CData::TYPE_EMAIL), _T("Email"));
2101                        m_EmailItem.m_hTreeItem = EmailItem;
2102                        m_EmailItem.m_pTreeView = &m_TreeView;
2103                        CTreeItem EmailLogItem = m_TreeView.InsertItem(EmailItem, NULL, CData(CData::TYPE_EMAIL_LOG), _T("Log Files"));
2104                        m_EmailLogItem.m_hTreeItem = EmailLogItem;
2105                        m_EmailLogItem.m_pTreeView = &m_TreeView;
2106                        #pragma endregion
2107                        m_TreeView.Expand(EmailItem);
2108                }
2109                VOID HideCurrentSite()
2110                {
2111                        if(!m_pCurrentSite)
2112                                return;
2113                        if(m_pCurrentSite->m_pPropertyPage)
2114                                __C(m_pCurrentSite->m_pPropertyPage->Show(SW_HIDE));
2115                        m_pCurrentSite.Release();
2116                }
2117                VOID HandleStatusChange(CPropertyPageSite* pPropertyPageSite)
2118                {
2119                        _A(pPropertyPageSite);
2120                        m_ApplyButton.EnableWindow(pPropertyPageSite->IsDirty());
2121                }
2122                VOID Apply()
2123                {
2124                        if(!m_pCurrentSite || !m_pCurrentSite->m_pPropertyPage)
2125                                return;
2126                        __C(m_pCurrentSite->m_pPropertyPage->Apply());
2127                        HandleStatusChange(m_pCurrentSite);
2128                }
2129                INT_PTR DoModal(HWND hParentWindow = GetActiveWindow())
2130                {
2131                        return CDialogWithAccelerators::DoModal(hParentWindow);
2132                }
2133
2134        // CDialogResize
2135                VOID DlgResize_UpdateLayout(INT nWidth, INT nHeight)
2136                {
2137                        __super::DlgResize_UpdateLayout(nWidth, nHeight);
2138                        const CRect Position = GetTextEditPosition();
2139                        if(m_pCurrentSite && m_pCurrentSite->m_pPropertyPage)
2140                                _V(m_pCurrentSite->m_pPropertyPage->Move(Position));
2141                        _W(m_MemoryAllocatorDialog.SetWindowPos(NULL, Position, SWP_NOZORDER | SWP_NOACTIVATE));
2142                        _W(m_ActionDialog.SetWindowPos(NULL, Position, SWP_NOZORDER | SWP_NOACTIVATE));
2143                        _W(m_EmailDialog.SetWindowPos(NULL, Position, SWP_NOZORDER | SWP_NOACTIVATE));
2144                        _W(m_EmailLogDialog.SetWindowPos(NULL, Position, SWP_NOZORDER | SWP_NOACTIVATE));
2145                }
2146
2147        // CDialogWithAcceleratorsT
2148                BOOL TranslateAccelerator(MSG* pMessage)
2149                {
2150                        CTreeItem TreeItem = m_TreeView.GetSelectedItem();
2151                        if(TreeItem)
2152                        {
2153                                CData& Data = m_TreeView.GetItemData(TreeItem);
2154                                if(Data.m_Type == CData::TYPE_FILTERPROPERTYPAGE)
2155                                {
2156                                        if(Data.m_pPropertyPage)
2157                                                if(Data.m_pPropertyPage->TranslateAccelerator(pMessage) == S_OK)
2158                                                        return TRUE;
2159                                }
2160                        }
2161                        return __super::TranslateAccelerator(pMessage);
2162                }
2163
2164        // Window Message Handler
2165                LRESULT OnInitDialog(HWND, LPARAM)
2166                {
2167                        m_bActivating = TRUE;
2168                        _ATLTRY
2169                        {
2170                                CWaitCursor WaitCursor;
2171                                CAboutDialog::UpdateCaption(*this);
2172                                #pragma region System Menu
2173                                CMenuHandle Menu = GetSystemMenu(FALSE);
2174                                _W(Menu.AppendMenu(MF_SEPARATOR));
2175                                _W(Menu.AppendMenu(MF_STRING, ID_APP_ABOUT, _T("&About...")));
2176                                #pragma endregion
2177                                #pragma region Icon
2178                                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_COLOR, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)), TRUE);
2179                                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_COLOR, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)), FALSE);
2180                                #pragma endregion
2181                                m_TreeView.Initialize(GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TREE));
2182                                m_TextEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TEXT);
2183                                CRect TextPosition;
2184                                _W(m_TextEdit.GetWindowRect(TextPosition));
2185                                _W(ScreenToClient(TextPosition));
2186                                m_TextPosition = TextPosition;
2187                                CLogFont TextFont;
2188                                CFontHandle(AtlGetDefaultGuiFont()).GetLogFont(TextFont);
2189                                _tcsncpy_s(TextFont.lfFaceName, _T("Courier New"), _TRUNCATE);
2190                                TextFont.SetHeight(8);
2191                                m_TextFont = TextFont.CreateFontIndirect();
2192                                m_TextEdit.SetFont(m_TextFont);
2193                                m_RefreshStatic.SubclassWindow(GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_REFRESH));
2194                                m_CopyStatic.SubclassWindow(GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_COPY));
2195                                m_SaveAsStatic.SubclassWindow(GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_SAVEAS));
2196                                CRoHyperStatic::ArrangeHorizontally(&m_RefreshStatic, &m_CopyStatic, &m_SaveAsStatic, NULL);
2197                                m_OkButton = GetDlgItem(IDOK);
2198                                m_CancelButton = GetDlgItem(IDCANCEL);
2199                                m_ApplyButton = GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_APPLY);
2200                                __E(m_MemoryAllocatorDialog.Create(m_hWnd, (LPARAM) this));
2201                                __E(m_ActionDialog.Create(m_hWnd, (LPARAM) this));
2202                                __E(m_EmailDialog.Create(m_hWnd, (LPARAM) this));
2203                                __E(m_EmailLogDialog.Create(m_hWnd, (LPARAM) this));
2204                                DlgResize_Init(TRUE);
2205                                UpdateTree();
2206                                m_FiltersItem.Select();
2207                                m_FiltersItem.EnsureVisible();
2208                                CRect Position;
2209                                _W(GetWindowRect(Position));
2210                                Position.right += Position.Width() / 2;
2211                                Position.bottom += Position.Width() / 4;
2212                                _W(SetWindowPos(NULL, Position, SWP_NOMOVE | SWP_NOZORDER));
2213                                _W(CenterWindow());
2214                                m_bActivating = FALSE;
2215                        }
2216                        _ATLCATCH(Exception)
2217                        {
2218                                for(CWindow Window = GetWindow(GW_CHILD); Window; Window = Window.GetWindow(GW_HWNDNEXT))
2219                                        Window.EnableWindow(FALSE);
2220                                AtlExceptionMessageBox(m_hWnd, Exception);
2221                        }
2222                        return TRUE;
2223                }
2224                LRESULT OnDestroy()
2225                {
2226                        #pragma region Deactivate and Terminate Sites
2227                        for(POSITION Position = m_TreeView.GetDataList().GetHeadPosition(); Position; m_TreeView.GetDataList().GetNext(Position))
2228                        {
2229                                CData& Data = m_TreeView.GetDataList().GetAt(Position);
2230                                if(!Data.m_pSite)
2231                                        continue;
2232                                if(Data.m_bSiteActivated)
2233                                {
2234                                        const HRESULT nDeactivateResult = Data.m_pPropertyPage->Deactivate();
2235                                        _Z35_DSHRESULT(nDeactivateResult);
2236                                        Data.m_bSiteActivated = FALSE;
2237                                }
2238                                Data.m_pSite->Terminate();
2239                        }
2240                        #pragma endregion
2241                        return 0;
2242                }
2243                LRESULT OnTreeViewGetInfoTip(NMTVGETINFOTIP* pHeader)
2244                {
2245                        _A(pHeader);
2246                        if(!pHeader->hItem) 
2247                                return 0;
2248                        CData& Data = m_TreeView.GetItemData(pHeader->hItem);
2249                        CString sInfoTip;
2250                        if(Data.m_pBaseFilter)
2251                        {
2252                                if(!Data.m_pPropertyPage)
2253                                {
2254                                        sInfoTip.AppendFormat(_T("Name: %ls") _T("\r\n"), _FilterGraphHelper::GetFilterName(Data.m_pBaseFilter));
2255                                        if(Data.m_BaseFilterClassIdentifier != CLSID_NULL)
2256                                                sInfoTip.AppendFormat(_T("Class Identifier: %ls") _T("\r\n"), _PersistHelper::StringFromIdentifier(Data.m_BaseFilterClassIdentifier));
2257                                        if(!Data.m_sBaseFilterClassDescription.IsEmpty())
2258                                                sInfoTip.AppendFormat(_T("Class Description: %s") _T("\r\n"), Data.m_sBaseFilterClassDescription);
2259                                        if(!Data.m_sBaseFilterModulePath.IsEmpty())
2260                                                sInfoTip.AppendFormat(_T("Module Path: %s") _T("\r\n"), Data.m_sBaseFilterModulePath);
2261                                } else
2262                                {
2263                                        // TODO: ...
2264                                }
2265                        }
2266                        sInfoTip.TrimRight(_T("\t\n\r "));
2267                        _tcsncpy_s(pHeader->pszText, pHeader->cchTextMax, sInfoTip, _TRUNCATE);
2268                        #pragma region Clipboard Copy
2269                        if(GetKeyState(VK_CONTROL) < 0 && GetKeyState(VK_SHIFT) < 0)
2270                                _ATLTRY
2271                                {
2272                                        SetClipboardText(m_hWnd, sInfoTip);
2273                                        MessageBeep(MB_OK);
2274                                }
2275                                _ATLCATCHALL()
2276                                {
2277                                        _Z_EXCEPTION();
2278                                        MessageBeep(MB_ICONERROR);
2279                                }
2280                        #pragma endregion
2281                        return 0;
2282                }
2283                LRESULT OnTreeViewSelChanged(NMTREEVIEW* pHeader)
2284                {
2285                        _A(pHeader);
2286                        #pragma region Tree Item
2287                        CTreeItem TreeItem(pHeader->itemNew.hItem);
2288                        if(TreeItem)
2289                        {
2290                                CData& Data = m_TreeView.GetItemData(TreeItem);
2291                                if(Data.m_Type != CData::TYPE_MEMORYALLOCATOR)
2292                                        m_MemoryAllocatorDialog.ShowWindow(SW_HIDE);
2293                                if(Data.m_Type != CData::TYPE_ACTION)
2294                                        m_ActionDialog.ShowWindow(SW_HIDE);
2295                                if(Data.m_Type != CData::TYPE_EMAIL)
2296                                        m_EmailDialog.ShowWindow(SW_HIDE);
2297                                if(Data.m_Type != CData::TYPE_EMAIL_LOG)
2298                                        m_EmailLogDialog.ShowWindow(SW_HIDE);
2299                                #pragma region Filter
2300                                if(Data.m_pBaseFilter)
2301                                {
2302                                        #pragma region Property Page
2303                                        if(Data.m_pPropertyPage)
2304                                        {
2305                                                ShowText(FALSE);
2306                                                if(Data.m_pSite != m_pCurrentSite)
2307                                                        HideCurrentSite();
2308                                                if(!Data.m_bSiteActivated)
2309                                                {
2310                                                        __C(Data.m_pPropertyPage->Activate(m_hWnd, GetTextEditPosition(), TRUE));
2311                                                        Data.m_bSiteActivated = TRUE;
2312                                                } else
2313                                                        __C(Data.m_pPropertyPage->Move(GetTextEditPosition()));
2314                                                __C(Data.m_pPropertyPage->Show(SW_SHOWNORMAL));
2315                                                m_pCurrentSite = Data.m_pSite;
2316                                                HandleStatusChange(m_pCurrentSite);
2317                                        } else
2318                                        #pragma endregion
2319                                        #pragma region Text
2320                                        {
2321                                                CWaitCursor WaitCursor;
2322                                                HideCurrentSite();
2323                                                ShowText(TRUE, FALSE);
2324                                                CString sText;
2325                                                sText += AtlFormatString(_T("## ") _T("Filter %ls") _T("\r\n") _T("\r\n"), _FilterGraphHelper::GetFilterName(Data.m_pBaseFilter));
2326                                                sText += m_Owner.GetFilterText(Data.m_pBaseFilter);
2327                                                sText += _T("\r\n");
2328                                                #pragma region Connection
2329                                                _FilterGraphHelper::CPinArray InputPinArray, OutputPinArray;
2330                                                _FilterGraphHelper::GetFilterPins(Data.m_pBaseFilter, PINDIR_INPUT, InputPinArray);
2331                                                _FilterGraphHelper::GetFilterPins(Data.m_pBaseFilter, PINDIR_OUTPUT, OutputPinArray);
2332                                                if(!InputPinArray.IsEmpty() || !OutputPinArray.IsEmpty())
2333                                                {
2334                                                        sText += AtlFormatString(_T("## ") _T("Connections") _T("\r\n") _T("\r\n"));
2335                                                        if(!InputPinArray.IsEmpty())
2336                                                        {
2337                                                                sText += AtlFormatString(_T("### ") _T("Input") _T("\r\n") _T("\r\n"));
2338                                                                for(SIZE_T nPinIndex = 0; nPinIndex < InputPinArray.GetCount(); nPinIndex++)
2339                                                                {
2340                                                                        const CComPtr<IPin>& pInputPin = InputPinArray[nPinIndex];
2341                                                                        const CComPtr<IPin> pOutputPin = _FilterGraphHelper::GetPeerPin(pInputPin);
2342                                                                        if(!pOutputPin)
2343                                                                                continue;
2344                                                                        sText += AtlFormatString(_T(" * ") _T("%s") _T("\r\n"), m_Owner.GetConnectionText(pOutputPin, pInputPin));
2345                                                                }
2346                                                                sText += _T("\r\n");
2347                                                        }
2348                                                        if(!OutputPinArray.IsEmpty())
2349                                                        {
2350                                                                sText += AtlFormatString(_T("### ") _T("Output") _T("\r\n") _T("\r\n"));
2351                                                                for(SIZE_T nPinIndex = 0; nPinIndex < OutputPinArray.GetCount(); nPinIndex++)
2352                                                                {
2353                                                                        const CComPtr<IPin>& pOutputPin = OutputPinArray[nPinIndex];
2354                                                                        const CComPtr<IPin> pInputPin = _FilterGraphHelper::GetPeerPin(pOutputPin);
2355                                                                        if(!pInputPin)
2356                                                                                continue;
2357                                                                        sText += AtlFormatString(_T(" * ") _T("%s") _T("\r\n"), m_Owner.GetConnectionText(pOutputPin, pInputPin));
2358                                                                }
2359                                                                sText += _T("\r\n");
2360                                                        }
2361                                                }
2362                                                #pragma endregion
2363                                                #pragma region Media Type
2364                                                _FilterGraphHelper::CPinArray PinArray;
2365                                                if(_FilterGraphHelper::GetFilterPins(Data.m_pBaseFilter, PinArray))
2366                                                {
2367                                                        sText += AtlFormatString(_T("## ") _T("Media Types") _T("\r\n") _T("\r\n"));
2368                                                        for(SIZE_T nPinIndex = 0; nPinIndex < PinArray.GetCount(); nPinIndex++)
2369                                                        {
2370                                                                const CComPtr<IPin>& pPin = PinArray[nPinIndex];
2371                                                                CString sPinText = AtlFormatString(_T("%s"), FormatIdentifier(_FilterGraphHelper::GetPinFullName(pPin)));
2372                                                                const CComPtr<IPin> pPeerPin = _FilterGraphHelper::GetPeerPin(pPin);
2373                                                                if(pPeerPin)
2374                                                                        sPinText += AtlFormatString(_T(", %s"), FormatIdentifier(_FilterGraphHelper::GetPinFullName(pPeerPin)));
2375                                                                sText += AtlFormatString(_T("%d. ") _T("%s") _T("\r\n"), 1 + nPinIndex, sPinText);
2376                                                                _ATLTRY
2377                                                                {
2378                                                                        CMediaType pMediaType;
2379                                                                        if(pPeerPin)
2380                                                                                pMediaType = _FilterGraphHelper::GetPinMediaType(pPin);
2381                                                                        else
2382                                                                                pMediaType = _FilterGraphHelper::EnumerateFirstPinMediaType(pPin);
2383                                                                        if(!pMediaType)
2384                                                                                continue;
2385                                                                        sText += m_Owner.GetMediaTypeText(pMediaType);
2386                                                                }
2387                                                                _ATLCATCHALL()
2388                                                                {
2389                                                                        _Z_EXCEPTION();
2390                                                                }
2391                                                        }
2392                                                        sText += _T("\r\n");
2393                                                }
2394                                                #pragma endregion
2395                                                #pragma region Runtime Property Bag
2396                                                _ATLTRY
2397                                                {
2398                                                        const CString sPropertyBagText = CRunPropertyBagHelper::GetPropertyBagText(Data.m_pBaseFilter, CComQIPtr<ISpy>(m_Owner.m_pFilterGraph));
2399                                                        if(!sPropertyBagText.IsEmpty())
2400                                                        {
2401                                                                sText += AtlFormatString(_T("## ") _T("Runtime Properties") _T("\r\n") _T("\r\n"));
2402                                                                sText += sPropertyBagText;
2403                                                                sText += _T("\r\n");
2404                                                        }
2405                                                }
2406                                                _ATLCATCHALL()
2407                                                {
2408                                                        _Z_EXCEPTION();
2409                                                }
2410                                                #pragma endregion
2411                                                m_TextEdit.SetValue(sText);
2412                                                m_ApplyButton.EnableWindow(FALSE);
2413                                        }
2414                                        #pragma endregion
2415                                } else
2416                                #pragma endregion
2417                                #pragma region Service Property Page
2418                                if(Data.m_pPropertyPage)
2419                                {
2420                                        m_TextEdit.ShowWindow(SW_HIDE);
2421                                        if(Data.m_pSite != m_pCurrentSite)
2422                                                HideCurrentSite();
2423                                        if(!Data.m_bSiteActivated)
2424                                        {
2425                                                __C(Data.m_pPropertyPage->Activate(m_hWnd, GetTextEditPosition(), TRUE));
2426                                                Data.m_bSiteActivated = TRUE;
2427                                        } else
2428                                                __C(Data.m_pPropertyPage->Move(GetTextEditPosition()));
2429                                        __C(Data.m_pPropertyPage->Show(SW_SHOWNORMAL));
2430                                        m_pCurrentSite = Data.m_pSite;
2431                                        HandleStatusChange(m_pCurrentSite);
2432                                } else
2433                                #pragma endregion
2434                                #pragma region Other
2435                                {
2436                                        CWaitCursor WaitCursor;
2437                                        HideCurrentSite();
2438                                        switch(Data.m_Type)
2439                                        {
2440                                        #pragma region TYPE_MEMORYALLOCATOR
2441                                        case CData::TYPE_MEMORYALLOCATOR:
2442                                                ShowText(FALSE);
2443                                                _W(m_MemoryAllocatorDialog.SetWindowPos(NULL, GetTextEditPosition(), SWP_NOZORDER | SWP_SHOWWINDOW));
2444                                                break;
2445                                        #pragma endregion
2446                                        #pragma region TYPE_ACTION
2447                                        case CData::TYPE_ACTION:
2448                                                ShowText(FALSE);
2449                                                _W(m_ActionDialog.SetWindowPos(NULL, GetTextEditPosition(), SWP_NOZORDER | SWP_SHOWWINDOW));
2450                                                break;
2451                                        #pragma endregion
2452                                        #pragma region TYPE_EMAIL
2453                                        case CData::TYPE_EMAIL:
2454                                                ShowText(FALSE);
2455                                                _W(m_EmailDialog.SetWindowPos(NULL, GetTextEditPosition(), SWP_NOZORDER | SWP_SHOWWINDOW));
2456                                                break;
2457                                        #pragma endregion
2458                                        #pragma region TYPE_EMAIL_LOG
2459                                        case CData::TYPE_EMAIL_LOG:
2460                                                ShowText(FALSE);
2461                                                _W(m_EmailLogDialog.SetWindowPos(NULL, GetTextEditPosition(), SWP_NOZORDER | SWP_SHOWWINDOW));
2462                                                break;
2463                                        #pragma endregion
2464                                        default:
2465                                                UpdateText();
2466                                                ShowText(TRUE, TRUE);
2467                                                m_MemoryAllocatorDialog.ShowWindow(SW_HIDE);
2468                                                m_ActionDialog.ShowWindow(SW_HIDE);
2469                                                m_EmailDialog.ShowWindow(SW_HIDE);
2470                                                m_EmailLogDialog.ShowWindow(SW_HIDE);
2471                                        }
2472                                        m_ApplyButton.EnableWindow(FALSE);
2473                                }
2474                                #pragma endregion
2475                        } else
2476                        #pragma endregion
2477                        #pragma region No Tree Item
2478                        {
2479                                HideCurrentSite();
2480                                ShowText(FALSE);
2481                                m_MemoryAllocatorDialog.ShowWindow(SW_HIDE);
2482                                m_ActionDialog.ShowWindow(SW_HIDE);
2483                                m_EmailDialog.ShowWindow(SW_HIDE);
2484                                m_EmailLogDialog.ShowWindow(SW_HIDE);
2485                                m_ApplyButton.EnableWindow(FALSE);
2486                        }
2487                        #pragma endregion
2488                        return 0;
2489                }
2490                LRESULT OnTreeViewItemExplanding(NMTREEVIEW* pHeader)
2491                {
2492                        if(pHeader->action == TVE_COLLAPSE)
2493                                return TRUE; // Prevent Collapsing
2494                        return 0;
2495                }
2496                LRESULT OnTreeViewDblClk(NMHDR*)
2497                {
2498                        CTreeItem TreeItem = m_TreeView.GetSelectedItem();
2499                        if(!TreeItem)
2500                                return 0;
2501                        CData& Data = m_TreeView.GetItemData(TreeItem);
2502                        if(!Data.m_pBaseFilter)
2503                                return 0;
2504                        COlePropertyFrameDialog Dialog(Data.m_pBaseFilter);
2505                        if(!Dialog.SetObjectPages())
2506                                return 0;
2507                        Dialog.DoModal(m_hWnd);
2508                        return 0;
2509                }
2510                VOID UpdateText()
2511                {
2512                        m_TextEdit.SetValue(m_Owner.GetText());
2513                        const INT nTextLength = m_TextEdit.GetWindowTextLength();
2514                        //m_RefreshStatic.EnableWindow(TRUE);
2515                        m_CopyStatic.EnableWindow(nTextLength > 0);
2516                        m_SaveAsStatic.EnableWindow(nTextLength > 0);
2517                }
2518                LRESULT OnRefreshAnchorClicked(NMHDR*)
2519                {
2520                        UpdateText();
2521                        MessageBeep(MB_OK);
2522                        return 0;
2523                }
2524                LRESULT OnCopyAnchorClicked(NMHDR*)
2525                {
2526                        SetClipboardText(m_hWnd, m_TextEdit.GetValue());
2527                        MessageBeep(MB_OK);
2528                        return 0;
2529                }
2530                LRESULT OnSaveAsAnchorClicked(NMHDR*)
2531                {
2532                        static const COMDLG_FILTERSPEC g_pFilter[] = 
2533                        {
2534                                { _T("Markdown Files"), _T("*.md") },
2535                                { _T("Text Files"), _T("*.txt") },
2536                                { _T("BZip2 Compressed Markdown Files"), _T("*.md.bz2") },
2537                                { _T("All Files"), _T("*.*") },
2538                        };
2539                        CPath sPath = _CommonDialogHelper::QuerySavePath(m_hWnd, g_pFilter, _T("md"));
2540                        if(!_tcslen(sPath))
2541                                return 0;
2542                        CAtlFile File;
2543                        __C(File.Create(sPath, GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS));
2544                        _ATLTRY
2545                        {
2546                                CStringA sText = Utf8StringFromString(CStringW(m_TextEdit.GetValue()));
2547                                static const BYTE g_pnByteOrderMark[] = { 0xEF, 0xBB, 0xBF, 0x00 };
2548                                sText.Insert(0, (LPCSTR) g_pnByteOrderMark);
2549                                if(_tcsicmp(GetPathExtension(sPath), _T(".bz2")) == 0)
2550                                {
2551                                        CLocalObjectPtr<CBzip2Item> pItem;
2552                                        pItem->SetRawData((const BYTE*) (LPCSTR) sText, sText.GetLength());
2553                                        CHeapPtr<BYTE> pnData;
2554                                        SIZE_T nDataSize = 0;
2555                                        pItem->GetData(pnData, nDataSize);
2556                                        __C(File.Write(pnData, (DWORD) nDataSize));
2557                                } else
2558                                        __C(File.Write(sText, (DWORD) sText.GetLength()));
2559                        }
2560                        _ATLCATCHALL()
2561                        {
2562                                File.Close();
2563                                _W(DeleteFile(sPath));
2564                                _ATLRETHROW;
2565                        }
2566                        MessageBeep(MB_OK);     
2567                        return 0;
2568                }
2569                LRESULT OnSysCommand(UINT nCommand, CPoint)
2570                {
2571                        switch(nCommand)
2572                        {
2573                        case ID_APP_ABOUT:
2574                                {
2575                                        CAboutDialog Dialog;
2576                                        Dialog.DoModal(m_hWnd);
2577                                }
2578                                break;
2579                        default:
2580                                SetMsgHandled(FALSE);
2581                        }
2582                        return 0;
2583                }
2584                LRESULT OnOk(UINT, INT nIdentifier, HWND)
2585                {
2586                        _ATLTRY
2587                        {
2588                                #pragma region Apply All
2589                                for(POSITION Position = m_TreeView.GetDataList().GetHeadPosition(); Position; m_TreeView.GetDataList().GetNext(Position))
2590                                {
2591                                        CData& Data = m_TreeView.GetDataList().GetAt(Position);
2592                                        if(!Data.m_pSite)
2593                                                continue;
2594                                        _A(Data.m_pPropertyPage);
2595                                        if(Data.m_bSiteActivated && Data.m_pSite->IsDirty())
2596                                                __C(Data.m_pPropertyPage->Apply());
2597                                }
2598                                #pragma endregion
2599                        }
2600                        _ATLCATCH(Exception)
2601                        {
2602                                _Z_ATLEXCEPTION(Exception);
2603                                AtlMessageBoxEx(m_hWnd, (LPCTSTR) Ds::FormatResult(Exception), IDS_ERROR, MB_ICONERROR | MB_OK);
2604                                return 0;
2605                        }
2606                        EndDialog(nIdentifier);
2607                        return 0;
2608                }
2609                LRESULT OnCancel(UINT, INT nIdentifier, HWND)
2610                {
2611                        EndDialog(nIdentifier);
2612                        return 0;
2613                }
2614                LRESULT OnApply(UINT, INT, HWND)
2615                {
2616                        _ATLTRY
2617                        {
2618                                Apply();
2619                        }
2620                        _ATLCATCH(Exception)
2621                        {
2622                                _Z_ATLEXCEPTION(Exception);
2623                                AtlMessageBoxEx(m_hWnd, (LPCTSTR) Ds::FormatResult(Exception), IDS_ERROR, MB_ICONERROR | MB_OK);
2624                        }
2625                        return 0;
2626                }
2627                LRESULT OnTreeWalkUp(UINT, INT, HWND)
2628                {
2629                        CTreeItem TreeItem = m_TreeView.GetSelectedItem();
2630                        CTreeItem ParentTreeItem = TreeItem.GetParent();
2631                        if(!ParentTreeItem)
2632                                return 0;
2633                        m_TreeView.SetFocus();
2634                        m_TreeView.Select(ParentTreeItem, TVGN_CARET);
2635                        return 0;
2636                }
2637                LRESULT OnActionCommand(UINT, INT nIdentifier, HWND)
2638                {
2639                        return m_ActionDialog.SendMessage(WM_COMMAND, nIdentifier);
2640                }
2641        };
2642
2643private:
2644        mutable CRoCriticalSection m_DataCriticalSection;
2645        CProcessData m_ProcessData;
2646        CComPtr<IFilterGraph> m_pFilterGraph;
2647        COptions m_Options;
2648
2649public:
2650// CFilterGraphHelper
2651        static HRESULT WINAPI UpdateRegistry(BOOL bRegister)
2652        {
2653                _Z2(atlTraceRegistrar, 2, _T("bRegister %d\n"), bRegister);
2654                _ATLTRY
2655                {
2656                        UpdateRegistryFromResource<CFilterGraphHelper>(bRegister);
2657                }
2658                _ATLCATCH(Exception)
2659                {
2660                        _C(Exception);
2661                }
2662                return S_OK;
2663        }
2664        CFilterGraphHelper()
2665        {
2666                _Z4_THIS();
2667        }
2668        ~CFilterGraphHelper()
2669        {
2670                _Z4_THIS();
2671        }
2672        static CString FormatIdentifier(LPCSTR pszValue)
2673        {
2674                CString sText;
2675                if(pszValue && *pszValue)
2676                {
2677                        sText = _T("``");
2678                        sText.Insert(1, CString(pszValue));
2679                }
2680                return sText;
2681        }
2682        static CString FormatIdentifier(LPCWSTR pszValue)
2683        {
2684                CString sText;
2685                if(pszValue && *pszValue)
2686                {
2687                        sText = _T("``");
2688                        sText.Insert(1, CString(pszValue));
2689                }
2690                return sText;
2691        }
2692        static CString FormatIdentifier(LONG nValue)
2693        {
2694                CString sText;
2695                sText = _T("``");
2696                sText.Insert(1, _StringHelper::FormatNumber(nValue));
2697                return sText;
2698        }
2699        static CString FormatIdentifier(ULONG nValue)
2700        {
2701                return FormatIdentifier((LONG) nValue);
2702        }
2703        static CString FormatIdentifier(BOOL nValue)
2704        {
2705                return FormatIdentifier((LONG) nValue);
2706        }
2707        static CString FormatIdentifier(LONGLONG nValue)
2708        {
2709                CString sText;
2710                sText = _T("``");
2711                sText.Insert(1, _StringHelper::FormatNumber(nValue));
2712                return sText;
2713        }
2714        static CString FormatIdentifier(LONG nValue, LPCTSTR pszFormat)
2715        {
2716                CString sText;
2717                sText = _T("``");
2718                sText.Insert(1, AtlFormatString(pszFormat, nValue));
2719                return sText;
2720        }
2721        static CString FormatIdentifier(const VOID* pvValue, LPCTSTR pszFormat = _T("0x%p"))
2722        {
2723                CString sText;
2724                sText = _T("``");
2725                sText.Insert(1, AtlFormatString(pszFormat, pvValue));
2726                return sText;
2727        }
2728        #define I FormatIdentifier
2729        static CString FormatPhysicalConnectorType(PhysicalConnectorType Value)
2730        {
2731                struct 
2732                {
2733                        PhysicalConnectorType Value;
2734                        LPCSTR pszName;
2735                } g_pMap[] = 
2736                {
2737                        #define A(x) { x, #x },
2738                        A(PhysConn_Video_Tuner)
2739                        A(PhysConn_Video_Composite)
2740                        A(PhysConn_Video_SVideo)
2741                        A(PhysConn_Video_RGB)
2742                        A(PhysConn_Video_YRYBY)
2743                        A(PhysConn_Video_SerialDigital)
2744                        A(PhysConn_Video_ParallelDigital)
2745                        A(PhysConn_Video_SCSI)
2746                        A(PhysConn_Video_AUX)
2747                        A(PhysConn_Video_1394)
2748                        A(PhysConn_Video_USB)
2749                        A(PhysConn_Video_VideoDecoder)
2750                        A(PhysConn_Video_VideoEncoder)
2751                        A(PhysConn_Video_SCART)
2752                        A(PhysConn_Video_Black)
2753                        A(PhysConn_Audio_Tuner)
2754                        A(PhysConn_Audio_Line)
2755                        A(PhysConn_Audio_Mic)
2756                        A(PhysConn_Audio_AESDigital)
2757                        A(PhysConn_Audio_SPDIFDigital)
2758                        A(PhysConn_Audio_SCSI)
2759                        A(PhysConn_Audio_AUX)
2760                        A(PhysConn_Audio_1394)
2761                        A(PhysConn_Audio_USB)
2762                        A(PhysConn_Audio_AudioDecoder)
2763                        #undef A
2764                };
2765                for(SIZE_T nIndex = 0; nIndex < DIM(g_pMap); nIndex++)
2766                        if(g_pMap[nIndex].Value == Value)
2767                                return CString(g_pMap[nIndex].pszName);
2768                return AtlFormatString(_T("0x%04X"), Value);
2769        }
2770        static CString FormatPins(_FilterGraphHelper::CPinArray& PinArray)
2771        {
2772                CRoArrayT<CString> Array;
2773                for(SIZE_T nIndex  = 0; nIndex < PinArray.GetCount(); nIndex++)
2774                {
2775                        const CComPtr<IPin>& pPin = PinArray[nIndex];
2776                        CString sText = I(_FilterGraphHelper::GetPinName(pPin));
2777                        const CComPtr<IPin> pPeerPin = _FilterGraphHelper::GetPeerPin(pPin);
2778                        if(pPeerPin)
2779                                sText += AtlFormatString(_T(" (%s)"), I(_FilterGraphHelper::GetPinFullName(pPeerPin)));
2780                        Array.Add(sText);
2781                }
2782                return _StringHelper::Join(Array, _T(", "));
2783        }
2784        static CString GetFilterText(IBaseFilter* pBaseFilter, const CProcessData* pProcessData, IReferenceClock* pFilterGraphReferenceClock = NULL)
2785        {
2786                CString sText;
2787                #pragma region COM
2788                CString sPath;
2789                const CStringW sClassIdentifierString = _FilterGraphHelper::GetFilterClassIdentifierString(pBaseFilter);
2790                if(!sClassIdentifierString.IsEmpty())
2791                {
2792                        CLSID ClassIdentifier = CLSID_NULL;
2793                        const BOOL bClassIdentifierAvailable = _PersistHelper::ClassIdentifierFromString(sClassIdentifierString, ClassIdentifier);
2794                        if(bClassIdentifierAvailable && ClassIdentifier != CLSID_NULL)
2795                        {
2796                                sText += AtlFormatString(_T(" * ") _T("Class: %s %s") _T("\r\n"), I(sClassIdentifierString), I(_FilterGraphHelper::GetFilterClassDescription(pBaseFilter)));
2797                                _ATLTRY
2798                                {
2799                                        sPath = _RegKeyHelper::QueryStringValue(HKEY_CLASSES_ROOT, AtlFormatString(_T("CLSID\\%ls\\InprocServer32"), sClassIdentifierString));
2800                                        if(!sPath.IsEmpty())
2801                                        {
2802                                                sText += AtlFormatString(_T(" * ") _T("Inproc Server: %s") _T("\r\n"), I(sPath));
2803                                                const ULONGLONG nProductVersion = _VersionInfoHelper::GetProductVersion(sPath);
2804                                                if(nProductVersion && (nProductVersion + 1))
2805                                                        sText += AtlFormatString(_T(" * ") _T("Product Version: %s") _T("\r\n"), I(_VersionInfoHelper::GetVersionString(nProductVersion)));
2806                                                const ULONGLONG nFileVersion = _VersionInfoHelper::GetFileVersion(sPath);
2807                                                if(nFileVersion && (nFileVersion + 1))
2808                                                        sText += AtlFormatString(_T(" * ") _T("File Version: %s") _T("\r\n"), I(_VersionInfoHelper::GetVersionString(nFileVersion)));
2809                                        }
2810                                }
2811                                _ATLCATCHALL()
2812                                {
2813                                        _Z_EXCEPTION();
2814                                }
2815                        }
2816                }
2817                if(_tcslen(sPath) == 0 && pProcessData && pProcessData->m_nIdentifier == GetCurrentProcessId())
2818                        _ATLTRY
2819                        {
2820                                const VOID* pvVirtualTable = *((const VOID**) pBaseFilter);
2821                                MEMORY_BASIC_INFORMATION Information;
2822                                if(VirtualQueryEx(GetCurrentProcess(), pvVirtualTable, &Information, sizeof Information))
2823                                {
2824                                        TCHAR pszPath[MAX_PATH] = { 0 };
2825                                        if(GetModuleFileName((HMODULE) Information.AllocationBase, pszPath, DIM(pszPath)))
2826                                        {
2827                                                sPath = pszPath;
2828                                                sText += AtlFormatString(_T(" * ") _T("Virtual Table Location: %s") _T("\r\n"), I(sPath));
2829                                                const ULONGLONG nProductVersion = _VersionInfoHelper::GetProductVersion(sPath);
2830                                                if(nProductVersion && (nProductVersion + 1))
2831                                                        sText += AtlFormatString(_T(" * ") _T("Product Version: %s") _T("\r\n"), I(_VersionInfoHelper::GetVersionString(nProductVersion)));
2832                                                const ULONGLONG nFileVersion = _VersionInfoHelper::GetFileVersion(sPath);
2833                                                if(nFileVersion && (nFileVersion + 1))
2834                                                        sText += AtlFormatString(_T(" * ") _T("File Version: %s") _T("\r\n"), I(_VersionInfoHelper::GetVersionString(nFileVersion)));
2835                                        }
2836                                }
2837                        }
2838                        _ATLCATCHALL()
2839                        {
2840                                _Z_EXCEPTION();
2841                        }
2842                #pragma endregion
2843                #pragma region Pin
2844                _FilterGraphHelper::CPinArray InputPinArray;
2845                if(_FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_INPUT, InputPinArray))
2846                        sText += AtlFormatString(_T(" * ") _T("Input Pins: %s") _T("\r\n"), FormatPins(InputPinArray));
2847                _FilterGraphHelper::CPinArray OutputPinArray;
2848                if(_FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_OUTPUT, OutputPinArray))
2849                        sText += AtlFormatString(_T(" * ") _T("Output Pins: %s") _T("\r\n"), FormatPins(OutputPinArray));
2850                #pragma endregion
2851                #pragma region IReferenceClock
2852                const CComQIPtr<IReferenceClock> pReferenceClock = pBaseFilter;
2853                if(pReferenceClock)
2854                {
2855                        CRoArrayT<CString> Array;
2856                        Array.Add(I(_T("Available")));
2857                        if(pReferenceClock == pFilterGraphReferenceClock)
2858                                Array.Add(I(_T("Selected")));
2859                        sText += AtlFormatString(_T(" * ") _T("Reference Clock: %s") _T("\r\n"), _StringHelper::Join(Array, _T(", ")));
2860                }
2861                #pragma endregion
2862                #pragma region IFileSourceFilter
2863                const CComQIPtr<IFileSourceFilter> pFileSourceFilter = pBaseFilter;
2864                if(pFileSourceFilter)
2865                        _ATLTRY
2866                        {
2867                                CComHeapPtr<OLECHAR> pszFileName;
2868                                CMediaType pMediaType;
2869                                pMediaType.Allocate(MEDIATYPE_NULL, MEDIASUBTYPE_NULL);
2870                                const HRESULT nGetCurFileResult = pFileSourceFilter->GetCurFile(&pszFileName, pMediaType);
2871                                _Z45_DSHRESULT(nGetCurFileResult);
2872                                if(SUCCEEDED(nGetCurFileResult))
2873                                        sText += AtlFormatString(_T(" * ") _T("File Source: %s") _T("\r\n"), I(pszFileName));
2874                        }
2875                        _ATLCATCHALL()
2876                        {
2877                                _Z_EXCEPTION();
2878                        }
2879                #pragma endregion
2880                #pragma region IFileSinkFilter
2881                const CComQIPtr<IFileSinkFilter> pFileSinkFilter = pBaseFilter;
2882                if(pFileSinkFilter)
2883                        _ATLTRY
2884                        {
2885                                CComHeapPtr<OLECHAR> pszFileName;
2886                                CMediaType pMediaType;
2887                                pMediaType.Allocate(MEDIATYPE_NULL, MEDIASUBTYPE_NULL);
2888                                const HRESULT nGetCurFileResult = pFileSinkFilter->GetCurFile(&pszFileName, pMediaType);
2889                                _Z45_DSHRESULT(nGetCurFileResult);
2890                                if(SUCCEEDED(nGetCurFileResult))
2891                                        sText += AtlFormatString(_T(" * ") _T("File Sink: %s") _T("\r\n"), I(pszFileName));
2892                        }
2893                        _ATLCATCHALL()
2894                        {
2895                                _Z_EXCEPTION();
2896                        }
2897                #pragma endregion
2898                #pragma region IMediaSeeking
2899                const CComQIPtr<IMediaSeeking> pMediaSeeking = pBaseFilter;
2900                if(pMediaSeeking)
2901                        _ATLTRY
2902                        {
2903                                sText += AtlFormatString(_T(" * ") _T("Media Seeking/Position") _T("\r\n"));
2904                                DWORD nCapabilities = 0;
2905                                if(SUCCEEDED(pMediaSeeking->GetCapabilities(&nCapabilities)))
2906                                        sText += AtlFormatString(_T("  * ") _T("Capabilities: %s") _T("\r\n"), I(AtlFormatString(_T("0x%X"), nCapabilities)));
2907                                LONGLONG nDuration = 0, nPosition = 0, nStopPosition = 0;
2908                                if(SUCCEEDED(pMediaSeeking->GetDuration(&nDuration)))
2909                                        sText += AtlFormatString(_T("  * ") _T("Duration: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime((DOUBLE) nDuration / 1E7)), I(_StringHelper::FormatNumber((DOUBLE) nDuration / 1E7, 3)));
2910                                if(SUCCEEDED(pMediaSeeking->GetCurrentPosition(&nPosition)))
2911                                        sText += AtlFormatString(_T("  * ") _T("Position: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime((DOUBLE) nPosition / 1E7)), I(_StringHelper::FormatNumber((DOUBLE) nPosition / 1E7, 3)));
2912                                if(SUCCEEDED(pMediaSeeking->GetStopPosition(&nStopPosition)))
2913                                        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)));
2914                                DOUBLE fRate = 1.0;
2915                                if(SUCCEEDED(pMediaSeeking->GetRate(&fRate)))
2916                                        sText += AtlFormatString(_T("  * ") _T("Rate: %s") _T("\r\n"), I(_StringHelper::FormatNumber(fRate, 3)));
2917                                LONGLONG nPreroll = 0;
2918                                if(SUCCEEDED(pMediaSeeking->GetPreroll(&nPreroll)) && nPreroll)
2919                                        sText += AtlFormatString(_T("  * ") _T("Preroll: %s seconds") _T("\r\n"), I(_StringHelper::FormatNumber((DOUBLE) nPreroll / 1E7, 3)));
2920                        }
2921                        _ATLCATCHALL()
2922                        {
2923                                _Z_EXCEPTION();
2924                        }
2925                #pragma endregion
2926                #pragma region IAMCrossbar
2927                const CComQIPtr<IAMCrossbar> pAmCrossbar = pBaseFilter;
2928                if(pAmCrossbar)
2929                        _ATLTRY
2930                        {
2931                                sText += AtlFormatString(_T(" * ") _T("Crossbar:") _T("\r\n"));
2932                                LONG nOutputPinCount = 0, nInputPinCount = 0;
2933                                __C(pAmCrossbar->get_PinCounts(&nOutputPinCount, &nInputPinCount));
2934                                sText += AtlFormatString(_T("  * ") _T("Pins: %s Input, %s Output") _T("\r\n"), I(nInputPinCount), I(nOutputPinCount));
2935                                #pragma region Input
2936                                for(LONG nInputPinIndex = 0; nInputPinIndex < nInputPinCount; nInputPinIndex++)
2937                                        _ATLTRY
2938                                        {
2939                                                CRoArrayT<CString> Array;
2940                                                LONG nRelatedPinIndex = -1;
2941                                                LONG nPhysicalType = 0; // PhysicalConnectorType
2942                                                __C(pAmCrossbar->get_CrossbarPinInfo(TRUE, nInputPinIndex, &nRelatedPinIndex, &nPhysicalType));
2943                                                if(nRelatedPinIndex >= 0)
2944                                                        Array.Add(AtlFormatString(_T("Related %s"), I(nRelatedPinIndex)));
2945                                                Array.Add(AtlFormatString(_T("Physical Type %s"), I(FormatPhysicalConnectorType((PhysicalConnectorType) nPhysicalType))));
2946                                                sText += AtlFormatString(_T("  * ") _T("Input Pin %s: %s") _T("\r\n"), I(nInputPinIndex), _StringHelper::Join(Array, _T("; ")));
2947                                        }
2948                                        _ATLCATCHALL()
2949                                        {
2950                                                _Z_EXCEPTION();
2951                                        }
2952                                #pragma endregion
2953                                #pragma region Output
2954                                for(LONG nOutputPinIndex = 0; nOutputPinIndex < nOutputPinCount; nOutputPinIndex++)
2955                                        _ATLTRY
2956                                        {
2957                                                CRoArrayT<CString> Array;
2958                                                LONG nRelatedPinIndex = -1;
2959                                                LONG nPhysicalType = 0; // PhysicalConnectorType
2960                                                __C(pAmCrossbar->get_CrossbarPinInfo(FALSE, nOutputPinIndex, &nRelatedPinIndex, &nPhysicalType));
2961                                                if(nRelatedPinIndex >= 0)
2962                                                        Array.Add(AtlFormatString(_T("Related %s"), I(nRelatedPinIndex)));
2963                                                if(nPhysicalType > 0)
2964                                                        Array.Add(AtlFormatString(_T("Physical Type %s"), I(FormatPhysicalConnectorType((PhysicalConnectorType) nPhysicalType))));
2965                                                LONG nRoutedInputPinIndex = -1;
2966                                                const HRESULT nGetIsRoutedToResult = pAmCrossbar->get_IsRoutedTo(nOutputPinIndex, &nRoutedInputPinIndex);
2967                                                _A(nGetIsRoutedToResult == S_OK || nRoutedInputPinIndex == -1);
2968                                                if(nRoutedInputPinIndex >= 0)
2969                                                        Array.Add(AtlFormatString(_T("Routed to Input Pin %s"), I(nRoutedInputPinIndex)));
2970                                                CRoArrayT<CString> PinArray;
2971                                                for(LONG nInputPinIndex = 0; nInputPinIndex < nInputPinCount; nInputPinIndex++)
2972                                                {
2973                                                        const HRESULT nCanRouteResult = pAmCrossbar->CanRoute(nOutputPinIndex, nInputPinIndex);
2974                                                        if(nCanRouteResult == S_OK)
2975                                                                PinArray.Add(I(nInputPinIndex));
2976                                                }
2977                                                if(!PinArray.IsEmpty())
2978                                                        Array.Add(AtlFormatString(_T("Routeable to Input Pins %s"), _StringHelper::Join(PinArray, _T(", "))));
2979                                                sText += AtlFormatString(_T("  * ") _T("Output Pin %s: %s") _T("\r\n"), I(nOutputPinIndex), _StringHelper::Join(Array, _T("; ")));
2980                                        }
2981                                        _ATLCATCHALL()
2982                                        {
2983                                                _Z_EXCEPTION();
2984                                        }
2985                                #pragma endregion
2986                        }
2987                        _ATLCATCHALL()
2988                        {
2989                                _Z_EXCEPTION();
2990                        }
2991                #pragma endregion
2992                return sText;
2993        }
2994        static CString GetConnectionText(IPin* pOutputPin, IPin* pInputPin)
2995        {
2996                _A(pOutputPin && pInputPin);
2997                CString sText = AtlFormatString(_T("%s - %s"), I(_FilterGraphHelper::GetPinFullName(pOutputPin)), I(_FilterGraphHelper::GetPinFullName(pInputPin)));
2998                _ATLTRY
2999                {
3000                        const CMediaType pMediaType = _FilterGraphHelper::GetPinMediaType(pOutputPin);
3001                        if(pMediaType)
3002                        {
3003                                CStringW sMajorType = _FilterGraphHelper::FormatMajorType(pMediaType->majortype);
3004                                CStringW sSubtype;
3005                                if(pMediaType->subtype != MEDIASUBTYPE_NULL)
3006                                        sSubtype = _FilterGraphHelper::FormatSubtype(pMediaType->majortype, pMediaType->subtype);
3007                                CRoArrayT<CString> Array;
3008                                Array.Add(I(sMajorType));
3009                                if(!sSubtype.IsEmpty())
3010                                        Array.Add(I(sSubtype));
3011                                #pragma region MEDIATYPE_Video
3012                                if(pMediaType->majortype == MEDIATYPE_Video)
3013                                {
3014                                        const CVideoInfoHeader2 VideoInfoHeader2 = pMediaType.GetCompatibleVideoInfoHeader2();
3015                                        const CSize Extent = VideoInfoHeader2.GetExtent();
3016                                        if(Extent.cx || Extent.cy)
3017                                                Array.Add(AtlFormatString(_T("%s x %s"), I(Extent.cx), I(Extent.cy)));
3018                                        if(VideoInfoHeader2.AvgTimePerFrame > 0)
3019                                                Array.Add(AtlFormatString(_T("%s frames/sec"), I(_StringHelper::FormatNumber(1E7 / VideoInfoHeader2.AvgTimePerFrame, 3))));
3020                                } else
3021                                #pragma endregion
3022                                #pragma region MEDIATYPE_Audio
3023                                if(pMediaType->majortype == MEDIATYPE_Audio)
3024                                {
3025                                        const CWaveFormatEx* pWaveFormatEx = pMediaType.GetWaveFormatEx();
3026                                        if(pWaveFormatEx)
3027                                        {
3028                                                if(pWaveFormatEx->nSamplesPerSec)
3029                                                        Array.Add(AtlFormatString(_T("%s Hz"), I(pWaveFormatEx->nSamplesPerSec)));
3030                                                if(pWaveFormatEx->nChannels)
3031                                                        Array.Add(AtlFormatString(_T("%s channels"), I(pWaveFormatEx->nChannels)));
3032                                                if(pWaveFormatEx->wBitsPerSample)
3033                                                        Array.Add(AtlFormatString(_T("%s bits"), I(pWaveFormatEx->wBitsPerSample)));
3034                                        }
3035                                }
3036                                #pragma endregion
3037                                sText += AtlFormatString(_T(" (%s)"), _StringHelper::Join(Array, _T(", ")));
3038                        }
3039                }
3040                _ATLCATCHALL()
3041                {
3042                        _Z_EXCEPTION();
3043                }
3044                return sText;
3045        }
3046        static CString GetMediaTypeText(const CMediaType& pMediaType)
3047        {
3048                CString sText;
3049                #pragma region AM_MEDIA_TYPE
3050                #define J(x) I(pMediaType->x)
3051                #define K1(x) sText += AtlFormatString(_T(" * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
3052                sText += AtlFormatString(_T(" * ") _T("Data: %s") _T("\r\n"), I(AtlFormatData((const BYTE*) (const AM_MEDIA_TYPE*) pMediaType, sizeof *pMediaType).TrimRight()));
3053                sText += AtlFormatString(_T(" * ") _T("`majortype`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatMajorType(pMediaType->majortype)));
3054                if(pMediaType->subtype != MEDIASUBTYPE_NULL)
3055                        sText += AtlFormatString(_T(" * ") _T("`subtype`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatSubtype(pMediaType->majortype, pMediaType->subtype)));
3056                K1(bFixedSizeSamples);
3057                K1(bTemporalCompression);
3058                K1(lSampleSize);
3059                if(pMediaType->formattype != GUID_NULL)
3060                        sText += AtlFormatString(_T(" * ") _T("`formattype`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatFormatType(pMediaType->formattype)));
3061                if(pMediaType->pUnk)
3062                        sText += AtlFormatString(_T(" * ") _T("`pUnk`: %s") _T("\r\n"), I(AtlFormatString(_T("0x%p"), pMediaType->pUnk)));
3063                if(pMediaType->cbFormat)
3064                {
3065                        K1(cbFormat);
3066                        if(pMediaType->pbFormat)
3067                                sText += AtlFormatString(_T(" * ") _T("Format Data, `pbFormat`: %s") _T("\r\n"), I(AtlFormatData(pMediaType->pbFormat, pMediaType->cbFormat).TrimRight()));
3068                }
3069                #undef J
3070                #undef K1
3071                #pragma endregion
3072                const BYTE* pnExtraData = NULL;
3073                SIZE_T nExtraDataSize = 0;
3074                #pragma region FORMAT_VideoInfo
3075                if(pMediaType->formattype == FORMAT_VideoInfo)
3076                {
3077                        sText += AtlFormatString(_T(" * ") _T("As `VIDEOINFOHEADER`:") _T("\r\n"));
3078                        const VIDEOINFOHEADER* pVideoInfoHeader = (const VIDEOINFOHEADER*) pMediaType->pbFormat;
3079                        #define J(x) I(pVideoInfoHeader->x)
3080                        #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
3081                        sText += AtlFormatString(_T("  * ") _T("`rcSource`: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcSource.left), J(rcSource.top), J(rcSource.right), J(rcSource.bottom));
3082                        sText += AtlFormatString(_T("  * ") _T("`rcTarget`: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcTarget.left), J(rcTarget.top), J(rcTarget.right), J(rcTarget.bottom));
3083                        K1(dwBitRate);
3084                        K1(dwBitErrorRate);
3085                        sText += AtlFormatString(_T("  * ") _T("`AvgTimePerFrame`: %s units") _T("\r\n"), I(_FilterGraphHelper::FormatReferenceTime(pVideoInfoHeader->AvgTimePerFrame)));
3086                        K1(bmiHeader.biSize);
3087                        K1(bmiHeader.biWidth);
3088                        K1(bmiHeader.biHeight);
3089                        K1(bmiHeader.biPlanes);
3090                        K1(bmiHeader.biBitCount);
3091                        sText += AtlFormatString(_T("  * ") _T("`bmiHeader.biCompression`: %s") _T("\r\n"), I(_FilterGraphHelper::GetFourccCodeString(pVideoInfoHeader->bmiHeader.biCompression)));
3092                        K1(bmiHeader.biSizeImage);
3093                        K1(bmiHeader.biXPelsPerMeter);
3094                        K1(bmiHeader.biYPelsPerMeter);
3095                        K1(bmiHeader.biClrUsed);
3096                        K1(bmiHeader.biClrImportant);
3097                        #undef J
3098                        #undef K1
3099                        nExtraDataSize = pMediaType->cbFormat - sizeof *pVideoInfoHeader;
3100                } else
3101                #pragma endregion
3102                #pragma region FORMAT_VideoInfo2
3103                if(pMediaType->formattype == FORMAT_VideoInfo2)
3104                {
3105                        sText += AtlFormatString(_T(" * ") _T("As `VIDEOINFOHEADER2`:") _T("\r\n"));
3106                        const VIDEOINFOHEADER2* pVideoInfoHeader2 = (const VIDEOINFOHEADER2*) pMediaType->pbFormat;
3107                        #define J(x) I(pVideoInfoHeader2->x)
3108                        #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
3109                        #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pVideoInfoHeader2->x, y))
3110                        sText += AtlFormatString(_T("  * ") _T("rcSource: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcSource.left), J(rcSource.top), J(rcSource.right), J(rcSource.bottom));
3111                        sText += AtlFormatString(_T("  * ") _T("rcTarget: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcTarget.left), J(rcTarget.top), J(rcTarget.right), J(rcTarget.bottom));
3112                        K1(dwBitRate);
3113                        K1(dwBitErrorRate);
3114                        sText += AtlFormatString(_T("  * ") _T("`AvgTimePerFrame`: %s units") _T("\r\n"), I(_FilterGraphHelper::FormatReferenceTime(pVideoInfoHeader2->AvgTimePerFrame)));
3115                        K2(dwInterlaceFlags, _T("0x%X"));
3116                        K2(dwCopyProtectFlags, _T("0x%X"));
3117                        K1(dwPictAspectRatioX);
3118                        K1(dwPictAspectRatioY);
3119                        K2(dwControlFlags, _T("0x%X"));
3120                        K1(bmiHeader.biSize);
3121                        K1(bmiHeader.biWidth);
3122                        K1(bmiHeader.biHeight);
3123                        K1(bmiHeader.biPlanes);
3124                        K1(bmiHeader.biBitCount);
3125                        sText += AtlFormatString(_T("  * ") _T("`bmiHeader.biCompression`: %s") _T("\r\n"), I(_FilterGraphHelper::GetFourccCodeString(pVideoInfoHeader2->bmiHeader.biCompression)));
3126                        K1(bmiHeader.biSizeImage);
3127                        K1(bmiHeader.biXPelsPerMeter);
3128                        K1(bmiHeader.biYPelsPerMeter);
3129                        K1(bmiHeader.biClrUsed);
3130                        K1(bmiHeader.biClrImportant);
3131                        #undef J
3132                        #undef K1
3133                        #undef K2
3134                        nExtraDataSize = pMediaType->cbFormat - sizeof *pVideoInfoHeader2;
3135                        if(nExtraDataSize)
3136                        {
3137                                sText += AtlFormatString(_T("  * ") _T("Extra Data: (%d bytes)") _T("\r\n"), nExtraDataSize);
3138                                nExtraDataSize = 0;
3139                        }
3140                } else
3141                #pragma endregion
3142                #pragma region FORMAT_MPEG2Video
3143                if(pMediaType->formattype == FORMAT_MPEG2Video)
3144                {
3145                        sText += AtlFormatString(_T(" * ") _T("As `MPEG2VIDEOINFO`:") _T("\r\n"));
3146                        const MPEG2VIDEOINFO* pMpeg2VideoInfo = (const MPEG2VIDEOINFO*) pMediaType->pbFormat;
3147                        #define J(x) I(pMpeg2VideoInfo->x)
3148                        #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
3149                        #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pMpeg2VideoInfo->x, y))
3150                        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));
3151                        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));
3152                        K1(hdr.dwBitRate);
3153                        K1(hdr.dwBitErrorRate);
3154                        sText += AtlFormatString(_T("  * ") _T("`hdr.AvgTimePerFrame`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatReferenceTime(pMpeg2VideoInfo->hdr.AvgTimePerFrame)));
3155                        K2(hdr.dwInterlaceFlags, _T("0x%X"));
3156                        K2(hdr.dwCopyProtectFlags, _T("0x%X"));
3157                        K1(hdr.dwPictAspectRatioX);
3158                        K1(hdr.dwPictAspectRatioY);
3159                        K2(hdr.dwControlFlags, _T("0x%X"));
3160                        K1(hdr.bmiHeader.biSize);
3161                        K1(hdr.bmiHeader.biWidth);
3162                        K1(hdr.bmiHeader.biHeight);
3163                        K1(hdr.bmiHeader.biPlanes);
3164                        K1(hdr.bmiHeader.biBitCount);
3165                        sText += AtlFormatString(_T("  * ") _T("`hdr.bmiHeader.biCompression`: %s") _T("\r\n"), I(_FilterGraphHelper::GetFourccCodeString(pMpeg2VideoInfo->hdr.bmiHeader.biCompression)));
3166                        K1(hdr.bmiHeader.biSizeImage);
3167                        K1(hdr.bmiHeader.biXPelsPerMeter);
3168                        K1(hdr.bmiHeader.biYPelsPerMeter);
3169                        K1(hdr.bmiHeader.biClrUsed);
3170                        K1(hdr.bmiHeader.biClrImportant);
3171                        K2(dwStartTimeCode, _T("0x%08X"));
3172                        K1(cbSequenceHeader);
3173                        K1(dwProfile);
3174                        K1(dwLevel);
3175                        K2(dwFlags, _T("0x%08X"));
3176                        #undef J
3177                        #undef K1
3178                        #undef K2
3179                        #undef J
3180                        nExtraDataSize = pMediaType->cbFormat - (sizeof *pMpeg2VideoInfo - sizeof pMpeg2VideoInfo->dwSequenceHeader);
3181                } else
3182                #pragma endregion
3183                #pragma region FORMAT_WaveFormatEx
3184                if(pMediaType->formattype == FORMAT_WaveFormatEx)
3185                {
3186                        const WAVEFORMATEX* pWaveFormatEx = (const WAVEFORMATEX*) pMediaType->pbFormat;
3187                        if(pWaveFormatEx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
3188                        {
3189                                const WAVEFORMATEXTENSIBLE* pWaveFormatExtensible = (const WAVEFORMATEXTENSIBLE*) pMediaType->pbFormat;
3190                                #define J(x) I(pWaveFormatExtensible->x)
3191                                #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
3192                                #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pWaveFormatExtensible->x, y))
3193                                sText += AtlFormatString(_T(" * ") _T("As `WAVEFORMATEXTENSIBLE`:") _T("\r\n"));
3194                                K2(Format.wFormatTag, _T("0x%02X"));
3195                                K1(Format.nChannels);
3196                                K1(Format.nSamplesPerSec);
3197                                K1(Format.nAvgBytesPerSec);
3198                                K1(Format.nBlockAlign);
3199                                K1(Format.wBitsPerSample);
3200                                K1(Format.cbSize);
3201                                K1(Samples.wValidBitsPerSample);
3202                                K2(dwChannelMask, _T("0x%02X"));
3203                                sText += AtlFormatString(_T("  * ") _T("`SubFormat`: %s") _T("\r\n"), I(_PersistHelper::StringFromIdentifier(pWaveFormatExtensible->SubFormat)));
3204                                #undef J
3205                                #undef K1
3206                                #undef K2
3207                                nExtraDataSize = pWaveFormatEx->cbSize - (sizeof *pWaveFormatExtensible - sizeof *pWaveFormatEx);
3208                        } else
3209                        {
3210                                #define J(x) I(pWaveFormatEx->x)
3211                                #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
3212                                #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pWaveFormatEx->x, y))
3213                                K2(wFormatTag, _T("0x%02X"));
3214                                K1(nChannels);
3215                                K1(nSamplesPerSec);
3216                                K1(nAvgBytesPerSec);
3217                                K1(nBlockAlign);
3218                                K1(wBitsPerSample);
3219                                K1(cbSize);
3220                                #undef J
3221                                #undef K1
3222                                #undef K2
3223                                nExtraDataSize = pWaveFormatEx->cbSize;
3224                        }
3225                }
3226                #pragma endregion
3227                #pragma region Extra Data
3228                if(nExtraDataSize)
3229                {
3230                        if(!pnExtraData)
3231                        {
3232                                if(nExtraDataSize > pMediaType->cbFormat)
3233                                        nExtraDataSize = pMediaType->cbFormat;
3234                                pnExtraData = pMediaType->pbFormat + pMediaType->cbFormat - nExtraDataSize;
3235                        }
3236                        const SSIZE_T nExtraDataExcessSize = (pnExtraData + nExtraDataSize) - (pMediaType->pbFormat + pMediaType->cbFormat);
3237                        if(nExtraDataExcessSize > 0)
3238                                nExtraDataSize -= min((SIZE_T) nExtraDataExcessSize, nExtraDataSize);
3239                        sText += AtlFormatString(_T("  * ") _T("Extra Data: %s") _T("\r\n"), I(AtlFormatData(pnExtraData, nExtraDataSize).TrimRight()));
3240                }
3241                #pragma endregion
3242                return sText;
3243        }
3244        static CString GetText(IFilterGraph* pFilterGraph, const CProcessData* pProcessData = NULL)
3245        {
3246                if(!pFilterGraph)
3247                        return (LPCTSTR) NULL;
3248                const CComQIPtr<IServiceProvider> pServiceProvider = pFilterGraph;
3249                const CComQIPtr<ISpy> pSpy = pFilterGraph;
3250                CString sText;
3251                sText += AtlFormatString(_T("# ") _T("Filter Graph") _T("\r\n") _T("\r\n"));
3252                #pragma region Graph Parameters
3253                if(pProcessData)
3254                        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)));
3255                #pragma region IMediaControl
3256                OAFilterState State = (OAFilterState) -1;
3257                const CComQIPtr<IMediaControl> pMediaControl = pFilterGraph;
3258                if(pMediaControl)
3259                        _ATLTRY
3260                        {
3261                                const HRESULT nGetStateResult = pMediaControl->GetState(0, &State);
3262                                _Z45_DSHRESULT(nGetStateResult);
3263                                static const LPCTSTR g_ppszStates[] = { _T("Stopped"), _T("Paused"), _T("Running"), };
3264                                if(SUCCEEDED(nGetStateResult) && (SIZE_T) State < DIM(g_ppszStates))
3265                                        sText += AtlFormatString(_T("* ") _T("State: %s") _T("\r\n"), I(g_ppszStates[(SIZE_T) State]));
3266                        }
3267                        _ATLCATCHALL()
3268                        {
3269                                _Z_EXCEPTION();
3270                        }
3271                #pragma endregion
3272                #pragma region IMediaPosition
3273                const CComQIPtr<IMediaPosition> pMediaPosition = pFilterGraph;
3274                if(pMediaPosition)
3275                        _ATLTRY
3276                        {
3277                                DOUBLE fDuration = 0, fPosition = 0;
3278                                const HRESULT nGetDurationResult = pMediaPosition->get_Duration(&fDuration);
3279                                _Z45_DSHRESULT(nGetDurationResult);
3280                                if(fDuration > 0)
3281                                {
3282                                        sText += AtlFormatString(_T("* ") _T("Duration: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime(fDuration)), I(_StringHelper::FormatNumber(fDuration, 3)));
3283                                        const HRESULT nCurrentPositionResult = pMediaPosition->get_CurrentPosition(&fPosition);
3284                                        _Z45_DSHRESULT(nCurrentPositionResult);
3285                                        if(SUCCEEDED(nCurrentPositionResult))
3286                                                sText += AtlFormatString(_T("* ") _T("Position: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime(fPosition)), I(_StringHelper::FormatNumber(fPosition, 3)));
3287                                }
3288                        }
3289                        _ATLCATCHALL()
3290                        {
3291                                _Z_EXCEPTION();
3292                        }
3293                #pragma endregion
3294                if(pProcessData)
3295                {
3296                        if(!pProcessData->m_sDisplayName.IsEmpty())
3297                                sText += AtlFormatString(_T("* ") _T("Display Name: %s") _T("\r\n"), I(pProcessData->m_sDisplayName));
3298                        if(_tcslen(pProcessData->m_sImagePath))
3299                        {
3300                                const CString sDirectory = (LPCTSTR) GetPathDirectory(pProcessData->m_sImagePath);
3301                                if(!sDirectory.IsEmpty())
3302                                        sText += AtlFormatString(_T("* ") _T("Process Directory: %s") _T("\r\n"), I(sDirectory));
3303                        }
3304                }
3305                const CComQIPtr<IMediaFilter> pMediaFilter = pFilterGraph;
3306                CComPtr<IReferenceClock> pFilterGraphReferenceClock;
3307                const HRESULT nGetSyncSourceResult = pMediaFilter->GetSyncSource(&pFilterGraphReferenceClock);
3308                _Z45_DSHRESULT(nGetSyncSourceResult);
3309                sText += _T("\r\n");
3310                #pragma endregion
3311                #pragma region Filter
3312                _FilterGraphHelper::CFilterArray FilterArray;
3313                _FilterGraphHelper::GetGraphFilters(pFilterGraph, FilterArray);
3314                if(!FilterArray.IsEmpty())
3315                {
3316                        sText += AtlFormatString(_T("## ") _T("Filters") _T("\r\n") _T("\r\n"));
3317                        for(SIZE_T nIndex = 0; nIndex < FilterArray.GetCount(); nIndex++)
3318                                _ATLTRY
3319                                {
3320                                        const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nIndex];
3321                                        sText += AtlFormatString(_T("%d. ") _T("%ls") _T("\r\n"), nIndex + 1, _FilterGraphHelper::GetFilterName(pBaseFilter));
3322                                        sText += GetFilterText(pBaseFilter, pProcessData, pFilterGraphReferenceClock);
3323                                }
3324                                _ATLCATCHALL()
3325                                {
3326                                        _Z_EXCEPTION();
3327                                }
3328                        sText += _T("\r\n");
3329                        #pragma region Connection
3330                        sText += AtlFormatString(_T("## ") _T("Connections") _T("\r\n") _T("\r\n"));
3331                        INT nConnectionIndex = 0;
3332                        for(auto&& pBaseFilter: FilterArray)
3333                        {
3334                                _FilterGraphHelper::CPinArray PinArray;
3335                                _FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_OUTPUT, PinArray);
3336                                for(auto&& pOutputPin: PinArray)
3337                                {
3338                                        const CComPtr<IPin> pInputPin = _FilterGraphHelper::GetPeerPin(pOutputPin);
3339                                        if(!pInputPin)
3340                                                continue;
3341                                        sText += AtlFormatString(_T("%d. ") _T("%s") _T("\r\n"), ++nConnectionIndex, GetConnectionText(pOutputPin, pInputPin));
3342                                }
3343                        }
3344                        sText += _T("\r\n");
3345                        #pragma endregion
3346                        #pragma region Media Type
3347                        sText += AtlFormatString(_T("## ") _T("Media Types") _T("\r\n") _T("\r\n"));
3348                        INT nGlobalPinIndex = 0;
3349                        CRoListT<CComPtr<IPin>> PinList;
3350                        for(SIZE_T nFilterIndex = 0; nFilterIndex < FilterArray.GetCount(); nFilterIndex++)
3351                        {
3352                                const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nFilterIndex];
3353                                _FilterGraphHelper::CPinArray PinArray;
3354                                _FilterGraphHelper::GetFilterPins(pBaseFilter, PinArray);
3355                                for(SIZE_T nPinIndex = 0; nPinIndex < PinArray.GetCount(); nPinIndex++)
3356                                {
3357                                        const CComPtr<IPin>& pPin = PinArray[nPinIndex];
3358                                        if(PinList.FindFirst(pPin))
3359                                                continue;
3360                                        PinList.AddTail(pPin);
3361                                        CString sPinText = AtlFormatString(_T("%s"), I(_FilterGraphHelper::GetPinFullName(pPin)));
3362                                        const CComPtr<IPin> pPeerPin = _FilterGraphHelper::GetPeerPin(pPin);
3363                                        if(pPeerPin)
3364                                        {
3365                                                PinList.AddTail(pPeerPin);
3366                                                sPinText += AtlFormatString(_T(", %s"), I(_FilterGraphHelper::GetPinFullName(pPeerPin)));
3367                                        }
3368                                        sText += AtlFormatString(_T("%d. ") _T("%s") _T("\r\n"), ++nGlobalPinIndex, sPinText);
3369                                        _ATLTRY
3370                                        {
3371                                                CMediaType pMediaType;
3372                                                if(pPeerPin)
3373                                                        pMediaType = _FilterGraphHelper::GetPinMediaType(pPin);
3374                                                else
3375                                                        pMediaType = _FilterGraphHelper::EnumerateFirstPinMediaType(pPin);
3376                                                if(!pMediaType)
3377                                                        continue;
3378                                                sText += GetMediaTypeText(pMediaType);
3379                                        }
3380                                        _ATLCATCHALL()
3381                                        {
3382                                                _Z_EXCEPTION();
3383                                        }
3384                                }
3385                        }
3386                        sText += _T("\r\n");
3387                        #pragma endregion
3388                        if(State > State_Stopped)
3389                        {
3390                                #pragma region Memory Allocator
3391                                INT nConnectionIndex = 0;
3392                                for(auto&& pBaseFilter: FilterArray)
3393                                {
3394                                        _FilterGraphHelper::CPinArray PinArray;
3395                                        _FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_INPUT, PinArray);
3396                                        for(auto&& pInputPin: PinArray)
3397                                        {
3398                                                _ATLTRY
3399                                                {
3400                                                        const CComQIPtr<IMemInputPin> pMemInputPin = pInputPin;
3401                                                        if(!pMemInputPin)
3402                                                                continue; // No IMemInputPin
3403                                                        const CComPtr<IPin> pOutputPin = _FilterGraphHelper::GetPeerPin(pInputPin);
3404                                                        if(!pOutputPin)
3405                                                                continue; // Not Connected
3406                                                        CComPtr<IMemAllocator> pMemAllocator;
3407                                                        pMemInputPin->GetAllocator(&pMemAllocator);
3408                                                        if(!pMemAllocator)
3409                                                                continue; // No Memory Allocator
3410                                                        ALLOCATOR_PROPERTIES Properties;
3411                                                        const HRESULT nGetPropertiesResult = pMemAllocator->GetProperties(&Properties);
3412                                                        _Z45_DSHRESULT(nGetPropertiesResult);
3413                                                        if(FAILED(nGetPropertiesResult))
3414                                                                continue; // No Memory Allocator Properties
3415                                                        const CComQIPtr<IMemAllocatorCallbackTemp> pMemAllocatorCallbackTemp = pMemAllocator;
3416                                                        BOOL bFreeCountAvailable;
3417                                                        LONG nFreeCount;
3418                                                        if(pMemAllocatorCallbackTemp)
3419                                                        {
3420                                                                const HRESULT nGetFreeCountResult = pMemAllocatorCallbackTemp->GetFreeCount(&nFreeCount);
3421                                                                _Z45_DSHRESULT(nGetFreeCountResult);
3422                                                                bFreeCountAvailable = SUCCEEDED(nGetFreeCountResult);
3423                                                        } else
3424                                                                bFreeCountAvailable = FALSE;
3425                                                        CString sConnectionText = AtlFormatString(_T("%s - %s"), I(_FilterGraphHelper::GetPinFullName(pInputPin)), I(_FilterGraphHelper::GetPinFullName(pOutputPin)));
3426                                                        sConnectionText += _T(": ");
3427                                                        CRoArrayT<CString> Array;
3428                                                        Array.Add(AtlFormatString(_T("%s buffers"), I(Properties.cBuffers)));
3429                                                        if(bFreeCountAvailable)
3430                                                                Array.Add(AtlFormatString(_T("%s free buffers"), I(nFreeCount)));
3431                                                        Array.Add(AtlFormatString(_T("%s bytes per buffer"), I(Properties.cbBuffer)));
3432                                                        if(Properties.cbAlign > 1)
3433                                                                Array.Add(AtlFormatString(_T("%s byte alignment"), I(Properties.cbAlign)));
3434                                                        if(Properties.cbPrefix > 0)
3435                                                                Array.Add(AtlFormatString(_T("%s byte prefix"), I(Properties.cbPrefix)));
3436                                                        sConnectionText += _StringHelper::Join(Array, _T(", "));
3437                                                        if(!nConnectionIndex)
3438                                                                sText += AtlFormatString(_T("## ") _T("Memory Allocators") _T("\r\n") _T("\r\n"));
3439                                                        sText += AtlFormatString(_T("%d. ") _T("%s") _T("\r\n"), ++nConnectionIndex, sConnectionText);
3440                                                }
3441                                                _ATLCATCHALL()
3442                                                {
3443                                                        _Z_EXCEPTION();
3444                                                }
3445                                        }
3446                                }
3447                                if(nConnectionIndex)
3448                                        sText += _T("\r\n");
3449                                #pragma endregion
3450                        }
3451                        #pragma region IMediaSeeking
3452                        BOOL bMediaSeekingHeaderAdded = FALSE;
3453                        for(SIZE_T nFilterIndex = 0; nFilterIndex < FilterArray.GetCount(); nFilterIndex++)
3454                        {
3455                                const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nFilterIndex];
3456                                _FilterGraphHelper::CPinArray PinArray;
3457                                _FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_OUTPUT, PinArray);
3458                                for(SIZE_T nPinIndex = 0; nPinIndex < PinArray.GetCount(); nPinIndex++)
3459                                {
3460                                        const CComPtr<IPin>& pOutputPin = PinArray[nPinIndex];
3461                                        const CComQIPtr<IMediaSeeking> pMediaSeeking = pOutputPin;
3462                                        if(!pMediaSeeking)
3463                                                continue;
3464                                        if(!bMediaSeekingHeaderAdded)
3465                                        {
3466                                                sText += AtlFormatString(_T("## ") _T("Media Seeking/Position") _T("\r\n") _T("\r\n"));
3467                                                bMediaSeekingHeaderAdded = TRUE;
3468                                        }
3469                                        sText += AtlFormatString(_T("* ") _T("Pin: %s") _T("\r\n"), I(_FilterGraphHelper::GetPinFullName(pOutputPin)));
3470                                        _ATLTRY
3471                                        {
3472                                                DWORD nCapabilities = 0;
3473                                                if(SUCCEEDED(pMediaSeeking->GetCapabilities(&nCapabilities)))
3474                                                        sText += AtlFormatString(_T(" * ") _T("Capabilities: %s") _T("\r\n"), I(AtlFormatString(_T("0x%X"), nCapabilities)));
3475                                                LONGLONG nDuration = 0, nPosition = 0, nStopPosition = 0;
3476                                                if(SUCCEEDED(pMediaSeeking->GetDuration(&nDuration)))
3477                                                        sText += AtlFormatString(_T(" * ") _T("Duration: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime((DOUBLE) nDuration / 1E7)), I(_StringHelper::FormatNumber((DOUBLE) nDuration / 1E7, 3)));
3478                                                if(SUCCEEDED(pMediaSeeking->GetCurrentPosition(&nPosition)))
3479                                                        sText += AtlFormatString(_T(" * ") _T("Position: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime((DOUBLE) nPosition / 1E7)), I(_StringHelper::FormatNumber((DOUBLE) nPosition / 1E7, 3)));
3480                                                if(SUCCEEDED(pMediaSeeking->GetStopPosition(&nStopPosition)))
3481                                                        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)));
3482                                                DOUBLE fRate = 1.0;
3483                                                if(SUCCEEDED(pMediaSeeking->GetRate(&fRate)))
3484                                                        sText += AtlFormatString(_T(" * ") _T("Rate: %s") _T("\r\n"), I(_StringHelper::FormatNumber(fRate, 3)));
3485                                                LONGLONG nPreroll = 0;
3486                                                if(SUCCEEDED(pMediaSeeking->GetPreroll(&nPreroll)) && nPreroll)
3487                                                        sText += AtlFormatString(_T(" * ") _T("Preroll: %s seconds") _T("\r\n"), I(_StringHelper::FormatNumber((DOUBLE) nPreroll / 1E7, 3)));
3488                                        }
3489                                        _ATLCATCHALL()
3490                                        {
3491                                                _Z_EXCEPTION();
3492                                        }
3493                                }
3494                        }
3495                        if(bMediaSeekingHeaderAdded)
3496                                sText += _T("\r\n");
3497                        #pragma endregion
3498                        #pragma region Runtime Property Bag
3499                        const CString sRunPropertyBagHeader = AtlFormatString(_T("## ") _T("Runtime Properties") _T("\r\n") _T("\r\n"));
3500                        BOOL bRunPropertyBagHeaderAdded = FALSE;
3501                        {
3502                                const CString sPropertyBagText = CRunPropertyBagHelper::GetPropertyBagText(pFilterGraph, pSpy);
3503                                if(!sPropertyBagText.IsEmpty())
3504                                {
3505                                        sText += sRunPropertyBagHeader;
3506                                        bRunPropertyBagHeaderAdded = TRUE;
3507                                        sText += sPropertyBagText;
3508                                        sText += _T("\r\n");
3509                                }
3510                        }
3511                        for(auto&& pBaseFilter: FilterArray)
3512                        {
3513                                _ATLTRY
3514                                {
3515                                        const CString sPropertyBagText = CRunPropertyBagHelper::GetPropertyBagText(pBaseFilter, pSpy);
3516                                        if(sPropertyBagText.IsEmpty())
3517                                                continue;
3518                                        if(!bRunPropertyBagHeaderAdded)
3519                                        {
3520                                                sText += sRunPropertyBagHeader;
3521                                                bRunPropertyBagHeaderAdded = TRUE;
3522                                        }
3523                                        sText += AtlFormatString(_T("### ") _T("Filter: %ls") _T("\r\n") _T("\r\n"), _FilterGraphHelper::GetFilterName(pBaseFilter));
3524                                        sText += sPropertyBagText;
3525                                        sText += _T("\r\n");
3526                                }
3527                                _ATLCATCHALL()
3528                                {
3529                                        _Z_EXCEPTION();
3530                                }
3531                        }
3532                        #pragma endregion
3533                }
3534                #pragma endregion
3535                #pragma region Clock
3536                {
3537                        sText += AtlFormatString(_T("## ") _T("Clock") _T("\r\n") _T("\r\n"));
3538                        CComPtr<IReferenceClock> pCurrentReferenceClock;
3539                        _ATLTRY
3540                        {
3541                                const CComQIPtr<IMediaFilter> pMediaFilter = pFilterGraph;
3542                                if(pMediaFilter)
3543                                        __C(pMediaFilter->GetSyncSource(&pCurrentReferenceClock));
3544                        }
3545                        _ATLCATCHALL()
3546                        {
3547                                _Z_EXCEPTION();
3548                        }
3549                        CStringW sCurrentName;
3550                        for(auto&& pBaseFilter: FilterArray)
3551                        {
3552                                const CComQIPtr<IReferenceClock> pReferenceClock = pBaseFilter;
3553                                if(!pReferenceClock)
3554                                        continue;
3555                                const CStringW sName = _FilterGraphHelper::GetFilterName(pBaseFilter);
3556                                CRoArrayT<CString> Array;
3557                                _ATLTRY
3558                                {
3559                                        if(pCurrentReferenceClock == pReferenceClock)
3560                                        {
3561                                                sCurrentName = sName;
3562                                                Array.Add(_T("Current"));
3563                                        }
3564                                        Array.Add(I(pReferenceClock));
3565                                        REFERENCE_TIME nTime = 0;
3566                                        __C(pReferenceClock->GetTime(&nTime));
3567                                        Array.Add(I(_FilterGraphHelper::FormatReferenceTime(nTime)));
3568                                        Array.Add(I(AtlFormatString(_T("0x%I64X"), nTime)));
3569                                }
3570                                _ATLCATCHALL()
3571                                {
3572                                        _Z_EXCEPTION();
3573                                }
3574                                sText += AtlFormatString(_T(" * ") _T("%s (%s)") _T("\r\n"), I(sName), _StringHelper::Join(Array, _T(", ")));
3575                        }
3576                        if(pCurrentReferenceClock)
3577                        {
3578                                if(sCurrentName.IsEmpty())
3579                                {
3580                                        CRoArrayT<CString> Array;
3581                                        _ATLTRY
3582                                        {
3583                                                Array.Add(I(pCurrentReferenceClock));
3584                                                REFERENCE_TIME nTime = 0;
3585                                                __C(pCurrentReferenceClock->GetTime(&nTime));
3586                                                Array.Add(I(_FilterGraphHelper::FormatReferenceTime(nTime)));
3587                                                Array.Add(I(AtlFormatString(_T("0x%I64X"), nTime)));
3588                                        }
3589                                        _ATLCATCHALL()
3590                                        {
3591                                                _Z_EXCEPTION();
3592                                        }
3593                                        sText += AtlFormatString(_T(" * ") _T("Current: External (%s)") _T("\r\n"), _StringHelper::Join(Array, _T(", ")));
3594                                }
3595                        } else
3596                                sText += AtlFormatString(_T(" * ") _T("Current: None") _T("\r\n"));
3597                        sText += _T("\r\n");
3598                }
3599                #pragma endregion
3600                return sText;
3601        }
3602        #undef I
3603        CComPtr<IFilterGraph> GetFilterGraph() const
3604        {
3605                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
3606                return m_pFilterGraph;
3607        }
3608        VOID SetFilterGraph(IFilterGraph* pFilterGraph, CProcessData* pProcessData = NULL) 
3609        {
3610                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
3611                if(!pProcessData)
3612                {
3613                        m_ProcessData = CProcessData();
3614                        const CComQIPtr<ISpyEx> pSpyEx = pFilterGraph;
3615                        if(pSpyEx)
3616                                m_ProcessData.m_nIdentifier = GetCurrentProcessId();
3617                } else
3618                        m_ProcessData = *pProcessData;
3619                m_pFilterGraph = pFilterGraph;
3620        }
3621        BOOL SetFilterGraph(IUnknown* pFilterGraphUnknown, CProcessData* pProcessData = NULL) 
3622        {
3623                CComQIPtr<IFilterGraph> pFilterGraph;
3624                if(pFilterGraphUnknown)
3625                {
3626                        pFilterGraph = pFilterGraphUnknown;
3627                        if(!pFilterGraph)
3628                        {
3629                                const CComQIPtr<IBaseFilter> pBaseFilter = pFilterGraphUnknown;
3630                                if(!pBaseFilter)
3631                                {
3632                                        const CComQIPtr<IPin> pPin = pFilterGraphUnknown;
3633                                        if(pPin)
3634                                                pFilterGraph = _FilterGraphHelper::GetFilterGraph(_FilterGraphHelper::GetPinFilter(pPin));
3635                                } else
3636                                        pFilterGraph = _FilterGraphHelper::GetFilterGraph(pBaseFilter);
3637                        }
3638                }
3639                SetFilterGraph(pFilterGraph, pProcessData);
3640                return pFilterGraph != NULL;
3641        }
3642        CString GetFilterText(IBaseFilter* pBaseFilter) const
3643        {
3644                return GetFilterText(pBaseFilter, m_ProcessData.m_nIdentifier ? &m_ProcessData : NULL);
3645        }
3646        CString GetText() const
3647        {
3648                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
3649                return GetText(m_pFilterGraph, m_ProcessData.m_nIdentifier ? &m_ProcessData : NULL);
3650        }
3651        static LPCTSTR GetPlatformName()
3652        {
3653                #if defined(_WIN64)
3654                        return _T("x64");
3655                #else
3656                        return _T("Win32");
3657                #endif // defined(_WIN64)
3658        }
3659        static BOOL OpenMonikerWithGsn(LPCWSTR pszMonikerDisplayName, HWND hParentWindow = GetActiveWindow())
3660        {
3661                _A(pszMonikerDisplayName);
3662                static const LPCTSTR g_pszValueName = _T("GraphStudioNext Path");
3663                static const LPCTSTR g_pszFileName = _T("graphstudionext.exe");
3664                const CString sValueName = AtlFormatString(_T("%s (%s)"), g_pszValueName, GetPlatformName());
3665                CString sPath = _RegKeyHelper::QueryStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, sValueName);
3666                if(!FileExists(sPath))
3667                        sPath.Empty();
3668                #pragma region Current Directory
3669                if(sPath.IsEmpty())
3670                {
3671                        sPath = (LPCTSTR) Combine(GetPathDirectory(GetModulePath()), g_pszFileName);
3672                        if(!FileExists(sPath))
3673                                sPath.Empty();
3674                }
3675                #pragma endregion
3676                #pragma region Application Registry
3677                if(sPath.IsEmpty())
3678                {
3679                        #if defined(_WIN64)
3680                                static const LPCTSTR g_pszValueName = _T("exeLocation64");
3681                        #else
3682                                static const LPCTSTR g_pszValueName = _T("exeLocation");
3683                        #endif // defined(_WIN64)
3684                        sPath = _RegKeyHelper::QueryStringValue(HKEY_CURRENT_USER, _T("Software\\MONOGRAM\\GraphStudioNext"), g_pszValueName);
3685                        if(!FileExists(sPath))
3686                                sPath.Empty();
3687                }
3688                #pragma endregion
3689                if(sPath.IsEmpty())
3690                {
3691                        static const COMDLG_FILTERSPEC g_pFilter[] = 
3692                        {
3693                                { _T("Executable Files"), _T("*.exe") },
3694                                { _T("All Files"), _T("*.*") },
3695                        };
3696                        sPath = (LPCTSTR) _CommonDialogHelper::QueryOpenPath(hParentWindow, g_pFilter, _T("exe"), g_pszFileName);
3697                        if(sPath.IsEmpty())
3698                                return FALSE;
3699                        _RegKeyHelper::SetStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, sValueName, sPath);
3700                }
3701                CWaitCursor WaitCursor;
3702                CString sParameters = AtlFormatString(_T("-a \"%ls\""), pszMonikerDisplayName);
3703                SHELLEXECUTEINFO Infomation;
3704                ZeroMemory(&Infomation, sizeof Infomation);
3705                Infomation.cbSize = sizeof Infomation;
3706                Infomation.lpFile = sPath;
3707                Infomation.lpParameters = sParameters;
3708                Infomation.nShow = SW_SHOWNORMAL;
3709                __E(ShellExecuteEx(&Infomation));
3710                return TRUE;
3711        }
3712        static BOOL OpenMonikerWithGe(LPCWSTR pszMonikerDisplayName, HWND hParentWindow = GetActiveWindow())
3713        {
3714                static const LPCTSTR g_pszValueName = _T("GraphEdit Path");
3715                static const LPCTSTR g_pszFileName = _T("graphedt.exe");
3716                const CString sValueName = AtlFormatString(_T("%s (%s)"), g_pszValueName, GetPlatformName());
3717                CString sPath = _RegKeyHelper::QueryStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, sValueName);
3718                if(!FileExists(sPath))
3719                        sPath.Empty();
3720                #pragma region Current Directory
3721                if(sPath.IsEmpty())
3722                {
3723                        sPath = (LPCTSTR) Combine(GetPathDirectory(GetModulePath()), g_pszFileName);
3724                        if(!FileExists(sPath))
3725                                sPath.Empty();
3726                }
3727                #pragma endregion
3728                // SUGG: Look for Windows SDK
3729                if(sPath.IsEmpty())
3730                {
3731                        static const COMDLG_FILTERSPEC g_pFilter[] = 
3732                        {
3733                                { _T("Executable Files"), _T("*.exe") },
3734                                { _T("All Files"), _T("*.*") },
3735                        };
3736                        sPath = (LPCTSTR) _CommonDialogHelper::QueryOpenPath(hParentWindow, g_pFilter, _T("exe"), g_pszFileName);
3737                        if(sPath.IsEmpty())
3738                                return FALSE;
3739                        _RegKeyHelper::SetStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, sValueName, sPath);
3740                }
3741                CStringW sFilterGraphMonikerDisplayName = pszMonikerDisplayName;
3742                const INT nSeparatorPosition = sFilterGraphMonikerDisplayName.Find(L';');
3743                if(nSeparatorPosition >= 0)
3744                        sFilterGraphMonikerDisplayName = sFilterGraphMonikerDisplayName.Left(nSeparatorPosition);
3745                CWaitCursor WaitCursor;
3746                CString sParameters = AtlFormatString(_T("-a %ls"), sFilterGraphMonikerDisplayName);
3747                SHELLEXECUTEINFO Infomation;
3748                ZeroMemory(&Infomation, sizeof Infomation);
3749                Infomation.cbSize = sizeof Infomation;
3750                Infomation.lpFile = sPath;
3751                Infomation.lpParameters = sParameters;
3752                Infomation.nShow = SW_SHOWNORMAL;
3753                __E(ShellExecuteEx(&Infomation));
3754                return TRUE;
3755        }
3756
3757// IFilterGraphHelper
3758        STDMETHOD(get_FilterGraph)(IUnknown** ppFilterGraphUnknown)
3759        {
3760                _Z4(atlTraceCOM, 4, _T("...\n"));
3761                _ATLTRY
3762                {
3763                        __D(ppFilterGraphUnknown, E_POINTER);
3764                        *ppFilterGraphUnknown = GetFilterGraph().Detach();
3765                }
3766                _ATLCATCH(Exception)
3767                {
3768                        _C(Exception);
3769                }
3770                return S_OK;
3771        }
3772        STDMETHOD(put_FilterGraph)(IUnknown* pFilterGraphUnknown)
3773        {
3774                _Z4(atlTraceCOM, 4, _T("pFilterGraphUnknown 0x%p\n"), pFilterGraphUnknown);
3775                _ATLTRY
3776                {
3777                        if(!SetFilterGraph(pFilterGraphUnknown))
3778                                return S_FALSE;
3779                }
3780                _ATLCATCH(Exception)
3781                {
3782                        _C(Exception);
3783                }
3784                return S_OK;
3785        }
3786        STDMETHOD(get_Text)(BSTR* psText)
3787        {
3788                _Z4(atlTraceCOM, 4, _T("...\n"));
3789                _ATLTRY
3790                {
3791                        __D(psText, E_POINTER);
3792                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
3793                        *psText = CComBSTR(GetText(m_pFilterGraph)).Detach();
3794                }
3795                _ATLCATCH(Exception)
3796                {
3797                        _C(Exception);
3798                }
3799                return S_OK;
3800        }
3801        STDMETHOD(DoPropertyFrameModal)(LONG nParentWindowHandle)
3802        {
3803                _Z4(atlTraceCOM, 4, _T("nParentWindowHandle 0x%08X\n"), nParentWindowHandle);
3804                _ATLTRY
3805                {
3806                        CWindow ParentWindow = (HWND) (LONG_PTR) nParentWindowHandle;
3807                        if(!ParentWindow)
3808                                ParentWindow = GetActiveWindow();
3809                        //__D(!ParentWindow || ParentWindow.IsWindow(), E_INVALIDARG);
3810                        const CComQIPtr<IFilterGraph2> pFilterGraph2 = GetFilterGraph();
3811                        __D(pFilterGraph2, E_NOINTERFACE);
3812                        CPropertyFrameDialog PropertyFrameDialog(this);
3813                        PropertyFrameDialog.DoModal(ParentWindow);
3814                }
3815                _ATLCATCH(Exception)
3816                {
3817                        _C(Exception);
3818                }
3819                return S_OK;
3820        }
3821        STDMETHOD(DoFilterGraphListModal)(LONG nParentWindowHandle)
3822        {
3823                _Z4(atlTraceCOM, 4, _T("nParentWindowHandle 0x%08X\n"), nParentWindowHandle);
3824                _ATLTRY
3825                {
3826                        CWindow ParentWindow = (HWND) (LONG_PTR) nParentWindowHandle;
3827                        if(!ParentWindow)
3828                                ParentWindow = GetActiveWindow();
3829                        //__D(!ParentWindow || ParentWindow.IsWindow(), E_INVALIDARG);
3830                        DoFilterGraphListPropertySheetModal(ParentWindow, &m_Options);
3831                }
3832                _ATLCATCH(Exception)
3833                {
3834                        _C(Exception);
3835                }
3836                return S_OK;
3837        }
3838        STDMETHOD(OpenGraphStudioNext)(LONG nParentWindowHandle, BSTR sMonikerDisplayName, VARIANT_BOOL* pbResult)
3839        {
3840                _Z4(atlTraceCOM, 4, _T("nParentWindowHandle 0x%08X, sMonikerDisplayName \"%s\"\n"), nParentWindowHandle, CString(sMonikerDisplayName));
3841                _ATLTRY
3842                {
3843                        __D(sMonikerDisplayName && *sMonikerDisplayName, E_INVALIDARG);
3844                        CWindow ParentWindow = (HWND) (LONG_PTR) nParentWindowHandle;
3845                        if(!ParentWindow)
3846                                ParentWindow = GetActiveWindow();
3847                        //__D(!ParentWindow || ParentWindow.IsWindow(), E_INVALIDARG);
3848                        const BOOL bResult = OpenMonikerWithGsn(sMonikerDisplayName, ParentWindow);
3849                        if(pbResult)
3850                                *pbResult = bResult ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE;
3851                }
3852                _ATLCATCH(Exception)
3853                {
3854                        _C(Exception);
3855                }
3856                return S_OK;
3857        }
3858        STDMETHOD(OpenGraphEdit)(LONG nParentWindowHandle, BSTR sMonikerDisplayName, VARIANT_BOOL* pbResult)
3859        {
3860                _Z4(atlTraceCOM, 4, _T("nParentWindowHandle 0x%08X, sMonikerDisplayName \"%s\"\n"), nParentWindowHandle, CString(sMonikerDisplayName));
3861                _ATLTRY
3862                {
3863                        __D(sMonikerDisplayName && *sMonikerDisplayName, E_INVALIDARG);
3864                        CWindow ParentWindow = (HWND) (LONG_PTR) nParentWindowHandle;
3865                        if(!ParentWindow)
3866                                ParentWindow = GetActiveWindow();
3867                        //__D(!ParentWindow || ParentWindow.IsWindow(), E_INVALIDARG);
3868                        const BOOL bResult = OpenMonikerWithGe(sMonikerDisplayName, ParentWindow);
3869                        if(pbResult)
3870                                *pbResult = bResult ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE;
3871                }
3872                _ATLCATCH(Exception)
3873                {
3874                        _C(Exception);
3875                }
3876                return S_OK;
3877        }
3878        STDMETHOD(get_Options)(VARIANT* pvOptions)
3879        {
3880                _Z4(atlTraceCOM, 4, _T("...\n"));
3881                _ATLTRY
3882                {
3883                        __D(pvOptions, E_POINTER);
3884                        VariantInit(pvOptions);
3885                        __C(m_Options.GetVariant().Detach(pvOptions));
3886                }
3887                _ATLCATCH(Exception)
3888                {
3889                        _C(Exception);
3890                }
3891                return S_OK;
3892        }
3893        STDMETHOD(put_Options)(VARIANT vOptions)
3894        {
3895                _Z4(atlTraceCOM, 4, _T("vOptions.vt 0x%X\n"), vOptions.vt);
3896                _ATLTRY
3897                {
3898                        m_Options.SetVariant(vOptions);
3899                }
3900                _ATLCATCH(Exception)
3901                {
3902                        _C(Exception);
3903                }
3904                return S_OK;
3905        }
3906};
3907
3908OBJECT_ENTRY_AUTO(__uuidof(FilterGraphHelper), CFilterGraphHelper)
3909
3910inline HRESULT FilterGraphHelper_DoPropertyFrameModal(LONG nParentWindowHandle, IUnknown* pFilterGraphUnknown)
3911{
3912        CLocalObjectPtr<CFilterGraphHelper> pFilterGraphHelper;
3913        pFilterGraphHelper->SetFilterGraph(pFilterGraphUnknown);
3914        return pFilterGraphHelper->DoPropertyFrameModal(nParentWindowHandle);
3915}
3916inline HRESULT FilterGraphHelper_DoFilterGraphListModal(LONG nParentWindowHandle)
3917{
3918        CLocalObjectPtr<CFilterGraphHelper> pFilterGraphHelper;
3919        return pFilterGraphHelper->DoFilterGraphListModal(nParentWindowHandle);
3920}
3921inline HRESULT FilterGraphHelper_OpenGraphStudioNext(LONG nParentWindowHandle, LPCWSTR pszMonikerDisplayName, VARIANT_BOOL* pbResult)
3922{
3923        CLocalObjectPtr<CFilterGraphHelper> pFilterGraphHelper;
3924        return pFilterGraphHelper->OpenGraphStudioNext(nParentWindowHandle, CComBSTR(pszMonikerDisplayName), pbResult);
3925}
3926inline HRESULT FilterGraphHelper_OpenGraphEdit(LONG nParentWindowHandle, LPCWSTR pszMonikerDisplayName, VARIANT_BOOL* pbResult)
3927{
3928        CLocalObjectPtr<CFilterGraphHelper> pFilterGraphHelper;
3929        return pFilterGraphHelper->OpenGraphEdit(nParentWindowHandle, CComBSTR(pszMonikerDisplayName), pbResult);
3930}
Note: See TracBrowser for help on using the repository browser.