source: trunk/Utilities/LogProcessExceptions/MainWizard.h @ 130

Last change on this file since 130 was 130, checked in by roman, 10 years ago

Added property pages for filters and email notification

  • Property svn:keywords set to Id
File size: 70.9 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2008-2012
3// Created by Roman Ryltsov roman@alax.info
4//
5// $Id: MainWizard.h 130 2012-10-07 22:33:42Z roman $
6
7#pragma once
8
9#include <psapi.h>
10#include <tlhelp32.h>
11#include <atlsecurity.h>
12#include "AboutDialog.h"
13#include "..\..\..\Repository-Private\Utilities\EmailTools\Message.h"
14
15#if PSAPI_VERSION == 1
16#pragma comment(lib, "psapi.lib")
17#endif // PSAPI_VERSION == 1
18
19////////////////////////////////////////////////////////////
20// CMainWizard
21
22class CMainWizard : 
23        public CWizardPropertySheetT<CMainWizard>
24{
25public:
26
27BEGIN_MSG_MAP_EX(CMainWizard)
28        CHAIN_MSG_MAP(CWizardPropertySheet)
29        MSG_WM_SYSCOMMAND(OnSysCommand)
30END_MSG_MAP()
31
32        ////////////////////////////////////////////////////////
33        // CIntroductionPropertyPage
34
35        class CIntroductionPropertyPage :
36                public CWizardPropertyPageT<CIntroductionPropertyPage>
37        {
38        public:
39                enum { IDD = IDD_MAIN_INTRODUCTION };
40
41        BEGIN_MSG_MAP_EX(CIntroductionPropertyPage)
42                CHAIN_MSG_MAP(CWizardPropertyPageT<CIntroductionPropertyPage>)
43                MSG_WM_INITDIALOG(OnInitDialog)
44                REFLECT_NOTIFICATIONS()
45        END_MSG_MAP()
46
47        private:
48                CMainWizard& m_Wizard;
49                CRoHyperStatic m_DescriptionHyperStatic;
50                CButton m_SkipButton;
51                BOOL m_bActivated;
52
53        public:
54        // CIntroductionPropertyPage
55                CIntroductionPropertyPage(CMainWizard* pWizard) throw() :
56                        m_Wizard(*pWizard),
57                        m_bActivated(FALSE)
58                {
59                        m_psp.dwFlags |= PSP_HIDEHEADER;
60                }
61
62        // Window message handlers
63                LRESULT OnInitDialog(HWND, LPARAM) throw()
64                {
65                        //_W(GetPropertySheet().ModifyStyle(0, WS_MINIMIZEBOX));
66                        GetPropertySheet().SetIcon(AtlLoadIcon(IDI_MODULE), TRUE);
67                        GetPropertySheet().SetIcon(AtlLoadIconImage(IDI_MODULE, LR_DEFAULTCOLOR, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)), FALSE);
68                        CMenuHandle Menu = GetPropertySheet().GetSystemMenu(FALSE);
69                        _W(Menu.AppendMenu(MF_SEPARATOR));
70                        _W(Menu.AppendMenu(MF_STRING, ID_APP_ABOUT, _T("&About...")));
71                        CStatic(GetDlgItem(IDC_WIZARDINTRODUCTION_TITLE)).SetFont(m_Wizard.GetMessageTitleFont());
72                        _W(m_DescriptionHyperStatic.SubclassWindow(GetDlgItem(IDC_WIZARDINTRODUCTION_DESCRIPTION)));
73                        m_SkipButton = GetDlgItem(IDC_WIZARDINTRODUCTION_SKIP);
74                        return TRUE;
75                }
76                INT OnSetActive() throw()
77                {
78                        SetWizardButtons(PSWIZB_NEXT);
79                        BOOL bActivated = m_bActivated;
80                        m_bActivated = TRUE;
81                        if(!bActivated && m_Wizard.GetConfirmation(_T("CMainWizard::CIntroductionPropertyPage")) == 1)
82                        {
83                                m_SkipButton.SetCheck(BST_CHECKED);
84                                return -1;
85                        }
86                        return 0;
87                }
88                INT OnWizardNext() throw()
89                {
90                        m_Wizard.SetConfirmation(_T("CMainWizard::CIntroductionPropertyPage"), m_SkipButton.GetCheck());
91                        return 0;
92                }
93        };
94
95        ////////////////////////////////////////////////////////
96        // CProcessPropertyPage
97
98        class CProcessPropertyPage :
99                public CWizardPropertyPageT<CProcessPropertyPage>
100        {
101        public:
102                enum { IDD = IDD_MAIN_PROCESS };
103
104        BEGIN_MSG_MAP_EX(CProcessPropertyPage)
105                CHAIN_MSG_MAP(CWizardPropertyPageT<CProcessPropertyPage>)
106                MSG_WM_INITDIALOG(OnInitDialog)
107                MSG_LVN_GETDISPINFO(IDC_MAIN_PROCESSES, OnProcessListViewGetDispInfo)
108                MSG_LVN_GETINFOTIP(IDC_MAIN_PROCESSES, OnProcessListViewGetInfoTip)
109                MSG_LVN_ITEMCHANGED(IDC_MAIN_PROCESSES, OnProcessListItemChanged)
110                MSG_LVN_DBLCLK(IDC_MAIN_PROCESSES, OnProcessListViewDblClk)
111                COMMAND_ID_HANDLER_EX(IDC_MAIN_REFRESHPROCESSES, OnRefreshButtonClicked)
112                REFLECT_NOTIFICATIONS()
113        END_MSG_MAP()
114
115        public:
116
117                ////////////////////////////////////////////////////
118                // CProcessData
119
120                class CProcessData
121                {
122                public:
123                        DWORD m_nIdentifier;
124                        CHandle m_Handle;
125                        CPath m_sFilePath;
126                        CPath m_sImageFilePath;
127                        BOOL m_bIsWow64;
128                        CString m_sAccount;
129                        PROCESS_MEMORY_COUNTERS_EX m_MemoryCounters;
130                        CString m_sWindowCaption;
131                        BOOL m_bValid;
132                        BOOL UpdateMemoryCounters()
133                        {
134                                ZeroMemory(&m_MemoryCounters, sizeof m_MemoryCounters);
135                                m_MemoryCounters.cb = sizeof m_MemoryCounters;
136                                if(!GetProcessMemoryInfo(m_Handle, (PROCESS_MEMORY_COUNTERS*) &m_MemoryCounters, m_MemoryCounters.cb))
137                                {
138                                        m_MemoryCounters.cb = sizeof (PROCESS_MEMORY_COUNTERS);
139                                        if(!GetProcessMemoryInfo(m_Handle, (PROCESS_MEMORY_COUNTERS*) &m_MemoryCounters, m_MemoryCounters.cb))
140                                                return FALSE;
141                                }
142                                return TRUE;
143                        }
144
145                public:
146                // CProcessData
147                        static BOOL CompareIdentifier(const CProcessData& ProcessData, DWORD nIdentifier) throw()
148                        {
149                                return ProcessData.m_nIdentifier == nIdentifier;
150                        }
151                        static BOOL ComparePartialFileName(const CProcessData& ProcessData, LPCTSTR pszFileName) throw()
152                        {
153                                _A(pszFileName);
154                                CString sProcessFileName = ProcessData.GetFileName();
155                                sProcessFileName.MakeLower();
156                                CString sPartialFileName = pszFileName;
157                                sPartialFileName.MakeLower();
158                                return sProcessFileName.Find(sPartialFileName) >= 0;
159                        }
160                        static BOOL ResetValid(CProcessData& ProcessData)
161                        {
162                                ProcessData.m_bValid = FALSE;
163                                return TRUE;
164                        }
165                        VOID Initialize(DWORD nProcessIdentifier, CHandle& Process, const CPath& sFilePath)
166                        {
167                                m_nIdentifier = nProcessIdentifier;
168                                m_Handle = Process;
169                                _A(!Process);
170                                m_sFilePath = sFilePath;
171                                TCHAR pszPath[MAX_PATH] = { 0 };
172                                if(GetProcessImageFileName(m_Handle, pszPath, DIM(pszPath)))
173                                        m_sImageFilePath = pszPath;
174                                m_bIsWow64 = SafeIsWow64Process(m_Handle);
175                                #pragma region
176                                _ATLTRY
177                                {
178                                        CAccessToken ProcessToken;
179                                        __E(ProcessToken.GetProcessToken(TOKEN_QUERY, m_Handle));
180                                        CSid Sid;
181                                        __E(ProcessToken.GetUser(&Sid));
182                                        m_sAccount = Sid.AccountName();
183                                        LPCTSTR pszDomain = Sid.Domain();
184                                        if(pszDomain && _tcslen(pszDomain))
185                                                m_sAccount = AtlFormatString(_T("%s\\%s"), pszDomain, m_sAccount);
186                                }
187                                _ATLCATCHALL()
188                                {
189                                        _Z_EXCEPTION();
190                                }
191                                #pragma endregion
192                                UpdateMemoryCounters();
193                                m_bValid = TRUE;
194                        }
195                        VOID Update()
196                        {
197                                UpdateMemoryCounters();
198                                m_bValid = TRUE;
199                        }
200                        LPCTSTR GetFileName() const throw()
201                        {
202                                return (LPCTSTR) m_sFilePath + m_sFilePath.FindFileName();
203                        }
204                        const CPath& GetImageFilePath() const throw()
205                        {
206                                return m_sImageFilePath;
207                        }
208                        const PROCESS_MEMORY_COUNTERS_EX& GetMemoryCounters() const throw()
209                        {
210                                return m_MemoryCounters;
211                        }
212                };
213
214                ////////////////////////////////////////////////////
215                // CProcessDataList
216
217                class CProcessDataList :
218                        public CRoListT<CProcessData>
219                {
220                public:
221                        CRoMapT<DWORD, CWindow> m_ProcessWindowMap;
222
223                        BOOL ProcessWindow(CWindow Window) throw()
224                        {
225                                const DWORD nProcessIdentifier = Window.GetWindowProcessID();
226                                if(!m_ProcessWindowMap.Lookup(nProcessIdentifier))
227                                        _W(m_ProcessWindowMap.SetAt(nProcessIdentifier, Window));
228                                return TRUE;
229                        }
230                        static BOOL CALLBACK ProcessWindow(HWND hWindow, LPARAM lParam)
231                        {
232                                return ((CProcessDataList*) lParam)->ProcessWindow(hWindow);
233                        }
234
235                public:
236                // CProcessDataList
237                        VOID ResetValid()
238                        {
239                                ForEach(&CProcessData::ResetValid);
240                        }
241                        VOID UpdateWindows()
242                        {
243                                m_ProcessWindowMap.RemoveAll();
244                                EnumWindows(&CProcessDataList::ProcessWindow, (LPARAM) this);
245                                for(POSITION Position = GetHeadPosition(); Position; GetNext(Position))
246                                {
247                                        CProcessData& ProcessData = GetAt(Position);
248                                        ProcessData.m_sWindowCaption.Empty();
249                                        CWindow Window;
250                                        if(m_ProcessWindowMap.Lookup(ProcessData.m_nIdentifier, Window))
251                                                Window.GetWindowText(ProcessData.m_sWindowCaption);
252                                }
253                        }
254                };
255
256        private:
257                CMainWizard& m_Wizard;
258                BOOL m_bActivating;
259                CRoHyperStatic m_DbghelpVersionStatic;
260                CRoListViewT<POSITION> m_ProcessListView;
261                ULONGLONG m_nDbghelpVersion;
262                CProcessDataList m_ProcessDataList;
263                POSITION m_SelectedPosition;
264
265                VOID UpdateButtons() throw()
266                {
267                        const BOOL bAllowBack = !m_Wizard.m_OperationPropertyPage.IsActive();
268                        const BOOL bAllowNext = m_ProcessListView.GetSelectedCount() == 1;
269                        SetWizardButtons((bAllowBack ? PSWIZB_BACK : 0) | (bAllowNext ? PSWIZB_NEXT : 0));
270                }
271                VOID UpdateProcessListView()
272                {
273                        CWindowRedraw ProcessListViewRedraw(m_ProcessListView);
274                        m_ProcessDataList.ResetValid();
275#if TRUE
276                        static const SIZE_T g_nDefaultProcessCount = 1 << 10;
277                        static const SIZE_T g_nMaximalProcessCount = 128 << 10;
278                        CTempBufferT<DWORD, g_nDefaultProcessCount * sizeof (DWORD)> pnProcessIdentifers(g_nDefaultProcessCount);
279                        SIZE_T nProcessCount = g_nDefaultProcessCount;
280                        DWORD nAvailableProcessCount = 0;
281                        for(; ; )
282                        {
283                                __D(nProcessCount <= g_nMaximalProcessCount, E_UNNAMED);
284                                if(EnumProcesses(pnProcessIdentifers, (DWORD) (nProcessCount * sizeof (DWORD)), &nAvailableProcessCount))
285                                        break;
286                                _Z4(atlTraceGeneral, 4, _T("GetLastError() 0x%08x\n"), GetLastError());
287                                pnProcessIdentifers.Free();
288                                nProcessCount <<= 1;
289                        }
290                        nAvailableProcessCount /= sizeof (DWORD);
291                        for(SIZE_T nProcessIndex = 0; nProcessIndex < nAvailableProcessCount; nProcessIndex++)
292                                _ATLTRY
293                                {
294                                        const DWORD nProcessIdentifier = pnProcessIdentifers[nProcessIndex];
295                                        if(nProcessIdentifier == GetCurrentThreadId())
296                                                continue; // We Won't Debug Ourself
297                                        POSITION Position;
298                                        if(m_ProcessDataList.FindFirstThatT<DWORD>(&CProcessData::CompareIdentifier, nProcessIdentifier, &Position))
299                                        {
300                                                m_ProcessDataList.GetAt(Position).Update();
301                                                continue; // Already a Known One
302                                        }
303                                        CHandle Process(OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, nProcessIdentifier));
304                                        if(!Process)
305                                        {
306                                                _Z3(atlTraceGeneral, 3, _T("Error 0x%08x (%s) opening process %d\n"), AtlHresultFromLastError(), AtlFormatSystemMessage(GetLastError()).TrimRight(_T("\t\n\r .")), nProcessIdentifier);
307                                                continue; // Access Denied?
308                                        }
309                                        Position = m_ProcessDataList.AddTail();
310                                        _ATLTRY
311                                        {
312                                                TCHAR pszFilePath[MAX_PATH] = { 0 };
313                                                _W(GetProcessImageFileName(Process, pszFilePath, DIM(pszFilePath)));
314                                                CProcessData& ProcessData = m_ProcessDataList.GetAt(Position);
315                                                ProcessData.Initialize(nProcessIdentifier, Process, pszFilePath);
316                                                _A(!Process);
317                                                const INT nItem = m_ProcessListView.InsertItem(m_ProcessListView.GetItemCount(), Position, ProcessData.GetFileName());
318                                                _A(nItem >= 0);
319                                        }
320                                        _ATLCATCHALL()
321                                        {
322                                                m_ProcessDataList.RemoveAt(Position);
323                                                _ATLRETHROW;
324                                        }
325                                }
326                                _ATLCATCHALL()
327                                {
328                                        _Z_EXCEPTION();
329                                }
330#else
331                        CHandle Snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
332                        __E(Snapshot);
333                        PROCESSENTRY32 ProcessEntry = { sizeof ProcessEntry };
334                        for(BOOL bHaveProcess = Process32First(Snapshot, &ProcessEntry); bHaveProcess; bHaveProcess = Process32Next(Snapshot, &ProcessEntry))
335                                _ATLTRY
336                                {
337                                        const DWORD nProcessIdentifier = ProcessEntry.th32ProcessID;
338                                        if(nProcessIdentifier == GetCurrentThreadId())
339                                                continue; // We Won't Debug Ourself
340                                        POSITION Position;
341                                        if(m_ProcessDataList.FindFirstThatT<DWORD>(&CProcessData::CompareIdentifier, nProcessIdentifier, &Position))
342                                        {
343                                                m_ProcessDataList.GetAt(Position).Update();
344                                                continue; // Already a Known One
345                                        }
346                                        const CPath sFilePath = ProcessEntry.szExeFile;
347                                        CHandle Process(OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, nProcessIdentifier));
348                                        if(!Process)
349                                        {
350                                                _Z3(atlTraceGeneral, 3, _T("Error 0x%08x (%s) opening process %d, %s\n"), AtlHresultFromLastError(), AtlFormatSystemMessage(GetLastError()).TrimRight(_T("\t\n\r .")), nProcessIdentifier, sFilePath);
351                                                continue; // Access Denied?
352                                        }
353                                        Position = m_ProcessDataList.AddTail();
354                                        _ATLTRY
355                                        {
356                                                CProcessData& ProcessData = m_ProcessDataList.GetAt(Position);
357                                                ProcessData.Initialize(nProcessIdentifier, Process, sFilePath);
358                                                _A(!Process);
359                                                const INT nItem = m_ProcessListView.InsertItem(m_ProcessListView.GetItemCount(), Position, ProcessData.GetFileName());
360                                                _A(nItem >= 0);
361                                        }
362                                        _ATLCATCHALL()
363                                        {
364                                                m_ProcessDataList.RemoveAt(Position);
365                                                _ATLRETHROW;
366                                        }
367                                }
368                                _ATLCATCHALL()
369                                {
370                                        _Z_EXCEPTION();
371                                }
372                        __E(GetLastError() == ERROR_NO_MORE_FILES);
373#endif
374                        for(INT nItem = m_ProcessListView.GetItemCount() - 1; nItem >= 0; nItem--)
375                        {
376                                const POSITION Position = m_ProcessListView.GetItemData(nItem);
377                                CProcessData& ProcessData = m_ProcessDataList.GetAt(Position);
378                                if(ProcessData.m_bValid)
379                                        continue;
380                                m_ProcessListView.DeleteItem(nItem);
381                                m_ProcessDataList.RemoveAt(Position);
382                        }
383                        m_ProcessDataList.UpdateWindows();
384                }
385
386        public:
387        // CProcessPropertyPage
388                CProcessPropertyPage(CMainWizard* pWizard) throw() :
389                        m_Wizard(*pWizard)
390                {
391                        SetHeaderTitles();
392                }
393                ULONGLONG GetDbghelpVersion() const throw()
394                {
395                        return m_nDbghelpVersion;
396                }
397                CProcessData& GetSelectedProcessData() throw()
398                {
399                        _A(m_SelectedPosition);
400                        return m_ProcessDataList.GetAt(m_SelectedPosition);
401                }
402                BOOL IsSelectedProcessActive() const throw()
403                {
404                        if(!m_SelectedPosition)
405                                return FALSE;
406                        const CProcessData& ProcessData = m_ProcessDataList.GetAt(m_SelectedPosition);
407                        return WaitForSingleObject(ProcessData.m_Handle, 0) != WAIT_TIMEOUT;
408                }
409
410        // Window message handlers
411                LRESULT OnInitDialog(HWND, LPARAM)
412                {
413                        m_bActivating = TRUE;
414                        _ATLTRY
415                        {
416                                CWaitCursor WaitCursor;
417                                #pragma region Debug Help Library Availability and Version
418                                m_nDbghelpVersion = 0;
419                                CStatic DbghelpVersionStatic = GetDlgItem(IDC_MAIN_DBGHELPVERSION);
420                                _ATLTRY
421                                {
422                                        CString sDefaultDbghelpVersionStaticText, sText;
423                                        _W(DbghelpVersionStatic.GetWindowText(sDefaultDbghelpVersionStaticText));
424                                        const HMODULE hModule = LoadLibrary(_T("dbghelp.dll"));
425                                        if(hModule)
426                                        {
427                                                _ATLTRY
428                                                {
429                                                        TCHAR pszPath[MAX_PATH] = { 0 };
430                                                        _W(GetModuleFileName(hModule, pszPath, DIM(pszPath)));
431                                                        const ULONGLONG nVersion = _VersionInfoHelper::GetFileVersion(_VersionInfoHelper::GetModulePath(hModule));
432                                                        if(nVersion)
433                                                                sText = AtlFormatString(_StringHelper::GetLine(sDefaultDbghelpVersionStaticText, 0), _VersionInfoHelper::GetVersionString(nVersion));
434                                                        m_nDbghelpVersion = nVersion;
435                                                }
436                                                _ATLCATCHALL()
437                                                {
438                                                        _W(FreeLibrary(hModule));
439                                                        _ATLRETHROW;
440                                                }
441                                                _W(FreeLibrary(hModule));
442                                        }
443                                        if(sText.IsEmpty())
444                                                sText = AtlFormatString(_StringHelper::GetLine(sDefaultDbghelpVersionStaticText, 0), _StringHelper::GetLine(sDefaultDbghelpVersionStaticText, 1));
445                                        DbghelpVersionStatic.SetWindowText(sText);
446                                        _W(m_DbghelpVersionStatic.SubclassWindow(DbghelpVersionStatic));
447                                        const CSize IdealExtent = m_DbghelpVersionStatic.GetIdealExtent();
448                                        CRect Position;
449                                        _W(m_DbghelpVersionStatic.GetWindowRect(Position));
450                                        _W(ScreenToClient(Position));
451                                        Position.left = Position.right - IdealExtent.cx - 2;
452                                        _W(m_DbghelpVersionStatic.MoveWindow(Position));
453                                }
454                                _ATLCATCHALL()
455                                {
456                                        _Z_EXCEPTION();
457                                        DbghelpVersionStatic.ShowWindow(SW_HIDE);
458                                }
459                                #pragma endregion
460                                m_ProcessListView.Initialize(GetDlgItem(IDC_MAIN_PROCESSES));
461                                #if !defined(_WIN64)
462                                // NOTE: 32-bit Application which is not a WOW64 process is running on 32-bit OS
463                                if(!SafeIsWow64Process())
464                                        _W(m_ProcessListView.DeleteColumn(2));
465                                #endif // !defined(_WIN64)
466                                // NOTE: We need to enable Debug privilege prior to enumerating processes, so that we could see service processes
467                                EnableTokenDebugPrivilege();
468                                UpdateProcessListView();
469                                #pragma region Initial Selection Using Command Line
470                                CString sCommandLine = GetCommandLine();
471                                sCommandLine.TrimLeft();
472                                if(!sCommandLine.IsEmpty())
473                                {
474                                        #pragma region Delete Application Path
475                                        if(sCommandLine[0] == _T('\"'))
476                                        {
477                                                const INT nPosition = sCommandLine.Find(_T('\"'), 1);
478                                                if(nPosition >= 0)
479                                                        sCommandLine.Delete(0, nPosition + 1);
480                                                else
481                                                        sCommandLine.Empty();
482                                        } else
483                                        {
484                                                const INT nPosition = sCommandLine.Find(_T(' '), 0);
485                                                if(nPosition >= 0)
486                                                        sCommandLine.Delete(0, nPosition + 1);
487                                                else
488                                                        sCommandLine.Empty();
489                                        }
490                                        sCommandLine.TrimLeft();
491                                        #pragma endregion
492                                        CString sProcess = sCommandLine;
493                                        sProcess.Trim();
494                                        if(!sProcess.IsEmpty())
495                                        {
496                                                POSITION Position = NULL;
497                                                const INT nProcessIdentifier = _ttoi(sProcess);
498                                                if(nProcessIdentifier)
499                                                        m_ProcessDataList.FindFirstThatT<DWORD>(&CProcessData::CompareIdentifier, nProcessIdentifier, &Position);
500                                                if(!Position && !sProcess.IsEmpty())
501                                                        m_ProcessDataList.FindFirstThatT<LPCTSTR>(&CProcessData::ComparePartialFileName, sProcess, &Position);
502                                                if(Position)
503                                                {
504                                                        const INT nItem = m_ProcessListView.FindItemData(Position);
505                                                        if(nItem >= 0)
506                                                        {
507                                                                _W(m_ProcessListView.SetItemState(nItem, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED));
508                                                                _W(m_ProcessListView.EnsureVisible(nItem, FALSE));
509                                                        }
510                                                }
511                                        }
512                                }
513                                #pragma endregion
514                                UpdateButtons();
515                                m_bActivating = FALSE;
516                        }
517                        _ATLCATCHALL()
518                        {
519                                _Z_EXCEPTION();
520                        }
521                        return TRUE;
522                }
523                INT OnSetActive() throw()
524                {
525                        _ATLTRY
526                        {
527                                const BOOL bActive = m_Wizard.m_OperationPropertyPage.IsActive();
528                                m_ProcessListView.EnableWindow(!bActive);
529                                CButton(GetDlgItem(IDC_MAIN_REFRESHPROCESSES)).EnableWindow(!bActive);
530                                UpdateButtons();
531                        }
532                        _ATLCATCHALL()
533                        {
534                                MessageBeep(MB_ICONERROR);
535                                return -1;
536                        }
537                        return 0;
538                }
539                LRESULT OnProcessListViewGetDispInfo(NMLVDISPINFO* pHeader)
540                {
541                        if(pHeader->item.mask & LVIF_TEXT)
542                        {
543                                const CProcessData& ProcessData = m_ProcessDataList.GetAt(m_ProcessListView.DataFromParameter(pHeader->item.lParam));
544                                INT nSubItem = pHeader->item.iSubItem;
545#if !defined(_WIN64)
546                                // NOTE: See OnInitDialog and DeleteColumn(2)
547                                if(!SafeIsWow64Process())
548                                        if(nSubItem >= 2)
549                                                nSubItem++;
550#endif // !defined(_WIN64)
551                                m_ProcessListView.m_sTextBuffer.Empty();
552                                switch(nSubItem)
553                                {
554                                case 1: // Identifier
555                                        m_ProcessListView.m_sTextBuffer = AtlFormatString(_T("%d"), ProcessData.m_nIdentifier);
556                                        break;
557                                case 2: // Type
558                                        m_ProcessListView.m_sTextBuffer = ProcessData.m_bIsWow64 ? _T("32-bit") : _T("64-bit");
559                                        break;
560                                case 3: // Window Caption
561                                        m_ProcessListView.m_sTextBuffer = ProcessData.m_sWindowCaption;
562                                        break;
563                                case 4: // Account
564                                        m_ProcessListView.m_sTextBuffer = ProcessData.m_sAccount;
565                                        break;
566                                //case 5: // Image File Path
567                                //      m_ProcessListView.m_sTextBuffer = (LPCTSTR) ProcessData.GetImageFilePath();
568                                //      break;
569                                default: // File Name
570                                        m_ProcessListView.m_sTextBuffer = ProcessData.GetFileName();
571                                }
572                                m_ProcessListView.m_sTextBuffer.TrimRight(_T("\t\n\r ."));
573                                pHeader->item.pszText = m_ProcessListView.GetTextBuffer();
574                        }
575                        //if(pHeader->item.mask & LVIF_IMAGE)
576                        //      pHeader->item.iImage = 0;
577                        return 0;
578                }
579                LRESULT OnProcessListViewGetInfoTip(NMLVGETINFOTIP* pHeader)
580                {
581                        const CProcessData& ProcessData = m_ProcessDataList.GetAt(m_ProcessListView.GetItemData(pHeader->iItem));
582                        CString& sTextBuffer = m_ProcessListView.GetTextBufferString(TRUE);
583                        sTextBuffer.AppendFormat(_T("File Name: %s\r\n"), ProcessData.GetFileName());
584                        sTextBuffer.AppendFormat(_T("Identifier: %d (0x%x)\r\n"), ProcessData.m_nIdentifier, ProcessData.m_nIdentifier);
585                        BOOL bIs64Bit = FALSE;
586#if !defined(_WIN64)
587                        if(SafeIsWow64Process())
588#endif // !defined(_WIN64)
589                                bIs64Bit = !ProcessData.m_bIsWow64;
590                        sTextBuffer.AppendFormat(_T("Type: %s\r\n"), !bIs64Bit ? _T("32-bit") : _T("64-bit"));
591                        if(!ProcessData.m_sAccount.IsEmpty())
592                                sTextBuffer.AppendFormat(_T("Account: %s\r\n"), ProcessData.m_sAccount);
593                        sTextBuffer.AppendFormat(_T("Window Caption: %s\r\n"), ProcessData.m_sWindowCaption);
594                        //sTextBuffer.AppendFormat(_T("Image File Path: %s\r\n"), ProcessData.GetImageFilePath());
595                        sTextBuffer.AppendFormat(_T("Working Set Size: %s MB\r\n"), _StringHelper::FormatNumber((LONG) ProcessData.GetMemoryCounters().WorkingSetSize >> 20));
596                        sTextBuffer.AppendFormat(_T("Private Memory: %s MB\r\n"), _StringHelper::FormatNumber((LONG) ProcessData.GetMemoryCounters().PrivateUsage >> 20));
597                        sTextBuffer.TrimRight(_T("\t\n\r ."));
598                        _tcsncpy_s(pHeader->pszText, pHeader->cchTextMax, m_ProcessListView.GetTextBuffer(), _TRUNCATE);
599                        return 0;
600                }
601                LRESULT OnProcessListItemChanged(NMLISTVIEW*)
602                {
603                        if(m_bActivating)
604                                return 0;
605                        UpdateButtons();
606                        return 0;
607                }
608                LRESULT OnProcessListViewDblClk(NMITEMACTIVATE*)
609                {
610                        if(m_ProcessListView.GetSelectedCount() == 1)
611                                m_Wizard.PressButton(PSBTN_NEXT);
612                        return 0;
613                }
614                LRESULT OnRefreshButtonClicked(UINT, INT, HWND)
615                {
616                        UpdateProcessListView();
617                        UpdateButtons();
618                        return 0;
619                }
620                BOOL OnQueryCancel()
621                {
622                        return m_Wizard.m_OperationPropertyPage.OnQueryCancel();
623                }
624                INT OnWizardNext() throw()
625                {
626                        _ATLTRY
627                        {
628                                __D(m_ProcessListView.GetSelectedCount() == 1, E_UNNAMED);
629                                m_SelectedPosition = m_ProcessListView.GetItemData(m_ProcessListView.GetNextItem(-1, LVNI_SELECTED));
630                                _A(m_SelectedPosition);
631                        }
632                        _ATLCATCHALL()
633                        {
634                                MessageBeep(MB_ICONERROR);
635                                return -1;
636                        }
637                        return 0;
638                }
639        };
640
641        ////////////////////////////////////////////////////////
642        // CMinidumpTypePropertyPage
643
644        class CMinidumpTypePropertyPage :
645                public CWizardPropertyPageT<CMinidumpTypePropertyPage>
646        {
647        public:
648                enum { IDD = IDD_MAIN_MINIDUMPTYPE };
649
650        BEGIN_MSG_MAP_EX(CMinidumpTypePropertyPage)
651                CHAIN_MSG_MAP(CWizardPropertyPageT<CMinidumpTypePropertyPage>)
652                MSG_WM_INITDIALOG(OnInitDialog)
653                REFLECT_NOTIFICATIONS()
654        END_MSG_MAP()
655
656        public:
657
658                ////////////////////////////////////////////////////
659                // TYPEITEM
660
661                typedef struct _TYPEITEM
662                {
663                        INT nIdentifier;
664                        MINIDUMP_TYPE Type;
665                        ULONGLONG nOsVersion;
666                        ULONGLONG nApiVersion;
667                } TYPEITEM;
668
669        private:
670                CMainWizard& m_Wizard;
671                BOOL m_bActivating;
672                CRoHyperStatic m_MinidumpTypeStatic;
673                mutable CRoCriticalSection m_DataCriticalSection;
674                MINIDUMP_TYPE m_MinidumpType;
675
676                static const TYPEITEM* GetTypeItemMap() throw()
677                {
678                        static const TYPEITEM g_pMap[] = 
679                        {
680                                { IDC_MAIN_MINIDUMPTYPE_DATASEGMENTS,               MiniDumpWithDataSegs },
681                                { IDC_MAIN_MINIDUMPTYPE_FULLMEMORY,                 MiniDumpWithFullMemory },
682                                { IDC_MAIN_MINIDUMPTYPE_HANDLEDATA,                 MiniDumpWithHandleData },
683                                { IDC_MAIN_MINIDUMPTYPE_FILTERMEMORY,               MiniDumpFilterMemory },
684                                { IDC_MAIN_MINIDUMPTYPE_SCANMEMORY,                 MiniDumpScanMemory},
685                                { IDC_MAIN_MINIDUMPTYPE_UNLOADEDMODULES,            MiniDumpWithUnloadedModules,            0, 0x0005000200000000 }, // Windows Server 2003 and Windows XP: See MSDN, DbgHelp 5.1: This value is not supported
686                                { IDC_MAIN_MINIDUMPTYPE_INDIRECTLYREFERENCEDMEMORY, MiniDumpWithIndirectlyReferencedMemory, 0, 0x0005000200000000 }, // DbgHelp 5.1: This value is not supported
687                                { IDC_MAIN_MINIDUMPTYPE_FILTERMODULEPATHS,          MiniDumpFilterModulePaths,              0, 0x0005000200000000 }, // DbgHelp 5.1: This value is not supported
688                                { IDC_MAIN_MINIDUMPTYPE_PROCESSTHREADDATA,          MiniDumpWithProcessThreadData,          0, 0x0005000200000000 }, // DbgHelp 5.1: This value is not supported
689                                { IDC_MAIN_MINIDUMPTYPE_PRIVATEREADWRITEMEMORY,     MiniDumpWithPrivateReadWriteMemory,     0, 0x0005000200000000 }, // DbgHelp 5.1: This value is not supported
690                                { IDC_MAIN_MINIDUMPTYPE_WITHOUTOPTIONALDATA,        MiniDumpWithoutOptionalData,            0, 0x0006000200000000 }, // DbgHelp 6.1 and earlier: This value is not supported
691                                { IDC_MAIN_MINIDUMPTYPE_FULLMEMORYINFO,             MiniDumpWithFullMemoryInfo,             0, 0x0006000200000000 }, // DbgHelp 6.1 and earlier: This value is not supported
692                                { IDC_MAIN_MINIDUMPTYPE_THREADINFO,                 MiniDumpWithThreadInfo,                 0, 0x0006000200000000 }, // DbgHelp 6.1 and earlier: This value is not supported
693                                { IDC_MAIN_MINIDUMPTYPE_CODESEGS,                   MiniDumpWithCodeSegs,                   0, 0x0006000200000000 }, // DbgHelp 6.1 and earlier: This value is not supported
694                                { IDC_MAIN_MINIDUMPTYPE_WITHOUTAUXILIARYSTATE,      MiniDumpWithoutAuxiliaryState },
695                                { IDC_MAIN_MINIDUMPTYPE_FULLAUXILIARYSTATE,         MiniDumpWithFullAuxiliaryState },
696                                { IDC_MAIN_MINIDUMPTYPE_PRIVATEWRITECOPYMEMORY,     MiniDumpWithPrivateWriteCopyMemory,     0, 0x0006000100000000 }, // Prior to DbgHelp 6.1: This value is not supported
697                                { IDC_MAIN_MINIDUMPTYPE_IGNOREINACCESSIBLEMEMORY,   MiniDumpIgnoreInaccessibleMemory,       0, 0x0006000100000000 }, // Prior to DbgHelp 6.1: This value is not supported
698                                { IDC_MAIN_MINIDUMPTYPE_TOKENINFORMATION,           MiniDumpWithTokenInformation,           0, 0x0006000100000000 }, // Prior to DbgHelp 6.1: This value is not supported
699                                { 0 }
700                        };
701                        return g_pMap;
702                }
703                VOID UpdateButtons() throw()
704                {
705                        const BOOL bAllowNext = m_Wizard.m_ProcessPropertyPage.IsSelectedProcessActive();
706                        SetWizardButtons(PSWIZB_BACK | (bAllowNext ? PSWIZB_NEXT : 0));
707                }
708
709        public:
710        // CMinidumpTypePropertyPage
711                CMinidumpTypePropertyPage(CMainWizard* pWizard) throw() :
712                        m_Wizard(*pWizard)
713                {
714                        SetHeaderTitles();
715                }
716                MINIDUMP_TYPE GetMinidumpType() const throw()
717                {
718                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
719                        return m_MinidumpType;
720                }
721
722        // Window message handlers
723                LRESULT OnInitDialog(HWND, LPARAM)
724                {
725                        m_bActivating = TRUE;
726                        _ATLTRY
727                        {
728                                CWaitCursor WaitCursor;
729                                _W(m_MinidumpTypeStatic.SubclassWindow(GetDlgItem(IDC_MAIN_MINIDUMPTYPE)));
730                                #pragma region Enable OS and API Dependent Items
731                                const ULONGLONG nOsVersion = GetOsVersion();
732                                const ULONGLONG nApiVersion = m_Wizard.m_ProcessPropertyPage.GetDbghelpVersion();
733                                static const MINIDUMP_TYPE g_DefaultType = (MINIDUMP_TYPE) (
734                                        MiniDumpWithDataSegs |
735                                        //MiniDumpWithFullMemory |
736                                        MiniDumpWithThreadInfo |
737                                        MiniDumpIgnoreInaccessibleMemory |
738                                        0);
739                                for(const TYPEITEM* pTypeItem = GetTypeItemMap(); pTypeItem->nIdentifier; pTypeItem++)
740                                {
741                                        CButton Button = GetDlgItem(pTypeItem->nIdentifier);
742                                        if(g_DefaultType & pTypeItem->Type)
743                                                Button.SetCheck(TRUE);
744                                        if(pTypeItem->nOsVersion && nOsVersion < pTypeItem->nOsVersion ||pTypeItem->nApiVersion && nApiVersion < pTypeItem->nApiVersion)
745                                        {
746                                                Button.SetCheck(FALSE);
747                                                Button.EnableWindow(FALSE);
748                                        }
749                                }
750                                #pragma endregion
751                                CButton(GetDlgItem(IDC_MAIN_MINIDUMPTYPE_DATASEGMENTS)).SetCheck(TRUE);
752                                #pragma region Initialize from Registry
753                                DWORD nIntegerType;
754                                if(_RegKeyHelper::QueryIntegerValueEx(HKEY_CURRENT_USER, REGISTRY_ROOT, _T("Minidump Type"), nIntegerType))
755                                {
756                                        MINIDUMP_TYPE Type = (MINIDUMP_TYPE) nIntegerType;
757                                        for(const TYPEITEM* pTypeItem = GetTypeItemMap(); pTypeItem->nIdentifier; pTypeItem++)
758                                        {
759                                                CButton Button = GetDlgItem(pTypeItem->nIdentifier);
760                                                if(Button.IsWindowEnabled())
761                                                        Button.SetCheck(Type & pTypeItem->Type);
762                                        }
763                                }
764                                #pragma endregion
765                                UpdateButtons();
766                                m_bActivating = FALSE;
767                        }
768                        _ATLCATCHALL()
769                        {
770                                _Z_EXCEPTION();
771                        }
772                        return TRUE;
773                }
774                INT OnSetActive() throw()
775                {
776                        #if defined(_DEBUG) && FALSE
777                                return -1;
778                        #endif // defined(_DEBUG)
779                        _ATLTRY
780                        {
781                                UpdateButtons();
782                        }
783                        _ATLCATCHALL()
784                        {
785                                MessageBeep(MB_ICONERROR);
786                                return -1;
787                        }
788                        return 0;
789                }
790                BOOL OnQueryCancel()
791                {
792                        return m_Wizard.m_OperationPropertyPage.OnQueryCancel();
793                }
794                INT OnWizardNext() throw()
795                {
796                        _ATLTRY
797                        {
798                                MINIDUMP_TYPE Type = MiniDumpNormal;
799                                _A(!Type);
800                                for(const TYPEITEM* pTypeItem = GetTypeItemMap(); pTypeItem->nIdentifier; pTypeItem++)
801                                {
802                                        CButton Button = GetDlgItem(pTypeItem->nIdentifier);
803                                        if(Button.IsWindowVisible() && Button.IsWindowEnabled())
804                                                if(Button.GetCheck())
805                                                        Type = (MINIDUMP_TYPE) ((UINT) Type | pTypeItem->Type);
806                                }
807                                _RegKeyHelper::SetIntegerValue(HKEY_CURRENT_USER, REGISTRY_ROOT, _T("Minidump Type"), (DWORD) Type);
808                                {
809                                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
810                                        m_MinidumpType = Type;
811                                }
812                                if(!m_Wizard.m_ProcessPropertyPage.IsSelectedProcessActive())
813                                        return CProcessPropertyPage::IDD;
814                        }
815                        _ATLCATCHALL()
816                        {
817                                MessageBeep(MB_ICONERROR);
818                                return -1;
819                        }
820                        return 0;
821                }
822        };
823
824        ////////////////////////////////////////////////////////
825        // CFilterPropertyPage
826
827        class CFilterPropertyPage :
828                public CWizardPropertyPageT<CFilterPropertyPage>
829        {
830        public:
831                enum { IDD = IDD_MAIN_FILTER };
832
833        BEGIN_MSG_MAP_EX(CFilterPropertyPage)
834                CHAIN_MSG_MAP(CWizardPropertyPageT<CFilterPropertyPage>)
835                MSG_WM_INITDIALOG(OnInitDialog)
836                NOTIFY_HANDLER_EX(IDC_MAIN_FILTER_RESET, CRoHyperStatic::NC_ANCHORCLICKED, OnResetStaticAnchorClicked)
837                //NOTIFY_HANDLER_EX(IDC_MAIN_FILTER_HELP, CRoHyperStatic::NC_ANCHORCLICKED, OnHelpStaticAnchorClicked)
838                REFLECT_NOTIFICATIONS()
839        END_MSG_MAP()
840
841        public:
842
843                ////////////////////////////////////////////////////
844                // CFilter
845
846                class CFilter
847                {
848                public:
849
850                        ////////////////////////////////////////////////
851                        // CValueRange
852
853                        class CValueRange
854                        {
855                        public:
856                                LONG m_nMinimalValue;
857                                LONG m_nMaximalValue;
858                       
859                        public:
860                        // CValueRange
861                                VOID Initialize(CString sValue)
862                                {
863                                        CRoArrayT<CString> Array;
864                                        _StringHelper::Split(sValue, _T('-'), Array);
865                                        __D(!Array.IsEmpty(), E_INVALIDARG);
866                                        INT nMinimalValue, nMaximalValue;
867                                        __D(StrToIntEx(Array[0], STIF_SUPPORT_HEX, &nMinimalValue), E_INVALIDARG);
868                                        if(Array.GetCount() >= 2)
869                                        {
870                                                __D(StrToIntEx(Array[1], STIF_SUPPORT_HEX, &nMaximalValue), E_INVALIDARG);
871                                                if(nMaximalValue < nMinimalValue)
872                                                        SwapMemory(&nMinimalValue, &nMaximalValue);
873                                        } else
874                                                nMaximalValue = nMinimalValue;
875                                        m_nMinimalValue = nMinimalValue;
876                                        m_nMaximalValue = nMaximalValue;
877                                }
878                                BOOL Compare(LONG nValue) const throw()
879                                {
880                                        return nValue >= m_nMinimalValue && nValue <= m_nMinimalValue;
881                                }
882                        };
883
884                public:
885                        INT m_nAction;
886                        BOOL m_bExceptionCodeAvailable;
887                        CValueRange m_ExceptionCode;
888                        BOOL m_bNativeExceptionCodeAvailable;
889                        CValueRange m_NativeExceptionCode;
890
891                public:
892                // CFilter
893                        CFilter() throw() :
894                                m_nAction(0),
895                                m_bExceptionCodeAvailable(FALSE),
896                                m_bNativeExceptionCodeAvailable(FALSE)
897                        {
898                        }
899                        static VOID PreprocessExceptionCode(CString& sValue)
900                        {
901                                if(sValue.CompareNoCase(_T("*")) == 0)
902                                        sValue = _T("0x80000000-0x7FFFFFFF");
903                                else if(sValue.CompareNoCase(_T("C++")) == 0)
904                                        sValue = _T("0xE06D7363");
905                        }
906                        static VOID PreprocessNativeExceptionCode(CString& sValue)
907                        {
908                                if(sValue.CompareNoCase(_T("*")) == 0)
909                                        sValue = _T("0x80000000-0x7FFFFFFF");
910                        }
911                        VOID Initialize(CString sValue)
912                        {
913                                for(; sValue.Replace(_T("  "), _T(" ")); )
914                                        ;
915                                CRoArrayT<CString> Array;
916                                _StringHelper::Split(sValue, _T(' '), Array);
917                                __D(!Array.IsEmpty(), E_UNNAMED);
918                                #pragma region Action
919                                __D(!Array[0].IsEmpty(), E_UNNAMED);
920                                static LPCTSTR g_ppszActions = _T("-+");
921                                LPCTSTR pszAction = _tcschr(g_ppszActions, Array[0][0]);
922                                __D(pszAction, E_UNNAMED);
923                                m_nAction = (pszAction - g_ppszActions) * 2 - 1;
924                                _A(m_nAction == -1 || m_nAction == +1);
925                                #pragma endregion
926                                m_bExceptionCodeAvailable = FALSE;
927                                m_bNativeExceptionCodeAvailable = FALSE;
928                                if(Array.GetCount() >= 2)
929                                {
930                                        CString sExceptionCode = Array[1];
931                                        PreprocessExceptionCode(sExceptionCode);
932                                        m_ExceptionCode.Initialize(sExceptionCode);
933                                        m_bExceptionCodeAvailable = TRUE;
934                                        if(Array.GetCount() >= 3)
935                                        {
936                                                CString sNativeExceptionCode = Array[2];
937                                                PreprocessNativeExceptionCode(sNativeExceptionCode);
938                                                m_NativeExceptionCode.Initialize(sNativeExceptionCode);
939                                                m_bNativeExceptionCodeAvailable = TRUE;
940                                        }
941                                }
942                        }
943                        BOOL Apply(LONG nExceptionCode, const LONG* pnNativeExceptionCode, INT& nAction) const throw()
944                        {
945                                if(m_bExceptionCodeAvailable)
946                                {
947                                        if(!m_ExceptionCode.Compare(nExceptionCode))
948                                                return FALSE; // Exception Code Mismatch
949                                        if(m_bNativeExceptionCodeAvailable)
950                                        {
951                                                if(!pnNativeExceptionCode)
952                                                        return FALSE; // No Native Exception Code
953                                                if(!m_NativeExceptionCode.Compare(*pnNativeExceptionCode))
954                                                        return FALSE; // Native Exception Code Mismatch
955                                        }
956                                }
957                                nAction = m_nAction;
958                                return TRUE;
959                        }
960                        VOID Trace() const
961                        {
962                                #if defined(_DEBUG)
963                                        CString sText;
964                                        if(m_bExceptionCodeAvailable)
965                                        {
966                                                if(m_ExceptionCode.m_nMinimalValue < m_ExceptionCode.m_nMaximalValue)
967                                                        sText += AtlFormatString(_T("0x%08X-0x%08X "), m_ExceptionCode.m_nMinimalValue, m_ExceptionCode.m_nMaximalValue);
968                                                else if(m_ExceptionCode.m_nMinimalValue == 0xE06D7363)
969                                                        sText += _T("C++ ");
970                                                else
971                                                        sText += AtlFormatString(_T("0x%08X "), m_ExceptionCode.m_nMinimalValue);
972                                                if(m_bNativeExceptionCodeAvailable)
973                                                {
974                                                        if(m_NativeExceptionCode.m_nMinimalValue < m_NativeExceptionCode.m_nMaximalValue)
975                                                                sText += AtlFormatString(_T("0x%08X-0x%08X "), m_NativeExceptionCode.m_nMinimalValue, m_NativeExceptionCode.m_nMaximalValue);
976                                                        else
977                                                                sText += AtlFormatString(_T("0x%08X "), m_NativeExceptionCode.m_nMinimalValue);
978                                                }
979                                        }
980                                        _Z4(atlTraceGeneral, 4, _T("m_nAction %d, %s\n"), m_nAction, sText);
981                                #endif // defined(_DEBUG)
982                        }
983                };
984
985                ////////////////////////////////////////////////////
986                // CFilterArray
987
988                class CFilterArray :
989                        public CRoAssignableArrayT<CRoArrayT<CFilter> >
990                {
991                public:
992                // CFilterArray
993                        CFilterArray()
994                        {
995                        }
996                        CFilterArray(const CString& sValue)
997                        {
998                                Initialize(sValue);
999                        }
1000                        VOID Initialize(CString sValue)
1001                        {
1002                                RemoveAll();
1003                                sValue.Replace(_T("\r\n"), _T("\n"));
1004                                sValue.Replace(_T("\t"), _T(" "));
1005                                CRoArrayT<CString> Array;
1006                                _StringHelper::Split(sValue, _T('\n'), Array);
1007                                for(SIZE_T nIndex = 0; nIndex < Array.GetCount(); nIndex++)
1008                                {
1009                                        CString sLine = Array[nIndex];
1010                                        const INT nPosition = sLine.Find(_T("//"));
1011                                        if(nPosition >= 0)
1012                                                sLine = sLine.Left(nPosition);
1013                                        sLine.Trim();
1014                                        if(sLine.IsEmpty())
1015                                                continue;
1016                                        GetAt(Add()).Initialize(sLine);
1017                                }
1018                        }
1019                        BOOL Apply(LONG nExceptionCode, const LONG* pnNativeExceptionCode, INT& nAction) const throw()
1020                        {
1021                                for(SIZE_T nIndex = 0; nIndex < GetCount(); nIndex++)
1022                                        if(GetAt(nIndex).Apply(nExceptionCode, pnNativeExceptionCode, nAction))
1023                                                return TRUE;
1024                                return FALSE;
1025                        }
1026                        VOID Trace() const
1027                        {
1028                                #if defined(_DEBUG)
1029                                        _Z4(atlTraceGeneral, 4, _T("GetCount() %d\n"), GetCount());
1030                                        for(SIZE_T nIndex = 0; nIndex < GetCount(); nIndex++)
1031                                                GetAt(nIndex).Trace();
1032
1033                                #endif // defined(_DEBUG)
1034                        }
1035                };
1036
1037        private:
1038                CMainWizard& m_Wizard;
1039                BOOL m_bActivating;
1040                CRoEdit m_TextEdit;
1041                CFont m_TextEditFont;
1042                CRoHyperStatic m_ResetStatic;
1043                CRoHyperStatic m_HelpStatic;
1044                mutable CRoCriticalSection m_DataCriticalSection;
1045                CFilterArray m_FilterArray;
1046
1047                static LPCTSTR GetDefaultText() throw()
1048                {
1049                        return 
1050                                _T("// Filters are processed top to bottom until a match is found.") _T("\r\n")
1051                                _T("// One filter per line, syntax: ") _T("\r\n")
1052                                _T("//   (+ or -) [(Exception Code) [(C++ ATL Exception HRESULT)]]") _T("\r\n")
1053                                _T("") _T("\r\n")
1054                                _T("+")
1055                                _T("");
1056                }
1057                VOID UpdateButtons() throw()
1058                {
1059                        const BOOL bAllowNext = m_Wizard.m_ProcessPropertyPage.IsSelectedProcessActive();
1060                        SetWizardButtons(PSWIZB_BACK | (bAllowNext ? PSWIZB_NEXT : 0));
1061                }
1062
1063        public:
1064        // CFilterPropertyPage
1065                CFilterPropertyPage(CMainWizard* pWizard) throw() :
1066                        m_Wizard(*pWizard)
1067                {
1068                        SetHeaderTitles();
1069                }
1070                BOOL ApplyFilters(LONG nExceptionCode, const LONG* pnNativeExceptionCode, INT& nAction) const
1071                {
1072                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1073                        return m_FilterArray.Apply(nExceptionCode, pnNativeExceptionCode, nAction);
1074                }
1075
1076        // Window message handlers
1077                LRESULT OnInitDialog(HWND, LPARAM)
1078                {
1079                        m_bActivating = TRUE;
1080                        _ATLTRY
1081                        {
1082                                CWaitCursor WaitCursor;
1083                                m_TextEdit = GetDlgItem(IDC_MAIN_FILTER_TEXT);
1084                                CLogFont LogFont;
1085                                LogFont.SetMessageBoxFont();
1086                                _tcsncpy_s(LogFont.lfFaceName, DIM(LogFont.lfFaceName), _T("Courier New"), _TRUNCATE);
1087                                m_TextEditFont = LogFont.CreateFontIndirect();
1088                                m_TextEdit.SetFont(m_TextEditFont);
1089                                _W(m_ResetStatic.SubclassWindow(GetDlgItem(IDC_MAIN_FILTER_RESET)));
1090                                _W(m_HelpStatic.SubclassWindow(GetDlgItem(IDC_MAIN_FILTER_HELP)));
1091                                CRoHyperStatic::SetIdealExtentHorizontally(2, &m_ResetStatic, &m_HelpStatic);
1092                                #pragma region Initialize from Registry
1093                                CString sText = GetDefaultText();
1094                                _RegKeyHelper::QueryStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, _T("Filter"), sText);
1095                                m_TextEdit.SetValue(sText);
1096                                #pragma endregion
1097                                UpdateButtons();
1098                                m_bActivating = FALSE;
1099                        }
1100                        _ATLCATCHALL()
1101                        {
1102                                _Z_EXCEPTION();
1103                        }
1104                        return TRUE;
1105                }
1106                LRESULT OnResetStaticAnchorClicked(NMHDR*)
1107                {
1108                        m_TextEdit.SetValue(GetDefaultText());
1109                        UpdateButtons();
1110                        return 0;
1111                }
1112                INT OnSetActive() throw()
1113                {
1114                        #if defined(_DEBUG) && FALSE
1115                                return -1;
1116                        #endif // defined(_DEBUG)
1117                        _ATLTRY
1118                        {
1119                                UpdateButtons();
1120                        }
1121                        _ATLCATCHALL()
1122                        {
1123                                MessageBeep(MB_ICONERROR);
1124                                return -1;
1125                        }
1126                        return 0;
1127                }
1128                BOOL OnQueryCancel()
1129                {
1130                        return m_Wizard.m_OperationPropertyPage.OnQueryCancel();
1131                }
1132                INT OnWizardNext() throw()
1133                {
1134                        _ATLTRY
1135                        {
1136                                CString sText = m_TextEdit.GetValue();
1137                                CFilterArray FilterArray;
1138                                _ATLTRY
1139                                {
1140                                        FilterArray.Initialize(sText);
1141                                }
1142                                _ATLCATCH(Exception)
1143                                {
1144                                        _Z_ATLEXCEPTION(Exception);
1145                                        AtlExceptionMessageBox(m_hWnd, Exception);
1146                                        m_TextEdit.SetFocus();
1147                                        return -1;
1148                                }
1149                                _RegKeyHelper::SetStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, _T("Filter"), sText);
1150                                {
1151                                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
1152                                        m_FilterArray = FilterArray;
1153                                        m_FilterArray.Trace();
1154                                }
1155                                if(!m_Wizard.m_ProcessPropertyPage.IsSelectedProcessActive())
1156                                        return CProcessPropertyPage::IDD;
1157                        }
1158                        _ATLCATCHALL()
1159                        {
1160                                MessageBeep(MB_ICONERROR);
1161                                return -1;
1162                        }
1163                        return 0;
1164                }
1165        };
1166
1167        ////////////////////////////////////////////////////////
1168        // CEmailPropertyPage
1169
1170        class CEmailPropertyPage :
1171                public CWizardPropertyPageT<CEmailPropertyPage>
1172        {
1173        public:
1174                enum { IDD = IDD_MAIN_EMAIL };
1175
1176        BEGIN_MSG_MAP_EX(CEmailPropertyPage)
1177                CHAIN_MSG_MAP(CWizardPropertyPageT<CEmailPropertyPage>)
1178                MSG_WM_INITDIALOG(OnInitDialog)
1179                COMMAND_HANDLER_EX(IDC_MAIN_EMAIL_ENABLED, BN_CLICKED, OnEnabledButtonClicked)
1180                COMMAND_HANDLER_EX(IDC_MAIN_EMAIL_FROM, EN_CHANGE, OnChanged)
1181                COMMAND_HANDLER_EX(IDC_MAIN_EMAIL_TO, EN_CHANGE, OnChanged)
1182                COMMAND_HANDLER_EX(IDC_MAIN_EMAIL_METHOD, CBN_SELENDOK, OnChanged)
1183                COMMAND_HANDLER_EX(IDC_MAIN_EMAIL_HOST, EN_CHANGE, OnChanged)
1184                COMMAND_HANDLER_EX(IDC_MAIN_EMAIL_USERNAME, EN_CHANGE, OnChanged)
1185                COMMAND_HANDLER_EX(IDC_MAIN_EMAIL_PASSWORD, EN_CHANGE, OnChanged)
1186                NOTIFY_HANDLER_EX(IDC_MAIN_EMAIL_MAXIMALATTACHMENTSIZE, CRoLongEdit::NC_VALUECHANGED, OnChanged)
1187                REFLECT_NOTIFICATIONS()
1188        END_MSG_MAP()
1189
1190        public:
1191
1192        private:
1193                CMainWizard& m_Wizard;
1194                BOOL m_bActivating;
1195                CButton m_EnabledButton;
1196                CFont m_BolderFont;
1197                CRoEdit m_FromEdit;
1198                CRoEdit m_ToEdit;
1199                CRoComboBoxT<> m_MethodComboBox;
1200                CRoEdit m_HostEdit;
1201                CRoEdit m_UsernameEdit;
1202                CRoEdit m_PasswordEdit;
1203                CRoLongEdit m_MaximalAttachmentSizeEdit;
1204                BOOL m_bEnabled;
1205                CStringA m_sMessageString;
1206                ULONG m_nMaximalAttachmentSize;
1207
1208                VOID UpdateButtons() throw()
1209                {
1210                        BOOL bAllowNext = m_Wizard.m_ProcessPropertyPage.IsSelectedProcessActive();
1211                        if(m_EnabledButton.GetCheck())
1212                        {
1213                                if(m_ToEdit.GetValue().Trim().IsEmpty())
1214                                        bAllowNext = FALSE;
1215                                const INT nMethod = m_MethodComboBox.GetCurSel();
1216                                if(nMethod != 0) // Google Mail
1217                                        if(m_HostEdit.GetValue().Trim().IsEmpty())
1218                                                bAllowNext = FALSE;
1219                                if(nMethod != 5) // No Authentication
1220                                {
1221                                        if(m_UsernameEdit.GetValue().Trim().IsEmpty())
1222                                                bAllowNext = FALSE;
1223                                        if(m_PasswordEdit.GetValue().Trim().IsEmpty())
1224                                                bAllowNext = FALSE;
1225                                }
1226                        }
1227                        SetWizardButtons(PSWIZB_BACK | (bAllowNext ? PSWIZB_NEXT : 0));
1228                }
1229                VOID UpdateControls()
1230                {
1231                        if(m_EnabledButton.GetCheck())
1232                        {
1233                                for(CWindow Window = m_EnabledButton.GetWindow(GW_HWNDNEXT); Window; Window = Window.GetWindow(GW_HWNDNEXT))
1234                                        Window.ShowWindow(SW_SHOW);
1235                                const INT nMethod = m_MethodComboBox.GetCurSel();
1236                                m_HostEdit.GetWindow(GW_HWNDPREV).EnableWindow(nMethod != 0); // Google Mail
1237                                m_HostEdit.EnableWindow(nMethod != 0); // Google Mail
1238                                m_UsernameEdit.GetWindow(GW_HWNDPREV).EnableWindow(nMethod != 5); // No Authentication
1239                                m_UsernameEdit.EnableWindow(nMethod != 5); // No Authentication
1240                                m_PasswordEdit.GetWindow(GW_HWNDPREV).EnableWindow(nMethod != 5); // No Authentication
1241                                m_PasswordEdit.EnableWindow(nMethod != 5); // No Authentication
1242                        } else
1243                        {
1244                                for(CWindow Window = m_EnabledButton.GetWindow(GW_HWNDNEXT); Window; Window = Window.GetWindow(GW_HWNDNEXT))
1245                                        Window.ShowWindow(SW_HIDE);
1246                        }
1247                        UpdateButtons();
1248                }
1249
1250        public:
1251        // CEmailPropertyPage
1252                CEmailPropertyPage(CMainWizard* pWizard) throw() :
1253                        m_Wizard(*pWizard)
1254                {
1255                        SetHeaderTitles();
1256                }
1257                CObjectPtr<CMessage> CreateMessage() const
1258                {
1259                        if(!m_bEnabled)
1260                                return NULL;
1261                        CObjectPtr<CMessage> pMessage;
1262                        pMessage.Construct();
1263                        pMessage->LoadTypeInfo(IDR_EMAILTOOLS);
1264                        pMessage->SetAsString(m_sMessageString);
1265                        return pMessage;
1266                }
1267                ULONG GetMaximalAttachmentSize() const throw()
1268                {
1269                        return m_nMaximalAttachmentSize;
1270                }
1271
1272        // Window message handlers
1273                LRESULT OnInitDialog(HWND, LPARAM)
1274                {
1275                        m_bActivating = TRUE;
1276                        _ATLTRY
1277                        {
1278                                CWaitCursor WaitCursor;
1279                                m_EnabledButton = GetDlgItem(IDC_MAIN_EMAIL_ENABLED);
1280                                CFontHandle Font(GetFont());
1281                                if(!m_BolderFont)
1282                                {
1283                                        CLogFont LogFont;
1284                                        _W(Font.GetLogFont(LogFont));
1285                                        LogFont.SetBold();
1286                                        m_BolderFont = LogFont.CreateFontIndirect();
1287                                }
1288                                m_EnabledButton.SetFont(m_BolderFont);
1289                                m_FromEdit = GetDlgItem(IDC_MAIN_EMAIL_FROM);
1290                                m_ToEdit = GetDlgItem(IDC_MAIN_EMAIL_TO);
1291                                m_MethodComboBox.Initialize(GetDlgItem(IDC_MAIN_EMAIL_METHOD));
1292                                m_MethodComboBox.SetCurSel(0);
1293                                m_HostEdit = GetDlgItem(IDC_MAIN_EMAIL_HOST);
1294                                m_UsernameEdit = GetDlgItem(IDC_MAIN_EMAIL_USERNAME);
1295                                m_PasswordEdit = GetDlgItem(IDC_MAIN_EMAIL_PASSWORD);
1296                                _W(m_MaximalAttachmentSizeEdit.SubclassWindow(GetDlgItem(IDC_MAIN_EMAIL_MAXIMALATTACHMENTSIZE)));
1297                                #pragma region Initialize from Registry
1298                                CRegKey Key;
1299                                Key.Open(HKEY_CURRENT_USER, REGISTRY_ROOT, KEY_READ);
1300                                if(Key)
1301                                {
1302                                        m_EnabledButton.SetCheck(_RegKeyHelper::QueryIntegerValue(Key, _T("Email Enabled")));
1303                                        CString sMessageString = _RegKeyHelper::QueryStringValue(Key, _T("Email Message Template"));
1304                                        if(!sMessageString.IsEmpty())
1305                                                _ATLTRY
1306                                                {
1307                                                        CObjectPtr<CMessage> pMessage;
1308                                                        pMessage.Construct();
1309                                                        pMessage->LoadTypeInfo(IDR_EMAILTOOLS);
1310                                                        pMessage->SetAsString(CStringA(sMessageString));
1311                                                        #pragma region Sender and Recipients
1312                                                        CComBSTR sSender, sToRecipients;
1313                                                        __C(pMessage->get_Sender(&sSender));
1314                                                        __C(pMessage->get_ToRecipients(&sToRecipients));
1315                                                        m_FromEdit.SetValue(CString(sSender));
1316                                                        m_ToEdit.SetValue(CString(sToRecipients));
1317                                                        #pragma endregion
1318                                                        CComBSTR sAuthMethods;
1319                                                        __C(pMessage->get_AuthMethods(&sAuthMethods));
1320                                                        VARIANT_BOOL bSecureSocketsLayer, bTransportLayerSecurity;
1321                                                        __C(pMessage->get_SecureSocketsLayer(&bSecureSocketsLayer));
1322                                                        __C(pMessage->get_TransportLayerSecurity(&bTransportLayerSecurity));
1323                                                        #pragma region Host and Port
1324                                                        CComBSTR sHost;
1325                                                        __C(pMessage->get_ServerHost(&sHost));
1326                                                        LONG nPort = 0;
1327                                                        __C(pMessage->get_ServerPort(&nPort));
1328                                                        CString sHostT(sHost);
1329                                                        if(nPort)
1330                                                                sHostT += AtlFormatString(_T(":%d"), nPort);
1331                                                        m_HostEdit.SetValue(sHostT);
1332                                                        #pragma endregion
1333                                                        #pragma region User Name and Password
1334                                                        CComBSTR sAuthName, sAuthPassword;
1335                                                        __C(pMessage->get_AuthName(&sAuthName));
1336                                                        __C(pMessage->get_AuthPassword(&sAuthPassword));
1337                                                        m_UsernameEdit.SetValue(CString(sAuthName));
1338                                                        m_PasswordEdit.SetValue(CString(sAuthPassword));
1339                                                        #pragma endregion
1340                                                        m_MethodComboBox.SetCurSel(0);
1341                                                        if(bTransportLayerSecurity != ATL_VARIANT_FALSE && sHostT.CompareNoCase(_T("smtp.gmail.com")) == 0)
1342                                                        {
1343                                                                //m_MethodComboBox.SetCurSel(0);
1344                                                        } else
1345                                                        {
1346                                                                if(bTransportLayerSecurity != ATL_VARIANT_FALSE)
1347                                                                        m_MethodComboBox.SetCurSel(1);
1348                                                                else if(bSecureSocketsLayer != ATL_VARIANT_FALSE)
1349                                                                        m_MethodComboBox.SetCurSel(2);
1350                                                                else if(CString(sAuthMethods).CompareNoCase(_T("cram-md5")) == 0)
1351                                                                        m_MethodComboBox.SetCurSel(3);
1352                                                                else if(!CString(sAuthName).IsEmpty())
1353                                                                        m_MethodComboBox.SetCurSel(4);
1354                                                                else
1355                                                                        m_MethodComboBox.SetCurSel(5);
1356                                                        }
1357                                                }
1358                                                _ATLCATCHALL()
1359                                                {
1360                                                        _Z_EXCEPTION();
1361                                                }
1362                                        const DWORD nMaximalAttachmentSize = _RegKeyHelper::QueryIntegerValue(Key, _T("Email Maximal Attachment Minidump File Size"));
1363                                        if(nMaximalAttachmentSize)
1364                                                m_MaximalAttachmentSizeEdit.SetValue(nMaximalAttachmentSize);
1365                                }
1366                                #pragma endregion
1367                                UpdateControls();
1368                                UpdateButtons();
1369                                m_bActivating = FALSE;
1370                        }
1371                        _ATLCATCHALL()
1372                        {
1373                                _Z_EXCEPTION();
1374                        }
1375                        return TRUE;
1376                }
1377                LRESULT OnEnabledButtonClicked(UINT, INT, HWND)
1378                {
1379                        UpdateControls();
1380                        return 0;
1381                }
1382                LRESULT OnChanged(UINT, INT, HWND)
1383                {
1384                        if(!m_bActivating)
1385                                UpdateControls();
1386                        return 0;
1387                }
1388                LRESULT OnChanged(NMHDR*)
1389                {
1390                        if(!m_bActivating)
1391                                UpdateControls();
1392                        return 0;
1393                }
1394                INT OnSetActive() throw()
1395                {
1396                        _ATLTRY
1397                        {
1398                                UpdateButtons();
1399                        }
1400                        _ATLCATCHALL()
1401                        {
1402                                MessageBeep(MB_ICONERROR);
1403                                return -1;
1404                        }
1405                        return 0;
1406                }
1407                BOOL OnQueryCancel()
1408                {
1409                        return m_Wizard.m_OperationPropertyPage.OnQueryCancel();
1410                }
1411                INT OnWizardNext() throw()
1412                {
1413                        _ATLTRY
1414                        {
1415                                m_bEnabled = m_EnabledButton.GetCheck();
1416                                _RegKeyHelper::SetIntegerValue(HKEY_CURRENT_USER, REGISTRY_ROOT, _T("Email Enabled"), m_bEnabled);
1417                                if(m_bEnabled)
1418                                {
1419                                        CObjectPtr<CMessage> pMessage;
1420                                        pMessage.Construct();
1421                                        pMessage->LoadTypeInfo(IDR_EMAILTOOLS);
1422                                        __C(pMessage->put_Sender(CComBSTR(m_FromEdit.GetValue())));
1423                                        __C(pMessage->put_ToRecipients(CComBSTR(m_ToEdit.GetValue())));
1424                                        // NOTE:
1425                                        // 0 Google Mail (SMTP, TLS Connection)
1426                                        // 1 SMTP, TLS Connection, Plain Text Authentication (TLS, PLAIN)
1427                                        // 2 SMTP, SSL Connection, Plain Text Authentication (SSL, PLAIN)
1428                                        // 3 SMTP, Digest Authentication (CRAM-MD5)
1429                                        // 4 SMTP, Plain Text Authentication (PLAIN)
1430                                        // 5 SMTP, No Authentication
1431                                        const INT nMethod = m_MethodComboBox.GetCurSel();
1432                                        __C(pMessage->put_SecureSocketsLayer((nMethod == 2) ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE));
1433                                        __C(pMessage->put_TransportLayerSecurity((nMethod < 2) ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE));
1434                                        if(nMethod != 5)
1435                                        {
1436                                                __C(pMessage->put_AuthMethods(CComBSTR(_T("plain"))));
1437                                                __C(pMessage->put_AuthName(CComBSTR(m_UsernameEdit.GetValue())));
1438                                                __C(pMessage->put_AuthPassword(CComBSTR(m_PasswordEdit.GetValue())));
1439                                        }
1440                                        switch(nMethod)
1441                                        {
1442                                        case 0:
1443                                                __C(pMessage->put_ServerHost(CComBSTR(_T("smtp.gmail.com"))));
1444                                                break;
1445                                        default:
1446                                                CString sHost = m_HostEdit.GetValue();
1447                                                sHost.Trim();
1448                                                const INT nPortPosition = sHost.Find(_T(":"));
1449                                                if(nPortPosition >= 0)
1450                                                {
1451                                                        INT nPort;
1452                                                        __D(AtlStringToInteger(sHost.Mid(nPortPosition + 1), nPort), E_UNNAMED);
1453                                                        __C(pMessage->put_ServerPort(nPort));
1454                                                        sHost = sHost.Left(nPortPosition);
1455                                                }
1456                                                __C(pMessage->put_ServerHost(CComBSTR(sHost)));
1457                                                break;
1458                                        }
1459                                        switch(nMethod)
1460                                        {
1461                                        case 3:
1462                                                __C(pMessage->put_AuthMethods(CComBSTR(_T("cram-md5"))));
1463                                                break;
1464                                        }
1465                                        m_sMessageString = pMessage->GetAsString();
1466                                        m_nMaximalAttachmentSize = (ULONG) m_MaximalAttachmentSizeEdit.GetValue();
1467                                        _RegKeyHelper::SetStringValue(HKEY_CURRENT_USER, REGISTRY_ROOT, _T("Email Message Template"), CString(m_sMessageString));
1468                                        _RegKeyHelper::SetIntegerValue(HKEY_CURRENT_USER, REGISTRY_ROOT, _T("Email Maximal Attachment Minidump File Size"), (DWORD) m_nMaximalAttachmentSize);
1469                                }
1470                                if(!m_Wizard.m_ProcessPropertyPage.IsSelectedProcessActive())
1471                                        return CProcessPropertyPage::IDD;
1472                        }
1473                        _ATLCATCHALL()
1474                        {
1475                                MessageBeep(MB_ICONERROR);
1476                                return -1;
1477                        }
1478                        return 0;
1479                }
1480        };
1481
1482        ////////////////////////////////////////////////////////
1483        // COperationPropertyPage
1484
1485        class COperationPropertyPage :
1486                public CWizardPropertyPageT<COperationPropertyPage>,
1487                public CWindowWithPrivateMessagesT<COperationPropertyPage>
1488        {
1489                typedef CThreadT<COperationPropertyPage> CThread;
1490
1491        public:
1492                enum { IDD = IDD_MAIN_OPERATION };
1493
1494        BEGIN_MSG_MAP_EX(COperationPropertyPage)
1495                CHAIN_MSG_MAP(CWizardPropertyPageT<COperationPropertyPage>)
1496                CHAIN_MSG_MAP(CWindowWithPrivateMessagesT<COperationPropertyPage>)
1497                MSG_WM_INITDIALOG(OnInitDialog)
1498                MSG_WM_DESTROY(OnDestroy)
1499                MESSAGE_HANDLER_EX(WM_UPDATELOGTEXT, OnUpdateLogText)
1500                MESSAGE_HANDLER_EX(WM_DEBUGTHREADENDED, OnDebugThreadEnded)
1501                NOTIFY_HANDLER_EX(IDC_MAIN_OPERATION_WRITEMINIDUMPNOW, CRoHyperStatic::NC_ANCHORCLICKED, OnWriteMinidumpNowStaticAnchorClicked)
1502                NOTIFY_HANDLER_EX(IDC_MAIN_OPERATION_OPENMINIDUMPFILEDIRECTORY, CRoHyperStatic::NC_ANCHORCLICKED, OnOpenMinidumpFileDirectoryStaticAnchorClicked)
1503                REFLECT_NOTIFICATIONS()
1504        END_MSG_MAP()
1505
1506        public:
1507
1508                ////////////////////////////////////////////////////
1509                // Message Identifiers
1510
1511                enum
1512                {
1513                        WM_FIRST = WM_APP,
1514                        WM_UPDATELOGTEXT,
1515                        WM_DEBUGTHREADENDED,
1516                };
1517
1518        private:
1519                CMainWizard& m_Wizard;
1520                BOOL m_bActivating;
1521                CPath m_sDataDirectory;
1522                CRoEdit m_LogEdit;
1523                CRoHyperStatic m_WriteMinidumpNowStatic;
1524                CRoHyperStatic m_OpenMinidumpFileDirectoryStatic;
1525                mutable CRoCriticalSection m_LogTextCriticalSection;
1526                CString m_sLogText;
1527                HRESULT m_nResult;
1528                CObjectPtr<CThread> m_pDebugThread;
1529                UINT m_nExceptionIndex;
1530                BOOL m_bSkipInitialException;
1531                UINT m_nUserIndex;
1532                CObjectPtr<CMessageQueue> m_pMessageQueue;
1533
1534                VOID UpdateButtons() throw()
1535                {
1536                        SetWizardButtons(PSWIZB_BACK | PSWIZB_NEXT);
1537                }
1538                VOID AppendLog(const CString& sText)
1539                {
1540                        if(sText.IsEmpty())
1541                                return;
1542                        CRoCriticalSectionLock LogTextLock(m_LogTextCriticalSection);
1543                        const BOOL bLogTextEmpty = m_sLogText.IsEmpty();
1544                        m_sLogText += sText;
1545                        if(bLogTextEmpty)
1546                                PostPrivateMessage(WM_UPDATELOGTEXT);
1547                }
1548                DWORD DebugThreadProc(CThread* pThread, CEvent& InitializationEvent, CEvent& TerminationEvent)
1549                {
1550                        // ASSU: Windows XP+
1551                        const CProcessPropertyPage::CProcessData& ProcessData = m_Wizard.m_ProcessPropertyPage.GetSelectedProcessData();
1552                        const DWORD nProcessIdentifier = ProcessData.m_nIdentifier;
1553                        __E(DebugActiveProcess(nProcessIdentifier));
1554                        _ATLTRY
1555                        {
1556                                CErrorMode LocalErrorMode(~SEM_FAILCRITICALERRORS, SEM_FAILCRITICALERRORS);
1557                                _W(DebugSetProcessKillOnExit(FALSE));
1558                                CHandle Process(OpenProcess(PROCESS_ALL_ACCESS, FALSE, nProcessIdentifier));
1559                                __E(Process);
1560                                TCHAR pszProcessFilePath[MAX_PATH] = { 0 };
1561                                _W(GetModuleFileNameEx(Process, NULL, pszProcessFilePath, DIM(pszProcessFilePath)));
1562                                LPCTSTR pszProcessFileName = FindFileName(pszProcessFilePath);
1563                                _W(InitializationEvent.Set());
1564                                CStackPointer StackPointer;
1565                                for(; ; )
1566                                {
1567                                        _A(StackPointer.Check()); StackPointer;
1568                                        {
1569                                                const DWORD nWaitResult = WaitForSingleObject(TerminationEvent, 0);
1570                                                _Z5(atlTraceSync, 5, _T("nWaitResult 0x%x\n"), nWaitResult);
1571                                                _A(nWaitResult == WAIT_OBJECT_0 || nWaitResult == WAIT_TIMEOUT);
1572                                                if(nWaitResult != WAIT_TIMEOUT)
1573                                                        break;
1574                                        }
1575                                        DEBUG_EVENT DebugEvent;
1576                                        ZeroMemory(&DebugEvent, sizeof DebugEvent);
1577                                        static const ULONG g_nTimeout = 1000; // 1 second
1578                                        const BOOL bWaitResult = WaitForDebugEvent(&DebugEvent, g_nTimeout);
1579                                        if(!bWaitResult)
1580                                                continue;
1581                                        _Z4(atlTraceGeneral, 4, _T("Debug event, DebugEvent.dwDebugEventCode %d, .dwProcessId %d, .dwThreadId %d\n"), DebugEvent.dwDebugEventCode, DebugEvent.dwProcessId, DebugEvent.dwThreadId);
1582                                        // TODO: Handle load/unload DLL, output debug strings (configurable)
1583                                        CObjectPtr<CMessage> pMessage;
1584                                        CPath sMessageAttachmentPath;
1585                                        BOOL bExitProcess = FALSE;
1586                                        switch(DebugEvent.dwDebugEventCode)
1587                                        {
1588                                        #pragma region CREATE_PROCESS_DEBUG_EVENT
1589                                        case CREATE_PROCESS_DEBUG_EVENT:
1590                                                {
1591                                                        const CREATE_PROCESS_DEBUG_INFO& DebugInformation = DebugEvent.u.CreateProcessInfo;
1592                                                }
1593                                                break;
1594                                        #pragma endregion
1595                                        #pragma region EXIT_PROCESS_DEBUG_EVENT
1596                                        case EXIT_PROCESS_DEBUG_EVENT:
1597                                                {
1598                                                        const EXIT_PROCESS_DEBUG_INFO& DebugInformation = DebugEvent.u.ExitProcess;
1599                                                        bExitProcess = TRUE;
1600                                                        break;
1601                                                }
1602                                                break;
1603                                        #pragma endregion
1604                                        #pragma region EXCEPTION_DEBUG_EVENT
1605                                        case EXCEPTION_DEBUG_EVENT:
1606                                                {
1607                                                        const EXCEPTION_DEBUG_INFO& DebugInformation = DebugEvent.u.Exception;
1608                                                        _Z4(atlTraceGeneral, 4, _T(".ExceptionCode %d, .ExceptionFlags %d, .dwFirstChance %d\n"), DebugInformation.ExceptionRecord.ExceptionCode, DebugInformation.ExceptionRecord.ExceptionFlags, DebugInformation.dwFirstChance);
1609                                                        #pragma region Skip Initial Debugger Attachment Exception
1610                                                        if(DebugInformation.ExceptionRecord.ExceptionCode == 0x80000003 && m_bSkipInitialException)
1611                                                        {
1612                                                                AppendLog(AtlFormatString(_T("Skipping initial debugger attachment exception (0x%08X)\r\n"), DebugInformation.ExceptionRecord.ExceptionCode));
1613                                                                m_bSkipInitialException = FALSE;
1614                                                                break;
1615                                                        }
1616                                                        #pragma endregion
1617                                                        #pragma region Skip "SetThreadName" Exception
1618                                                        // NOTE: See http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx, not a true exception, but an awful patch to set thread name
1619                                                        if(DebugInformation.ExceptionRecord.ExceptionCode == 0x406D1388)
1620                                                        {
1621                                                                AppendLog(AtlFormatString(_T("Skipping thread name setting exception (0x%08X)\r\n"), DebugInformation.ExceptionRecord.ExceptionCode));
1622                                                                break;
1623                                                        }
1624                                                        #pragma endregion
1625                                                        #pragma region Apply Exception Filter
1626                                                        const LONG nExceptionCode = DebugInformation.ExceptionRecord.ExceptionCode;
1627                                                        const LONG* pnNativeExceptionCode = NULL;
1628                                                        LONG nNativeExceptionCode;
1629                                                        if(nExceptionCode == 0xE06D7363 && DebugInformation.ExceptionRecord.NumberParameters >= 2)
1630                                                        {
1631                                                                SIZE_T nReadDataSize = 0;
1632                                                                if(ReadProcessMemory(Process, (const VOID*) DebugInformation.ExceptionRecord.ExceptionInformation[1], &nNativeExceptionCode, sizeof nNativeExceptionCode, &nReadDataSize))
1633                                                                        if(nReadDataSize == sizeof nNativeExceptionCode)
1634                                                                                pnNativeExceptionCode = &nNativeExceptionCode;
1635                                                        }
1636                                                        INT nAction = 1;
1637                                                        m_Wizard.m_FilterPropertyPage.ApplyFilters(nExceptionCode, pnNativeExceptionCode, nAction);
1638                                                        if(nAction < 1)
1639                                                        {
1640                                                                if(pnNativeExceptionCode)
1641                                                                        AppendLog(AtlFormatString(_T("Skipping C++ exception (0x%08X, 0x%08X)\r\n"), nExceptionCode, nNativeExceptionCode));
1642                                                                else
1643                                                                        AppendLog(AtlFormatString(_T("Skipping exception (0x%08X)\r\n"), nExceptionCode));
1644                                                                break;
1645                                                        }
1646                                                        #pragma endregion
1647                                                        _ATLTRY
1648                                                        {
1649                                                                MINIDUMP_EXCEPTION_INFORMATION ExceptionInformation;
1650                                                                ZeroMemory(&ExceptionInformation, sizeof ExceptionInformation);
1651                                                                ExceptionInformation.ThreadId = DebugEvent.dwThreadId;
1652                                                                EXCEPTION_POINTERS ExceptionPointers;
1653                                                                ZeroMemory(&ExceptionPointers, sizeof ExceptionPointers);
1654                                                                ExceptionPointers.ExceptionRecord = const_cast<EXCEPTION_RECORD*>(&DebugInformation.ExceptionRecord);
1655                                                                CONTEXT Context = { CONTEXT_ALL };
1656                                                                CHandle Thread(OpenThread(THREAD_ALL_ACCESS, FALSE, DebugEvent.dwThreadId));
1657                                                                if(Thread)
1658                                                                        if(GetThreadContext(Thread, &Context))
1659                                                                                ExceptionPointers.ContextRecord = &Context;
1660                                                                ExceptionInformation.ExceptionPointers = &ExceptionPointers;
1661                                                                ExceptionInformation.ClientPointers = FALSE;
1662                                                                #pragma region File Name
1663                                                                CString sName;
1664                                                                sName.AppendFormat(_T("%s-%d-%03d"), pszProcessFileName, nProcessIdentifier, m_nExceptionIndex++);
1665                                                                sName.AppendFormat(_T("-%08x"), DebugInformation.ExceptionRecord.ExceptionCode);
1666                                                                HRESULT nNativeExceptionCode = S_OK;
1667                                                                if(DebugInformation.ExceptionRecord.ExceptionCode == 0xE06D7363 && DebugInformation.ExceptionRecord.NumberParameters >= 2)
1668                                                                {
1669                                                                        SIZE_T nReadDataSize = 0;
1670                                                                        if(ReadProcessMemory(Process, (const VOID*) DebugInformation.ExceptionRecord.ExceptionInformation[1], &nNativeExceptionCode, sizeof nNativeExceptionCode, &nReadDataSize))
1671                                                                                if(nReadDataSize == sizeof nNativeExceptionCode)
1672                                                                                        sName.AppendFormat(_T("-%08x"), nNativeExceptionCode);
1673                                                                }
1674                                                                sName.Append(_T(".dmp"));
1675                                                                CPath sPath;
1676                                                                sPath.Combine(m_sDataDirectory, sName);
1677                                                                #pragma endregion
1678                                                                CAtlFile File;
1679                                                                __C(File.Create(sPath, GENERIC_WRITE, CREATE_ALWAYS, FILE_SHARE_READ));
1680                                                                const MINIDUMP_TYPE Type = m_Wizard.m_MinidumpTypePropertyPage.GetMinidumpType();
1681                                                                __E(MiniDumpWriteDump(Process, nProcessIdentifier, File, Type, ExceptionPointers.ContextRecord ? &ExceptionInformation : NULL, NULL, NULL));
1682                                                                AppendLog(AtlFormatString(_T("Written exception minidump into file %s\r\n"), sName));
1683                                                                #pragma region Message Notification
1684                                                                _ATLTRY
1685                                                                {
1686                                                                        pMessage = m_Wizard.m_EmailPropertyPage.CreateMessage();
1687                                                                        if(pMessage)
1688                                                                        {
1689                                                                                TCHAR pszComputerName[MAX_COMPUTERNAME_LENGTH] = { 0 };
1690                                                                                DWORD nComputerNameLength = DIM(pszComputerName);
1691                                                                                _W(GetComputerName(pszComputerName, &nComputerNameLength));
1692                                                                                CString sSubject = AtlFormatString(_T("Exception 0x%08X in %s on %s"), DebugInformation.ExceptionRecord.ExceptionCode, pszProcessFileName, pszComputerName);
1693                                                                                CString sBody;
1694                                                                                sBody += _T("Hi,") _T("\r\n")
1695                                                                                        _T("\r\n");
1696                                                                                sBody += AtlFormatString(_T("This is Log Process Exceptions notifying on exception occurred:") _T("\r\n")
1697                                                                                        _T("\r\n"), 
1698                                                                                        pszComputerName);
1699                                                                                sBody += AtlFormatString(_T(" * ") _T("Code: 0x%08X") _T("\r\n"), DebugInformation.ExceptionRecord.ExceptionCode);
1700                                                                                if(nNativeExceptionCode != S_OK)
1701                                                                                        sBody += AtlFormatString(_T(" * ") _T("Native ATL Code: 0x%08X") _T("\r\n"), nNativeExceptionCode);
1702                                                                                sBody += AtlFormatString(_T(" * ") _T("Local Time: %s") _T("\r\n"), _StringHelper::FormatDateTime());
1703                                                                                sBody += AtlFormatString(_T(" * ") _T("Computer Name: %s") _T("\r\n"), pszComputerName);
1704                                                                                __C(pMessage->put_Subject(CComBSTR(sSubject)));
1705                                                                                __C(pMessage->put_Body(CComBSTR(sBody)));
1706                                                                                sMessageAttachmentPath = sPath;
1707                                                                        }
1708                                                                }
1709                                                                _ATLCATCHALL()
1710                                                                {
1711                                                                        _Z_EXCEPTION();
1712                                                                        pMessage.Release();
1713                                                                }
1714                                                                #pragma endregion
1715                                                        }
1716                                                        _ATLCATCHALL()
1717                                                        {
1718                                                                _Z_EXCEPTION();
1719                                                        }
1720                                                }
1721                                                break;
1722                                        #pragma endregion
1723                                        }
1724                                        __E(ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED));
1725                                        #pragma region Message Notification (Delivery)
1726                                        if(pMessage)
1727                                                _ATLTRY
1728                                                {
1729                                                        // WARN: Attaching a minidump file requires it being closed by API (should we do ContinueDebugEvent and/or wait?)
1730                                                        if(_tcslen(sMessageAttachmentPath))
1731                                                                _ATLTRY
1732                                                                {
1733                                                                        ULONGLONG nFileSize;
1734                                                                        {
1735                                                                                CAtlFile File;
1736                                                                                __C(File.Create(sMessageAttachmentPath, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING));
1737                                                                                __C(File.GetSize(nFileSize));
1738                                                                        }
1739                                                                        if((ULONG) (nFileSize >> 20) < m_Wizard.m_EmailPropertyPage.GetMaximalAttachmentSize())
1740                                                                        {
1741                                                                                CComBSTR sBody;
1742                                                                                __C(pMessage->get_Body(&sBody));
1743                                                                                CString sBodyT(sBody);
1744                                                                                sBodyT += _T("\r\n")
1745                                                                                        _T("Minidump attached.") _T("\r\n");
1746                                                                                __C(pMessage->put_Body(CComBSTR(sBodyT)));
1747                                                                                CObjectPtr<CMessage::CComAttachment> pAttachment = pMessage->GetAttachments()->Add();
1748                                                                                __C(pAttachment->put_Name(CComBSTR((LPCTSTR) sMessageAttachmentPath + sMessageAttachmentPath.FindFileName())));
1749                                                                                __C(pAttachment->put_Type(CComBSTR(_T("application/x-mdmp"))));
1750                                                                                __C(pAttachment->LoadFromFile(CComBSTR(sMessageAttachmentPath)));
1751                                                                        }
1752                                                                }
1753                                                                _ATLCATCHALL()
1754                                                                {
1755                                                                        _Z_EXCEPTION();
1756                                                                }
1757                                                        if(!m_pMessageQueue)
1758                                                                m_pMessageQueue.Construct();
1759                                                        m_pMessageQueue->Add(pMessage);
1760                                                }
1761                                                _ATLCATCHALL()
1762                                                {
1763                                                        _Z_EXCEPTION();
1764                                                }
1765                                        #pragma endregion
1766                                        if(bExitProcess)
1767                                                break;
1768                                        #pragma endregion
1769                                }
1770                        }
1771                        _ATLCATCHALL()
1772                        {
1773                                _W(DebugActiveProcessStop(nProcessIdentifier));
1774                                _ATLRETHROW;
1775                        }
1776                        _W(DebugActiveProcessStop(nProcessIdentifier));
1777                        PostPrivateMessage(WM_DEBUGTHREADENDED);
1778                        return 0;
1779                }
1780                VOID AttachDebug()
1781                {
1782                        _A(!m_pDebugThread);
1783                        m_nUserIndex = 0;
1784                        const CProcessPropertyPage::CProcessData& ProcessData = m_Wizard.m_ProcessPropertyPage.GetSelectedProcessData();
1785                        const DWORD nProcessIdentifier = ProcessData.m_nIdentifier;
1786                        CObjectPtr<CThread> pDebugThread;
1787                        __E(pDebugThread.Construct()->Initialize(this, &CMainWizard::COperationPropertyPage::DebugThreadProc));
1788                        m_pDebugThread = pDebugThread;
1789                        AppendLog(AtlFormatString(_T("Attached to process %d\r\n"), nProcessIdentifier));
1790                }
1791                VOID DetachDebug() throw()
1792                {
1793                        if(m_pDebugThread)
1794                        {
1795                                AppendLog(AtlFormatString(_T("Detached from process\r\n")));
1796                                m_pDebugThread = NULL;
1797                        }
1798                }
1799
1800        public:
1801        // COperationPropertyPage
1802                COperationPropertyPage(CMainWizard* pWizard) throw() :
1803                        m_Wizard(*pWizard),
1804                        m_nResult(S_FALSE),
1805                        m_nExceptionIndex(0)
1806                {
1807                        SetHeaderTitles();
1808                }
1809                HRESULT GetResult() const throw()
1810                {
1811                        return m_nResult;
1812                }
1813                BOOL IsActive() const throw()
1814                {
1815                        return m_pDebugThread != NULL;
1816                }
1817
1818        // Window message handlers
1819                LRESULT OnInitDialog(HWND, LPARAM)
1820                {
1821                        m_bActivating = TRUE;
1822                        _ATLTRY
1823                        {
1824                                //CWaitCursor WaitCursor;
1825                                TCHAR pszModuleDirectory[MAX_PATH] = { 0 };
1826                                _W(GetModuleFileName(_AtlBaseModule.GetModuleInstance(), pszModuleDirectory, DIM(pszModuleDirectory)));
1827                                _W(RemoveFileSpec(pszModuleDirectory));
1828                                m_sDataDirectory = pszModuleDirectory;
1829                                m_LogEdit = GetDlgItem(IDC_MAIN_OPERATION_LOG);
1830                                _W(m_WriteMinidumpNowStatic.SubclassWindow(GetDlgItem(IDC_MAIN_OPERATION_WRITEMINIDUMPNOW)));
1831                                _W(m_OpenMinidumpFileDirectoryStatic.SubclassWindow(GetDlgItem(IDC_MAIN_OPERATION_OPENMINIDUMPFILEDIRECTORY)));
1832                                CRoHyperStatic::SetIdealExtentHorizontally(2, &m_WriteMinidumpNowStatic, &m_OpenMinidumpFileDirectoryStatic);
1833                                UpdateButtons();
1834                                m_bActivating = FALSE;
1835                        }
1836                        _ATLCATCHALL()
1837                        {
1838                                _Z_EXCEPTION();
1839                        }
1840                        return TRUE;
1841                }
1842                LRESULT OnDestroy()
1843                {
1844                        DetachDebug();
1845                        return 0;
1846                }
1847                INT OnSetActive() throw()
1848                {
1849                        _ATLTRY
1850                        {
1851                                if(!m_pDebugThread)
1852                                        _ATLTRY
1853                                        {
1854                                                CWaitCursor WaitCursor;
1855                                                const CProcessPropertyPage::CProcessData& ProcessData = m_Wizard.m_ProcessPropertyPage.GetSelectedProcessData();
1856                                                AppendLog(AtlFormatString(_T("Using directory \"%s\" for minidump files...\r\n"), m_sDataDirectory));
1857                                                AppendLog(AtlFormatString(_T("Attaching to process %d (%s)...\r\n"), ProcessData.m_nIdentifier, ProcessData.GetFileName()));
1858                                                EnableTokenDebugPrivilege();
1859                                                m_bSkipInitialException = TRUE;
1860                                                AttachDebug();
1861                                        }
1862                                        _ATLCATCH(Exception)
1863                                        {
1864                                                _Z_ATLEXCEPTION(Exception);
1865                                                m_nResult = Exception;
1866                                                _ATLRETHROW;
1867                                        }
1868                                UpdateButtons();
1869                        }
1870                        _ATLCATCHALL()
1871                        {
1872                                MessageBeep(MB_ICONERROR);
1873                                return -1;
1874                        }
1875                        return 0;
1876                }
1877                LRESULT OnUpdateLogText(UINT, WPARAM, LPARAM)
1878                {
1879                        CString sLogText;
1880                        {
1881                                CRoCriticalSectionLock LogTextLock(m_LogTextCriticalSection);
1882                                if(m_sLogText.IsEmpty())
1883                                        return 0;
1884                                sLogText = m_LogEdit.GetValue() + m_sLogText;
1885                                m_sLogText.Empty();
1886                        }
1887                        m_LogEdit.SetValue(sLogText);
1888                        m_LogEdit.SetSel(sLogText.GetLength(), -1, FALSE);
1889                        return 0;
1890                }
1891                LRESULT OnDebugThreadEnded(UINT, WPARAM, LPARAM)
1892                {
1893                        DetachDebug();
1894                        return 0;
1895                }
1896                LRESULT OnWriteMinidumpNowStaticAnchorClicked(NMHDR*)
1897                {
1898                        CWaitCursor WaitCursor;
1899                        CString sName;
1900                        const CProcessPropertyPage::CProcessData& ProcessData = m_Wizard.m_ProcessPropertyPage.GetSelectedProcessData();
1901                        LPCTSTR pszProcessFileName = (LPCTSTR) ProcessData.m_sFilePath + ProcessData.m_sFilePath.FindFileName();
1902                        const DWORD nProcessIdentifier = ProcessData.m_nIdentifier;
1903                        sName.AppendFormat(_T("%s-%d-User-%03d"), pszProcessFileName, nProcessIdentifier, m_nUserIndex++);
1904                        sName.Append(_T(".dmp"));
1905                        CPath sPath;
1906                        sPath.Combine(m_sDataDirectory, sName);
1907                        CAtlFile File;
1908                        __C(File.Create(sPath, GENERIC_WRITE, CREATE_ALWAYS, FILE_SHARE_READ));
1909                        const MINIDUMP_TYPE Type = m_Wizard.m_MinidumpTypePropertyPage.GetMinidumpType();
1910                        __E(MiniDumpWriteDump(ProcessData.m_Handle, nProcessIdentifier, File, Type, NULL, NULL, NULL));
1911                        AppendLog(AtlFormatString(_T("Written exception minidump into file %s per user request\r\n"), sName));
1912                        return 0;
1913                }
1914                LRESULT OnOpenMinidumpFileDirectoryStaticAnchorClicked(NMHDR*)
1915                {
1916                        CWaitCursor WaitCursor;
1917                        __E(ShellExecute(GetPropertySheet(), NULL, m_sDataDirectory, NULL, NULL, SW_SHOWNORMAL) > (HINSTANCE) HINSTANCE_ERROR);
1918                        return 0;
1919                }
1920                BOOL OnQueryCancel()
1921                {
1922                        if(IsActive())
1923                                if(AtlMessageBoxEx(m_Wizard, _T("Debug session is active, would you like to stop debugging and exit from the wizard?"), IDS_CONFIRMATION, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2) != IDYES)
1924                                        return TRUE;
1925                        return FALSE;
1926                }
1927                INT OnWizardBack() throw()
1928                {
1929                        _ATLTRY
1930                        {
1931                                if(!IsActive())
1932                                {
1933                                        // NOTE: If we are to go back after debugging session is complete, start with new process selection
1934                                        _W(m_Wizard.m_ProcessPropertyPage.PostMessage(WM_COMMAND, MAKEWPARAM(IDC_MAIN_REFRESHPROCESSES, BN_CLICKED)));
1935                                        return IDD_MAIN_PROCESS;
1936                                }
1937                        }
1938                        _ATLCATCHALL()
1939                        {
1940                                MessageBeep(MB_ICONERROR);
1941                                return -1;
1942                        }
1943                        return 0;
1944                }
1945                INT OnWizardNext() throw()
1946                {
1947                        _ATLTRY
1948                        {
1949                                if(IsActive())
1950                                        if(AtlMessageBoxEx(m_Wizard, _T("Debug session is still active, would you like to finish?"), IDS_CONFIRMATION, MB_ICONQUESTION | MB_YESNO) != IDYES)
1951                                                return -1;
1952                        }
1953                        _ATLCATCHALL()
1954                        {
1955                                MessageBeep(MB_ICONERROR);
1956                                return -1;
1957                        }
1958                        return 0;
1959                }
1960        };
1961
1962        ////////////////////////////////////////////////////////
1963        // CCompletionPropertyPage
1964
1965        class CCompletionPropertyPage :
1966                public CWizardPropertyPageT<CCompletionPropertyPage>
1967        {
1968        public:
1969                enum { IDD = IDD_MAIN_COMPLETION };
1970
1971        BEGIN_MSG_MAP_EX(CCompletionPropertyPage)
1972                CHAIN_MSG_MAP(CWizardPropertyPageT<CCompletionPropertyPage>)
1973                MSG_WM_INITDIALOG(OnInitDialog)
1974                NOTIFY_HANDLER_EX(IDC_MAIN_OPERATION_OPENMINIDUMPFILEDIRECTORY, CRoHyperStatic::NC_ANCHORCLICKED, OnOpenMinidumpFileDirectoryStaticAnchorClicked)
1975                REFLECT_NOTIFICATIONS()
1976        END_MSG_MAP()
1977
1978        private:
1979                CMainWizard& m_Wizard;
1980                CRoHyperStatic m_OpenMinidumpFileDirectoryStatic;
1981
1982        public:
1983        // CCompletionPropertyPage
1984                CCompletionPropertyPage(CMainWizard* pWizard) throw() :
1985                        m_Wizard(*pWizard)
1986                {
1987                        m_psp.dwFlags |= PSP_HIDEHEADER;
1988                }
1989
1990        // Window message handlers
1991                LRESULT OnInitDialog(HWND, LPARAM) throw()
1992                {
1993                        CStatic(GetDlgItem(IDC_WIZARDCOMPLETION_ICON)).SetIcon(AtlLoadSysIcon(IDI_INFORMATION));
1994                        CStatic(GetDlgItem(IDC_WIZARDCOMPLETION_TITLE)).SetFont(m_Wizard.GetMessageTitleFont());
1995                        _W(m_OpenMinidumpFileDirectoryStatic.SubclassWindow(GetDlgItem(IDC_MAIN_OPERATION_OPENMINIDUMPFILEDIRECTORY)));
1996                        _W(m_OpenMinidumpFileDirectoryStatic.SetWindowPos(NULL, CRect(CPoint(0, 0), m_OpenMinidumpFileDirectoryStatic.GetIdealExtent()), SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE));
1997                        return TRUE;
1998                }
1999                INT OnSetActive() throw()
2000                {
2001                        SetWizardButtons(PSWIZB_FINISH);
2002                        m_Wizard.GetDlgItem(IDCANCEL).EnableWindow(FALSE);
2003                        const HRESULT nResult = m_Wizard.m_OperationPropertyPage.GetResult();
2004                        if(FAILED(nResult))
2005                        {
2006                                CStatic(GetDlgItem(IDC_WIZARDCOMPLETION_ICON)).SetIcon(AtlLoadSysIcon(IDI_ERROR));
2007                                GetDlgItem(IDC_WIZARDCOMPLETION_RESULT).SetWindowText(AtlFormatString(_T("Error: %s (0x%08x)"), AtlFormatSystemMessage(nResult), nResult));
2008                        }
2009                        return 0;
2010                }
2011                LRESULT OnOpenMinidumpFileDirectoryStaticAnchorClicked(NMHDR* pHeader)
2012                {
2013                        return m_Wizard.m_OperationPropertyPage.OnOpenMinidumpFileDirectoryStaticAnchorClicked(pHeader);
2014                }
2015        };
2016
2017private:
2018        CFont m_LargerBoldFont;
2019        CIntroductionPropertyPage m_IntroductionPropertyPage;
2020        CProcessPropertyPage m_ProcessPropertyPage;
2021        CMinidumpTypePropertyPage m_MinidumpTypePropertyPage;
2022        CFilterPropertyPage m_FilterPropertyPage;
2023        CEmailPropertyPage m_EmailPropertyPage;
2024        COperationPropertyPage m_OperationPropertyPage;
2025        CCompletionPropertyPage m_CompletionPropertyPage;
2026
2027        const CFont& CreateLargerBoldFont()
2028        {
2029                CFontHandle BaseFont = AtlGetDefaultGuiFont();
2030                CLogFont LogFont;
2031                _W(BaseFont.GetLogFont(LogFont));
2032                LogFont.SetBold();
2033                LogFont.MakeLarger(2);
2034                m_LargerBoldFont = LogFont.CreateFontIndirect();
2035                return m_LargerBoldFont;
2036        }
2037
2038public:
2039// CMainWizard
2040        static BOOL EnableTokenDebugPrivilege()
2041        {
2042                _ATLTRY
2043                {
2044                        CAccessToken Token;
2045                if(!Token.GetThreadToken(TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES))
2046                        {
2047                                const HRESULT nResult = AtlHresultFromLastError();
2048                                __D(nResult == HRESULT_FROM_WIN32(ERROR_NO_TOKEN), nResult);
2049                                __E(Token.GetProcessToken(TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES));
2050                        }
2051                        __E(Token.EnablePrivilege(SE_DEBUG_NAME));
2052                }
2053                _ATLCATCHALL()
2054                {
2055                        _Z_EXCEPTION();
2056                        return FALSE;
2057                }
2058                return TRUE;
2059        }
2060        CMainWizard() :
2061                CWizardPropertySheetT<CMainWizard>(),
2062                m_IntroductionPropertyPage(this),
2063                m_ProcessPropertyPage(this),
2064                m_MinidumpTypePropertyPage(this),
2065                m_FilterPropertyPage(this),
2066                m_EmailPropertyPage(this),
2067                m_OperationPropertyPage(this),
2068                m_CompletionPropertyPage(this)
2069        {
2070                SetCaption(AtlLoadString(IDS_MAINWIZARD_CAPTION));
2071                SetHeader(MAKEINTRESOURCE(IDB_WIZARDHEADER));
2072                SetWatermark(MAKEINTRESOURCE(IDB_WIZARDWATERMARK));
2073                CreateLargerBoldFont();
2074                AddPage(m_IntroductionPropertyPage);
2075                AddPage(m_ProcessPropertyPage);
2076                AddPage(m_MinidumpTypePropertyPage);
2077                AddPage(m_FilterPropertyPage);
2078                AddPage(m_EmailPropertyPage);
2079                AddPage(m_OperationPropertyPage);
2080                AddPage(m_CompletionPropertyPage);
2081        }
2082        const CFont& GetLargerBoldFont() const throw()
2083        {
2084                return m_LargerBoldFont;
2085        }
2086
2087// Window message handelrs
2088        LRESULT OnSysCommand(UINT nCommand, CPoint)
2089        {
2090                switch(nCommand)
2091                {
2092                case ID_APP_ABOUT:
2093                        {
2094                                CAboutDialog Dialog;
2095                                Dialog.DoModal(m_hWnd);
2096                        }
2097                        break;
2098                default:
2099                        SetMsgHandled(FALSE);
2100                }
2101                return 0;
2102        }
2103};
Note: See TracBrowser for help on using the repository browser.