source: trunk/DirectShowSpy/FilterGraphHelper.h @ 238

Last change on this file since 238 was 238, checked in by roman, 9 years ago

Cosmetic

File size: 63.0 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);
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                        if(m_pCurrentSite && m_pCurrentSite->m_pPropertyPage)
728                                _V(m_pCurrentSite->m_pPropertyPage->Move(GetTextEditPosition()));
729                }
730
731        // Window Message Handler
732                LRESULT OnInitDialog(HWND, LPARAM)
733                {
734                        m_bActivating = TRUE;
735                        _ATLTRY
736                        {
737                                CWaitCursor WaitCursor;
738                                #pragma region Bitness Indication
739                                CString sCaption;
740                                _W(GetWindowText(sCaption));
741                                #if defined(_WIN64)
742                                        sCaption.Append(_T(" (64-bit)"));
743                                #else
744                                        if(SafeIsWow64Process())
745                                                sCaption.Append(_T(" (32-bit)"));
746                                #endif // defined(_WIN64)
747                                _W(SetWindowText(sCaption));
748                                #pragma endregion
749                                #pragma region System Menu
750                                CMenuHandle Menu = GetSystemMenu(FALSE);
751                                _W(Menu.AppendMenu(MF_SEPARATOR));
752                                _W(Menu.AppendMenu(MF_STRING, ID_APP_ABOUT, _T("&About...")));
753                                #pragma endregion
754                                m_TreeView.Initialize(GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TREE));
755                                m_TextEdit = GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_TEXT);
756                                CRect TextPosition;
757                                _W(m_TextEdit.GetWindowRect(TextPosition));
758                                _W(ScreenToClient(TextPosition));
759                                m_TextPosition = TextPosition;
760                                CLogFont TextFont;
761                                CFontHandle(AtlGetDefaultGuiFont()).GetLogFont(TextFont);
762                                _tcsncpy_s(TextFont.lfFaceName, _T("Courier New"), _TRUNCATE);
763                                TextFont.SetHeight(8);
764                                m_TextFont = TextFont.CreateFontIndirect();
765                                m_TextEdit.SetFont(m_TextFont);
766                                m_OkButton = GetDlgItem(IDOK);
767                                m_CancelButton = GetDlgItem(IDCANCEL);
768                                m_ApplyButton = GetDlgItem(IDC_FILTERGRAPHHELPER_PROPERTYFRAME_APPLY);
769                                __E(m_EmailDialog.Create(m_hWnd, (LPARAM) this));
770                                DlgResize_Init(TRUE);
771                                UpdateTree();
772                                m_FiltersItem.Select();
773                                m_FiltersItem.EnsureVisible();
774                                CRect Position;
775                                _W(GetWindowRect(Position));
776                                Position.right += Position.Width() / 2;
777                                Position.bottom += Position.Width() / 4;
778                                _W(SetWindowPos(NULL, Position, SWP_NOMOVE | SWP_NOZORDER));
779                                _W(CenterWindow());
780                                m_bActivating = FALSE;
781                        }
782                        _ATLCATCH(Exception)
783                        {
784                                for(CWindow Window = GetWindow(GW_CHILD); Window; Window = Window.GetWindow(GW_HWNDNEXT))
785                                        Window.EnableWindow(FALSE);
786                                AtlExceptionMessageBox(m_hWnd, Exception);
787                        }
788                        return TRUE;
789                }
790                LRESULT OnDestroy()
791                {
792                        #pragma region Deactivate and Terminate Sites
793                        for(POSITION Position = m_TreeView.GetDataList().GetHeadPosition(); Position; m_TreeView.GetDataList().GetNext(Position))
794                        {
795                                CData& Data = m_TreeView.GetDataList().GetAt(Position);
796                                if(!Data.m_pSite)
797                                        continue;
798                                if(Data.m_bSiteActivated)
799                                {
800                                        const HRESULT nDeactivateResult = Data.m_pPropertyPage->Deactivate();
801                                        _Z35_DSHRESULT(nDeactivateResult);
802                                        Data.m_bSiteActivated = FALSE;
803                                }
804                                Data.m_pSite->Terminate();
805                        }
806                        #pragma endregion
807                        return 0;
808                }
809                LRESULT OnTreeViewSelChanged(NMTREEVIEW* pHeader)
810                {
811                        _A(pHeader);
812                        CTreeItem TreeItem(pHeader->itemNew.hItem);
813                        if(TreeItem)
814                        {
815                                CData& Data = m_TreeView.GetItemData(TreeItem);
816                                if(Data.m_Type != CData::TYPE_EMAIL)
817                                        m_EmailDialog.ShowWindow(SW_HIDE);
818                                #pragma endregion
819                                if(Data.m_pBaseFilter)
820                                {
821                                        if(Data.m_pPropertyPage)
822                                        {
823                                                m_TextEdit.ShowWindow(SW_HIDE);
824                                                if(Data.m_pSite != m_pCurrentSite)
825                                                        HideCurrentSite();
826                                                if(!Data.m_bSiteActivated)
827                                                {
828                                                        __C(Data.m_pPropertyPage->Activate(m_hWnd, GetTextEditPosition(), TRUE));
829                                                        Data.m_bSiteActivated = TRUE;
830                                                } else
831                                                        __C(Data.m_pPropertyPage->Move(GetTextEditPosition()));
832                                                __C(Data.m_pPropertyPage->Show(SW_SHOWNORMAL));
833                                                m_pCurrentSite = Data.m_pSite;
834                                                HandleStatusChange(m_pCurrentSite);
835                                        } else
836                                        {
837                                                CWaitCursor WaitCursor;
838                                                HideCurrentSite();
839                                                m_TextEdit.ShowWindow(SW_SHOW);
840                                                CString sText;
841                                                sText += AtlFormatString(_T("## ") _T("Filter %ls") _T("\r\n") _T("\r\n"), _FilterGraphHelper::GetFilterName(Data.m_pBaseFilter));
842                                                sText += m_Owner.GetFilterText(Data.m_pBaseFilter);
843                                                sText += _T("\r\n");
844                                                #pragma region Connection
845                                                _FilterGraphHelper::CPinArray InputPinArray, OutputPinArray;
846                                                _FilterGraphHelper::GetFilterPins(Data.m_pBaseFilter, PINDIR_INPUT, InputPinArray);
847                                                _FilterGraphHelper::GetFilterPins(Data.m_pBaseFilter, PINDIR_OUTPUT, OutputPinArray);
848                                                if(!InputPinArray.IsEmpty() || !OutputPinArray.IsEmpty())
849                                                {
850                                                        sText += AtlFormatString(_T("## ") _T("Connections") _T("\r\n") _T("\r\n"));
851                                                        if(!InputPinArray.IsEmpty())
852                                                        {
853                                                                sText += AtlFormatString(_T("### ") _T("Input") _T("\r\n") _T("\r\n"));
854                                                                for(SIZE_T nPinIndex = 0; nPinIndex < InputPinArray.GetCount(); nPinIndex++)
855                                                                {
856                                                                        const CComPtr<IPin>& pInputPin = InputPinArray[nPinIndex];
857                                                                        const CComPtr<IPin> pOutputPin = _FilterGraphHelper::GetPeerPin(pInputPin);
858                                                                        if(!pOutputPin)
859                                                                                continue;
860                                                                        sText += AtlFormatString(_T(" * ") _T("%s") _T("\r\n"), m_Owner.GetConnectionText(pOutputPin, pInputPin));
861                                                                }
862                                                                sText += _T("\r\n");
863                                                        }
864                                                        if(!OutputPinArray.IsEmpty())
865                                                        {
866                                                                sText += AtlFormatString(_T("### ") _T("Output") _T("\r\n") _T("\r\n"));
867                                                                for(SIZE_T nPinIndex = 0; nPinIndex < OutputPinArray.GetCount(); nPinIndex++)
868                                                                {
869                                                                        const CComPtr<IPin>& pOutputPin = OutputPinArray[nPinIndex];
870                                                                        const CComPtr<IPin> pInputPin = _FilterGraphHelper::GetPeerPin(pOutputPin);
871                                                                        if(!pInputPin)
872                                                                                continue;
873                                                                        sText += AtlFormatString(_T(" * ") _T("%s") _T("\r\n"), m_Owner.GetConnectionText(pOutputPin, pInputPin));
874                                                                }
875                                                                sText += _T("\r\n");
876                                                        }
877                                                }
878                                                #pragma endregion
879                                                #pragma region Media Type
880                                                _FilterGraphHelper::CPinArray PinArray;
881                                                if(_FilterGraphHelper::GetFilterPins(Data.m_pBaseFilter, PinArray))
882                                                {
883                                                        sText += AtlFormatString(_T("## ") _T("Media Types") _T("\r\n") _T("\r\n"));
884                                                        for(SIZE_T nPinIndex = 0; nPinIndex < PinArray.GetCount(); nPinIndex++)
885                                                        {
886                                                                const CComPtr<IPin>& pPin = PinArray[nPinIndex];
887                                                                CString sPinText = AtlFormatString(_T("%s"), FormatIdentifier(_FilterGraphHelper::GetPinFullName(pPin)));
888                                                                const CComPtr<IPin> pPeerPin = _FilterGraphHelper::GetPeerPin(pPin);
889                                                                if(pPeerPin)
890                                                                        sPinText += AtlFormatString(_T(", %s"), FormatIdentifier(_FilterGraphHelper::GetPinFullName(pPeerPin)));
891                                                                sText += AtlFormatString(_T("%d. ") _T("%s") _T("\r\n"), 1 + nPinIndex, sPinText);
892                                                                _ATLTRY
893                                                                {
894                                                                        CMediaType pMediaType;
895                                                                        if(pPeerPin)
896                                                                                pMediaType = _FilterGraphHelper::GetPinMediaType(pPin);
897                                                                        else
898                                                                                pMediaType = _FilterGraphHelper::EnumerateFirstPinMediaType(pPin);
899                                                                        if(!pMediaType)
900                                                                                continue;
901                                                                        sText += m_Owner.GetMediaTypeText(pMediaType);
902                                                                }
903                                                                _ATLCATCHALL()
904                                                                {
905                                                                        _Z_EXCEPTION();
906                                                                }
907                                                        }
908                                                        sText += _T("\r\n");
909                                                }
910                                                #pragma endregion
911                                                m_TextEdit.SetValue(sText);
912                                                m_ApplyButton.EnableWindow(FALSE);
913                                        }
914                                } else
915                                {
916                                        CWaitCursor WaitCursor;
917                                        HideCurrentSite();
918                                        switch(Data.m_Type)
919                                        {
920                                        #pragma region TYPE_EMAIL
921                                        case CData::TYPE_EMAIL:
922                                                m_TextEdit.ShowWindow(SW_HIDE);
923                                                _W(m_EmailDialog.SetWindowPos(NULL, GetTextEditPosition(), SWP_NOZORDER | SWP_SHOWWINDOW));
924                                                break;
925                                        #pragma endregion
926                                        default:
927                                                m_TextEdit.ShowWindow(SW_SHOW);
928                                                m_TextEdit.SetValue(m_Owner.GetText());
929                                                m_EmailDialog.ShowWindow(SW_HIDE);
930                                        }
931                                        m_ApplyButton.EnableWindow(FALSE);
932                                }
933                        } else
934                        {
935                                HideCurrentSite();
936                                m_TextEdit.ShowWindow(SW_HIDE);
937                                m_EmailDialog.ShowWindow(SW_HIDE);
938                                m_ApplyButton.EnableWindow(FALSE);
939                        }
940                        return 0;
941                }
942                LRESULT OnTreeViewItemExplanding(NMTREEVIEW* pHeader)
943                {
944                        if(pHeader->action == TVE_COLLAPSE)
945                                return TRUE; // Prevent Collapsing
946                        return 0;
947                }
948                LRESULT OnTreeViewDblClk(NMHDR*)
949                {
950                        CTreeItem TreeItem = m_TreeView.GetSelectedItem();
951                        if(!TreeItem)
952                                return 0;
953                        CData& Data = m_TreeView.GetItemData(TreeItem);
954                        if(!Data.m_pBaseFilter)
955                                return 0;
956                        COlePropertyFrameDialog Dialog(Data.m_pBaseFilter);
957                        if(!Dialog.SetObjectPages())
958                                return 0;
959                        Dialog.DoModal(m_hWnd);
960                        return 0;
961                }
962                LRESULT OnSysCommand(UINT nCommand, CPoint)
963                {
964                        switch(nCommand)
965                        {
966                        case ID_APP_ABOUT:
967                                {
968                                        CAboutDialog Dialog;
969                                        Dialog.DoModal(m_hWnd);
970                                }
971                                break;
972                        default:
973                                SetMsgHandled(FALSE);
974                        }
975                        return 0;
976                }
977                LRESULT OnOk(UINT, INT nIdentifier, HWND)
978                {
979                        _ATLTRY
980                        {
981                                #pragma region Apply All
982                                for(POSITION Position = m_TreeView.GetDataList().GetHeadPosition(); Position; m_TreeView.GetDataList().GetNext(Position))
983                                {
984                                        CData& Data = m_TreeView.GetDataList().GetAt(Position);
985                                        if(!Data.m_pSite)
986                                                continue;
987                                        _A(Data.m_pPropertyPage);
988                                        if(Data.m_bSiteActivated && Data.m_pSite->IsDirty())
989                                                __C(Data.m_pPropertyPage->Apply());
990                                }
991                                #pragma endregion
992                        }
993                        _ATLCATCH(Exception)
994                        {
995                                _Z_ATLEXCEPTION(Exception);
996                                AtlMessageBoxEx(m_hWnd, (LPCTSTR) Ds::FormatResult(Exception), IDS_ERROR, MB_ICONERROR | MB_OK);
997                                return 0;
998                        }
999                        EndDialog(nIdentifier);
1000                        return 0;
1001                }
1002                LRESULT OnCancel(UINT, INT nIdentifier, HWND)
1003                {
1004                        EndDialog(nIdentifier);
1005                        return 0;
1006                }
1007                LRESULT OnApply(UINT, INT, HWND)
1008                {
1009                        _ATLTRY
1010                        {
1011                                Apply();
1012                        }
1013                        _ATLCATCH(Exception)
1014                        {
1015                                _Z_ATLEXCEPTION(Exception);
1016                                AtlMessageBoxEx(m_hWnd, (LPCTSTR) Ds::FormatResult(Exception), IDS_ERROR, MB_ICONERROR | MB_OK);
1017                        }
1018                        return 0;
1019                }
1020        };
1021
1022private:
1023        mutable CRoCriticalSection m_DataCriticalSection;
1024        CComPtr<IFilterGraph> m_pFilterGraph;
1025
1026public:
1027// CFilterGraphHelper
1028        static HRESULT WINAPI UpdateRegistry(BOOL bRegister)
1029        {
1030                _Z2(atlTraceRegistrar, 2, _T("bRegister %d\n"), bRegister);
1031                _ATLTRY
1032                {
1033                        UpdateRegistryFromResource<CFilterGraphHelper>(bRegister);
1034                }
1035                _ATLCATCH(Exception)
1036                {
1037                        _C(Exception);
1038                }
1039                return S_OK;
1040        }
1041        CFilterGraphHelper()
1042        {
1043                _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
1044        }
1045        ~CFilterGraphHelper()
1046        {
1047                _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
1048        }
1049        static CString FormatIdentifier(LPCSTR pszValue)
1050        {
1051                CString sText;
1052                if(pszValue && *pszValue)
1053                {
1054                        sText = _T("``");
1055                        sText.Insert(1, CString(pszValue));
1056                }
1057                return sText;
1058        }
1059        static CString FormatIdentifier(LPCWSTR pszValue)
1060        {
1061                CString sText;
1062                if(pszValue && *pszValue)
1063                {
1064                        sText = _T("``");
1065                        sText.Insert(1, CString(pszValue));
1066                }
1067                return sText;
1068        }
1069        static CString FormatIdentifier(LONG nValue)
1070        {
1071                CString sText;
1072                sText = _T("``");
1073                sText.Insert(1, _StringHelper::FormatNumber(nValue));
1074                return sText;
1075        }
1076        static CString FormatIdentifier(ULONG nValue)
1077        {
1078                return FormatIdentifier((LONG) nValue);
1079        }
1080        static CString FormatIdentifier(BOOL nValue)
1081        {
1082                return FormatIdentifier((LONG) nValue);
1083        }
1084        static CString FormatIdentifier(LONGLONG nValue)
1085        {
1086                CString sText;
1087                sText = _T("``");
1088                sText.Insert(1, _StringHelper::FormatNumber(nValue));
1089                return sText;
1090        }
1091        static CString FormatIdentifier(LONG nValue, LPCTSTR pszFormat)
1092        {
1093                CString sText;
1094                sText = _T("``");
1095                sText.Insert(1, AtlFormatString(pszFormat, nValue));
1096                return sText;
1097        }
1098        static CString FormatIdentifier(const VOID* pvValue, LPCTSTR pszFormat = _T("0x%p"))
1099        {
1100                CString sText;
1101                sText = _T("``");
1102                sText.Insert(1, AtlFormatString(pszFormat, pvValue));
1103                return sText;
1104        }
1105        #define I FormatIdentifier
1106        static CString FormatPhysicalConnectorType(PhysicalConnectorType Value)
1107        {
1108                struct 
1109                {
1110                        PhysicalConnectorType Value;
1111                        LPCSTR pszName;
1112                } g_pMap[] = 
1113                {
1114                        #define A(x) { x, #x },
1115                        A(PhysConn_Video_Tuner)
1116                        A(PhysConn_Video_Composite)
1117                        A(PhysConn_Video_SVideo)
1118                        A(PhysConn_Video_RGB)
1119                        A(PhysConn_Video_YRYBY)
1120                        A(PhysConn_Video_SerialDigital)
1121                        A(PhysConn_Video_ParallelDigital)
1122                        A(PhysConn_Video_SCSI)
1123                        A(PhysConn_Video_AUX)
1124                        A(PhysConn_Video_1394)
1125                        A(PhysConn_Video_USB)
1126                        A(PhysConn_Video_VideoDecoder)
1127                        A(PhysConn_Video_VideoEncoder)
1128                        A(PhysConn_Video_SCART)
1129                        A(PhysConn_Video_Black)
1130                        A(PhysConn_Audio_Tuner)
1131                        A(PhysConn_Audio_Line)
1132                        A(PhysConn_Audio_Mic)
1133                        A(PhysConn_Audio_AESDigital)
1134                        A(PhysConn_Audio_SPDIFDigital)
1135                        A(PhysConn_Audio_SCSI)
1136                        A(PhysConn_Audio_AUX)
1137                        A(PhysConn_Audio_1394)
1138                        A(PhysConn_Audio_USB)
1139                        A(PhysConn_Audio_AudioDecoder)
1140                        #undef A
1141                };
1142                for(SIZE_T nIndex = 0; nIndex < DIM(g_pMap); nIndex++)
1143                        if(g_pMap[nIndex].Value == Value)
1144                                return CString(g_pMap[nIndex].pszName);
1145                return AtlFormatString(_T("0x%04X"), Value);
1146        }
1147        static CString FormatPins(_FilterGraphHelper::CPinArray& PinArray)
1148        {
1149                CRoArrayT<CString> Array;
1150                for(SIZE_T nIndex  = 0; nIndex < PinArray.GetCount(); nIndex++)
1151                {
1152                        const CComPtr<IPin>& pPin = PinArray[nIndex];
1153                        CString sText = I(_FilterGraphHelper::GetPinName(pPin));
1154                        const CComPtr<IPin> pPeerPin = _FilterGraphHelper::GetPeerPin(pPin);
1155                        if(pPeerPin)
1156                                sText += AtlFormatString(_T(" (%s)"), I(_FilterGraphHelper::GetPinFullName(pPeerPin)));
1157                        Array.Add(sText);
1158                }
1159                return _StringHelper::Join(Array, _T(", "));
1160        }
1161        static CString GetFilterText(IBaseFilter* pBaseFilter, IReferenceClock* pFilterGraphReferenceClock = NULL)
1162        {
1163                CString sText;
1164                const CStringW sClassIdentifierString = _FilterGraphHelper::GetFilterClassIdentifierString(pBaseFilter);
1165                if(!sClassIdentifierString.IsEmpty())
1166                        sText += AtlFormatString(_T(" * ") _T("Class: %s %s") _T("\r\n"), I(sClassIdentifierString), I(_FilterGraphHelper::GetFilterClassDescription(pBaseFilter)));
1167                _FilterGraphHelper::CPinArray InputPinArray;
1168                if(_FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_INPUT, InputPinArray))
1169                        sText += AtlFormatString(_T(" * ") _T("Input Pins: %s") _T("\r\n"), FormatPins(InputPinArray));
1170                _FilterGraphHelper::CPinArray OutputPinArray;
1171                if(_FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_OUTPUT, OutputPinArray))
1172                        sText += AtlFormatString(_T(" * ") _T("Output Pins: %s") _T("\r\n"), FormatPins(OutputPinArray));
1173                #pragma region IReferenceClock
1174                const CComQIPtr<IReferenceClock> pReferenceClock = pBaseFilter;
1175                if(pReferenceClock)
1176                {
1177                        CRoArrayT<CString> Array;
1178                        Array.Add(I(_T("Available")));
1179                        if(pReferenceClock == pFilterGraphReferenceClock)
1180                                Array.Add(I(_T("Selected")));
1181                        sText += AtlFormatString(_T(" * ") _T("Reference Clock: %s") _T("\r\n"), _StringHelper::Join(Array, _T(", ")));
1182                }
1183                #pragma endregion
1184                #pragma region IFileSourceFilter
1185                const CComQIPtr<IFileSourceFilter> pFileSourceFilter = pBaseFilter;
1186                if(pFileSourceFilter)
1187                        _ATLTRY
1188                        {
1189                                CComHeapPtr<OLECHAR> pszFileName;
1190                                CMediaType pMediaType;
1191                                pMediaType.Allocate(MEDIATYPE_NULL, MEDIASUBTYPE_NULL);
1192                                const HRESULT nGetCurFileResult = pFileSourceFilter->GetCurFile(&pszFileName, pMediaType);
1193                                _Z45_DSHRESULT(nGetCurFileResult);
1194                                if(SUCCEEDED(nGetCurFileResult))
1195                                        sText += AtlFormatString(_T(" * ") _T("File Source: %s") _T("\r\n"), I(pszFileName));
1196                        }
1197                        _ATLCATCHALL()
1198                        {
1199                                _Z_EXCEPTION();
1200                        }
1201                #pragma endregion
1202                #pragma region IFileSinkFilter
1203                const CComQIPtr<IFileSinkFilter> pFileSinkFilter = pBaseFilter;
1204                if(pFileSinkFilter)
1205                        _ATLTRY
1206                        {
1207                                CComHeapPtr<OLECHAR> pszFileName;
1208                                CMediaType pMediaType;
1209                                pMediaType.Allocate(MEDIATYPE_NULL, MEDIASUBTYPE_NULL);
1210                                const HRESULT nGetCurFileResult = pFileSinkFilter->GetCurFile(&pszFileName, pMediaType);
1211                                _Z45_DSHRESULT(nGetCurFileResult);
1212                                if(SUCCEEDED(nGetCurFileResult))
1213                                        sText += AtlFormatString(_T(" * ") _T("File Sink: %s") _T("\r\n"), I(pszFileName));
1214                        }
1215                        _ATLCATCHALL()
1216                        {
1217                                _Z_EXCEPTION();
1218                        }
1219                #pragma endregion
1220                #pragma region IAMCrossbar
1221                const CComQIPtr<IAMCrossbar> pAmCrossbar = pBaseFilter;
1222                if(pAmCrossbar)
1223                        _ATLTRY
1224                        {
1225                                sText += AtlFormatString(_T(" * ") _T("Crossbar:") _T("\r\n"));
1226                                LONG nOutputPinCount = 0, nInputPinCount = 0;
1227                                __C(pAmCrossbar->get_PinCounts(&nOutputPinCount, &nInputPinCount));
1228                                sText += AtlFormatString(_T("  * ") _T("Pins: %s Input, %s Output") _T("\r\n"), I(nInputPinCount), I(nOutputPinCount));
1229                                #pragma region Input
1230                                for(LONG nInputPinIndex = 0; nInputPinIndex < nInputPinCount; nInputPinIndex++)
1231                                        _ATLTRY
1232                                        {
1233                                                CRoArrayT<CString> Array;
1234                                                LONG nRelatedPinIndex = -1;
1235                                                LONG nPhysicalType = 0; // PhysicalConnectorType
1236                                                __C(pAmCrossbar->get_CrossbarPinInfo(TRUE, nInputPinIndex, &nRelatedPinIndex, &nPhysicalType));
1237                                                if(nRelatedPinIndex >= 0)
1238                                                        Array.Add(AtlFormatString(_T("Related %s"), I(nRelatedPinIndex)));
1239                                                Array.Add(AtlFormatString(_T("Physical Type %s"), I(FormatPhysicalConnectorType((PhysicalConnectorType) nPhysicalType))));
1240                                                sText += AtlFormatString(_T("  * ") _T("Input Pin %s: %s") _T("\r\n"), I(nInputPinIndex), _StringHelper::Join(Array, _T("; ")));
1241                                        }
1242                                        _ATLCATCHALL()
1243                                        {
1244                                                _Z_EXCEPTION();
1245                                        }
1246                                #pragma endregion
1247                                #pragma region Output
1248                                for(LONG nOutputPinIndex = 0; nOutputPinIndex < nOutputPinCount; nOutputPinIndex++)
1249                                        _ATLTRY
1250                                        {
1251                                                CRoArrayT<CString> Array;
1252                                                LONG nRelatedPinIndex = -1;
1253                                                LONG nPhysicalType = 0; // PhysicalConnectorType
1254                                                __C(pAmCrossbar->get_CrossbarPinInfo(FALSE, nOutputPinIndex, &nRelatedPinIndex, &nPhysicalType));
1255                                                if(nRelatedPinIndex >= 0)
1256                                                        Array.Add(AtlFormatString(_T("Related %s"), I(nRelatedPinIndex)));
1257                                                if(nPhysicalType > 0)
1258                                                        Array.Add(AtlFormatString(_T("Physical Type %s"), I(FormatPhysicalConnectorType((PhysicalConnectorType) nPhysicalType))));
1259                                                LONG nRoutedInputPinIndex = -1;
1260                                                const HRESULT nGetIsRoutedToResult = pAmCrossbar->get_IsRoutedTo(nOutputPinIndex, &nRoutedInputPinIndex);
1261                                                _A(nGetIsRoutedToResult == S_OK || nRoutedInputPinIndex == -1);
1262                                                if(nRoutedInputPinIndex >= 0)
1263                                                        Array.Add(AtlFormatString(_T("Routed to Input Pin %s"), I(nRoutedInputPinIndex)));
1264                                                CRoArrayT<CString> PinArray;
1265                                                for(LONG nInputPinIndex = 0; nInputPinIndex < nInputPinCount; nInputPinIndex++)
1266                                                {
1267                                                        const HRESULT nCanRouteResult = pAmCrossbar->CanRoute(nOutputPinIndex, nInputPinIndex);
1268                                                        if(nCanRouteResult == S_OK)
1269                                                                PinArray.Add(I(nInputPinIndex));
1270                                                }
1271                                                if(!PinArray.IsEmpty())
1272                                                        Array.Add(AtlFormatString(_T("Routeable to Input Pins %s"), _StringHelper::Join(PinArray, _T(", "))));
1273                                                sText += AtlFormatString(_T("  * ") _T("Output Pin %s: %s") _T("\r\n"), I(nOutputPinIndex), _StringHelper::Join(Array, _T("; ")));
1274                                        }
1275                                        _ATLCATCHALL()
1276                                        {
1277                                                _Z_EXCEPTION();
1278                                        }
1279                                #pragma endregion
1280                        }
1281                        _ATLCATCHALL()
1282                        {
1283                                _Z_EXCEPTION();
1284                        }
1285                #pragma endregion
1286                return sText;
1287        }
1288        static CString GetConnectionText(IPin* pOutputPin, IPin* pInputPin)
1289        {
1290                _A(pOutputPin && pInputPin);
1291                CString sText = AtlFormatString(_T("%s - %s"), I(_FilterGraphHelper::GetPinFullName(pOutputPin)), I(_FilterGraphHelper::GetPinFullName(pInputPin)));
1292                _ATLTRY
1293                {
1294                        const CMediaType pMediaType = _FilterGraphHelper::GetPinMediaType(pOutputPin);
1295                        if(pMediaType)
1296                        {
1297                                CStringW sMajorType = _FilterGraphHelper::FormatMajorType(pMediaType->majortype);
1298                                CStringW sSubtype;
1299                                if(pMediaType->subtype != MEDIASUBTYPE_NULL)
1300                                        sSubtype = _FilterGraphHelper::FormatSubtype(pMediaType->majortype, pMediaType->subtype);
1301                                CRoArrayT<CString> Array;
1302                                Array.Add(I(sMajorType));
1303                                Array.Add(I(sSubtype));
1304                                #pragma region MEDIATYPE_Video
1305                                if(pMediaType->majortype == MEDIATYPE_Video)
1306                                {
1307                                        const CVideoInfoHeader2 VideoInfoHeader2 = pMediaType.GetCompatibleVideoInfoHeader2();
1308                                        const CSize Extent = VideoInfoHeader2.GetExtent();
1309                                        if(Extent.cx || Extent.cy)
1310                                                Array.Add(AtlFormatString(_T("%s x %s"), I(Extent.cx), I(Extent.cy)));
1311                                } else
1312                                #pragma endregion
1313                                #pragma region MEDIATYPE_Audio
1314                                if(pMediaType->majortype == MEDIATYPE_Audio)
1315                                {
1316                                        const CWaveFormatEx* pWaveFormatEx = pMediaType.GetWaveFormatEx();
1317                                        if(pWaveFormatEx)
1318                                        {
1319                                                if(pWaveFormatEx->nSamplesPerSec)
1320                                                        Array.Add(AtlFormatString(_T("%s Hz"), I(pWaveFormatEx->nSamplesPerSec)));
1321                                                if(pWaveFormatEx->nChannels)
1322                                                        Array.Add(AtlFormatString(_T("%s channels"), I(pWaveFormatEx->nChannels)));
1323                                                if(pWaveFormatEx->wBitsPerSample)
1324                                                        Array.Add(AtlFormatString(_T("%s bits"), I(pWaveFormatEx->wBitsPerSample)));
1325                                        }
1326                                }
1327                                #pragma endregion
1328                                sText += AtlFormatString(_T(" (%s)"), _StringHelper::Join(Array, _T(", ")));
1329                        }
1330                }
1331                _ATLCATCHALL()
1332                {
1333                        _Z_EXCEPTION();
1334                }
1335                return sText;
1336        }
1337        static CString GetMediaTypeText(const CMediaType& pMediaType)
1338        {
1339                CString sText;
1340                #pragma region AM_MEDIA_TYPE
1341                #define J(x) I(pMediaType->x)
1342                #define K1(x) sText += AtlFormatString(_T(" * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
1343                sText += AtlFormatString(_T(" * ") _T("Data: %s") _T("\r\n"), I(AtlFormatData((const BYTE*) (const AM_MEDIA_TYPE*) pMediaType, sizeof *pMediaType).TrimRight()));
1344                sText += AtlFormatString(_T(" * ") _T("`majortype`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatMajorType(pMediaType->majortype)));
1345                if(pMediaType->subtype != MEDIASUBTYPE_NULL)
1346                        sText += AtlFormatString(_T(" * ") _T("`subtype`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatSubtype(pMediaType->majortype, pMediaType->subtype)));
1347                K1(bFixedSizeSamples);
1348                K1(bTemporalCompression);
1349                K1(lSampleSize);
1350                if(pMediaType->formattype != GUID_NULL)
1351                        sText += AtlFormatString(_T(" * ") _T("`formattype`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatFormatType(pMediaType->formattype)));
1352                if(pMediaType->pUnk)
1353                        sText += AtlFormatString(_T(" * ") _T("`pUnk`: %s") _T("\r\n"), I(AtlFormatString(_T("0x%p"), pMediaType->pUnk)));
1354                if(pMediaType->cbFormat)
1355                {
1356                        K1(cbFormat);
1357                        if(pMediaType->pbFormat)
1358                                sText += AtlFormatString(_T(" * ") _T("Format Data, `pbFormat`: %s") _T("\r\n"), I(AtlFormatData(pMediaType->pbFormat, pMediaType->cbFormat).TrimRight()));
1359                }
1360                #undef J
1361                #undef K1
1362                #pragma endregion
1363                const BYTE* pnExtraData = NULL;
1364                SIZE_T nExtraDataSize = 0;
1365                #pragma region FORMAT_VideoInfo
1366                if(pMediaType->formattype == FORMAT_VideoInfo)
1367                {
1368                        sText += AtlFormatString(_T(" * ") _T("As `VIDEOINFOHEADER`:") _T("\r\n"));
1369                        const VIDEOINFOHEADER* pVideoInfoHeader = (const VIDEOINFOHEADER*) pMediaType->pbFormat;
1370                        #define J(x) I(pVideoInfoHeader->x)
1371                        #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
1372                        sText += AtlFormatString(_T("  * ") _T("`rcSource`: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcSource.left), J(rcSource.top), J(rcSource.right), J(rcSource.bottom));
1373                        sText += AtlFormatString(_T("  * ") _T("`rcTarget`: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcTarget.left), J(rcTarget.top), J(rcTarget.right), J(rcTarget.bottom));
1374                        K1(dwBitRate);
1375                        K1(dwBitErrorRate);
1376                        sText += AtlFormatString(_T("  * ") _T("`AvgTimePerFrame`: %s units") _T("\r\n"), I(_FilterGraphHelper::FormatReferenceTime(pVideoInfoHeader->AvgTimePerFrame)));
1377                        K1(bmiHeader.biSize);
1378                        K1(bmiHeader.biWidth);
1379                        K1(bmiHeader.biHeight);
1380                        K1(bmiHeader.biPlanes);
1381                        K1(bmiHeader.biBitCount);
1382                        sText += AtlFormatString(_T("  * ") _T("`bmiHeader.biCompression`: %s") _T("\r\n"), I(_FilterGraphHelper::GetFourccCodeString(pVideoInfoHeader->bmiHeader.biCompression)));
1383                        K1(bmiHeader.biSizeImage);
1384                        K1(bmiHeader.biXPelsPerMeter);
1385                        K1(bmiHeader.biYPelsPerMeter);
1386                        K1(bmiHeader.biClrUsed);
1387                        K1(bmiHeader.biClrImportant);
1388                        #undef J
1389                        #undef K1
1390                        nExtraDataSize = pMediaType->cbFormat - sizeof *pVideoInfoHeader;
1391                } else
1392                #pragma endregion
1393                #pragma region FORMAT_VideoInfo2
1394                if(pMediaType->formattype == FORMAT_VideoInfo2)
1395                {
1396                        sText += AtlFormatString(_T(" * ") _T("As `VIDEOINFOHEADER2`:") _T("\r\n"));
1397                        const VIDEOINFOHEADER2* pVideoInfoHeader2 = (const VIDEOINFOHEADER2*) pMediaType->pbFormat;
1398                        #define J(x) I(pVideoInfoHeader2->x)
1399                        #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
1400                        #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pVideoInfoHeader2->x, y))
1401                        sText += AtlFormatString(_T("  * ") _T("rcSource: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcSource.left), J(rcSource.top), J(rcSource.right), J(rcSource.bottom));
1402                        sText += AtlFormatString(_T("  * ") _T("rcTarget: (%s, %s) - (%s, %s)") _T("\r\n"), J(rcTarget.left), J(rcTarget.top), J(rcTarget.right), J(rcTarget.bottom));
1403                        K1(dwBitRate);
1404                        K1(dwBitErrorRate);
1405                        sText += AtlFormatString(_T("  * ") _T("`AvgTimePerFrame`: %s units") _T("\r\n"), I(_FilterGraphHelper::FormatReferenceTime(pVideoInfoHeader2->AvgTimePerFrame)));
1406                        K2(dwInterlaceFlags, _T("0x%X"));
1407                        K2(dwCopyProtectFlags, _T("0x%X"));
1408                        K1(dwPictAspectRatioX);
1409                        K1(dwPictAspectRatioY);
1410                        K2(dwControlFlags, _T("0x%X"));
1411                        K1(bmiHeader.biSize);
1412                        K1(bmiHeader.biWidth);
1413                        K1(bmiHeader.biHeight);
1414                        K1(bmiHeader.biPlanes);
1415                        K1(bmiHeader.biBitCount);
1416                        sText += AtlFormatString(_T("  * ") _T("`bmiHeader.biCompression`: %s") _T("\r\n"), I(_FilterGraphHelper::GetFourccCodeString(pVideoInfoHeader2->bmiHeader.biCompression)));
1417                        K1(bmiHeader.biSizeImage);
1418                        K1(bmiHeader.biXPelsPerMeter);
1419                        K1(bmiHeader.biYPelsPerMeter);
1420                        K1(bmiHeader.biClrUsed);
1421                        K1(bmiHeader.biClrImportant);
1422                        #undef J
1423                        #undef K1
1424                        #undef K2
1425                        nExtraDataSize = pMediaType->cbFormat - sizeof *pVideoInfoHeader2;
1426                        if(nExtraDataSize)
1427                        {
1428                                sText += AtlFormatString(_T("  * ") _T("Extra Data: (%d bytes)") _T("\r\n"), nExtraDataSize);
1429                                nExtraDataSize = 0;
1430                        }
1431                } else
1432                #pragma endregion
1433                #pragma region FORMAT_MPEG2Video
1434                if(pMediaType->formattype == FORMAT_MPEG2Video)
1435                {
1436                        sText += AtlFormatString(_T(" * ") _T("As `MPEG2VIDEOINFO`:") _T("\r\n"));
1437                        const MPEG2VIDEOINFO* pMpeg2VideoInfo = (const MPEG2VIDEOINFO*) pMediaType->pbFormat;
1438                        #define J(x) I(pMpeg2VideoInfo->x)
1439                        #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
1440                        #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pMpeg2VideoInfo->x, y))
1441                        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));
1442                        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));
1443                        K1(hdr.dwBitRate);
1444                        K1(hdr.dwBitErrorRate);
1445                        sText += AtlFormatString(_T("  * ") _T("`hdr.AvgTimePerFrame`: %s") _T("\r\n"), I(_FilterGraphHelper::FormatReferenceTime(pMpeg2VideoInfo->hdr.AvgTimePerFrame)));
1446                        K2(hdr.dwInterlaceFlags, _T("0x%X"));
1447                        K2(hdr.dwCopyProtectFlags, _T("0x%X"));
1448                        K1(hdr.dwPictAspectRatioX);
1449                        K1(hdr.dwPictAspectRatioY);
1450                        K2(hdr.dwControlFlags, _T("0x%X"));
1451                        K1(hdr.bmiHeader.biSize);
1452                        K1(hdr.bmiHeader.biWidth);
1453                        K1(hdr.bmiHeader.biHeight);
1454                        K1(hdr.bmiHeader.biPlanes);
1455                        K1(hdr.bmiHeader.biBitCount);
1456                        sText += AtlFormatString(_T("  * ") _T("`hdr.bmiHeader.biCompression`: %s") _T("\r\n"), I(_FilterGraphHelper::GetFourccCodeString(pMpeg2VideoInfo->hdr.bmiHeader.biCompression)));
1457                        K1(hdr.bmiHeader.biSizeImage);
1458                        K1(hdr.bmiHeader.biXPelsPerMeter);
1459                        K1(hdr.bmiHeader.biYPelsPerMeter);
1460                        K1(hdr.bmiHeader.biClrUsed);
1461                        K1(hdr.bmiHeader.biClrImportant);
1462                        K2(dwStartTimeCode, _T("0x%08X"));
1463                        K1(cbSequenceHeader);
1464                        K1(dwProfile);
1465                        K1(dwLevel);
1466                        K2(dwFlags, _T("0x%08X"));
1467                        #undef J
1468                        #undef K1
1469                        #undef K2
1470                        #undef J
1471                        nExtraDataSize = pMediaType->cbFormat - (sizeof *pMpeg2VideoInfo - sizeof pMpeg2VideoInfo->dwSequenceHeader);
1472                } else
1473                #pragma endregion
1474                #pragma region FORMAT_WaveFormatEx
1475                if(pMediaType->formattype == FORMAT_WaveFormatEx)
1476                {
1477                        const WAVEFORMATEX* pWaveFormatEx = (const WAVEFORMATEX*) pMediaType->pbFormat;
1478                        if(pWaveFormatEx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
1479                        {
1480                                const WAVEFORMATEXTENSIBLE* pWaveFormatExtensible = (const WAVEFORMATEXTENSIBLE*) pMediaType->pbFormat;
1481                                #define J(x) I(pWaveFormatExtensible->x)
1482                                #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
1483                                #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pWaveFormatExtensible->x, y))
1484                                sText += AtlFormatString(_T(" * ") _T("As `WAVEFORMATEXTENSIBLE`:") _T("\r\n"));
1485                                K2(Format.wFormatTag, _T("0x%02X"));
1486                                K1(Format.nChannels);
1487                                K1(Format.nSamplesPerSec);
1488                                K1(Format.nAvgBytesPerSec);
1489                                K1(Format.nBlockAlign);
1490                                K1(Format.wBitsPerSample);
1491                                K1(Format.cbSize);
1492                                K1(Samples.wValidBitsPerSample);
1493                                K2(dwChannelMask, _T("0x%02X"));
1494                                sText += AtlFormatString(_T("  * ") _T("`SubFormat`: %s") _T("\r\n"), I(_PersistHelper::StringFromIdentifier(pWaveFormatExtensible->SubFormat)));
1495                                #undef J
1496                                #undef K1
1497                                #undef K2
1498                                nExtraDataSize = pWaveFormatEx->cbSize - (sizeof *pWaveFormatExtensible - sizeof *pWaveFormatEx);
1499                        } else
1500                        {
1501                                #define J(x) I(pWaveFormatEx->x)
1502                                #define K1(x) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), J(x))
1503                                #define K2(x, y) sText += AtlFormatString(_T("  * `") _T(#x) _T("`: %s") _T("\r\n"), I(pWaveFormatEx->x, y))
1504                                K2(wFormatTag, _T("0x%02X"));
1505                                K1(nChannels);
1506                                K1(nSamplesPerSec);
1507                                K1(nAvgBytesPerSec);
1508                                K1(nBlockAlign);
1509                                K1(wBitsPerSample);
1510                                K1(cbSize);
1511                                #undef J
1512                                #undef K1
1513                                #undef K2
1514                                nExtraDataSize = pWaveFormatEx->cbSize;
1515                        }
1516                }
1517                #pragma endregion
1518                #pragma region Extra Data
1519                if(nExtraDataSize)
1520                {
1521                        if(!pnExtraData)
1522                                pnExtraData = pMediaType->pbFormat + pMediaType->cbFormat - nExtraDataSize;
1523                        sText += AtlFormatString(_T("  * ") _T("Extra Data: %s") _T("\r\n"), I(AtlFormatData(pnExtraData, nExtraDataSize).TrimRight()));
1524                }
1525                #pragma endregion
1526                return sText;
1527        }
1528        static CString GetText(IFilterGraph* pFilterGraph, const CProcessData* pProcessData = NULL)
1529        {
1530                if(!pFilterGraph)
1531                        return (LPCTSTR) NULL;
1532                CString sText;
1533                sText += AtlFormatString(_T("# ") _T("Filter Graph") _T("\r\n") _T("\r\n"));
1534                #pragma region Graph Parameters
1535                if(pProcessData)
1536                        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)));
1537                #pragma region IMediaControl
1538                const CComQIPtr<IMediaControl> pMediaControl = pFilterGraph;
1539                if(pMediaControl)
1540                        _ATLTRY
1541                        {
1542                                OAFilterState State;
1543                                const HRESULT nGetStateResult = pMediaControl->GetState(0, &State);
1544                                _Z45_DSHRESULT(nGetStateResult);
1545                                static const LPCTSTR g_ppszStates[] = { _T("Stopped"), _T("Paused"), _T("Running"), };
1546                                if(SUCCEEDED(nGetStateResult) && (SIZE_T) State < DIM(g_ppszStates))
1547                                        sText += AtlFormatString(_T("* ") _T("State: %s") _T("\r\n"), I(g_ppszStates[(SIZE_T) State]));
1548                        }
1549                        _ATLCATCHALL()
1550                        {
1551                                _Z_EXCEPTION();
1552                        }
1553                #pragma endregion
1554                #pragma region IMediaPosition
1555                const CComQIPtr<IMediaPosition> pMediaPosition = pFilterGraph;
1556                if(pMediaPosition)
1557                        _ATLTRY
1558                        {
1559                                DOUBLE fDuration = 0, fPosition = 0;
1560                                const HRESULT nGetDurationResult = pMediaPosition->get_Duration(&fDuration);
1561                                _Z45_DSHRESULT(nGetDurationResult);
1562                                if(fDuration > 0)
1563                                {
1564                                        sText += AtlFormatString(_T("* ") _T("Duration: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime(fDuration)), I(_StringHelper::FormatNumber(fDuration, 3)));
1565                                        const HRESULT nCurrentPositionResult = pMediaPosition->get_CurrentPosition(&fPosition);
1566                                        _Z45_DSHRESULT(nCurrentPositionResult);
1567                                        if(SUCCEEDED(nCurrentPositionResult))
1568                                                sText += AtlFormatString(_T("* ") _T("Position: %s (%s seconds)") _T("\r\n"), I(_FilterGraphHelper::FormatSecondTime(fPosition)), I(_StringHelper::FormatNumber(fPosition, 3)));
1569                                }
1570                        }
1571                        _ATLCATCHALL()
1572                        {
1573                                _Z_EXCEPTION();
1574                        }
1575                #pragma endregion
1576                if(pProcessData)
1577                {
1578                        if(!pProcessData->m_sDisplayName.IsEmpty())
1579                                sText += AtlFormatString(_T("* ") _T("Display Name: %s") _T("\r\n"), I(pProcessData->m_sDisplayName));
1580                        const CString sDirectory = (LPCTSTR) GetPathDirectory(pProcessData->m_sImagePath);
1581                        if(!sDirectory.IsEmpty())
1582                                sText += AtlFormatString(_T("* ") _T("Process Directory: %s") _T("\r\n"), I(sDirectory));
1583                }
1584                const CComQIPtr<IMediaFilter> pMediaFilter = pFilterGraph;
1585                CComPtr<IReferenceClock> pFilterGraphReferenceClock;
1586                const HRESULT nGetSyncSourceResult = pMediaFilter->GetSyncSource(&pFilterGraphReferenceClock);
1587                _Z45_DSHRESULT(nGetSyncSourceResult);
1588                sText += _T("\r\n");
1589                #pragma endregion
1590                #pragma region Filter
1591                _FilterGraphHelper::CFilterArray FilterArray;
1592                _FilterGraphHelper::GetGraphFilters(pFilterGraph, FilterArray);
1593                if(!FilterArray.IsEmpty())
1594                {
1595                        sText += AtlFormatString(_T("## ") _T("Filters") _T("\r\n") _T("\r\n"));
1596                        for(SIZE_T nIndex = 0; nIndex < FilterArray.GetCount(); nIndex++)
1597                                _ATLTRY
1598                                {
1599                                        const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nIndex];
1600                                        sText += AtlFormatString(_T("%d. ") _T("%ls") _T("\r\n"), nIndex + 1, _FilterGraphHelper::GetFilterName(pBaseFilter));
1601                                        sText += GetFilterText(pBaseFilter, pFilterGraphReferenceClock);
1602                                }
1603                                _ATLCATCHALL()
1604                                {
1605                                        _Z_EXCEPTION();
1606                                }
1607                        sText += _T("\r\n");
1608                        #pragma region Connection
1609                        sText += AtlFormatString(_T("## ") _T("Connections") _T("\r\n") _T("\r\n"));
1610                        INT nConnectionIndex = 0;
1611                        for(SIZE_T nFilterIndex = 0; nFilterIndex < FilterArray.GetCount(); nFilterIndex++)
1612                        {
1613                                const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nFilterIndex];
1614                                _FilterGraphHelper::CPinArray PinArray;
1615                                _FilterGraphHelper::GetFilterPins(pBaseFilter, PINDIR_OUTPUT, PinArray);
1616                                for(SIZE_T nPinIndex = 0; nPinIndex < PinArray.GetCount(); nPinIndex++)
1617                                {
1618                                        const CComPtr<IPin>& pOutputPin = PinArray[nPinIndex];
1619                                        const CComPtr<IPin> pInputPin = _FilterGraphHelper::GetPeerPin(pOutputPin);
1620                                        if(!pInputPin)
1621                                                continue;
1622                                        sText += AtlFormatString(_T("%d. ") _T("%s") _T("\r\n"), ++nConnectionIndex, GetConnectionText(pOutputPin, pInputPin));
1623                                }
1624                        }
1625                        sText += _T("\r\n");
1626                        #pragma endregion
1627                        #pragma region Media Type
1628                        sText += AtlFormatString(_T("## ") _T("Media Types") _T("\r\n") _T("\r\n"));
1629                        INT nGlobalPinIndex = 0;
1630                        CRoListT<CComPtr<IPin>> PinList;
1631                        for(SIZE_T nFilterIndex = 0; nFilterIndex < FilterArray.GetCount(); nFilterIndex++)
1632                        {
1633                                const CComPtr<IBaseFilter>& pBaseFilter = FilterArray[nFilterIndex];
1634                                _FilterGraphHelper::CPinArray PinArray;
1635                                _FilterGraphHelper::GetFilterPins(pBaseFilter, PinArray);
1636                                for(SIZE_T nPinIndex = 0; nPinIndex < PinArray.GetCount(); nPinIndex++)
1637                                {
1638                                        const CComPtr<IPin>& pPin = PinArray[nPinIndex];
1639                                        if(PinList.FindFirst(pPin))
1640                                                continue;
1641                                        PinList.AddTail(pPin);
1642                                        CString sPinText = AtlFormatString(_T("%s"), I(_FilterGraphHelper::GetPinFullName(pPin)));
1643                                        const CComPtr<IPin> pPeerPin = _FilterGraphHelper::GetPeerPin(pPin);
1644                                        if(pPeerPin)
1645                                        {
1646                                                PinList.AddTail(pPeerPin);
1647                                                sPinText += AtlFormatString(_T(", %s"), I(_FilterGraphHelper::GetPinFullName(pPeerPin)));
1648                                        }
1649                                        sText += AtlFormatString(_T("%d. ") _T("%s") _T("\r\n"), ++nGlobalPinIndex, sPinText);
1650                                        _ATLTRY
1651                                        {
1652                                                CMediaType pMediaType;
1653                                                if(pPeerPin)
1654                                                        pMediaType = _FilterGraphHelper::GetPinMediaType(pPin);
1655                                                else
1656                                                        pMediaType = _FilterGraphHelper::EnumerateFirstPinMediaType(pPin);
1657                                                if(!pMediaType)
1658                                                        continue;
1659                                                sText += GetMediaTypeText(pMediaType);
1660                                        }
1661                                        _ATLCATCHALL()
1662                                        {
1663                                                _Z_EXCEPTION();
1664                                        }
1665                                }
1666                        }
1667                        sText += _T("\r\n");
1668                        #pragma endregion
1669                }
1670                #pragma endregion
1671                return sText;
1672        }
1673        #undef I
1674        CComPtr<IFilterGraph> GetFilterGraph() const
1675        {
1676                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1677                return m_pFilterGraph;
1678        }
1679        VOID SetFilterGraph(IFilterGraph* pFilterGraph) 
1680        {
1681                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1682                m_pFilterGraph = pFilterGraph;
1683        }
1684        BOOL SetFilterGraph(IUnknown* pFilterGraphUnknown) 
1685        {
1686                CComQIPtr<IFilterGraph> pFilterGraph;
1687                if(pFilterGraphUnknown)
1688                {
1689                        pFilterGraph = pFilterGraphUnknown;
1690                        if(!pFilterGraph)
1691                        {
1692                                const CComQIPtr<IBaseFilter> pBaseFilter = pFilterGraphUnknown;
1693                                if(!pBaseFilter)
1694                                {
1695                                        const CComQIPtr<IPin> pPin = pFilterGraphUnknown;
1696                                        if(pPin)
1697                                                pFilterGraph = _FilterGraphHelper::GetFilterGraph(_FilterGraphHelper::GetPinFilter(pPin));
1698                                } else
1699                                        pFilterGraph = _FilterGraphHelper::GetFilterGraph(pBaseFilter);
1700                        }
1701                }
1702                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1703                m_pFilterGraph = pFilterGraph;
1704                return m_pFilterGraph != NULL;
1705        }
1706        CString GetText() const
1707        {
1708                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1709                return GetText(m_pFilterGraph);
1710        }
1711
1712// IFilterGraphHelper
1713        STDMETHOD(get_FilterGraph)(IUnknown** ppFilterGraphUnknown)
1714        {
1715                _Z4(atlTraceCOM, 4, _T("...\n"));
1716                _ATLTRY
1717                {
1718                        __D(ppFilterGraphUnknown, E_POINTER);
1719                        *ppFilterGraphUnknown = GetFilterGraph().Detach();
1720                }
1721                _ATLCATCH(Exception)
1722                {
1723                        _C(Exception);
1724                }
1725                return S_OK;
1726        }
1727        STDMETHOD(put_FilterGraph)(IUnknown* pFilterGraphUnknown)
1728        {
1729                _Z4(atlTraceCOM, 4, _T("pFilterGraphUnknown 0x%p\n"), pFilterGraphUnknown);
1730                _ATLTRY
1731                {
1732                        if(!SetFilterGraph(pFilterGraphUnknown))
1733                                return S_FALSE;
1734                }
1735                _ATLCATCH(Exception)
1736                {
1737                        _C(Exception);
1738                }
1739                return S_OK;
1740        }
1741        STDMETHOD(get_Text)(BSTR* psText)
1742        {
1743                _Z4(atlTraceCOM, 4, _T("...\n"));
1744                _ATLTRY
1745                {
1746                        __D(psText, E_POINTER);
1747                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1748                        *psText = CComBSTR(GetText(m_pFilterGraph)).Detach();
1749                }
1750                _ATLCATCH(Exception)
1751                {
1752                        _C(Exception);
1753                }
1754                return S_OK;
1755        }
1756        STDMETHOD(DoPropertyFrameModal)(LONG nParentWindowHandle)
1757        {
1758                _Z4(atlTraceCOM, 4, _T("...\n"));
1759                _ATLTRY
1760                {
1761                        CWindow ParentWindow = (HWND) (LONG_PTR) nParentWindowHandle;
1762                        if(!ParentWindow)
1763                                ParentWindow = GetActiveWindow();
1764                        __D(!ParentWindow || ParentWindow.IsWindow(), E_INVALIDARG);
1765                        const CComQIPtr<IFilterGraph2> pFilterGraph2 = GetFilterGraph();
1766                        __D(pFilterGraph2, E_NOINTERFACE);
1767                        CPropertyFrameDialog PropertyFrameDialog(this);
1768                        PropertyFrameDialog.DoModal(ParentWindow);
1769                }
1770                _ATLCATCH(Exception)
1771                {
1772                        _C(Exception);
1773                }
1774                return S_OK;
1775        }
1776};
1777
1778OBJECT_ENTRY_AUTO(__uuidof(FilterGraphHelper), CFilterGraphHelper)
Note: See TracBrowser for help on using the repository browser.