source: trunk/DirectShowSpy/MediaSampleTrace.h @ 455

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

Cosmetic

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