source: trunk/DirectShowSpy/FilterGraphHelper.h @ 370

Last change on this file since 370 was 359, checked in by roman, 9 years ago

Suppress exceptions on missing property pages in property frame helper; Suppress exceptions on reading non-implemented properties via IQualProp

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