source: trunk/DirectShowSpy/FilterGraphHelper.h @ 240

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