source: trunk/DirectShowSpy/GraphBuilderCallbackPropertySheet.h @ 188

Last change on this file since 188 was 147, checked in by roman, 11 years ago

COM registration UI

  • Property svn:keywords set to Id
File size: 51.8 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2008-2011
3// Created by Roman Ryltsov roman@alax.info
4//
5// $Id: GraphBuilderCallbackPropertySheet.h 147 2012-11-22 22:49:34Z roman $
6
7#pragma once
8
9#include <atlctrlx.h>
10#include <atlsplit.h>
11#include "rofiles.h"
12#include "AboutDialog.h"
13
14////////////////////////////////////////////////////////////
15// CGraphBuilderCallbackPropertySheet
16
17class CGraphBuilderCallbackPropertySheet :
18        public CSizablePropertySheetT<CGraphBuilderCallbackPropertySheet>
19{
20public:
21
22BEGIN_MSG_MAP_EX(CGraphBuilderCallbackPropertySheet)
23        CHAIN_MSG_MAP(CSizablePropertySheet)
24        MSG_WM_SYSCOMMAND(OnSysCommand)
25END_MSG_MAP()
26
27public:
28
29        ////////////////////////////////////////////////////////
30        // CGraphPropertyPage
31
32        class CGraphPropertyPage :
33                public CPropertyPageT<CGraphPropertyPage>,
34                public CDialogResize<CGraphPropertyPage>,
35                public CWindowWithPrivateMessagesT<CGraphPropertyPage>
36        {
37                typedef CThreadT<CGraphPropertyPage> CThread;
38
39        public:
40
41                enum { IDD = IDD_GRAPHBUILDERCALLBACK_GRAPH_PROPERTYPAGE };
42
43        BEGIN_MSG_MAP_EX(CGraphPropertyPage)
44                CHAIN_MSG_MAP(CPropertyPage)
45                CHAIN_MSG_MAP(CDialogResize<CGraphPropertyPage>)
46                CHAIN_MSG_MAP(CWindowWithPrivateMessages)
47                MSG_WM_INITDIALOG(OnInitDialog)
48                MSG_WM_DESTROY(OnDestroy)
49                MESSAGE_HANDLER_EX(WM_THREADPROGRESS, OnThreadProgress)
50                MESSAGE_HANDLER_EX(WM_THREADCOMPLETED, OnThreadCompleted)
51                MSG_LVN_GETDISPINFO(IDC_GRAPHBUILDERCALLBACK_GRAPH_GRAPH, OnGraphListViewGetDispInfo)
52                MSG_LVN_GETINFOTIP(IDC_GRAPHBUILDERCALLBACK_GRAPH_GRAPH, OnGraphListViewGetInfoTip)
53                MSG_LVN_ITEMCHANGED(IDC_GRAPHBUILDERCALLBACK_GRAPH_GRAPH, OnGraphListViewItemChanged)
54                MSG_LVN_GETDISPINFO(IDC_GRAPHBUILDERCALLBACK_GRAPH_LOG, OnLogListViewGetDispInfo)
55                MSG_LVN_GETINFOTIP(IDC_GRAPHBUILDERCALLBACK_GRAPH_LOG, OnLogListViewGetInfoTip)
56                NOTIFY_HANDLER_EX(IDC_GRAPHBUILDERCALLBACK_GRAPH_COPYTOCLIPBOARD, CRoHyperStatic::NC_ANCHORCLICKED, OnCopyToClipboardStaticAnchorClicked)
57                REFLECT_NOTIFICATIONS()
58        END_MSG_MAP()
59
60        BEGIN_DLGRESIZE_MAP(CGraphPropertyPage)
61                DLGRESIZE_CONTROL(IDC_GRAPHBUILDERCALLBACK_GRAPH_INTRODUCTION, DLSZ_SIZE_X)
62                DLGRESIZE_CONTROL(IDC_GRAPHBUILDERCALLBACK_GRAPH_SPLITTER, DLSZ_SIZE_X | DLSZ_SIZE_Y)
63                DLGRESIZE_CONTROL(IDC_GRAPHBUILDERCALLBACK_GRAPH_COPYTOCLIPBOARD, DLSZ_MOVE_Y)
64                //DLGRESIZE_CONTROL(IDC_GRAPHBUILDERCALLBACK_GRAPH_PROGRESS, ...
65        END_DLGRESIZE_MAP()
66
67        public:
68
69                ////////////////////////////////////////////////////
70                // Window message identifiers
71
72                enum 
73                {
74                        WM_FIRST = WM_APP,
75                        WM_THREADPROGRESS,
76                        WM_THREADCOMPLETED,
77                };
78
79                ////////////////////////////////////////////////////
80                // CLogData
81
82                class CLogData
83                {
84                public:
85
86                        ////////////////////////////////////////////////
87                        // TYPE
88
89                        typedef enum _TYPE
90                        {
91                                TYPE_SELECTEDFILTER,
92                                TYPE_CREATEDFILTER,
93                                TYPE_ADDFILTER,
94                                TYPE_REMOVEFILTER,
95                        } TYPE;
96
97                public:
98                        ULONGLONG m_nTime;
99                        TYPE m_Type;
100                        CStringA m_sMonikerDisplayName;
101                        SIZE_T m_nFilterPointer;
102                        CLSID m_FilterClassIdentifier;
103                        CStringA m_sFilterName;
104                        HRESULT m_nSiteResult;
105                        BOOL m_bSiteResultValid;
106
107                public:
108                // CLogData
109                        CLogData() throw() :
110                                m_nTime(0),
111                                m_bSiteResultValid(FALSE)
112                        {
113                        }
114                        CLogData(ULONGLONG nTime, const CStringA& sMonikerDisplayName) throw() :
115                                m_nTime(nTime),
116                                m_Type(TYPE_SELECTEDFILTER),
117                                m_sMonikerDisplayName(sMonikerDisplayName),
118                                m_FilterClassIdentifier(CLSID_NULL),
119                                m_bSiteResultValid(FALSE)
120                        {
121                        }
122                        CLogData(ULONGLONG nTime, TYPE Type, SIZE_T nFilterPointer, const CLSID& FilterClassIdentifier, const CStringA& sFilterName) throw() :
123                                m_nTime(nTime),
124                                m_Type(Type),
125                                m_nFilterPointer(nFilterPointer), 
126                                m_FilterClassIdentifier(FilterClassIdentifier), 
127                                m_sFilterName(sFilterName),
128                                m_bSiteResultValid(FALSE)
129                        {
130                                _A(Type == TYPE_CREATEDFILTER || Type == TYPE_ADDFILTER);
131                        }
132                        CLogData(ULONGLONG nTime, SIZE_T nFilterPointer) throw() :
133                                m_nTime(nTime),
134                                m_Type(TYPE_REMOVEFILTER),
135                                m_nFilterPointer(nFilterPointer),
136                                m_FilterClassIdentifier(CLSID_NULL),
137                                m_bSiteResultValid(FALSE)
138                        {
139                        }
140                        BOOL GetSiteResult(HRESULT& nResult) const throw()
141                        {
142                                if(!m_bSiteResultValid)
143                                        return FALSE;
144                                nResult = m_nSiteResult;
145                                return TRUE;
146                        }
147                        VOID SetSiteResult(HRESULT nResult) throw()
148                        {
149                                _A(!m_bSiteResultValid);
150                                m_nSiteResult = nResult;
151                                m_bSiteResultValid = TRUE;
152                        }
153                        CString GetFriendlyEventName() const
154                        {
155                                switch(m_Type)
156                                {
157                                case TYPE_SELECTEDFILTER:
158                                        _A(!m_sMonikerDisplayName.IsEmpty());
159                                        return _T("Selected Filter");
160                                case TYPE_CREATEDFILTER:
161                                        _A(m_nFilterPointer);
162                                        return _T("Created Filter");
163                                case TYPE_ADDFILTER:
164                                        _A(m_nFilterPointer);
165                                        return _T("Add Filter");
166                                case TYPE_REMOVEFILTER:
167                                        _A(m_nFilterPointer);
168                                        return _T("Remove Filter");
169                                }
170                                _A(FALSE);
171                                return _T("");
172                        }
173                        CComPtr<IPropertyBag> GetMonikerPropertyBag() const throw()
174                        {
175                                if(!m_sMonikerDisplayName.IsEmpty())
176                                        _ATLTRY
177                                        {
178                                                USES_CONVERSION;
179                                                CComPtr<IBindCtx> pBindCtx;
180                                                __C(CreateBindCtx(0, &pBindCtx));
181                                                ULONG nConsumedCount;
182                                                CComPtr<IMoniker> pMoniker;
183                                                const HRESULT nMkParseDisplayNameResult = MkParseDisplayName(pBindCtx, CA2W(m_sMonikerDisplayName), &nConsumedCount, &pMoniker);
184                                                if(SUCCEEDED(nMkParseDisplayNameResult))
185                                                {
186                                                        CComPtr<IPropertyBag> pPropertyBag;
187                                                        const HRESULT nBindToStorageResult = pMoniker->BindToStorage(pBindCtx, NULL, __uuidof(IPropertyBag), (VOID**) &pPropertyBag);
188                                                        if(SUCCEEDED(nBindToStorageResult))
189                                                        {
190                                                                _A(pPropertyBag);
191                                                                return pPropertyBag;
192                                                        } else
193                                                                _Z4(atlTraceGeneral, 4, _T("nBindToStorageResult 0x%08x\n"), nBindToStorageResult);
194                                                               
195                                                } else
196                                                        _Z4(atlTraceGeneral, 4, _T("nMkParseDisplayNameResult 0x%08x\n"), nMkParseDisplayNameResult);
197                                        }
198                                        _ATLCATCHALL()
199                                        {
200                                                _Z_EXCEPTION();
201                                        }
202                                return NULL;
203                        }
204                        CString GetFriendlyMonikerName() const
205                        {
206                                _ATLTRY
207                                {
208                                        const CComPtr<IPropertyBag> pPropertyBag = GetMonikerPropertyBag();
209                                        if(pPropertyBag)
210                                                return _FilterGraphHelper::ReadPropertyBagString(pPropertyBag, L"FriendlyName");
211                                }
212                                _ATLCATCHALL()
213                                {
214                                        _Z_EXCEPTION();
215                                }
216                                return _T("");
217                        }
218                        CString GetFriendlyApplicationResult() const
219                        {
220                                if(m_bSiteResultValid)
221                                        return AtlFormatString(_T("0x%08x"), m_nSiteResult);
222                                return _T("");
223                        }
224                };
225
226                ////////////////////////////////////////////////////
227                // CLogDataList
228
229                class CLogDataList :
230                        public CRoListT<CLogData>
231                {
232                public:
233                // CLogDataList
234                };
235
236                ////////////////////////////////////////////////////
237                // CFilterData
238
239                class CFilterData
240                {
241                public:
242                        SIZE_T m_nPointer;
243                        CLSID m_ClassIdentifier;
244                        CStringA m_sName;
245
246                public:
247                // CFilterData
248                        CFilterData() throw()
249                        {
250                        }
251                        CFilterData(SIZE_T nPointer, const CLSID& ClassIdentifier, const CStringA& sName) throw() :
252                                m_nPointer(nPointer),
253                                m_ClassIdentifier(ClassIdentifier),
254                                m_sName(sName)
255                        {
256                        }
257                };
258
259                ////////////////////////////////////////////////////
260                // CFilterDataMap
261
262                class CFilterDataMap :
263                        public CRoMapT<SIZE_T, CFilterData>
264                {
265                };
266
267                ////////////////////////////////////////////////////
268                // CGraphData
269
270                class CGraphData
271                {
272                public:
273                        INT m_nProcessIdentifier;
274                        CStringA m_sProcessPath;
275                        ULONGLONG m_nTime;
276                        SIZE_T m_nPointer;
277                        SIZE_T m_nCallbackPointer;
278                        CLogDataList m_LogDataList;
279                        CFilterDataMap m_FilterDataMap;
280                        INT m_nImageIndex;
281
282                public:
283                // CGraphData
284                        //static BOOL ComparePointer(const CGraphData& GraphData, SIZE_T nPointer) throw()
285                        //{
286                        //      return GraphData.m_nPointer == nPointer;
287                        //}
288                        //static BOOL CompareCallbackPointer(const CGraphData& GraphData, SIZE_T nCallbackPointer) throw()
289                        //{
290                        //      return GraphData.m_nCallbackPointer == nCallbackPointer;
291                        //}
292                        CString GetProcessName() const
293                        {
294                                if(m_sProcessPath.IsEmpty())
295                                        return _T("");
296                                CPath sPath = CA2CT(m_sProcessPath);
297                                return (LPCTSTR) sPath + sPath.FindFileName();
298                        }
299                        CString GetProcessDirectory() const
300                        {
301                                if(m_sProcessPath.IsEmpty())
302                                        return _T("");
303                                CPath sPath = CA2CT(m_sProcessPath);
304                                _W(sPath.RemoveFileSpec());
305                                return (LPCTSTR) sPath;
306                        }
307                };
308
309                ////////////////////////////////////////////////////
310                // CGraphDataList
311
312                class CGraphDataList :
313                        public CRoListT<CGraphData>
314                {
315                public:
316                // CGraphDataList
317                        //BOOL FindFirstPointer(SIZE_T nPointer, POSITION* pPosition = NULL) const throw()
318                        //{
319                        //      return FindFirstThatT<SIZE_T>(&CGraphData::ComparePointer, nPointer, pPosition);
320                        //}
321                        BOOL FindFirstPointer(INT nProcessIdentifier, SIZE_T nPointer, POSITION* pPosition = NULL) const throw()
322                        {
323                                for(POSITION Position = GetHeadPosition(); Position; GetNext(Position))
324                                {
325                                        const CGraphData& GraphData = GetAt(Position);
326                                        if(GraphData.m_nProcessIdentifier == nProcessIdentifier && GraphData.m_nPointer == nPointer)
327                                        {
328                                                if(pPosition)
329                                                        *pPosition = Position;
330                                                return TRUE;
331                                        }
332                                }
333                                return FALSE;
334                        }
335                        BOOL FindFirstPointer(INT nProcessIdentifier, SIZE_T nPointer, CGraphData*& pGraphData) throw()
336                        {
337                                POSITION Position = NULL;
338                                if(!FindFirstPointer(nProcessIdentifier, nPointer, &Position))
339                                        return FALSE;
340                                _A(Position);
341                                pGraphData = &GetAt(Position);
342                                return TRUE;
343                        }
344                        BOOL FindLastPointer(INT nProcessIdentifier, SIZE_T nPointer, POSITION* pPosition = NULL) const throw()
345                        {
346                                for(POSITION Position = GetTailPosition(); Position; GetPrev(Position))
347                                {
348                                        const CGraphData& GraphData = GetAt(Position);
349                                        if(GraphData.m_nProcessIdentifier == nProcessIdentifier && GraphData.m_nPointer == nPointer)
350                                        {
351                                                if(pPosition)
352                                                        *pPosition = Position;
353                                                return TRUE;
354                                        }
355                                }
356                                return FALSE;
357                        }
358                        BOOL FindLastPointer(INT nProcessIdentifier, SIZE_T nPointer, CGraphData*& pGraphData) throw()
359                        {
360                                POSITION Position = NULL;
361                                if(!FindLastPointer(nProcessIdentifier, nPointer, &Position))
362                                        return FALSE;
363                                _A(Position);
364                                pGraphData = &GetAt(Position);
365                                return TRUE;
366                        }
367                        //BOOL FindFirstCallbackPointer(SIZE_T nCallbackPointer, POSITION* pPosition = NULL) const throw()
368                        //{
369                        //      return FindFirstThatT<SIZE_T>(&CGraphData::CompareCallbackPointer, nCallbackPointer, pPosition);
370                        //}
371                        BOOL FindFirstCallbackPointer(INT nProcessIdentifier, SIZE_T nCallbackPointer, POSITION* pPosition = NULL) const throw()
372                        {
373                                for(POSITION Position = GetHeadPosition(); Position; GetNext(Position))
374                                {
375                                        const CGraphData& GraphData = GetAt(Position);
376                                        if(GraphData.m_nProcessIdentifier == nProcessIdentifier && GraphData.m_nCallbackPointer == nCallbackPointer)
377                                        {
378                                                if(pPosition)
379                                                        *pPosition = Position;
380                                                return TRUE;
381                                        }
382                                }
383                                return FALSE;
384                        }
385                        BOOL FindFirstCallbackPointer(INT nProcessIdentifier, SIZE_T nCallbackPointer, CGraphData*& pGraphData) throw()
386                        {
387                                POSITION Position = NULL;
388                                if(!FindFirstCallbackPointer(nProcessIdentifier, nCallbackPointer, &Position))
389                                        return FALSE;
390                                _A(Position);
391                                pGraphData = &GetAt(Position);
392                                return TRUE;
393                        }
394                        BOOL FindLastCallbackPointer(INT nProcessIdentifier, SIZE_T nCallbackPointer, POSITION* pPosition = NULL) const throw()
395                        {
396                                for(POSITION Position = GetTailPosition(); Position; GetPrev(Position))
397                                {
398                                        const CGraphData& GraphData = GetAt(Position);
399                                        if(GraphData.m_nProcessIdentifier == nProcessIdentifier && GraphData.m_nCallbackPointer == nCallbackPointer)
400                                        {
401                                                if(pPosition)
402                                                        *pPosition = Position;
403                                                return TRUE;
404                                        }
405                                }
406                                return FALSE;
407                        }
408                        BOOL FindLastCallbackPointer(INT nProcessIdentifier, SIZE_T nCallbackPointer, CGraphData*& pGraphData) throw()
409                        {
410                                POSITION Position = NULL;
411                                if(!FindLastCallbackPointer(nProcessIdentifier, nCallbackPointer, &Position))
412                                        return FALSE;
413                                _A(Position);
414                                pGraphData = &GetAt(Position);
415                                return TRUE;
416                        }
417                };
418
419                //////////////////////////////////////////////////////////
420                // CClassData
421
422                class CClassData
423                {
424                public:
425                        CString m_sDescription;
426                        CPath m_sFilePath;
427                        LPCTSTR m_pszFileName;
428                        CPath m_sFileDirectory;
429                        TCHAR m_pszFileProductVersion[32];
430                        TCHAR m_pszFileVersion[32];
431                        ULONGLONG m_nFileSize;
432
433                public:
434                // CClassData
435                        CClassData() throw()
436                        {
437                                Initialize();
438                        }
439                        CClassData(const CLSID& ClassIdentifier)
440                        {
441                                Initialize(ClassIdentifier);
442                        }
443                        VOID Initialize() throw()
444                        {
445                                m_sDescription.Empty();
446                                m_sFilePath = NULL;
447                                m_pszFileName = NULL;
448                                m_sFileDirectory = NULL;
449                                m_pszFileProductVersion[0] = 0;
450                                m_pszFileVersion[0] = 0;
451                                m_nFileSize = 0;
452                        }
453                        VOID Initialize(const CLSID& ClassIdentifier)
454                        {
455                                Initialize();
456                                m_sDescription = _RegKeyHelper::QueryStringValue(HKEY_CLASSES_ROOT, AtlFormatString(_T("CLSID\\%ls"), _PersistHelper::StringFromIdentifier(ClassIdentifier)));
457                                m_sFilePath = (LPCTSTR) _RegKeyHelper::QueryStringValue(HKEY_CLASSES_ROOT, AtlFormatString(_T("CLSID\\%ls\\InprocServer32"), _PersistHelper::StringFromIdentifier(ClassIdentifier)));
458                                if(_tcslen(m_sFilePath))
459                                {
460                                        m_pszFileName = (LPCTSTR) m_sFilePath + m_sFilePath.FindFileName();
461                                        m_sFileDirectory = m_sFilePath;
462                                        _W(m_sFileDirectory.RemoveFileSpec());
463                                        // SUGG: File times
464                                        _VersionInfoHelper::GetVersionStrings(m_sFilePath, m_pszFileProductVersion, m_pszFileVersion);
465                                        CFindFiles FindFiles;
466                                        if(FindFiles.FindFirstFile(m_sFilePath))
467                                                m_nFileSize = ((ULONGLONG) FindFiles.GetFindData().nFileSizeHigh << 32) + FindFiles.GetFindData().nFileSizeLow;
468                                }
469                        }
470                };
471
472        private:
473                CGraphBuilderCallbackPropertySheet& m_PropertySheet;
474                CRoHyperStatic m_IntroductionStatic;
475                CRoListViewT<CGraphData*, CRoListControlDataTraitsT> m_GraphListView;
476                CRoListViewT<CLogData*, CRoListControlDataTraitsT> m_LogListView;
477                CHorSplitterWindow m_Splitter;
478                CRoHyperStatic m_CopyToClipboardStatic;
479                CProgressBarCtrl m_ProgressBar;
480                CAtlMap<INT, BOOL> m_ChangeMap;
481                CObjectPtr<CThread> m_pThread;
482                BOOL m_bThreadCompleted;
483                mutable CRoCriticalSection m_DataCriticalSection;
484                CGraphDataList m_GraphDataList;
485
486                VOID UpdateControls()
487                {
488                        m_LogListView.EnableWindow(m_GraphListView.GetSelectedCount() == 1);
489                }
490                static SIZE_T StringToPointer(const CHAR* pszString)
491                {
492                        INT nValue;
493                        __D(StrToIntExA(pszString, STIF_SUPPORT_HEX, &nValue), E_UNNAMED);
494                        return (SIZE_T) nValue;
495                }
496                static HRESULT StringToResult(const CHAR* pszString)
497                {
498                        return (HRESULT) StringToPointer(pszString);
499                }
500                DWORD ThreadProc(CThread*, CEvent& InitializationEvent, CEvent& TerminationEvent)
501                {
502                        CMultiThreadedApartment MultiThreadedApartment;
503                        const CPath sPath = m_PropertySheet.m_sPath;
504                        _W(InitializationEvent.Set());
505                        CRoMapT<INT, CStringA> ProcessPathMap;
506                        CGraphDataList GraphDataList;
507                        _ATLTRY
508                        {
509                                CAtlFile File;
510                                __C(File.Create(sPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING));
511                                ULONGLONG nFileSize;
512                                __C(File.GetSize(nFileSize));
513                                __C(File.LockRange(0, nFileSize));
514                                _ATLTRY
515                                {
516                                        CHeapPtr<CHAR> pszData;
517                                        static const SIZE_T g_nDataCapacity = 4 << 20; // 4 MB
518                                        __D(pszData.Reallocate(g_nDataCapacity), E_OUTOFMEMORY);
519                                        SIZE_T nDataSize = 0, nDataPosition = 0;
520                                        BOOL bDataReadComplete = FALSE;
521                                        HRESULT nResult = S_OK;
522                                        for(UINT nLineIndex = 0; ; nLineIndex++)
523                                        {
524                                                #pragma region Termination Check
525                                                if(nLineIndex % (4 << 10) == 0)
526                                                {
527                                                        const DWORD nWaitResult = WaitForSingleObject(TerminationEvent, 0);
528                                                        _Z5(atlTraceSync, 5, _T("nWaitResult 0x%x\n"), nWaitResult);
529                                                        _A(nWaitResult == WAIT_OBJECT_0 || nWaitResult == WAIT_TIMEOUT);
530                                                        if(nWaitResult != WAIT_TIMEOUT)
531                                                        {
532                                                                nResult = S_FALSE;
533                                                                break;
534                                                        }
535                                                }
536                                                #pragma endregion
537                                                _A(nDataPosition <= nDataSize);
538                                                #pragma region Read Data
539                                                if(!bDataReadComplete && (nDataSize - nDataPosition) < g_nDataCapacity / 4)
540                                                {
541                                                        #pragma region Compact Data
542                                                        const SIZE_T nCarryOverDataSize = nDataSize - nDataPosition;
543                                                        if(nCarryOverDataSize)
544                                                                _W(!memmove_s(pszData, g_nDataCapacity, pszData + nDataPosition, nCarryOverDataSize));
545                                                        nDataSize -= nDataPosition;
546                                                        nDataPosition = 0;
547                                                        pszData[nDataSize] = 0;
548                                                        #pragma endregion
549                                                        #pragma region Progress
550                                                        ULONGLONG nFilePosition;
551                                                        __C(File.GetPosition(nFilePosition));
552                                                        _W(PostPrivateMessage(WM_THREADPROGRESS, (WPARAM) ((16 << 10) * nFilePosition / nFileSize)));
553                                                        #pragma endregion
554                                                        const SIZE_T nReadableDataSize = g_nDataCapacity - nDataSize - 1;
555                                                        DWORD nReadDataSize = 0;
556                                                        __C(File.Read(pszData + nDataSize, (DWORD) nReadableDataSize, nReadDataSize));
557                                                        _Z5(atlTraceGeneral, 5, _T("nDataSize %d, nReadableDataSize %d, nReadDataSize %d\n"), nDataSize, nReadableDataSize, nReadDataSize);
558                                                        bDataReadComplete = (SIZE_T) nReadDataSize < nReadableDataSize;
559                                                        nDataSize += nReadDataSize;
560                                                        _A(nDataSize < g_nDataCapacity);
561                                                        pszData[nDataSize] = 0;
562                                                }
563                                                #pragma endregion
564                                                LPSTR pszLineData = pszData + nDataPosition;
565                                                LPSTR pszSeparator = strchr(pszLineData, '\n');
566                                                // NOTE: Valid lines are terminated with \r\n, so we can skip incomplete line
567                                                if(!pszSeparator)
568                                                        break;
569                                                nDataPosition = (pszSeparator + 1) - pszData;
570                                                _A(nDataPosition <= nDataSize);
571                                                pszSeparator[0] = 0;
572                                                if(pszSeparator[-1] == '\r')
573                                                        pszSeparator[-1] = 0;
574                                                #pragma region Process Line
575                                                _ATLTRY
576                                                {
577                                                        #pragma region Parse Data
578                                                        static CAtlStaticRegExp<CAtlRECharTraitsA> g_LineExpression("^" 
579                                                                "{[0-9]+}" "\\-" // Year
580                                                                "{[0-9]+}" "\\-" // Month
581                                                                "{[0-9]+}" " " // Day
582                                                                "{[0-9]+}" "\\:" // Hour
583                                                                "{[0-9]+}" "\\:" // Minute
584                                                                "{[0-9]+}" "\t" // Second
585                                                                "{[0-9]+}" "\t" // Process Identifier
586                                                                "{[0-9]+}" "\t" // Thread Identifier
587                                                                "{.+}" // Payload
588                                                                "$", FALSE);
589                                                        CAtlREMatchContext<CAtlRECharTraitsA> MatchContext;
590                                                        __D(g_LineExpression.Match(pszLineData, &MatchContext), E_UNNAMED);
591                                                        INT pnValues[8];
592                                                        for(SIZE_T nIndex = 0; nIndex < DIM(pnValues); nIndex++)
593                                                                __D(AtlStringToInteger(_ReHelper::GetMatchString(MatchContext, (INT) nIndex), pnValues[nIndex]), E_UNNAMED);
594                                                        SYSTEMTIME Time;
595                                                        ZeroMemory(&Time, sizeof Time);
596                                                        Time.wYear = (WORD) pnValues[0];
597                                                        Time.wMonth = (WORD) pnValues[1];
598                                                        Time.wDay = (WORD) pnValues[2];
599                                                        Time.wHour = (WORD) pnValues[3];
600                                                        Time.wMinute = (WORD) pnValues[4];
601                                                        Time.wSecond = (WORD) pnValues[5];
602                                                        ULONGLONG nTime;
603                                                        _W(SystemTimeToFileTime(&Time, &reinterpret_cast<FILETIME&>(nTime)));
604                                                        const INT& nProcessIdentifier = pnValues[6];
605                                                        const INT& nThreadIdentifier = pnValues[7];
606                                                        _Y1(AtlFormatString(_T("nTime %s, nProcessIdentifier %d, nThreadIdentifier %d"), _StringHelper::FormatDateTime(nTime), nProcessIdentifier, nThreadIdentifier));
607                                                        LPCSTR pszPayloadLineData, pszPayloadLineDataSeparator;
608                                                        MatchContext.GetMatch(8, &pszPayloadLineData, &pszPayloadLineDataSeparator);
609                                                        _A(!*pszPayloadLineDataSeparator);
610                                                        #pragma endregion
611                                                        //CAtlREMatchContext<CAtlRECharTraitsA> MatchContext;
612                                                        static CAtlStaticRegExp<CAtlRECharTraitsA> g_ExpressionA("::CAmGraphBuilderCallback::Initialize: this {0x[0-9A-F]+}, pSpy {0x[0-9A-F]+}", FALSE);
613                                                        static CAtlStaticRegExp<CAtlRECharTraitsA> g_ExpressionB("::CAmGraphBuilderCallback::SelectedFilter: this {0x[0-9A-F]+}, pMoniker {.+}", FALSE);
614                                                        static CAtlStaticRegExp<CAtlRECharTraitsA> g_ExpressionC("::CAmGraphBuilderCallback::SelectedFilter: this {0x[0-9A-F]+}, nSelectedFilterResult {0x[0-9A-F]+}", FALSE);
615                                                        static CAtlStaticRegExp<CAtlRECharTraitsA> g_ExpressionD("::CAmGraphBuilderCallback::CreatedFilter: this {0x[0-9A-F]+}, pBaseFilter {0x[0-9A-F]+} {\\{[^\\}]+\\}} \\\"{[^\\\"]*}\\\"", FALSE);
616                                                        static CAtlStaticRegExp<CAtlRECharTraitsA> g_ExpressionE("::CAmGraphBuilderCallback::CreatedFilter: this {0x[0-9A-F]+}, nCreatedFilterResult {0x[0-9A-F]+}", FALSE);
617                                                        static CAtlStaticRegExp<CAtlRECharTraitsA> g_ExpressionF("::AddFilter: this {0x[0-9A-F]+}, pBaseFilter {0x[0-9A-F]+} {\\{[^\\}]+\\}}, pszName \\\"{[^\\\"]*}\\\"", FALSE);
618                                                        static CAtlStaticRegExp<CAtlRECharTraitsA> g_ExpressionG("::AddFilter: this {0x[0-9A-F]+}, sName \\\"{[^\\\"]*}\\\"", FALSE);
619                                                        static CAtlStaticRegExp<CAtlRECharTraitsA> g_ExpressionH("::RemoveFilter: this {0x[0-9A-F]+}, pBaseFilter {0x[0-9A-F]+}", FALSE);
620                                                        static CAtlStaticRegExp<CAtlRECharTraitsA> g_ExpressionI("::RemoveFilter: this {0x[0-9A-F]+}, sName \\\"{[^\\\"]*}\\\"", FALSE);
621                                                        static CAtlStaticRegExp<CAtlRECharTraitsA> g_ExpressionJ("version is [0-9\\.\\,]+, running in \\\"{[^\\\"]+}\\\" at ", FALSE);
622                                                        // TODO: Connect
623                                                        if(g_ExpressionA.Match(pszPayloadLineData, &MatchContext))
624                                                        {
625                                                                #pragma region Status Callback Initialization
626                                                                const SIZE_T nCallbackPointer = StringToPointer(_ReHelper::GetMatchString(MatchContext, 0));
627                                                                const SIZE_T nPointer = StringToPointer(_ReHelper::GetMatchString(MatchContext, 1));
628                                                                _Z5(atlTraceGeneral, 5, _T("nCallbackPointer 0x%p, nPointer 0x%p\n"), nCallbackPointer, nPointer);
629                                                                const POSITION Position = GraphDataList.AddTail();
630                                                                CGraphData& GraphData = GraphDataList.GetAt(Position);
631                                                                GraphData.m_nProcessIdentifier = nProcessIdentifier;
632                                                                #pragma region Process Path
633                                                                {
634                                                                        _A(GraphData.m_sProcessPath.IsEmpty());
635                                                                        const POSITION Position = ProcessPathMap.Lookup(nProcessIdentifier);
636                                                                        if(Position)
637                                                                                GraphData.m_sProcessPath = CA2CT(ProcessPathMap.GetValueAt(Position));
638                                                                }
639                                                                #pragma endregion
640                                                                GraphData.m_nTime = nTime;
641                                                                GraphData.m_nPointer = nPointer;
642                                                                GraphData.m_nCallbackPointer = nCallbackPointer;
643                                                                #pragma endregion
644                                                        } else
645                                                        if(g_ExpressionB.Match(pszPayloadLineData, &MatchContext))
646                                                        {
647                                                                #pragma region IAMGraphBuilderCallback::SelectedFilter Call
648                                                                const SIZE_T nCallbackPointer = StringToPointer(_ReHelper::GetMatchString(MatchContext, 0));
649                                                                const CStringA sMonikerDisplayName = _ReHelper::GetMatchString(MatchContext, 1);
650                                                                _Z5(atlTraceGeneral, 5, _T("nCallbackPointer 0x%p, sMonikerDisplayName \"%hs\"\n"), nCallbackPointer, sMonikerDisplayName);
651                                                                CGraphData* pGraphData = NULL;
652                                                                if(GraphDataList.FindLastCallbackPointer(nProcessIdentifier, nCallbackPointer, pGraphData))
653                                                                {
654                                                                        _A(pGraphData);
655                                                                        _W(pGraphData->m_LogDataList.AddTail(CLogData(nTime, sMonikerDisplayName)));
656                                                                }
657                                                                #pragma endregion
658                                                        } else
659                                                        if(g_ExpressionC.Match(pszPayloadLineData, &MatchContext))
660                                                        {
661                                                                #pragma region Site IAMGraphBuilderCallback::SelectedFilter Return
662                                                                const SIZE_T nCallbackPointer = StringToPointer(_ReHelper::GetMatchString(MatchContext, 0));
663                                                                const HRESULT nSelectedFilterResult = StringToResult(_ReHelper::GetMatchString(MatchContext, 1));
664                                                                _Z5(atlTraceGeneral, 5, _T("nCallbackPointer 0x%p, nSelectedFilterResult 0x%08x\n"), nCallbackPointer, nSelectedFilterResult);
665                                                                CGraphData* pGraphData = NULL;
666                                                                if(GraphDataList.FindLastCallbackPointer(nProcessIdentifier, nCallbackPointer, pGraphData))
667                                                                {
668                                                                        _A(pGraphData);
669                                                                        if(!pGraphData->m_LogDataList.IsEmpty())
670                                                                        {
671                                                                                // WARN: A bit unsafe, we could also check thread identifier match
672                                                                                pGraphData->m_LogDataList.GetTail().SetSiteResult(nSelectedFilterResult);
673                                                                        }
674                                                                }
675                                                                #pragma endregion
676                                                        } else
677                                                        if(g_ExpressionD.Match(pszPayloadLineData, &MatchContext))
678                                                        {
679                                                                #pragma region IAMGraphBuilderCallback::CreatedFilter Call
680                                                                const SIZE_T nCallbackPointer = StringToPointer(_ReHelper::GetMatchString(MatchContext, 0));
681                                                                const SIZE_T nFilterPointer = StringToPointer(_ReHelper::GetMatchString(MatchContext, 1));
682                                                                const CLSID FilterClassIdentifier = _PersistHelper::ClassIdentifierFromString(CStringW(_ReHelper::GetMatchString(MatchContext, 2)));
683                                                                const CStringA sFilterName = _ReHelper::GetMatchString(MatchContext, 3);
684                                                                _Z5(atlTraceGeneral, 5, _T("nCallbackPointer 0x%p, nFilterPointer 0x%p, FilterClassIdentifier %ls, sFilterName \"%hs\"\n"), nCallbackPointer, nFilterPointer, _PersistHelper::StringFromIdentifier(FilterClassIdentifier), sFilterName);
685                                                                CGraphData* pGraphData = NULL;
686                                                                if(GraphDataList.FindLastCallbackPointer(nProcessIdentifier, nCallbackPointer, pGraphData))
687                                                                {
688                                                                        _A(pGraphData);
689                                                                        _W(pGraphData->m_LogDataList.AddTail(CLogData(nTime, CLogData::TYPE_CREATEDFILTER, nFilterPointer, FilterClassIdentifier, sFilterName)));
690                                                                }
691                                                                #pragma endregion
692                                                        } else
693                                                        if(g_ExpressionE.Match(pszPayloadLineData, &MatchContext))
694                                                        {
695                                                                #pragma region Site IAMGraphBuilderCallback::CreatedFilter Return
696                                                                const SIZE_T nCallbackPointer = StringToPointer(_ReHelper::GetMatchString(MatchContext, 0));
697                                                                const HRESULT nCreatedFilterResult = StringToResult(_ReHelper::GetMatchString(MatchContext, 1));
698                                                                _Z5(atlTraceGeneral, 5, _T("nCallbackPointer 0x%p, nCreatedFilterResult 0x%08x\n"), nCallbackPointer, nCreatedFilterResult);
699                                                                CGraphData* pGraphData = NULL;
700                                                                if(GraphDataList.FindLastCallbackPointer(nProcessIdentifier, nCallbackPointer, pGraphData))
701                                                                {
702                                                                        _A(pGraphData);
703                                                                        if(!pGraphData->m_LogDataList.IsEmpty())
704                                                                        {
705                                                                                // WARN: A bit unsafe, we could also check thread identifier match
706                                                                                pGraphData->m_LogDataList.GetTail().SetSiteResult(nCreatedFilterResult);
707                                                                        }
708                                                                }
709                                                                #pragma endregion
710                                                        } else
711                                                        if(g_ExpressionF.Match(pszPayloadLineData, &MatchContext))
712                                                        {
713                                                                #pragma region AddFilter
714                                                                const SIZE_T nPointer = StringToPointer(_ReHelper::GetMatchString(MatchContext, 0));
715                                                                const SIZE_T nFilterPointer = StringToPointer(_ReHelper::GetMatchString(MatchContext, 1));
716                                                                const CLSID FilterClassIdentifier = _PersistHelper::ClassIdentifierFromString(CStringW(_ReHelper::GetMatchString(MatchContext, 2)));
717                                                                const CStringA sFilterName = _ReHelper::GetMatchString(MatchContext, 3);
718                                                                _Z5(atlTraceGeneral, 5, _T("nPointer 0x%p, nFilterPointer 0x%p, FilterClassIdentifier %ls, sFilterName \"%hs\"\n"), nPointer, nFilterPointer, _PersistHelper::StringFromIdentifier(FilterClassIdentifier), sFilterName);
719                                                                CGraphData* pGraphData = NULL;
720                                                                if(GraphDataList.FindLastPointer(nProcessIdentifier, nPointer, pGraphData))
721                                                                {
722                                                                        _A(pGraphData);
723                                                                        _W(pGraphData->m_FilterDataMap.SetAt(nFilterPointer, CFilterData(nFilterPointer, FilterClassIdentifier, sFilterName)));
724                                                                        _W(pGraphData->m_LogDataList.AddTail(CLogData(nTime, CLogData::TYPE_ADDFILTER, nFilterPointer, FilterClassIdentifier, sFilterName)));
725                                                                }
726                                                                #pragma endregion
727                                                        } else
728                                                        if(g_ExpressionG.Match(pszPayloadLineData, &MatchContext))
729                                                        {
730                                                                #pragma region AddFilter Name
731                                                                const SIZE_T nPointer = StringToPointer(_ReHelper::GetMatchString(MatchContext, 0));
732                                                                const CStringA sName = _ReHelper::GetMatchString(MatchContext, 1);
733                                                                _Z5(atlTraceGeneral, 5, _T("nPointer 0x%p, sName \"%hs\"\n"), nPointer, sName);
734                                                                CGraphData* pGraphData = NULL;
735                                                                if(GraphDataList.FindLastPointer(nProcessIdentifier, nPointer, pGraphData))
736                                                                {
737                                                                        _A(pGraphData);
738                                                                        if(!pGraphData->m_LogDataList.IsEmpty())
739                                                                        {
740                                                                                // WARN: A bit unsafe, we could also check thread identifier match
741                                                                                CLogData* pLogData = &pGraphData->m_LogDataList.GetTail();
742                                                                                if(pLogData->m_Type == CLogData::TYPE_ADDFILTER) // && pLogData->m_sFilterName.IsEmpty())
743                                                                                        pLogData->m_sFilterName = sName;
744                                                                        }
745                                                                }
746                                                                #pragma endregion
747                                                        } else
748                                                        if(g_ExpressionH.Match(pszPayloadLineData, &MatchContext))
749                                                        {
750                                                                #pragma region RemoveFilter
751                                                                const SIZE_T nPointer = StringToPointer(_ReHelper::GetMatchString(MatchContext, 0));
752                                                                const SIZE_T nFilterPointer = StringToPointer(_ReHelper::GetMatchString(MatchContext, 1));
753                                                                _Z5(atlTraceGeneral, 5, _T("nPointer 0x%p, nFilterPointer 0x%p\n"), nPointer, nFilterPointer);
754                                                                CGraphData* pGraphData = NULL;
755                                                                if(GraphDataList.FindLastPointer(nProcessIdentifier, nPointer, pGraphData))
756                                                                {
757                                                                        _A(pGraphData);
758                                                                        _W(pGraphData->m_LogDataList.AddTail(CLogData(nTime, nFilterPointer)));
759                                                                }
760                                                                #pragma endregion
761                                                        } else
762                                                        if(g_ExpressionI.Match(pszPayloadLineData, &MatchContext))
763                                                        {
764                                                                #pragma region RemoveFilter Name
765                                                                const SIZE_T nPointer = StringToPointer(_ReHelper::GetMatchString(MatchContext, 0));
766                                                                const CStringA sName = _ReHelper::GetMatchString(MatchContext, 1);
767                                                                _Z5(atlTraceGeneral, 5, _T("nPointer 0x%p, sName \"%hs\"\n"), nPointer, sName);
768                                                                CGraphData* pGraphData = NULL;
769                                                                if(GraphDataList.FindLastPointer(nProcessIdentifier, nPointer, pGraphData))
770                                                                {
771                                                                        _A(pGraphData);
772                                                                        if(!pGraphData->m_LogDataList.IsEmpty())
773                                                                        {
774                                                                                // WARN: A bit unsafe, we could also check thread identifier match
775                                                                                CLogData* pLogData = &pGraphData->m_LogDataList.GetTail();
776                                                                                if(pLogData->m_Type == CLogData::TYPE_REMOVEFILTER && pLogData->m_sFilterName.IsEmpty())
777                                                                                        pLogData->m_sFilterName = sName;
778                                                                        }
779                                                                }
780                                                                #pragma endregion
781                                                        } else
782                                                        if(g_ExpressionJ.Match(pszPayloadLineData, &MatchContext))
783                                                        {
784                                                                #pragma region Library Initialization
785                                                                const CStringA sPath = _ReHelper::GetMatchString(MatchContext, 0);
786                                                                _Z5(atlTraceGeneral, 5, _T("sPath \"%hs\"\n"), sPath);
787                                                                ProcessPathMap[nProcessIdentifier] = sPath;
788                                                                #pragma endregion
789                                                        } else
790                                                                ;
791                                                        _Y2();
792                                                }
793                                                _ATLCATCHALL()
794                                                {
795                                                        _Z_EXCEPTION();
796                                                }
797                                                #pragma endregion
798                                        }
799                                        {
800                                                CRoCriticalSectionLock DataLock(m_DataCriticalSection);
801                                                SwapMemory(&m_GraphDataList, &GraphDataList);
802                                        }
803                                        PostPrivateMessage(WM_THREADCOMPLETED, (WPARAM) nResult);
804                                }
805                                _ATLCATCHALL()
806                                {
807                                        __C(File.UnlockRange(0, nFileSize));
808                                        _ATLRETHROW;
809                                }
810                                __C(File.UnlockRange(0, nFileSize));
811                        }
812                        _ATLCATCH(Exception)
813                        {
814                                PostPrivateMessage(WM_THREADCOMPLETED, (WPARAM) (HRESULT) Exception);
815                        }
816                        return 0;
817                }
818
819        public:
820        // CGraphPropertyPage
821                CGraphPropertyPage(CGraphBuilderCallbackPropertySheet* pPropertySheet) throw() :
822                        m_PropertySheet(*pPropertySheet)
823                {
824                }
825
826        // CDialogResize                               
827                VOID DlgResize_UpdateLayout(INT nWidth, INT nHeight)
828                {
829                        __super::DlgResize_UpdateLayout(nWidth, nHeight);
830                        CRect SplitterPosition, ProgressPosition;
831                        _W(m_Splitter.GetWindowRect(SplitterPosition));
832                        _W(ScreenToClient(SplitterPosition));
833                        _W(m_ProgressBar.GetWindowRect(ProgressPosition));
834                        _W(ScreenToClient(ProgressPosition));
835                        const LONG nX = (SplitterPosition.Height() - ProgressPosition.Height()) / 2;
836                        ProgressPosition = SplitterPosition;
837                        ProgressPosition.DeflateRect(0, nX);
838                        _W(m_ProgressBar.MoveWindow(ProgressPosition));
839                }
840                       
841        // Window message handlers
842                LRESULT OnInitDialog(HWND, LPARAM)
843                {
844                        _ATLTRY
845                        {
846                                _W(m_IntroductionStatic.SubclassWindow(GetDlgItem(IDC_GRAPHBUILDERCALLBACK_GRAPH_INTRODUCTION)));
847                                CSize IconSize(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
848                                #pragma region Log List View
849                                {
850                                        m_GraphListView.Initialize(GetDlgItem(IDC_GRAPHBUILDERCALLBACK_GRAPH_GRAPH));
851                                        CImageList ImageList;
852                                        _W(ImageList.Create(IconSize.cx, IconSize.cy, ILC_COLOR32 | ILC_MASK, 1, 1));
853                                        _W(!m_GraphListView.SetImageList(ImageList.Detach(), LVSIL_SMALL));
854                                }
855                                #pragma endregion
856                                #pragma region Log List View
857                                {
858                                        m_LogListView.Initialize(GetDlgItem(IDC_GRAPHBUILDERCALLBACK_GRAPH_LOG));
859                                        CImageList ImageList;
860                                        _W(ImageList.Create(IconSize.cx, IconSize.cy, ILC_COLOR32 | ILC_MASK, 1, 1));
861                                        _W(ImageList.AddIcon(AtlLoadIconImage(IDI_LISTVIEW_SUCCESS, LR_DEFAULTCOLOR, IconSize.cx, IconSize.cy)) == 0);
862                                        _W(ImageList.AddIcon(AtlLoadIconImage(IDI_LISTVIEW_FAILURE, LR_DEFAULTCOLOR, IconSize.cx, IconSize.cy)) == 1);
863                                        _W(ImageList.AddIcon(AtlLoadIconImage(IDI_GRAPHBUILDERCALLBACK_LISTVIEW_ADDFILTER, LR_DEFAULTCOLOR, IconSize.cx, IconSize.cy)) == 2);
864                                        _W(ImageList.AddIcon(AtlLoadIconImage(IDI_GRAPHBUILDERCALLBACK_LISTVIEW_REMOVEFILTER, LR_DEFAULTCOLOR, IconSize.cx, IconSize.cy)) == 3);
865                                        _W(ImageList.AddIcon(AtlLoadIconImage(IDI_GRAPHBUILDERCALLBACK_LISTVIEW_SELECTEDFILTER, LR_DEFAULTCOLOR, IconSize.cx, IconSize.cy)) == 4);
866                                        _W(ImageList.AddIcon(AtlLoadIconImage(IDI_GRAPHBUILDERCALLBACK_LISTVIEW_CREATEDFILTER, LR_DEFAULTCOLOR, IconSize.cx, IconSize.cy)) == 5);
867                                        _W(!m_LogListView.SetImageList(ImageList.Detach(), LVSIL_SMALL));
868                                        CToolTipCtrl ToolTip = m_LogListView.GetToolTips();
869                                        ToolTip.SetMaxTipWidth(GetSystemMetrics(SM_CXSCREEN) / 2);
870                                        ToolTip.SetDelayTime(TTDT_AUTOPOP, 30 * 1000); // 30 seconds
871                                }
872                                #pragma endregion
873                                #pragma region Splitter
874                                CRect GraphPosition, LogPosition, SplitterPosition;
875                                _W(m_GraphListView.GetWindowRect(GraphPosition));
876                                _W(ScreenToClient(GraphPosition));
877                                _W(m_LogListView.GetWindowRect(LogPosition));
878                                _W(ScreenToClient(LogPosition));
879                                _W(SplitterPosition.UnionRect(GraphPosition, LogPosition));
880                                _W(m_Splitter.Create(m_hWnd, SplitterPosition, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CONTROLPARENT, IDC_GRAPHBUILDERCALLBACK_GRAPH_SPLITTER));
881                                m_GraphListView.SetParent(m_Splitter);
882                                m_LogListView.SetParent(m_Splitter);
883                                m_Splitter.SetSplitterPanes(m_GraphListView, m_LogListView);
884                                m_Splitter.SetSplitterPos(GraphPosition.Height());
885                                m_Splitter.ShowWindow(SW_HIDE);
886                                #pragma endregion
887                                _W(m_CopyToClipboardStatic.SubclassWindow(GetDlgItem(IDC_GRAPHBUILDERCALLBACK_GRAPH_COPYTOCLIPBOARD)));
888                                CRoHyperStatic::ArrangeHorizontally(&m_CopyToClipboardStatic, NULL);
889                                m_ProgressBar = GetDlgItem(IDC_GRAPHBUILDERCALLBACK_GRAPH_PROGRESS);
890                                m_ProgressBar.SetRange(0, 16 << 10);
891                                m_ProgressBar.SetStep(256);
892                                m_ProgressBar.ShowWindow(SW_SHOW);
893                                DlgResize_Init(FALSE, FALSE);
894                                {
895                                        CRect Position;
896                                        _W(GetClientRect(Position));
897                                        DlgResize_UpdateLayout(Position.Width(), Position.Height());
898                                }
899                                m_bThreadCompleted = FALSE;
900                                m_ChangeMap.RemoveAll();
901                                UpdateControls();
902                                #pragma region Default Property Sheet Size
903                                CRect Position;
904                                _W(m_PropertySheet.GetWindowRect(Position));
905                                Position.InflateRect(6 * Position.Width() / 8, 5 * Position.Width() / 8);
906                                CSize ScreenExtent(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
907                                ScreenExtent.cx -= ScreenExtent.cx / 8;
908                                ScreenExtent.cy -= ScreenExtent.cy / 8;
909                                if(Position.Width() > ScreenExtent.cx)
910                                        Position.right = Position.left + ScreenExtent.cx;
911                                if(Position.Height() > ScreenExtent.cy)
912                                        Position.bottom = Position.top + ScreenExtent.cy;
913                                _W(m_PropertySheet.MoveWindow(Position));
914                                _W(m_PropertySheet.CenterWindow());
915                                #pragma endregion
916                        }
917                        _ATLCATCHALL()
918                        {
919                                for(CWindow Window = GetWindow(GW_CHILD); Window.IsWindow(); Window = Window.GetWindow(GW_HWNDNEXT))
920                                        Window.EnableWindow(FALSE);
921                                _ATLRETHROW;
922                        }
923                        return TRUE;
924                }
925                LRESULT OnDestroy()
926                {
927                        m_pThread = NULL;
928                        return 0;
929                }
930                INT OnSetActive() throw()
931                {
932                        _ATLTRY
933                        {
934                                if(!m_bThreadCompleted)
935                                {
936                                        _A(!m_pThread);
937                                        m_ProgressBar.SetPos(0);
938                                        CObjectPtr<CThread> pThread;
939                                        __E(pThread.Construct()->Initialize(this, &CGraphPropertyPage::ThreadProc));
940                                        m_pThread = pThread;
941                                }
942                        }
943                        _ATLCATCHALL()
944                        {
945                                _Z_EXCEPTION();
946                                return -1;
947                        }
948                        return 0;
949                }
950                LRESULT OnThreadProgress(UINT, WPARAM wParam, LPARAM)
951                {
952                        m_ProgressBar.SetPos((INT) wParam);
953                        return 0;
954                }
955                LRESULT OnThreadCompleted(UINT, WPARAM wParam, LPARAM)
956                {
957                        const HRESULT nResult = (HRESULT) wParam;
958                        _ATLTRY
959                        {
960                                __C(nResult);
961                                CWaitCursor WaitCursor;
962                                CWindowRedraw NoGraphListViewRedraw(m_GraphListView);
963                                m_GraphListView.DeleteAllItems();
964                                CImageList ImageList = m_GraphListView.GetImageList(LVSIL_SMALL);
965                                CRoMapT<CStringA, INT, CStringElementTraitsI<CStringA> > PathIconIndexMap;
966                                for(POSITION Position = m_GraphDataList.GetHeadPosition(); Position; m_GraphDataList.GetNext(Position))
967                                {
968                                        CGraphData* pGraphData = &m_GraphDataList.GetAt(Position);
969                                        // NOTE: Reverse order
970                                        const INT nItem = m_GraphListView.InsertItem(0, pGraphData);
971                                        _A(nItem >= 0);
972                                        #pragma region Retrieve File Icon
973                                        pGraphData->m_nImageIndex = -1;
974                                        if(!pGraphData->m_sProcessPath.IsEmpty())
975                                                _ATLTRY
976                                                { 
977                                                        if(!PathIconIndexMap.Lookup(pGraphData->m_sProcessPath, pGraphData->m_nImageIndex))
978                                                        {
979                                                                SHFILEINFO FileInformation;
980                                                                ZeroMemory(&FileInformation, sizeof FileInformation);
981                                                                if(SHGetFileInfo(CA2CT(pGraphData->m_sProcessPath), 0, &FileInformation, sizeof FileInformation, SHGFI_ICON | SHGFI_SMALLICON))
982                                                                {
983                                                                        CIcon Icon;
984                                                                        Icon.Attach(FileInformation.hIcon);
985                                                                        pGraphData->m_nImageIndex = ImageList.AddIcon(Icon);
986                                                                        _A(pGraphData->m_nImageIndex >= 0);
987                                                                        PathIconIndexMap[pGraphData->m_sProcessPath] = pGraphData->m_nImageIndex;
988                                                                }
989                                                        }
990                                                }
991                                                _ATLCATCHALL()
992                                                {
993                                                        _Z_EXCEPTION();
994                                                        _A(pGraphData->m_nImageIndex == -1);
995                                                }
996                                        #pragma endregion
997                                }
998                                UpdateControls();
999                                m_ProgressBar.ShowWindow(SW_HIDE);
1000                                m_Splitter.ShowWindow(SW_SHOW);
1001                                m_GraphListView.SetFocus();
1002                        }
1003                        _ATLCATCH(Exception)
1004                        {
1005                                _Z_ATLEXCEPTION(Exception);
1006                                AtlExceptionMessageBox(m_hWnd, Exception);
1007                        }
1008                        m_bThreadCompleted = TRUE;
1009                        m_pThread = NULL;
1010                        return 0;
1011                }
1012                //LRESULT OnChanged(UINT, INT nIdentifier, HWND)
1013                //{
1014                //      m_ChangeMap[nIdentifier] = TRUE;
1015                //      SetModified();
1016                //      UpdateControls();
1017                //      return 0;
1018                //}
1019                LRESULT OnGraphListViewGetDispInfo(NMLVDISPINFO* pHeader)
1020                {
1021                        const CGraphData* pGraphData = m_GraphListView.DataFromParameter(pHeader->item.lParam);
1022                        if(pHeader->item.mask & LVIF_TEXT)
1023                        {
1024                                CString& sTextBuffer = m_GraphListView.GetTextBufferString(TRUE);
1025                                switch(pHeader->item.iSubItem)
1026                                {
1027                                case 1: // Process
1028                                        sTextBuffer = AtlFormatString(_T("%d"), pGraphData->m_nProcessIdentifier);
1029                                        break;
1030                                case 2: // Name
1031                                        sTextBuffer = pGraphData->GetProcessName();
1032                                        break;
1033                                case 3: // Directory
1034                                        sTextBuffer = pGraphData->GetProcessDirectory();
1035                                        break;
1036                                default: // Time
1037                                        sTextBuffer = _StringHelper::FormatDateTime(pGraphData->m_nTime);
1038                                }
1039                                pHeader->item.pszText = m_GraphListView.GetTextBuffer();
1040                        }
1041                        if(pHeader->item.mask & LVIF_IMAGE)
1042                                pHeader->item.iImage = pGraphData->m_nImageIndex;
1043                        return 0;
1044                }
1045                LRESULT OnGraphListViewGetInfoTip(NMLVGETINFOTIP* pHeader)
1046                {
1047                        const CGraphData* pGraphData = m_GraphListView.GetItemData(pHeader->iItem);
1048                        CString& sTextBuffer = m_GraphListView.GetTextBufferString(TRUE);
1049                        sTextBuffer.AppendFormat(_T("Time: %s\r\n"), _StringHelper::FormatDateTime(pGraphData->m_nTime));
1050                        sTextBuffer.AppendFormat(_T("Process: %d\r\n"), pGraphData->m_nProcessIdentifier);
1051                        if(!pGraphData->m_sProcessPath.IsEmpty())
1052                        {
1053                                sTextBuffer.AppendFormat(_T("Process Name: %s\r\n"), pGraphData->GetProcessName());
1054                                sTextBuffer.AppendFormat(_T("Process Directory: %s\r\n"), pGraphData->GetProcessDirectory());
1055                        }
1056                        sTextBuffer.TrimRight(_T("\t\n\r ."));
1057                        #pragma region Clipboard Copy
1058                        if(GetKeyState(VK_CONTROL) < 0 && GetKeyState(VK_SHIFT) < 0)
1059                                _ATLTRY
1060                                {
1061                                        SetClipboardText(m_hWnd, sTextBuffer);
1062                                        MessageBeep(MB_OK);
1063                                }
1064                                _ATLCATCHALL()
1065                                {
1066                                        _Z_EXCEPTION();
1067                                        MessageBeep(MB_ICONERROR);
1068                                }
1069                        #pragma endregion
1070                        _tcsncpy_s(pHeader->pszText, pHeader->cchTextMax, m_GraphListView.GetTextBuffer(), _TRUNCATE);
1071                        return 0;
1072                }
1073                LRESULT OnGraphListViewItemChanged(NMLISTVIEW* pHeader)
1074                {
1075                        UpdateControls();
1076                        if(pHeader->iItem >= 0 && ((pHeader->uOldState ^ pHeader->uNewState) & LVIS_SELECTED) && m_GraphListView.GetSelectedCount() == 1)
1077                        {
1078                                CWindowRedraw NoLogListViewRedraw(m_LogListView);
1079                                m_LogListView.DeleteAllItems();
1080                                CGraphData* pGraphData = m_GraphListView.GetItemData(m_GraphListView.GetNextItem(-1, LVNI_SELECTED));
1081                                CLogDataList& LogDataList = pGraphData->m_LogDataList;
1082                                for(POSITION Position = LogDataList.GetHeadPosition(); Position; LogDataList.GetNext(Position))
1083                                {
1084                                        CLogData* pLogData = &LogDataList.GetAt(Position);
1085                                        const INT nItem = m_LogListView.InsertItem(m_LogListView.GetItemCount(), pLogData);
1086                                        _A(nItem >= 0);
1087                                }
1088                        }
1089                        return 0;
1090                }
1091                LRESULT OnLogListViewGetDispInfo(NMLVDISPINFO* pHeader)
1092                {
1093                        const CLogData* pLogData = m_LogListView.DataFromParameter(pHeader->item.lParam);
1094                        if(pHeader->item.mask & LVIF_TEXT)
1095                        {
1096                                CString& sTextBuffer = m_LogListView.GetTextBufferString(TRUE);
1097                                switch(pHeader->item.iSubItem)
1098                                {
1099                                case 1: // Event
1100                                        sTextBuffer = pLogData->GetFriendlyEventName();
1101                                        break;
1102                                case 2: // Moniker Name
1103                                        sTextBuffer = pLogData->GetFriendlyMonikerName();
1104                                        break;
1105                                case 3: // Filter Name
1106                                        sTextBuffer = CA2CT(pLogData->m_sFilterName);
1107                                        break;
1108                                case 4: // Application Result
1109                                        sTextBuffer = pLogData->GetFriendlyApplicationResult();
1110                                        break;
1111                                default: // Time
1112                                        sTextBuffer = _StringHelper::FormatDateTime(pLogData->m_nTime);
1113                                }
1114                                pHeader->item.pszText = m_LogListView.GetTextBuffer();
1115                        }
1116                        if(pHeader->item.mask & LVIF_IMAGE)
1117                                switch(pLogData->m_Type)
1118                                {
1119                                case CLogData::TYPE_SELECTEDFILTER:
1120                                        pHeader->item.iImage = (!pLogData->m_bSiteResultValid || SUCCEEDED(pLogData->m_nSiteResult)) ? 4 : 1;
1121                                        break;
1122                                case CLogData::TYPE_CREATEDFILTER:
1123                                        pHeader->item.iImage = (!pLogData->m_bSiteResultValid || SUCCEEDED(pLogData->m_nSiteResult)) ? 5 : 1;
1124                                        break;
1125                                case CLogData::TYPE_ADDFILTER:
1126                                        pHeader->item.iImage = 2;
1127                                        break;
1128                                case CLogData::TYPE_REMOVEFILTER:
1129                                        pHeader->item.iImage = 3;
1130                                        break;
1131                                default:
1132                                        pHeader->item.iImage = -1;
1133                                }
1134                        return 0;
1135                }
1136                LRESULT OnLogListViewGetInfoTip(NMLVGETINFOTIP* pHeader)
1137                {
1138                        const CLogData* pLogData = m_LogListView.GetItemData(pHeader->iItem);
1139                        CString& sTextBuffer = m_LogListView.GetTextBufferString(TRUE);
1140                        //sTextBuffer.AppendFormat(_T("Time: %s\r\n"), _StringHelper::FormatDateTime(pLogData->m_nTime));
1141                        sTextBuffer.AppendFormat(_T("Event: %s\r\n"), pLogData->GetFriendlyEventName());
1142                        CLSID ClassIdentifier = CLSID_NULL;
1143                        if(!pLogData->m_sMonikerDisplayName.IsEmpty())
1144                        {
1145                                sTextBuffer.AppendFormat(_T("Moniker Display Name: %hs\r\n"), pLogData->m_sMonikerDisplayName);
1146                                const CComPtr<IPropertyBag> pPropertyBag = pLogData->GetMonikerPropertyBag();
1147                                if(pPropertyBag)
1148                                        _ATLTRY
1149                                        {
1150                                                sTextBuffer.AppendFormat(_T("Moniker Name: %ls\r\n"), _FilterGraphHelper::ReadPropertyBagString(pPropertyBag, L"FriendlyName"));
1151                                                _PersistHelper::ClassIdentifierFromString(_FilterGraphHelper::ReadPropertyBagString(pPropertyBag, L"CLSID"), ClassIdentifier);
1152                                        }
1153                                        _ATLCATCHALL()
1154                                        {
1155                                                _Z_EXCEPTION();
1156                                        }
1157                        }
1158                        if(pLogData->m_FilterClassIdentifier != CLSID_NULL)
1159                                ClassIdentifier = pLogData->m_FilterClassIdentifier;
1160                        if(ClassIdentifier != CLSID_NULL)
1161                        {
1162                                sTextBuffer.AppendFormat(_T("Class Identifier: %ls\r\n"), _PersistHelper::StringFromIdentifier(ClassIdentifier));
1163                                _ATLTRY
1164                                {
1165                                        CClassData ClassData(ClassIdentifier);
1166                                        if(!ClassData.m_sDescription.IsEmpty())
1167                                                sTextBuffer.AppendFormat(_T("Class Description: %s\r\n"), ClassData.m_sDescription);
1168                                        if(_tcslen(ClassData.m_sFilePath))
1169                                        {
1170                                                sTextBuffer.AppendFormat(_T("File Name: %s\r\n"), ClassData.m_pszFileName);
1171                                                sTextBuffer.AppendFormat(_T("File Directory: %s\r\n"), ClassData.m_sFileDirectory);
1172                                                // SUGG: File times
1173                                                if(_tcslen(ClassData.m_pszFileVersion))
1174                                                        sTextBuffer.AppendFormat(_T("File Version: %s\r\n"), ClassData.m_pszFileVersion);
1175                                                if(_tcslen(ClassData.m_pszFileProductVersion))
1176                                                        sTextBuffer.AppendFormat(_T("File Product Version: %s\r\n"), ClassData.m_pszFileProductVersion);
1177                                                if(ClassData.m_nFileSize)
1178                                                        sTextBuffer.AppendFormat(_T("File Size: %s\r\n"), _StringHelper::FormatNumber((LONGLONG) ClassData.m_nFileSize));
1179                                        }
1180                                }
1181                                _ATLCATCHALL()
1182                                {
1183                                        _Z_EXCEPTION();
1184                                        MessageBeep(MB_ICONERROR);
1185                                }
1186                        }
1187                        if(!pLogData->m_sFilterName.IsEmpty())
1188                                sTextBuffer.AppendFormat(_T("Filter Name: %hs\r\n"), pLogData->m_sFilterName);
1189                        if(pLogData->m_bSiteResultValid)
1190                                sTextBuffer.AppendFormat(_T("Application Result: 0x%08x\r\n"), pLogData->m_nSiteResult);
1191                        sTextBuffer.TrimRight(_T("\t\n\r ."));
1192                        #pragma region Clipboard Copy
1193                        if(GetKeyState(VK_CONTROL) < 0 && GetKeyState(VK_SHIFT) < 0)
1194                                _ATLTRY
1195                                {
1196                                        SetClipboardText(m_hWnd, sTextBuffer);
1197                                        MessageBeep(MB_OK);
1198                                }
1199                                _ATLCATCHALL()
1200                                {
1201                                        _Z_EXCEPTION();
1202                                        MessageBeep(MB_ICONERROR);
1203                                }
1204                        #pragma endregion
1205                        _tcsncpy_s(pHeader->pszText, pHeader->cchTextMax, m_LogListView.GetTextBuffer(), _TRUNCATE);
1206                        return 0;
1207                }
1208                LRESULT OnCopyToClipboardStaticAnchorClicked(NMHDR*)
1209                {
1210                        CString sText;
1211                        for(POSITION Position = m_GraphDataList.GetTailPosition(); Position; m_GraphDataList.GetPrev(Position))
1212                        {
1213                                CGraphData* pGraphData = &m_GraphDataList.GetAt(Position);
1214                                #pragma region Graph
1215                                #pragma region Header
1216                                LPCTSTR g_ppszGraphHeaderItems[] = 
1217                                {
1218                                        _T("Time"),
1219                                        _T("Process Identifier"),
1220                                        _T("Process Name"),
1221                                        _T("Process Directory"),
1222                                };
1223                                sText += _StringHelper::Join(g_ppszGraphHeaderItems, _T("\t")) + _T("\r\n");
1224                                #pragma endregion
1225                                sText += _StringHelper::Join<CString>(4, _T("\t"), 
1226                                        _StringHelper::FormatDateTime(pGraphData->m_nTime),
1227                                        AtlFormatString(_T("%d"), pGraphData->m_nProcessIdentifier),
1228                                        pGraphData->GetProcessName(),
1229                                        pGraphData->GetProcessDirectory(),
1230                                        0) + _T("\r\n");
1231                                sText += _T("\r\n");
1232                                #pragma endregion
1233                                #pragma region Log
1234                                if(pGraphData->m_LogDataList.IsEmpty())
1235                                        continue;
1236                                #pragma region Header
1237                                LPCTSTR g_ppszLogHeaderItems[] = 
1238                                {
1239                                        _T("Time"),
1240                                        _T("Event"),
1241                                        _T("Moniker Display Name"),
1242                                        _T("Moniker Friendly Name"),
1243                                        _T("Moniker Class Identifier"),
1244                                        _T("Filter Class Identifier"),
1245                                        _T("Filter Name"),
1246                                        _T("Class Description"),
1247                                        _T("File Name"),
1248                                        _T("File Directory"),
1249                                        _T("File Version"),
1250                                        _T("File Product Version"),
1251                                        _T("File Size"),
1252                                        _T("Application Result"),
1253                                };
1254                                sText += _StringHelper::Join(g_ppszLogHeaderItems, _T("\t")) + _T("\r\n");
1255                                #pragma endregion
1256                                CLogDataList& LogDataList = pGraphData->m_LogDataList;
1257                                for(POSITION Position = LogDataList.GetHeadPosition(); Position; LogDataList.GetNext(Position))
1258                                {
1259                                        CLogData* pLogData = &LogDataList.GetAt(Position);
1260                                        CStringW sMonikerFriendlyName, sMonikerClassIdentifier;
1261                                        if(!pLogData->m_sMonikerDisplayName.IsEmpty())
1262                                        {
1263                                                const CComPtr<IPropertyBag> pPropertyBag = pLogData->GetMonikerPropertyBag();
1264                                                if(pPropertyBag)
1265                                                        _ATLTRY
1266                                                        {
1267                                                                sMonikerFriendlyName = _FilterGraphHelper::ReadPropertyBagString(pPropertyBag, L"FriendlyName");
1268                                                                sMonikerClassIdentifier = _FilterGraphHelper::ReadPropertyBagString(pPropertyBag, L"CLSID");
1269                                                        }
1270                                                        _ATLCATCHALL()
1271                                                        {
1272                                                                _Z_EXCEPTION();
1273                                                        }
1274                                        }
1275                                        CStringW sFilterClassIdentifier;
1276                                        if(pLogData->m_FilterClassIdentifier != CLSID_NULL)
1277                                                sFilterClassIdentifier = _PersistHelper::StringFromIdentifier(pLogData->m_FilterClassIdentifier);
1278                                        CClassData ClassData;
1279                                        _ATLTRY
1280                                        {
1281                                                const CLSID ClassIdentifier = (pLogData->m_FilterClassIdentifier != CLSID_NULL) ? pLogData->m_FilterClassIdentifier : !sMonikerClassIdentifier.IsEmpty() ? _PersistHelper::ClassIdentifierFromString(sMonikerClassIdentifier) : CLSID_NULL;
1282                                                if(ClassIdentifier != CLSID_NULL)
1283                                                        ClassData.Initialize(ClassIdentifier);
1284                                        }
1285                                        _ATLCATCHALL()
1286                                        {
1287                                                _Z_EXCEPTION();
1288                                        }
1289                                        CString sSiteResult;
1290                                        if(pLogData->m_bSiteResultValid)
1291                                                sSiteResult = AtlFormatString(_T("0x%08x"), pLogData->m_nSiteResult);
1292                                        sText += _StringHelper::Join<CString>(14, _T("\t"), 
1293                                                _StringHelper::FormatDateTime(pLogData->m_nTime),
1294                                                pLogData->GetFriendlyEventName(),
1295                                                (LPCTSTR) CA2CT(pLogData->m_sMonikerDisplayName),
1296                                                (LPCTSTR) CW2CT(sMonikerFriendlyName),
1297                                                (LPCTSTR) CW2CT(sMonikerClassIdentifier),
1298                                                (LPCTSTR) CW2CT(sFilterClassIdentifier),
1299                                                (LPCTSTR) CA2CT(pLogData->m_sFilterName),
1300                                                ClassData.m_sDescription,
1301                                                ClassData.m_pszFileName,
1302                                                ClassData.m_sFileDirectory,
1303                                                ClassData.m_pszFileVersion,
1304                                                ClassData.m_pszFileProductVersion,
1305                                                ClassData.m_nFileSize ? (LPCTSTR) _StringHelper::FormatNumber((LONGLONG) ClassData.m_nFileSize) : NULL,
1306                                                sSiteResult,
1307                                                0) + _T("\r\n");
1308                                }
1309                                #pragma endregion
1310                                sText += _T("\r\n");
1311                        }
1312                        SetClipboardText(m_hWnd, sText);
1313                        MessageBeep(MB_OK);
1314                        return 0;
1315                }
1316        };
1317
1318private:
1319        CPath m_sPath;
1320        CGraphPropertyPage m_GraphPropertyPage;
1321
1322public:
1323// CGraphBuilderCallbackPropertySheet
1324        CGraphBuilderCallbackPropertySheet() :
1325                CSizablePropertySheetT<CGraphBuilderCallbackPropertySheet>(IDS_GRAPHBUILDERCALLBACK_GRAPH_PROPERTYSHEETCAPTION),
1326                m_GraphPropertyPage(this)
1327        {
1328                #pragma region Default Path
1329                if(!_tcslen(m_sPath))
1330                {
1331                        TCHAR pszDirectory[MAX_PATH] = { 0 };
1332                        _W(GetWindowsDirectory(pszDirectory, DIM(pszDirectory)));
1333                        #if defined(_TRACE) && _TRACE
1334                                _W(StripToRoot(pszDirectory));
1335                        #endif // defined(_TRACE) && _TRACE
1336                        if(GetOsVersion() >= 0x00060000) // Windows Vista+
1337                        {
1338                                _W(SHGetSpecialFolderPath(m_hWnd, pszDirectory, CSIDL_COMMON_APPDATA, FALSE));
1339                                AddBackslash(pszDirectory);
1340                        }
1341                        TCHAR pszPath[MAX_PATH] = { 0 };
1342                        _W(GetModuleFileName(_AtlBaseModule.GetModuleInstance(), pszPath, DIM(pszPath)));
1343                        LPTSTR pszFileName = FindFileName(pszPath);
1344                        _W(RenameExtension(pszFileName, _T(".log")));
1345                        m_sPath.Combine(pszDirectory, pszFileName);
1346                        _Z5(atlTraceGeneral, 5, _T("m_sPath \"%s\"\n"), m_sPath);
1347                }
1348                #pragma endregion
1349                #if _DEVELOPMENT && FALSE
1350                        static LPCTSTR g_pszPath = _T("D:\\Projects\\A&H\\LuxRiot\\_Issues\\45 Sanyo XP Issues\\DirectShowSpy.log");
1351                        m_sPath = g_pszPath;
1352                #endif // _DEVELOPMENT
1353                AddPage(m_GraphPropertyPage);
1354        }
1355        BOOL SetInitialPosition()
1356        {
1357                if(!__super::SetInitialPosition())
1358                        return FALSE;
1359                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_DEFAULTCOLOR, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)), TRUE);
1360                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_DEFAULTCOLOR, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)), FALSE);
1361                #pragma region Indication of Bitness
1362                CString sCaption;
1363                _W(GetWindowText(sCaption));
1364                #if defined(_WIN64)
1365                        sCaption.Append(_T(" (64-bit)"));
1366                #else
1367                        if(SafeIsWow64Process())
1368                                sCaption.Append(_T(" (32-bit)"));
1369                #endif // defined(_WIN64)
1370                _W(SetWindowText(sCaption));
1371                #pragma endregion
1372                #pragma region System Menu
1373                CMenuHandle Menu = GetSystemMenu(FALSE);
1374                _W(Menu.AppendMenu(MF_SEPARATOR));
1375                _W(Menu.AppendMenu(MF_STRING, ID_APP_ABOUT, _T("&About...")));
1376                #pragma endregion
1377                return TRUE;
1378        }
1379
1380// Window message handelrs
1381        LRESULT OnSysCommand(UINT nCommand, CPoint)
1382        {
1383                switch(nCommand)
1384                {
1385                case ID_APP_ABOUT:
1386                        {
1387                                CAboutDialog Dialog;
1388                                Dialog.DoModal(m_hWnd);
1389                        }
1390                        break;
1391                default:
1392                        SetMsgHandled(FALSE);
1393                }
1394                return 0;
1395        }
1396};
1397
Note: See TracBrowser for help on using the repository browser.