source: trunk/DirectShowSpy/FilterGraphHelper.h @ 247

Last change on this file since 247 was 247, checked in by roman, 10 years ago

Added ISpy methods, added IFilterGraphHelper methods for better GSN integration; Added property frame tree info tips and class descriptions; Added email credentials cleanup link and hints

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