source: trunk/DirectShowSpy/MediaSampleTrace.h @ 441

Last change on this file since 441 was 441, checked in by roman, 7 years ago

Added filtering in media sample trace UI; fixed thread safety problem; fixed file mapping initialization issue; removed media sample leak feature (to extend file mapping lifetime) and replaced with file mapping ownership transfer to UI process; added menu item to jump right to filter graph

File size: 53.7 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2008-2015
3// Created by Roman Ryltsov roman@alax.info, http://alax.info
4//
5// This source code is published to complement DirectShowSpy developer powertoy
6// and demonstrate the internal use of APIs and tricks powering the tool. It is
7// allowed to freely re-use the portions of the code in other projects, commercial
8// or otherwise (provided that you don’t pretend that you wrote the original tool).
9//
10// Please keep in mind that DirectShowSpy is a developer tool, it is strongly recommended
11// that it is not shipped with release grade software. It is allowed to distribute
12// DirectShowSpy if only it is not registered with Windows by default and either
13// used privately, or registered on specific throubleshooting request. The advice applies
14// to hooking methods used by DirectShowSpy in general as well.
15
16#pragma once
17
18#include "rodshow.h"
19#include "Module_i.h"
20#include "Common.h"
21#include "FilterGraphHelper.h"
22#include "FilterGraphList.h"
23
24////////////////////////////////////////////////////////////
25// CMediaSampleTraceBase
26
27class CMediaSampleTraceBase
28{
29public:
30
31        ////////////////////////////////////////////////////////
32        // Structure
33
34        #pragma pack(push, 1)
35
36        enum
37        {
38                HEADERFLAGS_NONE = 0,
39        };
40
41        typedef struct _HEADER
42        {
43                UINT32 nCapacity;
44                UINT32 nFlags;
45                UINT32 nVersion;
46                UINT32 nItemCount;
47        } HEADER;
48
49        enum
50        {
51                ITEMFLAGS_NONE = 0,
52                ITEMFLAG_INVALID = 1,
53        };
54
55        typedef struct _ITEM
56        {
57                UINT32 nFlags;
58                UINT32 nProcessIdentifier;
59                UINT32 nPageIdentifier;
60                UINT64 nFilterGraphIdentifier;
61                WCHAR pszFilterGraphName[128];
62        } ITEM;
63
64        enum
65        {
66                PAGEHEADERFLAGS_NONE = 0,
67                PAGEHEADERFLAG_X64 = 1,
68        };
69
70        typedef struct _PAGEHEADER
71        {
72                UINT32 nCapacity;
73                UINT32 nFlags;
74                UINT32 nProcessIdentifier;
75                UINT32 nItemCount;
76        } PAGEHEADER;
77
78        enum
79        {
80                PAGEITEMFLAGS_NONE = 0,
81                PAGEITEMFLAG_NEWSEGMENT = 0,
82                PAGEITEMFLAG_MEDIASAMPLE = 1,
83                PAGEITEMFLAG_ENDOFSTREAM = 2,
84                PAGEITEMFLAG_COMMENT = 3,
85                PAGEITEMFLAG_TYPE_MASK = 0x03,
86        };
87
88        typedef struct _PAGEITEM
89        {
90                UINT32 nFlags;
91                UINT32 nThreadIdentifier;
92                UINT64 nFilterIdentifier;
93                WCHAR pszFilterName[32];
94                WCHAR pszStreamName[32];
95                UINT64 nTime;
96                union
97                {
98                        struct
99                        {
100                                REFERENCE_TIME nStartTime;
101                                REFERENCE_TIME nStopTime;
102                                DOUBLE fRate;
103                        } NewSegment;
104                        struct
105                        {
106                                AM_SAMPLE2_PROPERTIES Properties;
107                        } MediaSample;
108                } Data;
109                WCHAR pszComment[64];
110        } PAGEITEM;
111
112        #pragma pack(pop)
113
114        ////////////////////////////////////////////////////////
115        // CData
116
117        class CData
118        {
119        public:
120
121                ///////////////////////////////////////////////////////
122                // CItem
123
124                class CItem
125                {
126                public:
127                        ITEM m_Item;
128                        PAGEITEM m_PageItem;
129
130                public:
131                // CItem
132                        LPCTSTR FormatType() const
133                        {
134                                switch(m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK)
135                                {
136                                case PAGEITEMFLAG_NEWSEGMENT:
137                                        return _T("New Segment");
138                                case PAGEITEMFLAG_MEDIASAMPLE:
139                                        return _T("Media Sample");
140                                case PAGEITEMFLAG_ENDOFSTREAM:
141                                        return _T("End of Stream");
142                                //case PAGEITEMFLAG_COMMENT:
143                                //      return _T("Comment");
144                                }
145                                return _T("Comment");
146                        }
147                };
148
149                ////////////////////////////////////////////////////
150                // CItemSortTraits
151
152                class CItemSortTraits :
153                        public CDefaultSortTraitsT<CItem>
154                {
155                public:
156                // CItemSortTraits
157                        static INT_PTR CompareElements(const CItem& Item1, const CItem& Item2, PARAMETERARGUMENT)
158                        {
159                                const INT64 nTime = Item1.m_PageItem.nTime - Item2.m_PageItem.nTime;
160                                return (nTime < 0) ? -1 : (nTime > 0) ? 1 : 0;
161                        }
162                };
163
164        public:
165                CRoArrayT<CItem> m_ItemArray;
166
167        public:
168        // CData
169                VOID Initialize()
170                {
171                        m_ItemArray.SetCount(0, 32768);
172                }
173                VOID Add(const HEADER* pHeader, const ITEM* pItem, const PAGEHEADER* pPageHeader, const PAGEITEM* pPageItem)
174                {
175                        _A(pHeader && pItem && pPageHeader && pPageItem);
176                        pHeader; pPageHeader;
177                        const SIZE_T nIndex = m_ItemArray.Add();
178                        CItem& Item = m_ItemArray[nIndex];
179                        Item.m_Item = *pItem;
180                        Item.m_PageItem = *pPageItem;
181                }
182                VOID Sort()
183                {
184                        _SortHelper::QuickSort<CItemSortTraits>(m_ItemArray);
185                }
186        };
187
188        ////////////////////////////////////////////////////////
189        // CHandleMap
190
191        class CHandleMap :
192                protected CRoMapT<CString, HANDLE>
193        {
194        protected:
195                mutable CRoCriticalSection m_DataCriticalSection;
196
197        public:
198        // CHandleMap
199                CHandleMap()
200                {
201                }
202                ~CHandleMap()
203                {
204                        RemoveAll();
205                }
206                VOID Add(const CString& sName, HANDLE hValue)
207                {
208                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
209                        if(Lookup(sName))
210                                return;
211                        CHandle PrivateValue;
212                        if(!DuplicateHandle(GetCurrentProcess(), hValue, GetCurrentProcess(), &PrivateValue.m_h, 0, FALSE, DUPLICATE_SAME_ACCESS))
213                                return;
214                        _W(SetAt(sName, PrivateValue.Detach()));
215                }
216                VOID RemoveAll()
217                {
218                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
219                        for(auto&& hValue: GetValues())
220                                reinterpret_cast<CHandle&>(hValue).Close();
221                        __super::RemoveAll();
222                }
223        };
224
225        ////////////////////////////////////////////////////////
226        // CPages
227
228        class CPages
229        {
230        private:
231                UINT64 m_nFilterGraphIdentifier;
232                CStringW m_sFilterGraphName;
233                CMutex m_Mutex;
234                CAtlFileMapping<HEADER> m_FileMapping;
235
236        public:
237        // CPages
238                static LPCTSTR GetMutexName()
239                {
240                        return _T("DirectShowSpy.MediaSamplePageRegistry.Access");
241                }
242                static SIZE_T GetFileMappingCapacity()
243                {
244                        return 1 << 20; // 1 MB
245                }
246                static LPCTSTR GetFileMappingName()
247                {
248                        return _T("DirectShowSpy.MediaSamplePageRegistry");
249                }
250                static CString GetPageMutexName(UINT32 nProcessIdentifier, UINT64 nPageIdentifier)
251                {
252                        return AtlFormatString(_T("DirectShowSpy.MediaSamplePage.%08X.%08X.Access"), nProcessIdentifier, nPageIdentifier);
253                }
254                static SIZE_T GetPageFileMappingCapacity()
255                {
256                        return 4 << 20; // 4 MB
257                }
258                static CString GetPageFileMappingName(UINT32 nProcessIdentifier, UINT64 nPageIdentifier)
259                {
260                        return AtlFormatString(_T("DirectShowSpy.MediaSamplePage.%08X.%08X"), nProcessIdentifier, nPageIdentifier);
261                }
262                static VOID InitializeFileMapping(CAtlFileMapping<HEADER>& FileMapping)
263                {
264                        HEADER* pHeader = FileMapping;
265                        pHeader->nCapacity = (UINT32) GetFileMappingCapacity();
266                        pHeader->nFlags = HEADERFLAGS_NONE;
267                        pHeader->nVersion = 0;
268                        pHeader->nItemCount = 0;
269                }
270                BOOL Initialize(BOOL bCreate = FALSE)
271                {
272                        _A(!m_Mutex && !m_FileMapping);
273                        if(!bCreate)
274                        {
275                                if(!m_Mutex.Open(MUTEX_ALL_ACCESS, FALSE, GetMutexName()))
276                                        return FALSE;
277                                _ATLTRY
278                                {
279                                        //CMutexLock MutexLock(m_Mutex);
280                                        __C(m_FileMapping.OpenMapping(GetFileMappingName(), GetFileMappingCapacity()));
281                                }
282                                _ATLCATCHALL()
283                                {
284                                        m_Mutex.Close();
285                                        _ATLRETHROW;
286                                }
287                        } else
288                        {
289                                __E(m_Mutex.Create(NULL, FALSE, GetMutexName()));
290                                //CMutexLock MutexLock(m_Mutex);
291                                __C(m_FileMapping.MapSharedMem(GetFileMappingCapacity(), GetFileMappingName()));
292                                HEADER* pHeader = m_FileMapping;
293                                if(!pHeader->nCapacity)
294                                        InitializeFileMapping(m_FileMapping);
295                        }
296                        return TRUE;
297                }
298                VOID GetData(CData& Data, CHandleMap* pHandleMap = NULL)
299                {
300                        _A(m_Mutex && m_FileMapping);
301                        if(pHandleMap)
302                        {
303                                pHandleMap->Add(GetMutexName(), m_Mutex);
304                                pHandleMap->Add(GetFileMappingName(), m_FileMapping.GetHandle());
305                        }
306                        Data.Initialize();
307                        CMutexLock MutexLock(m_Mutex);
308                        HEADER* pHeader = m_FileMapping;
309                        _A(pHeader->nCapacity);
310                        for(UINT32 nItemIndex = 0; nItemIndex < pHeader->nItemCount; nItemIndex++)
311                        {
312                                ITEM* pItem = (ITEM*) (pHeader + 1) + nItemIndex;
313                                if(pItem->nFlags & ITEMFLAG_INVALID)
314                                        continue;
315                                _ATLTRY
316                                {
317                                        CMutex PageMutex;
318                                        const CString sMutexName = GetPageMutexName(pItem->nProcessIdentifier, pItem->nPageIdentifier);
319                                        __E(PageMutex.Open(MUTEX_ALL_ACCESS, FALSE, sMutexName));
320                                        CAtlFileMapping<PAGEHEADER> PageFileMapping;
321                                        const CString sFileMappingName = GetPageFileMappingName(pItem->nProcessIdentifier, pItem->nPageIdentifier);
322                                        __C(PageFileMapping.OpenMapping(sFileMappingName, GetPageFileMappingCapacity()));
323                                        if(pHandleMap)
324                                        {
325                                                pHandleMap->Add(sMutexName, PageMutex);
326                                                pHandleMap->Add(sFileMappingName, PageFileMapping.GetHandle());
327                                        }
328                                        PAGEHEADER* pPageHeader = PageFileMapping;
329                                        CMutexLock MutexLock(PageMutex);
330                                        #pragma region Bitness
331                                        // SUGG: Support non-native bitness through conversion
332                                        #if defined(_WIN64)
333                                                if(!(pPageHeader->nFlags & PAGEHEADERFLAG_X64))
334                                                        continue;
335                                        #else
336                                                if(pPageHeader->nFlags & PAGEHEADERFLAG_X64)
337                                                        continue;
338                                        #endif // defined(_WIN64)
339                                        #pragma endregion
340                                        for(UINT32 nItemIndex = 0; nItemIndex < pPageHeader->nItemCount; nItemIndex++)
341                                        {
342                                                PAGEITEM* pPageItem = (PAGEITEM*) (pPageHeader + 1) + nItemIndex;
343                                                Data.Add(pHeader, pItem, pPageHeader, pPageItem);
344                                        }
345                                        continue;
346                                }
347                                _ATLCATCHALL()
348                                {
349                                        _Z_EXCEPTION();
350                                }
351                                pItem->nFlags |= ITEMFLAG_INVALID;
352                        }
353                }
354                VOID ResetData()
355                {
356                        CMutexLock MutexLock(m_Mutex);
357                        HEADER* pHeader = m_FileMapping;
358                        _A(pHeader->nCapacity);
359                        pHeader->nItemCount = 0;
360                        pHeader->nVersion++;
361                }
362                VOID Initialize(UINT64 nFilterGraphIdentifier, const CStringW& sFilterGraphName)
363                {
364                        _A(!m_Mutex && !m_FileMapping);
365                        m_nFilterGraphIdentifier = nFilterGraphIdentifier;
366                        m_sFilterGraphName = sFilterGraphName;
367                        __E(m_Mutex.Create(NULL, FALSE, GetMutexName()));
368                        CMutexLock MutexLock(m_Mutex);
369                        BOOL bOpen = FALSE;
370                        __C(m_FileMapping.MapSharedMem(GetFileMappingCapacity(), GetFileMappingName(), &bOpen));
371                        HEADER* pHeader = m_FileMapping;
372                        if(!pHeader->nCapacity)
373                                InitializeFileMapping(m_FileMapping);
374                        #if defined(_DEBUG)
375                                _Z4(atlTraceGeneral, 4, _T("File mapping size %d, item size %d, item capacity %d\n"), GetFileMappingCapacity(), sizeof (ITEM), (GetFileMappingCapacity() - sizeof (HEADER)) / sizeof (ITEM));
376                                _Z4(atlTraceGeneral, 4, _T("Page file mapping size %d, page item size %d, page item capacity %d\n"), GetPageFileMappingCapacity(), sizeof (PAGEITEM), (GetPageFileMappingCapacity() - sizeof (PAGEHEADER)) / sizeof (PAGEITEM));
377                        #endif // defined(_DEBUG)
378                }
379                VOID CreatePage(UINT32& nPageIdentifier, CMutex& Mutex, CAtlFileMapping<PAGEHEADER>& FileMapping)
380                {
381                        _A(!Mutex && !FileMapping);
382                        // SUGG: Random identifiers
383                        for(nPageIdentifier = 0; ; nPageIdentifier++)
384                        {
385                                if(!Mutex.Create(NULL, FALSE, GetPageMutexName(GetCurrentProcessId(), nPageIdentifier)))
386                                {
387                                        const HRESULT nCreateResult = AtlHresultFromLastError();
388                                        __D(nCreateResult == E_ACCESSDENIED, nCreateResult);
389                                        continue; // Already Exists, Access Denied
390                                }
391                                _ATLTRY
392                                {
393                                        CMutexLock MutexLock(Mutex);
394                                        if(GetLastError() != ERROR_ALREADY_EXISTS)
395                                        {
396                                                BOOL bOpen = FALSE;
397                                                __C(FileMapping.MapSharedMem(GetPageFileMappingCapacity(), GetPageFileMappingName(GetCurrentProcessId(), nPageIdentifier), &bOpen));
398                                                _ATLTRY
399                                                {
400                                                        __D(!bOpen, E_UNNAMED);
401                                                        PAGEHEADER* pPageHeader = FileMapping;
402                                                        _A(!pPageHeader->nCapacity);
403                                                        pPageHeader->nCapacity = (UINT32) GetPageFileMappingCapacity();
404                                                        pPageHeader->nFlags = 0;
405                                                        #if defined(_WIN64)
406                                                                pPageHeader->nFlags |= PAGEHEADERFLAG_X64;
407                                                        #endif // defined(_WIN64)
408                                                        pPageHeader->nProcessIdentifier = (UINT32) GetCurrentProcessId();
409                                                        pPageHeader->nItemCount = 0;
410                                                        MutexLock.Unlock();
411                                                        #pragma region Link Page
412                                                        {
413                                                                CMutexLock MutexLock(m_Mutex);
414                                                                HEADER* pHeader = m_FileMapping;
415                                                                const SIZE_T nCapacity = sizeof *pHeader + (pHeader->nItemCount + 1) * sizeof (ITEM);
416                                                                __D(nCapacity <= (SIZE_T) pHeader->nCapacity, HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW));
417                                                                ITEM* pItem = (ITEM*) (pHeader + 1) + pHeader->nItemCount;
418                                                                pItem->nFlags = ITEMFLAGS_NONE;
419                                                                pItem->nProcessIdentifier = (UINT32) GetCurrentProcessId();
420                                                                pItem->nPageIdentifier = nPageIdentifier;
421                                                                pItem->nFilterGraphIdentifier = m_nFilterGraphIdentifier;
422                                                                wcsncpy_s(pItem->pszFilterGraphName, m_sFilterGraphName, _TRUNCATE);
423                                                                pHeader->nItemCount++;
424                                                                pHeader->nVersion++;
425                                                        }
426                                                        #pragma endregion
427                                                        break;
428                                                }
429                                                _ATLCATCHALL()
430                                                {
431                                                        _V(FileMapping.Unmap());
432                                                        _ATLRETHROW;
433                                                }
434                                        }
435                                }
436                                _ATLCATCHALL()
437                                {
438                                        _Z_EXCEPTION();
439                                }
440                                Mutex.Close();
441                        }
442                }
443        };
444
445        ////////////////////////////////////////////////////////
446        // CPage
447
448        class CPage
449        {
450        public:
451
452                ///////////////////////////////////////////////////
453                // CItem
454
455                class CItem
456                {
457                public:
458                        UINT32 m_nPageIdentifier;
459                        CMutex m_Mutex;
460                        CAtlFileMapping<PAGEHEADER> m_FileMapping;
461                        BOOL m_bActive;
462
463                public:
464                // CItem
465                };
466
467        private:
468                CRoListT<CItem> m_ItemList;
469
470        public:
471        // CPage
472                BOOL IsEmpty() const
473                {
474                        return m_ItemList.IsEmpty();
475                }
476                VOID Register(CPages& Pages, UINT64 nFilterIdentifier, const CStringW& sFilterName, LPCWSTR pszStreamName, const PAGEITEM& PageItem, LPCWSTR pszComment)
477                {
478                        const UINT64 nTime = (UINT64) CUsAccurateFileTime::GetTime();
479                        for(UINT nIteration = 0; ; nIteration++)
480                        {
481                                _A(nIteration < 2);
482                                if(!m_ItemList.IsEmpty() && m_ItemList.GetTail().m_bActive)
483                                {
484                                        CMutexLock MutexLock(m_ItemList.GetTail().m_Mutex);
485                                        PAGEHEADER* pPageHeader = m_ItemList.GetTail().m_FileMapping;
486                                        const SIZE_T nCapacity = sizeof *pPageHeader + (pPageHeader->nItemCount + 1) * sizeof (PAGEITEM);
487                                        if(nCapacity <= (SIZE_T) pPageHeader->nCapacity)
488                                        {
489                                                PAGEITEM* pPageItem = (PAGEITEM*) (pPageHeader + 1) + pPageHeader->nItemCount;
490                                                pPageItem->nFlags = PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK;
491                                                pPageItem->nThreadIdentifier = GetCurrentThreadId();
492                                                pPageItem->nFilterIdentifier = nFilterIdentifier;
493                                                wcsncpy_s(pPageItem->pszFilterName, sFilterName, _TRUNCATE);
494                                                if(pszStreamName)
495                                                        wcsncpy_s(pPageItem->pszStreamName, pszStreamName, _TRUNCATE);
496                                                else
497                                                        *pPageItem->pszStreamName = 0;
498                                                pPageItem->nTime = nTime;
499                                                pPageItem->Data = PageItem.Data;
500                                                if(pszComment)
501                                                        wcsncpy_s(pPageItem->pszComment, pszComment, _TRUNCATE);
502                                                else
503                                                        *pPageItem->pszComment = 0;
504                                                pPageHeader->nItemCount++;
505                                                return;
506                                        }
507                                        m_ItemList.GetTail().m_bActive = FALSE;
508                                }
509                                const POSITION Position = m_ItemList.AddTail();
510                                _ATLTRY
511                                {
512                                        CItem& Item = m_ItemList.GetAt(Position);
513                                        Pages.CreatePage(Item.m_nPageIdentifier, Item.m_Mutex, Item.m_FileMapping);
514                                        Item.m_bActive = TRUE;
515                                }
516                                _ATLCATCHALL()
517                                {
518                                        m_ItemList.RemoveAt(Position);
519                                        _ATLRETHROW;
520                                }
521                        }
522                }
523        };
524
525public:
526// CMediaSampleTraceBase
527};
528
529////////////////////////////////////////////////////////////
530// CMediaSampleTrace
531
532class ATL_NO_VTABLE CMediaSampleTrace :
533        public CComObjectRootEx<CComMultiThreadModelNoCS>,
534        public CComCoClass<CMediaSampleTrace>,// &__uuidof(MediaSampleTrace)>,
535        //public IProvideClassInfo2Impl<&__uuidof(MediaSampleTrace), &IID_NULL>,
536        public IMediaSampleTrace,
537        public CMediaSampleTraceBase
538{
539public:
540        //enum { IDR = IDR_MEDIASAMPLETRACE };
541
542DECLARE_NO_REGISTRY() //DECLARE_REGISTRY_RESOURCEID(IDR)
543
544BEGIN_COM_MAP(CMediaSampleTrace)
545        COM_INTERFACE_ENTRY(IMediaSampleTrace)
546        //COM_INTERFACE_ENTRY(IProvideClassInfo2)
547        //COM_INTERFACE_ENTRY(IProvideClassInfo)
548END_COM_MAP()
549
550public:
551
552private:
553        mutable CRoCriticalSection m_DataCriticalSection;
554        UINT_PTR m_nFilterGraphIdentifier;
555        CStringW m_sFilterGraphName;
556        CPages m_Pages;
557        CPage m_Page;
558
559public:
560// CMediaSampleTrace
561        CMediaSampleTrace()
562        {
563                _Z4_THIS();
564        }
565        ~CMediaSampleTrace()
566        {
567                _Z4_THIS();
568                #pragma region Transfer Ownership
569                if(!m_Page.IsEmpty())
570                {
571                        CEvent RequestEvent, ResponseEvent;
572                        if(RequestEvent.Open(EVENT_ALL_ACCESS, FALSE, CString(CPages::GetFileMappingName()) + _T(".TransferRequest")))
573                        {
574                                ResponseEvent.Open(EVENT_ALL_ACCESS, FALSE, CString(CPages::GetFileMappingName()) + _T(".TransferResponse"));
575                                if(RequestEvent.Set())
576                                {
577                                        // NOTE: The event creator (UI) has some time to grap mapping handles and store a private copy
578                                        static const ULONG g_nTimeoutTime = 500; // 500 ms
579                                        if(ResponseEvent)
580                                        {
581                                                const DWORD nWaitResult = WaitForSingleObject(ResponseEvent, g_nTimeoutTime);
582                                                _Z5_WAITRESULT(nWaitResult);
583                                        } else
584                                                Sleep(g_nTimeoutTime);
585                                }
586                        }
587                }
588                #pragma endregion
589        }
590        VOID Initialize(ISpy* pSpy)
591        {
592                _A(pSpy);
593                CComBSTR sName;
594                __C(pSpy->get_FriendlyName(&sName));
595                const CComQIPtr<IFilterGraph2> pFilterGraph2 = pSpy;
596                _A(pFilterGraph2);
597                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
598                m_nFilterGraphIdentifier = (UINT_PTR) (IFilterGraph2*) pFilterGraph2;
599                m_sFilterGraphName = CStringW(sName);
600                m_Pages.Initialize((UINT64) m_nFilterGraphIdentifier, m_sFilterGraphName);
601        }
602        static CStringW GetFilterName(IUnknown* pBaseFilterUnknown)
603        {
604                CStringW sFilterName;
605                const CComQIPtr<IBaseFilter> pBaseFilter = pBaseFilterUnknown;
606                if(pBaseFilter)
607                        sFilterName = _FilterGraphHelper::GetFilterName(pBaseFilter);
608                return sFilterName;
609        }
610
611// IMediaSampleTrace
612        STDMETHOD(RegisterNewSegment)(IUnknown* pBaseFilterUnknown, const WCHAR* pszStreamName, LONGLONG nStartTime, LONGLONG nStopTime, DOUBLE fRate, const WCHAR* pszComment)
613        {
614                _Z5(atlTraceCOM, 5, _T("this 0x%p, pBaseFilterUnknown 0x%p, pszStreamName \"%s\", nStartTime %I64d\n"), this, pBaseFilterUnknown, CString(pszStreamName), nStartTime);
615                _ATLTRY
616                {
617                        PAGEITEM PageItem;
618                        PageItem.nFlags = PAGEITEMFLAG_NEWSEGMENT;
619                        PageItem.Data.NewSegment.nStartTime = nStartTime;
620                        PageItem.Data.NewSegment.nStopTime = nStopTime;
621                        PageItem.Data.NewSegment.fRate = fRate;
622                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
623                        m_Page.Register(m_Pages, (UINT_PTR) pBaseFilterUnknown, GetFilterName(pBaseFilterUnknown), pszStreamName, PageItem, pszComment);
624                }
625                _ATLCATCH(Exception)
626                {
627                        _C(Exception);
628                }
629                return S_OK;
630        }
631        STDMETHOD(RegisterMediaSample)(IUnknown* pBaseFilterUnknown, const WCHAR* pszStreamName, const BYTE* pnSamplePropertiesData, const WCHAR* pszComment)
632        {
633                _Z5(atlTraceCOM, 5, _T("this 0x%p, pBaseFilterUnknown 0x%p, pszStreamName \"%s\", pnSamplePropertiesData 0x%p\n"), this, pBaseFilterUnknown, CString(pszStreamName), pnSamplePropertiesData);
634                _ATLTRY
635                {
636                        __D(pnSamplePropertiesData, E_POINTER);
637                        PAGEITEM PageItem;
638                        PageItem.nFlags = PAGEITEMFLAG_MEDIASAMPLE;
639                        PageItem.Data.MediaSample.Properties = *((const AM_SAMPLE2_PROPERTIES*) pnSamplePropertiesData);
640                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
641                        m_Page.Register(m_Pages, (UINT_PTR) pBaseFilterUnknown, GetFilterName(pBaseFilterUnknown), pszStreamName, PageItem, pszComment);
642                }
643                _ATLCATCH(Exception)
644                {
645                        _C(Exception);
646                }
647                return S_OK;
648        }
649        STDMETHOD(RegisterEndOfStream)(IUnknown* pBaseFilterUnknown, const WCHAR* pszStreamName, const WCHAR* pszComment)
650        {
651                _Z5(atlTraceCOM, 5, _T("this 0x%p, pBaseFilterUnknown 0x%p, pszStreamName \"%s\"\n"), this, pBaseFilterUnknown, CString(pszStreamName));
652                _ATLTRY
653                {
654                        PAGEITEM PageItem;
655                        PageItem.nFlags = PAGEITEMFLAG_ENDOFSTREAM;
656                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
657                        m_Page.Register(m_Pages, (UINT_PTR) pBaseFilterUnknown, GetFilterName(pBaseFilterUnknown), pszStreamName, PageItem, pszComment);
658                }
659                _ATLCATCH(Exception)
660                {
661                        _C(Exception);
662                }
663                return S_OK;
664        }
665        STDMETHOD(RegisterComment)(IUnknown* pBaseFilterUnknown, const WCHAR* pszStreamName, const WCHAR* pszComment)
666        {
667                _Z5(atlTraceCOM, 5, _T("this 0x%p, pBaseFilterUnknown 0x%p, pszStreamName \"%s\", pszComment \"%s\"\n"), this, pBaseFilterUnknown, CString(pszStreamName), CString(pszComment));
668                _ATLTRY
669                {
670                        PAGEITEM PageItem;
671                        PageItem.nFlags = PAGEITEMFLAG_COMMENT;
672                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
673                        m_Page.Register(m_Pages, (UINT_PTR) pBaseFilterUnknown, GetFilterName(pBaseFilterUnknown), pszStreamName, PageItem, pszComment);
674                }
675                _ATLCATCH(Exception)
676                {
677                        _C(Exception);
678                }
679                return S_OK;
680        }
681};
682
683//OBJECT_ENTRY_AUTO(__uuidof(MediaSampleTrace), CMediaSampleTrace)
684
685////////////////////////////////////////////////////////////
686// CMediaSampleTracePropertySheet
687
688class CMediaSampleTracePropertySheet :
689        public CSizablePropertySheetT<CMediaSampleTracePropertySheet>,
690        public CMediaSampleTraceBase
691{
692public:
693
694BEGIN_MSG_MAP_EX(CMediaSampleTracePropertySheet)
695        CHAIN_MSG_MAP(CSizablePropertySheet)
696        MSG_WM_SYSCOMMAND(OnSysCommand)
697END_MSG_MAP()
698
699public:
700
701        ////////////////////////////////////////////////////////
702        // CMediaSamplePropertyPage
703
704        class CMediaSamplePropertyPage :
705                public CPropertyPageT<CMediaSamplePropertyPage>,
706                public CPropertyPageWithAcceleratorsT<CMediaSamplePropertyPage>,
707                public CDialogResize<CMediaSamplePropertyPage>
708        {
709                typedef CThreadT<CMediaSamplePropertyPage> CThread;
710
711        public:
712                enum { IDD = IDD_MEDIASAMPLETRACE_MEDIASAMPLE_PROPERTYPAGE };
713
714        BEGIN_MSG_MAP_EX(CMediaSamplePropertyPage)
715                CHAIN_MSG_MAP(CPropertyPage)
716                CHAIN_MSG_MAP(CPropertyPageWithAccelerators)
717                CHAIN_MSG_MAP(CDialogResize<CMediaSamplePropertyPage>)
718                MSG_WM_INITDIALOG(OnInitDialog)
719                MSG_WM_DESTROY(OnDestroy)
720                MSG_LVN_GETDISPINFO(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_LIST, OnListViewGetDispInfo)
721                MSG_LVN_GETINFOTIP(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_LIST, OnListViewGetInfoTip)
722                MSG_WM_CONTEXTMENU(OnContextMenu)
723                COMMAND_ID_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_REFRESH, OnRefresh)
724                COMMAND_ID_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_COPYTOCLIPBOARD, OnCopyToClipboard)
725                COMMAND_ID_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_SAVETOFILE, OnSaveToFile)
726                COMMAND_ID_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_RESETDATA, OnResetData)
727                COMMAND_ID_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_OPENFILTERGRAPHLIST, OnOpenFilterGraphList)
728                COMMAND_ID_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_OPENFILTERGRAPHPROPERTIES, OnOpenFilterGraphProperties)
729                REFLECT_NOTIFICATIONS()
730        END_MSG_MAP()
731
732        BEGIN_DLGRESIZE_MAP(CMediaSamplePropertyPage)
733                DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_INTRODUCTION, DLSZ_SIZE_X)
734                DLGRESIZE_CONTROL(IDD_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER, DLSZ_SIZE_X)
735                DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_LIST, DLSZ_SIZE_X | DLSZ_SIZE_Y)
736                DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_REFRESH, DLSZ_MOVE_Y)
737                DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_COPYTOCLIPBOARD, DLSZ_MOVE_Y)
738                DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_SAVETOFILE, DLSZ_MOVE_Y)
739        END_DLGRESIZE_MAP()
740
741        public:
742
743                ////////////////////////////////////////////////////
744                // CFilterDialog
745
746                class CFilterDialog :
747                        public CDialogImpl<CFilterDialog>,
748                        public CDialogResize<CFilterDialog>
749                {
750                public:
751                        enum { IDD = IDD_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER };
752
753                BEGIN_MSG_MAP_EX(CFilterDialog)
754                        //CHAIN_MSG_MAP(CFilterDialog)
755                        CHAIN_MSG_MAP(CDialogResize<CFilterDialog>)
756                        MSG_WM_INITDIALOG(OnInitDialog)
757                        COMMAND_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_PROCESS, CBN_SELENDOK, OnProcessComboBoxSelEndOk)
758                        COMMAND_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_FILTERGRAPH, CBN_SELENDOK, OnFilterGraphComboBoxSelEndOk)
759                        COMMAND_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_FILTER, CBN_SELENDOK, OnFilterComboBoxSelEndOk)
760                        COMMAND_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_STREAM, CBN_SELENDOK, OnStreamComboBoxSelEndOk)
761                        REFLECT_NOTIFICATIONS()
762                END_MSG_MAP()
763
764                BEGIN_DLGRESIZE_MAP(CFilterDialog)
765                        DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_PROCESS_TITLE, 0)
766                        DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_PROCESS, 0) //DLSZ_SIZE_X)
767                        DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_FILTERGRAPH_TITLE, 0)
768                        DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_FILTERGRAPH, DLSZ_SIZE_X)
769                        DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_FILTER_TITLE, 0)
770                        DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_FILTER, DLSZ_SIZE_X)
771                        DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_STREAM_TITLE, 0)
772                        DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_STREAM, DLSZ_SIZE_X)
773                END_DLGRESIZE_MAP()
774
775                public:
776
777                        ////////////////////////////////////////////////
778                        // CValueT
779
780                        template <typename CIdentifier>
781                        class CValueT
782                        {
783                        public:
784                                CIdentifier m_nIdentifier;
785                                CStringW m_sValue;
786
787                        public:
788                        // CValueT
789                                CValueT() :
790                                        m_nIdentifier(0)
791                                {
792                                }
793                                CValueT(CIdentifier nIdentifier, LPCWSTR pszValue = NULL) :
794                                        m_nIdentifier(nIdentifier),
795                                        m_sValue(pszValue)
796                                {
797                                }
798                        };
799
800                        typedef CValueT<UINT32> CProcessValue;
801                        typedef CValueT<UINT64> CFilterGraphValue;
802                        typedef CValueT<UINT64> CFilterValue;
803                        typedef CValueT<UINT> CStreamValue;
804
805                        class CProcessValueSortTraits :
806                                public CSimpleSortTraitsT<CProcessValue>
807                        {
808                        public:
809                        // CProcessValueSortTraits
810                                static INT_PTR CompareElements(const CProcessValue& Element1, const CProcessValue& Element2, PARAMETERARGUMENT)
811                                {
812                                        return (INT_PTR) (Element1.m_nIdentifier - Element2.m_nIdentifier);
813                                }
814                        };
815
816                        class CFilterGraphValueSortTraits :
817                                public CSimpleSortTraitsT<CFilterGraphValue>
818                        {
819                        public:
820                        // CFilterGraphValueSortTraits
821                                static INT_PTR CompareElements(const CFilterGraphValue& Element1, const CFilterGraphValue& Element2, PARAMETERARGUMENT)
822                                {
823                                        const INT nName = _wcsicmp(Element1.m_sValue, Element2.m_sValue);
824                                        if(nName)
825                                                return nName;
826                                        return (INT_PTR) (Element1.m_nIdentifier - Element2.m_nIdentifier);
827                                }
828                        };
829
830                        class CFilterValueSortTraits :
831                                public CSimpleSortTraitsT<CFilterValue>
832                        {
833                        public:
834                        // CFilterValueSortTraits
835                                static INT_PTR CompareElements(const CFilterValue& Element1, const CFilterValue& Element2, PARAMETERARGUMENT)
836                                {
837                                        const INT nName = _wcsicmp(Element1.m_sValue, Element2.m_sValue);
838                                        if(nName)
839                                                return nName;
840                                        return (INT_PTR) (Element1.m_nIdentifier - Element2.m_nIdentifier);
841                                }
842                        };
843
844                        class CStreamValueSortTraits :
845                                public CSimpleSortTraitsT<CStreamValue>
846                        {
847                        public:
848                        // CStreamValueSortTraits
849                                static INT_PTR CompareElements(const CStreamValue& Element1, const CStreamValue& Element2, PARAMETERARGUMENT)
850                                {
851                                        return _wcsicmp(Element1.m_sValue, Element2.m_sValue);
852                                }
853                        };
854
855                private:
856                        CMediaSamplePropertyPage& m_Owner;
857                        CRoComboBoxT<CProcessValue, CRoListControlDataTraitsT> m_ProcessComboBox;
858                        CRoComboBoxT<CFilterGraphValue, CRoListControlDataTraitsT> m_FilterGraphComboBox;
859                        CRoComboBoxT<CFilterValue, CRoListControlDataTraitsT> m_FilterComboBox;
860                        CRoComboBoxT<CStreamValue, CRoListControlDataTraitsT> m_StreamComboBox;
861                        CProcessValue* m_pProcessValue;
862                        CFilterGraphValue* m_pFilterGraphValue;
863                        CFilterValue* m_pFilterValue;
864                        CStreamValue* m_pStreamValue;
865
866                public:
867                // CFilterDialog
868                        CFilterDialog(CMediaSamplePropertyPage* pOwner) :
869                                m_Owner(*pOwner)
870                        {
871                        }
872                        VOID UpdateProcessComboBox()
873                        {
874                                m_ProcessComboBox.ResetContent();
875                                INT nItem = 0;
876                                _W(m_ProcessComboBox.InsertString(nItem++, _T("<All Processes>")) == 0);
877                                m_ProcessComboBox.SetCurSel(0);
878                                CRoArrayT<UINT32> IdentifierArray;
879                                CRoArrayT<CProcessValue> ValueArray;
880                                for(auto&& Item: m_Owner.m_Data.m_ItemArray)
881                                {
882                                        if(IdentifierArray.FindFirst(Item.m_Item.nProcessIdentifier))
883                                                continue;
884                                        IdentifierArray.Add(Item.m_Item.nProcessIdentifier);
885                                        ValueArray.Add(CProcessValue(Item.m_Item.nProcessIdentifier, AtlFormatStringW(L"%d", Item.m_Item.nProcessIdentifier)));
886                                }
887                                _SortHelper::QuickSort<CProcessValueSortTraits>(ValueArray);
888                                for(auto&& Value: ValueArray)
889                                        m_ProcessComboBox.InsertString(nItem++, Value.m_sValue, Value);
890                                if(ValueArray.GetCount() == 1)
891                                        m_ProcessComboBox.SetCurSel(1);
892                                const BOOL bEnabled = m_ProcessComboBox.GetCount() > 2;
893                                m_ProcessComboBox.GetWindow(GW_HWNDPREV).EnableWindow(bEnabled);
894                                m_ProcessComboBox.EnableWindow(bEnabled);
895                                OnProcessComboBoxSelEndOk();
896                                UpdateFilterGraphComboBox();
897                        }
898                        VOID UpdateFilterGraphComboBox()
899                        {
900                                m_FilterGraphComboBox.ResetContent();
901                                INT nItem = 0;
902                                _W(m_FilterGraphComboBox.InsertString(nItem++, _T("<All Filter Graphs>")) == 0);
903                                m_FilterGraphComboBox.SetCurSel(0);
904                                CRoArrayT<UINT64> IdentifierArray;
905                                CRoArrayT<CFilterGraphValue> ValueArray;
906                                for(auto&& Item: m_Owner.m_Data.m_ItemArray)
907                                {
908                                        if(m_pProcessValue && m_pProcessValue->m_nIdentifier != Item.m_Item.nProcessIdentifier)
909                                                continue;
910                                        if(IdentifierArray.FindFirst(Item.m_Item.nFilterGraphIdentifier))
911                                                continue;
912                                        IdentifierArray.Add(Item.m_Item.nFilterGraphIdentifier);
913                                        ValueArray.Add(CFilterGraphValue(Item.m_Item.nFilterGraphIdentifier, AtlFormatStringW(L"0x%p %ls", (UINT_PTR) Item.m_Item.nFilterGraphIdentifier, Item.m_Item.pszFilterGraphName)));
914                                }
915                                _SortHelper::QuickSort<CFilterGraphValueSortTraits>(ValueArray);
916                                for(auto&& Value: ValueArray)
917                                        m_FilterGraphComboBox.InsertString(nItem++, Value.m_sValue, Value);
918                                if(ValueArray.GetCount() == 1)
919                                        m_FilterGraphComboBox.SetCurSel(1);
920                                const BOOL bEnabled = m_FilterGraphComboBox.GetCount() > 2;
921                                m_FilterGraphComboBox.GetWindow(GW_HWNDPREV).EnableWindow(bEnabled);
922                                m_FilterGraphComboBox.EnableWindow(bEnabled);
923                                OnFilterGraphComboBoxSelEndOk();
924                                UpdateFilterComboBox();
925                        }
926                        VOID UpdateFilterComboBox()
927                        {
928                                m_FilterComboBox.ResetContent();
929                                INT nItem = 0;
930                                _W(m_FilterComboBox.InsertString(nItem++, _T("<All Filters>")) == 0);
931                                m_FilterComboBox.SetCurSel(0);
932                                CRoArrayT<UINT64> IdentifierArray;
933                                CRoArrayT<CFilterValue> ValueArray;
934                                for(auto&& Item: m_Owner.m_Data.m_ItemArray)
935                                {
936                                        if(m_pProcessValue && m_pProcessValue->m_nIdentifier != Item.m_Item.nProcessIdentifier)
937                                                continue;
938                                        if(m_pFilterGraphValue && m_pFilterGraphValue->m_nIdentifier != Item.m_Item.nFilterGraphIdentifier)
939                                                continue;
940                                        if(IdentifierArray.FindFirst(Item.m_PageItem.nFilterIdentifier))
941                                                continue;
942                                        IdentifierArray.Add(Item.m_PageItem.nFilterIdentifier);
943                                        ValueArray.Add(CFilterValue(Item.m_PageItem.nFilterIdentifier, AtlFormatStringW(L"0x%p %ls", (UINT_PTR) Item.m_PageItem.nFilterIdentifier, Item.m_PageItem.pszFilterName)));
944                                }
945                                _SortHelper::QuickSort<CFilterValueSortTraits>(ValueArray);
946                                for(auto&& Value: ValueArray)
947                                        m_FilterComboBox.InsertString(nItem++, Value.m_sValue, Value);
948                                if(ValueArray.GetCount() == 1)
949                                        m_FilterComboBox.SetCurSel(1);
950                                const BOOL bEnabled = m_FilterComboBox.GetCount() > 2;
951                                m_FilterComboBox.GetWindow(GW_HWNDPREV).EnableWindow(bEnabled);
952                                m_FilterComboBox.EnableWindow(bEnabled);
953                                OnFilterComboBoxSelEndOk();
954                                UpdateStreamComboBox();
955                        }
956                        VOID UpdateStreamComboBox()
957                        {
958                                m_StreamComboBox.ResetContent();
959                                INT nItem = 0;
960                                _W(m_StreamComboBox.InsertString(nItem++, _T("<All Streams>")) == 0);
961                                m_StreamComboBox.SetCurSel(0);
962                                CRoArrayT<CStringW> IdentifierArray;
963                                CRoArrayT<CStreamValue> ValueArray;
964                                for(auto&& Item: m_Owner.m_Data.m_ItemArray)
965                                {
966                                        if(m_pProcessValue && m_pProcessValue->m_nIdentifier != Item.m_Item.nProcessIdentifier)
967                                                continue;
968                                        if(m_pFilterGraphValue && m_pFilterGraphValue->m_nIdentifier != Item.m_Item.nFilterGraphIdentifier)
969                                                continue;
970                                        if(m_pFilterValue && m_pFilterValue->m_nIdentifier != Item.m_PageItem.nFilterIdentifier)
971                                                continue;
972                                        if(!*Item.m_PageItem.pszStreamName)
973                                                continue;
974                                        if(IdentifierArray.FindFirst(Item.m_PageItem.pszStreamName))
975                                                continue;
976                                        IdentifierArray.Add(Item.m_PageItem.pszStreamName);
977                                        ValueArray.Add(CStreamValue(1, Item.m_PageItem.pszStreamName));
978                                }
979                                _SortHelper::QuickSort<CStreamValueSortTraits>(ValueArray);
980                                for(auto&& Value: ValueArray)
981                                        m_StreamComboBox.InsertString(nItem++, Value.m_sValue, Value);
982                                if(ValueArray.GetCount() == 1)
983                                        m_StreamComboBox.SetCurSel(1);
984                                const BOOL bEnabled = m_StreamComboBox.GetCount() > 2;
985                                m_StreamComboBox.GetWindow(GW_HWNDPREV).EnableWindow(bEnabled);
986                                m_StreamComboBox.EnableWindow(bEnabled);
987                                OnStreamComboBoxSelEndOk();
988                        }
989                        VOID Reset()
990                        {
991                                m_pProcessValue = NULL;
992                                UpdateProcessComboBox();
993                        }
994                        BOOL IsVisible(const CData::CItem& Item) const
995                        {
996                                if(m_pProcessValue && Item.m_Item.nProcessIdentifier != m_pProcessValue->m_nIdentifier)
997                                        return FALSE;
998                                if(m_pFilterGraphValue && Item.m_Item.nFilterGraphIdentifier != m_pFilterGraphValue->m_nIdentifier)
999                                        return FALSE;
1000                                if(m_pFilterValue && Item.m_PageItem.nFilterIdentifier != m_pFilterValue->m_nIdentifier)
1001                                        return FALSE;
1002                                if(m_pStreamValue && wcscmp(Item.m_PageItem.pszStreamName, m_pStreamValue->m_sValue) != 0)
1003                                        return FALSE;
1004                                return TRUE;
1005                        }
1006
1007                // Window Message Handler
1008                        LRESULT OnInitDialog(HWND, LPARAM)
1009                        {
1010                                m_ProcessComboBox = GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_PROCESS);
1011                                m_FilterGraphComboBox = GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_FILTERGRAPH);
1012                                m_FilterComboBox = GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_FILTER);
1013                                m_StreamComboBox = GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_STREAM);
1014                                m_pProcessValue = NULL;
1015                                m_pFilterGraphValue = NULL;
1016                                m_pFilterValue = NULL;
1017                                m_pStreamValue = NULL;
1018                                DlgResize_Init(FALSE);
1019                                return TRUE;
1020                        }
1021                        LRESULT OnProcessComboBoxSelEndOk(UINT = 0, INT = 0, HWND = NULL)
1022                        {
1023                                CProcessValue& ProcessValue = m_ProcessComboBox.GetItemData(m_ProcessComboBox.GetCurSel());
1024                                m_pProcessValue = ProcessValue.m_nIdentifier ? &ProcessValue : NULL;
1025                                UpdateFilterGraphComboBox();
1026                                m_Owner.HandleFilterUpdate();
1027                                return 0;
1028                        }
1029                        LRESULT OnFilterGraphComboBoxSelEndOk(UINT = 0, INT = 0, HWND = NULL)
1030                        {
1031                                CFilterGraphValue& FilterGraphValue = m_FilterGraphComboBox.GetItemData(m_FilterGraphComboBox.GetCurSel());
1032                                m_pFilterGraphValue = FilterGraphValue.m_nIdentifier ? &FilterGraphValue : NULL;
1033                                UpdateFilterComboBox();
1034                                m_Owner.HandleFilterUpdate();
1035                                return 0;
1036                        }
1037                        LRESULT OnFilterComboBoxSelEndOk(UINT = 0, INT = 0, HWND = NULL)
1038                        {
1039                                CFilterValue& FilterValue = m_FilterComboBox.GetItemData(m_FilterComboBox.GetCurSel());
1040                                m_pFilterValue = FilterValue.m_nIdentifier ? &FilterValue : NULL;
1041                                UpdateStreamComboBox();
1042                                m_Owner.HandleFilterUpdate();
1043                                return 0;
1044                        }
1045                        LRESULT OnStreamComboBoxSelEndOk(UINT = 0, INT = 0, HWND = NULL)
1046                        {
1047                                CStreamValue& StreamValue = m_StreamComboBox.GetItemData(m_StreamComboBox.GetCurSel());
1048                                m_pStreamValue = !StreamValue.m_sValue.IsEmpty() ? &StreamValue : NULL;
1049                                m_Owner.HandleFilterUpdate();
1050                                return 0;
1051                        }
1052                };
1053
1054        private:
1055                CMediaSampleTracePropertySheet& m_PropertySheet;
1056                CRoHyperStatic m_IntroductionStatic;
1057                CRoListViewT<CData::CItem, CRoListControlDataTraitsT> m_ListView;
1058                CRoHyperStatic m_RefreshStatic;
1059                CRoHyperStatic m_CopyToClipboardStatic;
1060                CRoHyperStatic m_SaveToFileStatic;
1061                CFilterDialog m_FilterDialog;
1062                CRoMapT<INT, BOOL> m_ChangeMap;
1063                CData m_Data;
1064                CObjectPtr<CThread> m_pThread;
1065                CHandleMap m_HandleMap;
1066
1067                DWORD ThreadProc(CThread*, CEvent& InitializationEvent, CEvent& TerminationEvent)
1068                {
1069                        CMultiThreadedApartment Apartment;
1070                        CEvent RequestEvent, ResponseEvent;
1071                        _W(RequestEvent.Create(NULL, FALSE, FALSE, CString(CPages::GetFileMappingName()) + _T(".TransferRequest")));
1072                        _W(ResponseEvent.Create(NULL, FALSE, FALSE, CString(CPages::GetFileMappingName()) + _T(".TransferResponse")));
1073                        _W(InitializationEvent.Set());
1074                        if(!RequestEvent || !ResponseEvent)
1075                                return 0;
1076                        CStackPointer StackPointer;
1077                        const HANDLE phObjects[] = { TerminationEvent, RequestEvent };
1078                        for(; ; )
1079                        {
1080                                _A(StackPointer.Check()); StackPointer;
1081                                const DWORD nWaitResult = WaitForMultipleObjects(DIM(phObjects), phObjects, FALSE, INFINITE);
1082                                _Z4_WAITRESULT(nWaitResult);
1083                                _A(nWaitResult - WAIT_OBJECT_0 < DIM(phObjects));
1084                                if(nWaitResult != WAIT_OBJECT_0 + 1) // RequestEvent
1085                                        break;
1086                                CPages Pages;
1087                                if(Pages.Initialize())
1088                                        Pages.GetData(m_Data, &m_HandleMap);
1089                                _W(ResponseEvent.Set());
1090                        }
1091                        return 0;
1092                }
1093
1094        public:
1095        // CMediaSamplePropertyPage
1096                CMediaSamplePropertyPage(CMediaSampleTracePropertySheet* pPropertySheet) :
1097                        m_PropertySheet(*pPropertySheet),
1098                        m_FilterDialog(this)
1099                {
1100                }
1101                VOID UpdateControls()
1102                {
1103                }
1104                VOID UpdateListView()
1105                {
1106                        CWindowRedraw ListViewRedraw(m_ListView);
1107                        m_ListView.DeleteAllItems();
1108                        m_Data.Initialize();
1109                        CPages Pages;
1110                        if(Pages.Initialize())
1111                        {
1112                                Pages.GetData(m_Data, &m_HandleMap);
1113                                m_Data.Sort();
1114                                INT nItem = 0;
1115                                for(auto&& Item: m_Data.m_ItemArray)
1116                                        m_ListView.InsertItem(nItem++, Item);
1117                        }
1118                        m_FilterDialog.Reset();
1119                }
1120                static CString FormatTime(UINT64 nTime)
1121                {
1122                        SYSTEMTIME Time;
1123                        FileTimeToSystemTime(&reinterpret_cast<const FILETIME&>(nTime), &Time);
1124                        return AtlFormatString(_T("%02d:%02d:%02d.%03d"), Time.wHour, Time.wMinute, Time.wSecond, Time.wMilliseconds);
1125                }
1126                CStringA CreateText()
1127                {
1128                        CString sText;
1129                        #pragma region Header
1130                        LPCTSTR g_ppszHeader[] = 
1131                        {
1132                                _T("Time"),
1133                                _T("Process Identifier"),
1134                                _T("Thread Identifier"),
1135                                _T("Filter Graph Identifier"),
1136                                _T("Filter Graph Name"),
1137                                _T("Filter Identifier"),
1138                                _T("Filter Name"),
1139                                _T("Stream"),
1140                                _T("Type"),
1141                                _T("Media Sample Flags"),
1142                                _T("Start Time"),
1143                                _T("Stop Time"),
1144                                _T("Length Time"),
1145                                _T("Data Size"),
1146                                _T("Comment"),
1147                        };
1148                        sText += _StringHelper::Join(g_ppszHeader, _T("\t")) + _T("\r\n");
1149                        #pragma endregion
1150                        for(INT nItem = 0; nItem < m_ListView.GetItemCount(); nItem++)
1151                        {
1152                                const CData::CItem& Item = m_ListView.GetItemData(nItem);
1153                                CRoArrayT<CString> Array;
1154                                Array.Add(FormatTime(Item.m_PageItem.nTime));
1155                                Array.Add(AtlFormatString(_T("%d"), Item.m_Item.nProcessIdentifier));
1156                                Array.Add(AtlFormatString(_T("%d"), Item.m_PageItem.nThreadIdentifier));
1157                                Array.Add(AtlFormatString(_T("0x%p"), Item.m_Item.nFilterGraphIdentifier));
1158                                Array.Add(CString(Item.m_Item.pszFilterGraphName));
1159                                Array.Add(AtlFormatString(_T("0x%p"), Item.m_PageItem.nFilterIdentifier));
1160                                Array.Add(CString(Item.m_PageItem.pszFilterName));
1161                                Array.Add(CString(Item.m_PageItem.pszStreamName));
1162                                Array.Add(Item.FormatType());
1163                                switch(Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK)
1164                                {
1165                                case PAGEITEMFLAG_NEWSEGMENT:
1166                                        Array.Add(_T(""));
1167                                        Array.Add(AtlFormatString(_T("%I64d"), Item.m_PageItem.Data.NewSegment.nStartTime));
1168                                        if(Item.m_PageItem.Data.NewSegment.nStopTime < LLONG_MAX)
1169                                                Array.Add(AtlFormatString(_T("%I64d"), Item.m_PageItem.Data.NewSegment.nStopTime));
1170                                        //Item.m_PageItem.Data.NewSegment.fRate
1171                                        break;
1172                                case PAGEITEMFLAG_MEDIASAMPLE:
1173                                        Array.Add(_FilterGraphHelper::FormatSampleFlags(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags));
1174                                        if(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags & AM_SAMPLE_TIMEVALID)
1175                                        {
1176                                                Array.Add(AtlFormatString(_T("%I64d"), Item.m_PageItem.Data.MediaSample.Properties.tStart));
1177                                                if(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags & AM_SAMPLE_STOPVALID)
1178                                                {
1179                                                        Array.Add(AtlFormatString(_T("%I64d"), Item.m_PageItem.Data.MediaSample.Properties.tStop));
1180                                                        Array.Add(AtlFormatString(_T("%I64d"), Item.m_PageItem.Data.MediaSample.Properties.tStop - Item.m_PageItem.Data.MediaSample.Properties.tStart));
1181                                                }
1182                                        }
1183                                        while(Array.GetCount() < 13)
1184                                                Array.Add(_T(""));
1185                                        Array.Add(AtlFormatString(_T("%d"), Item.m_PageItem.Data.MediaSample.Properties.lActual));
1186                                        break;
1187                                case PAGEITEMFLAG_ENDOFSTREAM:
1188                                case PAGEITEMFLAG_COMMENT:
1189                                        break;
1190                                default:
1191                                        _A(FALSE);
1192                                }
1193                                if(*Item.m_PageItem.pszComment)
1194                                {
1195                                        while(Array.GetCount() < 14)
1196                                                Array.Add(_T(""));
1197                                        Array.Add(CString(Item.m_PageItem.pszComment));
1198                                }
1199                                sText += _StringHelper::Join(Array, _T("\t"));
1200                                sText += _T("\r\n");
1201                        }
1202                        return CStringA(sText);
1203                }
1204                VOID HandleFilterUpdate()
1205                {
1206                        CWindowRedraw ListViewRedraw(m_ListView);
1207                        m_ListView.DeleteAllItems();
1208                        INT nItem = 0;
1209                        for(auto&& Item: m_Data.m_ItemArray)
1210                                if(m_FilterDialog.IsVisible(Item))
1211                                        m_ListView.InsertItem(nItem++, Item);
1212                        // SUGG: Preserve selection
1213                }
1214
1215        // Window Message Handler
1216                LRESULT OnInitDialog(HWND, LPARAM)
1217                {
1218                        _ATLTRY
1219                        {
1220                                CWaitCursor WaitCursor;
1221                                _W(m_IntroductionStatic.SubclassWindow(GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_INTRODUCTION)));
1222                                m_ListView.Initialize(GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_LIST));
1223                                _W(m_RefreshStatic.SubclassWindow(GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_REFRESH)));
1224                                m_RefreshStatic.SetExtendedStyle(CRoHyperStatic::CS_ANCHORCLICKCOMMAND);
1225                                _W(m_CopyToClipboardStatic.SubclassWindow(GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_COPYTOCLIPBOARD)));
1226                                m_CopyToClipboardStatic.SetExtendedStyle(CRoHyperStatic::CS_ANCHORCLICKCOMMAND);
1227                                _W(m_SaveToFileStatic.SubclassWindow(GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_SAVETOFILE)));
1228                                m_SaveToFileStatic.SetExtendedStyle(CRoHyperStatic::CS_ANCHORCLICKCOMMAND);
1229                                CRoHyperStatic::ArrangeHorizontally(&m_RefreshStatic, &m_CopyToClipboardStatic, &m_SaveToFileStatic, NULL);
1230                                #pragma region Filter
1231                                __E(m_FilterDialog.Create(m_hWnd, (LPARAM) this));
1232                                {
1233                                        CRect FilterPosition, Position;
1234                                        _W(m_FilterDialog.GetWindowRect(FilterPosition));
1235                                        m_FilterDialog.SetDlgCtrlID(CFilterDialog::IDD);
1236                                        const CSize FilterExtent = FilterPosition.Size();
1237                                        _W(m_ListView.GetWindowRect(Position));
1238                                        _W(ScreenToClient(Position));
1239                                        const LONG nSpacing = Position.left;
1240                                        FilterPosition.left = Position.left;
1241                                        FilterPosition.right = Position.right;
1242                                        FilterPosition.top = Position.top;
1243                                        FilterPosition.bottom = FilterPosition.top + FilterExtent.cy;
1244                                        Position.top = FilterPosition.bottom + nSpacing;
1245                                        _W(m_FilterDialog.SetWindowPos(m_IntroductionStatic, FilterPosition, SWP_NOACTIVATE | SWP_SHOWWINDOW));
1246                                        _W(m_ListView.MoveWindow(Position));
1247                                }
1248                                #pragma endregion
1249                                DlgResize_Init(FALSE, FALSE);
1250                                UpdateListView();
1251                                m_ChangeMap.RemoveAll();
1252                                UpdateControls();
1253                                #pragma region Default Property Sheet Size
1254                                CRect Position;
1255                                _W(m_PropertySheet.GetWindowRect(Position));
1256                                Position.InflateRect(6 * Position.Width() / 8, 5 * Position.Width() / 8);
1257                                CSize ScreenExtent(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
1258                                ScreenExtent.cx -= ScreenExtent.cx / 8;
1259                                ScreenExtent.cy -= ScreenExtent.cy / 8;
1260                                if(Position.Width() > ScreenExtent.cx)
1261                                        Position.right = Position.left + ScreenExtent.cx;
1262                                if(Position.Height() > ScreenExtent.cy)
1263                                        Position.bottom = Position.top + ScreenExtent.cy;
1264                                _W(m_PropertySheet.MoveWindow(Position));
1265                                _W(m_PropertySheet.CenterWindow());
1266                                #pragma endregion
1267                                m_pThread.Construct()->Initialize(this, &CMediaSamplePropertyPage::ThreadProc);
1268                        }
1269                        _ATLCATCHALL()
1270                        {
1271                                for(CWindow Window = GetWindow(GW_CHILD); Window.IsWindow(); Window = Window.GetWindow(GW_HWNDNEXT))
1272                                        Window.EnableWindow(FALSE);
1273                                _ATLRETHROW;
1274                        }
1275                        return TRUE;
1276                }
1277                LRESULT OnDestroy()
1278                {
1279                        CWaitCursor WaitCursor;
1280                        m_pThread.Release();
1281                        return 0;
1282                }
1283                LRESULT OnTranslateAccelerator(MSG* pMessage)
1284                {
1285                        return TranslateAccelerator(m_hWnd, m_hAccelerators, pMessage) ? PSNRET_MESSAGEHANDLED : PSNRET_NOERROR;
1286                }
1287                LRESULT OnListViewGetDispInfo(NMLVDISPINFO* pHeader)
1288                {
1289                        const CData::CItem& Item = m_ListView.DataFromParameter(pHeader->item.lParam);
1290                        if(pHeader->item.mask & LVIF_TEXT)
1291                        {
1292                                CString& sTextBuffer = m_ListView.GetTextBufferString(TRUE);
1293                                switch(pHeader->item.iSubItem)
1294                                {
1295                                case 1: // Process
1296                                        sTextBuffer = AtlFormatString(_T("%d"), (UINT_PTR) Item.m_Item.nProcessIdentifier);
1297                                        break;
1298                                case 2: // Thread
1299                                        sTextBuffer = AtlFormatString(_T("%d"), (UINT_PTR) Item.m_PageItem.nThreadIdentifier);
1300                                        break;
1301                                case 3: // Filter Graph
1302                                        sTextBuffer = AtlFormatString(_T("0x%p %ls"), (UINT_PTR) Item.m_Item.nFilterGraphIdentifier, Item.m_Item.pszFilterGraphName);
1303                                        break;
1304                                case 4: // Filter
1305                                        sTextBuffer = AtlFormatString(_T("0x%p %ls"), (UINT_PTR) Item.m_PageItem.nFilterIdentifier, Item.m_PageItem.pszFilterName);
1306                                        break;
1307                                case 5: // Stream
1308                                        sTextBuffer = AtlFormatString(_T("%ls"), Item.m_PageItem.pszStreamName);
1309                                        break;
1310                                case 6: // Type
1311                                        sTextBuffer = Item.FormatType();
1312                                        break;
1313                                case 7: // Flags
1314                                        if((Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK) == PAGEITEMFLAG_MEDIASAMPLE)
1315                                                sTextBuffer = _FilterGraphHelper::FormatSampleFlags(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags);
1316                                        break;
1317                                case 8: // Start Time
1318                                        if((Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK) == PAGEITEMFLAG_NEWSEGMENT)
1319                                        {
1320                                                sTextBuffer = _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.NewSegment.nStartTime);
1321                                        } else
1322                                        if((Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK) == PAGEITEMFLAG_MEDIASAMPLE)
1323                                        {
1324                                                if(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags & AM_SAMPLE_TIMEVALID)
1325                                                        sTextBuffer = _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.MediaSample.Properties.tStart);
1326                                        }
1327                                        break;
1328                                case 9: // Stop Time
1329                                        if((Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK) == PAGEITEMFLAG_NEWSEGMENT)
1330                                        {
1331                                                if(Item.m_PageItem.Data.NewSegment.nStopTime < LLONG_MAX)
1332                                                        sTextBuffer = _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.NewSegment.nStopTime);
1333                                        } else
1334                                        if((Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK) == PAGEITEMFLAG_MEDIASAMPLE)
1335                                        {
1336                                                if((Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags & (AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID)) == (AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID))
1337                                                        sTextBuffer = _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.MediaSample.Properties.tStop);
1338                                        }
1339                                        break;
1340                                case 10: // Comment
1341                                        sTextBuffer = CString(Item.m_PageItem.pszComment);
1342                                        break;
1343                                default: // Time
1344                                        sTextBuffer = FormatTime(Item.m_PageItem.nTime);
1345                                }
1346                                pHeader->item.pszText = m_ListView.GetTextBuffer();
1347                                pHeader->item.mask |= LVIF_DI_SETITEM;
1348                        }
1349                        return 0;
1350                }
1351                LRESULT OnListViewGetInfoTip(NMLVGETINFOTIP* pHeader)
1352                {
1353                        const CData::CItem& Item = m_ListView.GetItemData(pHeader->iItem);
1354                        CString& sTextBuffer = m_ListView.GetTextBufferString(TRUE);
1355                        sTextBuffer.AppendFormat(_T("Time: %s\r\n"), FormatTime(Item.m_PageItem.nTime));
1356                        sTextBuffer.AppendFormat(_T("Process: %d\r\n"), (UINT_PTR) Item.m_Item.nProcessIdentifier);
1357                        sTextBuffer.AppendFormat(_T("Thread: %d\r\n"), (UINT_PTR) Item.m_PageItem.nThreadIdentifier);
1358                        sTextBuffer.AppendFormat(_T("Filter Graph: 0x%p %ls\r\n"), (UINT_PTR) Item.m_Item.nFilterGraphIdentifier, Item.m_Item.pszFilterGraphName);
1359                        sTextBuffer.AppendFormat(_T("Filter: 0x%p %ls\r\n"), (UINT_PTR) Item.m_PageItem.nFilterIdentifier, Item.m_PageItem.pszFilterName);
1360                        sTextBuffer.AppendFormat(_T("Stream: %ls\r\n"), Item.m_PageItem.pszStreamName);
1361                        sTextBuffer.AppendFormat(_T("Type: %s\r\n"), Item.FormatType());
1362                        switch(Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK)
1363                        {
1364                        case PAGEITEMFLAG_NEWSEGMENT:
1365                                sTextBuffer.AppendFormat(_T("Start Time: %s\r\n"), _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.NewSegment.nStartTime));
1366                                if(Item.m_PageItem.Data.NewSegment.nStopTime < LLONG_MAX)
1367                                        sTextBuffer.AppendFormat(_T("Stop Time: %s\r\n"), _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.NewSegment.nStopTime));
1368                                sTextBuffer.AppendFormat(_T("Rate: %.3f\r\n"), Item.m_PageItem.Data.NewSegment.fRate);
1369                                break;
1370                        case PAGEITEMFLAG_MEDIASAMPLE:
1371                                sTextBuffer.AppendFormat(_T("Sample Flags: %s\r\n"), _FilterGraphHelper::FormatSampleFlags(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags));
1372                                if(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags & AM_SAMPLE_TIMEVALID)
1373                                {
1374                                        sTextBuffer.AppendFormat(_T("Start Time: %s\r\n"), _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.MediaSample.Properties.tStart));
1375                                        if(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags & AM_SAMPLE_STOPVALID)
1376                                        {
1377                                                sTextBuffer.AppendFormat(_T("Stop Time: %s\r\n"), _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.MediaSample.Properties.tStop));
1378                                                sTextBuffer.AppendFormat(_T("Length Time: %s\r\n"), _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.MediaSample.Properties.tStop - Item.m_PageItem.Data.MediaSample.Properties.tStart));
1379                                        }
1380                                }
1381                                sTextBuffer.AppendFormat(_T("Data Size: %s\r\n"), _StringHelper::FormatNumber(Item.m_PageItem.Data.MediaSample.Properties.lActual));
1382                                break;
1383                        case PAGEITEMFLAG_ENDOFSTREAM:
1384                        case PAGEITEMFLAG_COMMENT:
1385                                break;
1386                        default:
1387                                _A(FALSE);
1388                        }
1389                        if(*Item.m_PageItem.pszComment)
1390                                sTextBuffer.AppendFormat(_T("\r\n") _T("%ls\r\n"), Item.m_PageItem.pszComment);
1391                        sTextBuffer.TrimRight(_T("\t\n\r ."));
1392                        #pragma region Clipboard Copy
1393                        if(GetKeyState(VK_CONTROL) < 0 && GetKeyState(VK_SHIFT) < 0)
1394                                _ATLTRY
1395                                {
1396                                        SetClipboardText(m_hWnd, sTextBuffer);
1397                                        MessageBeep(MB_OK);
1398                                }
1399                                _ATLCATCHALL()
1400                                {
1401                                        _Z_EXCEPTION();
1402                                        MessageBeep(MB_ICONERROR);
1403                                }
1404                        #pragma endregion
1405                        _tcsncpy_s(pHeader->pszText, pHeader->cchTextMax, m_ListView.GetTextBuffer(), _TRUNCATE);
1406                        return 0;
1407                }
1408                LRESULT OnContextMenu(CWindow, CPoint Position)
1409                {
1410                        CMenu ContainerMenu = AtlLoadMenu(IDD);
1411                        CMenuHandle Menu = ContainerMenu.GetSubMenu(0);
1412                        Menu.TrackPopupMenu(TPM_RIGHTBUTTON | TPM_LEFTALIGN | TPM_TOPALIGN, Position.x, Position.y, m_hWnd); 
1413                        return 0;
1414                }
1415                LRESULT OnRefresh(UINT, INT, HWND)
1416                {
1417                        CWaitCursor WaitCursor;
1418                        UpdateListView();
1419                        return 0;
1420                }
1421                LRESULT OnCopyToClipboard(UINT, INT, HWND)
1422                {
1423                        CWaitCursor WaitCursor;
1424                        SetClipboardText(m_hWnd, CreateText());
1425                        MessageBeep(MB_OK);
1426                        return 0;
1427                }
1428                LRESULT OnSaveToFile(UINT, INT, HWND)
1429                {
1430                        static const COMDLG_FILTERSPEC g_pFilter[] = 
1431                        {
1432                                { _T("TSV Files"), _T("*.tsv") },
1433                                { _T("TSV Files, Bzip2 Compressed"), _T("*.tsv.bz2") },
1434                                { _T("All Files"), _T("*.*") },
1435                        };
1436                        CPath sPath = _CommonDialogHelper::QuerySavePath(m_hWnd, g_pFilter, _T("tsv"), _T("Media Sample Trace.tsv"));
1437                        if(!_tcslen(sPath))
1438                                return 0;
1439                        CWaitCursor WaitCursor;
1440                        const CStringA sText = CreateText();
1441                        LPCTSTR pszExtension = FindExtension(sPath);
1442                        CAtlFile File;
1443                        __C(File.Create(sPath, GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS));
1444                        _ATLTRY
1445                        {
1446                                if(_tcsicmp(pszExtension, _T(".bz2")) == 0)
1447                                {
1448                                        CLocalObjectPtr<CBzip2Item> pItem;
1449                                        pItem->SetRawData((const BYTE*) (LPCSTR) sText, sText.GetLength());
1450                                        CHeapPtr<BYTE> pnData;
1451                                        SIZE_T nDataSize;
1452                                        pItem->GetData(pnData, nDataSize);
1453                                        __C(File.Write(pnData, (DWORD) nDataSize));
1454                                } else
1455                                {
1456                                        __C(File.Write(sText, sText.GetLength() * sizeof (CHAR)));
1457                                }
1458                        }
1459                        _ATLCATCHALL()
1460                        {
1461                                File.Close();
1462                                DeleteFile(sPath);
1463                                _ATLRETHROW;
1464                        }
1465                        return 0;
1466                }
1467                LRESULT OnResetData(UINT, INT, HWND)
1468                {
1469                        CWaitCursor WaitCursor;
1470                        m_HandleMap.RemoveAll();
1471                        CPages Pages;
1472                        if(Pages.Initialize())
1473                                Pages.ResetData();
1474                        UpdateListView();
1475                        return 0;
1476                }
1477                LRESULT OnOpenFilterGraphList(UINT, INT, HWND)
1478                {
1479                        CLocalObjectPtr<CFilterGraphHelper> pFilterGraphHelper;
1480                        pFilterGraphHelper->DoFilterGraphListModal((LONG) (LONG_PTR) m_hWnd);
1481                        return 0;
1482                }
1483                LRESULT OnOpenFilterGraphProperties(UINT, INT, HWND)
1484                {
1485                        if(m_ListView.GetSelectedCount() == 1)
1486                        {
1487                                const INT nItem = m_ListView.GetNextItem(-1, LVNI_SELECTED);
1488                                _A(nItem >= 0);
1489                                CData::CItem& Item = m_ListView.GetItemData(nItem);
1490                                const LONG nProcessIdentifier = Item.m_Item.nProcessIdentifier;
1491                                CComPtr<IRunningObjectTable> pRunningObjectTable;
1492                                __C(GetRunningObjectTable(0, &pRunningObjectTable));
1493                                CRoMapT<CStringW, CFilterGraphListPropertySheet::CListPropertyPage::CItem> ItemMap;
1494                                CFilterGraphListPropertySheet::CListPropertyPage::EnumerateItems(pRunningObjectTable, ItemMap, &nProcessIdentifier);
1495                                for(auto&& GraphItem: ItemMap.GetValues())
1496                                {
1497                                        if(abs((LONG_PTR) (GraphItem.m_nInstance - Item.m_Item.nFilterGraphIdentifier)) < 0x0100)
1498                                                if(GraphItem.FilterGraphNeeded(pRunningObjectTable))
1499                                                {
1500                                                        CLocalObjectPtr<CFilterGraphHelper> pFilterGraphHelper;
1501                                                        pFilterGraphHelper->SetFilterGraph(GraphItem.m_pFilterGraph);
1502                                                        _V(pFilterGraphHelper->DoPropertyFrameModal((LONG) (LONG_PTR) m_hWnd));
1503                                                        return 0;
1504                                                }
1505                                }
1506                        }
1507                        _W(PostMessage(WM_COMMAND, IDC_MEDIASAMPLETRACE_MEDIASAMPLE_OPENFILTERGRAPHLIST));
1508                        return 0;
1509                }
1510        };
1511
1512private:
1513        CMediaSamplePropertyPage m_MediaSamplePropertyPage;
1514
1515public:
1516// CMediaSampleTracePropertySheet
1517        CMediaSampleTracePropertySheet() :
1518                CSizablePropertySheetT<CMediaSampleTracePropertySheet>(IDS_MEDIASAMPLETRACE_MEDIASAMPLE_PROPERTYSHEETCAPTION),
1519                m_MediaSamplePropertyPage(this)
1520        {
1521                AddPage(m_MediaSamplePropertyPage);
1522        }
1523        BOOL SetInitialPosition()
1524        {
1525                if(!__super::SetInitialPosition())
1526                        return FALSE;
1527                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_DEFAULTCOLOR, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)), TRUE);
1528                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_DEFAULTCOLOR, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)), FALSE);
1529                CAboutDialog::UpdateCaption(*this);
1530                #pragma region System Menu
1531                CMenuHandle Menu = GetSystemMenu(FALSE);
1532                _W(Menu.AppendMenu(MF_SEPARATOR));
1533                _W(Menu.AppendMenu(MF_STRING, ID_APP_ABOUT, _T("&About...")));
1534                #pragma endregion
1535                return TRUE;
1536        }
1537
1538// Window Message Handler
1539        LRESULT OnSysCommand(UINT nCommand, CPoint)
1540        {
1541                switch(nCommand)
1542                {
1543                case ID_APP_ABOUT:
1544                        {
1545                                CAboutDialog Dialog;
1546                                Dialog.DoModal(m_hWnd);
1547                        }
1548                        break;
1549                default:
1550                        SetMsgHandled(FALSE);
1551                }
1552                return 0;
1553        }
1554};
Note: See TracBrowser for help on using the repository browser.