source: trunk/DirectShowSpy/FilterGraphHelper.h @ 348

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

Fixed small issues with runtime property pages; Added named options for FG helper; Implemented AutomaticInitialCheck? and ProcessIdentifier? options in FG list

File size: 134.0 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 = GetActiveWindow(), COptions* pOptions = NULL);
30
31HRESULT FilterGraphHelper_DoPropertyFrameModal(LONG nParentWindowHandle);
32HRESULT FilterGraphHelper_DoFilterGraphListModal(LONG nParentWindowHandle);
33HRESULT FilterGraphHelper_OpenGraphStudioNext(LONG nParentWindowHandle, LPCWSTR pszMonikerDisplayName, VARIANT_BOOL* pbResult);
34HRESULT FilterGraphHelper_OpenGraphEdit(LONG nParentWindowHandle, LPCWSTR pszMonikerDisplayName, VARIANT_BOOL* pbResult);
35
36////////////////////////////////////////////////////////////
37// CRunPropertyBagPropertyPage
38
39class ATL_NO_VTABLE CRunPropertyBagPropertyPage :
40        public CComObjectRootEx<CComSingleThreadModel>,
41        public CComCoClass<CRunPropertyBagPropertyPage, &__uuidof(RunPropertyBagPropertyPage)>,
42        public COlePropertyPageT<CRunPropertyBagPropertyPage>,
43        public CDialogResize<CRunPropertyBagPropertyPage>
44{
45public:
46        enum { IDR = IDR_GENERIC_RUNPROPERTYBAG_PROPERTYPAGE };
47        enum { IDD = IDD_GENERIC_RUNPROPERTYBAG };
48
49BEGIN_COM_MAP(CRunPropertyBagPropertyPage)
50        COM_INTERFACE_ENTRY(IPropertyPage2)
51        COM_INTERFACE_ENTRY(IPropertyPage)
52END_COM_MAP()
53
54BEGIN_MSG_MAP_EX(CRunPropertyBagPropertyPage)
55        CHAIN_MSG_MAP(COlePropertyPage)
56        CHAIN_MSG_MAP(CDialogResize<CRunPropertyBagPropertyPage>)
57        MSG_WM_INITDIALOG(OnInitDialog)
58        MSG_WM_DESTROY(OnDestroy)
59        COMMAND_ID_HANDLER_EX(IDC_GENERIC_RUNPROPERTYBAG_REFRESH, OnRefresh)
60        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, &m_pOwner->m_Owner.m_Options);
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_SERVICES,
1699                                TYPE_SERVICEPROPERTYPAGE,
1700                                TYPE_MEMORYALLOCATOR,
1701                                TYPE_ACTION,
1702                                TYPE_EMAIL,
1703                                TYPE_EMAIL_LOG,
1704                        } TYPE;
1705
1706                public:
1707                        TYPE m_Type;
1708                        CComPtr<IBaseFilter> m_pBaseFilter;
1709                        CLSID m_BaseFilterClassIdentifier;
1710                        CString m_sBaseFilterClassDescription;
1711                        CString m_sBaseFilterModulePath;
1712                        CLSID m_PropertyPageClassIdentifier;
1713                        CComPtr<IPropertyPage> m_pPropertyPage;
1714                        CObjectPtr<CPropertyPageSite> m_pSite;
1715                        BOOL m_bSiteActivated;
1716
1717                public:
1718                // CData
1719                        CData(TYPE Type = TYPE_UNKNOWN) :
1720                                m_Type(Type),
1721                                m_BaseFilterClassIdentifier(CLSID_NULL),
1722                                m_PropertyPageClassIdentifier(CLSID_NULL)
1723                        {
1724                        }
1725                        CData(IBaseFilter* pBaseFilter) :
1726                                m_Type(TYPE_FILTER),
1727                                m_pBaseFilter(pBaseFilter),
1728                                m_BaseFilterClassIdentifier(CLSID_NULL),
1729                                m_PropertyPageClassIdentifier(CLSID_NULL)
1730                        {
1731                                _ATLTRY
1732                                {
1733                                        CLSID ClassIdentifier = CLSID_NULL;
1734                                        if(SUCCEEDED(pBaseFilter->GetClassID(&ClassIdentifier)) && ClassIdentifier != CLSID_NULL)
1735                                        {
1736                                                m_BaseFilterClassIdentifier = ClassIdentifier;
1737                                                const CString sClassIdentifier(_PersistHelper::StringFromIdentifier(ClassIdentifier));
1738                                                m_sBaseFilterClassDescription = _RegKeyHelper::QueryStringValue(HKEY_CLASSES_ROOT, AtlFormatString(_T("CLSID\\%s"), sClassIdentifier));
1739                                                m_sBaseFilterModulePath = _RegKeyHelper::QueryStringValue(HKEY_CLASSES_ROOT, AtlFormatString(_T("CLSID\\%s\\InprocServer32"), sClassIdentifier));
1740                                        }
1741                                }
1742                                _ATLCATCHALL()
1743                                {
1744                                        _Z_EXCEPTION();
1745                                }
1746                        }
1747                        CData(IBaseFilter* pBaseFilter, const CLSID& PropertyPageClassIdentifier, IPropertyPage* pPropertyPage) :
1748                                m_Type(TYPE_FILTERPROPERTYPAGE),
1749                                m_pBaseFilter(pBaseFilter),
1750                                m_BaseFilterClassIdentifier(CLSID_NULL),
1751                                m_PropertyPageClassIdentifier(PropertyPageClassIdentifier),
1752                                m_pPropertyPage(pPropertyPage),
1753                                m_bSiteActivated(FALSE)
1754                        {
1755                                _A(pPropertyPage);
1756                        }
1757                        CData(IPropertyPage* pPropertyPage) :
1758                                m_Type(TYPE_SERVICEPROPERTYPAGE),
1759                                m_BaseFilterClassIdentifier(CLSID_NULL),
1760                                m_PropertyPageClassIdentifier(CLSID_NULL),
1761                                m_pPropertyPage(pPropertyPage),
1762                                m_bSiteActivated(FALSE)
1763                        {
1764                                _A(pPropertyPage);
1765                        }
1766                        CString GetPropertyPageTitle() const
1767                        {
1768                                if(!m_pPropertyPage)
1769                                        return _T("");
1770                                PROPPAGEINFO PageInformation;
1771                                ZeroMemory(&PageInformation, sizeof PageInformation);
1772                                PageInformation.cb = sizeof PageInformation;
1773                                __C(m_pPropertyPage->GetPageInfo(&PageInformation));
1774                                CString sTitle(PageInformation.pszTitle);
1775                                CoTaskMemFree(PageInformation.pszTitle);
1776                                CoTaskMemFree(PageInformation.pszDocString);
1777                                CoTaskMemFree(PageInformation.pszHelpFile);
1778                                return sTitle;
1779                        }
1780                };
1781
1782                ////////////////////////////////////////////////////
1783                // CObjectPropertyPage
1784
1785                class CObjectPropertyPage
1786                {
1787                public:
1788                        CComPtr<IUnknown> m_pUnknown;
1789                        CComPtr<IPropertyPage> m_pPropertyPage;
1790
1791                public:
1792                // CObjectPropertyPage
1793                        CObjectPropertyPage()
1794                        {
1795                        }
1796                        CObjectPropertyPage(IUnknown* pUnknown, IPropertyPage* pPropertyPage) :
1797                                m_pUnknown(pUnknown),
1798                                m_pPropertyPage(pPropertyPage)
1799                        {
1800                        }
1801                };
1802
1803                typedef CRoArrayT<CObjectPropertyPage> CObjectPropertyPageArray;
1804
1805        private:
1806                CFilterGraphHelper& m_Owner;
1807                BOOL m_bActivating; 
1808                CRoTreeViewT<CData, CRoListControlDataTraitsT> m_TreeView;
1809                CTreeItem m_FiltersItem;
1810                CTreeItem m_MemoryAllocatorItem;
1811                CTreeItem m_ActionItem;
1812                CTreeItem m_EmailItem;
1813                CTreeItem m_EmailLogItem;
1814                CTabCtrl m_Tab;
1815                CRoEdit m_TextEdit;
1816                CRect m_TextPosition;
1817                CFont m_TextFont;
1818                CButton m_OkButton;
1819                CButton m_CancelButton;
1820                CButton m_ApplyButton;
1821                CObjectPtr<CPropertyPageSite> m_pCurrentSite;
1822                CMemoryAllocatorDialog m_MemoryAllocatorDialog;
1823                CActionDialog m_ActionDialog;
1824                CEmailDialog m_EmailDialog;
1825                CEmailLogDialog m_EmailLogDialog;
1826
1827                static VOID CreateTitleFont(CFont& Font, HWND hStaticWindow = NULL)
1828                {
1829                        _A(!Font);
1830                        CLogFont LogFont;
1831                        LogFont.SetHeight(12);
1832                        LogFont.lfWeight = FW_BOLD;
1833                        _tcsncpy_s(LogFont.lfFaceName, _T("Verdana"), _TRUNCATE);
1834                        _W(Font.CreateFontIndirect(&LogFont));
1835                        if(hStaticWindow)
1836                                CStatic(hStaticWindow).SetFont(Font);
1837                }
1838
1839        public:
1840        // CPropertyFrameDialog
1841                CPropertyFrameDialog(CFilterGraphHelper* pOwner) :
1842                        m_Owner(*pOwner)
1843                {
1844                }
1845                CRect GetTextEditPosition() const
1846                {
1847                        CRect Position;
1848                        _W(m_TextEdit.GetWindowRect(Position));
1849                        _W(ScreenToClient(Position));
1850                        return Position;
1851                }
1852                VOID UpdateTree()
1853                {
1854                        CWindowRedraw TreeViewRedraw(m_TreeView);
1855                        m_TreeView.DeleteAllItems();
1856                        CTreeItem LastItem;
1857                        #pragma region Filter
1858                        CTreeItem FiltersItem = m_TreeView.InsertItem(NULL, NULL, CData(CData::TYPE_FILTERS), _T("Filters"));
1859                        _FilterGraphHelper::CFilterArray FilterArray;
1860                        _FilterGraphHelper::GetGraphFilters(m_Owner.m_pFilterGraph, FilterArray);
1861                        CTreeItem PreviousFilterItem;
1862                        for(SIZE_T nIndex = 0; nIndex < FilterArray.GetCount(); nIndex++)
1863                        {
1864                                const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nIndex];
1865                                CData Data(pBaseFilter);
1866                                CString sText(_FilterGraphHelper::GetFilterName(pBaseFilter));
1867                                if(!Data.m_sBaseFilterClassDescription.IsEmpty() && sText.Find(Data.m_sBaseFilterClassDescription) < 0)
1868                                        sText += AtlFormatString(_T(" (%s)"), Data.m_sBaseFilterClassDescription);
1869                                CTreeItem FilterItem = m_TreeView.InsertItem(FiltersItem, PreviousFilterItem, Data, sText);
1870                                PreviousFilterItem = FilterItem;
1871                                #pragma region Property Page
1872                                const CComQIPtr<ISpecifyPropertyPages> pSpecifyPropertyPages = pBaseFilter;
1873                                if(!pSpecifyPropertyPages)
1874                                        continue;
1875                                _ATLTRY
1876                                {
1877                                        CAUUID Pages;
1878                                        ZeroMemory(&Pages, sizeof Pages);
1879                                        __C(pSpecifyPropertyPages->GetPages(&Pages));
1880                                        CComHeapPtr<CLSID> pClassIdentifiers;
1881                                        pClassIdentifiers.Attach(Pages.pElems);
1882                                        CTreeItem PreviousPageItem;
1883                                        for(UINT nPageIndex = 0; nPageIndex < Pages.cElems; nPageIndex++)
1884                                        {
1885                                                const CLSID& ClassIdentifier = pClassIdentifiers[nPageIndex];
1886                                                if(ClassIdentifier == CLSID_NULL)
1887                                                        continue;
1888                                                _ATLTRY
1889                                                {
1890                                                        CComPtr<IPropertyPage> pPropertyPage;
1891                                                        __C(pPropertyPage.CoCreateInstance(ClassIdentifier));
1892                                                        CData Data(pBaseFilter, ClassIdentifier, pPropertyPage);
1893                                                        Data.m_pSite.Construct()->Initialize(this, pBaseFilter, pPropertyPage);
1894                                                        CTreeItem PageItem = m_TreeView.InsertItem(FilterItem, PreviousPageItem, Data, Data.GetPropertyPageTitle());
1895                                                        PreviousPageItem = PageItem;
1896                                                }
1897                                                _ATLCATCHALL()
1898                                                {
1899                                                        _Z_EXCEPTION();
1900                                                }
1901                                        }
1902                                        m_TreeView.Expand(FilterItem);
1903                                }
1904                                _ATLCATCHALL()
1905                                {
1906                                        _Z_EXCEPTION();
1907                                }
1908                                #pragma endregion
1909                        }
1910                        m_TreeView.Expand(FiltersItem);
1911                        m_FiltersItem.m_hTreeItem = FiltersItem;
1912                        m_FiltersItem.m_pTreeView = &m_TreeView;
1913                        LastItem = FiltersItem;
1914                        #pragma endregion
1915                        #pragma region Services
1916                        _ATLTRY
1917                        {
1918                                CObjectPropertyPageArray ObjectPropertyPageArray;
1919                                const CComQIPtr<IServiceProvider> pServiceProvider = m_Owner.m_pFilterGraph;
1920                                if(pServiceProvider)
1921                                {
1922                                        #pragma region RunPropertyBagAware
1923                                        CComPtr<IRunPropertyBagAware> pRunPropertyBagAware;
1924                                        if(SUCCEEDED(pServiceProvider->QueryService<IRunPropertyBagAware>(__uuidof(IRunPropertyBagAware), &pRunPropertyBagAware)))
1925                                                _ATLTRY
1926                                                {
1927                                                        _A(pRunPropertyBagAware);
1928                                                        CObjectPtr<CRunPropertyBagPropertyPage> pRunPropertyBagPropertyPage;
1929                                                        pRunPropertyBagPropertyPage.Construct();
1930                                                        ObjectPropertyPageArray.Add(CObjectPropertyPage(pRunPropertyBagAware, pRunPropertyBagPropertyPage));
1931                                                }
1932                                                _ATLCATCHALL()
1933                                                {
1934                                                        _Z_EXCEPTION();
1935                                                }
1936                                        #pragma endregion
1937                                        #pragma region RunEventAware
1938                                        CComPtr<IRunEventAware> pRunEventAware;
1939                                        if(SUCCEEDED(pServiceProvider->QueryService<IRunEventAware>(__uuidof(IRunEventAware), &pRunEventAware)))
1940                                                _ATLTRY
1941                                                {
1942                                                        _A(pRunEventAware);
1943                                                        CObjectPtr<CRunEventPropertyPage> pRunEventPropertyPage;
1944                                                        pRunEventPropertyPage.Construct();
1945                                                        ObjectPropertyPageArray.Add(CObjectPropertyPage(pRunEventAware, pRunEventPropertyPage));
1946                                                }
1947                                                _ATLCATCHALL()
1948                                                {
1949                                                        _Z_EXCEPTION();
1950                                                }
1951                                        #pragma endregion
1952                                }
1953                                if(!ObjectPropertyPageArray.IsEmpty())
1954                                {
1955                                        CTreeItem ServicesItem = m_TreeView.InsertItem(NULL, LastItem, CData(CData::TYPE_SERVICES), _T("Services"));
1956                                        LastItem = ServicesItem;
1957                                        CTreeItem PreviousServiceItem;
1958                                        for(auto&& ObjectPropertyPage: ObjectPropertyPageArray)
1959                                        {
1960                                                CData Data(ObjectPropertyPage.m_pPropertyPage);
1961                                                Data.m_pSite.Construct()->Initialize(this, ObjectPropertyPage.m_pUnknown, ObjectPropertyPage.m_pPropertyPage);
1962                                                CTreeItem ServiceItem = m_TreeView.InsertItem(ServicesItem, PreviousServiceItem, Data, Data.GetPropertyPageTitle());
1963                                                PreviousServiceItem = ServiceItem;
1964                                        }
1965                                        m_TreeView.Expand(ServicesItem);
1966                                }
1967                        }
1968                        _ATLCATCHALL()
1969                        {
1970                                _Z_EXCEPTION();
1971                        }
1972                        #pragma endregion
1973                        #pragma region Other
1974                        CTreeItem MemoryAllocatorItem = m_TreeView.InsertItem(NULL, LastItem, CData(CData::TYPE_MEMORYALLOCATOR), _T("Memory Allocators"));
1975                        m_MemoryAllocatorItem.m_hTreeItem = MemoryAllocatorItem;
1976                        m_MemoryAllocatorItem.m_pTreeView = &m_TreeView;
1977                        CTreeItem ActionItem = m_TreeView.InsertItem(NULL, MemoryAllocatorItem, CData(CData::TYPE_ACTION), _T("Action"));
1978                        m_ActionItem.m_hTreeItem = ActionItem;
1979                        m_ActionItem.m_pTreeView = &m_TreeView;
1980                        CTreeItem EmailItem = m_TreeView.InsertItem(NULL, ActionItem, CData(CData::TYPE_EMAIL), _T("Email"));
1981                        m_EmailItem.m_hTreeItem = EmailItem;
1982                        m_EmailItem.m_pTreeView = &m_TreeView;
1983                        CTreeItem EmailLogItem = m_TreeView.InsertItem(EmailItem, NULL, CData(CData::TYPE_EMAIL_LOG), _T("Log Files"));
1984                        m_EmailLogItem.m_hTreeItem = EmailLogItem;
1985                        m_EmailLogItem.m_pTreeView = &m_TreeView;
1986                        #pragma endregion
1987                        m_TreeView.Expand(EmailItem);
1988                }
1989                VOID HideCurrentSite()
1990                {
1991                        if(!m_pCurrentSite)
1992                                return;
1993                        if(m_pCurrentSite->m_pPropertyPage)
1994                                __C(m_pCurrentSite->m_pPropertyPage->Show(SW_HIDE));
1995                        m_pCurrentSite.Release();
1996                }
1997                VOID HandleStatusChange(CPropertyPageSite* pPropertyPageSite)
1998                {
1999                        _A(pPropertyPageSite);
2000                        m_ApplyButton.EnableWindow(pPropertyPageSite->IsDirty());
2001                }
2002                VOID Apply()
2003                {
2004                        if(!m_pCurrentSite || !m_pCurrentSite->m_pPropertyPage)
2005                                return;
2006                        __C(m_pCurrentSite->m_pPropertyPage->Apply());
2007                        HandleStatusChange(m_pCurrentSite);
2008                }
2009                INT_PTR DoModal(HWND hParentWindow = GetActiveWindow())
2010                {
2011                        return CDialogWithAccelerators::DoModal(hParentWindow);
2012                }
2013
2014        // CDialogResize
2015                VOID DlgResize_UpdateLayout(INT nWidth, INT nHeight)
2016                {
2017                        __super::DlgResize_UpdateLayout(nWidth, nHeight);
2018                        const CRect Position = GetTextEditPosition();
2019                        if(m_pCurrentSite && m_pCurrentSite->m_pPropertyPage)
2020                                _V(m_pCurrentSite->m_pPropertyPage->Move(Position));
2021                        _W(m_MemoryAllocatorDialog.SetWindowPos(NULL, Position, SWP_NOZORDER | SWP_NOACTIVATE));
2022                        _W(m_ActionDialog.SetWindowPos(NULL, Position, SWP_NOZORDER | SWP_NOACTIVATE));
2023                        _W(m_EmailDialog.SetWindowPos(NULL, Position, SWP_NOZORDER | SWP_NOACTIVATE));
2024                        _W(m_EmailLogDialog.SetWindowPos(NULL, Position, SWP_NOZORDER | SWP_NOACTIVATE));
2025                }
2026
2027        // Window Message Handler
2028                LRESULT OnInitDialog(HWND, LPARAM)
2029                {
2030                        m_bActivating = TRUE;
2031                        _ATLTRY
2032                        {
2033                                CWaitCursor WaitCursor;
2034                                #pragma region Bitness Indication
2035                                CString sCaption;
2036                                _W(GetWindowText(sCaption));
2037                                #if defined(_WIN64)
2038                                        sCaption.Append(_T(" (64-bit)"));
2039                                #else
2040                                        if(SafeIsWow64Process())
2041                                                sCaption.Append(_T(" (32-bit)"));
2042                                #endif // defined(_WIN64)
2043                                _W(SetWindowText(sCaption));
2044                                #pragma endregion
2045                                #pragma region System Menu
2046                                CMenuHandle Menu = GetSystemMenu(FALSE);
2047                                _W(Menu.AppendMenu(MF_SEPARATOR));
2048                                _W(Menu.AppendMenu(MF_STRING, ID_APP_ABOUT, _T("&About...")));
2049                                #pragma endregion
2050                                #pragma region Icon
2051                                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_COLOR, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)), TRUE);
2052                                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_COLOR, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)), FALSE);
2053                                #pragma endregion
2054                                m_TreeView.Initialize(GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TREE));
2055                                m_TextEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TEXT);
2056                                CRect TextPosition;
2057                                _W(m_TextEdit.GetWindowRect(TextPosition));
2058                                _W(ScreenToClient(TextPosition));
2059                                m_TextPosition = TextPosition;
2060                                CLogFont TextFont;
2061                                CFontHandle(AtlGetDefaultGuiFont()).GetLogFont(TextFont);
2062                                _tcsncpy_s(TextFont.lfFaceName, _T("Courier New"), _TRUNCATE);
2063                                TextFont.SetHeight(8);
2064                                m_TextFont = TextFont.CreateFontIndirect();
2065                                m_TextEdit.SetFont(m_TextFont);
2066                                m_OkButton = GetDlgItem(IDOK);
2067                                m_CancelButton = GetDlgItem(IDCANCEL);
2068                                m_ApplyButton = GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_APPLY);
2069                                __E(m_MemoryAllocatorDialog.Create(m_hWnd, (LPARAM) this));
2070                                __E(m_ActionDialog.Create(m_hWnd, (LPARAM) this));
2071                                __E(m_EmailDialog.Create(m_hWnd, (LPARAM) this));
2072                                __E(m_EmailLogDialog.Create(m_hWnd, (LPARAM) this));
2073                                DlgResize_Init(TRUE);
2074                                UpdateTree();
2075                                m_FiltersItem.Select();
2076                                m_FiltersItem.EnsureVisible();
2077                                CRect Position;
2078                                _W(GetWindowRect(Position));
2079                                Position.right += Position.Width() / 2;
2080                                Position.bottom += Position.Width() / 4;
2081                                _W(SetWindowPos(NULL, Position, SWP_NOMOVE | SWP_NOZORDER));
2082                                _W(CenterWindow());
2083                                m_bActivating = FALSE;
2084                        }
2085                        _ATLCATCH(Exception)
2086                        {
2087                                for(CWindow Window = GetWindow(GW_CHILD); Window; Window = Window.GetWindow(GW_HWNDNEXT))
2088                                        Window.EnableWindow(FALSE);
2089                                AtlExceptionMessageBox(m_hWnd, Exception);
2090                        }
2091                        return TRUE;
2092                }
2093                LRESULT OnDestroy()
2094                {
2095                        #pragma region Deactivate and Terminate Sites
2096                        for(POSITION Position = m_TreeView.GetDataList().GetHeadPosition(); Position; m_TreeView.GetDataList().GetNext(Position))
2097                        {
2098                                CData& Data = m_TreeView.GetDataList().GetAt(Position);
2099                                if(!Data.m_pSite)
2100                                        continue;
2101                                if(Data.m_bSiteActivated)
2102                                {
2103                                        const HRESULT nDeactivateResult = Data.m_pPropertyPage->Deactivate();
2104                                        _Z35_DSHRESULT(nDeactivateResult);
2105                                        Data.m_bSiteActivated = FALSE;
2106                                }
2107                                Data.m_pSite->Terminate();
2108                        }
2109                        #pragma endregion
2110                        return 0;
2111                }
2112                LRESULT OnTreeViewGetInfoTip(NMTVGETINFOTIP* pHeader)
2113                {
2114                        _A(pHeader);
2115                        if(!pHeader->hItem) 
2116                                return 0;
2117                        CData& Data = m_TreeView.GetItemData(pHeader->hItem);
2118                        CString sInfoTip;
2119                        if(Data.m_pBaseFilter)
2120                        {
2121                                if(!Data.m_pPropertyPage)
2122                                {
2123                                        sInfoTip.AppendFormat(_T("Name: %ls") _T("\r\n"), _FilterGraphHelper::GetFilterName(Data.m_pBaseFilter));
2124                                        if(Data.m_BaseFilterClassIdentifier != CLSID_NULL)
2125                                                sInfoTip.AppendFormat(_T("Class Identifier: %ls") _T("\r\n"), _PersistHelper::StringFromIdentifier(Data.m_BaseFilterClassIdentifier));
2126                                        if(!Data.m_sBaseFilterClassDescription.IsEmpty())
2127                                                sInfoTip.AppendFormat(_T("Class Description: %s") _T("\r\n"), Data.m_sBaseFilterClassDescription);
2128                                        if(!Data.m_sBaseFilterModulePath.IsEmpty())
2129                                                sInfoTip.AppendFormat(_T("Module Path: %s") _T("\r\n"), Data.m_sBaseFilterModulePath);
2130                                } else
2131                                {
2132                                        // TODO: ...
2133                                }
2134                        }
2135                        sInfoTip.TrimRight(_T("\t\n\r "));
2136                        _tcsncpy_s(pHeader->pszText, pHeader->cchTextMax, sInfoTip, _TRUNCATE);
2137                        #pragma region Clipboard Copy
2138                        if(GetKeyState(VK_CONTROL) < 0 && GetKeyState(VK_SHIFT) < 0)
2139                                _ATLTRY
2140                                {
2141                                        SetClipboardText(m_hWnd, sInfoTip);
2142                                        MessageBeep(MB_OK);
2143                                }
2144                                _ATLCATCHALL()
2145                                {
2146                                        _Z_EXCEPTION();
2147                                        MessageBeep(MB_ICONERROR);
2148                                }
2149                        #pragma endregion
2150                        return 0;
2151                }
2152                LRESULT OnTreeViewSelChanged(NMTREEVIEW* pHeader)
2153                {
2154                        _A(pHeader);
2155                        #pragma region Tree Item
2156                        CTreeItem TreeItem(pHeader->itemNew.hItem);
2157                        if(TreeItem)
2158                        {
2159                                CData& Data = m_TreeView.GetItemData(TreeItem);
2160                                if(Data.m_Type != CData::TYPE_MEMORYALLOCATOR)
2161                                        m_MemoryAllocatorDialog.ShowWindow(SW_HIDE);
2162                                if(Data.m_Type != CData::TYPE_ACTION)
2163                                        m_ActionDialog.ShowWindow(SW_HIDE);
2164                                if(Data.m_Type != CData::TYPE_EMAIL)
2165                                        m_EmailDialog.ShowWindow(SW_HIDE);
2166                                if(Data.m_Type != CData::TYPE_EMAIL_LOG)
2167                                        m_EmailLogDialog.ShowWindow(SW_HIDE);
2168                                #pragma region Filter
2169                                if(Data.m_pBaseFilter)
2170                                {
2171                                        #pragma region Property Page
2172                                        if(Data.m_pPropertyPage)
2173                                        {
2174                                                m_TextEdit.ShowWindow(SW_HIDE);
2175                                                if(Data.m_pSite != m_pCurrentSite)
2176                                                        HideCurrentSite();
2177                                                if(!Data.m_bSiteActivated)
2178                                                {
2179                                                        __C(Data.m_pPropertyPage->Activate(m_hWnd, GetTextEditPosition(), TRUE));
2180                                                        Data.m_bSiteActivated = TRUE;
2181                                                } else
2182                                                        __C(Data.m_pPropertyPage->Move(GetTextEditPosition()));
2183                                                __C(Data.m_pPropertyPage->Show(SW_SHOWNORMAL));
2184                                                m_pCurrentSite = Data.m_pSite;
2185                                                HandleStatusChange(m_pCurrentSite);
2186                                        } else
2187                                        #pragma endregion
2188                                        #pragma region Text
2189                                        {
2190                                                CWaitCursor WaitCursor;
2191                                                HideCurrentSite();
2192                                                m_TextEdit.ShowWindow(SW_SHOW);
2193                                                CString sText;
2194                                                sText += AtlFormatString(_T("## ") _T("Filter %ls") _T("\r\n") _T("\r\n"), _FilterGraphHelper::GetFilterName(Data.m_pBaseFilter));
2195                                                sText += m_Owner.GetFilterText(Data.m_pBaseFilter);
2196                                                sText += _T("\r\n");
2197                                                #pragma region Connection
2198                                                _FilterGraphHelper::CPinArray InputPinArray, OutputPinArray;
2199                                                _FilterGraphHelper::GetFilterPins(Data.m_pBaseFilter, PINDIR_INPUT, InputPinArray);
2200                                                _FilterGraphHelper::GetFilterPins(Data.m_pBaseFilter, PINDIR_OUTPUT, OutputPinArray);
2201                                                if(!InputPinArray.IsEmpty() || !OutputPinArray.IsEmpty())
2202                                                {
2203                                                        sText += AtlFormatString(_T("## ") _T("Connections") _T("\r\n") _T("\r\n"));
2204                                                        if(!InputPinArray.IsEmpty())
2205                                                        {
2206                                                                sText += AtlFormatString(_T("### ") _T("Input") _T("\r\n") _T("\r\n"));
2207                                                                for(SIZE_T nPinIndex = 0; nPinIndex < InputPinArray.GetCount(); nPinIndex++)
2208                                                                {
2209                                                                        const CComPtr<IPin>& pInputPin = InputPinArray[nPinIndex];
2210                                                                        const CComPtr<IPin> pOutputPin = _FilterGraphHelper::GetPeerPin(pInputPin);
2211                                                                        if(!pOutputPin)
2212                                                                                continue;
2213                                                                        sText += AtlFormatString(_T(" * ") _T("%s") _T("\r\n"), m_Owner.GetConnectionText(pOutputPin, pInputPin));
2214                                                                }
2215                                                                sText += _T("\r\n");
2216                                                        }
2217                                                        if(!OutputPinArray.IsEmpty())
2218                                                        {
2219                                                                sText += AtlFormatString(_T("### ") _T("Output") _T("\r\n") _T("\r\n"));
2220                                                                for(SIZE_T nPinIndex = 0; nPinIndex < OutputPinArray.GetCount(); nPinIndex++)
2221                                                                {
2222                                                                        const CComPtr<IPin>& pOutputPin = OutputPinArray[nPinIndex];
2223                                                                        const CComPtr<IPin> pInputPin = _FilterGraphHelper::GetPeerPin(pOutputPin);
2224                                                                        if(!pInputPin)
2225                                                                                continue;
2226                                                                        sText += AtlFormatString(_T(" * ") _T("%s") _T("\r\n"), m_Owner.GetConnectionText(pOutputPin, pInputPin));
2227                                                                }
2228                                                                sText += _T("\r\n");
2229                                                        }
2230                                                }
2231                                                #pragma endregion
2232                                                #pragma region Media Type
2233                                                _FilterGraphHelper::CPinArray PinArray;
2234                                                if(_FilterGraphHelper::GetFilterPins(Data.m_pBaseFilter, PinArray))
2235                                                {
2236                                                        sText += AtlFormatString(_T("## ") _T("Media Types") _T("\r\n") _T("\r\n"));
2237                                                        for(SIZE_T nPinIndex = 0; nPinIndex < PinArray.GetCount(); nPinIndex++)
2238                                                        {
2239                                                                const CComPtr<IPin>& pPin = PinArray[nPinIndex];
2240                                                                CString sPinText = AtlFormatString(_T("%s"), FormatIdentifier(_FilterGraphHelper::GetPinFullName(pPin)));
2241                                                                const CComPtr<IPin> pPeerPin = _FilterGraphHelper::GetPeerPin(pPin);
2242                                                                if(pPeerPin)
2243                                                                        sPinText += AtlFormatString(_T(", %s"), FormatIdentifier(_FilterGraphHelper::GetPinFullName(pPeerPin)));
2244                                                                sText += AtlFormatString(_T("%d. ") _T("%s") _T("\r\n"), 1 + nPinIndex, sPinText);
2245                                                                _ATLTRY
2246                                                                {
2247                                                                        CMediaType pMediaType;
2248                                                                        if(pPeerPin)
2249                                                                                pMediaType = _FilterGraphHelper::GetPinMediaType(pPin);
2250                                                                        else
2251                                                                                pMediaType = _FilterGraphHelper::EnumerateFirstPinMediaType(pPin);
2252                                                                        if(!pMediaType)
2253                                                                                continue;
2254                                                                        sText += m_Owner.GetMediaTypeText(pMediaType);
2255                                                                }
2256                                                                _ATLCATCHALL()
2257                                                                {
2258                                                                        _Z_EXCEPTION();
2259                                                                }
2260                                                        }
2261                                                        sText += _T("\r\n");
2262                                                }
2263                                                #pragma endregion
2264                                                #pragma region Runtime Property Bag
2265                                                _ATLTRY
2266                                                {
2267                                                        const CString sPropertyBagText = CRunPropertyBagHelper::GetPropertyBagText(Data.m_pBaseFilter, CComQIPtr<ISpy>(m_Owner.m_pFilterGraph));
2268                                                        if(!sPropertyBagText.IsEmpty())
2269                                                        {
2270                                                                sText += AtlFormatString(_T("## ") _T("Runtime Properties") _T("\r\n") _T("\r\n"));
2271                                                                sText += sPropertyBagText;
2272                                                                sText += _T("\r\n");
2273                                                        }
2274                                                }
2275                                                _ATLCATCHALL()
2276                                                {
2277                                                        _Z_EXCEPTION();
2278                                                }
2279                                                #pragma endregion
2280                                                m_TextEdit.SetValue(sText);
2281                                                m_ApplyButton.EnableWindow(FALSE);
2282                                        }
2283                                        #pragma endregion
2284                                } else
2285                                #pragma endregion
2286                                #pragma region Service Property Page
2287                                if(Data.m_pPropertyPage)
2288                                {
2289                                        m_TextEdit.ShowWindow(SW_HIDE);
2290                                        if(Data.m_pSite != m_pCurrentSite)
2291                                                HideCurrentSite();
2292                                        if(!Data.m_bSiteActivated)
2293                                        {
2294                                                __C(Data.m_pPropertyPage->Activate(m_hWnd, GetTextEditPosition(), TRUE));
2295                                                Data.m_bSiteActivated = TRUE;
2296                                        } else
2297                                                __C(Data.m_pPropertyPage->Move(GetTextEditPosition()));
2298                                        __C(Data.m_pPropertyPage->Show(SW_SHOWNORMAL));
2299                                        m_pCurrentSite = Data.m_pSite;
2300                                        HandleStatusChange(m_pCurrentSite);
2301                                } else
2302                                #pragma endregion
2303                                #pragma region Other
2304                                {
2305                                        CWaitCursor WaitCursor;
2306                                        HideCurrentSite();
2307                                        switch(Data.m_Type)
2308                                        {
2309                                        #pragma region TYPE_MEMORYALLOCATOR
2310                                        case CData::TYPE_MEMORYALLOCATOR:
2311                                                m_TextEdit.ShowWindow(SW_HIDE);
2312                                                _W(m_MemoryAllocatorDialog.SetWindowPos(NULL, GetTextEditPosition(), SWP_NOZORDER | SWP_SHOWWINDOW));
2313                                                break;
2314                                        #pragma endregion
2315                                        #pragma region TYPE_ACTION
2316                                        case CData::TYPE_ACTION:
2317                                                m_TextEdit.ShowWindow(SW_HIDE);
2318                                                _W(m_ActionDialog.SetWindowPos(NULL, GetTextEditPosition(), SWP_NOZORDER | SWP_SHOWWINDOW));
2319                                                break;
2320                                        #pragma endregion
2321                                        #pragma region TYPE_EMAIL
2322                                        case CData::TYPE_EMAIL:
2323                                                m_TextEdit.ShowWindow(SW_HIDE);
2324                                                _W(m_EmailDialog.SetWindowPos(NULL, GetTextEditPosition(), SWP_NOZORDER | SWP_SHOWWINDOW));
2325                                                break;
2326                                        #pragma endregion
2327                                        #pragma region TYPE_EMAIL_LOG
2328                                        case CData::TYPE_EMAIL_LOG:
2329                                                m_TextEdit.ShowWindow(SW_HIDE);
2330                                                _W(m_EmailLogDialog.SetWindowPos(NULL, GetTextEditPosition(), SWP_NOZORDER | SWP_SHOWWINDOW));
2331                                                break;
2332                                        #pragma endregion
2333                                        default:
2334                                                m_TextEdit.ShowWindow(SW_SHOW);
2335                                                m_TextEdit.SetValue(m_Owner.GetText());
2336                                                m_MemoryAllocatorDialog.ShowWindow(SW_HIDE);
2337                                                m_ActionDialog.ShowWindow(SW_HIDE);
2338                                                m_EmailDialog.ShowWindow(SW_HIDE);
2339                                                m_EmailLogDialog.ShowWindow(SW_HIDE);
2340                                        }
2341                                        m_ApplyButton.EnableWindow(FALSE);
2342                                }
2343                                #pragma endregion
2344                        } else
2345                        #pragma endregion
2346                        #pragma region No Tree Item
2347                        {
2348                                HideCurrentSite();
2349                                m_TextEdit.ShowWindow(SW_HIDE);
2350                                m_MemoryAllocatorDialog.ShowWindow(SW_HIDE);
2351                                m_ActionDialog.ShowWindow(SW_HIDE);
2352                                m_EmailDialog.ShowWindow(SW_HIDE);
2353                                m_EmailLogDialog.ShowWindow(SW_HIDE);
2354                                m_ApplyButton.EnableWindow(FALSE);
2355                        }
2356                        #pragma endregion
2357                        return 0;
2358                }
2359                LRESULT OnTreeViewItemExplanding(NMTREEVIEW* pHeader)
2360                {
2361                        if(pHeader->action == TVE_COLLAPSE)
2362                                return TRUE; // Prevent Collapsing
2363                        return 0;
2364                }
2365                LRESULT OnTreeViewDblClk(NMHDR*)
2366                {
2367                        CTreeItem TreeItem = m_TreeView.GetSelectedItem();
2368                        if(!TreeItem)
2369                                return 0;
2370                        CData& Data = m_TreeView.GetItemData(TreeItem);
2371                        if(!Data.m_pBaseFilter)
2372                                return 0;
2373                        COlePropertyFrameDialog Dialog(Data.m_pBaseFilter);
2374                        if(!Dialog.SetObjectPages())
2375                                return 0;
2376                        Dialog.DoModal(m_hWnd);
2377                        return 0;
2378                }
2379                LRESULT OnSysCommand(UINT nCommand, CPoint)
2380                {
2381                        switch(nCommand)
2382                        {
2383                        case ID_APP_ABOUT:
2384                                {
2385                                        CAboutDialog Dialog;
2386                                        Dialog.DoModal(m_hWnd);
2387                                }
2388                                break;
2389                        default:
2390                                SetMsgHandled(FALSE);
2391                        }
2392                        return 0;
2393                }
2394                LRESULT OnOk(UINT, INT nIdentifier, HWND)
2395                {
2396                        _ATLTRY
2397                        {
2398                                #pragma region Apply All
2399                                for(POSITION Position = m_TreeView.GetDataList().GetHeadPosition(); Position; m_TreeView.GetDataList().GetNext(Position))
2400                                {
2401                                        CData& Data = m_TreeView.GetDataList().GetAt(Position);
2402                                        if(!Data.m_pSite)
2403                                                continue;
2404                                        _A(Data.m_pPropertyPage);
2405                                        if(Data.m_bSiteActivated && Data.m_pSite->IsDirty())
2406                                                __C(Data.m_pPropertyPage->Apply());
2407                                }
2408                                #pragma endregion
2409                        }
2410                        _ATLCATCH(Exception)
2411                        {
2412                                _Z_ATLEXCEPTION(Exception);
2413                                AtlMessageBoxEx(m_hWnd, (LPCTSTR) Ds::FormatResult(Exception), IDS_ERROR, MB_ICONERROR | MB_OK);
2414                                return 0;
2415                        }
2416                        EndDialog(nIdentifier);
2417                        return 0;
2418                }
2419                LRESULT OnCancel(UINT, INT nIdentifier, HWND)
2420                {
2421                        EndDialog(nIdentifier);
2422                        return 0;
2423                }
2424                LRESULT OnApply(UINT, INT, HWND)
2425                {
2426                        _ATLTRY
2427                        {
2428                                Apply();
2429                        }
2430                        _ATLCATCH(Exception)
2431                        {
2432                                _Z_ATLEXCEPTION(Exception);
2433                                AtlMessageBoxEx(m_hWnd, (LPCTSTR) Ds::FormatResult(Exception), IDS_ERROR, MB_ICONERROR | MB_OK);
2434                        }
2435                        return 0;
2436                }
2437                LRESULT OnTreeWalkUp(UINT, INT, HWND)
2438                {
2439                        CTreeItem TreeItem = m_TreeView.GetSelectedItem();
2440                        CTreeItem ParentTreeItem = TreeItem.GetParent();
2441                        if(!ParentTreeItem)
2442                                return 0;
2443                        m_TreeView.SetFocus();
2444                        m_TreeView.Select(ParentTreeItem, TVGN_CARET);
2445                        return 0;
2446                }
2447                LRESULT OnActionCommand(UINT, INT nIdentifier, HWND)
2448                {
2449                        return m_ActionDialog.SendMessage(WM_COMMAND, nIdentifier);
2450                }
2451        };
2452
2453private:
2454        mutable CRoCriticalSection m_DataCriticalSection;
2455        CProcessData m_ProcessData;
2456        CComPtr<IFilterGraph> m_pFilterGraph;
2457        COptions m_Options;
2458
2459public:
2460// CFilterGraphHelper
2461        static HRESULT WINAPI UpdateRegistry(BOOL bRegister)
2462        {
2463                _Z2(atlTraceRegistrar, 2, _T("bRegister %d\n"), bRegister);
2464                _ATLTRY
2465                {
2466                        UpdateRegistryFromResource<CFilterGraphHelper>(bRegister);
2467                }
2468                _ATLCATCH(Exception)
2469                {
2470                        _C(Exception);
2471                }
2472                return S_OK;
2473        }
2474        CFilterGraphHelper()
2475        {
2476                _Z4_THIS();
2477        }
2478        ~CFilterGraphHelper()
2479        {
2480                _Z4_THIS();
2481        }
2482        static CString FormatIdentifier(LPCSTR pszValue)
2483        {
2484                CString sText;
2485                if(pszValue && *pszValue)
2486                {
2487                        sText = _T("``");
2488                        sText.Insert(1, CString(pszValue));
2489                }
2490                return sText;
2491        }
2492        static CString FormatIdentifier(LPCWSTR pszValue)
2493        {
2494                CString sText;
2495                if(pszValue && *pszValue)
2496                {
2497                        sText = _T("``");
2498                        sText.Insert(1, CString(pszValue));
2499                }
2500                return sText;
2501        }
2502        static CString FormatIdentifier(LONG nValue)
2503        {
2504                CString sText;
2505                sText = _T("``");
2506                sText.Insert(1, _StringHelper::FormatNumber(nValue));
2507                return sText;
2508        }
2509        static CString FormatIdentifier(ULONG nValue)
2510        {
2511                return FormatIdentifier((LONG) nValue);
2512        }
2513        static CString FormatIdentifier(BOOL nValue)
2514        {
2515                return FormatIdentifier((LONG) nValue);
2516        }
2517        static CString FormatIdentifier(LONGLONG nValue)
2518        {
2519                CString sText;
2520                sText = _T("``");
2521                sText.Insert(1, _StringHelper::FormatNumber(nValue));
2522                return sText;
2523        }
2524        static CString FormatIdentifier(LONG nValue, LPCTSTR pszFormat)
2525        {
2526                CString sText;
2527                sText = _T("``");
2528                sText.Insert(1, AtlFormatString(pszFormat, nValue));
2529                return sText;
2530        }
2531        static CString FormatIdentifier(const VOID* pvValue, LPCTSTR pszFormat = _T("0x%p"))
2532        {
2533                CString sText;
2534                sText = _T("``");
2535                sText.Insert(1, AtlFormatString(pszFormat, pvValue));
2536                return sText;
2537        }
2538        #define I FormatIdentifier
2539        static CString FormatPhysicalConnectorType(PhysicalConnectorType Value)
2540        {
2541                struct 
2542                {
2543                        PhysicalConnectorType Value;
2544                        LPCSTR pszName;
2545                } g_pMap[] = 
2546                {
2547                        #define A(x) { x, #x },
2548                        A(PhysConn_Video_Tuner)
2549                        A(PhysConn_Video_Composite)
2550                        A(PhysConn_Video_SVideo)
2551                        A(PhysConn_Video_RGB)
2552                        A(PhysConn_Video_YRYBY)
2553                        A(PhysConn_Video_SerialDigital)
2554                        A(PhysConn_Video_ParallelDigital)
2555                        A(PhysConn_Video_SCSI)
2556                        A(PhysConn_Video_AUX)
2557                        A(PhysConn_Video_1394)
2558                        A(PhysConn_Video_USB)
2559                        A(PhysConn_Video_VideoDecoder)
2560                        A(PhysConn_Video_VideoEncoder)
2561                        A(PhysConn_Video_SCART)
2562                        A(PhysConn_Video_Black)
2563                        A(PhysConn_Audio_Tuner)
2564                        A(PhysConn_Audio_Line)
2565                        A(PhysConn_Audio_Mic)
2566                        A(PhysConn_Audio_AESDigital)
2567                        A(PhysConn_Audio_SPDIFDigital)
2568                        A(PhysConn_Audio_SCSI)
2569                        A(PhysConn_Audio_AUX)
2570                        A(PhysConn_Audio_1394)
2571                        A(PhysConn_Audio_USB)
2572                        A(PhysConn_Audio_AudioDecoder)
2573                        #undef A
2574                };
2575                for(SIZE_T nIndex = 0; nIndex < DIM(g_pMap); nIndex++)
2576                        if(g_pMap[nIndex].Value == Value)
2577                                return CString(g_pMap[nIndex].pszName);
2578                return AtlFormatString(_T("0x%04X"), Value);
2579        }
2580        static CString FormatPins(_FilterGraphHelper::CPinArray& PinArray)
2581        {
2582                CRoArrayT<CString> Array;
2583                for(SIZE_T nIndex  = 0; nIndex < PinArray.GetCount(); nIndex++)
2584                {
2585                        const CComPtr<IPin>& pPin = PinArray[nIndex];
2586                        CString sText = I(_FilterGraphHelper::GetPinName(pPin));
2587                        const CComPtr<IPin> pPeerPin = _FilterGraphHelper::GetPeerPin(pPin);
2588                        if(pPeerPin)
2589                                sText += AtlFormatString(_T(" (%s)"), I(_FilterGraphHelper::GetPinFullName(pPeerPin)));
2590                        Array.Add(sText);
2591                }
2592                return _StringHelper::Join(Array, _T(", "));
2593        }
2594        static CString GetFilterText(IBaseFilter* pBaseFilter, const CProcessData* pProcessData, IReferenceClock* pFilterGraphReferenceClock = NULL)
2595        {
2596                CString sText;
2597                #pragma region COM
2598                CString sPath;
2599                const CStringW sClassIdentifierString = _FilterGraphHelper::GetFilterClassIdentifierString(pBaseFilter);
2600                if(!sClassIdentifierString.IsEmpty())
2601                {
2602                        CLSID ClassIdentifier = CLSID_NULL;
2603                        const BOOL bClassIdentifierAvailable = _PersistHelper::ClassIdentifierFromString(sClassIdentifierString, ClassIdentifier);
2604                        if(bClassIdentifierAvailable && ClassIdentifier != CLSID_NULL)
2605                        {
2606                                sText += AtlFormatString(_T(" * ") _T("Class: %s %s") _T("\r\n"), I(sClassIdentifierString), I(_FilterGraphHelper::GetFilterClassDescription(pBaseFilter)));
2607                                _ATLTRY
2608                                {
2609                                        sPath = _RegKeyHelper::QueryStringValue(HKEY_CLASSES_ROOT, AtlFormatString(_T("CLSID\\%ls\\InprocServer32"), sClassIdentifierString));
2610                                        if(!sPath.IsEmpty())
2611                                        {
2612                                                sText += AtlFormatString(_T(" * ") _T("Inproc Server: %s") _T("\r\n"), I(sPath));
2613                                                const ULONGLONG nProductVersion = _VersionInfoHelper::GetProductVersion(sPath);
2614                                                if(nProductVersion && (nProductVersion + 1))
2615                                                        sText += AtlFormatString(_T(" * ") _T("Product Version: %s") _T("\r\n"), I(_VersionInfoHelper::GetVersionString(nProductVersion)));
2616                                                const ULONGLONG nFileVersion = _VersionInfoHelper::GetFileVersion(sPath);
2617                                                if(nFileVersion && (nFileVersion + 1))
2618                                                        sText += AtlFormatString(_T(" * ") _T("File Version: %s") _T("\r\n"), I(_VersionInfoHelper::GetVersionString(nFileVersion)));
2619                                        }
2620                                }
2621                                _ATLCATCHALL()
2622                                {
2623                                        _Z_EXCEPTION();
2624                                }
2625                        }
2626                }
2627                if(_tcslen(sPath) == 0 && pProcessData && pProcessData->m_nIdentifier == GetCurrentProcessId())
2628                        _ATLTRY
2629                        {
2630                                const VOID* pvVirtualTable = *((const VOID**) pBaseFilter);
2631                                MEMORY_BASIC_INFORMATION Information;
2632                                if(VirtualQueryEx(GetCurrentProcess(), pvVirtualTable, &Information, sizeof Information))
2633                                {
2634                                        TCHAR pszPath[MAX_PATH] = { 0 };
2635                                        if(GetModuleFileName((HMODULE) Information.AllocationBase, pszPath, DIM(pszPath)))
2636                                        {
2637                                                sPath = pszPath;
2638                                                sText += AtlFormatString(_T(" * ") _T("Virtual Table Location: %s") _T("\r\n"), I(sPath));
2639                                                const ULONGLONG nProductVersion = _VersionInfoHelper::GetProductVersion(sPath);
2640                                                if(nProductVersion && (nProductVersion + 1))
2641                                                        sText += AtlFormatString(_T(" * ") _T("Product Version: %s") _T("\r\n"), I(_VersionInfoHelper::GetVersionString(nProductVersion)));
2642                                                const ULONGLONG nFileVersion = _VersionInfoHelper::GetFileVersion(sPath);
2643                                                if(nFileVersion && (nFileVersion + 1))
2644                                                        sText += AtlFormatString(_T(" * ") _T("File Version: %s") _T("\r\n"), I(_VersionInfoHelper::GetVersionString(nFileVersion)));
2645                                        }
2646                                }
2647                        }
2648                        _ATLCATCHALL()
2649                        {
2650                                _Z_EXCEPTION();
2651                        }
2652                #pragma endregion
2653                #pragma region Pin
2654                _FilterGraphHelper::CPinArray InputPinArray;
2655                if(_FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_INPUT, InputPinArray))
2656                        sText += AtlFormatString(_T(" * ") _T("Input Pins: %s") _T("\r\n"), FormatPins(InputPinArray));
2657                _FilterGraphHelper::CPinArray OutputPinArray;
2658                if(_FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_OUTPUT, OutputPinArray))
2659                        sText += AtlFormatString(_T(" * ") _T("Output Pins: %s") _T("\r\n"), FormatPins(OutputPinArray));
2660                #pragma endregion
2661                #pragma region IReferenceClock
2662                const CComQIPtr<IReferenceClock> pReferenceClock = pBaseFilter;
2663                if(pReferenceClock)
2664                {
2665                        CRoArrayT<CString> Array;
2666                        Array.Add(I(_T("Available")));
2667                        if(pReferenceClock == pFilterGraphReferenceClock)
2668                                Array.Add(I(_T("Selected")));
2669                        sText += AtlFormatString(_T(" * ") _T("Reference Clock: %s") _T("\r\n"), _StringHelper::Join(Array, _T(", ")));
2670                }
2671                #pragma endregion
2672                #pragma region IFileSourceFilter
2673                const CComQIPtr<IFileSourceFilter> pFileSourceFilter = pBaseFilter;
2674                if(pFileSourceFilter)
2675                        _ATLTRY
2676                        {
2677                                CComHeapPtr<OLECHAR> pszFileName;
2678                                CMediaType pMediaType;
2679                                pMediaType.Allocate(MEDIATYPE_NULL, MEDIASUBTYPE_NULL);
2680                                const HRESULT nGetCurFileResult = pFileSourceFilter->GetCurFile(&pszFileName, pMediaType);
2681                                _Z45_DSHRESULT(nGetCurFileResult);
2682                                if(SUCCEEDED(nGetCurFileResult))
2683                                        sText += AtlFormatString(_T(" * ") _T("File Source: %s") _T("\r\n"), I(pszFileName));
2684                        }
2685                        _ATLCATCHALL()
2686                        {
2687                                _Z_EXCEPTION();
2688                        }
2689                #pragma endregion
2690                #pragma region IFileSinkFilter
2691                const CComQIPtr<IFileSinkFilter> pFileSinkFilter = pBaseFilter;
2692                if(pFileSinkFilter)
2693                        _ATLTRY
2694                        {
2695                                CComHeapPtr<OLECHAR> pszFileName;
2696                                CMediaType pMediaType;
2697                                pMediaType.Allocate(MEDIATYPE_NULL, MEDIASUBTYPE_NULL);
2698                                const HRESULT nGetCurFileResult = pFileSinkFilter->GetCurFile(&pszFileName, pMediaType);
2699                                _Z45_DSHRESULT(nGetCurFileResult);
2700                                if(SUCCEEDED(nGetCurFileResult))
2701                                        sText += AtlFormatString(_T(" * ") _T("File Sink: %s") _T("\r\n"), I(pszFileName));
2702                        }
2703                        _ATLCATCHALL()
2704                        {
2705                                _Z_EXCEPTION();
2706                        }
2707                #pragma endregion
2708                #pragma region IMediaSeeking
2709                const CComQIPtr<IMediaSeeking> pMediaSeeking = pBaseFilter;
2710                if(pMediaSeeking)
2711                        _ATLTRY
2712                        {
2713                                sText += AtlFormatString(_T(" * ") _T("Media Seeking/Position") _T("\r\n"));
2714                                DWORD nCapabilities = 0;
2715                                if(SUCCEEDED(pMediaSeeking->GetCapabilities(&nCapabilities)))
2716                                        sText += AtlFormatString(_T("  * ") _T("Capabilities: %s") _T("\r\n"), I(AtlFormatString(_T("0x%X"), nCapabilities)));
2717                                LONGLONG nDuration = 0, nPosition = 0, nStopPosition = 0;
2718                                if(SUCCEEDED(pMediaSeeking->GetDuration(&nDuration)))
2719                                        sText += AtlFormatString(_T("  * ") _T("Duration: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime((DOUBLE) nDuration / 1E7)), I(_StringHelper::FormatNumber((DOUBLE) nDuration / 1E7, 3)));
2720                                if(SUCCEEDED(pMediaSeeking->GetCurrentPosition(&nPosition)))
2721                                        sText += AtlFormatString(_T("  * ") _T("Position: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime((DOUBLE) nPosition / 1E7)), I(_StringHelper::FormatNumber((DOUBLE) nPosition / 1E7, 3)));
2722                                if(SUCCEEDED(pMediaSeeking->GetStopPosition(&nStopPosition)))
2723                                        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)));
2724                                DOUBLE fRate = 1.0;
2725                                if(SUCCEEDED(pMediaSeeking->GetRate(&fRate)))
2726                                        sText += AtlFormatString(_T("  * ") _T("Rate: %s") _T("\r\n"), I(_StringHelper::FormatNumber(fRate, 3)));
2727                                LONGLONG nPreroll = 0;
2728                                if(SUCCEEDED(pMediaSeeking->GetPreroll(&nPreroll)) && nPreroll)
2729                                        sText += AtlFormatString(_T("  * ") _T("Preroll: %s seconds") _T("\r\n"), I(_StringHelper::FormatNumber((DOUBLE) nPreroll / 1E7, 3)));
2730                        }
2731                        _ATLCATCHALL()
2732                        {
2733                                _Z_EXCEPTION();
2734                        }
2735                #pragma endregion
2736                #pragma region IAMCrossbar
2737                const CComQIPtr<IAMCrossbar> pAmCrossbar = pBaseFilter;
2738                if(pAmCrossbar)
2739                        _ATLTRY
2740                        {
2741                                sText += AtlFormatString(_T(" * ") _T("Crossbar:") _T("\r\n"));
2742                                LONG nOutputPinCount = 0, nInputPinCount = 0;
2743                                __C(pAmCrossbar->get_PinCounts(&nOutputPinCount, &nInputPinCount));
2744                                sText += AtlFormatString(_T("  * ") _T("Pins: %s Input, %s Output") _T("\r\n"), I(nInputPinCount), I(nOutputPinCount));
2745                                #pragma region Input
2746                                for(LONG nInputPinIndex = 0; nInputPinIndex < nInputPinCount; nInputPinIndex++)
2747                                        _ATLTRY
2748                                        {
2749                                                CRoArrayT<CString> Array;
2750                                                LONG nRelatedPinIndex = -1;
2751                                                LONG nPhysicalType = 0; // PhysicalConnectorType
2752                                                __C(pAmCrossbar->get_CrossbarPinInfo(TRUE, nInputPinIndex, &nRelatedPinIndex, &nPhysicalType));
2753                                                if(nRelatedPinIndex >= 0)
2754                                                        Array.Add(AtlFormatString(_T("Related %s"), I(nRelatedPinIndex)));
2755                                                Array.Add(AtlFormatString(_T("Physical Type %s"), I(FormatPhysicalConnectorType((PhysicalConnectorType) nPhysicalType))));
2756                                                sText += AtlFormatString(_T("  * ") _T("Input Pin %s: %s") _T("\r\n"), I(nInputPinIndex), _StringHelper::Join(Array, _T("; ")));
2757                                        }
2758                                        _ATLCATCHALL()
2759                                        {
2760                                                _Z_EXCEPTION();
2761                                        }
2762                                #pragma endregion
2763                                #pragma region Output
2764                                for(LONG nOutputPinIndex = 0; nOutputPinIndex < nOutputPinCount; nOutputPinIndex++)
2765                                        _ATLTRY
2766                                        {
2767                                                CRoArrayT<CString> Array;
2768                                                LONG nRelatedPinIndex = -1;
2769                                                LONG nPhysicalType = 0; // PhysicalConnectorType
2770                                                __C(pAmCrossbar->get_CrossbarPinInfo(FALSE, nOutputPinIndex, &nRelatedPinIndex, &nPhysicalType));
2771                                                if(nRelatedPinIndex >= 0)
2772                                                        Array.Add(AtlFormatString(_T("Related %s"), I(nRelatedPinIndex)));
2773                                                if(nPhysicalType > 0)
2774                                                        Array.Add(AtlFormatString(_T("Physical Type %s"), I(FormatPhysicalConnectorType((PhysicalConnectorType) nPhysicalType))));
2775                                                LONG nRoutedInputPinIndex = -1;
2776                                                const HRESULT nGetIsRoutedToResult = pAmCrossbar->get_IsRoutedTo(nOutputPinIndex, &nRoutedInputPinIndex);
2777                                                _A(nGetIsRoutedToResult == S_OK || nRoutedInputPinIndex == -1);
2778                                                if(nRoutedInputPinIndex >= 0)
2779                                                        Array.Add(AtlFormatString(_T("Routed to Input Pin %s"), I(nRoutedInputPinIndex)));
2780                                                CRoArrayT<CString> PinArray;
2781                                                for(LONG nInputPinIndex = 0; nInputPinIndex < nInputPinCount; nInputPinIndex++)
2782                                                {
2783                                                        const HRESULT nCanRouteResult = pAmCrossbar->CanRoute(nOutputPinIndex, nInputPinIndex);
2784                                                        if(nCanRouteResult == S_OK)
2785                                                                PinArray.Add(I(nInputPinIndex));
2786                                                }
2787                                                if(!PinArray.IsEmpty())
2788                                                        Array.Add(AtlFormatString(_T("Routeable to Input Pins %s"), _StringHelper::Join(PinArray, _T(", "))));
2789                                                sText += AtlFormatString(_T("  * ") _T("Output Pin %s: %s") _T("\r\n"), I(nOutputPinIndex), _StringHelper::Join(Array, _T("; ")));
2790                                        }
2791                                        _ATLCATCHALL()
2792                                        {
2793                                                _Z_EXCEPTION();
2794                                        }
2795                                #pragma endregion
2796                        }
2797                        _ATLCATCHALL()
2798                        {
2799                                _Z_EXCEPTION();
2800                        }
2801                #pragma endregion
2802                return sText;
2803        }
2804        static CString GetConnectionText(IPin* pOutputPin, IPin* pInputPin)
2805        {
2806                _A(pOutputPin && pInputPin);
2807                CString sText = AtlFormatString(_T("%s - %s"), I(_FilterGraphHelper::GetPinFullName(pOutputPin)), I(_FilterGraphHelper::GetPinFullName(pInputPin)));
2808                _ATLTRY
2809                {
2810                        const CMediaType pMediaType = _FilterGraphHelper::GetPinMediaType(pOutputPin);
2811                        if(pMediaType)
2812                        {
2813                                CStringW sMajorType = _FilterGraphHelper::FormatMajorType(pMediaType->majortype);
2814                                CStringW sSubtype;
2815                                if(pMediaType->subtype != MEDIASUBTYPE_NULL)
2816                                        sSubtype = _FilterGraphHelper::FormatSubtype(pMediaType->majortype, pMediaType->subtype);
2817                                CRoArrayT<CString> Array;
2818                                Array.Add(I(sMajorType));
2819                                if(!sSubtype.IsEmpty())
2820                                        Array.Add(I(sSubtype));
2821                                #pragma region MEDIATYPE_Video
2822                                if(pMediaType->majortype == MEDIATYPE_Video)
2823                                {
2824                                        const CVideoInfoHeader2 VideoInfoHeader2 = pMediaType.GetCompatibleVideoInfoHeader2();
2825                                        const CSize Extent = VideoInfoHeader2.GetExtent();
2826                                        if(Extent.cx || Extent.cy)
2827                                                Array.Add(AtlFormatString(_T("%s x %s"), I(Extent.cx), I(Extent.cy)));
2828                                        if(VideoInfoHeader2.AvgTimePerFrame > 0)
2829                                                Array.Add(AtlFormatString(_T("%s frames/sec"), I(_StringHelper::FormatNumber(1E7 / VideoInfoHeader2.AvgTimePerFrame, 3))));
2830                                } else
2831                                #pragma endregion
2832                                #pragma region MEDIATYPE_Audio
2833                                if(pMediaType->majortype == MEDIATYPE_Audio)
2834                                {
2835                                        const CWaveFormatEx* pWaveFormatEx = pMediaType.GetWaveFormatEx();
2836                                        if(pWaveFormatEx)
2837                                        {
2838                                                if(pWaveFormatEx->nSamplesPerSec)
2839                                                        Array.Add(AtlFormatString(_T("%s Hz"), I(pWaveFormatEx->nSamplesPerSec)));
2840                                                if(pWaveFormatEx->nChannels)
2841                                                        Array.Add(AtlFormatString(_T("%s channels"), I(pWaveFormatEx->nChannels)));
2842                                                if(pWaveFormatEx->wBitsPerSample)
2843                                                        Array.Add(AtlFormatString(_T("%s bits"), I(pWaveFormatEx->wBitsPerSample)));
2844                                        }
2845                                }
2846                                #pragma endregion
2847                                sText += AtlFormatString(_T(" (%s)"), _StringHelper::Join(Array, _T(", ")));
2848                        }
2849                }
2850                _ATLCATCHALL()
2851                {
2852                        _Z_EXCEPTION();
2853                }
2854                return sText;
2855        }
2856        static CString GetMediaTypeText(const CMediaType& pMediaType)
2857        {
2858                CString sText;
2859                #pragma region AM_MEDIA_TYPE
2860                #define J(x) I(pMediaType->x)
2861                #define K1(x) sText += AtlFormatString(_T(" * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
2862                sText += AtlFormatString(_T(" * ") _T("Data: %s") _T("\r\n"), I(AtlFormatData((const BYTE*) (const AM_MEDIA_TYPE*) pMediaType, sizeof *pMediaType).TrimRight()));
2863                sText += AtlFormatString(_T(" * ") _T("`majortype`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatMajorType(pMediaType->majortype)));
2864                if(pMediaType->subtype != MEDIASUBTYPE_NULL)
2865                        sText += AtlFormatString(_T(" * ") _T("`subtype`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatSubtype(pMediaType->majortype, pMediaType->subtype)));
2866                K1(bFixedSizeSamples);
2867                K1(bTemporalCompression);
2868                K1(lSampleSize);
2869                if(pMediaType->formattype != GUID_NULL)
2870                        sText += AtlFormatString(_T(" * ") _T("`formattype`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatFormatType(pMediaType->formattype)));
2871                if(pMediaType->pUnk)
2872                        sText += AtlFormatString(_T(" * ") _T("`pUnk`: %s") _T("\r\n"), I(AtlFormatString(_T("0x%p"), pMediaType->pUnk)));
2873                if(pMediaType->cbFormat)
2874                {
2875                        K1(cbFormat);
2876                        if(pMediaType->pbFormat)
2877                                sText += AtlFormatString(_T(" * ") _T("Format Data, `pbFormat`: %s") _T("\r\n"), I(AtlFormatData(pMediaType->pbFormat, pMediaType->cbFormat).TrimRight()));
2878                }
2879                #undef J
2880                #undef K1
2881                #pragma endregion
2882                const BYTE* pnExtraData = NULL;
2883                SIZE_T nExtraDataSize = 0;
2884                #pragma region FORMAT_VideoInfo
2885                if(pMediaType->formattype == FORMAT_VideoInfo)
2886                {
2887                        sText += AtlFormatString(_T(" * ") _T("As `VIDEOINFOHEADER`:") _T("\r\n"));
2888                        const VIDEOINFOHEADER* pVideoInfoHeader = (const VIDEOINFOHEADER*) pMediaType->pbFormat;
2889                        #define J(x) I(pVideoInfoHeader->x)
2890                        #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
2891                        sText += AtlFormatString(_T("  * ") _T("`rcSource`: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcSource.left), J(rcSource.top), J(rcSource.right), J(rcSource.bottom));
2892                        sText += AtlFormatString(_T("  * ") _T("`rcTarget`: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcTarget.left), J(rcTarget.top), J(rcTarget.right), J(rcTarget.bottom));
2893                        K1(dwBitRate);
2894                        K1(dwBitErrorRate);
2895                        sText += AtlFormatString(_T("  * ") _T("`AvgTimePerFrame`: %s units") _T("\r\n"), I(_FilterGraphHelper::FormatReferenceTime(pVideoInfoHeader->AvgTimePerFrame)));
2896                        K1(bmiHeader.biSize);
2897                        K1(bmiHeader.biWidth);
2898                        K1(bmiHeader.biHeight);
2899                        K1(bmiHeader.biPlanes);
2900                        K1(bmiHeader.biBitCount);
2901                        sText += AtlFormatString(_T("  * ") _T("`bmiHeader.biCompression`: %s") _T("\r\n"), I(_FilterGraphHelper::GetFourccCodeString(pVideoInfoHeader->bmiHeader.biCompression)));
2902                        K1(bmiHeader.biSizeImage);
2903                        K1(bmiHeader.biXPelsPerMeter);
2904                        K1(bmiHeader.biYPelsPerMeter);
2905                        K1(bmiHeader.biClrUsed);
2906                        K1(bmiHeader.biClrImportant);
2907                        #undef J
2908                        #undef K1
2909                        nExtraDataSize = pMediaType->cbFormat - sizeof *pVideoInfoHeader;
2910                } else
2911                #pragma endregion
2912                #pragma region FORMAT_VideoInfo2
2913                if(pMediaType->formattype == FORMAT_VideoInfo2)
2914                {
2915                        sText += AtlFormatString(_T(" * ") _T("As `VIDEOINFOHEADER2`:") _T("\r\n"));
2916                        const VIDEOINFOHEADER2* pVideoInfoHeader2 = (const VIDEOINFOHEADER2*) pMediaType->pbFormat;
2917                        #define J(x) I(pVideoInfoHeader2->x)
2918                        #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
2919                        #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pVideoInfoHeader2->x, y))
2920                        sText += AtlFormatString(_T("  * ") _T("rcSource: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcSource.left), J(rcSource.top), J(rcSource.right), J(rcSource.bottom));
2921                        sText += AtlFormatString(_T("  * ") _T("rcTarget: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcTarget.left), J(rcTarget.top), J(rcTarget.right), J(rcTarget.bottom));
2922                        K1(dwBitRate);
2923                        K1(dwBitErrorRate);
2924                        sText += AtlFormatString(_T("  * ") _T("`AvgTimePerFrame`: %s units") _T("\r\n"), I(_FilterGraphHelper::FormatReferenceTime(pVideoInfoHeader2->AvgTimePerFrame)));
2925                        K2(dwInterlaceFlags, _T("0x%X"));
2926                        K2(dwCopyProtectFlags, _T("0x%X"));
2927                        K1(dwPictAspectRatioX);
2928                        K1(dwPictAspectRatioY);
2929                        K2(dwControlFlags, _T("0x%X"));
2930                        K1(bmiHeader.biSize);
2931                        K1(bmiHeader.biWidth);
2932                        K1(bmiHeader.biHeight);
2933                        K1(bmiHeader.biPlanes);
2934                        K1(bmiHeader.biBitCount);
2935                        sText += AtlFormatString(_T("  * ") _T("`bmiHeader.biCompression`: %s") _T("\r\n"), I(_FilterGraphHelper::GetFourccCodeString(pVideoInfoHeader2->bmiHeader.biCompression)));
2936                        K1(bmiHeader.biSizeImage);
2937                        K1(bmiHeader.biXPelsPerMeter);
2938                        K1(bmiHeader.biYPelsPerMeter);
2939                        K1(bmiHeader.biClrUsed);
2940                        K1(bmiHeader.biClrImportant);
2941                        #undef J
2942                        #undef K1
2943                        #undef K2
2944                        nExtraDataSize = pMediaType->cbFormat - sizeof *pVideoInfoHeader2;
2945                        if(nExtraDataSize)
2946                        {
2947                                sText += AtlFormatString(_T("  * ") _T("Extra Data: (%d bytes)") _T("\r\n"), nExtraDataSize);
2948                                nExtraDataSize = 0;
2949                        }
2950                } else
2951                #pragma endregion
2952                #pragma region FORMAT_MPEG2Video
2953                if(pMediaType->formattype == FORMAT_MPEG2Video)
2954                {
2955                        sText += AtlFormatString(_T(" * ") _T("As `MPEG2VIDEOINFO`:") _T("\r\n"));
2956                        const MPEG2VIDEOINFO* pMpeg2VideoInfo = (const MPEG2VIDEOINFO*) pMediaType->pbFormat;
2957                        #define J(x) I(pMpeg2VideoInfo->x)
2958                        #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
2959                        #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pMpeg2VideoInfo->x, y))
2960                        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));
2961                        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));
2962                        K1(hdr.dwBitRate);
2963                        K1(hdr.dwBitErrorRate);
2964                        sText += AtlFormatString(_T("  * ") _T("`hdr.AvgTimePerFrame`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatReferenceTime(pMpeg2VideoInfo->hdr.AvgTimePerFrame)));
2965                        K2(hdr.dwInterlaceFlags, _T("0x%X"));
2966                        K2(hdr.dwCopyProtectFlags, _T("0x%X"));
2967                        K1(hdr.dwPictAspectRatioX);
2968                        K1(hdr.dwPictAspectRatioY);
2969                        K2(hdr.dwControlFlags, _T("0x%X"));
2970                        K1(hdr.bmiHeader.biSize);
2971                        K1(hdr.bmiHeader.biWidth);
2972                        K1(hdr.bmiHeader.biHeight);
2973                        K1(hdr.bmiHeader.biPlanes);
2974                        K1(hdr.bmiHeader.biBitCount);
2975                        sText += AtlFormatString(_T("  * ") _T("`hdr.bmiHeader.biCompression`: %s") _T("\r\n"), I(_FilterGraphHelper::GetFourccCodeString(pMpeg2VideoInfo->hdr.bmiHeader.biCompression)));
2976                        K1(hdr.bmiHeader.biSizeImage);
2977                        K1(hdr.bmiHeader.biXPelsPerMeter);
2978                        K1(hdr.bmiHeader.biYPelsPerMeter);
2979                        K1(hdr.bmiHeader.biClrUsed);
2980                        K1(hdr.bmiHeader.biClrImportant);
2981                        K2(dwStartTimeCode, _T("0x%08X"));
2982                        K1(cbSequenceHeader);
2983                        K1(dwProfile);
2984                        K1(dwLevel);
2985                        K2(dwFlags, _T("0x%08X"));
2986                        #undef J
2987                        #undef K1
2988                        #undef K2
2989                        #undef J
2990                        nExtraDataSize = pMediaType->cbFormat - (sizeof *pMpeg2VideoInfo - sizeof pMpeg2VideoInfo->dwSequenceHeader);
2991                } else
2992                #pragma endregion
2993                #pragma region FORMAT_WaveFormatEx
2994                if(pMediaType->formattype == FORMAT_WaveFormatEx)
2995                {
2996                        const WAVEFORMATEX* pWaveFormatEx = (const WAVEFORMATEX*) pMediaType->pbFormat;
2997                        if(pWaveFormatEx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
2998                        {
2999                                const WAVEFORMATEXTENSIBLE* pWaveFormatExtensible = (const WAVEFORMATEXTENSIBLE*) pMediaType->pbFormat;
3000                                #define J(x) I(pWaveFormatExtensible->x)
3001                                #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
3002                                #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pWaveFormatExtensible->x, y))
3003                                sText += AtlFormatString(_T(" * ") _T("As `WAVEFORMATEXTENSIBLE`:") _T("\r\n"));
3004                                K2(Format.wFormatTag, _T("0x%02X"));
3005                                K1(Format.nChannels);
3006                                K1(Format.nSamplesPerSec);
3007                                K1(Format.nAvgBytesPerSec);
3008                                K1(Format.nBlockAlign);
3009                                K1(Format.wBitsPerSample);
3010                                K1(Format.cbSize);
3011                                K1(Samples.wValidBitsPerSample);
3012                                K2(dwChannelMask, _T("0x%02X"));
3013                                sText += AtlFormatString(_T("  * ") _T("`SubFormat`: %s") _T("\r\n"), I(_PersistHelper::StringFromIdentifier(pWaveFormatExtensible->SubFormat)));
3014                                #undef J
3015                                #undef K1
3016                                #undef K2
3017                                nExtraDataSize = pWaveFormatEx->cbSize - (sizeof *pWaveFormatExtensible - sizeof *pWaveFormatEx);
3018                        } else
3019                        {
3020                                #define J(x) I(pWaveFormatEx->x)
3021                                #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
3022                                #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pWaveFormatEx->x, y))
3023                                K2(wFormatTag, _T("0x%02X"));
3024                                K1(nChannels);
3025                                K1(nSamplesPerSec);
3026                                K1(nAvgBytesPerSec);
3027                                K1(nBlockAlign);
3028                                K1(wBitsPerSample);
3029                                K1(cbSize);
3030                                #undef J
3031                                #undef K1
3032                                #undef K2
3033                                nExtraDataSize = pWaveFormatEx->cbSize;
3034                        }
3035                }
3036                #pragma endregion
3037                #pragma region Extra Data
3038                if(nExtraDataSize)
3039                {
3040                        if(!pnExtraData)
3041                        {
3042                                if(nExtraDataSize > pMediaType->cbFormat)
3043                                        nExtraDataSize = pMediaType->cbFormat;
3044                                pnExtraData = pMediaType->pbFormat + pMediaType->cbFormat - nExtraDataSize;
3045                        }
3046                        const SSIZE_T nExtraDataExcessSize = (pnExtraData + nExtraDataSize) - (pMediaType->pbFormat + pMediaType->cbFormat);
3047                        if(nExtraDataExcessSize > 0)
3048                                nExtraDataSize -= min((SIZE_T) nExtraDataExcessSize, nExtraDataSize);
3049                        sText += AtlFormatString(_T("  * ") _T("Extra Data: %s") _T("\r\n"), I(AtlFormatData(pnExtraData, nExtraDataSize).TrimRight()));
3050                }
3051                #pragma endregion
3052                return sText;
3053        }
3054        static CString GetText(IFilterGraph* pFilterGraph, const CProcessData* pProcessData = NULL)
3055        {
3056                if(!pFilterGraph)
3057                        return (LPCTSTR) NULL;
3058                const CComQIPtr<IServiceProvider> pServiceProvider = pFilterGraph;
3059                const CComQIPtr<ISpy> pSpy = pFilterGraph;
3060                CString sText;
3061                sText += AtlFormatString(_T("# ") _T("Filter Graph") _T("\r\n") _T("\r\n"));
3062                #pragma region Graph Parameters
3063                if(pProcessData)
3064                        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)));
3065                #pragma region IMediaControl
3066                OAFilterState State = (OAFilterState) -1;
3067                const CComQIPtr<IMediaControl> pMediaControl = pFilterGraph;
3068                if(pMediaControl)
3069                        _ATLTRY
3070                        {
3071                                const HRESULT nGetStateResult = pMediaControl->GetState(0, &State);
3072                                _Z45_DSHRESULT(nGetStateResult);
3073                                static const LPCTSTR g_ppszStates[] = { _T("Stopped"), _T("Paused"), _T("Running"), };
3074                                if(SUCCEEDED(nGetStateResult) && (SIZE_T) State < DIM(g_ppszStates))
3075                                        sText += AtlFormatString(_T("* ") _T("State: %s") _T("\r\n"), I(g_ppszStates[(SIZE_T) State]));
3076                        }
3077                        _ATLCATCHALL()
3078                        {
3079                                _Z_EXCEPTION();
3080                        }
3081                #pragma endregion
3082                #pragma region IMediaPosition
3083                const CComQIPtr<IMediaPosition> pMediaPosition = pFilterGraph;
3084                if(pMediaPosition)
3085                        _ATLTRY
3086                        {
3087                                DOUBLE fDuration = 0, fPosition = 0;
3088                                const HRESULT nGetDurationResult = pMediaPosition->get_Duration(&fDuration);
3089                                _Z45_DSHRESULT(nGetDurationResult);
3090                                if(fDuration > 0)
3091                                {
3092                                        sText += AtlFormatString(_T("* ") _T("Duration: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime(fDuration)), I(_StringHelper::FormatNumber(fDuration, 3)));
3093                                        const HRESULT nCurrentPositionResult = pMediaPosition->get_CurrentPosition(&fPosition);
3094                                        _Z45_DSHRESULT(nCurrentPositionResult);
3095                                        if(SUCCEEDED(nCurrentPositionResult))
3096                                                sText += AtlFormatString(_T("* ") _T("Position: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime(fPosition)), I(_StringHelper::FormatNumber(fPosition, 3)));
3097                                }
3098                        }
3099                        _ATLCATCHALL()
3100                        {
3101                                _Z_EXCEPTION();
3102                        }
3103                #pragma endregion
3104                if(pProcessData)
3105                {
3106                        if(!pProcessData->m_sDisplayName.IsEmpty())
3107                                sText += AtlFormatString(_T("* ") _T("Display Name: %s") _T("\r\n"), I(pProcessData->m_sDisplayName));
3108                        if(_tcslen(pProcessData->m_sImagePath))
3109                        {
3110                                const CString sDirectory = (LPCTSTR) GetPathDirectory(pProcessData->m_sImagePath);
3111                                if(!sDirectory.IsEmpty())
3112                                        sText += AtlFormatString(_T("* ") _T("Process Directory: %s") _T("\r\n"), I(sDirectory));
3113                        }
3114                }
3115                const CComQIPtr<IMediaFilter> pMediaFilter = pFilterGraph;
3116                CComPtr<IReferenceClock> pFilterGraphReferenceClock;
3117                const HRESULT nGetSyncSourceResult = pMediaFilter->GetSyncSource(&pFilterGraphReferenceClock);
3118                _Z45_DSHRESULT(nGetSyncSourceResult);
3119                sText += _T("\r\n");
3120                #pragma endregion
3121                #pragma region Filter
3122                _FilterGraphHelper::CFilterArray FilterArray;
3123                _FilterGraphHelper::GetGraphFilters(pFilterGraph, FilterArray);
3124                if(!FilterArray.IsEmpty())
3125                {
3126                        sText += AtlFormatString(_T("## ") _T("Filters") _T("\r\n") _T("\r\n"));
3127                        for(SIZE_T nIndex = 0; nIndex < FilterArray.GetCount(); nIndex++)
3128                                _ATLTRY
3129                                {
3130                                        const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nIndex];
3131                                        sText += AtlFormatString(_T("%d. ") _T("%ls") _T("\r\n"), nIndex + 1, _FilterGraphHelper::GetFilterName(pBaseFilter));
3132                                        sText += GetFilterText(pBaseFilter, pProcessData, pFilterGraphReferenceClock);
3133                                }
3134                                _ATLCATCHALL()
3135                                {
3136                                        _Z_EXCEPTION();
3137                                }
3138                        sText += _T("\r\n");
3139                        #pragma region Connection
3140                        sText += AtlFormatString(_T("## ") _T("Connections") _T("\r\n") _T("\r\n"));
3141                        INT nConnectionIndex = 0;
3142                        for(auto&& pBaseFilter: FilterArray)
3143                        {
3144                                _FilterGraphHelper::CPinArray PinArray;
3145                                _FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_OUTPUT, PinArray);
3146                                for(auto&& pOutputPin: PinArray)
3147                                {
3148                                        const CComPtr<IPin> pInputPin = _FilterGraphHelper::GetPeerPin(pOutputPin);
3149                                        if(!pInputPin)
3150                                                continue;
3151                                        sText += AtlFormatString(_T("%d. ") _T("%s") _T("\r\n"), ++nConnectionIndex, GetConnectionText(pOutputPin, pInputPin));
3152                                }
3153                        }
3154                        sText += _T("\r\n");
3155                        #pragma endregion
3156                        #pragma region Media Type
3157                        sText += AtlFormatString(_T("## ") _T("Media Types") _T("\r\n") _T("\r\n"));
3158                        INT nGlobalPinIndex = 0;
3159                        CRoListT<CComPtr<IPin>> PinList;
3160                        for(SIZE_T nFilterIndex = 0; nFilterIndex < FilterArray.GetCount(); nFilterIndex++)
3161                        {
3162                                const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nFilterIndex];
3163                                _FilterGraphHelper::CPinArray PinArray;
3164                                _FilterGraphHelper::GetFilterPins(pBaseFilter, PinArray);
3165                                for(SIZE_T nPinIndex = 0; nPinIndex < PinArray.GetCount(); nPinIndex++)
3166                                {
3167                                        const CComPtr<IPin>& pPin = PinArray[nPinIndex];
3168                                        if(PinList.FindFirst(pPin))
3169                                                continue;
3170                                        PinList.AddTail(pPin);
3171                                        CString sPinText = AtlFormatString(_T("%s"), I(_FilterGraphHelper::GetPinFullName(pPin)));
3172                                        const CComPtr<IPin> pPeerPin = _FilterGraphHelper::GetPeerPin(pPin);
3173                                        if(pPeerPin)
3174                                        {
3175                                                PinList.AddTail(pPeerPin);
3176                                                sPinText += AtlFormatString(_T(", %s"), I(_FilterGraphHelper::GetPinFullName(pPeerPin)));
3177                                        }
3178                                        sText += AtlFormatString(_T("%d. ") _T("%s") _T("\r\n"), ++nGlobalPinIndex, sPinText);
3179                                        _ATLTRY
3180                                        {
3181                                                CMediaType pMediaType;
3182                                                if(pPeerPin)
3183                                                        pMediaType = _FilterGraphHelper::GetPinMediaType(pPin);
3184                                                else
3185                                                        pMediaType = _FilterGraphHelper::EnumerateFirstPinMediaType(pPin);
3186                                                if(!pMediaType)
3187                                                        continue;
3188                                                sText += GetMediaTypeText(pMediaType);
3189                                        }
3190                                        _ATLCATCHALL()
3191                                        {
3192                                                _Z_EXCEPTION();
3193                                        }
3194                                }
3195                        }
3196                        sText += _T("\r\n");
3197                        #pragma endregion
3198                        if(State > State_Stopped)
3199                        {
3200                                #pragma region Memory Allocator
3201                                INT nConnectionIndex = 0;
3202                                for(auto&& pBaseFilter: FilterArray)
3203                                {
3204                                        _FilterGraphHelper::CPinArray PinArray;
3205                                        _FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_INPUT, PinArray);
3206                                        for(auto&& pInputPin: PinArray)
3207                                        {
3208                                                _ATLTRY
3209                                                {
3210                                                        const CComQIPtr<IMemInputPin> pMemInputPin = pInputPin;
3211                                                        if(!pMemInputPin)
3212                                                                continue; // No IMemInputPin
3213                                                        const CComPtr<IPin> pOutputPin = _FilterGraphHelper::GetPeerPin(pInputPin);
3214                                                        if(!pOutputPin)
3215                                                                continue; // Not Connected
3216                                                        CComPtr<IMemAllocator> pMemAllocator;
3217                                                        pMemInputPin->GetAllocator(&pMemAllocator);
3218                                                        if(!pMemAllocator)
3219                                                                continue; // No Memory Allocator
3220                                                        ALLOCATOR_PROPERTIES Properties;
3221                                                        const HRESULT nGetPropertiesResult = pMemAllocator->GetProperties(&Properties);
3222                                                        _Z45_DSHRESULT(nGetPropertiesResult);
3223                                                        if(FAILED(nGetPropertiesResult))
3224                                                                continue; // No Memory Allocator Properties
3225                                                        const CComQIPtr<IMemAllocatorCallbackTemp> pMemAllocatorCallbackTemp = pMemAllocator;
3226                                                        BOOL bFreeCountAvailable;
3227                                                        LONG nFreeCount;
3228                                                        if(pMemAllocatorCallbackTemp)
3229                                                        {
3230                                                                const HRESULT nGetFreeCountResult = pMemAllocatorCallbackTemp->GetFreeCount(&nFreeCount);
3231                                                                _Z45_DSHRESULT(nGetFreeCountResult);
3232                                                                bFreeCountAvailable = SUCCEEDED(nGetFreeCountResult);
3233                                                        } else
3234                                                                bFreeCountAvailable = FALSE;
3235                                                        CString sConnectionText = AtlFormatString(_T("%s - %s"), I(_FilterGraphHelper::GetPinFullName(pInputPin)), I(_FilterGraphHelper::GetPinFullName(pOutputPin)));
3236                                                        sConnectionText += _T(": ");
3237                                                        CRoArrayT<CString> Array;
3238                                                        Array.Add(AtlFormatString(_T("%s buffers"), I(Properties.cBuffers)));
3239                                                        if(bFreeCountAvailable)
3240                                                                Array.Add(AtlFormatString(_T("%s free buffers"), I(nFreeCount)));
3241                                                        Array.Add(AtlFormatString(_T("%s bytes per buffer"), I(Properties.cbBuffer)));
3242                                                        if(Properties.cbAlign > 1)
3243                                                                Array.Add(AtlFormatString(_T("%s byte alignment"), I(Properties.cbAlign)));
3244                                                        if(Properties.cbPrefix > 0)
3245                                                                Array.Add(AtlFormatString(_T("%s byte prefix"), I(Properties.cbPrefix)));
3246                                                        sConnectionText += _StringHelper::Join(Array, _T(", "));
3247                                                        if(!nConnectionIndex)
3248                                                                sText += AtlFormatString(_T("## ") _T("Memory Allocators") _T("\r\n") _T("\r\n"));
3249                                                        sText += AtlFormatString(_T("%d. ") _T("%s") _T("\r\n"), ++nConnectionIndex, sConnectionText);
3250                                                }
3251                                                _ATLCATCHALL()
3252                                                {
3253                                                        _Z_EXCEPTION();
3254                                                }
3255                                        }
3256                                }
3257                                if(nConnectionIndex)
3258                                        sText += _T("\r\n");
3259                                #pragma endregion
3260                        }
3261                        #pragma region IMediaSeeking
3262                        BOOL bMediaSeekingHeaderAdded = FALSE;
3263                        for(SIZE_T nFilterIndex = 0; nFilterIndex < FilterArray.GetCount(); nFilterIndex++)
3264                        {
3265                                const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nFilterIndex];
3266                                _FilterGraphHelper::CPinArray PinArray;
3267                                _FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_OUTPUT, PinArray);
3268                                for(SIZE_T nPinIndex = 0; nPinIndex < PinArray.GetCount(); nPinIndex++)
3269                                {
3270                                        const CComPtr<IPin>& pOutputPin = PinArray[nPinIndex];
3271                                        const CComQIPtr<IMediaSeeking> pMediaSeeking = pOutputPin;
3272                                        if(!pMediaSeeking)
3273                                                continue;
3274                                        if(!bMediaSeekingHeaderAdded)
3275                                        {
3276                                                sText += AtlFormatString(_T("## ") _T("Media Seeking/Position") _T("\r\n") _T("\r\n"));
3277                                                bMediaSeekingHeaderAdded = TRUE;
3278                                        }
3279                                        sText += AtlFormatString(_T("* ") _T("Pin: %s") _T("\r\n"), I(_FilterGraphHelper::GetPinFullName(pOutputPin)));
3280                                        _ATLTRY
3281                                        {
3282                                                DWORD nCapabilities = 0;
3283                                                if(SUCCEEDED(pMediaSeeking->GetCapabilities(&nCapabilities)))
3284                                                        sText += AtlFormatString(_T(" * ") _T("Capabilities: %s") _T("\r\n"), I(AtlFormatString(_T("0x%X"), nCapabilities)));
3285                                                LONGLONG nDuration = 0, nPosition = 0, nStopPosition = 0;
3286                                                if(SUCCEEDED(pMediaSeeking->GetDuration(&nDuration)))
3287                                                        sText += AtlFormatString(_T(" * ") _T("Duration: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime((DOUBLE) nDuration / 1E7)), I(_StringHelper::FormatNumber((DOUBLE) nDuration / 1E7, 3)));
3288                                                if(SUCCEEDED(pMediaSeeking->GetCurrentPosition(&nPosition)))
3289                                                        sText += AtlFormatString(_T(" * ") _T("Position: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime((DOUBLE) nPosition / 1E7)), I(_StringHelper::FormatNumber((DOUBLE) nPosition / 1E7, 3)));
3290                                                if(SUCCEEDED(pMediaSeeking->GetStopPosition(&nStopPosition)))
3291                                                        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)));
3292                                                DOUBLE fRate = 1.0;
3293                                                if(SUCCEEDED(pMediaSeeking->GetRate(&fRate)))
3294                                                        sText += AtlFormatString(_T(" * ") _T("Rate: %s") _T("\r\n"), I(_StringHelper::FormatNumber(fRate, 3)));
3295                                                LONGLONG nPreroll = 0;
3296                                                if(SUCCEEDED(pMediaSeeking->GetPreroll(&nPreroll)) && nPreroll)
3297                                                        sText += AtlFormatString(_T(" * ") _T("Preroll: %s seconds") _T("\r\n"), I(_StringHelper::FormatNumber((DOUBLE) nPreroll / 1E7, 3)));
3298                                        }
3299                                        _ATLCATCHALL()
3300                                        {
3301                                                _Z_EXCEPTION();
3302                                        }
3303                                }
3304                        }
3305                        if(bMediaSeekingHeaderAdded)
3306                                sText += _T("\r\n");
3307                        #pragma endregion
3308                        #pragma region Runtime Property Bag
3309                        const CString sRunPropertyBagHeader = AtlFormatString(_T("## ") _T("Runtime Properties") _T("\r\n") _T("\r\n"));
3310                        BOOL bRunPropertyBagHeaderAdded = FALSE;
3311                        {
3312                                const CString sPropertyBagText = CRunPropertyBagHelper::GetPropertyBagText(pFilterGraph, pSpy);
3313                                if(!sPropertyBagText.IsEmpty())
3314                                {
3315                                        sText += sRunPropertyBagHeader;
3316                                        bRunPropertyBagHeaderAdded = TRUE;
3317                                        sText += sPropertyBagText;
3318                                        sText += _T("\r\n");
3319                                }
3320                        }
3321                        for(auto&& pBaseFilter: FilterArray)
3322                        {
3323                                _ATLTRY
3324                                {
3325                                        const CString sPropertyBagText = CRunPropertyBagHelper::GetPropertyBagText(pBaseFilter, pSpy);
3326                                        if(sPropertyBagText.IsEmpty())
3327                                                continue;
3328                                        if(!bRunPropertyBagHeaderAdded)
3329                                        {
3330                                                sText += sRunPropertyBagHeader;
3331                                                bRunPropertyBagHeaderAdded = TRUE;
3332                                        }
3333                                        sText += AtlFormatString(_T("### ") _T("Filter: %ls") _T("\r\n") _T("\r\n"), _FilterGraphHelper::GetFilterName(pBaseFilter));
3334                                        sText += sPropertyBagText;
3335                                        sText += _T("\r\n");
3336                                }
3337                                _ATLCATCHALL()
3338                                {
3339                                        _Z_EXCEPTION();
3340                                }
3341                        }
3342                        #pragma endregion
3343                }
3344                #pragma endregion
3345                #pragma region Clock
3346                {
3347                        sText += AtlFormatString(_T("## ") _T("Clock") _T("\r\n") _T("\r\n"));
3348                        CComPtr<IReferenceClock> pCurrentReferenceClock;
3349                        _ATLTRY
3350                        {
3351                                const CComQIPtr<IMediaFilter> pMediaFilter = pFilterGraph;
3352                                if(pMediaFilter)
3353                                        __C(pMediaFilter->GetSyncSource(&pCurrentReferenceClock));
3354                        }
3355                        _ATLCATCHALL()
3356                        {
3357                                _Z_EXCEPTION();
3358                        }
3359                        CStringW sCurrentName;
3360                        for(auto&& pBaseFilter: FilterArray)
3361                        {
3362                                const CComQIPtr<IReferenceClock> pReferenceClock = pBaseFilter;
3363                                if(!pReferenceClock)
3364                                        continue;
3365                                const CStringW sName = _FilterGraphHelper::GetFilterName(pBaseFilter);
3366                                CRoArrayT<CString> Array;
3367                                _ATLTRY
3368                                {
3369                                        if(pCurrentReferenceClock == pReferenceClock)
3370                                        {
3371                                                sCurrentName = sName;
3372                                                Array.Add(_T("Current"));
3373                                        }
3374                                        Array.Add(I(pReferenceClock));
3375                                        REFERENCE_TIME nTime = 0;
3376                                        __C(pReferenceClock->GetTime(&nTime));
3377                                        Array.Add(I(_FilterGraphHelper::FormatReferenceTime(nTime)));
3378                                        Array.Add(I(AtlFormatString(_T("0x%I64X"), nTime)));
3379                                }
3380                                _ATLCATCHALL()
3381                                {
3382                                        _Z_EXCEPTION();
3383                                }
3384                                sText += AtlFormatString(_T(" * ") _T("%s (%s)") _T("\r\n"), I(sName), _StringHelper::Join(Array, _T(", ")));
3385                        }
3386                        if(pCurrentReferenceClock)
3387                        {
3388                                if(sCurrentName.IsEmpty())
3389                                {
3390                                        CRoArrayT<CString> Array;
3391                                        _ATLTRY
3392                                        {
3393                                                Array.Add(I(pCurrentReferenceClock));
3394                                                REFERENCE_TIME nTime = 0;
3395                                                __C(pCurrentReferenceClock->GetTime(&nTime));
3396                                                Array.Add(I(_FilterGraphHelper::FormatReferenceTime(nTime)));
3397                                                Array.Add(I(AtlFormatString(_T("0x%I64X"), nTime)));
3398                                        }
3399                                        _ATLCATCHALL()
3400                                        {
3401                                                _Z_EXCEPTION();
3402                                        }
3403                                        sText += AtlFormatString(_T(" * ") _T("Current: External (%s)") _T("\r\n"), _StringHelper::Join(Array, _T(", ")));
3404                                }
3405                        } else
3406                                sText += AtlFormatString(_T(" * ") _T("Current: None") _T("\r\n"));
3407                        sText += _T("\r\n");
3408                }
3409                #pragma endregion
3410                return sText;
3411        }
3412        #undef I
3413        CComPtr<IFilterGraph> GetFilterGraph() const
3414        {
3415                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
3416                return m_pFilterGraph;
3417        }
3418        VOID SetFilterGraph(IFilterGraph* pFilterGraph, CProcessData* pProcessData = NULL) 
3419        {
3420                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
3421                if(!pProcessData)
3422                {
3423                        m_ProcessData = CProcessData();
3424                        const CComQIPtr<ISpyEx> pSpyEx = pFilterGraph;
3425                        if(pSpyEx)
3426                                m_ProcessData.m_nIdentifier = GetCurrentProcessId();
3427                } else
3428                        m_ProcessData = *pProcessData;
3429                m_pFilterGraph = pFilterGraph;
3430        }
3431        BOOL SetFilterGraph(IUnknown* pFilterGraphUnknown, CProcessData* pProcessData = NULL) 
3432        {
3433                CComQIPtr<IFilterGraph> pFilterGraph;
3434                if(pFilterGraphUnknown)
3435                {
3436                        pFilterGraph = pFilterGraphUnknown;
3437                        if(!pFilterGraph)
3438                        {
3439                                const CComQIPtr<IBaseFilter> pBaseFilter = pFilterGraphUnknown;
3440                                if(!pBaseFilter)
3441                                {
3442                                        const CComQIPtr<IPin> pPin = pFilterGraphUnknown;
3443                                        if(pPin)
3444                                                pFilterGraph = _FilterGraphHelper::GetFilterGraph(_FilterGraphHelper::GetPinFilter(pPin));
3445                                } else
3446                                        pFilterGraph = _FilterGraphHelper::GetFilterGraph(pBaseFilter);
3447                        }
3448                }
3449                SetFilterGraph(pFilterGraph, pProcessData);
3450                return pFilterGraph != NULL;
3451        }
3452        CString GetFilterText(IBaseFilter* pBaseFilter) const
3453        {
3454                return GetFilterText(pBaseFilter, m_ProcessData.m_nIdentifier ? &m_ProcessData : NULL);
3455        }
3456        CString GetText() const
3457        {
3458                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
3459                return GetText(m_pFilterGraph, m_ProcessData.m_nIdentifier ? &m_ProcessData : NULL);
3460        }
3461        static LPCTSTR GetPlatformName()
3462        {
3463                #if defined(_WIN64)
3464                        return _T("x64");
3465                #else
3466                        return _T("Win32");
3467                #endif // defined(_WIN64)
3468        }
3469        template <SIZE_T t_nItemCount>
3470        static CString& GetLegacyFilter(const COMDLG_FILTERSPEC (&pItems)[t_nItemCount], CString& sFilter)
3471        {
3472                _A(sFilter.IsEmpty());
3473                for(SIZE_T nIndex = 0; nIndex < t_nItemCount; nIndex++)
3474                {
3475                        const COMDLG_FILTERSPEC& Item = pItems[nIndex];
3476                        sFilter += AtlFormatString(_T("%s (%s)|%s|"), Item.pszName, Item.pszSpec, Item.pszSpec);
3477                }
3478                sFilter.Replace(_T('|'), 0);
3479                return sFilter;
3480        }
3481        static BOOL OpenMonikerWithGsn(LPCWSTR pszMonikerDisplayName, HWND hParentWindow = GetActiveWindow())
3482        {
3483                _A(pszMonikerDisplayName);
3484                static const LPCTSTR g_pszValueName = _T("GraphStudioNext Path");
3485                static const LPCTSTR g_pszFileName = _T("graphstudionext.exe");
3486                const CString sValueName = AtlFormatString(_T("%s (%s)"), g_pszValueName, GetPlatformName());
3487                CString sPath = _RegKeyHelper::QueryStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, sValueName);
3488                if(!FileExists(sPath))
3489                        sPath.Empty();
3490                #pragma region Current Directory
3491                if(sPath.IsEmpty())
3492                {
3493                        sPath = (LPCTSTR) Combine(GetPathDirectory(GetModulePath()), g_pszFileName);
3494                        if(!FileExists(sPath))
3495                                sPath.Empty();
3496                }
3497                #pragma endregion
3498                #pragma region Application Registry
3499                if(sPath.IsEmpty())
3500                {
3501                        #if defined(_WIN64)
3502                                static const LPCTSTR g_pszValueName = _T("exeLocation64");
3503                        #else
3504                                static const LPCTSTR g_pszValueName = _T("exeLocation");
3505                        #endif // defined(_WIN64)
3506                        sPath = _RegKeyHelper::QueryStringValue(HKEY_CURRENT_USER, _T("Software\\MONOGRAM\\GraphStudioNext"), g_pszValueName);
3507                        if(!FileExists(sPath))
3508                                sPath.Empty();
3509                }
3510                #pragma endregion
3511                if(sPath.IsEmpty())
3512                {
3513                        #pragma region Prompt
3514                        static const COMDLG_FILTERSPEC g_pFilter[] = 
3515                        {
3516                                { _T("Executable Files"), _T("*.exe") },
3517                                { _T("All Files"), _T("*.*") },
3518                        };
3519                        if(GetOsVersion() >= GetWinVistaOsVersion())
3520                        {
3521                                CShellFileOpenDialog Dialog(g_pszFileName, FOS_FORCEFILESYSTEM | FOS_FILEMUSTEXIST, _T("exe"), g_pFilter, DIM(g_pFilter));
3522                                if(Dialog.DoModal(hParentWindow) != IDOK)
3523                                        return FALSE;
3524                                __C(Dialog.GetFilePath(sPath));
3525                        } else
3526                        {
3527                                CString sFilter;
3528                                CFileDialog Dialog(TRUE, _T("exe"), NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_ENABLESIZING, GetLegacyFilter(g_pFilter, sFilter));
3529                                if(Dialog.DoModal(hParentWindow) != IDOK)
3530                                        return FALSE;
3531                                sPath = Dialog.m_szFileName;
3532                        }
3533                        #pragma endregion
3534                        _RegKeyHelper::SetStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, sValueName, sPath);
3535                }
3536                CWaitCursor WaitCursor;
3537                CString sParameters = AtlFormatString(_T("-a \"%ls\""), pszMonikerDisplayName);
3538                SHELLEXECUTEINFO Infomation;
3539                ZeroMemory(&Infomation, sizeof Infomation);
3540                Infomation.cbSize = sizeof Infomation;
3541                Infomation.lpFile = sPath;
3542                Infomation.lpParameters = sParameters;
3543                Infomation.nShow = SW_SHOWNORMAL;
3544                __E(ShellExecuteEx(&Infomation));
3545                return TRUE;
3546        }
3547        static BOOL OpenMonikerWithGe(LPCWSTR pszMonikerDisplayName, HWND hParentWindow = GetActiveWindow())
3548        {
3549                static const LPCTSTR g_pszValueName = _T("GraphEdit Path");
3550                static const LPCTSTR g_pszFileName = _T("graphedt.exe");
3551                const CString sValueName = AtlFormatString(_T("%s (%s)"), g_pszValueName, GetPlatformName());
3552                CString sPath = _RegKeyHelper::QueryStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, sValueName);
3553                if(!FileExists(sPath))
3554                        sPath.Empty();
3555                #pragma region Current Directory
3556                if(sPath.IsEmpty())
3557                {
3558                        sPath = (LPCTSTR) Combine(GetPathDirectory(GetModulePath()), g_pszFileName);
3559                        if(!FileExists(sPath))
3560                                sPath.Empty();
3561                }
3562                #pragma endregion
3563                // SUGG: Look for Windows SDK
3564                if(sPath.IsEmpty())
3565                {
3566                        #pragma region Prompt
3567                        static const COMDLG_FILTERSPEC g_pFilter[] = 
3568                        {
3569                                { _T("Executable Files"), _T("*.exe") },
3570                                { _T("All Files"), _T("*.*") },
3571                        };
3572                        if(GetOsVersion() >= GetWinVistaOsVersion())
3573                        {
3574                                CShellFileOpenDialog Dialog(g_pszFileName, FOS_FORCEFILESYSTEM | FOS_FILEMUSTEXIST, _T("exe"), g_pFilter, DIM(g_pFilter));
3575                                if(Dialog.DoModal(hParentWindow) != IDOK)
3576                                        return FALSE;
3577                                __C(Dialog.GetFilePath(sPath));
3578                        } else
3579                        {
3580                                CString sFilter;
3581                                CFileDialog Dialog(TRUE, _T("exe"), NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_ENABLESIZING, GetLegacyFilter(g_pFilter, sFilter));
3582                                if(Dialog.DoModal(hParentWindow) != IDOK)
3583                                        return FALSE;
3584                                sPath = Dialog.m_szFileName;
3585                        }
3586                        #pragma endregion
3587                        _RegKeyHelper::SetStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, sValueName, sPath);
3588                }
3589                CStringW sFilterGraphMonikerDisplayName = pszMonikerDisplayName;
3590                const INT nSeparatorPosition = sFilterGraphMonikerDisplayName.Find(L';');
3591                if(nSeparatorPosition >= 0)
3592                        sFilterGraphMonikerDisplayName = sFilterGraphMonikerDisplayName.Left(nSeparatorPosition);
3593                CWaitCursor WaitCursor;
3594                CString sParameters = AtlFormatString(_T("-a %ls"), sFilterGraphMonikerDisplayName);
3595                SHELLEXECUTEINFO Infomation;
3596                ZeroMemory(&Infomation, sizeof Infomation);
3597                Infomation.cbSize = sizeof Infomation;
3598                Infomation.lpFile = sPath;
3599                Infomation.lpParameters = sParameters;
3600                Infomation.nShow = SW_SHOWNORMAL;
3601                __E(ShellExecuteEx(&Infomation));
3602                return TRUE;
3603        }
3604
3605// IFilterGraphHelper
3606        STDMETHOD(get_FilterGraph)(IUnknown** ppFilterGraphUnknown)
3607        {
3608                _Z4(atlTraceCOM, 4, _T("...\n"));
3609                _ATLTRY
3610                {
3611                        __D(ppFilterGraphUnknown, E_POINTER);
3612                        *ppFilterGraphUnknown = GetFilterGraph().Detach();
3613                }
3614                _ATLCATCH(Exception)
3615                {
3616                        _C(Exception);
3617                }
3618                return S_OK;
3619        }
3620        STDMETHOD(put_FilterGraph)(IUnknown* pFilterGraphUnknown)
3621        {
3622                _Z4(atlTraceCOM, 4, _T("pFilterGraphUnknown 0x%p\n"), pFilterGraphUnknown);
3623                _ATLTRY
3624                {
3625                        if(!SetFilterGraph(pFilterGraphUnknown))
3626                                return S_FALSE;
3627                }
3628                _ATLCATCH(Exception)
3629                {
3630                        _C(Exception);
3631                }
3632                return S_OK;
3633        }
3634        STDMETHOD(get_Text)(BSTR* psText)
3635        {
3636                _Z4(atlTraceCOM, 4, _T("...\n"));
3637                _ATLTRY
3638                {
3639                        __D(psText, E_POINTER);
3640                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
3641                        *psText = CComBSTR(GetText(m_pFilterGraph)).Detach();
3642                }
3643                _ATLCATCH(Exception)
3644                {
3645                        _C(Exception);
3646                }
3647                return S_OK;
3648        }
3649        STDMETHOD(DoPropertyFrameModal)(LONG nParentWindowHandle)
3650        {
3651                _Z4(atlTraceCOM, 4, _T("nParentWindowHandle 0x%08X\n"), nParentWindowHandle);
3652                _ATLTRY
3653                {
3654                        CWindow ParentWindow = (HWND) (LONG_PTR) nParentWindowHandle;
3655                        if(!ParentWindow)
3656                                ParentWindow = GetActiveWindow();
3657                        //__D(!ParentWindow || ParentWindow.IsWindow(), E_INVALIDARG);
3658                        const CComQIPtr<IFilterGraph2> pFilterGraph2 = GetFilterGraph();
3659                        __D(pFilterGraph2, E_NOINTERFACE);
3660                        CPropertyFrameDialog PropertyFrameDialog(this);
3661                        PropertyFrameDialog.DoModal(ParentWindow);
3662                }
3663                _ATLCATCH(Exception)
3664                {
3665                        _C(Exception);
3666                }
3667                return S_OK;
3668        }
3669        STDMETHOD(DoFilterGraphListModal)(LONG nParentWindowHandle)
3670        {
3671                _Z4(atlTraceCOM, 4, _T("nParentWindowHandle 0x%08X\n"), nParentWindowHandle);
3672                _ATLTRY
3673                {
3674                        CWindow ParentWindow = (HWND) (LONG_PTR) nParentWindowHandle;
3675                        if(!ParentWindow)
3676                                ParentWindow = GetActiveWindow();
3677                        //__D(!ParentWindow || ParentWindow.IsWindow(), E_INVALIDARG);
3678                        DoFilterGraphListPropertySheetModal(ParentWindow, &m_Options);
3679                }
3680                _ATLCATCH(Exception)
3681                {
3682                        _C(Exception);
3683                }
3684                return S_OK;
3685        }
3686        STDMETHOD(OpenGraphStudioNext)(LONG nParentWindowHandle, BSTR sMonikerDisplayName, VARIANT_BOOL* pbResult)
3687        {
3688                _Z4(atlTraceCOM, 4, _T("nParentWindowHandle 0x%08X, sMonikerDisplayName \"%s\"\n"), nParentWindowHandle, CString(sMonikerDisplayName));
3689                _ATLTRY
3690                {
3691                        __D(sMonikerDisplayName && *sMonikerDisplayName, E_INVALIDARG);
3692                        CWindow ParentWindow = (HWND) (LONG_PTR) nParentWindowHandle;
3693                        if(!ParentWindow)
3694                                ParentWindow = GetActiveWindow();
3695                        //__D(!ParentWindow || ParentWindow.IsWindow(), E_INVALIDARG);
3696                        const BOOL bResult = OpenMonikerWithGsn(sMonikerDisplayName, ParentWindow);
3697                        if(pbResult)
3698                                *pbResult = bResult ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE;
3699                }
3700                _ATLCATCH(Exception)
3701                {
3702                        _C(Exception);
3703                }
3704                return S_OK;
3705        }
3706        STDMETHOD(OpenGraphEdit)(LONG nParentWindowHandle, BSTR sMonikerDisplayName, VARIANT_BOOL* pbResult)
3707        {
3708                _Z4(atlTraceCOM, 4, _T("nParentWindowHandle 0x%08X, sMonikerDisplayName \"%s\"\n"), nParentWindowHandle, CString(sMonikerDisplayName));
3709                _ATLTRY
3710                {
3711                        __D(sMonikerDisplayName && *sMonikerDisplayName, E_INVALIDARG);
3712                        CWindow ParentWindow = (HWND) (LONG_PTR) nParentWindowHandle;
3713                        if(!ParentWindow)
3714                                ParentWindow = GetActiveWindow();
3715                        //__D(!ParentWindow || ParentWindow.IsWindow(), E_INVALIDARG);
3716                        const BOOL bResult = OpenMonikerWithGe(sMonikerDisplayName, ParentWindow);
3717                        if(pbResult)
3718                                *pbResult = bResult ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE;
3719                }
3720                _ATLCATCH(Exception)
3721                {
3722                        _C(Exception);
3723                }
3724                return S_OK;
3725        }
3726        STDMETHOD(get_Options)(VARIANT* pvOptions)
3727        {
3728                _Z4(atlTraceCOM, 4, _T("...\n"));
3729                _ATLTRY
3730                {
3731                        __D(pvOptions, E_POINTER);
3732                        VariantInit(pvOptions);
3733                        __C(m_Options.GetVariant().Detach(pvOptions));
3734                }
3735                _ATLCATCH(Exception)
3736                {
3737                        _C(Exception);
3738                }
3739                return S_OK;
3740        }
3741        STDMETHOD(put_Options)(VARIANT vOptions)
3742        {
3743                _Z4(atlTraceCOM, 4, _T("vOptions.vt 0x%X\n"), vOptions.vt);
3744                _ATLTRY
3745                {
3746                        m_Options.SetVariant(vOptions);
3747                }
3748                _ATLCATCH(Exception)
3749                {
3750                        _C(Exception);
3751                }
3752                return S_OK;
3753        }
3754};
3755
3756OBJECT_ENTRY_AUTO(__uuidof(FilterGraphHelper), CFilterGraphHelper)
3757
3758inline HRESULT FilterGraphHelper_DoPropertyFrameModal(LONG nParentWindowHandle, IUnknown* pFilterGraphUnknown)
3759{
3760        CLocalObjectPtr<CFilterGraphHelper> pFilterGraphHelper;
3761        pFilterGraphHelper->SetFilterGraph(pFilterGraphUnknown);
3762        return pFilterGraphHelper->DoPropertyFrameModal(nParentWindowHandle);
3763}
3764inline HRESULT FilterGraphHelper_DoFilterGraphListModal(LONG nParentWindowHandle)
3765{
3766        CLocalObjectPtr<CFilterGraphHelper> pFilterGraphHelper;
3767        return pFilterGraphHelper->DoFilterGraphListModal(nParentWindowHandle);
3768}
3769inline HRESULT FilterGraphHelper_OpenGraphStudioNext(LONG nParentWindowHandle, LPCWSTR pszMonikerDisplayName, VARIANT_BOOL* pbResult)
3770{
3771        CLocalObjectPtr<CFilterGraphHelper> pFilterGraphHelper;
3772        return pFilterGraphHelper->OpenGraphStudioNext(nParentWindowHandle, CComBSTR(pszMonikerDisplayName), pbResult);
3773}
3774inline HRESULT FilterGraphHelper_OpenGraphEdit(LONG nParentWindowHandle, LPCWSTR pszMonikerDisplayName, VARIANT_BOOL* pbResult)
3775{
3776        CLocalObjectPtr<CFilterGraphHelper> pFilterGraphHelper;
3777        return pFilterGraphHelper->OpenGraphEdit(nParentWindowHandle, CComBSTR(pszMonikerDisplayName), pbResult);
3778}
Note: See TracBrowser for help on using the repository browser.