source: trunk/DirectShowSpy/MediaSampleTrace.h @ 485

Last change on this file since 485 was 460, checked in by roman, 9 years ago

Added ability to highlight items programmatically

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