#include "ProfileManager.h" #include "profile/Profile.h" #include "host.h" #include "hookman.h" #include "vnrhook/include/types.h" #include "vnrhook/include/const.h" #include "utility.h" #include "profile/misc.h" extern HookManager* man; // main.cpp ProfileManager* pfman; ProfileManager::ProfileManager() { LoadProfiles(); } ProfileManager::~ProfileManager() { SaveProfiles(); } Profile* ProfileManager::GetProfile(DWORD pid) { std::wstring path = GetProcessPath(pid); if (!path.empty()) { auto node = profile_tree.find(path); if (node != profile_tree.end()) return node->second.get(); } return NULL; } bool ProfileManager::CreateProfile(pugi::xml_node game) { auto file = game.child(L"File"); auto profile = game.child(L"Profile"); if (!file || !profile) return false; auto path = file.attribute(L"Path"); if (!path) return false; auto profile_title = game.attribute(L"Title"); auto title = profile_title ? profile_title.value() : L""; auto pf = new Profile(title); if (!pf->XmlReadProfile(profile)) return false; CSLock lock(cs); auto& oldProfile = profile_tree[path.value()]; if (!oldProfile) oldProfile.swap(profile_ptr(pf)); return true; } Profile* ProfileManager::CreateProfile(DWORD pid) { CSLock lock(cs); auto path = GetProcessPath(pid); auto& pf = profile_tree[path]; if (!pf) { std::wstring title = GetProcessTitle(pid); pf.reset(new Profile(title)); } return pf.get(); } void ProfileManager::WriteProfileXml(const std::wstring& path, Profile& pf, pugi::xml_node root) { auto game = root.append_child(L"Game"); auto file_node = game.append_child(L"File"); file_node.append_attribute(L"Path") = path.c_str(); auto profile_node = game.append_child(L"Profile"); pf.XmlWriteProfile(profile_node); if (!pf.Title().empty()) { if (!game.attribute(L"Title")) game.append_attribute(L"Title"); game.attribute(L"Title") = pf.Title().c_str(); } } void ProfileManager::LoadProfiles() { pugi::xml_document doc; UniqueHandle hFile(IthCreateFile(L"NextHooker_Profile.xml", GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING)); if (hFile.get() == INVALID_HANDLE_VALUE) return; DWORD size = GetFileSize(hFile.get(), NULL); std::unique_ptr buffer(new char[size]); ReadFile(hFile.get(), buffer.get(), size, &size, NULL); auto result = doc.load_buffer(buffer.get(), size); if (!result) return; auto root = doc.root().child(L"NextHookerProfile"); if (!root) return; for (auto game = root.begin(); game != root.end(); ++game) CreateProfile(*game); } void ProfileManager::SaveProfiles() { pugi::xml_document doc; auto root = doc.append_child(L"NextHookerProfile"); for (auto it = profile_tree.begin(); it != profile_tree.end(); ++it) { auto& path = it->first; auto& profile = it->second; WriteProfileXml(path, *profile, root); } UniqueHandle hFile(IthCreateFile(L"NextHooker_Profile.xml", GENERIC_WRITE, 0, CREATE_ALWAYS)); if (hFile.get() != INVALID_HANDLE_VALUE) { FileWriter fw(hFile.get()); doc.save(fw); } } void ProfileManager::DeleteProfile(const std::wstring& path) { CSLock lock(cs); profile_tree.erase(profile_tree.find(path)); } Profile* ProfileManager::GetProfile(const std::wstring& path) { if (path.empty()) return nullptr; auto it = profile_tree.find(path); if (it == profile_tree.end()) return nullptr; return it->second.get(); } bool ProfileManager::HasProfile(const std::wstring& path) { return profile_tree.find(path) != profile_tree.end(); } DWORD ProfileManager::CountProfiles() { return profile_tree.size(); } DWORD SaveProcessProfile(TextThread* thread) { ThreadParameter tp = thread->GetThreadParameter(); std::wstring path = GetProcessPath(tp.pid); if (path.empty()) return 0; pugi::xml_document doc; pugi::xml_node profile_node = doc.append_child(L"Profile"); Profile* pf = pfman->GetProfile(tp.pid); if (pf != NULL) pf->Clear(); else pf = pfman->CreateProfile(tp.pid); pf->AddHook(hook_ptr(new HookProfile(man->GetHookParam(tp.pid, tp.hook), man->GetHookName(tp.pid, tp.hook)))); pf->AddThread(thread_ptr(new ThreadProfile(man->GetHookName(tp.pid, tp.hook), tp.retn, tp.spl, tp.hook, 0, THREAD_MASK_RETN | THREAD_MASK_SPLIT, L""))); pf->XmlReadProfile(profile_node); return 0; }