source: trunk/DirectShowSpy/FilterGraphHelper.h @ 276

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

Updated header (on use, applicability, redistribution)

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