source: trunk/DirectShowSpy/FilterGraphHelper.h @ 937

Last change on this file since 937 was 851, checked in by roman, 6 years ago

Added filter states and intermediate states; earlier minor fixes

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