source: trunk/DirectShowSpy/FilterGraphHelper.h @ 325

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

Print clocks on the filter graph report/text

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