source: trunk/DirectShowSpy/FilterGraphHelper.h @ 270

Last change on this file since 270 was 270, checked in by roman, 10 years ago

Fixed issue with showing up helper window on older Common Controls application without ListView? grouping support

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