source: trunk/DirectShowSpy/MediaSampleTrace.h @ 617

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

Exported function signatures replaced to accurately rundll32 compatible; added IModuleVersionInformation implementation to FilterGraphHelper?; added debug Host01 project; IFilterGraphHelper interface is extended with MediaSampleTrace? related automation methods; MediaSampleTrace? UI is extended to support data load from external file

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