| 188 | |
| 189 | |
| 190 | void CProcessModuleTable::Refresh() { |
| 191 | if (!m_Tracker.IsRunning()) { |
| 192 | AtlMessageBox(*this, L"Process has terminated", IDS_TITLE, MB_OK | MB_ICONWARNING); |
| 193 | EndDialog(_hDlg, 0); |
| 194 | return; |
| 195 | } |
| 196 | auto first = m_Table.data.info.empty(); |
| 197 | m_Tracker.EnumModules(); |
| 198 | if (first) { |
| 199 | m_Table.data.info = m_Tracker.GetModules(); |
| 200 | } |
| 201 | else { |
| 202 | auto count = static_cast<int>(m_Table.data.info.size()); |
| 203 | for (int i = 0; i < count; i++) { |
| 204 | auto& mi = m_Table.data.info[i]; |
| 205 | auto& mx = GetModuleEx(mi.get()); |
| 206 | if (mx.IsUnloaded && ::GetTickCount64() > mx.TargetTime) { |
| 207 | ATLTRACE(L"Module unload end: %u %s (0x%p)\n", ::GetTickCount(), mi->Name.c_str(), mi->Base); |
| 208 | m_ModulesEx.erase(mi.get()); |
| 209 | m_Table.data.info.erase(m_Table.data.info.begin() + i); |
| 210 | i--; |
| 211 | count--; |
| 212 | } |
| 213 | else if (mx.IsNew && !mx.IsUnloaded && ::GetTickCount64() > mx.TargetTime) { |
| 214 | mx.IsNew = false; |
| 215 | } |
| 216 | } |
| 217 | |
| 218 | for (auto& mi : m_Tracker.GetNewModules()) { |
| 219 | m_Table.data.info.push_back(mi); |
| 220 | auto& mx = GetModuleEx(mi.get()); |
| 221 | mx.IsNew = true; |
| 222 | mx.TargetTime = ::GetTickCount64() + 2000; |
| 223 | } |
| 224 | for (auto& mi : m_Tracker.GetUnloadedModules()) { |
| 225 | ATLTRACE(L"Module unload start: %u %s (0x%p)\n", ::GetTickCount(), mi->Name.c_str(), mi->Base); |
| 226 | auto& mx = GetModuleEx(mi.get()); |
| 227 | ATLASSERT(!mx.IsUnloaded); |
| 228 | mx.IsNew = false; |
| 229 | mx.IsUnloaded = true; |
| 230 | mx.TargetTime = ::GetTickCount64() + 2000; |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | auto count = static_cast<int>(m_Table.data.info.size()); |
| 235 | m_Table.data.n = count; |
| 236 | |
| 237 | return; |
| 238 | } |
| 239 | |
| 240 | std::wstring CProcessModuleTable::GetFileDescription(std::wstring path) { |
| 241 | BYTE buffer[1 << 12]; |