source: trunk/DirectShowSpy/FilterGraphHelper.h @ 333

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

Added filter graph runtime property bag and events through IRegisterServiceProvider

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