source: trunk/DirectShowSpy/FilterGraphHelper.h @ 242

Last change on this file since 242 was 242, checked in by roman, 10 years ago
File size: 75.6 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
14INT_PTR DoFilterGraphListPropertySheetModal(HWND hParentWindow);
15
16////////////////////////////////////////////////////////////
17// CFilterGraphHelper
18
19class ATL_NO_VTABLE CFilterGraphHelper :
20        public CComObjectRootEx<CComMultiThreadModelNoCS>,
21        public CComCoClass<CFilterGraphHelper, &__uuidof(FilterGraphHelper)>,
22        public IProvideClassInfo2Impl<&__uuidof(FilterGraphHelper), &IID_NULL>,
23        public IDispatchImpl<IFilterGraphHelper>
24{
25public:
26        enum { IDR = IDR_FILTERGRAPHHELPER };
27
28//DECLARE_REGISTRY_RESOURCEID(IDR)
29
30BEGIN_COM_MAP(CFilterGraphHelper)
31        COM_INTERFACE_ENTRY(IFilterGraphHelper)
32        COM_INTERFACE_ENTRY(IDispatch)
33        COM_INTERFACE_ENTRY(IProvideClassInfo2)
34        COM_INTERFACE_ENTRY(IProvideClassInfo)
35END_COM_MAP()
36
37public:
38
39        ////////////////////////////////////////////////////////
40        // CProcessData
41
42        class CProcessData
43        {
44        public:
45                CStringW m_sDisplayName;
46                DWORD m_nIdentifier;
47                CPath m_sImagePath;
48        };
49
50        ////////////////////////////////////////////////////////
51        // CPropertyFrameDialog
52
53        class CPropertyFrameDialog :
54                public CDialogImpl<CPropertyFrameDialog>,
55                public CDialogResize<CPropertyFrameDialog>,
56                public CDialogWithAcceleratorsT<CPropertyFrameDialog>
57        {
58        public:
59                enum { IDD = IDD_FILTERGRAPHHELPER_PROPERTYFRAME };
60
61        BEGIN_MSG_MAP_EX(CPropertyFrameDialog)
62                //CHAIN_MSG_MAP(CDialogImpl<CPropertyFrameDialog>)
63                CHAIN_MSG_MAP(CDialogResize<CPropertyFrameDialog>)
64                MSG_WM_INITDIALOG(OnInitDialog)
65                MSG_WM_DESTROY(OnDestroy)
66                MSG_TVN_SELCHANGED(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TREE, OnTreeViewSelChanged)
67                MSG_TVN_ITEMEXPANDING(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TREE, OnTreeViewItemExplanding)
68                MSG_TVN_DBLCLK(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TREE, OnTreeViewDblClk)
69                MSG_WM_SYSCOMMAND(OnSysCommand)
70                COMMAND_ID_HANDLER_EX(IDOK, OnOk)
71                COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel)
72                COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_APPLY, OnApply)
73                COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_ACTION_OPENGSN, OnActionCommand)
74                COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_ACTION_OPENGE, OnActionCommand)
75                COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_ACTION_OPENLIST, OnActionCommand)
76                REFLECT_NOTIFICATIONS()
77        END_MSG_MAP()
78
79        BEGIN_DLGRESIZE_MAP(CPropertyFrameDialog)
80                DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TREE, DLSZ_SIZE_Y)
81                DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TEXT, DLSZ_SIZE_X | DLSZ_SIZE_Y)
82                DLGRESIZE_CONTROL(IDOK, DLSZ_MOVE_X | DLSZ_MOVE_Y)
83                DLGRESIZE_CONTROL(IDCANCEL, DLSZ_MOVE_X | DLSZ_MOVE_Y)
84                DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_APPLY, DLSZ_MOVE_X | DLSZ_MOVE_Y)
85        END_DLGRESIZE_MAP()
86
87        public:
88
89                ////////////////////////////////////////////////////
90                // CPropertyPageSite
91
92                class ATL_NO_VTABLE CPropertyPageSite :
93                        public CComObjectRootEx<CComSingleThreadModel>,
94                        public IPropertyPageSite
95                {
96                        friend class CPropertyFrameDialog;
97
98                public:
99
100                BEGIN_COM_MAP(CPropertyPageSite)
101                        COM_INTERFACE_ENTRY(IPropertyPageSite)
102                END_COM_MAP()
103
104                private:
105                        CPropertyFrameDialog* m_pOwner;
106                        CComPtr<IUnknown> m_pUnknown;
107                        CComPtr<IPropertyPage> m_pPropertyPage;
108                        CString m_sTitle;
109                        DWORD m_nStatus;
110
111                public:
112                // CPropertyPageSite
113                        CPropertyPageSite() :
114                                m_pOwner(NULL)
115                        {
116                        }
117                        VOID Initialize(CPropertyFrameDialog* pOwner, IUnknown* pUnknown, IPropertyPage* pPropertyPage)
118                        {
119                                _A(pOwner && pUnknown && pPropertyPage);
120                                _A(!m_pOwner);
121                                m_pOwner = pOwner;
122                                m_pUnknown = pUnknown;
123                                m_pPropertyPage = pPropertyPage;
124                                __C(pPropertyPage->SetObjects(1, &m_pUnknown.p));
125                                PROPPAGEINFO Information;
126                                ZeroMemory(&Information, sizeof Information);
127                                Information.cb = sizeof Information;
128                                __C(pPropertyPage->GetPageInfo(&Information));
129                                CStringW sTitle = Information.pszTitle;
130                                CoTaskMemFree(Information.pszTitle);
131                                CoTaskMemFree(Information.pszDocString);
132                                CoTaskMemFree(Information.pszHelpFile);
133                                m_sTitle = CString(sTitle);
134                                m_nStatus = 0;
135                                __C(pPropertyPage->SetPageSite(this));
136                        }
137                        VOID Terminate()
138                        {
139                                if(m_pPropertyPage)
140                                {
141                                        _V(m_pPropertyPage->SetPageSite(NULL));
142                                        m_pPropertyPage.Release();
143                                }
144                                m_pUnknown.Release();
145                                m_pOwner = NULL;
146                        }
147                        BOOL IsDirty()
148                        {
149                                return m_nStatus & PROPPAGESTATUS_DIRTY;
150                        }
151
152                // IPropertyPageSite
153                        STDMETHOD(OnStatusChange)(DWORD nFlags)
154                        {
155                                _Z4(atlTraceCOM, 4, _T("nFlags 0x%x\n"), nFlags);
156                                m_nStatus = nFlags;
157                                m_pOwner->HandleStatusChange(this);
158                                return S_OK;
159                        }
160                        STDMETHOD(GetLocaleID)(LCID* pLocaleIdentifier)
161                        {
162                                _Z4(atlTraceCOM, 4, _T("...\n"));
163                                pLocaleIdentifier;
164                                return E_NOTIMPL;
165                        }
166                        STDMETHOD(GetPageContainer)(IUnknown** ppUnknown)
167                        {
168                                _Z4(atlTraceCOM, 4, _T("...\n"));
169                                ppUnknown;
170                                return E_NOTIMPL;
171                        }
172                        STDMETHOD(TranslateAccelerator)(MSG* pMessage)
173                        {
174                                _Z4(atlTraceCOM, 4, _T("...\n"));
175                                pMessage;
176                                return E_NOTIMPL;
177                        }
178                };
179
180                ////////////////////////////////////////////////////
181                // CActionDialog
182
183                class CActionDialog :
184                        public CDialogImpl<CActionDialog>,
185                        public CDialogResize<CActionDialog>
186                {
187                public:
188                        enum { IDD = IDD_FILTERGRAPHHELPER_ACTION };
189
190                BEGIN_MSG_MAP_EX(CActionDialog)
191                        //CHAIN_MSG_MAP(CDialogImpl<CActionDialog>)
192                        CHAIN_MSG_MAP(CDialogResize<CActionDialog>)
193                        MSG_WM_INITDIALOG(OnInitDialog)
194                        COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_ACTION_SAVEAS, OnSaveAs)
195                        COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_ACTION_OPENGSN, OnOpenGsn)
196                        COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_ACTION_OPENGE, OnOpenGe)
197                        COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_ACTION_OPENLIST, OnOpenList)
198                        REFLECT_NOTIFICATIONS()
199                END_MSG_MAP()
200
201                BEGIN_DLGRESIZE_MAP(CActionDialog)
202                        //DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_ACTION_, DLSZ_SIZE_X | DLSZ_SIZE_Y)
203                END_DLGRESIZE_MAP()
204
205                private:
206                        CPropertyFrameDialog* m_pOwner;
207                        BOOL m_bActivating;
208                        CStatic m_TitleStatic;
209                        CFont m_TitleFont;
210                        CButton m_SaveAsButton;
211                        CRoHyperStatic m_SaveAsDescriptionStatic;
212                        CButton m_OpenGsnButton;
213                        CRoHyperStatic m_OpenGsnDescriptionStatic;
214                        CButton m_OpenGeButton;
215                        CRoHyperStatic m_OpenGeDescriptionStatic;
216                        CButton m_OpenListButton;
217                        CRoHyperStatic m_OpenListDescriptionStatic;
218                        CStringW m_sFilterGraphMonikerDisplayName;
219                        CRoMapT<INT_PTR, BOOL> m_ChangeMap;
220
221                public:
222                // CActionDialog
223
224                // Window Message Handler
225                        LRESULT OnInitDialog(HWND, LPARAM lParam)
226                        {
227                                m_pOwner = (CPropertyFrameDialog*) lParam;
228                                m_bActivating = TRUE;
229                                _ATLTRY
230                                {
231                                        CWaitCursor WaitCursor;
232                                        m_TitleStatic = GetDlgItem(IDC_FILTERGRAPHHELPER_ACTION_TITLE);
233                                        CreateTitleFont(m_TitleFont, m_TitleStatic);
234                                        m_SaveAsButton = GetDlgItem(IDC_FILTERGRAPHHELPER_ACTION_SAVEAS);
235                                        _W(m_SaveAsDescriptionStatic.SubclassWindow(GetDlgItem(IDC_FILTERGRAPHHELPER_ACTION_SAVEASDESCRIPTION)));
236                                        m_OpenGsnButton = GetDlgItem(IDC_FILTERGRAPHHELPER_ACTION_OPENGSN);
237                                        _W(m_OpenGsnDescriptionStatic.SubclassWindow(GetDlgItem(IDC_FILTERGRAPHHELPER_ACTION_OPENGSNDESCRIPTION)));
238                                        m_OpenGeButton = GetDlgItem(IDC_FILTERGRAPHHELPER_ACTION_OPENGE);
239                                        _W(m_OpenGeDescriptionStatic.SubclassWindow(GetDlgItem(IDC_FILTERGRAPHHELPER_ACTION_OPENGEDESCRIPTION)));
240                                        m_OpenListButton = GetDlgItem(IDC_FILTERGRAPHHELPER_ACTION_OPENLIST);
241                                        _W(m_OpenListDescriptionStatic.SubclassWindow(GetDlgItem(IDC_FILTERGRAPHHELPER_ACTION_OPENLISTDESCRIPTION)));
242                                        //DlgResize_Init(FALSE, FALSE);
243                                        _ATLTRY
244                                        {
245                                                m_sFilterGraphMonikerDisplayName.Empty();
246                                                const CComQIPtr<ISpy> pSpy = m_pOwner->m_Owner.GetFilterGraph();
247                                                if(pSpy)
248                                                {
249                                                        CComBSTR sFilterGraphMonikerDisplayName;
250                                                        __C(pSpy->get_MonikerDisplayName(&sFilterGraphMonikerDisplayName));
251                                                        m_sFilterGraphMonikerDisplayName = sFilterGraphMonikerDisplayName;
252                                                }
253                                        }
254                                        _ATLCATCHALL()
255                                        {
256                                                _Z_EXCEPTION();
257                                        }
258                                        const BOOL bMonikerDisplayNameAvailable = !m_sFilterGraphMonikerDisplayName.IsEmpty();
259                                        m_OpenGsnButton.EnableWindow(bMonikerDisplayNameAvailable);
260                                        m_OpenGeButton.EnableWindow(bMonikerDisplayNameAvailable);
261                                        m_bActivating = FALSE;
262                                }
263                                _ATLCATCH(Exception)
264                                {
265                                        for(CWindow Window = GetWindow(GW_CHILD); Window; Window = Window.GetWindow(GW_HWNDNEXT))
266                                                Window.EnableWindow(FALSE);
267                                        AtlExceptionMessageBox(m_hWnd, Exception);
268                                }
269                                return TRUE;
270                        }
271                        LRESULT OnSaveAs(UINT, INT, HWND)
272                        {
273                                CPath sPath;
274                                static const COMDLG_FILTERSPEC g_pFilter[] = 
275                                {
276                                        { _T("GraphEdit Files"), _T("*.grf") },
277                                        { _T("All Files"), _T("*.*") },
278                                };
279                                if(GetOsVersion() >= GetWinVistaOsVersion())
280                                {
281                                        CShellFileSaveDialog Dialog(NULL, FOS_OVERWRITEPROMPT | FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST, _T("grf"), g_pFilter, DIM(g_pFilter));
282                                        if(Dialog.DoModal(m_hWnd) != IDOK)
283                                                return 0;
284                                        CString sPathString;
285                                        __C(Dialog.GetFilePath(sPathString));
286                                        sPath = (LPCTSTR) sPathString;
287                                } else
288                                {
289                                        CString sFilter;
290                                        CFileDialog Dialog(FALSE, _T("grf"), NULL, OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_EXPLORER | OFN_ENABLESIZING, GetLegacyFilter(g_pFilter, sFilter));
291                                        if(Dialog.DoModal(m_hWnd) != IDOK)
292                                                return 0;
293                                        sPath = Dialog.m_szFileName;
294                                }
295                                #pragma region Save
296                                // NOTE: See http://msdn.microsoft.com/en-us/library/windows/desktop/dd377551
297                                const CComQIPtr<IPersistStream> pPersistStream = m_pOwner->m_Owner.GetFilterGraph();
298                                __D(pPersistStream, E_NOINTERFACE);
299                                CComPtr<IStorage> pStorage;
300                                {
301                                        __C(StgCreateDocfile(CStringW(sPath), STGM_CREATE | STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage));
302                                        CComPtr<IStream> pStream;
303                                        __C(pStorage->CreateStream(L"ActiveMovieGraph", STGM_WRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream));
304                                        __C(pPersistStream->Save(pStream, TRUE));
305                                }
306                                __C(pStorage->Commit(STGC_DEFAULT));
307                                #pragma endregion
308                                MessageBeep(MB_OK);
309                                return 0;
310                        }
311                        LRESULT OnOpenGsn(UINT, INT, HWND)
312                        {
313                                OpenMonikerWithGsn(m_sFilterGraphMonikerDisplayName, m_hWnd);
314                                return 0;
315                        }
316                        LRESULT OnOpenGe(UINT, INT, HWND)
317                        {
318                                OpenMonikerWithGe(m_sFilterGraphMonikerDisplayName, m_hWnd);
319                                return 0;
320                        }
321                        LRESULT OnOpenList(UINT, INT, HWND)
322                        {
323                                DoFilterGraphListPropertySheetModal(m_hWnd);
324                                return 0;
325                        }
326                };
327
328                ////////////////////////////////////////////////////
329                // CEmailDialog
330
331                class CEmailDialog :
332                        public CDialogImpl<CEmailDialog>,
333                        public CDialogResize<CEmailDialog>
334                {
335                public:
336                        enum { IDD = IDD_FILTERGRAPHHELPER_EMAIL };
337
338                BEGIN_MSG_MAP_EX(CEmailDialog)
339                        //CHAIN_MSG_MAP(CDialogImpl<CEmailDialog>)
340                        CHAIN_MSG_MAP(CDialogResize<CEmailDialog>)
341                        MSG_WM_INITDIALOG(OnInitDialog)
342                        MSG_WM_DESTROY(OnDestroy)
343                        MSG_WM_SHOWWINDOW(OnShowWindow)
344                        COMMAND_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_FROM, EN_CHANGE, OnChanged)
345                        COMMAND_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_TO, EN_CHANGE, OnChanged)
346                        COMMAND_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_METHOD, CBN_SELENDOK, OnChanged)
347                        COMMAND_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_HOST, EN_CHANGE, OnChanged)
348                        COMMAND_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_USERNAME, EN_CHANGE, OnChanged)
349                        COMMAND_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_PASSWORD, EN_CHANGE, OnChanged)
350                        COMMAND_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_BODY, EN_CHANGE, OnChanged)
351                        COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHHELPER_EMAIL_SEND, OnSend)
352                        REFLECT_NOTIFICATIONS()
353                END_MSG_MAP()
354
355                BEGIN_DLGRESIZE_MAP(CEmailDialog)
356                        DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_EMAIL_BODY, DLSZ_SIZE_X | DLSZ_SIZE_Y)
357                        DLGRESIZE_CONTROL(IDC_FILTERGRAPHHELPER_EMAIL_SEND, DLSZ_MOVE_X | DLSZ_MOVE_Y)
358                END_DLGRESIZE_MAP()
359
360                private:
361                        CPropertyFrameDialog* m_pOwner;
362                        BOOL m_bActivating;
363                        CStatic m_TitleStatic;
364                        CFont m_TitleFont;
365                        CRoEdit m_FromEdit;
366                        CRoEdit m_ToEdit;
367                        CRoComboBoxT<> m_MethodComboBox;
368                        CRoEdit m_HostEdit;
369                        CRoEdit m_UsernameEdit;
370                        CRoEdit m_PasswordEdit;
371                        CRoEdit m_BodyEdit;
372                        CButton m_SendButton;
373                        CString m_sFilterGraphText;
374                        CRoMapT<INT_PTR, BOOL> m_ChangeMap;
375
376                public:
377                // CEmailDialog
378                        VOID InitializeControlsFromRegistry()
379                        {
380                                const CString sMessageString = _RegKeyHelper::QueryStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, _T("Email Message Template"));
381                                if(sMessageString.IsEmpty())
382                                        return;
383                                _ATLTRY
384                                {
385                                        CObjectPtr<CMessage> pMessage;
386                                        pMessage.Construct();
387                                        pMessage->LoadTypeInfo(IDR_EMAILTOOLS);
388                                        pMessage->SetAsString(CStringA(sMessageString));
389                                        #pragma region Sender and Recipients
390                                        CComBSTR sSender, sToRecipients;
391                                        __C(pMessage->get_Sender(&sSender));
392                                        __C(pMessage->get_ToRecipients(&sToRecipients));
393                                        m_FromEdit.SetValue(CString(sSender));
394                                        m_ToEdit.SetValue(CString(sToRecipients));
395                                        #pragma endregion
396                                        CComBSTR sAuthMethods;
397                                        __C(pMessage->get_AuthMethods(&sAuthMethods));
398                                        VARIANT_BOOL bSecureSocketsLayer, bTransportLayerSecurity;
399                                        __C(pMessage->get_SecureSocketsLayer(&bSecureSocketsLayer));
400                                        __C(pMessage->get_TransportLayerSecurity(&bTransportLayerSecurity));
401                                        #pragma region Host and Port
402                                        CComBSTR sHost;
403                                        __C(pMessage->get_ServerHost(&sHost));
404                                        LONG nPort = 0;
405                                        __C(pMessage->get_ServerPort(&nPort));
406                                        CString sHostT(sHost);
407                                        if(nPort)
408                                                sHostT += AtlFormatString(_T(":%d"), nPort);
409                                        m_HostEdit.SetValue(sHostT);
410                                        #pragma endregion
411                                        #pragma region User Name and Password
412                                        CComBSTR sAuthName, sAuthPassword;
413                                        __C(pMessage->get_AuthName(&sAuthName));
414                                        __C(pMessage->get_AuthPassword(&sAuthPassword));
415                                        m_UsernameEdit.SetValue(CString(sAuthName));
416                                        m_PasswordEdit.SetValue(CString(sAuthPassword));
417                                        #pragma endregion
418                                        m_MethodComboBox.SetCurSel(0);
419                                        if(bTransportLayerSecurity != ATL_VARIANT_FALSE && sHostT.CompareNoCase(_T("smtp.gmail.com")) == 0)
420                                        {
421                                                //m_MethodComboBox.SetCurSel(0);
422                                        } else
423                                        {
424                                                if(bTransportLayerSecurity != ATL_VARIANT_FALSE)
425                                                        m_MethodComboBox.SetCurSel(1);
426                                                else if(bSecureSocketsLayer != ATL_VARIANT_FALSE)
427                                                        m_MethodComboBox.SetCurSel(2);
428                                                else if(CString(sAuthMethods).CompareNoCase(_T("cram-md5")) == 0)
429                                                        m_MethodComboBox.SetCurSel(3);
430                                                else if(!CString(sAuthName).IsEmpty())
431                                                        m_MethodComboBox.SetCurSel(4);
432                                                else
433                                                        m_MethodComboBox.SetCurSel(5);
434                                        }
435                                }
436                                _ATLCATCHALL()
437                                {
438                                        _Z_EXCEPTION();
439                                }
440                        }
441                        VOID InitializeBody()
442                        {
443                                CString sText;
444                                sText += _T("(add notes here; graph data will be appended below)") _T("\r\n") _T("\r\n");
445                                sText += _T("* * *") _T("\r\n") _T("\r\n");
446                                #define I FormatIdentifier
447                                #pragma region System
448                                {
449                                        sText += _T("# System") _T("\r\n") _T("\r\n");
450                                        OSVERSIONINFOEX Version;
451                                        ZeroMemory(&Version, sizeof Version);
452                                        Version.dwOSVersionInfoSize = sizeof Version;
453                                        GetVersionEx((OSVERSIONINFO*) &Version);
454                                        #pragma region Version
455                                        CRoArrayT<CString> VersionArray;
456                                        VersionArray.Add(AtlFormatString(_T("%s Build %s"), I(AtlFormatString(_T("%d.%d"), Version.dwMajorVersion, Version.dwMinorVersion)), I(Version.dwBuildNumber)));
457                                        switch((Version.dwMajorVersion << 16) + Version.dwMinorVersion)
458                                        {
459                                        case 0x00050001: 
460                                                VersionArray.Add(_T("Windows XP"));
461                                                break;
462                                        case 0x00050002: 
463                                                if(Version.wProductType != VER_NT_WORKSTATION)
464                                                        VersionArray.Add(_T("Windows Server 2003"));
465                                                break;
466                                        case 0x00060000: 
467                                                if(Version.wProductType == VER_NT_WORKSTATION)
468                                                        VersionArray.Add(_T("Windows Vista"));
469                                                else
470                                                        VersionArray.Add(_T("Windows Server 2008"));
471                                                break;
472                                        case 0x00060001: 
473                                                if(Version.wProductType == VER_NT_WORKSTATION)
474                                                        VersionArray.Add(_T("Windows 7"));
475                                                else
476                                                        VersionArray.Add(_T("Windows Server 2008 R2"));
477                                                break;
478                                        case 0x00060002: 
479                                                if(Version.wProductType == VER_NT_WORKSTATION)
480                                                        VersionArray.Add(_T("Windows 8"));
481                                                else
482                                                        VersionArray.Add(_T("Windows Server 2012"));
483                                                break;
484                                        }
485                                        if(_tcslen(Version.szCSDVersion))
486                                                VersionArray.Add(Version.szCSDVersion);
487                                        if(Version.wServicePackMajor)
488                                                VersionArray.Add(AtlFormatString(_T("Service Pack %s"), I(AtlFormatString(_T("%d.%d"), Version.wServicePackMajor, Version.wServicePackMinor))));
489                                        //Version.wSuiteMask, Version.wProductType
490                                        sText += AtlFormatString(_T(" * ") _T("Version: %s") _T("\r\n"), _StringHelper::Join(VersionArray, _T("; ")));
491                                        #pragma endregion
492                                        TCHAR pszComputerName[256] = { 0 };
493                                        DWORD nComputerNameLength = DIM(pszComputerName);
494                                        GetComputerName(pszComputerName, &nComputerNameLength);
495                                        sText += AtlFormatString(_T(" * ") _T("Computer Name: %s") _T("\r\n"), I(pszComputerName));
496                                        TCHAR pszUserName[256] = { 0 };
497                                        DWORD nUserNameLength = DIM(pszUserName);
498                                        GetUserName(pszUserName, &nUserNameLength);
499                                        CString sUserName(pszUserName);
500                                        BOOL bAdministrator = FALSE;
501                                        bool bIsMember = FALSE;
502                                        if(CAccessToken().CheckTokenMembership(Sids::Admins(), &bIsMember) && bIsMember)
503                                                bAdministrator = TRUE;
504                                        sText += AtlFormatString(_T(" * ") _T("User Name: %s %s") _T("\r\n"), I(sUserName), bAdministrator ? _T("(Administrator)") : _T(""));
505                                        SYSTEM_INFO SystemInformation;
506                                        GetSystemInfo(&SystemInformation);
507                                        #pragma region Architecture
508                                        CString sArchitecture;
509                                        switch(SystemInformation.wProcessorArchitecture)
510                                        {
511                                        case PROCESSOR_ARCHITECTURE_INTEL:
512                                                sArchitecture = I(_T("x86"));
513                                                break;
514                                        case PROCESSOR_ARCHITECTURE_AMD64:
515                                                sArchitecture = I(_T("AMD/Intel x64"));
516                                                break;
517                                        case PROCESSOR_ARCHITECTURE_IA64:
518                                                sArchitecture = I(_T("Intel Itanium"));
519                                                break;
520                                        default:
521                                                sArchitecture = I(SystemInformation.wProcessorArchitecture, _T("0x%04X"));
522                                        }
523                                        #if defined(_WIN64)
524                                                sText += AtlFormatString(_T(" * ") _T("Architecture: %s (x64 Application)") _T("\r\n"), sArchitecture);
525                                        #else
526                                                sText += AtlFormatString(_T(" * ") _T("Architecture: %s") _T("\r\n"), sArchitecture);
527                                        #endif // defined(_WIN64)
528                                        #pragma endregion
529                                        sText += AtlFormatString(_T(" * ") _T("Processors: %s, Active Mask %s") _T("\r\n"), I(SystemInformation.dwNumberOfProcessors), I((DWORD) SystemInformation.dwActiveProcessorMask, _T("0x%X")));
530                                        sText += AtlFormatString(_T(" * ") _T("Page Size: %s") _T("\r\n"), I(SystemInformation.dwPageSize, _T("0x%X")));
531                                        sText += AtlFormatString(_T(" * ") _T("Application Address Space: %s..%s") _T("\r\n"), I(SystemInformation.lpMinimumApplicationAddress), I(SystemInformation.lpMaximumApplicationAddress));
532                                        #pragma region Memory
533                                        MEMORYSTATUSEX MemoryStatus = { sizeof MemoryStatus };
534                                        _W(GlobalMemoryStatusEx(&MemoryStatus));
535                                        sText += AtlFormatString(_T(" * ") _T("Physical Memory: %s MB") _T("\r\n"), I(_StringHelper::FormatNumber((LONG) (MemoryStatus.ullTotalPhys >> 20))));
536                                        sText += AtlFormatString(_T(" * ") _T("Committed Memory Limit: %s MB") _T("\r\n"), I(_StringHelper::FormatNumber((LONG) (MemoryStatus.ullTotalPageFile >> 20))));
537                                        #pragma endregion
538                                }
539                                #pragma endregion
540                                sText += AtlFormatString(_T(" * ") _T("Module Version: %s") _T("\r\n"), I(_VersionInfoHelper::GetVersionString(_VersionInfoHelper::GetFileVersion(_VersionInfoHelper::GetModulePath()))));
541                                SYSTEMTIME LocalTime;
542                                GetLocalTime(&LocalTime);
543                                sText += AtlFormatString(_T(" * ") _T("Local Time: %s") _T("\r\n"), I(_StringHelper::FormatDateTime(&LocalTime)));
544                                sText += _T("\r\n");
545                                #undef I
546                                m_BodyEdit.SetValue(sText);
547                        }
548                        VOID UpdateControls()
549                        {
550                                BOOL bAllowSend = TRUE;
551                                if(m_ToEdit.GetValue().Trim().IsEmpty())
552                                        bAllowSend = FALSE;
553                                const INT nMethod = m_MethodComboBox.GetCurSel();
554                                m_HostEdit.GetWindow(GW_HWNDPREV).EnableWindow(nMethod != 0); // Google Mail
555                                m_HostEdit.EnableWindow(nMethod != 0); // Google Mail
556                                m_UsernameEdit.GetWindow(GW_HWNDPREV).EnableWindow(nMethod != 5); // No Authentication
557                                m_UsernameEdit.EnableWindow(nMethod != 5); // No Authentication
558                                m_PasswordEdit.GetWindow(GW_HWNDPREV).EnableWindow(nMethod != 5); // No Authentication
559                                m_PasswordEdit.EnableWindow(nMethod != 5); // No Authentication
560                                if(nMethod != 0) // Google Mail
561                                        if(m_HostEdit.GetValue().Trim().IsEmpty())
562                                                bAllowSend = FALSE;
563                                if(nMethod != 5) // No Authentication
564                                {
565                                        if(m_UsernameEdit.GetValue().Trim().IsEmpty())
566                                                bAllowSend = FALSE;
567                                        if(m_PasswordEdit.GetValue().Trim().IsEmpty())
568                                                bAllowSend = FALSE;
569                                }
570                                m_SendButton.EnableWindow(bAllowSend);
571                        }
572
573                // Window Message Handler
574                        LRESULT OnInitDialog(HWND, LPARAM lParam)
575                        {
576                                m_pOwner = (CPropertyFrameDialog*) lParam;
577                                m_bActivating = TRUE;
578                                _ATLTRY
579                                {
580                                        CWaitCursor WaitCursor;
581                                        m_TitleStatic = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_TITLE);
582                                        CreateTitleFont(m_TitleFont, m_TitleStatic);
583                                        m_FromEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_FROM);
584                                        m_ToEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_TO);
585                                        m_MethodComboBox.Initialize(GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_METHOD));
586                                        m_MethodComboBox.SetCurSel(0);
587                                        m_HostEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_HOST);
588                                        m_UsernameEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_USERNAME);
589                                        m_PasswordEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_PASSWORD);
590                                        m_BodyEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_BODY);
591                                        m_BodyEdit.SetFont(m_pOwner->m_TextFont);
592                                        m_SendButton = GetDlgItem(IDC_FILTERGRAPHHELPER_EMAIL_SEND);
593                                        DlgResize_Init(FALSE, FALSE);
594                                        InitializeControlsFromRegistry();
595                                        InitializeBody();
596                                        m_sFilterGraphText = m_pOwner->m_Owner.GetText();
597                                        UpdateControls();
598                                        m_bActivating = FALSE;
599                                }
600                                _ATLCATCH(Exception)
601                                {
602                                        for(CWindow Window = GetWindow(GW_CHILD); Window; Window = Window.GetWindow(GW_HWNDNEXT))
603                                                Window.EnableWindow(FALSE);
604                                        AtlExceptionMessageBox(m_hWnd, Exception);
605                                }
606                                return TRUE;
607                        }
608                        LRESULT OnDestroy()
609                        {
610                                return 0;
611                        }
612                        LRESULT OnShowWindow(BOOL bShowing, INT)
613                        {
614                                if(bShowing && !m_ChangeMap.Lookup(IDC_FILTERGRAPHHELPER_EMAIL_BODY))
615                                        InitializeBody();
616                                return 0;
617                        }
618                        LRESULT OnChanged(UINT, INT_PTR nIdentifier, HWND)
619                        {
620                                if(m_bActivating)
621                                        return 0;
622                                m_ChangeMap[nIdentifier] = TRUE;
623                                UpdateControls();
624                                return 0;
625                        }
626                        LRESULT OnChanged(NMHDR* pHeader)
627                        {
628                                return OnChanged(pHeader->code, pHeader->idFrom, pHeader->hwndFrom);
629                        }
630                        LRESULT OnSend(UINT, INT, HWND)
631                        {
632                                CWaitCursor WaitCursor;
633                                CObjectPtr<CMessage> pMessage;
634                                pMessage.Construct();
635                                #pragma region Setup
636                                pMessage->LoadTypeInfo(IDR_EMAILTOOLS);
637                                __C(pMessage->put_Sender(CComBSTR(m_FromEdit.GetValue())));
638                                __C(pMessage->put_ToRecipients(CComBSTR(m_ToEdit.GetValue())));
639                                // NOTE:
640                                // 0 Google Mail (SMTP, TLS Connection)
641                                // 1 SMTP, TLS Connection, Plain Text Authentication (TLS, PLAIN)
642                                // 2 SMTP, SSL Connection, Plain Text Authentication (SSL, PLAIN)
643                                // 3 SMTP, Digest Authentication (CRAM-MD5)
644                                // 4 SMTP, Plain Text Authentication (PLAIN)
645                                // 5 SMTP, No Authentication
646                                const INT nMethod = m_MethodComboBox.GetCurSel();
647                                __C(pMessage->put_SecureSocketsLayer((nMethod == 2) ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE));
648                                __C(pMessage->put_TransportLayerSecurity((nMethod < 2) ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE));
649                                if(nMethod != 5)
650                                {
651                                        __C(pMessage->put_AuthMethods(CComBSTR(_T("plain"))));
652                                        __C(pMessage->put_AuthName(CComBSTR(m_UsernameEdit.GetValue())));
653                                        __C(pMessage->put_AuthPassword(CComBSTR(m_PasswordEdit.GetValue())));
654                                }
655                                switch(nMethod)
656                                {
657                                case 0:
658                                        __C(pMessage->put_ServerHost(CComBSTR(_T("smtp.gmail.com"))));
659                                        break;
660                                default:
661                                        CString sHost = m_HostEdit.GetValue();
662                                        sHost.Trim();
663                                        const INT nPortPosition = sHost.Find(_T(":"));
664                                        if(nPortPosition >= 0)
665                                        {
666                                                INT nPort;
667                                                __D(AtlStringToInteger(sHost.Mid(nPortPosition + 1), nPort), E_UNNAMED);
668                                                __C(pMessage->put_ServerPort(nPort));
669                                                sHost = sHost.Left(nPortPosition);
670                                        }
671                                        __C(pMessage->put_ServerHost(CComBSTR(sHost)));
672                                        break;
673                                }
674                                switch(nMethod)
675                                {
676                                case 3:
677                                        __C(pMessage->put_AuthMethods(CComBSTR(_T("cram-md5"))));
678                                        break;
679                                }
680                                #pragma endregion
681                                CStringA sMessageString = pMessage->GetAsString();
682                                CString sText = m_BodyEdit.GetValue();
683                                sText.TrimRight(_T("\t\n\r "));
684                                sText += _T("\r\n") _T("\r\n") _T("* * *") _T("\r\n") _T("\r\n");
685                                sText += m_sFilterGraphText;
686                                __C(pMessage->put_Body(CComBSTR(sText)));
687                                CString sSubject = AtlFormatString(_T("DirectShow Filter Graph by %s"), AtlLoadString(IDS_PROJNAME));
688                                __C(pMessage->put_Subject(CComBSTR(sSubject)));
689                                __C(pMessage->Send());
690                                MessageBeep(MB_OK);
691                                _RegKeyHelper::SetStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, _T("Email Message Template"), CString(sMessageString));
692                                return 0;
693                        }
694                };
695
696                ////////////////////////////////////////////////////
697                // CData
698
699                class CData
700                {
701                public:
702
703                        /////////////////////////////////////////////////////////
704                        // TYPE
705
706                        typedef enum _TYPE
707                        {
708                                TYPE_UNKNOWN = 0,
709                                TYPE_FILTERS,
710                                TYPE_FILTER,
711                                TYPE_FILTERPROPERTYPAGE,
712                                TYPE_ACTION,
713                                TYPE_EMAIL,
714                        } TYPE;
715
716                public:
717                        TYPE m_Type;
718                        CComPtr<IBaseFilter> m_pBaseFilter;
719                        CLSID m_ClassIdentifier;
720                        CComPtr<IPropertyPage> m_pPropertyPage;
721                        CObjectPtr<CPropertyPageSite> m_pSite;
722                        BOOL m_bSiteActivated;
723
724                public:
725                // CData
726                        CData(TYPE Type = TYPE_UNKNOWN) :
727                                m_Type(Type),
728                                m_ClassIdentifier(CLSID_NULL)
729                        {
730                        }
731                        CData(IBaseFilter* pBaseFilter) :
732                                m_Type(TYPE_FILTER),
733                                m_pBaseFilter(pBaseFilter),
734                                m_ClassIdentifier(CLSID_NULL)
735                        {
736                        }
737                        CData(IBaseFilter* pBaseFilter, const CLSID& ClassIdentifier, IPropertyPage* pPropertyPage) :
738                                m_Type(TYPE_FILTERPROPERTYPAGE),
739                                m_pBaseFilter(pBaseFilter),
740                                m_ClassIdentifier(ClassIdentifier),
741                                m_pPropertyPage(pPropertyPage),
742                                m_bSiteActivated(FALSE)
743                        {
744                                _A(pPropertyPage);
745                        }
746                        CString GetPropertyPageTitle() const
747                        {
748                                if(!m_pPropertyPage)
749                                        return _T("");
750                                PROPPAGEINFO PageInformation;
751                                ZeroMemory(&PageInformation, sizeof PageInformation);
752                                PageInformation.cb = sizeof PageInformation;
753                                __C(m_pPropertyPage->GetPageInfo(&PageInformation));
754                                CString sTitle(PageInformation.pszTitle);
755                                CoTaskMemFree(PageInformation.pszTitle);
756                                CoTaskMemFree(PageInformation.pszDocString);
757                                CoTaskMemFree(PageInformation.pszHelpFile);
758                                return sTitle;
759                        }
760                };
761
762        private:
763                CFilterGraphHelper& m_Owner;
764                BOOL m_bActivating; 
765                CRoTreeViewT<CData, CRoListControlDataTraitsT> m_TreeView;
766                CTreeItem m_FiltersItem;
767                CTreeItem m_ActionItem;
768                CTreeItem m_EmailItem;
769                CTabCtrl m_Tab;
770                CRoEdit m_TextEdit;
771                CRect m_TextPosition;
772                CFont m_TextFont;
773                CButton m_OkButton;
774                CButton m_CancelButton;
775                CButton m_ApplyButton;
776                CObjectPtr<CPropertyPageSite> m_pCurrentSite;
777                CActionDialog m_ActionDialog;
778                CEmailDialog m_EmailDialog;
779
780                static VOID CreateTitleFont(CFont& Font, HWND hStaticWindow = NULL)
781                {
782                        _A(!Font);
783                        CLogFont LogFont;
784                        LogFont.SetHeight(12);
785                        LogFont.lfWeight = FW_BOLD;
786                        _tcsncpy_s(LogFont.lfFaceName, _T("Verdana"), _TRUNCATE);
787                        _W(Font.CreateFontIndirect(&LogFont));
788                        if(hStaticWindow)
789                                CStatic(hStaticWindow).SetFont(Font);
790                }
791
792        public:
793        // CPropertyFrameDialog
794                CPropertyFrameDialog(CFilterGraphHelper* pOwner) :
795                        m_Owner(*pOwner)
796                {
797                }
798                CRect GetTextEditPosition() const
799                {
800                        CRect Position;
801                        _W(m_TextEdit.GetWindowRect(Position));
802                        _W(ScreenToClient(Position));
803                        return Position;
804                }
805                VOID UpdateTree()
806                {
807                        CWindowRedraw TreeViewRedraw(m_TreeView);
808                        m_TreeView.DeleteAllItems();
809                        #pragma region Filter
810                        CTreeItem FiltersItem = m_TreeView.InsertItem(NULL, NULL, CData(CData::TYPE_FILTERS), _T("Filters"));
811                        _FilterGraphHelper::CFilterArray FilterArray;
812                        _FilterGraphHelper::GetGraphFilters(m_Owner.m_pFilterGraph, FilterArray);
813                        CTreeItem PreviousFilterItem;
814                        for(SIZE_T nIndex = 0; nIndex < FilterArray.GetCount(); nIndex++)
815                        {
816                                const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nIndex];
817                                CTreeItem FilterItem = m_TreeView.InsertItem(FiltersItem, PreviousFilterItem, CData(pBaseFilter), CString(_FilterGraphHelper::GetFilterName(pBaseFilter)));
818                                PreviousFilterItem = FilterItem;
819                                #pragma region Property Page
820                                const CComQIPtr<ISpecifyPropertyPages> pSpecifyPropertyPages = pBaseFilter;
821                                if(!pSpecifyPropertyPages)
822                                        continue;
823                                _ATLTRY
824                                {
825                                        CAUUID Pages;
826                                        ZeroMemory(&Pages, sizeof Pages);
827                                        __C(pSpecifyPropertyPages->GetPages(&Pages));
828                                        CComHeapPtr<CLSID> pClassIdentifiers;
829                                        pClassIdentifiers.Attach(Pages.pElems);
830                                        CTreeItem PreviousPageItem;
831                                        for(UINT nPageIndex = 0; nPageIndex < Pages.cElems; nPageIndex++)
832                                        {
833                                                const CLSID& ClassIdentifier = pClassIdentifiers[nPageIndex];
834                                                if(ClassIdentifier == CLSID_NULL)
835                                                        continue;
836                                                _ATLTRY
837                                                {
838                                                        CComPtr<IPropertyPage> pPropertyPage;
839                                                        __C(pPropertyPage.CoCreateInstance(ClassIdentifier));
840                                                        CData Data(pBaseFilter, ClassIdentifier, pPropertyPage);
841                                                        Data.m_pSite.Construct()->Initialize(this, pBaseFilter, pPropertyPage);
842                                                        CTreeItem PageItem = m_TreeView.InsertItem(FilterItem, PreviousPageItem, Data, Data.GetPropertyPageTitle());
843                                                        PreviousPageItem = PageItem;
844                                                }
845                                                _ATLCATCHALL()
846                                                {
847                                                        _Z_EXCEPTION();
848                                                }
849                                        }
850                                        m_TreeView.Expand(FilterItem);
851                                }
852                                _ATLCATCHALL()
853                                {
854                                        _Z_EXCEPTION();
855                                }
856                                #pragma endregion
857                        }
858                        m_TreeView.Expand(FiltersItem);
859                        m_FiltersItem.m_hTreeItem = FiltersItem;
860                        m_FiltersItem.m_pTreeView = &m_TreeView;
861                        #pragma endregion
862                        CTreeItem ActionItem = m_TreeView.InsertItem(NULL, FiltersItem, CData(CData::TYPE_ACTION), _T("Action"));
863                        m_ActionItem.m_hTreeItem = ActionItem;
864                        m_ActionItem.m_pTreeView = &m_TreeView;
865                        CTreeItem EmailItem = m_TreeView.InsertItem(NULL, ActionItem, CData(CData::TYPE_EMAIL), _T("Email"));
866                        m_EmailItem.m_hTreeItem = EmailItem;
867                        m_EmailItem.m_pTreeView = &m_TreeView;
868                }
869                VOID HideCurrentSite()
870                {
871                        if(!m_pCurrentSite)
872                                return;
873                        if(m_pCurrentSite->m_pPropertyPage)
874                                __C(m_pCurrentSite->m_pPropertyPage->Show(SW_HIDE));
875                        m_pCurrentSite.Release();
876                }
877                VOID HandleStatusChange(CPropertyPageSite* pPropertyPageSite)
878                {
879                        _A(pPropertyPageSite);
880                        m_ApplyButton.EnableWindow(pPropertyPageSite->IsDirty());
881                }
882                VOID Apply()
883                {
884                        if(!m_pCurrentSite || !m_pCurrentSite->m_pPropertyPage)
885                                return;
886                        __C(m_pCurrentSite->m_pPropertyPage->Apply());
887                        HandleStatusChange(m_pCurrentSite);
888                }
889                INT_PTR DoModal(HWND hParentWindow = GetActiveWindow())
890                {
891                        return CDialogWithAccelerators::DoModal(hParentWindow);
892                }
893
894        // CDialogResize
895                VOID DlgResize_UpdateLayout(INT nWidth, INT nHeight)
896                {
897                        __super::DlgResize_UpdateLayout(nWidth, nHeight);
898                        const CRect Position = GetTextEditPosition();
899                        if(m_pCurrentSite && m_pCurrentSite->m_pPropertyPage)
900                                _V(m_pCurrentSite->m_pPropertyPage->Move(Position));
901                        _W(m_ActionDialog.SetWindowPos(NULL, Position, SWP_NOZORDER | SWP_NOACTIVATE));
902                        _W(m_EmailDialog.SetWindowPos(NULL, Position, SWP_NOZORDER | SWP_NOACTIVATE));
903                }
904
905        // Window Message Handler
906                LRESULT OnInitDialog(HWND, LPARAM)
907                {
908                        m_bActivating = TRUE;
909                        _ATLTRY
910                        {
911                                CWaitCursor WaitCursor;
912                                #pragma region Bitness Indication
913                                CString sCaption;
914                                _W(GetWindowText(sCaption));
915                                #if defined(_WIN64)
916                                        sCaption.Append(_T(" (64-bit)"));
917                                #else
918                                        if(SafeIsWow64Process())
919                                                sCaption.Append(_T(" (32-bit)"));
920                                #endif // defined(_WIN64)
921                                _W(SetWindowText(sCaption));
922                                #pragma endregion
923                                #pragma region System Menu
924                                CMenuHandle Menu = GetSystemMenu(FALSE);
925                                _W(Menu.AppendMenu(MF_SEPARATOR));
926                                _W(Menu.AppendMenu(MF_STRING, ID_APP_ABOUT, _T("&About...")));
927                                #pragma endregion
928                                #pragma region Icon
929                                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_COLOR, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)), TRUE);
930                                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_COLOR, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)), FALSE);
931                                #pragma endregion
932                                m_TreeView.Initialize(GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TREE));
933                                m_TextEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TEXT);
934                                CRect TextPosition;
935                                _W(m_TextEdit.GetWindowRect(TextPosition));
936                                _W(ScreenToClient(TextPosition));
937                                m_TextPosition = TextPosition;
938                                CLogFont TextFont;
939                                CFontHandle(AtlGetDefaultGuiFont()).GetLogFont(TextFont);
940                                _tcsncpy_s(TextFont.lfFaceName, _T("Courier New"), _TRUNCATE);
941                                TextFont.SetHeight(8);
942                                m_TextFont = TextFont.CreateFontIndirect();
943                                m_TextEdit.SetFont(m_TextFont);
944                                m_OkButton = GetDlgItem(IDOK);
945                                m_CancelButton = GetDlgItem(IDCANCEL);
946                                m_ApplyButton = GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_APPLY);
947                                __E(m_ActionDialog.Create(m_hWnd, (LPARAM) this));
948                                __E(m_EmailDialog.Create(m_hWnd, (LPARAM) this));
949                                DlgResize_Init(TRUE);
950                                UpdateTree();
951                                m_FiltersItem.Select();
952                                m_FiltersItem.EnsureVisible();
953                                CRect Position;
954                                _W(GetWindowRect(Position));
955                                Position.right += Position.Width() / 2;
956                                Position.bottom += Position.Width() / 4;
957                                _W(SetWindowPos(NULL, Position, SWP_NOMOVE | SWP_NOZORDER));
958                                _W(CenterWindow());
959                                m_bActivating = FALSE;
960                        }
961                        _ATLCATCH(Exception)
962                        {
963                                for(CWindow Window = GetWindow(GW_CHILD); Window; Window = Window.GetWindow(GW_HWNDNEXT))
964                                        Window.EnableWindow(FALSE);
965                                AtlExceptionMessageBox(m_hWnd, Exception);
966                        }
967                        return TRUE;
968                }
969                LRESULT OnDestroy()
970                {
971                        #pragma region Deactivate and Terminate Sites
972                        for(POSITION Position = m_TreeView.GetDataList().GetHeadPosition(); Position; m_TreeView.GetDataList().GetNext(Position))
973                        {
974                                CData& Data = m_TreeView.GetDataList().GetAt(Position);
975                                if(!Data.m_pSite)
976                                        continue;
977                                if(Data.m_bSiteActivated)
978                                {
979                                        const HRESULT nDeactivateResult = Data.m_pPropertyPage->Deactivate();
980                                        _Z35_DSHRESULT(nDeactivateResult);
981                                        Data.m_bSiteActivated = FALSE;
982                                }
983                                Data.m_pSite->Terminate();
984                        }
985                        #pragma endregion
986                        return 0;
987                }
988                LRESULT OnTreeViewSelChanged(NMTREEVIEW* pHeader)
989                {
990                        _A(pHeader);
991                        CTreeItem TreeItem(pHeader->itemNew.hItem);
992                        if(TreeItem)
993                        {
994                                CData& Data = m_TreeView.GetItemData(TreeItem);
995                                if(Data.m_Type != CData::TYPE_ACTION)
996                                        m_ActionDialog.ShowWindow(SW_HIDE);
997                                if(Data.m_Type != CData::TYPE_EMAIL)
998                                        m_EmailDialog.ShowWindow(SW_HIDE);
999                                if(Data.m_pBaseFilter)
1000                                {
1001                                        if(Data.m_pPropertyPage)
1002                                        {
1003                                                m_TextEdit.ShowWindow(SW_HIDE);
1004                                                if(Data.m_pSite != m_pCurrentSite)
1005                                                        HideCurrentSite();
1006                                                if(!Data.m_bSiteActivated)
1007                                                {
1008                                                        __C(Data.m_pPropertyPage->Activate(m_hWnd, GetTextEditPosition(), TRUE));
1009                                                        Data.m_bSiteActivated = TRUE;
1010                                                } else
1011                                                        __C(Data.m_pPropertyPage->Move(GetTextEditPosition()));
1012                                                __C(Data.m_pPropertyPage->Show(SW_SHOWNORMAL));
1013                                                m_pCurrentSite = Data.m_pSite;
1014                                                HandleStatusChange(m_pCurrentSite);
1015                                        } else
1016                                        {
1017                                                CWaitCursor WaitCursor;
1018                                                HideCurrentSite();
1019                                                m_TextEdit.ShowWindow(SW_SHOW);
1020                                                CString sText;
1021                                                sText += AtlFormatString(_T("## ") _T("Filter %ls") _T("\r\n") _T("\r\n"), _FilterGraphHelper::GetFilterName(Data.m_pBaseFilter));
1022                                                sText += m_Owner.GetFilterText(Data.m_pBaseFilter);
1023                                                sText += _T("\r\n");
1024                                                #pragma region Connection
1025                                                _FilterGraphHelper::CPinArray InputPinArray, OutputPinArray;
1026                                                _FilterGraphHelper::GetFilterPins(Data.m_pBaseFilter, PINDIR_INPUT, InputPinArray);
1027                                                _FilterGraphHelper::GetFilterPins(Data.m_pBaseFilter, PINDIR_OUTPUT, OutputPinArray);
1028                                                if(!InputPinArray.IsEmpty() || !OutputPinArray.IsEmpty())
1029                                                {
1030                                                        sText += AtlFormatString(_T("## ") _T("Connections") _T("\r\n") _T("\r\n"));
1031                                                        if(!InputPinArray.IsEmpty())
1032                                                        {
1033                                                                sText += AtlFormatString(_T("### ") _T("Input") _T("\r\n") _T("\r\n"));
1034                                                                for(SIZE_T nPinIndex = 0; nPinIndex < InputPinArray.GetCount(); nPinIndex++)
1035                                                                {
1036                                                                        const CComPtr<IPin>& pInputPin = InputPinArray[nPinIndex];
1037                                                                        const CComPtr<IPin> pOutputPin = _FilterGraphHelper::GetPeerPin(pInputPin);
1038                                                                        if(!pOutputPin)
1039                                                                                continue;
1040                                                                        sText += AtlFormatString(_T(" * ") _T("%s") _T("\r\n"), m_Owner.GetConnectionText(pOutputPin, pInputPin));
1041                                                                }
1042                                                                sText += _T("\r\n");
1043                                                        }
1044                                                        if(!OutputPinArray.IsEmpty())
1045                                                        {
1046                                                                sText += AtlFormatString(_T("### ") _T("Output") _T("\r\n") _T("\r\n"));
1047                                                                for(SIZE_T nPinIndex = 0; nPinIndex < OutputPinArray.GetCount(); nPinIndex++)
1048                                                                {
1049                                                                        const CComPtr<IPin>& pOutputPin = OutputPinArray[nPinIndex];
1050                                                                        const CComPtr<IPin> pInputPin = _FilterGraphHelper::GetPeerPin(pOutputPin);
1051                                                                        if(!pInputPin)
1052                                                                                continue;
1053                                                                        sText += AtlFormatString(_T(" * ") _T("%s") _T("\r\n"), m_Owner.GetConnectionText(pOutputPin, pInputPin));
1054                                                                }
1055                                                                sText += _T("\r\n");
1056                                                        }
1057                                                }
1058                                                #pragma endregion
1059                                                #pragma region Media Type
1060                                                _FilterGraphHelper::CPinArray PinArray;
1061                                                if(_FilterGraphHelper::GetFilterPins(Data.m_pBaseFilter, PinArray))
1062                                                {
1063                                                        sText += AtlFormatString(_T("## ") _T("Media Types") _T("\r\n") _T("\r\n"));
1064                                                        for(SIZE_T nPinIndex = 0; nPinIndex < PinArray.GetCount(); nPinIndex++)
1065                                                        {
1066                                                                const CComPtr<IPin>& pPin = PinArray[nPinIndex];
1067                                                                CString sPinText = AtlFormatString(_T("%s"), FormatIdentifier(_FilterGraphHelper::GetPinFullName(pPin)));
1068                                                                const CComPtr<IPin> pPeerPin = _FilterGraphHelper::GetPeerPin(pPin);
1069                                                                if(pPeerPin)
1070                                                                        sPinText += AtlFormatString(_T(", %s"), FormatIdentifier(_FilterGraphHelper::GetPinFullName(pPeerPin)));
1071                                                                sText += AtlFormatString(_T("%d. ") _T("%s") _T("\r\n"), 1 + nPinIndex, sPinText);
1072                                                                _ATLTRY
1073                                                                {
1074                                                                        CMediaType pMediaType;
1075                                                                        if(pPeerPin)
1076                                                                                pMediaType = _FilterGraphHelper::GetPinMediaType(pPin);
1077                                                                        else
1078                                                                                pMediaType = _FilterGraphHelper::EnumerateFirstPinMediaType(pPin);
1079                                                                        if(!pMediaType)
1080                                                                                continue;
1081                                                                        sText += m_Owner.GetMediaTypeText(pMediaType);
1082                                                                }
1083                                                                _ATLCATCHALL()
1084                                                                {
1085                                                                        _Z_EXCEPTION();
1086                                                                }
1087                                                        }
1088                                                        sText += _T("\r\n");
1089                                                }
1090                                                #pragma endregion
1091                                                m_TextEdit.SetValue(sText);
1092                                                m_ApplyButton.EnableWindow(FALSE);
1093                                        }
1094                                } else
1095                                {
1096                                        CWaitCursor WaitCursor;
1097                                        HideCurrentSite();
1098                                        switch(Data.m_Type)
1099                                        {
1100                                        #pragma region TYPE_ACTION
1101                                        case CData::TYPE_ACTION:
1102                                                m_TextEdit.ShowWindow(SW_HIDE);
1103                                                _W(m_ActionDialog.SetWindowPos(NULL, GetTextEditPosition(), SWP_NOZORDER | SWP_SHOWWINDOW));
1104                                                break;
1105                                        #pragma endregion
1106                                        #pragma region TYPE_EMAIL
1107                                        case CData::TYPE_EMAIL:
1108                                                m_TextEdit.ShowWindow(SW_HIDE);
1109                                                _W(m_EmailDialog.SetWindowPos(NULL, GetTextEditPosition(), SWP_NOZORDER | SWP_SHOWWINDOW));
1110                                                break;
1111                                        #pragma endregion
1112                                        default:
1113                                                m_TextEdit.ShowWindow(SW_SHOW);
1114                                                m_TextEdit.SetValue(m_Owner.GetText());
1115                                                m_ActionDialog.ShowWindow(SW_HIDE);
1116                                                m_EmailDialog.ShowWindow(SW_HIDE);
1117                                        }
1118                                        m_ApplyButton.EnableWindow(FALSE);
1119                                }
1120                        } else
1121                        {
1122                                HideCurrentSite();
1123                                m_TextEdit.ShowWindow(SW_HIDE);
1124                                m_ActionDialog.ShowWindow(SW_HIDE);
1125                                m_EmailDialog.ShowWindow(SW_HIDE);
1126                                m_ApplyButton.EnableWindow(FALSE);
1127                        }
1128                        return 0;
1129                }
1130                LRESULT OnTreeViewItemExplanding(NMTREEVIEW* pHeader)
1131                {
1132                        if(pHeader->action == TVE_COLLAPSE)
1133                                return TRUE; // Prevent Collapsing
1134                        return 0;
1135                }
1136                LRESULT OnTreeViewDblClk(NMHDR*)
1137                {
1138                        CTreeItem TreeItem = m_TreeView.GetSelectedItem();
1139                        if(!TreeItem)
1140                                return 0;
1141                        CData& Data = m_TreeView.GetItemData(TreeItem);
1142                        if(!Data.m_pBaseFilter)
1143                                return 0;
1144                        COlePropertyFrameDialog Dialog(Data.m_pBaseFilter);
1145                        if(!Dialog.SetObjectPages())
1146                                return 0;
1147                        Dialog.DoModal(m_hWnd);
1148                        return 0;
1149                }
1150                LRESULT OnSysCommand(UINT nCommand, CPoint)
1151                {
1152                        switch(nCommand)
1153                        {
1154                        case ID_APP_ABOUT:
1155                                {
1156                                        CAboutDialog Dialog;
1157                                        Dialog.DoModal(m_hWnd);
1158                                }
1159                                break;
1160                        default:
1161                                SetMsgHandled(FALSE);
1162                        }
1163                        return 0;
1164                }
1165                LRESULT OnOk(UINT, INT nIdentifier, HWND)
1166                {
1167                        _ATLTRY
1168                        {
1169                                #pragma region Apply All
1170                                for(POSITION Position = m_TreeView.GetDataList().GetHeadPosition(); Position; m_TreeView.GetDataList().GetNext(Position))
1171                                {
1172                                        CData& Data = m_TreeView.GetDataList().GetAt(Position);
1173                                        if(!Data.m_pSite)
1174                                                continue;
1175                                        _A(Data.m_pPropertyPage);
1176                                        if(Data.m_bSiteActivated && Data.m_pSite->IsDirty())
1177                                                __C(Data.m_pPropertyPage->Apply());
1178                                }
1179                                #pragma endregion
1180                        }
1181                        _ATLCATCH(Exception)
1182                        {
1183                                _Z_ATLEXCEPTION(Exception);
1184                                AtlMessageBoxEx(m_hWnd, (LPCTSTR) Ds::FormatResult(Exception), IDS_ERROR, MB_ICONERROR | MB_OK);
1185                                return 0;
1186                        }
1187                        EndDialog(nIdentifier);
1188                        return 0;
1189                }
1190                LRESULT OnCancel(UINT, INT nIdentifier, HWND)
1191                {
1192                        EndDialog(nIdentifier);
1193                        return 0;
1194                }
1195                LRESULT OnApply(UINT, INT, HWND)
1196                {
1197                        _ATLTRY
1198                        {
1199                                Apply();
1200                        }
1201                        _ATLCATCH(Exception)
1202                        {
1203                                _Z_ATLEXCEPTION(Exception);
1204                                AtlMessageBoxEx(m_hWnd, (LPCTSTR) Ds::FormatResult(Exception), IDS_ERROR, MB_ICONERROR | MB_OK);
1205                        }
1206                        return 0;
1207                }
1208                LRESULT OnActionCommand(UINT, INT nIdentifier, HWND)
1209                {
1210                        return m_ActionDialog.SendMessage(WM_COMMAND, nIdentifier);
1211                }
1212        };
1213
1214private:
1215        mutable CRoCriticalSection m_DataCriticalSection;
1216        CComPtr<IFilterGraph> m_pFilterGraph;
1217
1218public:
1219// CFilterGraphHelper
1220        static HRESULT WINAPI UpdateRegistry(BOOL bRegister)
1221        {
1222                _Z2(atlTraceRegistrar, 2, _T("bRegister %d\n"), bRegister);
1223                _ATLTRY
1224                {
1225                        UpdateRegistryFromResource<CFilterGraphHelper>(bRegister);
1226                }
1227                _ATLCATCH(Exception)
1228                {
1229                        _C(Exception);
1230                }
1231                return S_OK;
1232        }
1233        CFilterGraphHelper()
1234        {
1235                _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
1236        }
1237        ~CFilterGraphHelper()
1238        {
1239                _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
1240        }
1241        static CString FormatIdentifier(LPCSTR pszValue)
1242        {
1243                CString sText;
1244                if(pszValue && *pszValue)
1245                {
1246                        sText = _T("``");
1247                        sText.Insert(1, CString(pszValue));
1248                }
1249                return sText;
1250        }
1251        static CString FormatIdentifier(LPCWSTR pszValue)
1252        {
1253                CString sText;
1254                if(pszValue && *pszValue)
1255                {
1256                        sText = _T("``");
1257                        sText.Insert(1, CString(pszValue));
1258                }
1259                return sText;
1260        }
1261        static CString FormatIdentifier(LONG nValue)
1262        {
1263                CString sText;
1264                sText = _T("``");
1265                sText.Insert(1, _StringHelper::FormatNumber(nValue));
1266                return sText;
1267        }
1268        static CString FormatIdentifier(ULONG nValue)
1269        {
1270                return FormatIdentifier((LONG) nValue);
1271        }
1272        static CString FormatIdentifier(BOOL nValue)
1273        {
1274                return FormatIdentifier((LONG) nValue);
1275        }
1276        static CString FormatIdentifier(LONGLONG nValue)
1277        {
1278                CString sText;
1279                sText = _T("``");
1280                sText.Insert(1, _StringHelper::FormatNumber(nValue));
1281                return sText;
1282        }
1283        static CString FormatIdentifier(LONG nValue, LPCTSTR pszFormat)
1284        {
1285                CString sText;
1286                sText = _T("``");
1287                sText.Insert(1, AtlFormatString(pszFormat, nValue));
1288                return sText;
1289        }
1290        static CString FormatIdentifier(const VOID* pvValue, LPCTSTR pszFormat = _T("0x%p"))
1291        {
1292                CString sText;
1293                sText = _T("``");
1294                sText.Insert(1, AtlFormatString(pszFormat, pvValue));
1295                return sText;
1296        }
1297        #define I FormatIdentifier
1298        static CString FormatPhysicalConnectorType(PhysicalConnectorType Value)
1299        {
1300                struct 
1301                {
1302                        PhysicalConnectorType Value;
1303                        LPCSTR pszName;
1304                } g_pMap[] = 
1305                {
1306                        #define A(x) { x, #x },
1307                        A(PhysConn_Video_Tuner)
1308                        A(PhysConn_Video_Composite)
1309                        A(PhysConn_Video_SVideo)
1310                        A(PhysConn_Video_RGB)
1311                        A(PhysConn_Video_YRYBY)
1312                        A(PhysConn_Video_SerialDigital)
1313                        A(PhysConn_Video_ParallelDigital)
1314                        A(PhysConn_Video_SCSI)
1315                        A(PhysConn_Video_AUX)
1316                        A(PhysConn_Video_1394)
1317                        A(PhysConn_Video_USB)
1318                        A(PhysConn_Video_VideoDecoder)
1319                        A(PhysConn_Video_VideoEncoder)
1320                        A(PhysConn_Video_SCART)
1321                        A(PhysConn_Video_Black)
1322                        A(PhysConn_Audio_Tuner)
1323                        A(PhysConn_Audio_Line)
1324                        A(PhysConn_Audio_Mic)
1325                        A(PhysConn_Audio_AESDigital)
1326                        A(PhysConn_Audio_SPDIFDigital)
1327                        A(PhysConn_Audio_SCSI)
1328                        A(PhysConn_Audio_AUX)
1329                        A(PhysConn_Audio_1394)
1330                        A(PhysConn_Audio_USB)
1331                        A(PhysConn_Audio_AudioDecoder)
1332                        #undef A
1333                };
1334                for(SIZE_T nIndex = 0; nIndex < DIM(g_pMap); nIndex++)
1335                        if(g_pMap[nIndex].Value == Value)
1336                                return CString(g_pMap[nIndex].pszName);
1337                return AtlFormatString(_T("0x%04X"), Value);
1338        }
1339        static CString FormatPins(_FilterGraphHelper::CPinArray& PinArray)
1340        {
1341                CRoArrayT<CString> Array;
1342                for(SIZE_T nIndex  = 0; nIndex < PinArray.GetCount(); nIndex++)
1343                {
1344                        const CComPtr<IPin>& pPin = PinArray[nIndex];
1345                        CString sText = I(_FilterGraphHelper::GetPinName(pPin));
1346                        const CComPtr<IPin> pPeerPin = _FilterGraphHelper::GetPeerPin(pPin);
1347                        if(pPeerPin)
1348                                sText += AtlFormatString(_T(" (%s)"), I(_FilterGraphHelper::GetPinFullName(pPeerPin)));
1349                        Array.Add(sText);
1350                }
1351                return _StringHelper::Join(Array, _T(", "));
1352        }
1353        static CString GetFilterText(IBaseFilter* pBaseFilter, IReferenceClock* pFilterGraphReferenceClock = NULL)
1354        {
1355                CString sText;
1356                const CStringW sClassIdentifierString = _FilterGraphHelper::GetFilterClassIdentifierString(pBaseFilter);
1357                if(!sClassIdentifierString.IsEmpty())
1358                        sText += AtlFormatString(_T(" * ") _T("Class: %s %s") _T("\r\n"), I(sClassIdentifierString), I(_FilterGraphHelper::GetFilterClassDescription(pBaseFilter)));
1359                _FilterGraphHelper::CPinArray InputPinArray;
1360                if(_FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_INPUT, InputPinArray))
1361                        sText += AtlFormatString(_T(" * ") _T("Input Pins: %s") _T("\r\n"), FormatPins(InputPinArray));
1362                _FilterGraphHelper::CPinArray OutputPinArray;
1363                if(_FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_OUTPUT, OutputPinArray))
1364                        sText += AtlFormatString(_T(" * ") _T("Output Pins: %s") _T("\r\n"), FormatPins(OutputPinArray));
1365                #pragma region IReferenceClock
1366                const CComQIPtr<IReferenceClock> pReferenceClock = pBaseFilter;
1367                if(pReferenceClock)
1368                {
1369                        CRoArrayT<CString> Array;
1370                        Array.Add(I(_T("Available")));
1371                        if(pReferenceClock == pFilterGraphReferenceClock)
1372                                Array.Add(I(_T("Selected")));
1373                        sText += AtlFormatString(_T(" * ") _T("Reference Clock: %s") _T("\r\n"), _StringHelper::Join(Array, _T(", ")));
1374                }
1375                #pragma endregion
1376                #pragma region IFileSourceFilter
1377                const CComQIPtr<IFileSourceFilter> pFileSourceFilter = pBaseFilter;
1378                if(pFileSourceFilter)
1379                        _ATLTRY
1380                        {
1381                                CComHeapPtr<OLECHAR> pszFileName;
1382                                CMediaType pMediaType;
1383                                pMediaType.Allocate(MEDIATYPE_NULL, MEDIASUBTYPE_NULL);
1384                                const HRESULT nGetCurFileResult = pFileSourceFilter->GetCurFile(&pszFileName, pMediaType);
1385                                _Z45_DSHRESULT(nGetCurFileResult);
1386                                if(SUCCEEDED(nGetCurFileResult))
1387                                        sText += AtlFormatString(_T(" * ") _T("File Source: %s") _T("\r\n"), I(pszFileName));
1388                        }
1389                        _ATLCATCHALL()
1390                        {
1391                                _Z_EXCEPTION();
1392                        }
1393                #pragma endregion
1394                #pragma region IFileSinkFilter
1395                const CComQIPtr<IFileSinkFilter> pFileSinkFilter = pBaseFilter;
1396                if(pFileSinkFilter)
1397                        _ATLTRY
1398                        {
1399                                CComHeapPtr<OLECHAR> pszFileName;
1400                                CMediaType pMediaType;
1401                                pMediaType.Allocate(MEDIATYPE_NULL, MEDIASUBTYPE_NULL);
1402                                const HRESULT nGetCurFileResult = pFileSinkFilter->GetCurFile(&pszFileName, pMediaType);
1403                                _Z45_DSHRESULT(nGetCurFileResult);
1404                                if(SUCCEEDED(nGetCurFileResult))
1405                                        sText += AtlFormatString(_T(" * ") _T("File Sink: %s") _T("\r\n"), I(pszFileName));
1406                        }
1407                        _ATLCATCHALL()
1408                        {
1409                                _Z_EXCEPTION();
1410                        }
1411                #pragma endregion
1412                #pragma region IAMCrossbar
1413                const CComQIPtr<IAMCrossbar> pAmCrossbar = pBaseFilter;
1414                if(pAmCrossbar)
1415                        _ATLTRY
1416                        {
1417                                sText += AtlFormatString(_T(" * ") _T("Crossbar:") _T("\r\n"));
1418                                LONG nOutputPinCount = 0, nInputPinCount = 0;
1419                                __C(pAmCrossbar->get_PinCounts(&nOutputPinCount, &nInputPinCount));
1420                                sText += AtlFormatString(_T("  * ") _T("Pins: %s Input, %s Output") _T("\r\n"), I(nInputPinCount), I(nOutputPinCount));
1421                                #pragma region Input
1422                                for(LONG nInputPinIndex = 0; nInputPinIndex < nInputPinCount; nInputPinIndex++)
1423                                        _ATLTRY
1424                                        {
1425                                                CRoArrayT<CString> Array;
1426                                                LONG nRelatedPinIndex = -1;
1427                                                LONG nPhysicalType = 0; // PhysicalConnectorType
1428                                                __C(pAmCrossbar->get_CrossbarPinInfo(TRUE, nInputPinIndex, &nRelatedPinIndex, &nPhysicalType));
1429                                                if(nRelatedPinIndex >= 0)
1430                                                        Array.Add(AtlFormatString(_T("Related %s"), I(nRelatedPinIndex)));
1431                                                Array.Add(AtlFormatString(_T("Physical Type %s"), I(FormatPhysicalConnectorType((PhysicalConnectorType) nPhysicalType))));
1432                                                sText += AtlFormatString(_T("  * ") _T("Input Pin %s: %s") _T("\r\n"), I(nInputPinIndex), _StringHelper::Join(Array, _T("; ")));
1433                                        }
1434                                        _ATLCATCHALL()
1435                                        {
1436                                                _Z_EXCEPTION();
1437                                        }
1438                                #pragma endregion
1439                                #pragma region Output
1440                                for(LONG nOutputPinIndex = 0; nOutputPinIndex < nOutputPinCount; nOutputPinIndex++)
1441                                        _ATLTRY
1442                                        {
1443                                                CRoArrayT<CString> Array;
1444                                                LONG nRelatedPinIndex = -1;
1445                                                LONG nPhysicalType = 0; // PhysicalConnectorType
1446                                                __C(pAmCrossbar->get_CrossbarPinInfo(FALSE, nOutputPinIndex, &nRelatedPinIndex, &nPhysicalType));
1447                                                if(nRelatedPinIndex >= 0)
1448                                                        Array.Add(AtlFormatString(_T("Related %s"), I(nRelatedPinIndex)));
1449                                                if(nPhysicalType > 0)
1450                                                        Array.Add(AtlFormatString(_T("Physical Type %s"), I(FormatPhysicalConnectorType((PhysicalConnectorType) nPhysicalType))));
1451                                                LONG nRoutedInputPinIndex = -1;
1452                                                const HRESULT nGetIsRoutedToResult = pAmCrossbar->get_IsRoutedTo(nOutputPinIndex, &nRoutedInputPinIndex);
1453                                                _A(nGetIsRoutedToResult == S_OK || nRoutedInputPinIndex == -1);
1454                                                if(nRoutedInputPinIndex >= 0)
1455                                                        Array.Add(AtlFormatString(_T("Routed to Input Pin %s"), I(nRoutedInputPinIndex)));
1456                                                CRoArrayT<CString> PinArray;
1457                                                for(LONG nInputPinIndex = 0; nInputPinIndex < nInputPinCount; nInputPinIndex++)
1458                                                {
1459                                                        const HRESULT nCanRouteResult = pAmCrossbar->CanRoute(nOutputPinIndex, nInputPinIndex);
1460                                                        if(nCanRouteResult == S_OK)
1461                                                                PinArray.Add(I(nInputPinIndex));
1462                                                }
1463                                                if(!PinArray.IsEmpty())
1464                                                        Array.Add(AtlFormatString(_T("Routeable to Input Pins %s"), _StringHelper::Join(PinArray, _T(", "))));
1465                                                sText += AtlFormatString(_T("  * ") _T("Output Pin %s: %s") _T("\r\n"), I(nOutputPinIndex), _StringHelper::Join(Array, _T("; ")));
1466                                        }
1467                                        _ATLCATCHALL()
1468                                        {
1469                                                _Z_EXCEPTION();
1470                                        }
1471                                #pragma endregion
1472                        }
1473                        _ATLCATCHALL()
1474                        {
1475                                _Z_EXCEPTION();
1476                        }
1477                #pragma endregion
1478                return sText;
1479        }
1480        static CString GetConnectionText(IPin* pOutputPin, IPin* pInputPin)
1481        {
1482                _A(pOutputPin && pInputPin);
1483                CString sText = AtlFormatString(_T("%s - %s"), I(_FilterGraphHelper::GetPinFullName(pOutputPin)), I(_FilterGraphHelper::GetPinFullName(pInputPin)));
1484                _ATLTRY
1485                {
1486                        const CMediaType pMediaType = _FilterGraphHelper::GetPinMediaType(pOutputPin);
1487                        if(pMediaType)
1488                        {
1489                                CStringW sMajorType = _FilterGraphHelper::FormatMajorType(pMediaType->majortype);
1490                                CStringW sSubtype;
1491                                if(pMediaType->subtype != MEDIASUBTYPE_NULL)
1492                                        sSubtype = _FilterGraphHelper::FormatSubtype(pMediaType->majortype, pMediaType->subtype);
1493                                CRoArrayT<CString> Array;
1494                                Array.Add(I(sMajorType));
1495                                Array.Add(I(sSubtype));
1496                                #pragma region MEDIATYPE_Video
1497                                if(pMediaType->majortype == MEDIATYPE_Video)
1498                                {
1499                                        const CVideoInfoHeader2 VideoInfoHeader2 = pMediaType.GetCompatibleVideoInfoHeader2();
1500                                        const CSize Extent = VideoInfoHeader2.GetExtent();
1501                                        if(Extent.cx || Extent.cy)
1502                                                Array.Add(AtlFormatString(_T("%s x %s"), I(Extent.cx), I(Extent.cy)));
1503                                } else
1504                                #pragma endregion
1505                                #pragma region MEDIATYPE_Audio
1506                                if(pMediaType->majortype == MEDIATYPE_Audio)
1507                                {
1508                                        const CWaveFormatEx* pWaveFormatEx = pMediaType.GetWaveFormatEx();
1509                                        if(pWaveFormatEx)
1510                                        {
1511                                                if(pWaveFormatEx->nSamplesPerSec)
1512                                                        Array.Add(AtlFormatString(_T("%s Hz"), I(pWaveFormatEx->nSamplesPerSec)));
1513                                                if(pWaveFormatEx->nChannels)
1514                                                        Array.Add(AtlFormatString(_T("%s channels"), I(pWaveFormatEx->nChannels)));
1515                                                if(pWaveFormatEx->wBitsPerSample)
1516                                                        Array.Add(AtlFormatString(_T("%s bits"), I(pWaveFormatEx->wBitsPerSample)));
1517                                        }
1518                                }
1519                                #pragma endregion
1520                                sText += AtlFormatString(_T(" (%s)"), _StringHelper::Join(Array, _T(", ")));
1521                        }
1522                }
1523                _ATLCATCHALL()
1524                {
1525                        _Z_EXCEPTION();
1526                }
1527                return sText;
1528        }
1529        static CString GetMediaTypeText(const CMediaType& pMediaType)
1530        {
1531                CString sText;
1532                #pragma region AM_MEDIA_TYPE
1533                #define J(x) I(pMediaType->x)
1534                #define K1(x) sText += AtlFormatString(_T(" * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
1535                sText += AtlFormatString(_T(" * ") _T("Data: %s") _T("\r\n"), I(AtlFormatData((const BYTE*) (const AM_MEDIA_TYPE*) pMediaType, sizeof *pMediaType).TrimRight()));
1536                sText += AtlFormatString(_T(" * ") _T("`majortype`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatMajorType(pMediaType->majortype)));
1537                if(pMediaType->subtype != MEDIASUBTYPE_NULL)
1538                        sText += AtlFormatString(_T(" * ") _T("`subtype`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatSubtype(pMediaType->majortype, pMediaType->subtype)));
1539                K1(bFixedSizeSamples);
1540                K1(bTemporalCompression);
1541                K1(lSampleSize);
1542                if(pMediaType->formattype != GUID_NULL)
1543                        sText += AtlFormatString(_T(" * ") _T("`formattype`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatFormatType(pMediaType->formattype)));
1544                if(pMediaType->pUnk)
1545                        sText += AtlFormatString(_T(" * ") _T("`pUnk`: %s") _T("\r\n"), I(AtlFormatString(_T("0x%p"), pMediaType->pUnk)));
1546                if(pMediaType->cbFormat)
1547                {
1548                        K1(cbFormat);
1549                        if(pMediaType->pbFormat)
1550                                sText += AtlFormatString(_T(" * ") _T("Format Data, `pbFormat`: %s") _T("\r\n"), I(AtlFormatData(pMediaType->pbFormat, pMediaType->cbFormat).TrimRight()));
1551                }
1552                #undef J
1553                #undef K1
1554                #pragma endregion
1555                const BYTE* pnExtraData = NULL;
1556                SIZE_T nExtraDataSize = 0;
1557                #pragma region FORMAT_VideoInfo
1558                if(pMediaType->formattype == FORMAT_VideoInfo)
1559                {
1560                        sText += AtlFormatString(_T(" * ") _T("As `VIDEOINFOHEADER`:") _T("\r\n"));
1561                        const VIDEOINFOHEADER* pVideoInfoHeader = (const VIDEOINFOHEADER*) pMediaType->pbFormat;
1562                        #define J(x) I(pVideoInfoHeader->x)
1563                        #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
1564                        sText += AtlFormatString(_T("  * ") _T("`rcSource`: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcSource.left), J(rcSource.top), J(rcSource.right), J(rcSource.bottom));
1565                        sText += AtlFormatString(_T("  * ") _T("`rcTarget`: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcTarget.left), J(rcTarget.top), J(rcTarget.right), J(rcTarget.bottom));
1566                        K1(dwBitRate);
1567                        K1(dwBitErrorRate);
1568                        sText += AtlFormatString(_T("  * ") _T("`AvgTimePerFrame`: %s units") _T("\r\n"), I(_FilterGraphHelper::FormatReferenceTime(pVideoInfoHeader->AvgTimePerFrame)));
1569                        K1(bmiHeader.biSize);
1570                        K1(bmiHeader.biWidth);
1571                        K1(bmiHeader.biHeight);
1572                        K1(bmiHeader.biPlanes);
1573                        K1(bmiHeader.biBitCount);
1574                        sText += AtlFormatString(_T("  * ") _T("`bmiHeader.biCompression`: %s") _T("\r\n"), I(_FilterGraphHelper::GetFourccCodeString(pVideoInfoHeader->bmiHeader.biCompression)));
1575                        K1(bmiHeader.biSizeImage);
1576                        K1(bmiHeader.biXPelsPerMeter);
1577                        K1(bmiHeader.biYPelsPerMeter);
1578                        K1(bmiHeader.biClrUsed);
1579                        K1(bmiHeader.biClrImportant);
1580                        #undef J
1581                        #undef K1
1582                        nExtraDataSize = pMediaType->cbFormat - sizeof *pVideoInfoHeader;
1583                } else
1584                #pragma endregion
1585                #pragma region FORMAT_VideoInfo2
1586                if(pMediaType->formattype == FORMAT_VideoInfo2)
1587                {
1588                        sText += AtlFormatString(_T(" * ") _T("As `VIDEOINFOHEADER2`:") _T("\r\n"));
1589                        const VIDEOINFOHEADER2* pVideoInfoHeader2 = (const VIDEOINFOHEADER2*) pMediaType->pbFormat;
1590                        #define J(x) I(pVideoInfoHeader2->x)
1591                        #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
1592                        #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pVideoInfoHeader2->x, y))
1593                        sText += AtlFormatString(_T("  * ") _T("rcSource: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcSource.left), J(rcSource.top), J(rcSource.right), J(rcSource.bottom));
1594                        sText += AtlFormatString(_T("  * ") _T("rcTarget: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcTarget.left), J(rcTarget.top), J(rcTarget.right), J(rcTarget.bottom));
1595                        K1(dwBitRate);
1596                        K1(dwBitErrorRate);
1597                        sText += AtlFormatString(_T("  * ") _T("`AvgTimePerFrame`: %s units") _T("\r\n"), I(_FilterGraphHelper::FormatReferenceTime(pVideoInfoHeader2->AvgTimePerFrame)));
1598                        K2(dwInterlaceFlags, _T("0x%X"));
1599                        K2(dwCopyProtectFlags, _T("0x%X"));
1600                        K1(dwPictAspectRatioX);
1601                        K1(dwPictAspectRatioY);
1602                        K2(dwControlFlags, _T("0x%X"));
1603                        K1(bmiHeader.biSize);
1604                        K1(bmiHeader.biWidth);
1605                        K1(bmiHeader.biHeight);
1606                        K1(bmiHeader.biPlanes);
1607                        K1(bmiHeader.biBitCount);
1608                        sText += AtlFormatString(_T("  * ") _T("`bmiHeader.biCompression`: %s") _T("\r\n"), I(_FilterGraphHelper::GetFourccCodeString(pVideoInfoHeader2->bmiHeader.biCompression)));
1609                        K1(bmiHeader.biSizeImage);
1610                        K1(bmiHeader.biXPelsPerMeter);
1611                        K1(bmiHeader.biYPelsPerMeter);
1612                        K1(bmiHeader.biClrUsed);
1613                        K1(bmiHeader.biClrImportant);
1614                        #undef J
1615                        #undef K1
1616                        #undef K2
1617                        nExtraDataSize = pMediaType->cbFormat - sizeof *pVideoInfoHeader2;
1618                        if(nExtraDataSize)
1619                        {
1620                                sText += AtlFormatString(_T("  * ") _T("Extra Data: (%d bytes)") _T("\r\n"), nExtraDataSize);
1621                                nExtraDataSize = 0;
1622                        }
1623                } else
1624                #pragma endregion
1625                #pragma region FORMAT_MPEG2Video
1626                if(pMediaType->formattype == FORMAT_MPEG2Video)
1627                {
1628                        sText += AtlFormatString(_T(" * ") _T("As `MPEG2VIDEOINFO`:") _T("\r\n"));
1629                        const MPEG2VIDEOINFO* pMpeg2VideoInfo = (const MPEG2VIDEOINFO*) pMediaType->pbFormat;
1630                        #define J(x) I(pMpeg2VideoInfo->x)
1631                        #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
1632                        #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pMpeg2VideoInfo->x, y))
1633                        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));
1634                        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));
1635                        K1(hdr.dwBitRate);
1636                        K1(hdr.dwBitErrorRate);
1637                        sText += AtlFormatString(_T("  * ") _T("`hdr.AvgTimePerFrame`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatReferenceTime(pMpeg2VideoInfo->hdr.AvgTimePerFrame)));
1638                        K2(hdr.dwInterlaceFlags, _T("0x%X"));
1639                        K2(hdr.dwCopyProtectFlags, _T("0x%X"));
1640                        K1(hdr.dwPictAspectRatioX);
1641                        K1(hdr.dwPictAspectRatioY);
1642                        K2(hdr.dwControlFlags, _T("0x%X"));
1643                        K1(hdr.bmiHeader.biSize);
1644                        K1(hdr.bmiHeader.biWidth);
1645                        K1(hdr.bmiHeader.biHeight);
1646                        K1(hdr.bmiHeader.biPlanes);
1647                        K1(hdr.bmiHeader.biBitCount);
1648                        sText += AtlFormatString(_T("  * ") _T("`hdr.bmiHeader.biCompression`: %s") _T("\r\n"), I(_FilterGraphHelper::GetFourccCodeString(pMpeg2VideoInfo->hdr.bmiHeader.biCompression)));
1649                        K1(hdr.bmiHeader.biSizeImage);
1650                        K1(hdr.bmiHeader.biXPelsPerMeter);
1651                        K1(hdr.bmiHeader.biYPelsPerMeter);
1652                        K1(hdr.bmiHeader.biClrUsed);
1653                        K1(hdr.bmiHeader.biClrImportant);
1654                        K2(dwStartTimeCode, _T("0x%08X"));
1655                        K1(cbSequenceHeader);
1656                        K1(dwProfile);
1657                        K1(dwLevel);
1658                        K2(dwFlags, _T("0x%08X"));
1659                        #undef J
1660                        #undef K1
1661                        #undef K2
1662                        #undef J
1663                        nExtraDataSize = pMediaType->cbFormat - (sizeof *pMpeg2VideoInfo - sizeof pMpeg2VideoInfo->dwSequenceHeader);
1664                } else
1665                #pragma endregion
1666                #pragma region FORMAT_WaveFormatEx
1667                if(pMediaType->formattype == FORMAT_WaveFormatEx)
1668                {
1669                        const WAVEFORMATEX* pWaveFormatEx = (const WAVEFORMATEX*) pMediaType->pbFormat;
1670                        if(pWaveFormatEx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
1671                        {
1672                                const WAVEFORMATEXTENSIBLE* pWaveFormatExtensible = (const WAVEFORMATEXTENSIBLE*) pMediaType->pbFormat;
1673                                #define J(x) I(pWaveFormatExtensible->x)
1674                                #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
1675                                #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pWaveFormatExtensible->x, y))
1676                                sText += AtlFormatString(_T(" * ") _T("As `WAVEFORMATEXTENSIBLE`:") _T("\r\n"));
1677                                K2(Format.wFormatTag, _T("0x%02X"));
1678                                K1(Format.nChannels);
1679                                K1(Format.nSamplesPerSec);
1680                                K1(Format.nAvgBytesPerSec);
1681                                K1(Format.nBlockAlign);
1682                                K1(Format.wBitsPerSample);
1683                                K1(Format.cbSize);
1684                                K1(Samples.wValidBitsPerSample);
1685                                K2(dwChannelMask, _T("0x%02X"));
1686                                sText += AtlFormatString(_T("  * ") _T("`SubFormat`: %s") _T("\r\n"), I(_PersistHelper::StringFromIdentifier(pWaveFormatExtensible->SubFormat)));
1687                                #undef J
1688                                #undef K1
1689                                #undef K2
1690                                nExtraDataSize = pWaveFormatEx->cbSize - (sizeof *pWaveFormatExtensible - sizeof *pWaveFormatEx);
1691                        } else
1692                        {
1693                                #define J(x) I(pWaveFormatEx->x)
1694                                #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
1695                                #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pWaveFormatEx->x, y))
1696                                K2(wFormatTag, _T("0x%02X"));
1697                                K1(nChannels);
1698                                K1(nSamplesPerSec);
1699                                K1(nAvgBytesPerSec);
1700                                K1(nBlockAlign);
1701                                K1(wBitsPerSample);
1702                                K1(cbSize);
1703                                #undef J
1704                                #undef K1
1705                                #undef K2
1706                                nExtraDataSize = pWaveFormatEx->cbSize;
1707                        }
1708                }
1709                #pragma endregion
1710                #pragma region Extra Data
1711                if(nExtraDataSize)
1712                {
1713                        if(!pnExtraData)
1714                                pnExtraData = pMediaType->pbFormat + pMediaType->cbFormat - nExtraDataSize;
1715                        sText += AtlFormatString(_T("  * ") _T("Extra Data: %s") _T("\r\n"), I(AtlFormatData(pnExtraData, nExtraDataSize).TrimRight()));
1716                }
1717                #pragma endregion
1718                return sText;
1719        }
1720        static CString GetText(IFilterGraph* pFilterGraph, const CProcessData* pProcessData = NULL)
1721        {
1722                if(!pFilterGraph)
1723                        return (LPCTSTR) NULL;
1724                CString sText;
1725                sText += AtlFormatString(_T("# ") _T("Filter Graph") _T("\r\n") _T("\r\n"));
1726                #pragma region Graph Parameters
1727                if(pProcessData)
1728                        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)));
1729                #pragma region IMediaControl
1730                const CComQIPtr<IMediaControl> pMediaControl = pFilterGraph;
1731                if(pMediaControl)
1732                        _ATLTRY
1733                        {
1734                                OAFilterState State;
1735                                const HRESULT nGetStateResult = pMediaControl->GetState(0, &State);
1736                                _Z45_DSHRESULT(nGetStateResult);
1737                                static const LPCTSTR g_ppszStates[] = { _T("Stopped"), _T("Paused"), _T("Running"), };
1738                                if(SUCCEEDED(nGetStateResult) && (SIZE_T) State < DIM(g_ppszStates))
1739                                        sText += AtlFormatString(_T("* ") _T("State: %s") _T("\r\n"), I(g_ppszStates[(SIZE_T) State]));
1740                        }
1741                        _ATLCATCHALL()
1742                        {
1743                                _Z_EXCEPTION();
1744                        }
1745                #pragma endregion
1746                #pragma region IMediaPosition
1747                const CComQIPtr<IMediaPosition> pMediaPosition = pFilterGraph;
1748                if(pMediaPosition)
1749                        _ATLTRY
1750                        {
1751                                DOUBLE fDuration = 0, fPosition = 0;
1752                                const HRESULT nGetDurationResult = pMediaPosition->get_Duration(&fDuration);
1753                                _Z45_DSHRESULT(nGetDurationResult);
1754                                if(fDuration > 0)
1755                                {
1756                                        sText += AtlFormatString(_T("* ") _T("Duration: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime(fDuration)), I(_StringHelper::FormatNumber(fDuration, 3)));
1757                                        const HRESULT nCurrentPositionResult = pMediaPosition->get_CurrentPosition(&fPosition);
1758                                        _Z45_DSHRESULT(nCurrentPositionResult);
1759                                        if(SUCCEEDED(nCurrentPositionResult))
1760                                                sText += AtlFormatString(_T("* ") _T("Position: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime(fPosition)), I(_StringHelper::FormatNumber(fPosition, 3)));
1761                                }
1762                        }
1763                        _ATLCATCHALL()
1764                        {
1765                                _Z_EXCEPTION();
1766                        }
1767                #pragma endregion
1768                if(pProcessData)
1769                {
1770                        if(!pProcessData->m_sDisplayName.IsEmpty())
1771                                sText += AtlFormatString(_T("* ") _T("Display Name: %s") _T("\r\n"), I(pProcessData->m_sDisplayName));
1772                        const CString sDirectory = (LPCTSTR) GetPathDirectory(pProcessData->m_sImagePath);
1773                        if(!sDirectory.IsEmpty())
1774                                sText += AtlFormatString(_T("* ") _T("Process Directory: %s") _T("\r\n"), I(sDirectory));
1775                }
1776                const CComQIPtr<IMediaFilter> pMediaFilter = pFilterGraph;
1777                CComPtr<IReferenceClock> pFilterGraphReferenceClock;
1778                const HRESULT nGetSyncSourceResult = pMediaFilter->GetSyncSource(&pFilterGraphReferenceClock);
1779                _Z45_DSHRESULT(nGetSyncSourceResult);
1780                sText += _T("\r\n");
1781                #pragma endregion
1782                #pragma region Filter
1783                _FilterGraphHelper::CFilterArray FilterArray;
1784                _FilterGraphHelper::GetGraphFilters(pFilterGraph, FilterArray);
1785                if(!FilterArray.IsEmpty())
1786                {
1787                        sText += AtlFormatString(_T("## ") _T("Filters") _T("\r\n") _T("\r\n"));
1788                        for(SIZE_T nIndex = 0; nIndex < FilterArray.GetCount(); nIndex++)
1789                                _ATLTRY
1790                                {
1791                                        const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nIndex];
1792                                        sText += AtlFormatString(_T("%d. ") _T("%ls") _T("\r\n"), nIndex + 1, _FilterGraphHelper::GetFilterName(pBaseFilter));
1793                                        sText += GetFilterText(pBaseFilter, pFilterGraphReferenceClock);
1794                                }
1795                                _ATLCATCHALL()
1796                                {
1797                                        _Z_EXCEPTION();
1798                                }
1799                        sText += _T("\r\n");
1800                        #pragma region Connection
1801                        sText += AtlFormatString(_T("## ") _T("Connections") _T("\r\n") _T("\r\n"));
1802                        INT nConnectionIndex = 0;
1803                        for(SIZE_T nFilterIndex = 0; nFilterIndex < FilterArray.GetCount(); nFilterIndex++)
1804                        {
1805                                const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nFilterIndex];
1806                                _FilterGraphHelper::CPinArray PinArray;
1807                                _FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_OUTPUT, PinArray);
1808                                for(SIZE_T nPinIndex = 0; nPinIndex < PinArray.GetCount(); nPinIndex++)
1809                                {
1810                                        const CComPtr<IPin>& pOutputPin = PinArray[nPinIndex];
1811                                        const CComPtr<IPin> pInputPin = _FilterGraphHelper::GetPeerPin(pOutputPin);
1812                                        if(!pInputPin)
1813                                                continue;
1814                                        sText += AtlFormatString(_T("%d. ") _T("%s") _T("\r\n"), ++nConnectionIndex, GetConnectionText(pOutputPin, pInputPin));
1815                                }
1816                        }
1817                        sText += _T("\r\n");
1818                        #pragma endregion
1819                        #pragma region Media Type
1820                        sText += AtlFormatString(_T("## ") _T("Media Types") _T("\r\n") _T("\r\n"));
1821                        INT nGlobalPinIndex = 0;
1822                        CRoListT<CComPtr<IPin>> PinList;
1823                        for(SIZE_T nFilterIndex = 0; nFilterIndex < FilterArray.GetCount(); nFilterIndex++)
1824                        {
1825                                const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nFilterIndex];
1826                                _FilterGraphHelper::CPinArray PinArray;
1827                                _FilterGraphHelper::GetFilterPins(pBaseFilter, PinArray);
1828                                for(SIZE_T nPinIndex = 0; nPinIndex < PinArray.GetCount(); nPinIndex++)
1829                                {
1830                                        const CComPtr<IPin>& pPin = PinArray[nPinIndex];
1831                                        if(PinList.FindFirst(pPin))
1832                                                continue;
1833                                        PinList.AddTail(pPin);
1834                                        CString sPinText = AtlFormatString(_T("%s"), I(_FilterGraphHelper::GetPinFullName(pPin)));
1835                                        const CComPtr<IPin> pPeerPin = _FilterGraphHelper::GetPeerPin(pPin);
1836                                        if(pPeerPin)
1837                                        {
1838                                                PinList.AddTail(pPeerPin);
1839                                                sPinText += AtlFormatString(_T(", %s"), I(_FilterGraphHelper::GetPinFullName(pPeerPin)));
1840                                        }
1841                                        sText += AtlFormatString(_T("%d. ") _T("%s") _T("\r\n"), ++nGlobalPinIndex, sPinText);
1842                                        _ATLTRY
1843                                        {
1844                                                CMediaType pMediaType;
1845                                                if(pPeerPin)
1846                                                        pMediaType = _FilterGraphHelper::GetPinMediaType(pPin);
1847                                                else
1848                                                        pMediaType = _FilterGraphHelper::EnumerateFirstPinMediaType(pPin);
1849                                                if(!pMediaType)
1850                                                        continue;
1851                                                sText += GetMediaTypeText(pMediaType);
1852                                        }
1853                                        _ATLCATCHALL()
1854                                        {
1855                                                _Z_EXCEPTION();
1856                                        }
1857                                }
1858                        }
1859                        sText += _T("\r\n");
1860                        #pragma endregion
1861                }
1862                #pragma endregion
1863                return sText;
1864        }
1865        #undef I
1866        CComPtr<IFilterGraph> GetFilterGraph() const
1867        {
1868                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1869                return m_pFilterGraph;
1870        }
1871        VOID SetFilterGraph(IFilterGraph* pFilterGraph) 
1872        {
1873                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1874                m_pFilterGraph = pFilterGraph;
1875        }
1876        BOOL SetFilterGraph(IUnknown* pFilterGraphUnknown) 
1877        {
1878                CComQIPtr<IFilterGraph> pFilterGraph;
1879                if(pFilterGraphUnknown)
1880                {
1881                        pFilterGraph = pFilterGraphUnknown;
1882                        if(!pFilterGraph)
1883                        {
1884                                const CComQIPtr<IBaseFilter> pBaseFilter = pFilterGraphUnknown;
1885                                if(!pBaseFilter)
1886                                {
1887                                        const CComQIPtr<IPin> pPin = pFilterGraphUnknown;
1888                                        if(pPin)
1889                                                pFilterGraph = _FilterGraphHelper::GetFilterGraph(_FilterGraphHelper::GetPinFilter(pPin));
1890                                } else
1891                                        pFilterGraph = _FilterGraphHelper::GetFilterGraph(pBaseFilter);
1892                        }
1893                }
1894                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1895                m_pFilterGraph = pFilterGraph;
1896                return m_pFilterGraph != NULL;
1897        }
1898        CString GetText() const
1899        {
1900                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1901                return GetText(m_pFilterGraph);
1902        }
1903        static LPCTSTR GetPlatformName()
1904        {
1905                #if defined(_WIN64)
1906                        return _T("x64");
1907                #else
1908                        return _T("Win32");
1909                #endif // defined(_WIN64)
1910        }
1911        template <SIZE_T t_nItemCount>
1912        static CString& GetLegacyFilter(const COMDLG_FILTERSPEC (&pItems)[t_nItemCount], CString& sFilter)
1913        {
1914                _A(sFilter.IsEmpty());
1915                for(SIZE_T nIndex = 0; nIndex < t_nItemCount; nIndex++)
1916                {
1917                        const COMDLG_FILTERSPEC& Item = pItems[nIndex];
1918                        sFilter += AtlFormatString(_T("%s (%s)|%s|"), Item.pszName, Item.pszSpec, Item.pszSpec);
1919                }
1920                sFilter.Replace(_T('|'), 0);
1921                return sFilter;
1922        }
1923        static BOOL OpenMonikerWithGsn(LPCWSTR pszMonikerDisplayName, HWND hParentWindow = GetActiveWindow())
1924        {
1925                _A(pszMonikerDisplayName);
1926                static const LPCTSTR g_pszValueName = _T("GraphStudioNext Path");
1927                static const LPCTSTR g_pszFileName = _T("graphstudionext.exe");
1928                const CString sValueName = AtlFormatString(_T("%s (%s)"), g_pszValueName, GetPlatformName());
1929                CString sPath = _RegKeyHelper::QueryStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, sValueName);
1930                if(!FileExists(sPath))
1931                        sPath.Empty();
1932                #pragma region Current Directory
1933                if(sPath.IsEmpty())
1934                {
1935                        sPath = (LPCTSTR) Combine(GetPathDirectory(GetModulePath()), g_pszFileName);
1936                        if(!FileExists(sPath))
1937                                sPath.Empty();
1938                }
1939                #pragma endregion
1940                #pragma region Application Registry
1941                if(sPath.IsEmpty())
1942                {
1943                        #if defined(_WIN64)
1944                                static const LPCTSTR g_pszValueName = _T("exeLocation64");
1945                        #else
1946                                static const LPCTSTR g_pszValueName = _T("exeLocation");
1947                        #endif // defined(_WIN64)
1948                        sPath = _RegKeyHelper::QueryStringValue(HKEY_CURRENT_USER, _T("Software\\MONOGRAM\\GraphStudioNext"), g_pszValueName);
1949                        if(!FileExists(sPath))
1950                                sPath.Empty();
1951                }
1952                #pragma endregion
1953                if(sPath.IsEmpty())
1954                {
1955                        #pragma region Prompt
1956                        static const COMDLG_FILTERSPEC g_pFilter[] = 
1957                        {
1958                                { _T("Executable Files"), _T("*.exe") },
1959                                { _T("All Files"), _T("*.*") },
1960                        };
1961                        if(GetOsVersion() >= GetWinVistaOsVersion())
1962                        {
1963                                CShellFileOpenDialog Dialog(g_pszFileName, FOS_FORCEFILESYSTEM | FOS_FILEMUSTEXIST, _T("exe"), g_pFilter, DIM(g_pFilter));
1964                                if(Dialog.DoModal(hParentWindow) != IDOK)
1965                                        return FALSE;
1966                                __C(Dialog.GetFilePath(sPath));
1967                        } else
1968                        {
1969                                CString sFilter;
1970                                CFileDialog Dialog(TRUE, _T("exe"), NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_ENABLESIZING, GetLegacyFilter(g_pFilter, sFilter));
1971                                if(Dialog.DoModal(hParentWindow) != IDOK)
1972                                        return FALSE;
1973                                sPath = Dialog.m_szFileName;
1974                        }
1975                        #pragma endregion
1976                        _RegKeyHelper::SetStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, sValueName, sPath);
1977                }
1978                CWaitCursor WaitCursor;
1979                CString sParameters = AtlFormatString(_T("-a \"%ls\""), pszMonikerDisplayName);
1980                SHELLEXECUTEINFO Infomation;
1981                ZeroMemory(&Infomation, sizeof Infomation);
1982                Infomation.cbSize = sizeof Infomation;
1983                Infomation.lpFile = sPath;
1984                Infomation.lpParameters = sParameters;
1985                Infomation.nShow = SW_SHOWNORMAL;
1986                __E(ShellExecuteEx(&Infomation));
1987                return TRUE;
1988        }
1989        static BOOL OpenMonikerWithGe(LPCWSTR pszMonikerDisplayName, HWND hParentWindow = GetActiveWindow())
1990        {
1991                static const LPCTSTR g_pszValueName = _T("GraphEdit Path");
1992                static const LPCTSTR g_pszFileName = _T("graphedt.exe");
1993                const CString sValueName = AtlFormatString(_T("%s (%s)"), g_pszValueName, GetPlatformName());
1994                CString sPath = _RegKeyHelper::QueryStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, sValueName);
1995                if(!FileExists(sPath))
1996                        sPath.Empty();
1997                #pragma region Current Directory
1998                if(sPath.IsEmpty())
1999                {
2000                        sPath = (LPCTSTR) Combine(GetPathDirectory(GetModulePath()), g_pszFileName);
2001                        if(!FileExists(sPath))
2002                                sPath.Empty();
2003                }
2004                #pragma endregion
2005                // SUGG: Look for Windows SDK
2006                if(sPath.IsEmpty())
2007                {
2008                        #pragma region Prompt
2009                        static const COMDLG_FILTERSPEC g_pFilter[] = 
2010                        {
2011                                { _T("Executable Files"), _T("*.exe") },
2012                                { _T("All Files"), _T("*.*") },
2013                        };
2014                        if(GetOsVersion() >= GetWinVistaOsVersion())
2015                        {
2016                                CShellFileOpenDialog Dialog(g_pszFileName, FOS_FORCEFILESYSTEM | FOS_FILEMUSTEXIST, _T("exe"), g_pFilter, DIM(g_pFilter));
2017                                if(Dialog.DoModal(hParentWindow) != IDOK)
2018                                        return FALSE;
2019                                __C(Dialog.GetFilePath(sPath));
2020                        } else
2021                        {
2022                                CString sFilter;
2023                                CFileDialog Dialog(TRUE, _T("exe"), NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_ENABLESIZING, GetLegacyFilter(g_pFilter, sFilter));
2024                                if(Dialog.DoModal(hParentWindow) != IDOK)
2025                                        return FALSE;
2026                                sPath = Dialog.m_szFileName;
2027                        }
2028                        #pragma endregion
2029                        _RegKeyHelper::SetStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, sValueName, sPath);
2030                }
2031                CStringW sFilterGraphMonikerDisplayName = pszMonikerDisplayName;
2032                const INT nSeparatorPosition = sFilterGraphMonikerDisplayName.Find(L';');
2033                if(nSeparatorPosition >= 0)
2034                        sFilterGraphMonikerDisplayName = sFilterGraphMonikerDisplayName.Left(nSeparatorPosition);
2035                CWaitCursor WaitCursor;
2036                CString sParameters = AtlFormatString(_T("-a %ls"), sFilterGraphMonikerDisplayName);
2037                SHELLEXECUTEINFO Infomation;
2038                ZeroMemory(&Infomation, sizeof Infomation);
2039                Infomation.cbSize = sizeof Infomation;
2040                Infomation.lpFile = sPath;
2041                Infomation.lpParameters = sParameters;
2042                Infomation.nShow = SW_SHOWNORMAL;
2043                __E(ShellExecuteEx(&Infomation));
2044                return TRUE;
2045        }
2046
2047// IFilterGraphHelper
2048        STDMETHOD(get_FilterGraph)(IUnknown** ppFilterGraphUnknown)
2049        {
2050                _Z4(atlTraceCOM, 4, _T("...\n"));
2051                _ATLTRY
2052                {
2053                        __D(ppFilterGraphUnknown, E_POINTER);
2054                        *ppFilterGraphUnknown = GetFilterGraph().Detach();
2055                }
2056                _ATLCATCH(Exception)
2057                {
2058                        _C(Exception);
2059                }
2060                return S_OK;
2061        }
2062        STDMETHOD(put_FilterGraph)(IUnknown* pFilterGraphUnknown)
2063        {
2064                _Z4(atlTraceCOM, 4, _T("pFilterGraphUnknown 0x%p\n"), pFilterGraphUnknown);
2065                _ATLTRY
2066                {
2067                        if(!SetFilterGraph(pFilterGraphUnknown))
2068                                return S_FALSE;
2069                }
2070                _ATLCATCH(Exception)
2071                {
2072                        _C(Exception);
2073                }
2074                return S_OK;
2075        }
2076        STDMETHOD(get_Text)(BSTR* psText)
2077        {
2078                _Z4(atlTraceCOM, 4, _T("...\n"));
2079                _ATLTRY
2080                {
2081                        __D(psText, E_POINTER);
2082                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
2083                        *psText = CComBSTR(GetText(m_pFilterGraph)).Detach();
2084                }
2085                _ATLCATCH(Exception)
2086                {
2087                        _C(Exception);
2088                }
2089                return S_OK;
2090        }
2091        STDMETHOD(DoPropertyFrameModal)(LONG nParentWindowHandle)
2092        {
2093                _Z4(atlTraceCOM, 4, _T("...\n"));
2094                _ATLTRY
2095                {
2096                        CWindow ParentWindow = (HWND) (LONG_PTR) nParentWindowHandle;
2097                        if(!ParentWindow)
2098                                ParentWindow = GetActiveWindow();
2099                        __D(!ParentWindow || ParentWindow.IsWindow(), E_INVALIDARG);
2100                        const CComQIPtr<IFilterGraph2> pFilterGraph2 = GetFilterGraph();
2101                        __D(pFilterGraph2, E_NOINTERFACE);
2102                        CPropertyFrameDialog PropertyFrameDialog(this);
2103                        PropertyFrameDialog.DoModal(ParentWindow);
2104                }
2105                _ATLCATCH(Exception)
2106                {
2107                        _C(Exception);
2108                }
2109                return S_OK;
2110        }
2111};
2112
2113OBJECT_ENTRY_AUTO(__uuidof(FilterGraphHelper), CFilterGraphHelper)
Note: See TracBrowser for help on using the repository browser.