source: trunk/DirectShowSpy/MediaSampleTrace.h @ 457

Last change on this file since 457 was 457, checked in by roman, 8 years ago

Added media trace item highlighting

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