source: trunk/DirectShowSpy/FilterGraphHelper.h @ 537

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

Added media sample trace API and UI

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