source: trunk/DirectShowSpy/MediaSampleTrace.h @ 795

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

MediaSampleTrace? UI small improvements - ability to switch back to live data from context menu; SystemDeviceEnumeratorSpy? is extended to track IMMDeviceActivator interface and blind-forward other interfaces

File size: 67.2 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_LOADLIVE, OnLoadLive)
979                COMMAND_ID_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_RESETDATA, OnResetData)
980                COMMAND_ID_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_OPENFILTERGRAPHLIST, OnOpenFilterGraphList)
981                COMMAND_ID_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_OPENFILTERGRAPHPROPERTIES, OnOpenFilterGraphProperties)
982                COMMAND_ID_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_HIGHLIGHT_REMOVEALL, OnHighlightRemoveAll)
983                COMMAND_RANGE_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_HIGHLIGHT_REMOVE, IDC_MEDIASAMPLETRACE_MEDIASAMPLE_HIGHLIGHT_8, OnHighlight)
984                REFLECT_NOTIFICATIONS()
985        END_MSG_MAP()
986
987        BEGIN_DLGRESIZE_MAP(CMediaSamplePropertyPage)
988                DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_INTRODUCTION, DLSZ_SIZE_X)
989                DLGRESIZE_CONTROL(IDD_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER, DLSZ_SIZE_X)
990                DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_LIST, DLSZ_SIZE_X | DLSZ_SIZE_Y)
991                DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_REFRESH, DLSZ_MOVE_Y)
992                DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_COPYTOCLIPBOARD, DLSZ_MOVE_Y)
993                DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_SAVETOFILE, DLSZ_MOVE_Y)
994                DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_LOADFROMFILE, DLSZ_MOVE_Y)
995        END_DLGRESIZE_MAP()
996
997        public:
998
999                ////////////////////////////////////////////////////
1000                // CFilterDialog
1001
1002                class CFilterDialog :
1003                        public CDialogImpl<CFilterDialog>,
1004                        public CDialogResize<CFilterDialog>
1005                {
1006                public:
1007                        enum { IDD = IDD_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER };
1008
1009                BEGIN_MSG_MAP_EX(CFilterDialog)
1010                        //CHAIN_MSG_MAP(CFilterDialog)
1011                        CHAIN_MSG_MAP(CDialogResize<CFilterDialog>)
1012                        MSG_WM_INITDIALOG(OnInitDialog)
1013                        COMMAND_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_PROCESS, CBN_SELENDOK, OnProcessComboBoxSelEndOk)
1014                        COMMAND_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_FILTERGRAPH, CBN_SELENDOK, OnFilterGraphComboBoxSelEndOk)
1015                        COMMAND_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_FILTER, CBN_SELENDOK, OnFilterComboBoxSelEndOk)
1016                        COMMAND_HANDLER_EX(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_STREAM, CBN_SELENDOK, OnStreamComboBoxSelEndOk)
1017                        REFLECT_NOTIFICATIONS()
1018                END_MSG_MAP()
1019
1020                BEGIN_DLGRESIZE_MAP(CFilterDialog)
1021                        DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_PROCESS_TITLE, 0)
1022                        DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_PROCESS, 0) //DLSZ_SIZE_X)
1023                        DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_FILTERGRAPH_TITLE, 0)
1024                        DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_FILTERGRAPH, DLSZ_SIZE_X)
1025                        DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_FILTER_TITLE, 0)
1026                        DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_FILTER, DLSZ_SIZE_X)
1027                        DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_STREAM_TITLE, 0)
1028                        DLGRESIZE_CONTROL(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_STREAM, DLSZ_SIZE_X)
1029                END_DLGRESIZE_MAP()
1030
1031                public:
1032
1033                        ////////////////////////////////////////////////
1034                        // CValueT
1035
1036                        template <typename CIdentifier>
1037                        class CValueT
1038                        {
1039                        public:
1040                                CIdentifier m_nIdentifier;
1041                                CStringW m_sValue;
1042
1043                        public:
1044                        // CValueT
1045                                CValueT() :
1046                                        m_nIdentifier(0)
1047                                {
1048                                }
1049                                CValueT(CIdentifier nIdentifier, LPCWSTR pszValue = NULL) :
1050                                        m_nIdentifier(nIdentifier),
1051                                        m_sValue(pszValue)
1052                                {
1053                                }
1054                        };
1055
1056                        typedef CValueT<UINT32> CProcessValue;
1057                        typedef CValueT<UINT64> CFilterGraphValue;
1058                        typedef CValueT<UINT64> CFilterValue;
1059                        typedef CValueT<UINT> CStreamValue;
1060
1061                        class CProcessValueSortTraits :
1062                                public CSimpleSortTraitsT<CProcessValue>
1063                        {
1064                        public:
1065                        // CProcessValueSortTraits
1066                                static INT_PTR CompareElements(const CProcessValue& Element1, const CProcessValue& Element2, PARAMETERARGUMENT)
1067                                {
1068                                        return (INT_PTR) (Element1.m_nIdentifier - Element2.m_nIdentifier);
1069                                }
1070                        };
1071
1072                        class CFilterGraphValueSortTraits :
1073                                public CSimpleSortTraitsT<CFilterGraphValue>
1074                        {
1075                        public:
1076                        // CFilterGraphValueSortTraits
1077                                static INT_PTR CompareElements(const CFilterGraphValue& Element1, const CFilterGraphValue& Element2, PARAMETERARGUMENT)
1078                                {
1079                                        const INT nName = _wcsicmp(Element1.m_sValue, Element2.m_sValue);
1080                                        if(nName)
1081                                                return nName;
1082                                        return (INT_PTR) (Element1.m_nIdentifier - Element2.m_nIdentifier);
1083                                }
1084                        };
1085
1086                        class CFilterValueSortTraits :
1087                                public CSimpleSortTraitsT<CFilterValue>
1088                        {
1089                        public:
1090                        // CFilterValueSortTraits
1091                                static INT_PTR CompareElements(const CFilterValue& Element1, const CFilterValue& Element2, PARAMETERARGUMENT)
1092                                {
1093                                        const INT nName = _wcsicmp(Element1.m_sValue, Element2.m_sValue);
1094                                        if(nName)
1095                                                return nName;
1096                                        return (INT_PTR) (Element1.m_nIdentifier - Element2.m_nIdentifier);
1097                                }
1098                        };
1099
1100                        class CStreamValueSortTraits :
1101                                public CSimpleSortTraitsT<CStreamValue>
1102                        {
1103                        public:
1104                        // CStreamValueSortTraits
1105                                static INT_PTR CompareElements(const CStreamValue& Element1, const CStreamValue& Element2, PARAMETERARGUMENT)
1106                                {
1107                                        return _wcsicmp(Element1.m_sValue, Element2.m_sValue);
1108                                }
1109                        };
1110
1111                private:
1112                        CMediaSamplePropertyPage& m_Owner;
1113                        CRoComboBoxT<CProcessValue, CRoListControlDataTraitsT> m_ProcessComboBox;
1114                        CRoComboBoxT<CFilterGraphValue, CRoListControlDataTraitsT> m_FilterGraphComboBox;
1115                        CRoComboBoxT<CFilterValue, CRoListControlDataTraitsT> m_FilterComboBox;
1116                        CRoComboBoxT<CStreamValue, CRoListControlDataTraitsT> m_StreamComboBox;
1117                        CProcessValue* m_pProcessValue;
1118                        CFilterGraphValue* m_pFilterGraphValue;
1119                        CFilterValue* m_pFilterValue;
1120                        CStreamValue* m_pStreamValue;
1121
1122                public:
1123                // CFilterDialog
1124                        CFilterDialog(CMediaSamplePropertyPage* pOwner) :
1125                                m_Owner(*pOwner)
1126                        {
1127                        }
1128                        VOID UpdateProcessComboBox()
1129                        {
1130                                m_ProcessComboBox.ResetContent();
1131                                INT nItem = 0;
1132                                _W(m_ProcessComboBox.InsertString(nItem++, _T("<All Processes>")) == 0);
1133                                m_ProcessComboBox.SetCurSel(0);
1134                                CRoArrayT<UINT32> IdentifierArray;
1135                                CRoArrayT<CProcessValue> ValueArray;
1136                                for(auto&& Item: m_Owner.m_Data.m_ItemArray)
1137                                {
1138                                        if(IdentifierArray.FindFirst(Item.m_Item.nProcessIdentifier))
1139                                                continue;
1140                                        IdentifierArray.Add(Item.m_Item.nProcessIdentifier);
1141                                        ValueArray.Add(CProcessValue(Item.m_Item.nProcessIdentifier, AtlFormatStringW(L"%d", Item.m_Item.nProcessIdentifier)));
1142                                }
1143                                _SortHelper::QuickSort<CProcessValueSortTraits>(ValueArray);
1144                                for(auto&& Value: ValueArray)
1145                                        m_ProcessComboBox.InsertString(nItem++, Value.m_sValue, Value);
1146                                if(ValueArray.GetCount() == 1)
1147                                        m_ProcessComboBox.SetCurSel(1);
1148                                const BOOL bEnabled = m_ProcessComboBox.GetCount() > 2;
1149                                m_ProcessComboBox.GetWindow(GW_HWNDPREV).EnableWindow(bEnabled);
1150                                m_ProcessComboBox.EnableWindow(bEnabled);
1151                                OnProcessComboBoxSelEndOk();
1152                                UpdateFilterGraphComboBox();
1153                        }
1154                        VOID UpdateFilterGraphComboBox()
1155                        {
1156                                m_FilterGraphComboBox.ResetContent();
1157                                INT nItem = 0;
1158                                _W(m_FilterGraphComboBox.InsertString(nItem++, _T("<All Filter Graphs>")) == 0);
1159                                m_FilterGraphComboBox.SetCurSel(0);
1160                                CRoArrayT<UINT64> IdentifierArray;
1161                                CRoArrayT<CFilterGraphValue> ValueArray;
1162                                for(auto&& Item: m_Owner.m_Data.m_ItemArray)
1163                                {
1164                                        if(m_pProcessValue && m_pProcessValue->m_nIdentifier != Item.m_Item.nProcessIdentifier)
1165                                                continue;
1166                                        if(IdentifierArray.FindFirst(Item.m_Item.nFilterGraphIdentifier))
1167                                                continue;
1168                                        IdentifierArray.Add(Item.m_Item.nFilterGraphIdentifier);
1169                                        ValueArray.Add(CFilterGraphValue(Item.m_Item.nFilterGraphIdentifier, GetFilterGraphFriendlyName(Item.m_Item)));
1170                                }
1171                                _SortHelper::QuickSort<CFilterGraphValueSortTraits>(ValueArray);
1172                                for(auto&& Value: ValueArray)
1173                                        m_FilterGraphComboBox.InsertString(nItem++, Value.m_sValue, Value);
1174                                if(ValueArray.GetCount() == 1)
1175                                        m_FilterGraphComboBox.SetCurSel(1);
1176                                const BOOL bEnabled = m_FilterGraphComboBox.GetCount() > 2;
1177                                m_FilterGraphComboBox.GetWindow(GW_HWNDPREV).EnableWindow(bEnabled);
1178                                m_FilterGraphComboBox.EnableWindow(bEnabled);
1179                                OnFilterGraphComboBoxSelEndOk();
1180                                UpdateFilterComboBox();
1181                        }
1182                        VOID UpdateFilterComboBox()
1183                        {
1184                                m_FilterComboBox.ResetContent();
1185                                INT nItem = 0;
1186                                _W(m_FilterComboBox.InsertString(nItem++, _T("<All Filters>")) == 0);
1187                                m_FilterComboBox.SetCurSel(0);
1188                                CRoArrayT<UINT64> IdentifierArray;
1189                                CRoArrayT<CFilterValue> ValueArray;
1190                                for(auto&& Item: m_Owner.m_Data.m_ItemArray)
1191                                {
1192                                        if(m_pProcessValue && m_pProcessValue->m_nIdentifier != Item.m_Item.nProcessIdentifier)
1193                                                continue;
1194                                        if(m_pFilterGraphValue && m_pFilterGraphValue->m_nIdentifier != Item.m_Item.nFilterGraphIdentifier)
1195                                                continue;
1196                                        if(IdentifierArray.FindFirst(Item.m_PageItem.nFilterIdentifier))
1197                                                continue;
1198                                        IdentifierArray.Add(Item.m_PageItem.nFilterIdentifier);
1199                                        ValueArray.Add(CFilterValue(Item.m_PageItem.nFilterIdentifier, GetFilterFriendlyName(Item.m_PageItem)));
1200                                }
1201                                _SortHelper::QuickSort<CFilterValueSortTraits>(ValueArray);
1202                                for(auto&& Value: ValueArray)
1203                                        m_FilterComboBox.InsertString(nItem++, Value.m_sValue, Value);
1204                                if(ValueArray.GetCount() == 1)
1205                                        m_FilterComboBox.SetCurSel(1);
1206                                const BOOL bEnabled = m_FilterComboBox.GetCount() > 2;
1207                                m_FilterComboBox.GetWindow(GW_HWNDPREV).EnableWindow(bEnabled);
1208                                m_FilterComboBox.EnableWindow(bEnabled);
1209                                OnFilterComboBoxSelEndOk();
1210                                UpdateStreamComboBox();
1211                        }
1212                        VOID UpdateStreamComboBox()
1213                        {
1214                                m_StreamComboBox.ResetContent();
1215                                INT nItem = 0;
1216                                _W(m_StreamComboBox.InsertString(nItem++, _T("<All Streams>")) == 0);
1217                                m_StreamComboBox.SetCurSel(0);
1218                                CRoArrayT<CStringW> IdentifierArray;
1219                                CRoArrayT<CStreamValue> ValueArray;
1220                                for(auto&& Item: m_Owner.m_Data.m_ItemArray)
1221                                {
1222                                        if(m_pProcessValue && m_pProcessValue->m_nIdentifier != Item.m_Item.nProcessIdentifier)
1223                                                continue;
1224                                        if(m_pFilterGraphValue && m_pFilterGraphValue->m_nIdentifier != Item.m_Item.nFilterGraphIdentifier)
1225                                                continue;
1226                                        if(m_pFilterValue && m_pFilterValue->m_nIdentifier != Item.m_PageItem.nFilterIdentifier)
1227                                                continue;
1228                                        if(!*Item.m_PageItem.pszStreamName)
1229                                                continue;
1230                                        if(IdentifierArray.FindFirst(Item.m_PageItem.pszStreamName))
1231                                                continue;
1232                                        IdentifierArray.Add(Item.m_PageItem.pszStreamName);
1233                                        ValueArray.Add(CStreamValue(1, Item.m_PageItem.pszStreamName));
1234                                }
1235                                _SortHelper::QuickSort<CStreamValueSortTraits>(ValueArray);
1236                                for(auto&& Value: ValueArray)
1237                                        m_StreamComboBox.InsertString(nItem++, Value.m_sValue, Value);
1238                                if(ValueArray.GetCount() == 1)
1239                                        m_StreamComboBox.SetCurSel(1);
1240                                const BOOL bEnabled = m_StreamComboBox.GetCount() > 2;
1241                                m_StreamComboBox.GetWindow(GW_HWNDPREV).EnableWindow(bEnabled);
1242                                m_StreamComboBox.EnableWindow(bEnabled);
1243                                OnStreamComboBoxSelEndOk();
1244                        }
1245                        VOID Reset()
1246                        {
1247                                m_pProcessValue = NULL;
1248                                UpdateProcessComboBox();
1249                        }
1250                        BOOL IsVisible(const CData::CItem& Item) const
1251                        {
1252                                if(m_pProcessValue && Item.m_Item.nProcessIdentifier != m_pProcessValue->m_nIdentifier)
1253                                        return FALSE;
1254                                if(m_pFilterGraphValue && Item.m_Item.nFilterGraphIdentifier != m_pFilterGraphValue->m_nIdentifier)
1255                                        return FALSE;
1256                                if(m_pFilterValue && Item.m_PageItem.nFilterIdentifier != m_pFilterValue->m_nIdentifier)
1257                                        return FALSE;
1258                                if(m_pStreamValue && wcscmp(Item.m_PageItem.pszStreamName, m_pStreamValue->m_sValue) != 0)
1259                                        return FALSE;
1260                                return TRUE;
1261                        }
1262
1263                // Window Message Handler
1264                        LRESULT OnInitDialog(HWND, LPARAM)
1265                        {
1266                                m_ProcessComboBox = GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_PROCESS);
1267                                m_FilterGraphComboBox = GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_FILTERGRAPH);
1268                                m_FilterComboBox = GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_FILTER);
1269                                m_StreamComboBox = GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_FILTER_STREAM);
1270                                m_pProcessValue = NULL;
1271                                m_pFilterGraphValue = NULL;
1272                                m_pFilterValue = NULL;
1273                                m_pStreamValue = NULL;
1274                                DlgResize_Init(FALSE);
1275                                return TRUE;
1276                        }
1277                        LRESULT OnProcessComboBoxSelEndOk(UINT = 0, INT = 0, HWND = NULL)
1278                        {
1279                                CProcessValue& ProcessValue = m_ProcessComboBox.GetItemData(m_ProcessComboBox.GetCurSel());
1280                                m_pProcessValue = ProcessValue.m_nIdentifier ? &ProcessValue : NULL;
1281                                UpdateFilterGraphComboBox();
1282                                m_Owner.HandleFilterUpdate();
1283                                return 0;
1284                        }
1285                        LRESULT OnFilterGraphComboBoxSelEndOk(UINT = 0, INT = 0, HWND = NULL)
1286                        {
1287                                CFilterGraphValue& FilterGraphValue = m_FilterGraphComboBox.GetItemData(m_FilterGraphComboBox.GetCurSel());
1288                                m_pFilterGraphValue = FilterGraphValue.m_nIdentifier ? &FilterGraphValue : NULL;
1289                                UpdateFilterComboBox();
1290                                m_Owner.HandleFilterUpdate();
1291                                return 0;
1292                        }
1293                        LRESULT OnFilterComboBoxSelEndOk(UINT = 0, INT = 0, HWND = NULL)
1294                        {
1295                                CFilterValue& FilterValue = m_FilterComboBox.GetItemData(m_FilterComboBox.GetCurSel());
1296                                m_pFilterValue = FilterValue.m_nIdentifier ? &FilterValue : NULL;
1297                                UpdateStreamComboBox();
1298                                m_Owner.HandleFilterUpdate();
1299                                return 0;
1300                        }
1301                        LRESULT OnStreamComboBoxSelEndOk(UINT = 0, INT = 0, HWND = NULL)
1302                        {
1303                                CStreamValue& StreamValue = m_StreamComboBox.GetItemData(m_StreamComboBox.GetCurSel());
1304                                m_pStreamValue = !StreamValue.m_sValue.IsEmpty() ? &StreamValue : NULL;
1305                                m_Owner.HandleFilterUpdate();
1306                                return 0;
1307                        }
1308                };
1309
1310        private:
1311                CMediaSampleTracePropertySheet& m_PropertySheet;
1312                CRoHyperStatic m_IntroductionStatic;
1313                CRoListViewT<CData::CItem, CRoListControlDataTraitsT> m_ListView;
1314                CRoHyperStatic m_RefreshStatic;
1315                CRoHyperStatic m_CopyToClipboardStatic;
1316                CRoHyperStatic m_SaveToFileStatic;
1317                CRoHyperStatic m_LoadFromFileStatic;
1318                CFilterDialog m_FilterDialog;
1319                CRoMapT<INT, BOOL> m_ChangeMap;
1320                CData m_Data;
1321                CHandleMap m_HandleMap;
1322                CObjectPtr<CHandleMapLock> m_pHandleMapLock;
1323
1324        public:
1325        // CMediaSamplePropertyPage
1326                CMediaSamplePropertyPage(CMediaSampleTracePropertySheet* pPropertySheet) :
1327                        m_PropertySheet(*pPropertySheet),
1328                        m_FilterDialog(this)
1329                {
1330                }
1331                VOID UpdateControls()
1332                {
1333                }
1334                VOID UpdateListView()
1335                {
1336                        CWindowRedraw ListViewRedraw(m_ListView);
1337                        m_ListView.DeleteAllItems();
1338                        if(m_pHandleMapLock) // Live vs. File Source
1339                        {
1340                                m_Data.Initialize();
1341                                CPages Pages;
1342                                if(Pages.Initialize())
1343                                {
1344                                        Pages.GetData(m_Data, &m_HandleMap);
1345                                        m_Data.Sort();
1346                                        INT nItem = 0;
1347                                        for(auto&& Item: m_Data.m_ItemArray)
1348                                                m_ListView.InsertItem(nItem++, Item);
1349                                }
1350                        }
1351                        m_FilterDialog.Reset();
1352                }
1353                static CString GetFilterGraphFriendlyName(const ITEM& Item)
1354                {
1355                        CString sFriendlyName(Item.pszFilterGraphName);
1356                        if(!sFriendlyName.IsEmpty())
1357                                sFriendlyName.AppendFormat(_T(" (0x%p)"), (UINT_PTR) Item.nFilterGraphIdentifier);
1358                        else
1359                                sFriendlyName.AppendFormat(_T("0x%p"), (UINT_PTR) Item.nFilterGraphIdentifier);
1360                        return sFriendlyName;
1361                }
1362                static CString GetFilterFriendlyName(const PAGEITEM& PageItem)
1363                {
1364                        CString sFriendlyName(PageItem.pszFilterName);
1365                        if(!sFriendlyName.IsEmpty())
1366                                sFriendlyName.AppendFormat(_T(" (0x%p)"), (UINT_PTR) PageItem.nFilterIdentifier);
1367                        else
1368                                sFriendlyName.AppendFormat(_T("0x%p"), (UINT_PTR) PageItem.nFilterIdentifier);
1369                        return sFriendlyName;
1370                }
1371                CStringA CreateText()
1372                {
1373                        CString sText;
1374                        sText += CreateDataItemHeaderText();
1375                        for(INT nItem = 0; nItem < m_ListView.GetItemCount(); nItem++)
1376                                sText += CreateDataItemText(m_ListView.GetItemData(nItem));
1377                        return Utf8StringFromString(sText);
1378                }
1379                VOID HandleFilterUpdate()
1380                {
1381                        CWindowRedraw ListViewRedraw(m_ListView);
1382                        m_ListView.DeleteAllItems();
1383                        INT nItem = 0;
1384                        for(auto&& Item: m_Data.m_ItemArray)
1385                                if(m_FilterDialog.IsVisible(Item))
1386                                        m_ListView.InsertItem(nItem++, Item);
1387                        // SUGG: Preserve selection
1388                }
1389                VOID LoadFrom(CString sText)
1390                {
1391                        sText.Replace(_T("\r\n"), _T("\n"));
1392                        CRoListT<CData::CItem> ItemList;
1393                        {
1394                                CRoArrayT<CString> LineArray;
1395                                _StringHelper::GetLines(sText, LineArray);
1396                                __D(LineArray.GetCount() > 1, E_UNNAMED);
1397                                LineArray.RemoveAt(0); // Header
1398                                for(auto&& sLine: LineArray)
1399                                {
1400                                        CData::CItem Item;
1401                                        _ATLTRY
1402                                        {
1403                                                ZeroMemory(&Item.m_Item, sizeof Item.m_Item);
1404                                                ZeroMemory(&Item.m_PageItem, sizeof Item.m_PageItem);
1405                                                CRoArrayT<CString> Array;
1406                                                _StringHelper::Split(sLine, _T('\t'), Array);
1407                                                __D(Array.GetCount() >= 9, E_UNNAMED);
1408                                                Item.m_Item.nFlags = ITEMFLAGS_NONE;
1409                                                _W(StrToIntEx(Array[1], 0, (INT*) &Item.m_Item.nProcessIdentifier));
1410                                                Item.m_Item.nPageIdentifier = 0;
1411                                                _W(StrToInt64Ex(Array[3], STIF_SUPPORT_HEX, (LONGLONG*) &Item.m_Item.nFilterGraphIdentifier));
1412                                                wcsncpy_s(Item.m_Item.pszFilterGraphName, Array[4], _TRUNCATE);
1413                                                Item.m_PageItem.nFlags = PAGEITEMFLAGS_NONE;
1414                                                _W(StrToIntEx(Array[2], 0, (INT*) &Item.m_PageItem.nThreadIdentifier));
1415                                                _W(StrToInt64Ex(Array[5], STIF_SUPPORT_HEX, (LONGLONG*) &Item.m_PageItem.nFilterIdentifier));
1416                                                wcsncpy_s(Item.m_PageItem.pszFilterName, Array[6], _TRUNCATE);
1417                                                wcsncpy_s(Item.m_PageItem.pszStreamName, Array[7], _TRUNCATE);
1418                                                #pragma region Time
1419                                                static CRoStaticRe g_Expression(_T("^{[0-9]+}\\:{[0-9]+}\\:{[0-9]+}\\.{[0-9]+}$"), FALSE);
1420                                                CRoReMatchContext MatchContext;
1421                                                if(g_Expression.Match(Array[0], &MatchContext))
1422                                                {
1423                                                        // NOTE: Let's go with today
1424                                                        SYSTEMTIME Time;
1425                                                        GetSystemTime(&Time);
1426                                                        Time.wHour = (WORD) _ttoi(MatchContext.GetMatchString(0));
1427                                                        Time.wMinute = (WORD) _ttoi(MatchContext.GetMatchString(1));
1428                                                        Time.wSecond = (WORD) _ttoi(MatchContext.GetMatchString(2));
1429                                                        Time.wMilliseconds = (WORD) _ttoi(MatchContext.GetMatchString(3));
1430                                                        _W(SystemTimeToFileTime(&Time, &reinterpret_cast<FILETIME&>(Item.m_PageItem.nTime)));
1431                                                }
1432                                                #pragma endregion
1433                                                const CString& sType = Array[8];
1434                                                if(sType.Compare(_T("New Segment")) == 0)
1435                                                {
1436                                                        Item.m_PageItem.nFlags |= PAGEITEMFLAG_NEWSEGMENT;
1437                                                } else
1438                                                if(sType.Compare(_T("Media Sample")) == 0)
1439                                                {
1440                                                        Item.m_PageItem.nFlags |= PAGEITEMFLAG_MEDIASAMPLE;
1441                                                        AM_SAMPLE2_PROPERTIES& Properties = Item.m_PageItem.Data.MediaSample.Properties;
1442                                                        #pragma region Sample Flags
1443                                                        _A(!Properties.dwSampleFlags);
1444                                                        CString sSampleFlags = Array[9];
1445                                                        sSampleFlags.Replace(_T(" | "), _T("|"));
1446                                                        CRoArrayT<CString> FlagArray;
1447                                                        _StringHelper::Split(sSampleFlags, _T('|'), FlagArray);
1448                                                        for(auto&& sFlag: FlagArray)
1449                                                        {
1450                                                                static const CFlagNameT<DWORD> g_pMap[] = 
1451                                                                {
1452                                                                        #define A(x) { x, #x },
1453                                                                        A(AM_SAMPLE_SPLICEPOINT)
1454                                                                        A(AM_SAMPLE_PREROLL)
1455                                                                        A(AM_SAMPLE_DATADISCONTINUITY)
1456                                                                        A(AM_SAMPLE_TYPECHANGED)
1457                                                                        A(AM_SAMPLE_TIMEVALID)
1458                                                                        A(AM_SAMPLE_TIMEDISCONTINUITY)
1459                                                                        A(AM_SAMPLE_FLUSH_ON_PAUSE)
1460                                                                        A(AM_SAMPLE_STOPVALID)
1461                                                                        A(AM_SAMPLE_ENDOFSTREAM)
1462                                                                        //A(AM_STREAM_MEDIA)
1463                                                                        //A(AM_STREAM_CONTROL)
1464                                                                        #undef A
1465                                                                };
1466                                                                BOOL bHandled = FALSE;
1467                                                                for(auto&& Item: g_pMap)
1468                                                                        if(sFlag.Compare(CString(Item.pszName)) == 0)
1469                                                                        {
1470                                                                                Properties.dwSampleFlags |= Item.Value;
1471                                                                                bHandled = TRUE;
1472                                                                                break;
1473                                                                        }
1474                                                                if(bHandled)
1475                                                                        continue;
1476                                                                INT nFlag;
1477                                                                _W(StrToIntEx(sFlag, STIF_SUPPORT_HEX, &nFlag));
1478                                                                Properties.dwSampleFlags |= nFlag;
1479                                                        }
1480                                                        #pragma endregion
1481                                                        if(!Array[10].IsEmpty())
1482                                                                _W(StrToInt64Ex(Array[10], 0, (LONGLONG*) &Properties.tStart));
1483                                                        if(!Array[11].IsEmpty())
1484                                                                _W(StrToInt64Ex(Array[11], 0, (LONGLONG*) &Properties.tStop));
1485                                                        if(!Array[13].IsEmpty())
1486                                                                _W(StrToIntEx(Array[13], 0, (INT*) &Properties.lActual));
1487                                                } else
1488                                                if(sType.Compare(_T("End of Stream")) == 0)
1489                                                {
1490                                                        Item.m_PageItem.nFlags |= PAGEITEMFLAG_ENDOFSTREAM;
1491                                                } else
1492                                                {
1493                                                        _A(sType.Compare(_T("Comment")) == 0);
1494                                                        Item.m_PageItem.nFlags |= PAGEITEMFLAG_COMMENT;
1495                                                }
1496                                                if(Array.GetCount() > 14)
1497                                                        wcsncpy_s(Item.m_PageItem.pszComment, Array[14], _TRUNCATE);
1498                                                if(Array.GetCount() > 15)
1499                                                {
1500                                                        CString sHighlight = Array[15];
1501                                                        if(!sHighlight.IsEmpty())
1502                                                        {
1503                                                                _A(sHighlight[0] == _T('*'));
1504                                                                sHighlight.Delete(0);
1505                                                                _W(StrToIntEx(sHighlight, 0, (INT*) &Item.m_nHighlightIndex));
1506                                                                //Item.m_PageItem.nFlags &= ~PAGEITEMFLAG_HIGHLIGHT_MASK;
1507                                                                //Item.m_PageItem.nFlags |= (Item.m_nHighlightIndex << PAGEITEMFLAG_HIGHLIGHT_SHIFT) & PAGEITEMFLAG_HIGHLIGHT_MASK;
1508                                                        }
1509                                                }
1510                                        }
1511                                        _ATLCATCHALL()
1512                                        {
1513                                                _Z_EXCEPTION();
1514                                                continue;
1515                                        }
1516                                        ItemList.AddTail(Item);
1517                                }
1518                        }
1519                        m_Data.Initialize();
1520                        for(auto&& Item: ItemList)
1521                                m_Data.m_ItemArray.Add(Item);
1522                        m_pHandleMapLock.Release();
1523                        m_HandleMap.RemoveAll();
1524                        m_RefreshStatic.EnableWindow(FALSE);
1525                        UpdateListView();
1526                }
1527                VOID LoadFromFile(LPCTSTR pszPath)
1528                {
1529                        CAtlFile File;
1530                        __C(File.Create(pszPath, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING));
1531                        ULONGLONG nFileSize;
1532                        __C(File.GetSize(nFileSize));
1533                        CHeapPtr<BYTE> pnData;
1534                        __D(pnData.Allocate((SIZE_T) nFileSize + 1), E_OUTOFMEMORY);
1535                        __C(File.Read(pnData, (DWORD) nFileSize));
1536                        pnData[(SIZE_T) nFileSize] = 0;
1537                        LoadFrom(StringFromUtf8String(CStringA((LPCSTR) (const BYTE*) pnData)));
1538                }
1539
1540        // CCustomDraw
1541                DWORD OnPrePaint(INT nIdentifier, NMCUSTOMDRAW*)
1542                {
1543                        if(nIdentifier == IDC_MEDIASAMPLETRACE_MEDIASAMPLE_LIST)
1544                                return CDRF_NOTIFYITEMDRAW;
1545                        return CDRF_DODEFAULT;
1546                }
1547                DWORD OnItemPrePaint(INT, NMCUSTOMDRAW* pHeader)
1548                {
1549                        NMLVCUSTOMDRAW* pHeaderEx = (NMLVCUSTOMDRAW*) pHeader;
1550                        const CData::CItem& Item = m_ListView.DataFromParameter(pHeaderEx->nmcd.lItemlParam);
1551                        Item.GetBackgroundColor(pHeaderEx->clrTextBk);
1552                        return CDRF_DODEFAULT;
1553                }
1554
1555        // Window Message Handler
1556                LRESULT OnInitDialog(HWND, LPARAM)
1557                {
1558                        _ATLTRY
1559                        {
1560                                CWaitCursor WaitCursor;
1561                                _W(m_IntroductionStatic.SubclassWindow(GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_INTRODUCTION)));
1562                                m_ListView.Initialize(GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_LIST));
1563                                _W(m_RefreshStatic.SubclassWindow(GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_REFRESH)));
1564                                m_RefreshStatic.SetExtendedStyle(CRoHyperStatic::CS_ANCHORCLICKCOMMAND);
1565                                _W(m_CopyToClipboardStatic.SubclassWindow(GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_COPYTOCLIPBOARD)));
1566                                m_CopyToClipboardStatic.SetExtendedStyle(CRoHyperStatic::CS_ANCHORCLICKCOMMAND);
1567                                _W(m_SaveToFileStatic.SubclassWindow(GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_SAVETOFILE)));
1568                                m_SaveToFileStatic.SetExtendedStyle(CRoHyperStatic::CS_ANCHORCLICKCOMMAND);
1569                                _W(m_LoadFromFileStatic.SubclassWindow(GetDlgItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_LOADFROMFILE)));
1570                                m_LoadFromFileStatic.SetExtendedStyle(CRoHyperStatic::CS_ANCHORCLICKCOMMAND);
1571                                CRoHyperStatic::ArrangeHorizontally(&m_RefreshStatic, &m_CopyToClipboardStatic, &m_SaveToFileStatic, &m_LoadFromFileStatic, NULL);
1572                                #pragma region Filter
1573                                __E(m_FilterDialog.Create(m_hWnd, (LPARAM) this));
1574                                {
1575                                        CRect FilterPosition, Position;
1576                                        _W(m_FilterDialog.GetWindowRect(FilterPosition));
1577                                        m_FilterDialog.SetDlgCtrlID(CFilterDialog::IDD);
1578                                        const CSize FilterExtent = FilterPosition.Size();
1579                                        _W(m_ListView.GetWindowRect(Position));
1580                                        _W(ScreenToClient(Position));
1581                                        const LONG nSpacing = Position.left;
1582                                        FilterPosition.left = Position.left;
1583                                        FilterPosition.right = Position.right;
1584                                        FilterPosition.top = Position.top;
1585                                        FilterPosition.bottom = FilterPosition.top + FilterExtent.cy;
1586                                        Position.top = FilterPosition.bottom + nSpacing;
1587                                        _W(m_FilterDialog.SetWindowPos(m_IntroductionStatic, FilterPosition, SWP_NOACTIVATE | SWP_SHOWWINDOW));
1588                                        _W(m_ListView.MoveWindow(Position));
1589                                }
1590                                #pragma endregion
1591                                DlgResize_Init(FALSE, FALSE);
1592                                m_pHandleMapLock.Construct();
1593                                UpdateListView();
1594                                m_ChangeMap.RemoveAll();
1595                                UpdateControls();
1596                                #pragma region Default Property Sheet Size
1597                                CRect Position;
1598                                _W(m_PropertySheet.GetWindowRect(Position));
1599                                Position.InflateRect(6 * Position.Width() / 8, 5 * Position.Width() / 8);
1600                                CSize ScreenExtent(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
1601                                ScreenExtent.cx -= ScreenExtent.cx / 8;
1602                                ScreenExtent.cy -= ScreenExtent.cy / 8;
1603                                if(Position.Width() > ScreenExtent.cx)
1604                                        Position.right = Position.left + ScreenExtent.cx;
1605                                if(Position.Height() > ScreenExtent.cy)
1606                                        Position.bottom = Position.top + ScreenExtent.cy;
1607                                _W(m_PropertySheet.MoveWindow(Position));
1608                                _W(m_PropertySheet.CenterWindow());
1609                                #pragma endregion
1610                                #if _DEVELOPMENT && FALSE
1611                                        LoadFromFile(_T("D:\\MediaSampleTrace.tsv"));
1612                                #endif // _DEVELOPMENT
1613                        }
1614                        _ATLCATCHALL()
1615                        {
1616                                for(CWindow Window = GetWindow(GW_CHILD); Window.IsWindow(); Window = Window.GetWindow(GW_HWNDNEXT))
1617                                        Window.EnableWindow(FALSE);
1618                                _ATLRETHROW;
1619                        }
1620                        return TRUE;
1621                }
1622                LRESULT OnDestroy()
1623                {
1624                        CWaitCursor WaitCursor;
1625                        m_pHandleMapLock.Release();
1626                        return 0;
1627                }
1628                LRESULT OnTranslateAccelerator(MSG* pMessage)
1629                {
1630                        return TranslateAccelerator(m_hWnd, m_hAccelerators, pMessage) ? PSNRET_MESSAGEHANDLED : PSNRET_NOERROR;
1631                }
1632                LRESULT OnListViewGetDispInfo(NMLVDISPINFO* pHeader)
1633                {
1634                        const CData::CItem& Item = m_ListView.DataFromParameter(pHeader->item.lParam);
1635                        if(pHeader->item.mask & LVIF_TEXT)
1636                        {
1637                                CString& sTextBuffer = m_ListView.GetTextBufferString(TRUE);
1638                                switch(pHeader->item.iSubItem)
1639                                {
1640                                case 1: // Process
1641                                        sTextBuffer = AtlFormatString(_T("%d"), (UINT_PTR) Item.m_Item.nProcessIdentifier);
1642                                        break;
1643                                case 2: // Thread
1644                                        sTextBuffer = AtlFormatString(_T("%d"), (UINT_PTR) Item.m_PageItem.nThreadIdentifier);
1645                                        break;
1646                                case 3: // Filter Graph
1647                                        sTextBuffer = GetFilterGraphFriendlyName(Item.m_Item);
1648                                        break;
1649                                case 4: // Filter
1650                                        sTextBuffer = GetFilterFriendlyName(Item.m_PageItem);
1651                                        break;
1652                                case 5: // Stream
1653                                        sTextBuffer = AtlFormatString(_T("%ls"), Item.m_PageItem.pszStreamName);
1654                                        break;
1655                                case 6: // Type
1656                                        sTextBuffer = Item.FormatType();
1657                                        break;
1658                                case 7: // Flags
1659                                        if((Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK) == PAGEITEMFLAG_MEDIASAMPLE)
1660                                                sTextBuffer = _FilterGraphHelper::FormatSampleFlags(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags);
1661                                        break;
1662                                case 8: // Start Time
1663                                        if((Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK) == PAGEITEMFLAG_NEWSEGMENT)
1664                                        {
1665                                                sTextBuffer = _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.NewSegment.nStartTime);
1666                                        } else
1667                                        if((Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK) == PAGEITEMFLAG_MEDIASAMPLE)
1668                                        {
1669                                                if(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags & AM_SAMPLE_TIMEVALID)
1670                                                        sTextBuffer = _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.MediaSample.Properties.tStart);
1671                                        }
1672                                        break;
1673                                case 9: // Stop Time
1674                                        if((Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK) == PAGEITEMFLAG_NEWSEGMENT)
1675                                        {
1676                                                if(Item.m_PageItem.Data.NewSegment.nStopTime < LLONG_MAX)
1677                                                        sTextBuffer = _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.NewSegment.nStopTime);
1678                                        } else
1679                                        if((Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK) == PAGEITEMFLAG_MEDIASAMPLE)
1680                                        {
1681                                                if((Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags & (AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID)) == (AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID))
1682                                                        sTextBuffer = _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.MediaSample.Properties.tStop);
1683                                        }
1684                                        break;
1685                                case 10: // Comment
1686                                        sTextBuffer = CString(Item.m_PageItem.pszComment);
1687                                        break;
1688                                default: // Time
1689                                        sTextBuffer = FormatTime(Item.m_PageItem.nTime);
1690                                }
1691                                pHeader->item.pszText = m_ListView.GetTextBuffer();
1692                                pHeader->item.mask |= LVIF_DI_SETITEM;
1693                        }
1694                        return 0;
1695                }
1696                LRESULT OnListViewGetInfoTip(NMLVGETINFOTIP* pHeader)
1697                {
1698                        const CData::CItem& Item = m_ListView.GetItemData(pHeader->iItem);
1699                        CString& sTextBuffer = m_ListView.GetTextBufferString(TRUE);
1700                        sTextBuffer.AppendFormat(_T("Time: %s\r\n"), FormatTime(Item.m_PageItem.nTime));
1701                        sTextBuffer.AppendFormat(_T("Process: %d\r\n"), (UINT_PTR) Item.m_Item.nProcessIdentifier);
1702                        sTextBuffer.AppendFormat(_T("Thread: %d\r\n"), (UINT_PTR) Item.m_PageItem.nThreadIdentifier);
1703                        sTextBuffer.AppendFormat(_T("Filter Graph: %s\r\n"), GetFilterGraphFriendlyName(Item.m_Item));
1704                        sTextBuffer.AppendFormat(_T("Filter: %s\r\n"), GetFilterFriendlyName(Item.m_PageItem));
1705                        sTextBuffer.AppendFormat(_T("Stream: %ls\r\n"), Item.m_PageItem.pszStreamName);
1706                        sTextBuffer.AppendFormat(_T("Type: %s\r\n"), Item.FormatType());
1707                        switch(Item.m_PageItem.nFlags & PAGEITEMFLAG_TYPE_MASK)
1708                        {
1709                        case PAGEITEMFLAG_NEWSEGMENT:
1710                                sTextBuffer.AppendFormat(_T("Start Time: %s\r\n"), _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.NewSegment.nStartTime));
1711                                if(Item.m_PageItem.Data.NewSegment.nStopTime < LLONG_MAX)
1712                                        sTextBuffer.AppendFormat(_T("Stop Time: %s\r\n"), _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.NewSegment.nStopTime));
1713                                sTextBuffer.AppendFormat(_T("Rate: %.3f\r\n"), Item.m_PageItem.Data.NewSegment.fRate);
1714                                break;
1715                        case PAGEITEMFLAG_MEDIASAMPLE:
1716                                sTextBuffer.AppendFormat(_T("Sample Flags: %s\r\n"), _FilterGraphHelper::FormatSampleFlags(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags));
1717                                if(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags & AM_SAMPLE_TIMEVALID)
1718                                {
1719                                        sTextBuffer.AppendFormat(_T("Start Time: %s\r\n"), _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.MediaSample.Properties.tStart));
1720                                        if(Item.m_PageItem.Data.MediaSample.Properties.dwSampleFlags & AM_SAMPLE_STOPVALID)
1721                                        {
1722                                                sTextBuffer.AppendFormat(_T("Stop Time: %s\r\n"), _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.MediaSample.Properties.tStop));
1723                                                sTextBuffer.AppendFormat(_T("Length Time: %s\r\n"), _FilterGraphHelper::FormatReferenceTime(Item.m_PageItem.Data.MediaSample.Properties.tStop - Item.m_PageItem.Data.MediaSample.Properties.tStart));
1724                                        }
1725                                }
1726                                sTextBuffer.AppendFormat(_T("Data Size: %s\r\n"), _StringHelper::FormatNumber(Item.m_PageItem.Data.MediaSample.Properties.lActual));
1727                                break;
1728                        case PAGEITEMFLAG_ENDOFSTREAM:
1729                        case PAGEITEMFLAG_COMMENT:
1730                                break;
1731                        default:
1732                                _A(FALSE);
1733                        }
1734                        if(*Item.m_PageItem.pszComment)
1735                                sTextBuffer.AppendFormat(_T("\r\n") _T("%ls\r\n"), Item.m_PageItem.pszComment);
1736                        sTextBuffer.TrimRight(_T("\t\n\r ."));
1737                        #pragma region Clipboard Copy
1738                        if(GetKeyState(VK_CONTROL) < 0 && GetKeyState(VK_SHIFT) < 0)
1739                                _ATLTRY
1740                                {
1741                                        SetClipboardText(m_hWnd, sTextBuffer);
1742                                        MessageBeep(MB_OK);
1743                                }
1744                                _ATLCATCHALL()
1745                                {
1746                                        _Z_EXCEPTION();
1747                                        MessageBeep(MB_ICONERROR);
1748                                }
1749                        #pragma endregion
1750                        _tcsncpy_s(pHeader->pszText, pHeader->cchTextMax, m_ListView.GetTextBuffer(), _TRUNCATE);
1751                        return 0;
1752                }
1753                LRESULT OnContextMenu(CWindow, CPoint Position)
1754                {
1755                        CMenu ContainerMenu = AtlLoadMenu(IDD);
1756                        CMenuHandle Menu = ContainerMenu.GetSubMenu(0);
1757                        const INT nItemCount = m_ListView.GetItemCount();
1758                        const INT nSelectItemCount = m_ListView.GetSelectedCount();
1759                        Menu.EnableMenuItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_REFRESH, m_RefreshStatic.IsWindowEnabled() ? MF_ENABLED : MF_GRAYED | MF_DISABLED);
1760                        for(INT nIdentifier = IDC_MEDIASAMPLETRACE_MEDIASAMPLE_HIGHLIGHT_REMOVE; nIdentifier <= IDC_MEDIASAMPLETRACE_MEDIASAMPLE_HIGHLIGHT_8; nIdentifier++)
1761                                Menu.EnableMenuItem(nIdentifier, nSelectItemCount ? MF_ENABLED : MF_GRAYED | MF_DISABLED);
1762                        Menu.EnableMenuItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_HIGHLIGHT_REMOVEALL, nItemCount ? MF_ENABLED : MF_GRAYED | MF_DISABLED);
1763                        Menu.EnableMenuItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_COPYTOCLIPBOARD, nItemCount ? MF_ENABLED : MF_GRAYED | MF_DISABLED);
1764                        Menu.EnableMenuItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_SAVETOFILE, nItemCount ? MF_ENABLED : MF_GRAYED | MF_DISABLED);
1765                        Menu.EnableMenuItem(IDC_MEDIASAMPLETRACE_MEDIASAMPLE_LOADLIVE, !m_pHandleMapLock ? MF_ENABLED : MF_GRAYED | MF_DISABLED);
1766                        Menu.TrackPopupMenu(TPM_RIGHTBUTTON | TPM_LEFTALIGN | TPM_TOPALIGN, Position.x, Position.y, m_hWnd); 
1767                        return 0;
1768                }
1769                LRESULT OnRefresh(UINT, INT, HWND)
1770                {
1771                        CWaitCursor WaitCursor;
1772                        UpdateListView();
1773                        return 0;
1774                }
1775                LRESULT OnCopyToClipboard(UINT, INT, HWND)
1776                {
1777                        CWaitCursor WaitCursor;
1778                        SetClipboardText(m_hWnd, CreateText());
1779                        MessageBeep(MB_OK);
1780                        return 0;
1781                }
1782                LRESULT OnSaveToFile(UINT, INT, HWND)
1783                {
1784                        static const COMDLG_FILTERSPEC g_pFilter[] = 
1785                        {
1786                                { _T("TSV Files"), _T("*.tsv") },
1787                                { _T("TSV Files, Bzip2 Compressed"), _T("*.tsv.bz2") },
1788                                { _T("All Files"), _T("*.*") },
1789                        };
1790                        CPath sPath = _CommonDialogHelper::QuerySavePath(m_hWnd, g_pFilter, _T("tsv"), _T("Media Sample Trace.tsv"));
1791                        if(!_tcslen(sPath))
1792                                return 0;
1793                        CWaitCursor WaitCursor;
1794                        SaveToFile(CreateText(), sPath);
1795                        return 0;
1796                }
1797                LRESULT OnLoadFromFile(UINT, INT, HWND)
1798                {
1799                        static const COMDLG_FILTERSPEC g_pFilter[] = 
1800                        {
1801                                { _T("TSV Files"), _T("*.tsv") },
1802                                { _T("All Files"), _T("*.*") },
1803                        };
1804                        CPath sPath = _CommonDialogHelper::QueryOpenPath(m_hWnd, g_pFilter, _T("tsv"), _T("Media Sample Trace.tsv"));
1805                        if(!_tcslen(sPath))
1806                                return 0;
1807                        CWaitCursor WaitCursor;
1808                        LoadFromFile(sPath);
1809                        return 0;
1810                }
1811                LRESULT OnLoadLive(UINT, INT, HWND)
1812                {
1813                        m_pHandleMapLock.Release();
1814                        m_pHandleMapLock.Construct();
1815                        m_RefreshStatic.EnableWindow(TRUE);
1816                        UpdateListView();
1817                        return 0;
1818                }
1819                LRESULT OnResetData(UINT, INT, HWND)
1820                {
1821                        CWaitCursor WaitCursor;
1822                        m_HandleMap.RemoveAll();
1823                        CPages Pages;
1824                        if(Pages.Initialize())
1825                                Pages.ResetData();
1826                        UpdateListView();
1827                        return 0;
1828                }
1829                LRESULT OnOpenFilterGraphList(UINT, INT, HWND)
1830                {
1831                        CLocalObjectPtr<CFilterGraphHelper> pFilterGraphHelper;
1832                        pFilterGraphHelper->DoFilterGraphListModal((LONG) (LONG_PTR) m_hWnd);
1833                        return 0;
1834                }
1835                LRESULT OnOpenFilterGraphProperties(UINT, INT, HWND)
1836                {
1837                        if(m_ListView.GetSelectedCount() == 1)
1838                        {
1839                                const INT nItem = m_ListView.GetNextItem(-1, LVNI_SELECTED);
1840                                _A(nItem >= 0);
1841                                CData::CItem& Item = m_ListView.GetItemData(nItem);
1842                                const LONG nProcessIdentifier = Item.m_Item.nProcessIdentifier;
1843                                CComPtr<IRunningObjectTable> pRunningObjectTable;
1844                                __C(GetRunningObjectTable(0, &pRunningObjectTable));
1845                                CRoMapT<CStringW, CFilterGraphListPropertySheet::CListPropertyPage::CItem> ItemMap;
1846                                CFilterGraphListPropertySheet::CListPropertyPage::EnumerateItems(pRunningObjectTable, ItemMap, &nProcessIdentifier);
1847                                for(auto&& GraphItem: ItemMap.GetValues())
1848                                {
1849                                        if(abs((LONG_PTR) (GraphItem.m_nInstance - Item.m_Item.nFilterGraphIdentifier)) < 0x0100)
1850                                                if(GraphItem.FilterGraphNeeded(pRunningObjectTable))
1851                                                {
1852                                                        CLocalObjectPtr<CFilterGraphHelper> pFilterGraphHelper;
1853                                                        pFilterGraphHelper->SetFilterGraph(GraphItem.m_pFilterGraph);
1854                                                        _V(pFilterGraphHelper->DoPropertyFrameModal((LONG) (LONG_PTR) m_hWnd));
1855                                                        return 0;
1856                                                }
1857                                }
1858                        }
1859                        _W(PostMessage(WM_COMMAND, IDC_MEDIASAMPLETRACE_MEDIASAMPLE_OPENFILTERGRAPHLIST));
1860                        return 0;
1861                }
1862                LRESULT OnHighlightRemoveAll(UINT, INT nIdentifier, HWND)
1863                {
1864                        const INT nItemCount = m_ListView.GetItemCount();
1865                        if(nItemCount > 0)
1866                        {
1867                                for(INT nItem = 0; nItem < nItemCount; nItem++)
1868                                        m_ListView.GetItemData(nItem).m_nHighlightIndex = 0;
1869                                m_ListView.RedrawItems(0, nItemCount - 1);
1870                        }
1871                        return 0;
1872                }
1873                LRESULT OnHighlight(UINT, INT nIdentifier, HWND)
1874                {
1875                        for(INT nItem: m_ListView.GetSelectedItems())
1876                        {
1877                                m_ListView.GetItemData(nItem).m_nHighlightIndex = nIdentifier - IDC_MEDIASAMPLETRACE_MEDIASAMPLE_HIGHLIGHT_REMOVE;
1878                                m_ListView.RedrawItems(nItem, nItem);
1879                        }
1880                        return 0;
1881                }
1882        };
1883
1884private:
1885        CMediaSamplePropertyPage m_MediaSamplePropertyPage;
1886
1887public:
1888// CMediaSampleTracePropertySheet
1889        CMediaSampleTracePropertySheet() :
1890                CSizablePropertySheetT<CMediaSampleTracePropertySheet>(IDS_MEDIASAMPLETRACE_MEDIASAMPLE_PROPERTYSHEETCAPTION, TRUE),
1891                m_MediaSamplePropertyPage(this)
1892        {
1893                AddPage(m_MediaSamplePropertyPage);
1894        }
1895        BOOL SetInitialPosition()
1896        {
1897                if(!__super::SetInitialPosition())
1898                        return FALSE;
1899                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_DEFAULTCOLOR, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)), TRUE);
1900                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_DEFAULTCOLOR, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)), FALSE);
1901                CAboutDialog::UpdateCaption(*this);
1902                #pragma region System Menu
1903                CMenuHandle Menu = GetSystemMenu(FALSE);
1904                _W(Menu.AppendMenu(MF_SEPARATOR));
1905                _W(Menu.AppendMenu(MF_STRING, ID_APP_ABOUT, _T("&About...")));
1906                #pragma endregion
1907                return TRUE;
1908        }
1909
1910// Window Message Handler
1911        LRESULT OnSysCommand(UINT nCommand, CPoint)
1912        {
1913                switch(nCommand)
1914                {
1915                case ID_APP_ABOUT:
1916                        {
1917                                CAboutDialog Dialog;
1918                                Dialog.DoModal(m_hWnd);
1919                        }
1920                        break;
1921                default:
1922                        SetMsgHandled(FALSE);
1923                }
1924                return 0;
1925        }
1926};
1927
1928inline VOID MediaSampleTrace_Reset(DWORD nProcessIdentifier)
1929{
1930        nProcessIdentifier;
1931        // TODO: Implement processs-specific operation (support non-zero nProcessIdentifier)
1932        CMediaSampleTraceBase::CPages Pages;
1933        if(Pages.Initialize())
1934                Pages.ResetData();
1935}
1936inline CString MediaSampleTrace_Get(DWORD nProcessIdentifier)
1937{
1938        CString sText;
1939        CMediaSampleTraceBase::CPages Pages;
1940        if(Pages.Initialize())
1941        {
1942                CMediaSampleTraceBase::CData Data;
1943                Data.Initialize();
1944                CMediaSampleTraceBase::CHandleMap HandleMap;
1945                Pages.GetData(Data, &HandleMap);
1946                Data.Sort();
1947                sText += CMediaSampleTracePropertySheet::CreateDataItemHeaderText();
1948                for(auto&& Item: Data.m_ItemArray)
1949                        if(!nProcessIdentifier || Item.m_Item.nProcessIdentifier == nProcessIdentifier)
1950                                sText += CMediaSampleTracePropertySheet::CreateDataItemText(Item);
1951        }
1952        return sText;
1953}
1954inline CComPtr<IUnknown> MediaSampleTrace_Lock()
1955{
1956        CObjectPtr<CMediaSampleTraceBase::CHandleMapLock> pHandleMapLock;
1957        pHandleMapLock.Construct();
1958        return (CMediaSampleTraceBase::CHandleMapLock*) pHandleMapLock;
1959}
Note: See TracBrowser for help on using the repository browser.