source: trunk/DirectShowSpy/FilterGraphHelper.h @ 270

Last change on this file since 270 was 270, checked in by roman, 9 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.