• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

E:/PROJECTS/cvsed/mixed/VIRTUA~1/vmmon/MainDlg.cpp

Go to the documentation of this file.
00001 
00007 #include "stdafx.h"
00008 #include "resource.h"
00009 #include <bzscmn/bzscmn.h>
00010 #include <bzswin/findproc.h>
00011 #include <bzswin/registry.h>
00012 #include <bzsnet/ratecalc.h>
00013 #include <bzswin/wow64.h>
00014 
00015 #include "MainDlg.h"
00016 #include "trparams.h"
00017 
00018 #include "../kdclient/patchapi.h"
00019 #include "../rpcdispatch/permdesc.h"
00020 
00021 enum
00022 {
00023         ProcessInactive,
00024         ProcessPending,
00025         ProcessPatched,
00026         ProcessFailed
00027 };
00028 
00029 using namespace BazisLib;
00030 
00031 static const TCHAR tszRegistryPath[] = _T("SOFTWARE\\BazisSoft\\KdVMWare\\Monitor");
00032 
00034 HANDLE CreateLogPipe(unsigned PID)
00035 {
00036         PermissiveSecurityDescriptor desc;
00037         TCHAR tszPipeName[MAX_PATH];
00038         _sntprintf_s(tszPipeName, __countof(tszPipeName), _TRUNCATE, tszLogPipeNameFormat, PID);
00039         return CreateNamedPipe(tszPipeName, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE, 2, 65536, 65536, 1000, desc);
00040 }
00041 
00042 static LPCTSTR GetVMTypeName(VMType type)
00043 {
00044         switch (type)
00045         {
00046         case kVMWare32:
00047                 return _T("VMWare");
00048         case kVBox32:
00049                 return _T("VirtualBox");
00050         case kVMWare64:
00051                 return _T("VMWare x64");
00052         case kVBox64:
00053                 return _T("VirtualBox x64");
00054         default:
00055                 return _T("Unknown");
00056         }
00057 }
00058 
00059 static void EnableDebugPrivilege()
00060 {
00061         HANDLE hToken;
00062         LUID sedebugnameValue;
00063         TOKEN_PRIVILEGES tkp;
00064 
00065         OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
00066 
00067 
00068         LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue);
00069 
00070         tkp.PrivilegeCount = 1;
00071         tkp.Privileges[0].Luid = sedebugnameValue;
00072         tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
00073 
00074         AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL);
00075 
00076         CloseHandle(hToken);
00077 }
00078 
00079 CMainDlg::CMainDlg()
00080         : m_DbgToolsPath(_T(""))
00081 {
00082         EnableDebugPrivilege();
00083         SYSTEM_INFO sysinfo;
00084         GetSystemInfo(&sysinfo);
00085         m_ProcessorCount = sysinfo.dwNumberOfProcessors;
00086 
00087         RegistryKey key(HKEY_LOCAL_MACHINE, tszRegistryPath);
00088         key.DeserializeObject(m_Params);
00089 
00090         FilePath toolsPath(_T(""));
00091         if (m_Params.ToolsPath.empty())
00092         {
00093                 RegistryKey key2(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion"));
00094                 toolsPath = (String)key2[_T("ProgramFilesDir")];
00095                 toolsPath = toolsPath + (FilePath)_T("Debugging Tools for Windows");
00096         }
00097         else
00098                 toolsPath = m_Params.ToolsPath;
00099         if (File::Exists(toolsPath + (FilePath)_T("windbg.exe")) && File::Exists(toolsPath + (FilePath)_T("kd.exe")))
00100                 m_DbgToolsPath = toolsPath;
00101 }
00102 
00103 LRESULT CMainDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
00104 {
00105         // center the dialog on the screen
00106         CenterWindow();
00107 
00108         // set icons
00109         HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
00110                 IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
00111         SetIcon(hIcon, TRUE);
00112         HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
00113                 IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
00114         SetIcon(hIconSmall, FALSE);
00115 
00116         m_ListView.m_hWnd = GetDlgItem(IDC_LIST1);
00117         m_StatsView.m_hWnd = GetDlgItem(IDC_STATS);
00118         m_DebugLevel.m_hWnd = GetDlgItem(IDC_DBGLEVEL);
00119 
00120         DlgResize_Init();
00121 
00122         //The lines in the combo box should correspond to DebugXXX enumeration values in status.h
00123         m_DebugLevel.InsertString(-1, _T("No debug messages"));
00124         m_DebugLevel.InsertString(-1, _T("Patcher debug messages"));
00125         //The following level of debug messages is NOT supported in release builds of KDCLIENT.DLL, as
00126         //it considerably slows down everything. KdTraceEnabled constant controls it.
00127 #ifdef _DEBUG
00128         m_DebugLevel.InsertString(-1, _T("Patcher and KDCOM protocol messages (normal)"));
00129         m_DebugLevel.InsertString(-1, _T("Patcher and KDCOM protocol messages (detailed)"));
00130 #endif
00131 
00132         if (m_Params.DebugLevel < (unsigned)m_DebugLevel.GetCount())
00133                 m_DebugLevel.SetCurSel(m_Params.DebugLevel);
00134 
00135         m_ListView.AddColumn(_T("PID"), 0);
00136         m_ListView.AddColumn(_T("VM type"), 1);
00137         m_ListView.AddColumn(_T("Uptime"), 2);
00138         m_ListView.AddColumn(_T("CPU"), 3);
00139         m_ListView.AddColumn(_T("Pipe name"), 4);
00140         m_ListView.AddColumn(_T("Packets"), 5);
00141         m_ListView.AddColumn(_T("Resets"), 6);
00142         m_ListView.AddColumn(_T("OS"), 7);
00143         m_ListView.AddColumn(_T("Debugger"), 8);
00144 
00145         m_ImageList.Create(16, 16, ILC_COLOR4 | ILC_MASK, 4, 0);
00146         m_ImageList.AddIcon(LoadIcon(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDI_GREY)));
00147         m_ImageList.AddIcon(LoadIcon(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDI_YELLOW)));
00148         m_ImageList.AddIcon(LoadIcon(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDI_GREEN)));
00149         m_ImageList.AddIcon(LoadIcon(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDI_RED)));
00150 
00151         m_ListView.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);
00152         m_ListView.ModifyStyle(0, LVS_SINGLESEL);
00153 
00154         m_ListView.SetColumnWidth(0, 60);
00155         m_ListView.SetColumnWidth(1, 100);
00156         m_ListView.SetColumnWidth(2, 60);
00157         m_ListView.SetColumnWidth(3, 40);
00158         m_ListView.SetColumnWidth(4, 100);
00159         m_ListView.SetColumnWidth(5, 70);
00160 
00161         m_ListView.SetImageList(m_ImageList, LVSIL_SMALL);
00162 
00163         SendDlgItemMessage(IDC_STARTDBG,  BM_SETCHECK, m_Params.AutoInvokeDebugger ? BST_CHECKED : 0, 0);
00164         SendDlgItemMessage(IDC_STOPDBG,   BM_SETCHECK, m_Params.AutoCloseDebugger? BST_CHECKED : 0, 0);
00165         SendDlgItemMessage(IDC_BREAKIN,   BM_SETCHECK, m_Params.InitialBreakIn ? BST_CHECKED : 0, 0);
00166         switch(m_Params.DebuggerType)
00167         {
00168         case 0:
00169                 SendDlgItemMessage(IDC_USEKD, BM_SETCHECK, BST_CHECKED);
00170                 break;
00171         case 1:
00172                 SendDlgItemMessage(IDC_USEWINDBG, BM_SETCHECK, BST_CHECKED);
00173                 break;
00174         case 2:
00175                 SendDlgItemMessage(IDC_USECUSTOM, BM_SETCHECK, BST_CHECKED);
00176                 break;
00177         }
00178 
00179         OnDebuggerPathChanged();
00180 
00181         SetTimer(0, 200);
00182 
00183         CFont font((HFONT)GetStockObject(SYSTEM_FONT));
00184         LOGFONT logFont;
00185         font.GetLogFont(logFont);
00186         _tcsncpy(logFont.lfFaceName, _T("Courier New"), __countof(logFont.lfFaceName));
00187         HFONT hFont = CreateFontIndirect(&logFont);
00188         GetDlgItem(IDC_EDIT1).SetFont(hFont, TRUE);
00189 
00190         SetDlgItemText(IDC_DBGTEMPLATE, m_Params.CustomDebuggerTemplate.c_str());
00191         UpdateParamControls();
00192 
00193         m_StatsView.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
00194         m_StatsView.AddColumn(_T("Parameter"), 0);
00195         m_StatsView.AddColumn(_T("Value"), 1);
00196 
00197         int i = 0;
00198         m_StatsView.InsertItem(i++, _T("Bytes received"));
00199         m_StatsView.InsertItem(i++, _T("Bytes send"));
00200         m_StatsView.InsertItem(i++, _T("Packets received"));
00201         m_StatsView.InsertItem(i++, _T("Packets sent"));
00202         m_StatsView.InsertItem(i++, _T("IN packet rate"));
00203         m_StatsView.InsertItem(i++, _T("OUT packet rate"));
00204         m_StatsView.InsertItem(i++, _T("Reset count"));
00205         m_StatsView.InsertItem(i++, _T("Send rate"));
00206         m_StatsView.InsertItem(i++, _T("Receive rate"));
00207         m_StatsView.InsertItem(i++, _T("Max. send rate"));
00208         m_StatsView.InsertItem(i++, _T("Max. recv. rate"));
00209         m_StatsView.InsertItem(i++, _T("CPU usage"));
00210         m_StatsView.InsertItem(i++, _T("Avg. CPU usage"));
00211 
00212         m_StatsView.SetColumnWidth(0, 100);
00213         m_StatsView.SetColumnWidth(1, 65);
00214 
00215 #ifdef KDVMWARE_USE_PROXY
00216         SetWindowText(_T("Virtual Machine monitor (proxy mode)"));
00217 #endif
00218 
00219         if (BazisLib::WOW64APIProvider::sIsWow64Process())
00220         {
00221                 SetWindowText(_T("Virtual Machine monitor (32-bit version on 64-bit windows). Use VMMON64.EXE instead."));
00222         }
00223 
00224         return bHandled = FALSE;
00225 }
00226 
00227 void CMainDlg::UpdateParamControls()
00228 {
00229         GetDlgItem(IDC_DBGTEMPLATE).EnableWindow((m_Params.DebuggerType == 2));
00230 }
00231 
00232 LRESULT CMainDlg::OnParamsChanged(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
00233 {
00234         m_Params.AutoInvokeDebugger = ((SendDlgItemMessage(IDC_STARTDBG,  BM_GETCHECK) & BST_CHECKED) != 0);
00235         m_Params.AutoCloseDebugger = ((SendDlgItemMessage(IDC_STOPDBG,  BM_GETCHECK) & BST_CHECKED) != 0);
00236         m_Params.InitialBreakIn = ((SendDlgItemMessage(IDC_BREAKIN,  BM_GETCHECK) & BST_CHECKED) != 0);
00237         if ((SendDlgItemMessage(IDC_USEKD,  BM_GETCHECK) & BST_CHECKED) != 0)
00238                 m_Params.DebuggerType = 0;
00239         else if ((SendDlgItemMessage(IDC_USEWINDBG,  BM_GETCHECK) & BST_CHECKED) != 0)
00240                 m_Params.DebuggerType = 1;
00241         else if ((SendDlgItemMessage(IDC_USECUSTOM,  BM_GETCHECK) & BST_CHECKED) != 0)
00242                 m_Params.DebuggerType = 2; 
00243         TCHAR tsz[MAX_PATH * 2];
00244         GetDlgItemText(IDC_DBGTEMPLATE, tsz, __countof(tsz));
00245         m_Params.CustomDebuggerTemplate = tsz;
00246         UpdateParamControls();
00247         SaveParamsToRegistry();
00248         return 0;
00249 }
00250 
00251 void CMainDlg::SaveParamsToRegistry()
00252 {
00253         RegistryKey key(HKEY_LOCAL_MACHINE, tszRegistryPath);
00254         key.SerializeObject(m_Params);
00255 }
00256 
00257 LRESULT CMainDlg::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
00258 {
00259         return 0;
00260 }
00261 
00262 LRESULT CMainDlg::OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
00263 {
00264         // TODO: Add validation code 
00265         EndDialog(wID);
00266         return 0;
00267 }
00268 
00269 LRESULT CMainDlg::OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
00270 {
00271         EndDialog(wID);
00272         return 0;
00273 }
00274 
00275 LRESULT CMainDlg::OnTimer(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
00276 {
00277         SearchForNewProcesses();
00278         UpdateProcessInfo();
00279         return 0;
00280 }
00281 
00282 static inline bool UpdateProcessStats(PatchedProcess &proc, unsigned PID, unsigned ProcessorCount)
00283 {
00284         HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, PID);
00285         if (hProc == INVALID_HANDLE_VALUE)
00286         {
00287                 proc.StillRunning = false;
00288                 return false;
00289         }
00290         DateTime now = DateTime::Now();
00291         FILETIME StartTime = {0,}, EndTime = {0,};
00292         FILETIME KernelTime = {0,}, UserTime = {0,};
00293         GetProcessTimes(hProc, &StartTime, &EndTime, &KernelTime, &UserTime);
00294         if (WaitForSingleObject(hProc, 0) == WAIT_OBJECT_0)
00295         {
00296                 proc.StillRunning = false;
00297                 proc.StopTime = EndTime;
00298         }
00299         else
00300         {
00301                 proc.StillRunning = true;
00302                 proc.StopTime = now;
00303         }
00304         ULONGLONG sum = (*((ULONGLONG*)&KernelTime) + *((ULONGLONG*)&UserTime));
00305         FILETIME CPUTime = *((FILETIME *)&sum);
00306         CloseHandle(hProc);
00307         proc.PID = PID;
00308         proc.StartTime = StartTime;
00309 
00310         ULONGLONG timeReal = (now - proc.PreviousSampleTime).GetTotalMilliseconds();
00311         ULONGLONG timeSinceStart = (now - proc.StartTime).GetTotalMilliseconds();
00312         if (!timeReal)
00313                 timeReal++;
00314         if (proc.CpuUsage != -1)
00315         {
00316                 ULONGLONG timeCPU = (DateTime(CPUTime) - proc.PreviousCPUTime).GetTotalMilliseconds();
00317                 proc.CpuUsage = ((int)((timeCPU * 1000) / timeReal)) / ProcessorCount;
00318         }
00319         else
00320                 proc.CpuUsage = 0;
00321 
00322         proc.AvgCpuUsage = (unsigned)((TimeSpan(sum).GetTotalMilliseconds() * 1000) / (timeSinceStart * ProcessorCount));
00323         if (proc.pStatus)
00324         {
00325                 if (proc.PrevRecvd > proc.pStatus->BytesReceived)
00326                         proc.PrevRecvd = proc.pStatus->BytesReceived;
00327                 if (proc.PrevSent > proc.pStatus->BytesSent)
00328                         proc.PrevSent = proc.pStatus->BytesSent;
00329                 if (proc.PrevPacketsRecvd > proc.pStatus->PacketsReceived)
00330                         proc.PrevPacketsRecvd = proc.pStatus->PacketsReceived;
00331                 if (proc.PrevPacketsSent > proc.pStatus->PacketsSent)
00332                         proc.PrevPacketsSent = proc.pStatus->PacketsSent;
00333 
00334                 if (timeReal > 10)
00335                 {
00336                         if (proc.PrevRecvd)
00337                                 proc.RecvRate = (unsigned)(((ULONGLONG)(proc.pStatus->BytesReceived - proc.PrevRecvd) * 1000) / timeReal);
00338                         if (proc.PrevSent)
00339                                 proc.SendRate = (unsigned)(((ULONGLONG)(proc.pStatus->BytesSent- proc.PrevSent) * 1000) / timeReal);
00340 
00341                         if (proc.PrevPacketsRecvd)
00342                                 proc.PacketRecvRate = (unsigned)(((ULONGLONG)(proc.pStatus->PacketsReceived - proc.PrevPacketsRecvd) * 1000) / timeReal);
00343                         if (proc.PrevPacketsSent)
00344                                 proc.PacketSendRate = (unsigned)(((ULONGLONG)(proc.pStatus->PacketsSent - proc.PrevPacketsSent) * 1000) / timeReal);
00345                 }
00346 
00347                 proc.PrevRecvd = proc.pStatus->BytesReceived;
00348                 proc.PrevSent = proc.pStatus->BytesSent;
00349 
00350                 proc.PrevPacketsRecvd = proc.pStatus->PacketsReceived;
00351                 proc.PrevPacketsSent = proc.pStatus->PacketsSent;
00352 
00353                 if (proc.RecvRate > proc.MaxRecvRate)
00354                         proc.MaxRecvRate = proc.RecvRate;
00355                 if (proc.SendRate > proc.MaxSendRate)
00356                         proc.MaxSendRate = proc.SendRate;
00357         }
00358 
00359         proc.PreviousSampleTime = now;
00360         proc.PreviousCPUTime = CPUTime;
00361         return true;
00362 }
00363 
00364 void CMainDlg::SearchForNewProcesses()
00365 {
00366         HANDLE hList = CreateVMSessionList();
00367         unsigned PID = 0;
00368         VMType vmType = kVMUnknown;
00369         
00370         while (PID = GetNextVMSessionPIDEx(hList, &vmType))
00371         {
00372                 if (m_PatchedSet.find(PID) == m_PatchedSet.end())
00373                 {
00374                         PatchedProcess proc;
00375                         proc.State = PatchPending;
00376                         proc.vmType = vmType;
00377                         if (UpdateProcessStats(proc, PID, m_ProcessorCount))
00378                         {
00379                                 m_PatchedSet.insert(PID);
00380                                 TCHAR tsz[32];
00381                                 _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%d"), proc.PID);
00382                                 if (IsVMSessionPatched(PID))
00383                                 {
00384                                         proc.State = PatchSuccessful;
00385                                         CreateStatusMapping(proc, false);
00386                                 }
00387                                 wchar_t szName[MAX_PATH] = {0,};
00388                                 GetVMSessionNameW(PID, szName, _countof(szName));
00389                                 if (szName[0])
00390                                         proc.SessionNameRetreived = true;
00391                                 m_Processes.push_back(proc);
00392                                 size_t idx = m_Processes.size() - 1;
00393 
00394                                 m_ListView.InsertItem((UINT)idx, tsz, ProcessPending); 
00395                                 m_ListView.SetItem((UINT)idx, 1, LVIF_TEXT, GetVMTypeName(proc.vmType), 0, 0, 0, 0);
00396                         }
00397                 }
00398         };
00399         CloseVMSessionList(hList);
00400 }
00401 
00402 static BOOL CALLBACK CloseEnumWndProc(HWND hWnd, LPARAM lParam)
00403 {
00404         DWORD dwProcessID = 0;
00405         GetWindowThreadProcessId(hWnd, &dwProcessID);
00406         if (dwProcessID == lParam)
00407         {
00408                 TCHAR tsz[512] = {0,};
00409                 RealGetWindowClass(hWnd, tsz, __countof(tsz));
00410                 if (!_tcscmp(tsz, _T("WinDbgFrameClass")) || !_tcscmp(tsz, _T("ConsoleWindowClass")))
00411                 {
00412                         ::SendMessage(hWnd, WM_CLOSE, 0, 0);
00413                         return FALSE;
00414                 }
00415         }
00416         return TRUE;
00417 }
00418 
00419 static bool CloseDebugger(unsigned PID)
00420 {
00421         if (!EnumWindows(CloseEnumWndProc, PID))
00422                 return true;
00423         return false;
00424 }       
00425 
00426 void CMainDlg::CleanupProcessEntry(PatchedProcess &proc)
00427 {
00428         if (proc.hLogPipe != INVALID_HANDLE_VALUE)
00429         {
00430                 CloseHandle(proc.hLogPipe);
00431                 proc.hLogPipe = INVALID_HANDLE_VALUE;
00432         }
00433         if (proc.hMapping != INVALID_HANDLE_VALUE)
00434         {
00435                 if (proc.pStatus)
00436                 {
00437                         UnmapViewOfFile(proc.pStatus);
00438                         proc.pStatus = NULL;
00439                 }
00440                 CloseHandle(proc.hMapping);
00441                 proc.hMapping = INVALID_HANDLE_VALUE;
00442         }
00443 }
00444 
00445 void CMainDlg::CreateStatusMapping(PatchedProcess &proc, bool Reset)
00446 {
00447         TCHAR tszMappingName[MAX_PATH];
00448         _sntprintf_s(tszMappingName, __countof(tszMappingName), _TRUNCATE, tszMappingNameFormat, proc.PID);
00449         PermissiveSecurityDescriptor descriptor;
00450         proc.hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, descriptor, PAGE_READWRITE, 0, sizeof(KdClientStatus), tszMappingName);
00451         if (GetLastError() == ERROR_ALREADY_EXISTS)
00452                 Reset = false;
00453         if (proc.hMapping != INVALID_HANDLE_VALUE)
00454         {
00455                 proc.pStatus = (KdClientStatus *)MapViewOfFile(proc.hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
00456                 if (!proc.pStatus)
00457                 {
00458                         CloseHandle(proc.hMapping);
00459                         proc.hMapping = INVALID_HANDLE_VALUE;
00460                 }
00461                 else
00462                 {
00463                         if (Reset)
00464                                 memset(proc.pStatus, 0, sizeof(KdClientStatus));
00465                         proc.pStatus->DebugLevel = m_Params.DebugLevel;
00466                         proc.pStatus->LogAllPackets = ((SendDlgItemMessage(IDC_LOGPACKETS,  BM_GETCHECK) & BST_CHECKED) != 0);
00467                 }
00468         }
00469         if (proc.hMapping == INVALID_HANDLE_VALUE)
00470         {
00471                 MessageBox(MAKE_STATUS(ActionStatus::FromLastError()).GetErrorText().c_str(),
00472                                         _T("Cannot create shared parameter block"),
00473                                         MB_ICONERROR);
00474         }
00475 }
00476 
00477 bool CMainDlg::InitiatePatching(PatchedProcess &proc)
00478 {
00479         CreateStatusMapping(proc, true);
00480         if (proc.hLogPipe == INVALID_HANDLE_VALUE)
00481                 proc.hLogPipe = CreateLogPipe(proc.PID);
00482         proc.hRemoteThread = StartVMSessionPatching(proc.PID);
00483         if (!proc.hRemoteThread)
00484         {
00485                 proc.State = PatchSuccessful;
00486                 return true;
00487         }
00488         else if (proc.hRemoteThread == INVALID_HANDLE_VALUE)
00489         {
00490                 proc.State = PatchFailed;
00491                 return false;
00492         }
00493         else
00494         {
00495                 proc.State = PatchInProgress;
00496                 return true;
00497         }
00498 }
00499 
00500 void CMainDlg::UpdateLog(PatchedProcess &proc)
00501 {
00502         if (proc.hLogPipe != INVALID_HANDLE_VALUE)
00503         {
00504                 DWORD bytesAvailable = 0;
00505                 PeekNamedPipe(proc.hLogPipe, NULL, 0, NULL, &bytesAvailable, NULL);
00506                 if (bytesAvailable)
00507                 {
00508                         CBuffer buf;
00509                         buf.EnsureSize(bytesAvailable);
00510                         DWORD dwOk = 0;
00511                         ReadFile(proc.hLogPipe, buf.GetData(), bytesAvailable, &dwOk, NULL);
00512                         if (dwOk == bytesAvailable)
00513                         {
00514                                 proc.Log.append((TCHAR *)buf.GetData(), bytesAvailable / sizeof(TCHAR));
00515                                 proc.LogChanged = true;
00516                         }
00517                 }
00518         }
00519 }
00520 
00521 void CMainDlg::PerformProcessActions(PatchedProcess &proc, TimeSpan &runTime, bool *pPatchingStarted)
00522 {
00523         if ((proc.State == PatchProcessTerminated) || (proc.State == Unpatched))
00524                 CleanupProcessEntry(proc);
00525         else
00526         {
00527                 if (proc.hLogPipe == INVALID_HANDLE_VALUE)
00528                         proc.hLogPipe = CreateLogPipe(proc.PID);
00529         }
00530 
00531         if (proc.State == PatchPending)
00532         {
00533                 if (runTime.GetTotalSeconds() > m_Params.PatchDelay)
00534                 {
00535                         bool started = InitiatePatching(proc);
00536                         if (pPatchingStarted)
00537                                 *pPatchingStarted = started;
00538                 }
00539         }
00540 
00541         if (proc.State == PatchInProgress)
00542         {
00543                 if (WaitForSingleObject(proc.hRemoteThread, 0) == WAIT_OBJECT_0)
00544                 {
00545                         DWORD dwCode = 0;
00546                         GetExitCodeThread(proc.hRemoteThread, &dwCode);
00547                         if (dwCode)
00548                                 proc.State = PatchInProgress2;
00549                         else
00550                                 proc.State = PatchFailed;
00551                         CloseHandle(proc.hRemoteThread);
00552                         proc.hRemoteThread = INVALID_HANDLE_VALUE;
00553                 }
00554         }
00555 
00556         if ((proc.State == PatchInProgress2) || (proc.State == PatchSuccessful))
00557         {
00558                 if (proc.pStatus)
00559                 {
00560                         switch (proc.pStatus->PatchErrorPlus1 - 1)
00561                         {
00562                         case ERROR_SUCCESS:
00563                                 proc.State = PatchSuccessful;
00564                                 break;
00565                         case -1:
00566                                 proc.State = PatchInProgress2;
00567                                 break;
00568                         default:
00569                                 proc.State = PatchFailed;
00570                         }
00571                 }
00572                 if (proc.pStatus->ProtocolMismatchStatus)
00573                 {
00574                         proc.State = ProtocolMismatch;
00575                         WORD expected = HIWORD(proc.pStatus->ProtocolMismatchStatus), found = LOWORD(proc.pStatus->ProtocolMismatchStatus);
00576                         proc.pStatus->ProtocolMismatchStatus = 0;
00577                         TCHAR tsz[256];
00578                         _sntprintf(tsz, __countof(tsz), _T("Warning! KDVMWARE.DLL version %x.%02x was loaded by virtual machine, while version %x.%02x was expected. Debugging functions disabled!"),
00579                                 HIBYTE(found), LOBYTE(found), HIBYTE(expected), LOBYTE(expected));
00580                         MessageBox(tsz, _T("Invalid KDVMWARE.DLL version"), MB_ICONWARNING);
00581                 }
00582         }
00583 
00584         if (proc.State == UnpatchInProgress)
00585         {
00586                 if (WaitForSingleObject(proc.hRemoteThread, 0) == WAIT_OBJECT_0)
00587                 {
00588                         CloseHandle(proc.hRemoteThread);
00589                         proc.hRemoteThread = INVALID_HANDLE_VALUE;
00590                         proc.State = Unpatched;
00591                         UpdateLog(proc);
00592                         CleanupProcessEntry(proc);
00593                 }
00594         }
00595 
00596         UpdateLog(proc);
00597 }
00598 
00599 void CMainDlg::UpdateProcessInfo()
00600 {
00601         DateTime now = DateTime::Now();
00602         int idx = m_ListView.GetSelectedIndex();
00603         for (unsigned i = 0; i < (unsigned)m_Processes.size(); i++)
00604         {
00605                 PatchedProcess &proc = m_Processes[i];
00606                 if (proc.StillRunning)
00607                         UpdateProcessStats(proc, proc.PID, m_ProcessorCount);
00608 
00609                 if (!proc.StillRunning)
00610                         proc.State = PatchProcessTerminated;
00611                 TimeSpan runTime = now - proc.StartTime;
00612                 if (!proc.StillRunning)
00613                         runTime = proc.StopTime - proc.StartTime;
00614                 m_ListView.AddItem(i, 2, runTime.ToString().c_str());
00615                 TCHAR tsz[128];
00616                 _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%d%%"), proc.CpuUsage / 10);
00617                 m_ListView.AddItem(i, 3, tsz);
00618                 bool patchStarted = false;
00619                 PerformProcessActions(proc, runTime, &patchStarted);
00620 
00621                 if (patchStarted)
00622                         m_ListView.SelectItem(i), idx = i;
00623 
00624                 if (idx == i)
00625                 {
00626                         if (proc.LogChanged)
00627                         {
00628                                 SetDlgItemText(IDC_EDIT1, proc.Log.c_str());
00629                                 SendDlgItemMessage(IDC_EDIT1, WM_VSCROLL, SB_BOTTOM, 0);
00630                                 proc.LogChanged = false;
00631                         }
00632                         if (proc.State == PatchSuccessful)
00633                         {
00634                                 m_StatsView.EnableWindow(TRUE);
00635                                 DisplayStats(proc);
00636                         }
00637                         else
00638                                 m_StatsView.EnableWindow(FALSE);
00639                 }
00640 
00641                 switch (proc.State)
00642                 {
00643                 case PatchInProgress:
00644                 case PatchInProgress2:
00645                         m_ListView.SetItem(i, 0, LVIF_IMAGE, NULL, ProcessPending, 0, 0, 0);
00646                         m_ListView.AddItem(i, 4, _T("loading..."));
00647                         break;
00648                 case UnpatchInProgress:
00649                         m_ListView.SetItem(i, 0, LVIF_IMAGE, NULL, ProcessPending, 0, 0, 0);
00650                         m_ListView.AddItem(i, 4, _T("unloading..."));
00651                         break;
00652                 case PatchPending:
00653                         m_ListView.SetItem(i, 0, LVIF_IMAGE, NULL, ProcessPending, 0, 0, 0);
00654                         m_ListView.AddItem(i, 4, _T(""));
00655                         break;
00656                 case PatchSuccessful:
00657                         m_ListView.SetItem(i, 0, LVIF_IMAGE, NULL, ProcessPatched, 0, 0, 0);
00658                         if (proc.pStatus)
00659                         {
00660                                 const KdClientStatus &status = *proc.pStatus;
00661                                 m_ListView.AddItem(i, 4, status.PipeName + 9);
00662                                 proc.PipeName = status.PipeName;
00663 
00664 #ifdef _DEBUG
00665                                 {
00666                                         wchar_t wszT[MAX_PATH] = {0,};
00667                                         GetVMPipeNameW(proc.PID, wszT, __countof(wszT), true);
00668                                         ASSERT(!wcscmp(wszT, status.PipeName));
00669                                 }
00670 #endif
00671 
00672                                 _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%d/%d"), status.PacketsSent, status.PacketsReceived);
00673                                 m_ListView.AddItem(i, 5, tsz);
00674                                 _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%d"), status.ResyncCount);
00675                                 m_ListView.AddItem(i, 6, tsz);
00676                                 m_ListView.AddItem(i, 7, status.OSDetected ? _T("yes") : _T(""));
00677                                 m_ListView.AddItem(i, 8, status.DebuggerConnected ? _T("yes") : _T(""));
00678                                 if (!proc.idDebuggerProcess)
00679                                 {
00680                                         if ((m_Params.AutoInvokeDebugger && status.PipeName[0]) && (!m_Params.WaitForOS || status.OSDetected))
00681                                         {
00682                                                 RunDebugger(i);
00683                                         }
00684                                 }
00685                         }
00686                         else
00687                         {
00688                                 m_ListView.AddItem(i, 4, _T("loading..."));
00689                                 m_ListView.AddItem(i, 7, _T(""));
00690                                 m_ListView.AddItem(i, 8, _T(""));
00691                         }
00692                         break;
00693                 case PatchFailed:
00694                         m_ListView.SetItem(i, 0, LVIF_IMAGE, NULL, ProcessFailed, 0, 0, 0);
00695                         m_ListView.AddItem(i, 4, _T(""));
00696                         break;
00697                 case ProtocolMismatch:
00698                         m_ListView.SetItem(i, 0, LVIF_IMAGE, NULL, ProcessFailed, 0, 0, 0);
00699                         m_ListView.AddItem(i, 4, _T("Old KDVMWARE.DLL loaded in guest"));
00700                         break;
00701                 case PatchProcessTerminated:
00702                 case Unpatched:
00703                         m_ListView.SetItem(i, 0, LVIF_IMAGE, NULL, ProcessInactive, 0, 0, 0);
00704                         m_ListView.AddItem(i, 4, (proc.State == Unpatched) ? _T("(KDCLIENT.DLL unloaded)") : _T("(terminated)"));
00705                         if (proc.idDebuggerProcess)
00706                         {
00707                                 if (m_Params.AutoCloseDebugger)
00708                                 {
00709                                         if (CloseDebugger(proc.idDebuggerProcess))
00710                                                 proc.idDebuggerProcess = 0;
00711                                 }
00712                         }
00713                         break;
00714                 }
00715                 if (proc.State != proc.PreviousState)
00716                 {
00717                         if (idx == i)
00718                                 UpdateUnpatchButton(i);
00719                         proc.PreviousState = proc.State;
00720                 }
00721                 if ((proc.State != PatchProcessTerminated) && !proc.SessionNameRetreived)
00722                 {
00723                         wchar_t szName[MAX_PATH] = {0,};
00724                         GetVMSessionNameW(proc.PID, szName, _countof(szName));
00725 //                      m_ListView.SetItem((UINT)i, 1, LVIF_TEXT, szName, 0, 0, 0, 0);
00726                         if (szName[0])
00727                                 proc.SessionNameRetreived = true;
00728                 }
00729         }
00730 }
00731 
00732 static inline void FindAndReplace(String &src, const String& find, const String& replace) 
00733 { 
00734         size_t pos; 
00735         for (;(pos = src.find( find )) != std::string::npos;) 
00736         { 
00737                 src.replace( pos, find.length(), replace ); 
00738         } 
00739 }
00740 
00741 void CMainDlg::RunDebugger(unsigned entryIndex)
00742 {
00743         PatchedProcess &proc = m_Processes[entryIndex];
00744         if (proc.PipeName.empty())
00745                 return;
00746         FilePath debugger(_T(""));
00747         TCHAR tszCmdLine[MAX_PATH * 2] = {0,};
00748         if (m_Params.DebuggerType < 2)
00749         {
00750                 debugger = m_DbgToolsPath + (FilePath)(m_Params.DebuggerType ? _T("windbg.exe") : _T("kd.exe"));
00751                 LPCTSTR lpFormat = _T("\"%s\" %s-k com:pipe,resets=0,reconnect,port=%s");
00752                 _sntprintf_s(tszCmdLine, __countof(tszCmdLine), _TRUNCATE, lpFormat, debugger.c_str(), m_Params.InitialBreakIn ? _T("-b ") : _T(""), proc.PipeName.c_str());
00753         }
00754         else
00755         {
00756                 String cmdLine = m_Params.CustomDebuggerTemplate;
00757                 FindAndReplace(cmdLine, _T("$(toolspath)"), m_DbgToolsPath);
00758                 FindAndReplace(cmdLine, _T("$(pipename)"), proc.PipeName.c_str());
00759                 _tcsncpy(tszCmdLine, cmdLine.c_str(), __countof(tszCmdLine));
00760         }
00761         STARTUPINFO startupInfo = {0,};
00762         startupInfo.cb = sizeof(startupInfo);
00763         PROCESS_INFORMATION processInfo = {0,};
00764         CreateProcess(debugger.empty() ? NULL : debugger.c_str(), tszCmdLine, NULL, NULL, FALSE, CREATE_NEW_PROCESS_GROUP, NULL, m_DbgToolsPath.c_str(), &startupInfo, &processInfo);
00765         CloseHandle(processInfo.hProcess);
00766         CloseHandle(processInfo.hThread);
00767         proc.idDebuggerProcess = processInfo.dwProcessId;
00768 }
00769 
00770 
00771 LRESULT CMainDlg::OnRunDebugger(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
00772 {
00773         int idx = m_ListView.GetSelectedIndex();
00774         if ((idx != -1) && ((size_t)idx < m_Processes.size()))
00775                 RunDebugger(idx);
00776         else
00777                 MessageBox(_T("No Virtual Machine selected"), _T("Error"), MB_ICONERROR);
00778         return 0;
00779 }
00780 
00781 LRESULT CMainDlg::OnSelChanged(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
00782 {
00783         int idx = m_ListView.GetSelectedIndex();
00784         if (idx != -1)
00785         {
00786                 PatchedProcess &proc = m_Processes[idx];
00787                 SetDlgItemText(IDC_EDIT1, proc.Log.c_str());
00788                 proc.LogChanged = false;
00789                 if (proc.pStatus && proc.pStatus->DebugLevel)
00790                         m_DebugLevel.SetCurSel(proc.pStatus->DebugLevel);
00791                 UpdateUnpatchButton(idx);
00792 
00793                 if (proc.pStatus)
00794                 {
00795                         if (proc.pStatus->LogAllPackets)
00796                                 SendDlgItemMessage(IDC_LOGPACKETS, BM_SETCHECK, BST_CHECKED);
00797                         else
00798                                 SendDlgItemMessage(IDC_LOGPACKETS, BM_SETCHECK, BST_UNCHECKED);
00799                 }
00800 
00801                 DisplayStats(proc);
00802         }
00803         else
00804                 m_StatsView.EnableWindow(FALSE);
00805         return 0;
00806 }
00807 
00808 LRESULT CMainDlg::OnDebugLevelChanged(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
00809 {
00810         m_Params.DebugLevel = m_DebugLevel.GetCurSel();
00811         int idx = m_ListView.GetSelectedIndex();
00812         if (idx != -1)
00813         {
00814                 PatchedProcess &proc = m_Processes[idx];
00815                 if ((proc.State == PatchSuccessful) && (proc.pStatus))
00816                         proc.pStatus->DebugLevel = m_Params.DebugLevel;
00817         }
00818         SaveParamsToRegistry();
00819         return 0;
00820 }
00821 
00822 LRESULT CMainDlg::OnBnClickedClearlog(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
00823 {
00824         int idx = m_ListView.GetSelectedIndex();
00825         if (idx != -1)
00826         {
00827                 PatchedProcess &proc = m_Processes[idx];
00828                 proc.Log.clear();
00829                 SetDlgItemText(IDC_EDIT1, proc.Log.c_str());
00830                 proc.LogChanged = false;
00831         }
00832         return 0;
00833 }
00834 
00835 LRESULT CMainDlg::OnBnClickedUnpatch(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
00836 {
00837         int idx = m_ListView.GetSelectedIndex();
00838         if (idx != -1)
00839         {
00840                 PatchedProcess &proc = m_Processes[idx];
00841                 if (proc.State == PatchSuccessful)
00842                 {
00843                         proc.hRemoteThread = (HANDLE)StartVMSessionUnpatching(proc.PID);
00844                         if (proc.hRemoteThread == INVALID_HANDLE_VALUE)
00845                                 MessageBox(_T("Cannot unpatch process"), _T("Error"), MB_ICONERROR);
00846                         else
00847                         {
00848                                 if (proc.hRemoteThread)
00849                                         proc.State = UnpatchInProgress;
00850                                 else
00851                                         proc.State = Unpatched;
00852                         }
00853                 }
00854                 else if (proc.State == Unpatched)
00855                 {
00856                         proc.State = PatchPending;
00857                 }
00858                 UpdateUnpatchButton(idx);
00859         }
00860         return 0;
00861 }
00862 
00863 void CMainDlg::UpdateUnpatchButton(int SelectionIndex)
00864 {
00865         if (SelectionIndex == -1)
00866                 return;
00867         PatchedProcess &proc = m_Processes[SelectionIndex];
00868         switch (proc.State)
00869         {
00870         case PatchSuccessful:
00871                 SetDlgItemText(IDC_UNPATCH, _T("Unpatch process"));
00872                 GetDlgItem(IDC_UNPATCH).EnableWindow();
00873                 break;
00874         case Unpatched:
00875                 SetDlgItemText(IDC_UNPATCH, _T("Repatch process"));
00876                 GetDlgItem(IDC_UNPATCH).EnableWindow();
00877                 break;
00878         default:
00879                 GetDlgItem(IDC_UNPATCH).EnableWindow(FALSE);
00880                 break;
00881         }
00882 
00883 }
00884 
00885 void CMainDlg::OnDebuggerPathChanged()
00886 {
00887         bool b = !m_DbgToolsPath.empty();
00888         GetDlgItem(IDC_STARTDBG).EnableWindow(b);
00889         GetDlgItem(IDC_STOPDBG).EnableWindow(b);
00890         GetDlgItem(IDC_USEKD).EnableWindow(b);
00891         GetDlgItem(IDC_USEWINDBG).EnableWindow(b);
00892         GetDlgItem(IDC_RUNDBG).EnableWindow(b);
00893         GetDlgItem(IDC_USECUSTOM).EnableWindow(b);
00894 }
00895 
00896 LRESULT CMainDlg::OnBnClickedDbgpath(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
00897 {
00898         const TCHAR *pFileName = NULL;
00899         String fileName;
00900         if (!m_DbgToolsPath.empty())
00901         {
00902                 fileName = m_DbgToolsPath + FilePath(_T("windbg.exe"));
00903                 pFileName = fileName.c_str();
00904         }
00905         CFileDialog dlg(TRUE, _T("exe"), pFileName, OFN_HIDEREADONLY, _T("Debugging tools\0windbg.exe;kd.exe\0Executable files (*.exe)\0*.exe\0All files(*.*)\0*.*\0\0"));
00906         if (dlg.DoModal() == IDOK)
00907         {
00908                 FilePath dbgPath = dlg.m_szFileName;
00909                 dbgPath = dbgPath.GetParentPath();
00910                 if (File::Exists(dbgPath + FilePath(_T("windbg.exe"))))
00911                 {
00912                         m_DbgToolsPath = dbgPath;
00913                         m_Params.ToolsPath = m_DbgToolsPath;
00914                         SaveParamsToRegistry();
00915                 }
00916                 OnDebuggerPathChanged();
00917         }
00918         return 0;
00919 }
00920 
00921 void CMainDlg::DisplayStats(PatchedProcess &proc)
00922 {
00923         TCHAR tsz[512];
00924         if (!proc.pStatus)
00925         {
00926                 m_StatsView.EnableWindow(FALSE);
00927                 return;
00928         }
00929         int i = 0;
00930         m_StatsView.SetItem(i++, 1, LVIF_TEXT, Network::RateCalculator::FormatByteCount(proc.pStatus->BytesSent).c_str(), 0, 0, 0, 0);
00931         m_StatsView.SetItem(i++, 1, LVIF_TEXT, Network::RateCalculator::FormatByteCount(proc.pStatus->BytesReceived).c_str(), 0, 0, 0, 0);
00932         _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%d"), proc.pStatus->PacketsSent);
00933         m_StatsView.SetItem(i++, 1, LVIF_TEXT, tsz, 0, 0, 0, 0);
00934         _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%d"), proc.pStatus->PacketsReceived);
00935         m_StatsView.SetItem(i++, 1, LVIF_TEXT, tsz, 0, 0, 0, 0);
00936         _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%s/s"), Network::RateCalculator::FormatByteCount(proc.PacketSendRate).c_str());
00937         m_StatsView.SetItem(i++, 1, LVIF_TEXT, tsz, 0, 0, 0, 0);
00938         _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%s/s"), Network::RateCalculator::FormatByteCount(proc.PacketRecvRate).c_str());
00939         m_StatsView.SetItem(i++, 1, LVIF_TEXT, tsz, 0, 0, 0, 0);
00940 
00941         _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%d"), proc.pStatus->ResyncCount);
00942         m_StatsView.SetItem(i++, 1, LVIF_TEXT, tsz, 0, 0, 0, 0);
00943 
00944         _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%s/s"), Network::RateCalculator::FormatByteCount(proc.RecvRate).c_str());
00945         m_StatsView.SetItem(i++, 1, LVIF_TEXT, tsz, 0, 0, 0, 0);
00946         _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%s/s"), Network::RateCalculator::FormatByteCount(proc.SendRate).c_str());
00947         m_StatsView.SetItem(i++, 1, LVIF_TEXT, tsz, 0, 0, 0, 0);
00948         _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%s/s"), Network::RateCalculator::FormatByteCount(proc.MaxRecvRate).c_str());
00949         m_StatsView.SetItem(i++, 1, LVIF_TEXT, tsz, 0, 0, 0, 0);
00950         _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%s/s"), Network::RateCalculator::FormatByteCount(proc.MaxSendRate).c_str());
00951         m_StatsView.SetItem(i++, 1, LVIF_TEXT, tsz, 0, 0, 0, 0);
00952 
00953         _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%d%%"), proc.CpuUsage / 10);
00954         m_StatsView.SetItem(i++, 1, LVIF_TEXT, tsz, 0, 0, 0, 0);
00955 
00956         _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%d%%"), proc.AvgCpuUsage / 10);
00957         m_StatsView.SetItem(i++, 1, LVIF_TEXT, tsz, 0, 0, 0, 0);
00958 
00959 }
00960 
00961 LRESULT CMainDlg::OnBnClickedTraceassist(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
00962 {
00963         CTraceParamsDlg dlg;
00964         if (dlg.DoModal() == IDOK)
00965         {
00966                 for (size_t i = 0; i < m_Processes.size(); i++)
00967                 {
00968                         PatchedProcess &proc = m_Processes[i];
00969                         if (proc.pStatus)
00970                                 proc.pStatus->TraceAssistUpdatePending = true;
00971                 }
00972         }
00973         return 0;
00974 }
00975 
00976 LRESULT CMainDlg::OnLogPacketsChanged( WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/ )
00977 {
00978         bool bLogPackets = ((SendDlgItemMessage(IDC_LOGPACKETS,  BM_GETCHECK) & BST_CHECKED) != 0);
00979         int idx = m_ListView.GetSelectedIndex();
00980         if (idx != -1)
00981         {
00982                 PatchedProcess &proc = m_Processes[idx];
00983                 if ((proc.State == PatchSuccessful) && (proc.pStatus))
00984                         proc.pStatus->LogAllPackets = bLogPackets;
00985         }
00986         return 0;
00987 }