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

Last change on this file since 61 was 61, checked in by roman, 11 years ago
  • moved from assembla
  • early add Debug privilege in order to be able to list service processes
  • cosmetic fix
  • Property svn:keywords set to Id
File size: 45.9 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2008-2011
3// Created by Roman Ryltsov roman@alax.info
4//
5// $Id: MainWizard.h 61 2012-04-27 10:54:06Z roman $
6
7#pragma once
8
9#include <psapi.h>
10#include <tlhelp32.h>
11#include <atlsecurity.h>
12#include "AboutDialog.h"
13
14#if PSAPI_VERSION == 1
15#pragma comment(lib, "psapi.lib")
16#endif // PSAPI_VERSION == 1
17
18////////////////////////////////////////////////////////////
19// CMainWizard
20
21class CMainWizard : 
22        public CWizardPropertySheetT<CMainWizard>
23{
24public:
25
26BEGIN_MSG_MAP_EX(CMainWizard)
27        CHAIN_MSG_MAP(CWizardPropertySheet)
28        MSG_WM_SYSCOMMAND(OnSysCommand)
29END_MSG_MAP()
30
31        ////////////////////////////////////////////////////////
32        // CIntroductionPropertyPage
33
34        class CIntroductionPropertyPage :
35                public CWizardPropertyPageT<CIntroductionPropertyPage>
36        {
37        public:
38                enum { IDD = IDD_MAIN_INTRODUCTION };
39
40        BEGIN_MSG_MAP_EX(CIntroductionPropertyPage)
41                CHAIN_MSG_MAP(CWizardPropertyPageT<CIntroductionPropertyPage>)
42                MSG_WM_INITDIALOG(OnInitDialog)
43                REFLECT_NOTIFICATIONS()
44        END_MSG_MAP()
45
46        private:
47                CMainWizard& m_Wizard;
48                CRoHyperStatic m_DescriptionHyperStatic;
49                CButton m_SkipButton;
50                BOOL m_bActivated;
51
52        public:
53        // CIntroductionPropertyPage
54                CIntroductionPropertyPage(CMainWizard* pWizard) throw() :
55                        m_Wizard(*pWizard),
56                        m_bActivated(FALSE)
57                {
58                        m_psp.dwFlags |= PSP_HIDEHEADER;
59                }
60
61        // Window message handlers
62                LRESULT OnInitDialog(HWND, LPARAM) throw()
63                {
64                        //_W(GetPropertySheet().ModifyStyle(0, WS_MINIMIZEBOX));
65                        GetPropertySheet().SetIcon(AtlLoadIcon(IDI_MODULE), TRUE);
66                        GetPropertySheet().SetIcon(AtlLoadIconImage(IDI_MODULE, LR_DEFAULTCOLOR, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)), FALSE);
67                        CMenuHandle Menu = GetPropertySheet().GetSystemMenu(FALSE);
68                        _W(Menu.AppendMenu(MF_SEPARATOR));
69                        _W(Menu.AppendMenu(MF_STRING, ID_APP_ABOUT, _T("&About...")));
70                        CStatic(GetDlgItem(IDC_WIZARDINTRODUCTION_TITLE)).SetFont(m_Wizard.GetMessageTitleFont());
71                        _W(m_DescriptionHyperStatic.SubclassWindow(GetDlgItem(IDC_WIZARDINTRODUCTION_DESCRIPTION)));
72                        m_SkipButton = GetDlgItem(IDC_WIZARDINTRODUCTION_SKIP);
73                        return TRUE;
74                }
75                INT OnSetActive() throw()
76                {
77                        SetWizardButtons(PSWIZB_NEXT);
78                        BOOL bActivated = m_bActivated;
79                        m_bActivated = TRUE;
80                        if(!bActivated && m_Wizard.GetConfirmation(_T("CMainWizard::CIntroductionPropertyPage")) == 1)
81                        {
82                                m_SkipButton.SetCheck(BST_CHECKED);
83                                return -1;
84                        }
85                        return 0;
86                }
87                INT OnWizardNext() throw()
88                {
89                        m_Wizard.SetConfirmation(_T("CMainWizard::CIntroductionPropertyPage"), m_SkipButton.GetCheck());
90                        return 0;
91                }
92        };
93
94        ////////////////////////////////////////////////////////
95        // CProcessPropertyPage
96
97        class CProcessPropertyPage :
98                public CWizardPropertyPageT<CProcessPropertyPage>
99        {
100        public:
101                enum { IDD = IDD_MAIN_PROCESS };
102
103        BEGIN_MSG_MAP_EX(CProcessPropertyPage)
104                CHAIN_MSG_MAP(CWizardPropertyPageT<CProcessPropertyPage>)
105                MSG_WM_INITDIALOG(OnInitDialog)
106                MSG_LVN_GETDISPINFO(IDC_MAIN_PROCESSES, OnProcessListViewGetDispInfo)
107                MSG_LVN_GETINFOTIP(IDC_MAIN_PROCESSES, OnProcessListViewGetInfoTip)
108                MSG_LVN_ITEMCHANGED(IDC_MAIN_PROCESSES, OnProcessListItemChanged)
109                MSG_LVN_DBLCLK(IDC_MAIN_PROCESSES, OnProcessListViewDblClk)
110                COMMAND_ID_HANDLER_EX(IDC_MAIN_REFRESHPROCESSES, OnRefreshButtonClicked)
111                REFLECT_NOTIFICATIONS()
112        END_MSG_MAP()
113
114        public:
115
116                ////////////////////////////////////////////////////
117                // CProcessData
118
119                class CProcessData
120                {
121                public:
122                        DWORD m_nIdentifier;
123                        CHandle m_Handle;
124                        CPath m_sFilePath;
125                        CPath m_sImageFilePath;
126                        BOOL m_bIsWow64;
127                        CString m_sAccount;
128                        PROCESS_MEMORY_COUNTERS_EX m_MemoryCounters;
129                        CString m_sWindowCaption;
130                        BOOL m_bValid;
131                        BOOL UpdateMemoryCounters()
132                        {
133                                ZeroMemory(&m_MemoryCounters, sizeof m_MemoryCounters);
134                                m_MemoryCounters.cb = sizeof m_MemoryCounters;
135                                if(!GetProcessMemoryInfo(m_Handle, (PROCESS_MEMORY_COUNTERS*) &m_MemoryCounters, m_MemoryCounters.cb))
136                                {
137                                        m_MemoryCounters.cb = sizeof (PROCESS_MEMORY_COUNTERS);
138                                        if(!GetProcessMemoryInfo(m_Handle, (PROCESS_MEMORY_COUNTERS*) &m_MemoryCounters, m_MemoryCounters.cb))
139                                                return FALSE;
140                                }
141                                return TRUE;
142                        }
143
144                public:
145                // CProcessData
146                        static BOOL CompareIdentifier(const CProcessData& ProcessData, DWORD nIdentifier) throw()
147                        {
148                                return ProcessData.m_nIdentifier == nIdentifier;
149                        }
150                        static BOOL ComparePartialFileName(const CProcessData& ProcessData, LPCTSTR pszFileName) throw()
151                        {
152                                _A(pszFileName);
153                                CString sProcessFileName = ProcessData.GetFileName();
154                                sProcessFileName.MakeLower();
155                                CString sPartialFileName = pszFileName;
156                                sPartialFileName.MakeLower();
157                                return sProcessFileName.Find(sPartialFileName) >= 0;
158                        }
159                        static BOOL ResetValid(CProcessData& ProcessData)
160                        {
161                                ProcessData.m_bValid = FALSE;
162                                return TRUE;
163                        }
164                        VOID Initialize(DWORD nProcessIdentifier, CHandle& Process, const CPath& sFilePath)
165                        {
166                                m_nIdentifier = nProcessIdentifier;
167                                m_Handle = Process;
168                                _A(!Process);
169                                m_sFilePath = sFilePath;
170                                TCHAR pszPath[MAX_PATH] = { 0 };
171                                if(GetProcessImageFileName(m_Handle, pszPath, DIM(pszPath)))
172                                        m_sImageFilePath = pszPath;
173                                m_bIsWow64 = SafeIsWow64Process(m_Handle);
174                                #pragma region
175                                _ATLTRY
176                                {
177                                        CAccessToken ProcessToken;
178                                        __E(ProcessToken.GetProcessToken(TOKEN_QUERY, m_Handle));
179                                        CSid Sid;
180                                        __E(ProcessToken.GetUser(&Sid));
181                                        m_sAccount = Sid.AccountName();
182                                        LPCTSTR pszDomain = Sid.Domain();
183                                        if(pszDomain && _tcslen(pszDomain))
184                                                m_sAccount = AtlFormatString(_T("%s\\%s"), pszDomain, m_sAccount);
185                                }
186                                _ATLCATCHALL()
187                                {
188                                        _Z_EXCEPTION();
189                                }
190                                #pragma endregion
191                                UpdateMemoryCounters();
192                                m_bValid = TRUE;
193                        }
194                        VOID Update()
195                        {
196                                UpdateMemoryCounters();
197                                m_bValid = TRUE;
198                        }
199                        LPCTSTR GetFileName() const throw()
200                        {
201                                return (LPCTSTR) m_sFilePath + m_sFilePath.FindFileName();
202                        }
203                        const CPath& GetImageFilePath() const throw()
204                        {
205                                return m_sImageFilePath;
206                        }
207                        const PROCESS_MEMORY_COUNTERS_EX& GetMemoryCounters() const throw()
208                        {
209                                return m_MemoryCounters;
210                        }
211                };
212
213                ////////////////////////////////////////////////////
214                // CProcessDataList
215
216                class CProcessDataList :
217                        public CRoListT<CProcessData>
218                {
219                public:
220                        CRoMapT<DWORD, CWindow> m_ProcessWindowMap;
221
222                        BOOL ProcessWindow(CWindow Window) throw()
223                        {
224                                const DWORD nProcessIdentifier = Window.GetWindowProcessID();
225                                if(!m_ProcessWindowMap.Lookup(nProcessIdentifier))
226                                        _W(m_ProcessWindowMap.SetAt(nProcessIdentifier, Window));
227                                return TRUE;
228                        }
229                        static BOOL CALLBACK ProcessWindow(HWND hWindow, LPARAM lParam)
230                        {
231                                return ((CProcessDataList*) lParam)->ProcessWindow(hWindow);
232                        }
233
234                public:
235                // CProcessDataList
236                        VOID ResetValid()
237                        {
238                                ForEach(&CProcessData::ResetValid);
239                        }
240                        VOID UpdateWindows()
241                        {
242                                m_ProcessWindowMap.RemoveAll();
243                                EnumWindows(&CProcessDataList::ProcessWindow, (LPARAM) this);
244                                for(POSITION Position = GetHeadPosition(); Position; GetNext(Position))
245                                {
246                                        CProcessData& ProcessData = GetAt(Position);
247                                        ProcessData.m_sWindowCaption.Empty();
248                                        CWindow Window;
249                                        if(m_ProcessWindowMap.Lookup(ProcessData.m_nIdentifier, Window))
250                                                Window.GetWindowText(ProcessData.m_sWindowCaption);
251                                }
252                        }
253                };
254
255        private:
256                CMainWizard& m_Wizard;
257                BOOL m_bActivating;
258                CRoHyperStatic m_DbghelpVersionStatic;
259                CRoListViewT<POSITION> m_ProcessListView;
260                ULONGLONG m_nDbghelpVersion;
261                CProcessDataList m_ProcessDataList;
262                POSITION m_SelectedPosition;
263
264                VOID UpdateButtons() throw()
265                {
266                        const BOOL bAllowBack = !m_Wizard.m_OperationPropertyPage.IsActive();
267                        const BOOL bAllowNext = m_ProcessListView.GetSelectedCount() == 1;
268                        SetWizardButtons((bAllowBack ? PSWIZB_BACK : 0) | (bAllowNext ? PSWIZB_NEXT : 0));
269                }
270                VOID UpdateProcessListView()
271                {
272                        CWindowRedraw ProcessListViewRedraw(m_ProcessListView);
273                        m_ProcessDataList.ResetValid();
274#if TRUE
275                        static const SIZE_T g_nDefaultProcessCount = 1 << 10;
276                        static const SIZE_T g_nMaximalProcessCount = 128 << 10;
277                        CTempBufferT<DWORD, g_nDefaultProcessCount * sizeof (DWORD)> pnProcessIdentifers(g_nDefaultProcessCount);
278                        SIZE_T nProcessCount = g_nDefaultProcessCount;
279                        DWORD nAvailableProcessCount = 0;
280                        for(; ; )
281                        {
282                                __D(nProcessCount <= g_nMaximalProcessCount, E_UNNAMED);
283                                if(EnumProcesses(pnProcessIdentifers, (DWORD) (nProcessCount * sizeof (DWORD)), &nAvailableProcessCount))
284                                        break;
285                                _Z4(atlTraceGeneral, 4, _T("GetLastError() 0x%08x\n"), GetLastError());
286                                pnProcessIdentifers.Free();
287                                nProcessCount <<= 1;
288                        }
289                        nAvailableProcessCount /= sizeof (DWORD);
290                        for(SIZE_T nProcessIndex = 0; nProcessIndex < nAvailableProcessCount; nProcessIndex++)
291                                _ATLTRY
292                                {
293                                        const DWORD nProcessIdentifier = pnProcessIdentifers[nProcessIndex];
294                                        if(nProcessIdentifier == GetCurrentThreadId())
295                                                continue; // We Won't Debug Ourself
296                                        POSITION Position;
297                                        if(m_ProcessDataList.FindFirstThatT<DWORD>(&CProcessData::CompareIdentifier, nProcessIdentifier, &Position))
298                                        {
299                                                m_ProcessDataList.GetAt(Position).Update();
300                                                continue; // Already a Known One
301                                        }
302                                        CHandle Process(OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, nProcessIdentifier));
303                                        if(!Process)
304                                        {
305                                                _Z3(atlTraceGeneral, 3, _T("Error 0x%08x (%s) opening process %d\n"), AtlHresultFromLastError(), AtlFormatSystemMessage(GetLastError()).TrimRight(_T("\t\n\r .")), nProcessIdentifier);
306                                                continue; // Access Denied?
307                                        }
308                                        Position = m_ProcessDataList.AddTail();
309                                        _ATLTRY
310                                        {
311                                                TCHAR pszFilePath[MAX_PATH] = { 0 };
312                                                _W(GetProcessImageFileName(Process, pszFilePath, DIM(pszFilePath)));
313                                                CProcessData& ProcessData = m_ProcessDataList.GetAt(Position);
314                                                ProcessData.Initialize(nProcessIdentifier, Process, pszFilePath);
315                                                _A(!Process);
316                                                const INT nItem = m_ProcessListView.InsertItem(m_ProcessListView.GetItemCount(), Position, ProcessData.GetFileName());
317                                                _A(nItem >= 0);
318                                        }
319                                        _ATLCATCHALL()
320                                        {
321                                                m_ProcessDataList.RemoveAt(Position);
322                                                _ATLRETHROW;
323                                        }
324                                }
325                                _ATLCATCHALL()
326                                {
327                                        _Z_EXCEPTION();
328                                }
329#else
330                        CHandle Snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
331                        __E(Snapshot);
332                        PROCESSENTRY32 ProcessEntry = { sizeof ProcessEntry };
333                        for(BOOL bHaveProcess = Process32First(Snapshot, &ProcessEntry); bHaveProcess; bHaveProcess = Process32Next(Snapshot, &ProcessEntry))
334                                _ATLTRY
335                                {
336                                        const DWORD nProcessIdentifier = ProcessEntry.th32ProcessID;
337                                        if(nProcessIdentifier == GetCurrentThreadId())
338                                                continue; // We Won't Debug Ourself
339                                        POSITION Position;
340                                        if(m_ProcessDataList.FindFirstThatT<DWORD>(&CProcessData::CompareIdentifier, nProcessIdentifier, &Position))
341                                        {
342                                                m_ProcessDataList.GetAt(Position).Update();
343                                                continue; // Already a Known One
344                                        }
345                                        const CPath sFilePath = ProcessEntry.szExeFile;
346                                        CHandle Process(OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, nProcessIdentifier));
347                                        if(!Process)
348                                        {
349                                                _Z3(atlTraceGeneral, 3, _T("Error 0x%08x (%s) opening process %d, %s\n"), AtlHresultFromLastError(), AtlFormatSystemMessage(GetLastError()).TrimRight(_T("\t\n\r .")), nProcessIdentifier, sFilePath);
350                                                continue; // Access Denied?
351                                        }
352                                        Position = m_ProcessDataList.AddTail();
353                                        _ATLTRY
354                                        {
355                                                CProcessData& ProcessData = m_ProcessDataList.GetAt(Position);
356                                                ProcessData.Initialize(nProcessIdentifier, Process, sFilePath);
357                                                _A(!Process);
358                                                const INT nItem = m_ProcessListView.InsertItem(m_ProcessListView.GetItemCount(), Position, ProcessData.GetFileName());
359                                                _A(nItem >= 0);
360                                        }
361                                        _ATLCATCHALL()
362                                        {
363                                                m_ProcessDataList.RemoveAt(Position);
364                                                _ATLRETHROW;
365                                        }
366                                }
367                                _ATLCATCHALL()
368                                {
369                                        _Z_EXCEPTION();
370                                }
371                        __E(GetLastError() == ERROR_NO_MORE_FILES);
372#endif
373                        for(INT nItem = m_ProcessListView.GetItemCount() - 1; nItem >= 0; nItem--)
374                        {
375                                const POSITION Position = m_ProcessListView.GetItemData(nItem);
376                                CProcessData& ProcessData = m_ProcessDataList.GetAt(Position);
377                                if(ProcessData.m_bValid)
378                                        continue;
379                                m_ProcessListView.DeleteItem(nItem);
380                                m_ProcessDataList.RemoveAt(Position);
381                        }
382                        m_ProcessDataList.UpdateWindows();
383                }
384
385        public:
386        // CProcessPropertyPage
387                CProcessPropertyPage(CMainWizard* pWizard) throw() :
388                        m_Wizard(*pWizard)
389                {
390                        SetHeaderTitles();
391                }
392                ULONGLONG GetDbghelpVersion() const throw()
393                {
394                        return m_nDbghelpVersion;
395                }
396                CProcessData& GetSelectedProcessData() throw()
397                {
398                        _A(m_SelectedPosition);
399                        return m_ProcessDataList.GetAt(m_SelectedPosition);
400                }
401                BOOL IsSelectedProcessActive() const throw()
402                {
403                        if(!m_SelectedPosition)
404                                return FALSE;
405                        const CProcessData& ProcessData = m_ProcessDataList.GetAt(m_SelectedPosition);
406                        return WaitForSingleObject(ProcessData.m_Handle, 0) != WAIT_TIMEOUT;
407                }
408
409        // Window message handlers
410                LRESULT OnInitDialog(HWND, LPARAM)
411                {
412                        m_bActivating = TRUE;
413                        _ATLTRY
414                        {
415                                CWaitCursor WaitCursor;
416                                #pragma region Debug Help Library Availability and Version
417                                m_nDbghelpVersion = 0;
418                                CStatic DbghelpVersionStatic = GetDlgItem(IDC_MAIN_DBGHELPVERSION);
419                                _ATLTRY
420                                {
421                                        CString sDefaultDbghelpVersionStaticText, sText;
422                                        _W(DbghelpVersionStatic.GetWindowText(sDefaultDbghelpVersionStaticText));
423                                        const HMODULE hModule = LoadLibrary(_T("dbghelp.dll"));
424                                        if(hModule)
425                                        {
426                                                _ATLTRY
427                                                {
428                                                        TCHAR pszPath[MAX_PATH] = { 0 };
429                                                        _W(GetModuleFileName(hModule, pszPath, DIM(pszPath)));
430                                                        const ULONGLONG nVersion = _VersionInfoHelper::GetFileVersion(_VersionInfoHelper::GetModulePath(hModule));
431                                                        if(nVersion)
432                                                                sText = AtlFormatString(_StringHelper::GetLine(sDefaultDbghelpVersionStaticText, 0), _VersionInfoHelper::GetVersionString(nVersion));
433                                                        m_nDbghelpVersion = nVersion;
434                                                }
435                                                _ATLCATCHALL()
436                                                {
437                                                        _W(FreeLibrary(hModule));
438                                                        _ATLRETHROW;
439                                                }
440                                                _W(FreeLibrary(hModule));
441                                        }
442                                        if(sText.IsEmpty())
443                                                sText = AtlFormatString(_StringHelper::GetLine(sDefaultDbghelpVersionStaticText, 0), _StringHelper::GetLine(sDefaultDbghelpVersionStaticText, 1));
444                                        DbghelpVersionStatic.SetWindowText(sText);
445                                        _W(m_DbghelpVersionStatic.SubclassWindow(DbghelpVersionStatic));
446                                        const CSize IdealExtent = m_DbghelpVersionStatic.GetIdealExtent();
447                                        CRect Position;
448                                        _W(m_DbghelpVersionStatic.GetWindowRect(Position));
449                                        _W(ScreenToClient(Position));
450                                        Position.left = Position.right - IdealExtent.cx - 2;
451                                        _W(m_DbghelpVersionStatic.MoveWindow(Position));
452                                }
453                                _ATLCATCHALL()
454                                {
455                                        _Z_EXCEPTION();
456                                        DbghelpVersionStatic.ShowWindow(SW_HIDE);
457                                }
458                                #pragma endregion
459                                m_ProcessListView.Initialize(GetDlgItem(IDC_MAIN_PROCESSES));
460                                #if !defined(_WIN64)
461                                // NOTE: 32-bit Application which is not a WOW64 process is running on 32-bit OS
462                                if(!SafeIsWow64Process())
463                                        _W(m_ProcessListView.DeleteColumn(2));
464                                #endif // !defined(_WIN64)
465                                // NOTE: We need to enable Debug privilege prior to enumerating processes, so that we could see service processes
466                                EnableTokenDebugPrivilege();
467                                UpdateProcessListView();
468                                #pragma region Initial Selection Using Command Line
469                                CString sCommandLine = GetCommandLine();
470                                sCommandLine.TrimLeft();
471                                if(!sCommandLine.IsEmpty())
472                                {
473                                        #pragma region Delete Application Path
474                                        if(sCommandLine[0] == _T('\"'))
475                                        {
476                                                const INT nPosition = sCommandLine.Find(_T('\"'), 1);
477                                                if(nPosition >= 0)
478                                                        sCommandLine.Delete(0, nPosition + 1);
479                                                else
480                                                        sCommandLine.Empty();
481                                        } else
482                                        {
483                                                const INT nPosition = sCommandLine.Find(_T(' '), 0);
484                                                if(nPosition >= 0)
485                                                        sCommandLine.Delete(0, nPosition + 1);
486                                                else
487                                                        sCommandLine.Empty();
488                                        }
489                                        sCommandLine.TrimLeft();
490                                        #pragma endregion
491                                        CString sProcess = sCommandLine;
492                                        sProcess.Trim();
493                                        if(!sProcess.IsEmpty())
494                                        {
495                                                POSITION Position = NULL;
496                                                const INT nProcessIdentifier = _ttoi(sProcess);
497                                                if(nProcessIdentifier)
498                                                        m_ProcessDataList.FindFirstThatT<DWORD>(&CProcessData::CompareIdentifier, nProcessIdentifier, &Position);
499                                                if(!Position && !sProcess.IsEmpty())
500                                                        m_ProcessDataList.FindFirstThatT<LPCTSTR>(&CProcessData::ComparePartialFileName, sProcess, &Position);
501                                                if(Position)
502                                                {
503                                                        const INT nItem = m_ProcessListView.FindItemData(Position);
504                                                        if(nItem >= 0)
505                                                        {
506                                                                _W(m_ProcessListView.SetItemState(nItem, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED));
507                                                                _W(m_ProcessListView.EnsureVisible(nItem, FALSE));
508                                                        }
509                                                }
510                                        }
511                                }
512                                #pragma endregion
513                                UpdateButtons();
514                                m_bActivating = FALSE;
515                        }
516                        _ATLCATCHALL()
517                        {
518                                _Z_EXCEPTION();
519                        }
520                        return TRUE;
521                }
522                INT OnSetActive() throw()
523                {
524                        _ATLTRY
525                        {
526                                const BOOL bActive = m_Wizard.m_OperationPropertyPage.IsActive();
527                                m_ProcessListView.EnableWindow(!bActive);
528                                CButton(GetDlgItem(IDC_MAIN_REFRESHPROCESSES)).EnableWindow(!bActive);
529                                UpdateButtons();
530                        }
531                        _ATLCATCHALL()
532                        {
533                                MessageBeep(MB_ICONERROR);
534                                return -1;
535                        }
536                        return 0;
537                }
538                LRESULT OnProcessListViewGetDispInfo(NMLVDISPINFO* pHeader)
539                {
540                        if(pHeader->item.mask & LVIF_TEXT)
541                        {
542                                const CProcessData& ProcessData = m_ProcessDataList.GetAt(m_ProcessListView.DataFromParameter(pHeader->item.lParam));
543                                INT nSubItem = pHeader->item.iSubItem;
544#if !defined(_WIN64)
545                                // NOTE: See OnInitDialog and DeleteColumn(2)
546                                if(!SafeIsWow64Process())
547                                        if(nSubItem >= 2)
548                                                nSubItem++;
549#endif // !defined(_WIN64)
550                                m_ProcessListView.m_sTextBuffer.Empty();
551                                switch(nSubItem)
552                                {
553                                case 1: // Identifier
554                                        m_ProcessListView.m_sTextBuffer = AtlFormatString(_T("%d"), ProcessData.m_nIdentifier);
555                                        break;
556                                case 2: // Type
557                                        m_ProcessListView.m_sTextBuffer = ProcessData.m_bIsWow64 ? _T("32-bit") : _T("64-bit");
558                                        break;
559                                case 3: // Window Caption
560                                        m_ProcessListView.m_sTextBuffer = ProcessData.m_sWindowCaption;
561                                        break;
562                                case 4: // Account
563                                        m_ProcessListView.m_sTextBuffer = ProcessData.m_sAccount;
564                                        break;
565                                //case 5: // Image File Path
566                                //      m_ProcessListView.m_sTextBuffer = (LPCTSTR) ProcessData.GetImageFilePath();
567                                //      break;
568                                default: // File Name
569                                        m_ProcessListView.m_sTextBuffer = ProcessData.GetFileName();
570                                }
571                                m_ProcessListView.m_sTextBuffer.TrimRight(_T("\t\n\r ."));
572                                pHeader->item.pszText = m_ProcessListView.GetTextBuffer();
573                        }
574                        //if(pHeader->item.mask & LVIF_IMAGE)
575                        //      pHeader->item.iImage = 0;
576                        return 0;
577                }
578                LRESULT OnProcessListViewGetInfoTip(NMLVGETINFOTIP* pHeader)
579                {
580                        const CProcessData& ProcessData = m_ProcessDataList.GetAt(m_ProcessListView.GetItemData(pHeader->iItem));
581                        CString& sTextBuffer = m_ProcessListView.GetTextBufferString(TRUE);
582                        sTextBuffer.AppendFormat(_T("File Name: %s\r\n"), ProcessData.GetFileName());
583                        sTextBuffer.AppendFormat(_T("Identifier: %d (0x%x)\r\n"), ProcessData.m_nIdentifier, ProcessData.m_nIdentifier);
584                        BOOL bIs64Bit = FALSE;
585#if !defined(_WIN64)
586                        if(SafeIsWow64Process())
587#endif // !defined(_WIN64)
588                                bIs64Bit = !ProcessData.m_bIsWow64;
589                        sTextBuffer.AppendFormat(_T("Type: %s\r\n"), !bIs64Bit ? _T("32-bit") : _T("64-bit"));
590                        if(!ProcessData.m_sAccount.IsEmpty())
591                                sTextBuffer.AppendFormat(_T("Account: %s\r\n"), ProcessData.m_sAccount);
592                        sTextBuffer.AppendFormat(_T("Window Caption: %s\r\n"), ProcessData.m_sWindowCaption);
593                        //sTextBuffer.AppendFormat(_T("Image File Path: %s\r\n"), ProcessData.GetImageFilePath());
594                        sTextBuffer.AppendFormat(_T("Working Set Size: %s MB\r\n"), _StringHelper::FormatNumber((LONG) ProcessData.GetMemoryCounters().WorkingSetSize >> 20));
595                        sTextBuffer.AppendFormat(_T("Private Memory: %s MB\r\n"), _StringHelper::FormatNumber((LONG) ProcessData.GetMemoryCounters().PrivateUsage >> 20));
596                        sTextBuffer.TrimRight(_T("\t\n\r ."));
597                        _tcsncpy_s(pHeader->pszText, pHeader->cchTextMax, m_ProcessListView.GetTextBuffer(), _TRUNCATE);
598                        return 0;
599                }
600                LRESULT OnProcessListItemChanged(NMLISTVIEW*)
601                {
602                        if(m_bActivating)
603                                return 0;
604                        UpdateButtons();
605                        return 0;
606                }
607                LRESULT OnProcessListViewDblClk(NMITEMACTIVATE*)
608                {
609                        if(m_ProcessListView.GetSelectedCount() == 1)
610                                m_Wizard.PressButton(PSBTN_NEXT);
611                        return 0;
612                }
613                LRESULT OnRefreshButtonClicked(UINT, INT, HWND)
614                {
615                        UpdateProcessListView();
616                        UpdateButtons();
617                        return 0;
618                }
619                BOOL OnQueryCancel()
620                {
621                        return m_Wizard.m_OperationPropertyPage.OnQueryCancel();
622                }
623                INT OnWizardNext() throw()
624                {
625                        _ATLTRY
626                        {
627                                __D(m_ProcessListView.GetSelectedCount() == 1, E_UNNAMED);
628                                m_SelectedPosition = m_ProcessListView.GetItemData(m_ProcessListView.GetNextItem(-1, LVNI_SELECTED));
629                                _A(m_SelectedPosition);
630                        }
631                        _ATLCATCHALL()
632                        {
633                                MessageBeep(MB_ICONERROR);
634                                return -1;
635                        }
636                        return 0;
637                }
638        };
639
640        ////////////////////////////////////////////////////////
641        // CMinidumpTypePropertyPage
642
643        class CMinidumpTypePropertyPage :
644                public CWizardPropertyPageT<CMinidumpTypePropertyPage>
645        {
646        public:
647                enum { IDD = IDD_MAIN_MINIDUMPTYPE };
648
649        BEGIN_MSG_MAP_EX(CMinidumpTypePropertyPage)
650                CHAIN_MSG_MAP(CWizardPropertyPageT<CMinidumpTypePropertyPage>)
651                MSG_WM_INITDIALOG(OnInitDialog)
652                REFLECT_NOTIFICATIONS()
653        END_MSG_MAP()
654
655        public:
656
657                ////////////////////////////////////////////////////
658                // TYPEITEM
659
660                typedef struct _TYPEITEM
661                {
662                        INT nIdentifier;
663                        MINIDUMP_TYPE Type;
664                        ULONGLONG nOsVersion;
665                        ULONGLONG nApiVersion;
666                } TYPEITEM;
667
668        private:
669                CMainWizard& m_Wizard;
670                BOOL m_bActivating;
671                CRoHyperStatic m_MinidumpTypeStatic;
672                mutable CRoCriticalSection m_DataCriticalSection;
673                MINIDUMP_TYPE m_MinidumpType;
674
675                static const TYPEITEM* GetTypeItemMap() throw()
676                {
677                        static const TYPEITEM g_pMap[] = 
678                        {
679                                { IDC_MAIN_MINIDUMPTYPE_DATASEGMENTS,               MiniDumpWithDataSegs },
680                                { IDC_MAIN_MINIDUMPTYPE_FULLMEMORY,                 MiniDumpWithFullMemory },
681                                { IDC_MAIN_MINIDUMPTYPE_HANDLEDATA,                 MiniDumpWithHandleData },
682                                { IDC_MAIN_MINIDUMPTYPE_FILTERMEMORY,               MiniDumpFilterMemory },
683                                { IDC_MAIN_MINIDUMPTYPE_SCANMEMORY,                 MiniDumpScanMemory},
684                                { IDC_MAIN_MINIDUMPTYPE_UNLOADEDMODULES,            MiniDumpWithUnloadedModules,            0, 0x0005000200000000 }, // Windows Server 2003 and Windows XP: See MSDN, DbgHelp 5.1: This value is not supported
685                                { IDC_MAIN_MINIDUMPTYPE_INDIRECTLYREFERENCEDMEMORY, MiniDumpWithIndirectlyReferencedMemory, 0, 0x0005000200000000 }, // DbgHelp 5.1: This value is not supported
686                                { IDC_MAIN_MINIDUMPTYPE_FILTERMODULEPATHS,          MiniDumpFilterModulePaths,              0, 0x0005000200000000 }, // DbgHelp 5.1: This value is not supported
687                                { IDC_MAIN_MINIDUMPTYPE_PROCESSTHREADDATA,          MiniDumpWithProcessThreadData,          0, 0x0005000200000000 }, // DbgHelp 5.1: This value is not supported
688                                { IDC_MAIN_MINIDUMPTYPE_PRIVATEREADWRITEMEMORY,     MiniDumpWithPrivateReadWriteMemory,     0, 0x0005000200000000 }, // DbgHelp 5.1: This value is not supported
689                                { IDC_MAIN_MINIDUMPTYPE_WITHOUTOPTIONALDATA,        MiniDumpWithoutOptionalData,            0, 0x0006000200000000 }, // DbgHelp 6.1 and earlier: This value is not supported
690                                { IDC_MAIN_MINIDUMPTYPE_FULLMEMORYINFO,             MiniDumpWithFullMemoryInfo,             0, 0x0006000200000000 }, // DbgHelp 6.1 and earlier: This value is not supported
691                                { IDC_MAIN_MINIDUMPTYPE_THREADINFO,                 MiniDumpWithThreadInfo,                 0, 0x0006000200000000 }, // DbgHelp 6.1 and earlier: This value is not supported
692                                { IDC_MAIN_MINIDUMPTYPE_CODESEGS,                   MiniDumpWithCodeSegs,                   0, 0x0006000200000000 }, // DbgHelp 6.1 and earlier: This value is not supported
693                                { IDC_MAIN_MINIDUMPTYPE_WITHOUTAUXILIARYSTATE,      MiniDumpWithoutAuxiliaryState },
694                                { IDC_MAIN_MINIDUMPTYPE_FULLAUXILIARYSTATE,         MiniDumpWithFullAuxiliaryState },
695                                { IDC_MAIN_MINIDUMPTYPE_PRIVATEWRITECOPYMEMORY,     MiniDumpWithPrivateWriteCopyMemory,     0, 0x0006000100000000 }, // Prior to DbgHelp 6.1: This value is not supported
696                                { IDC_MAIN_MINIDUMPTYPE_IGNOREINACCESSIBLEMEMORY,   MiniDumpIgnoreInaccessibleMemory,       0, 0x0006000100000000 }, // Prior to DbgHelp 6.1: This value is not supported
697                                { IDC_MAIN_MINIDUMPTYPE_TOKENINFORMATION,           MiniDumpWithTokenInformation,           0, 0x0006000100000000 }, // Prior to DbgHelp 6.1: This value is not supported
698                                { 0 }
699                        };
700                        return g_pMap;
701                }
702                VOID UpdateButtons() throw()
703                {
704                        const BOOL bAllowNext = m_Wizard.m_ProcessPropertyPage.IsSelectedProcessActive();
705                        SetWizardButtons(PSWIZB_BACK | (bAllowNext ? PSWIZB_NEXT : 0));
706                }
707
708        public:
709        // CMinidumpTypePropertyPage
710                CMinidumpTypePropertyPage(CMainWizard* pWizard) throw() :
711                        m_Wizard(*pWizard)
712                {
713                        SetHeaderTitles();
714                }
715                MINIDUMP_TYPE GetMinidumpType() const throw()
716                {
717                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
718                        return m_MinidumpType;
719                }
720
721        // Window message handlers
722                LRESULT OnInitDialog(HWND, LPARAM)
723                {
724                        m_bActivating = TRUE;
725                        _ATLTRY
726                        {
727                                CWaitCursor WaitCursor;
728                                _W(m_MinidumpTypeStatic.SubclassWindow(GetDlgItem(IDC_MAIN_MINIDUMPTYPE)));
729                                #pragma region Enable OS and API Dependent Items
730                                const ULONGLONG nOsVersion = GetOsVersion();
731                                const ULONGLONG nApiVersion = m_Wizard.m_ProcessPropertyPage.GetDbghelpVersion();
732                                static const MINIDUMP_TYPE g_DefaultType = (MINIDUMP_TYPE) (
733                                        MiniDumpWithDataSegs |
734                                        //MiniDumpWithFullMemory |
735                                        MiniDumpWithThreadInfo |
736                                        MiniDumpIgnoreInaccessibleMemory |
737                                        0);
738                                for(const TYPEITEM* pTypeItem = GetTypeItemMap(); pTypeItem->nIdentifier; pTypeItem++)
739                                {
740                                        CButton Button = GetDlgItem(pTypeItem->nIdentifier);
741                                        if(g_DefaultType & pTypeItem->Type)
742                                                Button.SetCheck(TRUE);
743                                        if(pTypeItem->nOsVersion && nOsVersion < pTypeItem->nOsVersion ||pTypeItem->nApiVersion && nApiVersion < pTypeItem->nApiVersion)
744                                        {
745                                                Button.SetCheck(FALSE);
746                                                Button.EnableWindow(FALSE);
747                                        }
748                                }
749                                #pragma endregion
750                                CButton(GetDlgItem(IDC_MAIN_MINIDUMPTYPE_DATASEGMENTS)).SetCheck(TRUE);
751                                #pragma region Initialize from Registry
752                                DWORD nIntegerType;
753                                if(_RegKeyHelper::QueryIntegerValueEx(HKEY_CURRENT_USER, REGISTRY_ROOT, _T("Minidump Type"), nIntegerType))
754                                {
755                                        MINIDUMP_TYPE Type = (MINIDUMP_TYPE) nIntegerType;
756                                        for(const TYPEITEM* pTypeItem = GetTypeItemMap(); pTypeItem->nIdentifier; pTypeItem++)
757                                        {
758                                                CButton Button = GetDlgItem(pTypeItem->nIdentifier);
759                                                if(Button.IsWindowEnabled())
760                                                        Button.SetCheck(Type & pTypeItem->Type);
761                                        }
762                                }
763                                #pragma endregion
764                                UpdateButtons();
765                                m_bActivating = FALSE;
766                        }
767                        _ATLCATCHALL()
768                        {
769                                _Z_EXCEPTION();
770                        }
771                        return TRUE;
772                }
773                INT OnSetActive() throw()
774                {
775                        _ATLTRY
776                        {
777                                UpdateButtons();
778                        }
779                        _ATLCATCHALL()
780                        {
781                                MessageBeep(MB_ICONERROR);
782                                return -1;
783                        }
784                        return 0;
785                }
786                BOOL OnQueryCancel()
787                {
788                        return m_Wizard.m_OperationPropertyPage.OnQueryCancel();
789                }
790                INT OnWizardNext() throw()
791                {
792                        _ATLTRY
793                        {
794                                MINIDUMP_TYPE Type = MiniDumpNormal;
795                                _A(!Type);
796                                for(const TYPEITEM* pTypeItem = GetTypeItemMap(); pTypeItem->nIdentifier; pTypeItem++)
797                                {
798                                        CButton Button = GetDlgItem(pTypeItem->nIdentifier);
799                                        if(Button.IsWindowVisible() && Button.IsWindowEnabled())
800                                                if(Button.GetCheck())
801                                                        Type = (MINIDUMP_TYPE) ((UINT) Type | pTypeItem->Type);
802                                }
803                                _RegKeyHelper::SetIntegerValue(HKEY_CURRENT_USER, REGISTRY_ROOT, _T("Minidump Type"), (DWORD) Type);
804                                {
805                                        CRoCriticalSectionLock DataLock(m_DataCriticalSection);
806                                        m_MinidumpType = Type;
807                                }
808                                if(!m_Wizard.m_ProcessPropertyPage.IsSelectedProcessActive())
809                                {
810                                        UpdateButtons();
811                                        __C(E_UNNAMED);
812                                }
813                        }
814                        _ATLCATCHALL()
815                        {
816                                MessageBeep(MB_ICONERROR);
817                                return -1;
818                        }
819                        return 0;
820                }
821        };
822
823        ////////////////////////////////////////////////////////
824        // COperationPropertyPage
825
826        class COperationPropertyPage :
827                public CWizardPropertyPageT<COperationPropertyPage>,
828                public CWindowWithPrivateMessagesT<COperationPropertyPage>
829        {
830                typedef CThreadT<COperationPropertyPage> CThread;
831
832        public:
833                enum { IDD = IDD_MAIN_OPERATION };
834
835        BEGIN_MSG_MAP_EX(COperationPropertyPage)
836                CHAIN_MSG_MAP(CWizardPropertyPageT<COperationPropertyPage>)
837                CHAIN_MSG_MAP(CWindowWithPrivateMessagesT<COperationPropertyPage>)
838                MSG_WM_INITDIALOG(OnInitDialog)
839                MSG_WM_DESTROY(OnDestroy)
840                MESSAGE_HANDLER_EX(WM_UPDATELOGTEXT, OnUpdateLogText)
841                MESSAGE_HANDLER_EX(WM_DEBUGTHREADENDED, OnDebugThreadEnded)
842                NOTIFY_HANDLER_EX(IDC_MAIN_OPERATION_WRITEMINIDUMPNOW, CRoHyperStatic::NC_ANCHORCLICKED, OnWriteMinidumpNowStaticAnchorClicked)
843                NOTIFY_HANDLER_EX(IDC_MAIN_OPERATION_OPENMINIDUMPFILEDIRECTORY, CRoHyperStatic::NC_ANCHORCLICKED, OnOpenMinidumpFileDirectoryStaticAnchorClicked)
844                REFLECT_NOTIFICATIONS()
845        END_MSG_MAP()
846
847        public:
848
849                ////////////////////////////////////////////////////
850                // Message Identifiers
851
852                enum
853                {
854                        WM_FIRST = WM_APP,
855                        WM_UPDATELOGTEXT,
856                        WM_DEBUGTHREADENDED,
857                };
858
859        private:
860                CMainWizard& m_Wizard;
861                BOOL m_bActivating;
862                CPath m_sDataDirectory;
863                CRoEdit m_LogEdit;
864                CRoHyperStatic m_WriteMinidumpNowStatic;
865                CRoHyperStatic m_OpenMinidumpFileDirectoryStatic;
866                mutable CRoCriticalSection m_LogTextCriticalSection;
867                CString m_sLogText;
868                HRESULT m_nResult;
869                CObjectPtr<CThread> m_pDebugThread;
870                UINT m_nExceptionIndex;
871                UINT m_nUserIndex;
872
873                VOID UpdateButtons() throw()
874                {
875                        SetWizardButtons(PSWIZB_BACK | PSWIZB_NEXT);
876                }
877                VOID AppendLog(const CString& sText)
878                {
879                        if(sText.IsEmpty())
880                                return;
881                        CRoCriticalSectionLock LogTextLock(m_LogTextCriticalSection);
882                        const BOOL bLogTextEmpty = m_sLogText.IsEmpty();
883                        m_sLogText += sText;
884                        if(bLogTextEmpty)
885                                PostPrivateMessage(WM_UPDATELOGTEXT);
886                }
887                DWORD DebugThreadProc(CThread* pThread, CEvent& InitializationEvent, CEvent& TerminationEvent)
888                {
889                        // ASSU: Windows XP+
890                        const CProcessPropertyPage::CProcessData& ProcessData = m_Wizard.m_ProcessPropertyPage.GetSelectedProcessData();
891                        const DWORD nProcessIdentifier = ProcessData.m_nIdentifier;
892                        __E(DebugActiveProcess(nProcessIdentifier));
893                        _ATLTRY
894                        {
895                                CErrorMode LocalErrorMode(~SEM_FAILCRITICALERRORS, SEM_FAILCRITICALERRORS);
896                                _W(DebugSetProcessKillOnExit(FALSE));
897                                CHandle Process(OpenProcess(PROCESS_ALL_ACCESS, FALSE, nProcessIdentifier));
898                                __E(Process);
899                                TCHAR pszProcessFilePath[MAX_PATH] = { 0 };
900                                _W(GetModuleFileNameEx(Process, NULL, pszProcessFilePath, DIM(pszProcessFilePath)));
901                                LPCTSTR pszProcessFileName = FindFileName(pszProcessFilePath);
902                                _W(InitializationEvent.Set());
903                                CStackPointer StackPointer;
904                                for(; ; )
905                                {
906                                        _A(StackPointer.Check()); StackPointer;
907                                        {
908                                                const DWORD nWaitResult = WaitForSingleObject(TerminationEvent, 0);
909                                                _Z5(atlTraceSync, 5, _T("nWaitResult 0x%x\n"), nWaitResult);
910                                                _A(nWaitResult == WAIT_OBJECT_0 || nWaitResult == WAIT_TIMEOUT);
911                                                if(nWaitResult != WAIT_TIMEOUT)
912                                                        break;
913                                        }
914                                        DEBUG_EVENT DebugEvent;
915                                        ZeroMemory(&DebugEvent, sizeof DebugEvent);
916                                        static const ULONG g_nTimeout = 1000; // 1 second
917                                        const BOOL bWaitResult = WaitForDebugEvent(&DebugEvent, g_nTimeout);
918                                        if(!bWaitResult)
919                                                continue;
920                                        _Z4(atlTraceGeneral, 4, _T("Debug event, DebugEvent.dwDebugEventCode %d, .dwProcessId %d, .dwThreadId %d\n"), DebugEvent.dwDebugEventCode, DebugEvent.dwProcessId, DebugEvent.dwThreadId);
921                                        // TODO: Handle load/unload DLL, output debug strings (configurable)
922                                        BOOL bExitProcess = FALSE;
923                                        switch(DebugEvent.dwDebugEventCode)
924                                        {
925                                        case CREATE_PROCESS_DEBUG_EVENT:
926                                                {
927                                                        const CREATE_PROCESS_DEBUG_INFO& DebugInformation = DebugEvent.u.CreateProcessInfo;
928                                                }
929                                                break;
930                                        case EXIT_PROCESS_DEBUG_EVENT:
931                                                {
932                                                        const EXIT_PROCESS_DEBUG_INFO& DebugInformation = DebugEvent.u.ExitProcess;
933                                                        bExitProcess = TRUE;
934                                                        break;
935                                                }
936                                                break;
937                                        case EXCEPTION_DEBUG_EVENT:
938                                                {
939                                                        const EXCEPTION_DEBUG_INFO& DebugInformation = DebugEvent.u.Exception;
940                                                        _Z4(atlTraceGeneral, 4, _T(".ExceptionCode %d, .ExceptionFlags %d, .dwFirstChance %d\n"), DebugInformation.ExceptionRecord.ExceptionCode, DebugInformation.ExceptionRecord.ExceptionFlags, DebugInformation.dwFirstChance);
941                                                        #pragma region Skip Initial Debugger Attachment Exception
942                                                        if(DebugInformation.ExceptionRecord.ExceptionCode == 0x80000003 && !m_nExceptionIndex)
943                                                        {
944                                                                AppendLog(AtlFormatString(_T("Skipping initial debugger attachment exception (0x%08x)\r\n"), DebugInformation.ExceptionRecord.ExceptionCode));
945                                                                break;
946                                                        }
947                                                        #pragma endregion
948                                                        #pragma region Skip "SetThreadName" Exception
949                                                        // NOTE: See http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx, not a true exception, but an awful patch to set thread name
950                                                        if(DebugInformation.ExceptionRecord.ExceptionCode == 0x406D1388)
951                                                        {
952                                                                AppendLog(AtlFormatString(_T("Skipping thread name setting exception (0x%08x)\r\n"), DebugInformation.ExceptionRecord.ExceptionCode));
953                                                                break;
954                                                        }
955                                                        #pragma endregion
956                                                        #pragma region Skip C++ Exceptions (Debug)
957                                                        #if _DEVELOPMENT && FALSE
958                                                        COMPILER_MESSAGE("Debug: Skip C++ Exceptions")
959                                                        if(DebugInformation.ExceptionRecord.ExceptionCode == 0xE06D7363)
960                                                        {
961                                                                AppendLog(AtlFormatString(_T("Skipping C++ exception (0x%08x)\r\n"), DebugInformation.ExceptionRecord.ExceptionCode));
962                                                                break;
963                                                        }
964                                                        #endif // _DEVELOPMENT
965                                                        #pragma endregion
966                                                        _ATLTRY
967                                                        {
968                                                                MINIDUMP_EXCEPTION_INFORMATION ExceptionInformation;
969                                                                ZeroMemory(&ExceptionInformation, sizeof ExceptionInformation);
970                                                                ExceptionInformation.ThreadId = DebugEvent.dwThreadId;
971                                                                EXCEPTION_POINTERS ExceptionPointers;
972                                                                ZeroMemory(&ExceptionPointers, sizeof ExceptionPointers);
973                                                                ExceptionPointers.ExceptionRecord = const_cast<EXCEPTION_RECORD*>(&DebugInformation.ExceptionRecord);
974                                                                CONTEXT Context = { CONTEXT_ALL };
975                                                                CHandle Thread(OpenThread(THREAD_ALL_ACCESS, FALSE, DebugEvent.dwThreadId));
976                                                                if(Thread)
977                                                                        if(GetThreadContext(Thread, &Context))
978                                                                                ExceptionPointers.ContextRecord = &Context;
979                                                                ExceptionInformation.ExceptionPointers = &ExceptionPointers;
980                                                                ExceptionInformation.ClientPointers = FALSE;
981                                                                CString sName;
982                                                                sName.AppendFormat(_T("%s-%d-%03d"), pszProcessFileName, nProcessIdentifier, m_nExceptionIndex++);
983                                                                sName.AppendFormat(_T("-%08x"), DebugInformation.ExceptionRecord.ExceptionCode);
984                                                                if(DebugInformation.ExceptionRecord.ExceptionCode == 0xE06D7363 && DebugInformation.ExceptionRecord.NumberParameters >= 2)
985                                                                {
986                                                                        HRESULT nNativeExceptionCode = 0;
987                                                                        SIZE_T nReadDataSize = 0;
988                                                                        if(ReadProcessMemory(Process, (const VOID*) DebugInformation.ExceptionRecord.ExceptionInformation[1], &nNativeExceptionCode, sizeof nNativeExceptionCode, &nReadDataSize))
989                                                                                if(nReadDataSize == sizeof nNativeExceptionCode)
990                                                                                        sName.AppendFormat(_T("-%08x"), nNativeExceptionCode);
991                                                                }
992                                                                sName.Append(_T(".dmp"));
993                                                                CPath sPath;
994                                                                sPath.Combine(m_sDataDirectory, sName);
995                                                                CAtlFile File;
996                                                                __C(File.Create(sPath, GENERIC_WRITE, CREATE_ALWAYS, FILE_SHARE_READ));
997                                                                const MINIDUMP_TYPE Type = m_Wizard.m_MinidumpTypePropertyPage.GetMinidumpType();
998                                                                __E(MiniDumpWriteDump(Process, nProcessIdentifier, File, Type, ExceptionPointers.ContextRecord ? &ExceptionInformation : NULL, NULL, NULL));
999                                                                AppendLog(AtlFormatString(_T("Written exception minidump into file %s\r\n"), sName));
1000                                                        }
1001                                                        _ATLCATCHALL()
1002                                                        {
1003                                                                _Z_EXCEPTION();
1004                                                        }
1005                                                }
1006                                                break;
1007                                        }
1008                                        __E(ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED));
1009                                        if(bExitProcess)
1010                                                break;
1011                                }
1012                        }
1013                        _ATLCATCHALL()
1014                        {
1015                                _W(DebugActiveProcessStop(nProcessIdentifier));
1016                                _ATLRETHROW;
1017                        }
1018                        _W(DebugActiveProcessStop(nProcessIdentifier));
1019                        PostPrivateMessage(WM_DEBUGTHREADENDED);
1020                        return 0;
1021                }
1022                VOID AttachDebug()
1023                {
1024                        _A(!m_pDebugThread);
1025                        m_nUserIndex = 0;
1026                        const CProcessPropertyPage::CProcessData& ProcessData = m_Wizard.m_ProcessPropertyPage.GetSelectedProcessData();
1027                        const DWORD nProcessIdentifier = ProcessData.m_nIdentifier;
1028                        CObjectPtr<CThread> pDebugThread;
1029                        __E(pDebugThread.Construct()->Initialize(this, &CMainWizard::COperationPropertyPage::DebugThreadProc));
1030                        m_pDebugThread = pDebugThread;
1031                        AppendLog(AtlFormatString(_T("Attached to process %d\r\n"), nProcessIdentifier));
1032                }
1033                VOID DetachDebug() throw()
1034                {
1035                        if(m_pDebugThread)
1036                        {
1037                                AppendLog(AtlFormatString(_T("Detached from process\r\n")));
1038                                m_pDebugThread = NULL;
1039                        }
1040                }
1041
1042        public:
1043        // COperationPropertyPage
1044                COperationPropertyPage(CMainWizard* pWizard) throw() :
1045                        m_Wizard(*pWizard),
1046                        m_nResult(S_FALSE),
1047                        m_nExceptionIndex(0)
1048                {
1049                        SetHeaderTitles();
1050                }
1051                HRESULT GetResult() const throw()
1052                {
1053                        return m_nResult;
1054                }
1055                BOOL IsActive() const throw()
1056                {
1057                        return m_pDebugThread != NULL;
1058                }
1059
1060        // Window message handlers
1061                LRESULT OnInitDialog(HWND, LPARAM)
1062                {
1063                        m_bActivating = TRUE;
1064                        _ATLTRY
1065                        {
1066                                //CWaitCursor WaitCursor;
1067                                TCHAR pszModuleDirectory[MAX_PATH] = { 0 };
1068                                _W(GetModuleFileName(_AtlBaseModule.GetModuleInstance(), pszModuleDirectory, DIM(pszModuleDirectory)));
1069                                _W(RemoveFileSpec(pszModuleDirectory));
1070                                m_sDataDirectory = pszModuleDirectory;
1071                                m_LogEdit = GetDlgItem(IDC_MAIN_OPERATION_LOG);
1072                                _W(m_WriteMinidumpNowStatic.SubclassWindow(GetDlgItem(IDC_MAIN_OPERATION_WRITEMINIDUMPNOW)));
1073                                _W(m_OpenMinidumpFileDirectoryStatic.SubclassWindow(GetDlgItem(IDC_MAIN_OPERATION_OPENMINIDUMPFILEDIRECTORY)));
1074                                CRoHyperStatic::SetIdealExtentHorizontally(2, &m_WriteMinidumpNowStatic, &m_OpenMinidumpFileDirectoryStatic);
1075                                UpdateButtons();
1076                                m_bActivating = FALSE;
1077                        }
1078                        _ATLCATCHALL()
1079                        {
1080                                _Z_EXCEPTION();
1081                        }
1082                        return TRUE;
1083                }
1084                LRESULT OnDestroy()
1085                {
1086                        DetachDebug();
1087                        return 0;
1088                }
1089                INT OnSetActive() throw()
1090                {
1091                        _ATLTRY
1092                        {
1093                                if(!m_pDebugThread)
1094                                        _ATLTRY
1095                                        {
1096                                                CWaitCursor WaitCursor;
1097                                                const CProcessPropertyPage::CProcessData& ProcessData = m_Wizard.m_ProcessPropertyPage.GetSelectedProcessData();
1098                                                AppendLog(AtlFormatString(_T("Using directory \"%s\" for minidump files...\r\n"), m_sDataDirectory));
1099                                                AppendLog(AtlFormatString(_T("Attaching to process %d (%s)...\r\n"), ProcessData.m_nIdentifier, ProcessData.GetFileName()));
1100                                                EnableTokenDebugPrivilege();
1101                                                AttachDebug();
1102                                        }
1103                                        _ATLCATCH(Exception)
1104                                        {
1105                                                _Z_ATLEXCEPTION(Exception);
1106                                                m_nResult = Exception;
1107                                                _ATLRETHROW;
1108                                        }
1109                                UpdateButtons();
1110                        }
1111                        _ATLCATCHALL()
1112                        {
1113                                MessageBeep(MB_ICONERROR);
1114                                return -1;
1115                        }
1116                        return 0;
1117                }
1118                LRESULT OnUpdateLogText(UINT, WPARAM, LPARAM)
1119                {
1120                        CString sLogText;
1121                        {
1122                                CRoCriticalSectionLock LogTextLock(m_LogTextCriticalSection);
1123                                if(m_sLogText.IsEmpty())
1124                                        return 0;
1125                                sLogText = m_LogEdit.GetValue() + m_sLogText;
1126                                m_sLogText.Empty();
1127                        }
1128                        m_LogEdit.SetValue(sLogText);
1129                        m_LogEdit.SetSel(sLogText.GetLength(), -1, FALSE);
1130                        return 0;
1131                }
1132                LRESULT OnDebugThreadEnded(UINT, WPARAM, LPARAM)
1133                {
1134                        DetachDebug();
1135                        return 0;
1136                }
1137                LRESULT OnWriteMinidumpNowStaticAnchorClicked(NMHDR*)
1138                {
1139                        CWaitCursor WaitCursor;
1140                        CString sName;
1141                        const CProcessPropertyPage::CProcessData& ProcessData = m_Wizard.m_ProcessPropertyPage.GetSelectedProcessData();
1142                        LPCTSTR pszProcessFileName = (LPCTSTR) ProcessData.m_sFilePath + ProcessData.m_sFilePath.FindFileName();
1143                        const DWORD nProcessIdentifier = ProcessData.m_nIdentifier;
1144                        sName.AppendFormat(_T("%s-%d-User-%03d"), pszProcessFileName, nProcessIdentifier, m_nUserIndex++);
1145                        sName.Append(_T(".dmp"));
1146                        CPath sPath;
1147                        sPath.Combine(m_sDataDirectory, sName);
1148                        CAtlFile File;
1149                        __C(File.Create(sPath, GENERIC_WRITE, CREATE_ALWAYS, FILE_SHARE_READ));
1150                        const MINIDUMP_TYPE Type = m_Wizard.m_MinidumpTypePropertyPage.GetMinidumpType();
1151                        __E(MiniDumpWriteDump(ProcessData.m_Handle, nProcessIdentifier, File, Type, NULL, NULL, NULL));
1152                        AppendLog(AtlFormatString(_T("Written exception minidump into file %s per user request\r\n"), sName));
1153                        return 0;
1154                }
1155                LRESULT OnOpenMinidumpFileDirectoryStaticAnchorClicked(NMHDR*)
1156                {
1157                        CWaitCursor WaitCursor;
1158                        __E(ShellExecute(GetPropertySheet(), NULL, m_sDataDirectory, NULL, NULL, SW_SHOWNORMAL) > (HINSTANCE) HINSTANCE_ERROR);
1159                        return 0;
1160                }
1161                BOOL OnQueryCancel()
1162                {
1163                        if(IsActive())
1164                                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)
1165                                        return TRUE;
1166                        return FALSE;
1167                }
1168                INT OnWizardBack() throw()
1169                {
1170                        _ATLTRY
1171                        {
1172                                if(!IsActive())
1173                                {
1174                                        // NOTE: If we are to go back after debugging session is complete, start with new process selection
1175                                        _W(m_Wizard.m_ProcessPropertyPage.PostMessage(WM_COMMAND, MAKEWPARAM(IDC_MAIN_REFRESHPROCESSES, BN_CLICKED)));
1176                                        return IDD_MAIN_PROCESS;
1177                                }
1178                        }
1179                        _ATLCATCHALL()
1180                        {
1181                                MessageBeep(MB_ICONERROR);
1182                                return -1;
1183                        }
1184                        return 0;
1185                }
1186                INT OnWizardNext() throw()
1187                {
1188                        _ATLTRY
1189                        {
1190                                if(IsActive())
1191                                        if(AtlMessageBoxEx(m_Wizard, _T("Debug session is still active, would you like to finish?"), IDS_CONFIRMATION, MB_ICONQUESTION | MB_YESNO) != IDYES)
1192                                                return -1;
1193                        }
1194                        _ATLCATCHALL()
1195                        {
1196                                MessageBeep(MB_ICONERROR);
1197                                return -1;
1198                        }
1199                        return 0;
1200                }
1201        };
1202
1203        ////////////////////////////////////////////////////////
1204        // CCompletionPropertyPage
1205
1206        class CCompletionPropertyPage :
1207                public CWizardPropertyPageT<CCompletionPropertyPage>
1208        {
1209        public:
1210                enum { IDD = IDD_MAIN_COMPLETION };
1211
1212        BEGIN_MSG_MAP_EX(CCompletionPropertyPage)
1213                CHAIN_MSG_MAP(CWizardPropertyPageT<CCompletionPropertyPage>)
1214                MSG_WM_INITDIALOG(OnInitDialog)
1215                NOTIFY_HANDLER_EX(IDC_MAIN_OPERATION_OPENMINIDUMPFILEDIRECTORY, CRoHyperStatic::NC_ANCHORCLICKED, OnOpenMinidumpFileDirectoryStaticAnchorClicked)
1216                REFLECT_NOTIFICATIONS()
1217        END_MSG_MAP()
1218
1219        private:
1220                CMainWizard& m_Wizard;
1221                CRoHyperStatic m_OpenMinidumpFileDirectoryStatic;
1222
1223        public:
1224        // CCompletionPropertyPage
1225                CCompletionPropertyPage(CMainWizard* pWizard) throw() :
1226                        m_Wizard(*pWizard)
1227                {
1228                        m_psp.dwFlags |= PSP_HIDEHEADER;
1229                }
1230
1231        // Window message handlers
1232                LRESULT OnInitDialog(HWND, LPARAM) throw()
1233                {
1234                        CStatic(GetDlgItem(IDC_WIZARDCOMPLETION_ICON)).SetIcon(AtlLoadSysIcon(IDI_INFORMATION));
1235                        CStatic(GetDlgItem(IDC_WIZARDCOMPLETION_TITLE)).SetFont(m_Wizard.GetMessageTitleFont());
1236                        _W(m_OpenMinidumpFileDirectoryStatic.SubclassWindow(GetDlgItem(IDC_MAIN_OPERATION_OPENMINIDUMPFILEDIRECTORY)));
1237                        _W(m_OpenMinidumpFileDirectoryStatic.SetWindowPos(NULL, CRect(CPoint(0, 0), m_OpenMinidumpFileDirectoryStatic.GetIdealExtent()), SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE));
1238                        return TRUE;
1239                }
1240                INT OnSetActive() throw()
1241                {
1242                        SetWizardButtons(PSWIZB_FINISH);
1243                        m_Wizard.GetDlgItem(IDCANCEL).EnableWindow(FALSE);
1244                        const HRESULT nResult = m_Wizard.m_OperationPropertyPage.GetResult();
1245                        if(FAILED(nResult))
1246                        {
1247                                CStatic(GetDlgItem(IDC_WIZARDCOMPLETION_ICON)).SetIcon(AtlLoadSysIcon(IDI_ERROR));
1248                                GetDlgItem(IDC_WIZARDCOMPLETION_RESULT).SetWindowText(AtlFormatString(_T("Error: %s (0x%08x)"), AtlFormatSystemMessage(nResult), nResult));
1249                        }
1250                        return 0;
1251                }
1252                LRESULT OnOpenMinidumpFileDirectoryStaticAnchorClicked(NMHDR* pHeader)
1253                {
1254                        return m_Wizard.m_OperationPropertyPage.OnOpenMinidumpFileDirectoryStaticAnchorClicked(pHeader);
1255                }
1256        };
1257
1258private:
1259        CFont m_LargerBoldFont;
1260        CIntroductionPropertyPage m_IntroductionPropertyPage;
1261        CProcessPropertyPage m_ProcessPropertyPage;
1262        CMinidumpTypePropertyPage m_MinidumpTypePropertyPage;
1263        COperationPropertyPage m_OperationPropertyPage;
1264        CCompletionPropertyPage m_CompletionPropertyPage;
1265
1266        const CFont& CreateLargerBoldFont()
1267        {
1268                CFontHandle BaseFont = AtlGetDefaultGuiFont();
1269                CLogFont LogFont;
1270                _W(BaseFont.GetLogFont(LogFont));
1271                LogFont.SetBold();
1272                LogFont.MakeLarger(2);
1273                m_LargerBoldFont = LogFont.CreateFontIndirect();
1274                return m_LargerBoldFont;
1275        }
1276
1277public:
1278// CMainWizard
1279        static BOOL EnableTokenDebugPrivilege()
1280        {
1281                _ATLTRY
1282                {
1283                        CAccessToken Token;
1284                if(!Token.GetThreadToken(TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES))
1285                        {
1286                                const HRESULT nResult = AtlHresultFromLastError();
1287                                __D(nResult == HRESULT_FROM_WIN32(ERROR_NO_TOKEN), nResult);
1288                                __E(Token.GetProcessToken(TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES));
1289                        }
1290                        __E(Token.EnablePrivilege(SE_DEBUG_NAME));
1291                }
1292                _ATLCATCHALL()
1293                {
1294                        _Z_EXCEPTION();
1295                        return FALSE;
1296                }
1297                return TRUE;
1298        }
1299        CMainWizard() :
1300                CWizardPropertySheetT<CMainWizard>(),
1301                m_IntroductionPropertyPage(this),
1302                m_ProcessPropertyPage(this),
1303                m_MinidumpTypePropertyPage(this),
1304                m_OperationPropertyPage(this),
1305                m_CompletionPropertyPage(this)
1306        {
1307                SetCaption(AtlLoadString(IDS_MAINWIZARD_CAPTION));
1308                SetHeader(MAKEINTRESOURCE(IDB_WIZARDHEADER));
1309                SetWatermark(MAKEINTRESOURCE(IDB_WIZARDWATERMARK));
1310                CreateLargerBoldFont();
1311                AddPage(m_IntroductionPropertyPage);
1312                AddPage(m_ProcessPropertyPage);
1313                AddPage(m_MinidumpTypePropertyPage);
1314                AddPage(m_OperationPropertyPage);
1315                AddPage(m_CompletionPropertyPage);
1316        }
1317        const CFont& GetLargerBoldFont() const throw()
1318        {
1319                return m_LargerBoldFont;
1320        }
1321
1322// Window message handelrs
1323        LRESULT OnSysCommand(UINT nCommand, CPoint)
1324        {
1325                switch(nCommand)
1326                {
1327                case ID_APP_ABOUT:
1328                        {
1329                                CAboutDialog Dialog;
1330                                Dialog.DoModal(m_hWnd);
1331                        }
1332                        break;
1333                default:
1334                        SetMsgHandled(FALSE);
1335                }
1336                return 0;
1337        }
1338};
Note: See TracBrowser for help on using the repository browser.