source: trunk/DirectShowSpy/FilterGraphHelper.h @ 256

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