diff --git a/gui/command.cpp b/gui/command.cpp index b652bb7..4c275ab 100644 --- a/gui/command.cpp +++ b/gui/command.cpp @@ -43,17 +43,6 @@ DWORD ProcessCommand(const std::wstring& cmd, DWORD pid) if (Parse(m[1].str(), hp)) Host_InsertHook(pid, &hp); } - else if (regex_match(cmd, m, wregex(L":l([[:xdigit:]]+)-([[:xdigit:]]+)", wregex::icase))) - { - DWORD from = std::stoul(m[1].str(), NULL, 16); - DWORD to = std::stoul(m[2].str(), NULL, 16); - Host_AddLink(from, to); - } - else if (regex_match(cmd, m, wregex(L":u([[:xdigit:]]+)", wregex::icase))) - { - DWORD from = std::stoul(m[1].str(), NULL, 16); - Host_UnLink(from); - } else if (regex_match(cmd, m, wregex(L":(?:h|help)", wregex::icase))) { ConsoleOutput(Usage); diff --git a/gui/language.cpp b/gui/language.cpp index 6149eb9..66ad8fb 100644 --- a/gui/language.cpp +++ b/gui/language.cpp @@ -20,11 +20,6 @@ const wchar_t* ErrorSyntax=L"Syntax error"; const wchar_t* Usage = L"Syntax:\r\n\ \r\n\ :H[ELP] - print help\r\n\ -:Lfrom-to - link from thread 'from' to thread 'to'\r\n\ -:Ufrom - unlink link from thread 'from'\r\n\ -\r\n\ -'from' and 'to' and hexadecimal thread numbers. The thread number is the first number in the combo box.\r\n\ -\r\n\ Loader options:\r\n\ /P[{process_id|Nprocess_name}] - attach to process\r\n\ \r\n\ diff --git a/gui/window.cpp b/gui/window.cpp index ab349b1..5b9c09f 100644 --- a/gui/window.cpp +++ b/gui/window.cpp @@ -325,14 +325,7 @@ void ClickButton(HWND hWnd, HWND h) } else if (h == hwndClear) { - WCHAR pwcEntry[128] = {}; - DWORD dwId = ComboBox_GetCurSel(hwndCombo); - int len = ComboBox_GetLBText(hwndCombo, dwId, pwcEntry); - dwId = std::stoul(pwcEntry, NULL, 16); - if (dwId == 0) - man->ClearCurrent(); - else - man->RemoveSingleThread(dwId); + man->ClearCurrent(); } else if (h == hwndTop) { @@ -365,16 +358,6 @@ void ClickButton(HWND hWnd, HWND h) } pfman->SaveProfiles(); } - else if (h == hwndRemoveLink) - { - WCHAR str[32]; - if (GetWindowText(hwndCombo, str, 32)) - { - DWORD from = std::stoul(str, NULL, 16); - if (from != 0) - Host_UnLink(from); - } - } else if (h == hwndRemoveHook) { WCHAR str[32]; @@ -508,8 +491,6 @@ std::wstring GetEntryString(TextThread& thread) std::wstring CreateEntryWithLink(TextThread& thread, std::wstring& entry) { std::wstring entryWithLink = entry; - if (thread.Link()) - entryWithLink += L"->" + ToHexString(thread.LinkNumber()); if (thread.PID() == 0) entryWithLink += L"ConsoleOutput"; HookParam hp = {}; @@ -609,7 +590,6 @@ DWORD AddRemoveLink(TextThread* thread) } bool IsUnicodeHook(const ProcessRecord& pr, DWORD hook); -void AddLinksToHookManager(const Profile* pf, size_t thread_index, const TextThread* thread); DWORD ThreadCreate(TextThread* thread) { @@ -631,7 +611,6 @@ DWORD ThreadCreate(TextThread* thread) { (*thread_profile)->HookManagerIndex() = thread->Number(); auto thread_index = thread_profile - pf->Threads().begin(); - AddLinksToHookManager(pf, thread_index, thread); if (pf->IsThreadSelected(thread_profile)) ThreadReset(thread); } @@ -655,25 +634,6 @@ bool IsUnicodeHook(const ProcessRecord& pr, DWORD hook) return res; } -void AddLinksToHookManager(const Profile* pf, size_t thread_index, const TextThread* thread) -{ - for (auto lp = pf->Links().begin(); lp != pf->Links().end(); ++lp) - { - if ((*lp)->FromIndex() == thread_index) - { - WORD to_index = pf->Threads()[(*lp)->ToIndex()]->HookManagerIndex(); - if (to_index != 0) - man->AddLink(thread->Number(), to_index); - } - if ((*lp)->ToIndex() == thread_index) - { - WORD from_index = pf->Threads()[(*lp)->FromIndex()]->HookManagerIndex(); - if (from_index != 0) - man->AddLink(from_index, thread->Number()); - } - } -} - DWORD ThreadRemove(TextThread* thread) { RemoveFromCombo(thread); @@ -709,11 +669,6 @@ DWORD RemoveProcessList(DWORD pid) return 0; } -DWORD RefreshProfileOnNewHook(DWORD pid) -{ - return 0; -} - LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) @@ -750,7 +705,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) AddToCombo(*console, false); man->RegisterProcessAttachCallback(RegisterProcessList); man->RegisterProcessDetachCallback(RemoveProcessList); - man->RegisterProcessNewHookCallback(RefreshProfileOnNewHook); + //man->RegisterProcessNewHookCallback(RefreshProfileOnNewHook); Artikash 5/30/2018 TODO: Finish implementing this. man->RegisterAddRemoveLinkCallback(AddRemoveLink); man->RegisterConsoleCallback(ConsoleOutput); StartHost(); diff --git a/vnr/texthook/host/CMakeLists.txt b/vnr/texthook/host/CMakeLists.txt index 4fa56a7..1f6e558 100644 --- a/vnr/texthook/host/CMakeLists.txt +++ b/vnr/texthook/host/CMakeLists.txt @@ -7,7 +7,6 @@ # DEFINES += _CRT_NON_CONFORMING_SWPRINTFS set(vnrhost_src - avl_p.h config.h hookman.h host.h diff --git a/vnr/texthook/host/avl_p.h b/vnr/texthook/host/avl_p.h deleted file mode 100644 index 5f06449..0000000 --- a/vnr/texthook/host/avl_p.h +++ /dev/null @@ -1,588 +0,0 @@ -#pragma once -// avl_p.h -// 8/23/2013 jichi -// Branch: ITH/AVL.h, rev 133 - -#include "config.h" -#include - -enum { STACK_SIZE = 32 }; - -//#ifndef ITH_STACK -//#define ITH_STACK - -template -class MyStack -{ - int index; - T s[stack_size]; - -public: - MyStack(): index(0) - { ::memset(s, 0, sizeof(s)); } // jichi 9/21/2013: assume T is atomic type - - T &back() { return s[index-1]; } - int size() { return index; } - - void push_back(const T &e) - { - if (index < stack_size) - s[index++]=e; - } - - void pop_back() { index--; } - - T &operator[](int i) { return s[i]; } -}; -//#endif // ITH_STACK - -// jichi 9/22/2013: T must be a pointer type which can be deleted -template -struct IHFSERVICE TreeNode -{ - //typedef TreeNode Self; - TreeNode() : - Left(nullptr), Right(nullptr), Parent(nullptr) - , rank(1) - , factor('\0'), reserve('\0') - //, key() - //, data() - { - ::memset(&key, 0, sizeof(key)); // jcihi 9/26/2013: zero memory - ::memset(&data, 0, sizeof(data)); // jcihi 9/26/2013: zero memory - } - - TreeNode(const T &k, const D &d) : - Left(nullptr), Right(nullptr), Parent(nullptr) - , rank(1) - , factor('\0'), reserve('\0') // jichi 9/21/2013: zero reserve - , key(k) - , data(d) - {} - - TreeNode *Successor() - { - TreeNode *Node, - *ParentNode; - Node = Right; - if (!Node) { - Node = this; - for (;;) { - ParentNode = Node->Parent; - if (!ParentNode) - return nullptr; - if (ParentNode->Left == Node) - break; - Node = ParentNode; - } - return ParentNode; - } - else - while (Node->Left) - Node = Node->Left; - return Node; - } - TreeNode *Predecessor() - { - TreeNode *Node, - *ParentNode; - Node = Left; - if (!Node) { - Node = this; - for(;;) { - ParentNode = Node->Parent; - if (!ParentNode) - return nullptr; - if (ParentNode->Right == Node) - break; - Node = ParentNode; - } - return ParentNode; - } - else - while (Node->Right) - Node = Node->Right; - return Node; - } - int height() - { - if (!this) // jichi 9/26/2013: what?! - return 0; - int l = Left->height(), - r = Right->height(), - f = factor; - if (l - r + f != 0) - __debugbreak(); - f = l > r ? l : r; - return f + 1; - } - TreeNode *Left, - *Right, - *Parent; - unsigned short rank; - char factor, - reserve; - T key; - D data; -}; - -template -struct NodePath -{ - NodePath() { ::memset(this, 0, sizeof(NodePath)); } // jichi 11/30/2013: This is the original code in ITH - NodePath(TreeNode *n, int f): Node(n), fact(f) {} - TreeNode *Node; - union { char factor; int fact; }; -}; - -template -class AVLTree -{ -protected: - TreeNode head; - fComp fCmp; - fCopy fCpy; - fLength fLen; - -public: - // - Construction - - AVLTree() {} - - virtual ~AVLTree() { DeleteAll(); } - - // - Properties - - - TreeNode *TreeRoot() const { return head.Left; } - - // - Actions - - - void DeleteAll() - { - while (head.Left) - DeleteRoot(); - } - - TreeNode *Insert(const T *key, const D &data) - { - if (head.Left) { - MyStack *,STACK_SIZE> path; - TreeNode *DownNode, *ParentNode, *BalanceNode, *TryNode, *NewNode; //P,T,S,Q - ParentNode = &head; - path.push_back(ParentNode); - char factor,f; - BalanceNode = DownNode = head.Left; - for (;;) { //The first part of AVL tree insert. Just do as binary tree insert routine and record some nodes. - factor = fCmp(key,DownNode->key); - if (factor == 0) - return DownNode; //Duplicate key. Return and do nothing. - TryNode = _FactorLink(DownNode, factor); - if (factor == -1) - path.push_back(DownNode); - if (TryNode) { //DownNode has a child. - if (TryNode->factor != 0) { //Keep track of unbalance node and its parent. - ParentNode = DownNode; - BalanceNode = TryNode; - } - DownNode = TryNode; - } - else - break; //Finished binary tree search; - } - while (path.size()) { - path.back()->rank++; - path.pop_back(); - } - size_t sz = fLen(key) + 1; - T *new_key = new T[sz]; - ::memset(new_key, 0, sz * sizeof(T)); // jichi 9/26/2013: Zero memory - fCpy(new_key, key); - TryNode = new TreeNode(new_key, data); - _FactorLink(DownNode, factor) = TryNode; - TryNode->Parent = DownNode; - NewNode = TryNode; - //Finished binary tree insert. Next to do is to modify balance factors between - //BalanceNode and the new node. - TreeNode *ModifyNode; - factor = fCmp(key, BalanceNode->key); - //factor=keykey ? factor=-1:1; //Determine the balance factor at BalanceNode. - ModifyNode = DownNode = _FactorLink(BalanceNode,factor); - //ModifyNode will be the 1st child. - //DownNode will travel from here to the recent inserted node (TryNode). - while (DownNode != TryNode) { //Check if we reach the bottom. - f = fCmp(key,DownNode->key); - //f=_FactorCompare(key,DownNode->key); - DownNode->factor = f; - DownNode = _FactorLink(DownNode, f);//Modify balance factor and travels down. - } - //Finshed modifying balance factor. - //Next to do is check the tree if it's unbalance and recover balance. - if (BalanceNode->factor == 0) { //Tree has grown higher. - BalanceNode->factor = factor; - _IncreaseHeight(); //Modify balance factor and increase the height. - return NewNode; - } - if (BalanceNode->factor + factor == 0) { //Tree has gotten more balanced. - BalanceNode->factor = 0; //Set balance factor to 0. - return NewNode; - } - //Tree has gotten out of balance. - if (ModifyNode->factor == factor) //A node and its child has same factor. Single rotation. - DownNode = _SingleRotation(BalanceNode, ModifyNode, factor); - else //A node and its child has converse factor. Double rotation. - DownNode = _DoubleRotation(BalanceNode, ModifyNode, factor); - //Finished the balancing work. Set child field to the root of the new child tree. - if (BalanceNode == ParentNode->Left) - ParentNode->Left = DownNode; - else - ParentNode->Right = DownNode; - return NewNode; - } - else { //root null? - size_t sz = fLen(key) + 1; - T *new_key = new T[sz]; - ::memset(new_key, 0, sz * sizeof(T)); // jichi 9/26/2013: Zero memory - fCpy(new_key, key); - head.Left = new TreeNode(new_key, data); - head.rank++; - _IncreaseHeight(); - return head.Left; - } - } - bool Delete(T *key) - { - NodePath PathNode; - MyStack,STACK_SIZE> path; //Use to record a path to the destination node. - path.push_back(NodePath(&head,-1)); - TreeNode *TryNode,*ChildNode,*BalanceNode,*SuccNode; - TryNode=head.Left; - char factor; - for (;;) { //Search for the - if (TryNode == 0) - return false; //Not found. - factor = fCmp(key, TryNode->key); - if (factor == 0) - break; //Key found, continue to delete. - //factor = _FactorCompare( key, TryNode->key ); - path.push_back(NodePath(TryNode,factor)); - TryNode = _FactorLink(TryNode,factor); //Move to left. - } - SuccNode = TryNode->Right; //Find a successor. - factor = 1; - if (SuccNode == 0) { - SuccNode = TryNode->Left; - factor = -1; - } - path.push_back(NodePath(TryNode,factor)); - while (SuccNode) { - path.push_back(NodePath(SuccNode, -factor)); - SuccNode = _FactorLink(SuccNode,-factor); - } - PathNode = path.back(); - delete[] TryNode->key; // jichi 9/22/2013: key is supposed to be an array - TryNode->key = PathNode.Node->key; //Replace key and data field with the successor or predecessor. - PathNode.Node->key = nullptr; - TryNode->data = PathNode.Node->data; - path.pop_back(); - _FactorLink(path.back().Node,path.back().factor) = _FactorLink(PathNode.Node,-PathNode.factor); - delete PathNode.Node; //Remove the successor from the tree and release memory. - PathNode = path.back(); - for (int i=0; irank--; - for (;;) { //Rebalance the tree along the path back to the root. - if (path.size()==1) { - _DecreaseHeight(); - break; - } - BalanceNode = PathNode.Node; - if (BalanceNode->factor == 0) { // A balance node, just need to adjust the factor. Don't have to recurve since subtree height stays. - BalanceNode->factor=-PathNode.factor; - break; - } - if (BalanceNode->factor == PathNode.factor) { // Node get more balance. Subtree height decrease, need to recurve. - BalanceNode->factor = 0; - path.pop_back(); - PathNode = path.back(); - continue; - } - //Node get out of balance. Here raises 3 cases. - ChildNode = _FactorLink(BalanceNode, -PathNode.factor); - if (ChildNode->factor == 0) { // New case different to insert operation. - TryNode = _SingleRotation2( BalanceNode, ChildNode, BalanceNode->factor ); - path.pop_back(); - PathNode = path.back(); - _FactorLink(PathNode.Node, PathNode.factor) = TryNode; - break; - } - else { - if (ChildNode->factor == BalanceNode->factor) // Analogous to insert operation case 1. - TryNode = _SingleRotation( BalanceNode, ChildNode, BalanceNode->factor ); - else if (ChildNode->factor + BalanceNode->factor == 0) // Analogous to insert operation case 2. - TryNode = _DoubleRotation( BalanceNode, ChildNode, BalanceNode->factor ); - } - path.pop_back(); //Recurse back along the path. - PathNode = path.back(); - _FactorLink(PathNode.Node, PathNode.factor) = TryNode; - } - return true; - } - - D &operator [](T *key) - { return (Insert(key,D())->data); } - - TreeNode *Search(const T *key) - { - TreeNode *Find=head.Left; - char k; - while (Find != 0) {//&&Find->key!=key) - k = fCmp(key, Find->key); - if (k == 0) break; - Find = _FactorLink(Find, k); - } - return Find; - } - - TreeNode *SearchIndex(unsigned int rank) - { - unsigned int r = head.rank; - if (rank == -1) - return 0; - if (++rank>=r) - return 0; - TreeNode *n=&head; - while (r!=rank) { - if (rank>r) { - n=n->Right; - rank-=r; - r=n->rank; - } else { - n=n->Left; - r=n->rank; - } - } - return n; - } - - TreeNode *Begin() - { - TreeNode *Node = head.Left; - if (Node) - while (Node->Left) Node = Node->Left; - return Node; - } - - TreeNode *End() - { - TreeNode *Node=head.Left; - if (Node) - while (Node->Right) Node = Node->Right; - return Node; - } - unsigned int Count() const { return head.rank - 1; } - - template - Fn TraverseTree(Fn &f) - { return TraverseTreeNode(head.Left,f); } - -protected: - bool DeleteRoot() - { - NodePath PathNode; - MyStack,STACK_SIZE> path; //Use to record a path to the destination node. - path.push_back(NodePath(&head,-1)); - TreeNode *TryNode,*ChildNode,*BalanceNode,*SuccNode; - TryNode=head.Left; - char factor; - SuccNode=TryNode->Right; //Find a successor. - factor=1; - if (SuccNode==0) - { - SuccNode=TryNode->Left; - factor=-1; - } - path.push_back(NodePath(TryNode,factor)); - while (SuccNode) { - path.push_back(NodePath(SuccNode,-factor)); - SuccNode=_FactorLink(SuccNode,-factor); - } - PathNode=path.back(); - delete[] TryNode->key; // jichi 9/22/2013: key is supposed to be an array - TryNode->key=PathNode.Node->key; //Replace key and data field with the successor. - PathNode.Node->key = nullptr; - TryNode->data=PathNode.Node->data; - path.pop_back(); - _FactorLink(path.back().Node,path.back().factor) = _FactorLink(PathNode.Node,-PathNode.factor); - delete PathNode.Node; //Remove the successor from the tree and release memory. - PathNode=path.back(); - for (int i=0;irank--; - for (;;) { //Rebalance the tree along the path back to the root. - if (path.size() == 1) { - _DecreaseHeight(); - break; - } - - BalanceNode = PathNode.Node; - if (BalanceNode->factor == 0) { // A balance node, just need to adjust the factor. Don't have to recurse since subtree height not changed. - BalanceNode->factor=-PathNode.factor; - break; - } - if (BalanceNode->factor==PathNode.factor) { // Node get more balance. Subtree height decrease, need to recurse. - BalanceNode->factor=0; - path.pop_back(); - PathNode=path.back(); - continue; - } - //Node get out of balance. Here raises 3 cases. - ChildNode = _FactorLink(BalanceNode, -PathNode.factor); - if (ChildNode->factor == 0) { // New case different to insert operation. - TryNode = _SingleRotation2( BalanceNode, ChildNode, BalanceNode->factor ); - path.pop_back(); - PathNode=path.back(); - _FactorLink(PathNode.Node, PathNode.factor) = TryNode; - break; - } else { - if (ChildNode->factor == BalanceNode->factor) // Analogous to insert operation case 1. - TryNode = _SingleRotation( BalanceNode, ChildNode, BalanceNode->factor ); - else if (ChildNode->factor + BalanceNode->factor == 0) // Analogous to insert operation case 2. - TryNode = _DoubleRotation( BalanceNode, ChildNode, BalanceNode->factor ); - } - path.pop_back(); // Recurve back along the path. - PathNode=path.back(); - _FactorLink(PathNode.Node, PathNode.factor) = TryNode; - } - return true; - } - template - Fn TraverseTreeNode(TreeNode *Node, Fn &f) - { - if (Node) { - if (Node->Left) - TraverseTreeNode(Node->Left,f); - f(Node); - if (Node->Right) - TraverseTreeNode(Node->Right,f); - } - return f; - } - TreeNode *_SingleRotation(TreeNode *BalanceNode, TreeNode *ModifyNode, char factor) - { - TreeNode *Node = _FactorLink(ModifyNode, -factor); - _FactorLink(BalanceNode, factor) = Node; - _FactorLink(ModifyNode, -factor) = BalanceNode; - if (Node) - Node->Parent = BalanceNode; - ModifyNode->Parent = BalanceNode->Parent; - BalanceNode->Parent = ModifyNode; - BalanceNode->factor = ModifyNode->factor = 0; //After single rotation, set all factor of 3 node to 0. - if (factor == 1) - ModifyNode->rank += BalanceNode->rank; - else - BalanceNode->rank -= ModifyNode->rank; - return ModifyNode; - } - TreeNode *_SingleRotation2(TreeNode *BalanceNode, TreeNode *ModifyNode, char factor) - { - TreeNode *Node = _FactorLink(ModifyNode, -factor); - _FactorLink(BalanceNode, factor) = Node; - _FactorLink(ModifyNode, -factor) = BalanceNode; - if (Node) Node->Parent = BalanceNode; - ModifyNode->Parent = BalanceNode->Parent; - BalanceNode->Parent = ModifyNode; - ModifyNode->factor = -factor; - if (factor == 1) - ModifyNode->rank+=BalanceNode->rank; - else - BalanceNode->rank-=ModifyNode->rank; - return ModifyNode; - } - TreeNode *_DoubleRotation(TreeNode *BalanceNode, TreeNode *ModifyNode, char factor) - { - TreeNode *DownNode = _FactorLink(ModifyNode, -factor); - TreeNode *Node1, *Node2; - Node1 = _FactorLink(DownNode, factor); - Node2 = _FactorLink(DownNode, -factor); - _FactorLink(ModifyNode, -factor) = Node1; - _FactorLink(DownNode, factor) = ModifyNode; - _FactorLink(BalanceNode, factor) = Node2; - _FactorLink(DownNode, -factor) = BalanceNode; - if (Node1) - Node1->Parent = ModifyNode; - if (Node2) - Node2->Parent = BalanceNode; - DownNode->Parent = BalanceNode->Parent; - BalanceNode->Parent = DownNode; - ModifyNode->Parent = DownNode; - //Set factor according to the result. - if (DownNode->factor == factor) { - BalanceNode->factor = -factor; - ModifyNode->factor = 0; - } else if (DownNode->factor == 0) - BalanceNode->factor = ModifyNode->factor = 0; - else { - BalanceNode->factor = 0; - ModifyNode->factor = factor; - } - DownNode->factor = 0; - if (factor==1) { - ModifyNode->rank -= DownNode->rank; - DownNode->rank += BalanceNode->rank; - } else { - DownNode->rank += ModifyNode->rank; - BalanceNode->rank -= DownNode->rank; - } - return DownNode; - } - - TreeNode* &__fastcall _FactorLink(TreeNode *Node, char factor) - //Private helper method to retrieve child according to factor. - //Return right child if factor>0 and left child otherwise. - { return factor>0? Node->Right : Node->Left; } - - void Check() - { - unsigned int k = (unsigned int)head.Right; - unsigned int t = head.Left->height(); - if (k != t) - __debugbreak(); - } - - void _IncreaseHeight() - { - unsigned int k = (unsigned int)head.Right; - head.Right = (TreeNode*)++k; - } - - void _DecreaseHeight() - { - unsigned int k = (unsigned int)head.Right; - head.Right = (TreeNode*)--k; - } -}; - -struct SCMP -{ - char operator()(const char *s1,const char *s2) - { - int t = _stricmp(s1, s2); - return t == 0 ? 0 : t > 0 ? 1 :-1; - } -}; - -struct SCPY { char *operator()(char *dest, const char *src) { return strcpy(dest, src); } }; -struct SLEN { int operator()(const char *str) { return strlen(str); } }; - -struct WCMP -{ - char operator()(const wchar_t *s1,const wchar_t *s2) - { - int t =_wcsicmp(s1, s2); - return t == 0 ? 0 : t > 0 ? 1 : -1; - } -}; - -struct WCPY { wchar_t *operator()(wchar_t *dest, const wchar_t *src) { return wcscpy(dest,src); } }; -struct WLEN { int operator()(const wchar_t *str) { return wcslen(str); } }; - -// EOF diff --git a/vnr/texthook/host/hookman.cc b/vnr/texthook/host/hookman.cc index 97abda6..941d150 100644 --- a/vnr/texthook/host/hookman.cc +++ b/vnr/texthook/host/hookman.cc @@ -60,7 +60,7 @@ DWORD GetHookName(LPSTR str, DWORD pid, DWORD hook_addr, DWORD max) if (!pr) return 0; NtWaitForSingleObject(pr->hookman_mutex, 0, 0); - Hook *hks = (Hook *)pr->hookman_map; + const Hook *hks = (const Hook *)pr->hookman_map; for (int i = 0; i < MAX_HOOK; i++) if (hks[i].Address() == hook_addr) { len = hks[i].NameLength(); @@ -79,76 +79,12 @@ DWORD GetHookName(LPSTR str, DWORD pid, DWORD hook_addr, DWORD max) return len; } -void ThreadTable::SetThread(DWORD num, TextThread *ptr) +// Artikash 5/31/2018: required for unordered_map to work with struct key +bool operator==(const ThreadParameter& one, const ThreadParameter& two) { - int number = num; - if (number >= size) { - while (number >= size) - size <<= 1; - TextThread **temp; - //if (size < 0x10000) { - temp = new TextThread*[size]; - if (size > used) - ::memset(temp, 0, (size - used) * sizeof(TextThread *)); // jichi 9/21/2013: zero memory - memcpy(temp, storage, used * sizeof(TextThread *)); - //} - delete[] storage; - storage = temp; - } - storage[number] = ptr; - if (ptr == nullptr) { - if (number == used - 1) - while (storage[used - 1] == 0) - used--; - } else if (number >= used) - used = number + 1; + return one.pid == two.pid && one.hook == two.hook && one.retn == two.retn && one.spl == two.spl; } -TextThread *ThreadTable::FindThread(DWORD number) -{ return number <= (DWORD)used ? storage[number] : nullptr; } - -static const char sse_table_eq[0x100]={ - -1,1,-1,1, -1,1,-1,1, -1,1,-1,1, -1,1,-1,1, //0, compare 1 - -1,-1,1,1, -1,-1,1,1, -1,-1,1,1, -1,-1,1,1, //1, compare 2 - -1,1,-1,1, -1,1,-1,1, -1,1,-1,1, -1,1,-1,1, //0, compare 1 - -1,-1,-1,-1, 1,1,1,1, -1,-1,-1,-1, 1,1,1,1, //3, compare 3 - -1,1,-1,1, -1,1,-1,1, -1,1,-1,1, -1,1,-1,1, //0, compare 1 - -1,-1,1,1, -1,-1,1,1, -1,-1,1,1, -1,-1,1,1, //1, compare 2 - -1,1,-1,1, -1,1,-1,1, -1,1,-1,1, -1,1,-1,1, //0, compare 1 - -1,-1,-1,-1, -1,-1,-1,-1, 1,1,1,1, 1,1,1,1, //7, compare 4 - -1,1,-1,1, -1,1,-1,1, -1,1,-1,1, -1,1,-1,1, //0, compare 1 - -1,-1,1,1, -1,-1,1,1, -1,-1,1,1, -1,-1,1,1, //1, compare 2 - -1,1,-1,1, -1,1,-1,1, -1,1,-1,1, -1,1,-1,1, //0, compare 1 - -1,-1,-1,-1, 1,1,1,1, -1,-1,-1,-1, 1,1,1,1, //3, compare 3 - -1,1,-1,1, -1,1,-1,1, -1,1,-1,1, -1,1,-1,1, //0, compare 1 - -1,-1,1,1, -1,-1,1,1, -1,-1,1,1, -1,-1,1,1, //1, compare 2 - -1,1,-1,1, -1,1,-1,1, -1,1,-1,1, -1,1,-1,1, //0, compare 1 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 //f, equal -}; - -char TCmp::operator()(const ThreadParameter* t1, const ThreadParameter* t2) - //SSE speed up. Compare four integers in const time without branching. - //The AVL tree branching operation needs 2 bit of information. - //One bit for equality and one bit for "less than" or "greater than". - -{ - union{__m128 m0;__m128i i0;}; - union{__m128 m1;__m128i i1;}; - union{__m128 m2;__m128i i2;}; - int k0,k1; - i1 = _mm_loadu_si128((const __m128i*)t1); - i2 = _mm_loadu_si128((const __m128i*)t2); - i0 = _mm_cmpgt_epi32(i1,i2); - k0 = _mm_movemask_ps(m0); - i1 = _mm_cmpeq_epi32(i1,i2); - k1 = _mm_movemask_ps(m1); - return sse_table_eq[k1*16+k0]; -} -void TCpy::operator()(ThreadParameter* t1, const ThreadParameter* t2) -{ memcpy(t1,t2,sizeof(ThreadParameter)); } - -int TLen::operator()(const ThreadParameter* t) { return 0; } - #define NAMED_PIPE_DISCONNECT 1 //Class member of HookManger HookManager::HookManager() : @@ -162,65 +98,40 @@ HookManager::HookManager() : , detach(nullptr) , hook(nullptr) , current_pid(0) - , thread_table(nullptr) - , destroy_event(nullptr) - , register_count(0) , new_thread_number(0) + , threadTable() + , processRecordsByIds() { - // jichi 9/21/2013: zero memory - ::memset(record, 0, sizeof(record)); - ::memset(text_pipes, 0, sizeof(text_pipes)); - ::memset(cmd_pipes, 0, sizeof(cmd_pipes)); - ::memset(recv_threads, 0, sizeof(recv_threads)); - - head.key = new ThreadParameter; - head.key->pid = 0; - head.key->hook = -1; - head.key->retn = -1; - head.key->spl = -1; - head.data = 0; - thread_table = new ThreadTable; // jichi 9/26/2013: zero memory in ThreadTable - - TextThread *entry = new TextThread(0, -1,-1,-1, new_thread_number++); // jichi 9/26/2013: zero memory in TextThread - thread_table->SetThread(0, entry); - SetCurrent(entry); - entry->Status() |= USING_UNICODE; - //texts->SetUnicode(true); - //entry->AddToCombo(); - //entry->ComboSelectCurrent(); - - //if (background==0) entry->AddToStore((BYTE*)BackgroundMsg,wcslen(BackgroundMsg)<<1,0,1); - - //InitializeCriticalSection(&hmcs); - destroy_event = IthCreateEvent(0, 0, 0); + TextThread* consoleTextThread = threadTable[{0, -1UL, -1UL, -1UL}] = new TextThread(0, -1, -1, -1, new_thread_number++); + consoleTextThread->Status() |= USING_UNICODE; + SetCurrent(consoleTextThread); } HookManager::~HookManager() { + // Artikash 5/31/2018: This is called when the program terminates, so Windows should automatically free all these resources.....right? //LARGE_INTEGER timeout={-1000*1000,-1}; //IthBreak(); - NtWaitForSingleObject(destroy_event, 0, 0); - NtClose(destroy_event); - NtClose(cmd_pipes[0]); - NtClose(recv_threads[0]); - delete thread_table; - delete head.key; + //NtWaitForSingleObject(destroy_event, 0, 0); + //NtClose(destroy_event); + //NtClose(cmd_pipes[0]); + //NtClose(recv_threads[0]); + //delete thread_table; + //delete head.key; //DeleteCriticalSection(&hmcs); } -TextThread *HookManager::FindSingle(DWORD pid, DWORD hook, DWORD retn, DWORD split) -{ - if (pid == 0) - return thread_table->FindThread(0); - ThreadParameter tp = {pid, hook, retn, split}; - TreeNode *node = Search(&tp); - return node ? thread_table->FindThread(node->data) : nullptr; -} - TextThread *HookManager::FindSingle(DWORD number) -{ return (number & 0x80008000) ? nullptr : thread_table->FindThread(number); } - -void HookManager::DetachProcess(DWORD pid) {} +{ + for (auto i : threadTable) + { + if (i.second->Number() == number) + { + return i.second; + } + } + return nullptr; +} void HookManager::SetCurrent(TextThread *it) { @@ -242,201 +153,70 @@ void HookManager::SelectCurrent(DWORD num) void HookManager::RemoveSingleHook(DWORD pid, DWORD addr) { HM_LOCK; - //ConsoleOutput("vnrhost:RemoveSingleHook: lock"); - //EnterCriticalSection(&hmcs); - DWORD max = thread_table->Used(); - bool flag = false; - for (DWORD i = 1; i <= max; i++) - if (TextThread *it = thread_table->FindThread(i)) - if (it->PID() == pid && it->Addr() == addr) { - flag |= (it == current); - //flag|=it->RemoveFromCombo(); - thread_table->SetThread(i, 0); - if (it->Number() < new_thread_number) - new_thread_number = it->Number(); - Delete(it->GetThreadParameter()); - if (remove) - remove(it); - delete it; - } - - for (DWORD i = 0; i <= max; i++) - if (TextThread *it = thread_table->FindThread(i)) - if (it->Link() && thread_table->FindThread(it->LinkNumber()) == nullptr) { - it->LinkNumber() = -1; - it->Link() = nullptr; - } - - if (flag) { - current = nullptr; - DWORD number = head.Left ? head.Left->data : 0; - SetCurrent(thread_table->FindThread(number)); - if (reset && current) - reset(current); - //it->ResetEditText(); + std::vector removedThreads; + for (auto i : threadTable) + { + if (i.second->PID() == pid && i.second->Addr() == addr) + { + if (remove) + { + remove(i.second); + } + delete i.second; + removedThreads.push_back(i.first); + } } - //LeaveCriticalSection(&hmcs); - //ConsoleOutput("vnrhost:RemoveSingleHook: unlock"); -} -void HookManager::RemoveSingleThread(DWORD number) -{ - if (number == 0) - return; - HM_LOCK; - //ConsoleOutput("vnrhost:RemoveSingleThread: lock"); - //EnterCriticalSection(&hmcs); - if (TextThread *it = thread_table->FindThread(number)) { - thread_table->SetThread(number, 0); - Delete(it->GetThreadParameter()); - if (remove) - remove(it); - bool flag = (it == current); - if (it->Number() < new_thread_number) - new_thread_number = it->Number(); - delete it; - for (int i = 0; i <= thread_table->Used(); i++) - if (TextThread *t = thread_table->FindThread(i)) - if (t->LinkNumber() == number) { - t->Link() = 0; - t->LinkNumber() = -1; - } - - if (flag) { - current = nullptr; - number = head.Left ? head.Left->data : 0; - SetCurrent(thread_table->FindThread(number)); - if (reset && current) - reset(current); - //it->ResetEditText(); - } + for (auto i : removedThreads) + { + threadTable.erase(i); } - //LeaveCriticalSection(&hmcs); - //ConsoleOutput("vnrhost:RemoveSingleThread: unlock"); + SelectCurrent(0); } void HookManager::RemoveProcessContext(DWORD pid) { - HM_LOCK; - bool flag = false; - //ConsoleOutput("vnrhost:RemoveProcessContext: lock"); - //EnterCriticalSection(&hmcs); - for (int i = 1; i < thread_table->Used(); i++) - if (TextThread *it = thread_table->FindThread(i)) - if (it->PID() == pid) { - Delete(it->GetThreadParameter()); - //if (false == Delete(it->GetThreadParameter())) { - // // jichi 11/26/2013: Remove debugging instructions - // //if (debug) - // // __asm int 3 - //} - flag |= (it == current); - //flag|=it->RemoveFromCombo(); - if (it->Number() Number(); - thread_table->SetThread(i,0); - if (remove) - remove(it); - delete it; - } - - for (int i = 0; i < thread_table->Used(); i++) - if (TextThread *it=thread_table->FindThread(i)) - if (it->Link() && thread_table->FindThread(it->LinkNumber()) == nullptr) { - it->LinkNumber()=-1; - it->Link() = nullptr; - } - - if (flag) { - current = nullptr; - DWORD number = head.Left ? head.Left->data : 0; - SetCurrent(thread_table->FindThread(number)); - if (reset && current) - reset(current); - //if (it) it->ResetEditText(); - } - //LeaveCriticalSection(&hmcs); - //ConsoleOutput("vnrhost:RemoveProcessContext: unlock"); + HM_LOCK; + std::vector removedThreads; + for (auto i : threadTable) + { + if (i.second->PID() == pid) + { + if (remove) + { + remove(i.second); + } + delete i.second; + removedThreads.push_back(i.first); + } + } + for (auto i : removedThreads) + { + threadTable.erase(i); + } + SelectCurrent(0); } -void HookManager::RegisterThread(TextThread* it, DWORD num) -{ thread_table->SetThread(num, it); } -void HookManager::RegisterPipe(HANDLE text, HANDLE cmd, HANDLE thread) -{ - text_pipes[register_count] = text; - cmd_pipes[register_count] = cmd; - recv_threads[register_count] = thread; - register_count++; - if (register_count == 1) - NtSetEvent(destroy_event, 0); - else - NtClearEvent(destroy_event); -} -void HookManager::RegisterProcess(DWORD pid) +void HookManager::RegisterProcess(DWORD pid, HANDLE hostPipe) { HM_LOCK; - wchar_t str[0x40], - path[MAX_PATH]; - //pid_map->Set(pid>>2); - //ConsoleOutput("vnrhost:RegisterProcess: lock"); - //EnterCriticalSection(&hmcs); - record[register_count - 1].pid_register = pid; - //record[register_count - 1].engine_register = engine; - swprintf(str, ITH_SECTION_ L"%d", pid); - HANDLE hSection = IthCreateSection(str, HOOK_SECTION_SIZE, PAGE_READONLY); - LPVOID map = nullptr; - //DWORD map_size = 0x1000; - DWORD map_size = HOOK_SECTION_SIZE / 2; // jichi 1/16/2015: Changed to half to hook section size - //if (::ith_has_section) - NtMapViewOfSection(hSection, NtCurrentProcess(), - &map, 0, map_size, 0, &map_size, ViewUnmap, 0, - PAGE_READONLY); - record[register_count - 1].hookman_section = hSection; - record[register_count - 1].hookman_map = map; + ProcessRecord* record = processRecordsByIds[pid] = new ProcessRecord; + record->hostPipe = hostPipe; + record->hookman_section = OpenFileMappingW(FILE_MAP_READ, FALSE, (std::wstring(ITH_SECTION_) + std::to_wstring(pid)).c_str()); + record->hookman_map = MapViewOfFile(record->hookman_section, FILE_MAP_READ, 0, 0, HOOK_SECTION_SIZE / 2); // jichi 1/16/2015: Changed to half to hook section size + record->process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); + record->hookman_mutex = OpenMutexW(MUTEX_ALL_ACCESS, FALSE, (std::wstring(ITH_HOOKMAN_MUTEX_) + std::to_wstring(pid)).c_str()); + //if (NT_SUCCESS(NtOpenProcess(&hProc, + // PROCESS_QUERY_INFORMATION| + // PROCESS_CREATE_THREAD| + // PROCESS_VM_READ| + // PROCESS_VM_WRITE| + // PROCESS_VM_OPERATION, + // &oa,&id))) - HANDLE hProc; - CLIENT_ID id; - id.UniqueProcess = pid; - id.UniqueThread = 0; - OBJECT_ATTRIBUTES oa = {}; - oa.uLength = sizeof(oa); - if (NT_SUCCESS(NtOpenProcess(&hProc, - PROCESS_QUERY_INFORMATION| - PROCESS_CREATE_THREAD| - PROCESS_VM_READ| - PROCESS_VM_WRITE| - PROCESS_VM_OPERATION, - &oa,&id))) - record[register_count - 1].process_handle = hProc; - else { - DOUT("failed to open process"); - //::man->AddConsoleOutput(ErrorOpenProcess); - //LeaveCriticalSection(&hmcs); - //ConsoleOutput("vnrhost:RegisterProcess: unlock"); - return; - } - - // jichi 9/27/2013: The hook man should be consistent with the one defined in vnrcli - //Hook *h = (Hook *)map; - //for (int i = 0; i < MAX_HOOK; i++) - // if (!h[i].hook_name) - // break; - // else { - // const Hook &hi = h[i]; - // wchar_t buffer[1000]; - // DWORD len = hi.NameLength(); - // NtReadVirtualMemory(hProc, hi.hook_name, buffer, len << 1, &len); - // buffer[len] = 0; - // ITH_MSG(buffer); - // } - - swprintf(str, ITH_HOOKMAN_MUTEX_ L"%d", pid); - record[register_count - 1].hookman_mutex = IthOpenMutex(str); - current_pid = pid; if (attach) attach(pid); - //LeaveCriticalSection(&hmcs); - //ConsoleOutput("vnrhost:RegisterProcess: unlock"); + } void HookManager::UnRegisterProcess(DWORD pid) @@ -445,42 +225,41 @@ void HookManager::UnRegisterProcess(DWORD pid) //ConsoleOutput("vnrhost:UnRegisterProcess: lock"); //EnterCriticalSection(&hmcs); - int i; - for (i = 0; i < MAX_REGISTER; i++) - if(record[i].pid_register == pid) - break; + ProcessRecord pr = *processRecordsByIds[pid]; + CloseHandle(pr.hookman_mutex); + UnmapViewOfFile(pr.hookman_map); + CloseHandle(pr.process_handle); + CloseHandle(pr.hookman_section); + //NtClose(text_pipes[i]); + //NtClose(cmd_pipes[i]); + //NtClose(recv_threads[i]); + //NtClose(record[i].hookman_mutex); - if (i < MAX_REGISTER) { - NtClose(text_pipes[i]); - NtClose(cmd_pipes[i]); - NtClose(recv_threads[i]); - NtClose(record[i].hookman_mutex); + ////if (::ith_has_section) + //NtUnmapViewOfSection(NtCurrentProcess(), record[i].hookman_map); + ////else + //// delete[] record[i].hookman_map; - //if (::ith_has_section) - NtUnmapViewOfSection(NtCurrentProcess(), record[i].hookman_map); - //else - // delete[] record[i].hookman_map; + //NtClose(record[i].process_handle); + //NtClose(record[i].hookman_section); - NtClose(record[i].process_handle); - NtClose(record[i].hookman_section); - - for (; i < MAX_REGISTER; i++) { - record[i] = record[i+1]; - text_pipes[i] = text_pipes[i+1]; - cmd_pipes[i] = cmd_pipes[i+1]; - recv_threads[i] = recv_threads[i+1]; - if (text_pipes[i] == 0) - break; - } - register_count--; - if (current_pid == pid) - current_pid = register_count ? record[0].pid_register : 0; + //for (; i < MAX_REGISTER; i++) { + // record[i] = record[i+1]; + // text_pipes[i] = text_pipes[i+1]; + // cmd_pipes[i] = cmd_pipes[i+1]; + // recv_threads[i] = recv_threads[i+1]; + // if (text_pipes[i] == 0) + // break; + //} + //register_count--; + //if (current_pid == pid) + // current_pid = register_count ? record[0].pid_register : 0; RemoveProcessContext(pid); - } + //pid_map->Clear(pid>>2); - if (register_count == 1) - NtSetEvent(destroy_event, 0); + //if (register_count == 1) + // NtSetEvent(destroy_event, 0); //LeaveCriticalSection(&hmcs); //ConsoleOutput("vnrhost:UnRegisterProcess: unlock"); if (detach) @@ -511,75 +290,6 @@ void HookManager::UnRegisterProcess(DWORD pid) // //swprintf(user_entry,L"UserHook%c",c); //} -void HookManager::AddLink(WORD from, WORD to) -{ - HM_LOCK; - //bool flag=false; - //ConsoleOutput("vnrhost:AddLink: lock"); - //EnterCriticalSection(&hmcs); - TextThread *from_thread = thread_table->FindThread(from), - *to_thread = thread_table->FindThread(to); - if (to_thread && from_thread) { - if (from_thread->GetThreadParameter()->pid != to_thread->GetThreadParameter()->pid) - DOUT("link to different process"); - else if (from_thread->Link()==to_thread) - DOUT("link already exists"); - else if (to_thread->CheckCycle(from_thread)) - DOUT("cyclic link"); - else { - from_thread->Link()=to_thread; - from_thread->LinkNumber()=to; - DOUT("thread linked"); - if (addRemoveLink) - addRemoveLink(from_thread); - //WCHAR str[0x40]; - //swprintf(str,FormatLink,from,to); - //AddConsoleOutput(str); - } - } else - DOUT("error link"); - //else - // AddConsoleOutput(ErrorLink); - //LeaveCriticalSection(&hmcs); - //ConsoleOutput("vnrhost:AddLink: unlock"); -} -void HookManager::UnLink(WORD from) -{ - HM_LOCK; - //bool flag=false; - //ConsoleOutput("vnrhost:UnLink: lock"); - //EnterCriticalSection(&hmcs); - if (TextThread *from_thread = thread_table->FindThread(from)) { - from_thread->Link() = nullptr; - from_thread->LinkNumber() = 0xffff; - DOUT("link deleted"); - if (addRemoveLink) - addRemoveLink(from_thread); - } - //else // jichi 12/25/2013: This could happen when the game exist - // ConsoleOutput("vnrhost:UnLink: thread does not exist"); - //LeaveCriticalSection(&hmcs); - //ConsoleOutput("vnrhost:UnLink: unlock"); -} -void HookManager::UnLinkAll(WORD from) -{ - HM_LOCK; - //bool flag=false; - //ConsoleOutput("vnrhost:UnLinkAll: lock"); - //EnterCriticalSection(&hmcs); - if (TextThread *from_thread = thread_table->FindThread(from)) { - from_thread->UnLinkAll(); - DOUT("link deleted"); - } - //else // jichi 12/25/2013: This could happen after the process exists - // ConsoleOutput("vnrhost:UnLinkAll: thread not exist"); - //AddConsoleOutput(L"Link deleted."); - //} else - // AddConsoleOutput(L"Thread not exist."); - //LeaveCriticalSection(&hmcs); - //ConsoleOutput("vnrhost:UnLinkAll: unlock"); -} - void HookManager::DispatchText(DWORD pid, const BYTE *text, DWORD hook, DWORD retn, DWORD spl, int len, bool space) { // jichi 20/27/2013: When PID is zero, the text comes from console, which I don't need @@ -591,43 +301,23 @@ void HookManager::DispatchText(DWORD pid, const BYTE *text, DWORD hook, DWORD re //ConsoleOutput("vnrhost:DispatchText: lock"); //EnterCriticalSection(&hmcs); TextThread *it; - //`try { - if (TreeNode *in = Search(&tp)) { - DWORD number = in->data; - it = thread_table->FindThread(number); - } else if (IsFull()) { // jichi 1/16/2015: Skip adding threads when full - static bool once = true; // output only once - if (once) { - once = false; - DOUT("so many new threads, skip"); - } - return; - } else { // New thread - Insert(&tp, new_thread_number); - it = new TextThread(pid, hook, retn, spl, new_thread_number); - RegisterThread(it, new_thread_number); - DOUT("found new thread"); - char entstr[0x200]; - it->GetEntryString(entstr); - DOUT(entstr); - while (thread_table->FindThread(++new_thread_number)); - if (create) - create(it); - } - if (it) - it->AddText(text, len, false, space); // jichi 10/27/2013: new line is false - //LeaveCriticalSection(&hmcs); - //ConsoleOutput("vnrhost:DispatchText: unlock"); - //} catch (...) { - // // ignored - //} + if (!(it = threadTable[tp])) + { + it = threadTable[tp] = new TextThread(pid, hook, retn, spl, new_thread_number++); + if (create) + { + create(it); + } + } + it->AddText(text, len, false, space); } void HookManager::AddConsoleOutput(LPCWSTR text) { - if (text) { - int len = wcslen(text) << 1; - TextThread *console = thread_table->FindThread(0); + if (text) + { + int len = wcslen(text) * 2; + TextThread *console = threadTable[{0, -1UL, -1UL, -1UL}]; //EnterCriticalSection(&hmcs); console->AddText((BYTE*)text,len,false,true); console->AddText((BYTE*)L"\r\n",4,false,true); @@ -635,25 +325,6 @@ void HookManager::AddConsoleOutput(LPCWSTR text) } } -void HookManager::ClearText(DWORD pid, DWORD hook, DWORD retn, DWORD spl) -{ - HM_LOCK; - //bool flag=false; - //ConsoleOutput("vnrhost:ClearText: lock"); - //EnterCriticalSection(&hmcs); - ThreadParameter tp = {pid, hook, retn, spl}; - if (TreeNode *in = Search(&tp)) - if (TextThread *it = thread_table->FindThread(in->data)) { - it->Reset(); - //SetCurrent(it); - if (reset) - reset(it); - //it->ResetEditText(); - } - - //LeaveCriticalSection(&hmcs); - //ConsoleOutput("vnrhost:ClearText: unlock"); -} void HookManager::ClearCurrent() { HM_LOCK; @@ -673,9 +344,10 @@ void HookManager::ResetRepeatStatus() HM_LOCK; //ConsoleOutput("vnrhost:ResetRepeatStatus: lock"); //EnterCriticalSection(&hmcs); - for (int i = 1; i < thread_table->Used(); i++) - if (TextThread *it = thread_table->FindThread(i)) - it->ResetRepeatStatus(); + for (auto i : threadTable) + { + i.second->ResetRepeatStatus(); + } //LeaveCriticalSection(&hmcs); //ConsoleOutput("vnrhost:ResetRepeatStatus: unlock"); @@ -698,25 +370,17 @@ ProcessRecord *HookManager::GetProcessRecord(DWORD pid) { HM_LOCK; //EnterCriticalSection(&hmcs); - for (int i = 0; i < MAX_REGISTER; i++) - if (record[i].pid_register == pid) - return record + i; - return nullptr; + return processRecordsByIds[pid]; //ProcessRecord *pr = i < MAX_REGISTER ? record + i : nullptr; //LeaveCriticalSection(&hmcs); //return pr; } -DWORD HookManager::GetCurrentPID() { return current_pid; } - -HANDLE HookManager::GetCmdHandleByPID(DWORD pid) +HANDLE HookManager::GetHostPipeByPID(DWORD pid) { HM_LOCK; //EnterCriticalSection(&hmcs); - for (int i = 0; i < MAX_REGISTER; i++) - if (record[i].pid_register == pid) - return cmd_pipes[i]; - return nullptr; + return processRecordsByIds[pid] ? processRecordsByIds[pid]->hostPipe : nullptr; //HANDLE h = i < MAX_REGISTER ? cmd_pipes[i] : 0; //LeaveCriticalSection(&hmcs); //return h; @@ -734,10 +398,6 @@ MK_BASIC_TYPE(LPVOID) // return hash; //} -DWORD GetCurrentPID() { return ::man->GetCurrentPID(); } - -HANDLE GetCmdHandleByPID(DWORD pid) { return ::man->GetCmdHandleByPID(pid); } - //void AddLink(WORD from, WORD to) { ::man->AddLink(from, to); } // jichi 9/27/2013: Unparse to hook parameters /H code @@ -811,9 +471,6 @@ void GetCode(const HookParam &hp, LPWSTR buffer, DWORD pid) ptr += swprintf(ptr, L"@%X", hp.address); } -// jichi 1/16/2015 -bool HookManager::IsFull() const { return new_thread_number >= MAX_HOOK; } - void AddHooksToProfile(Profile& pf, const ProcessRecord& pr); DWORD AddThreadToProfile(Profile& pf, const ProcessRecord& pr, TextThread* thread); void MakeHookRelative(const ProcessRecord& pr, HookParam& hp); @@ -869,16 +526,7 @@ void MakeHookRelative(const ProcessRecord& pr, HookParam& hp) void HookManager::AddThreadsToProfile(Profile& pf, const ProcessRecord& pr, DWORD pid) { HM_LOCK; - ThreadTable* table = Table(); - for (int i = 0; i < table->Used(); ++i) - { - TextThread* tt = table->FindThread(i); - if (tt == NULL || tt->GetThreadParameter()->pid != pid) - continue; - //if (tt->Status() & CURRENT_SELECT || tt->Link() || tt->GetComment()) - if (tt->Status() & CURRENT_SELECT || tt->Link()) - AddThreadToProfile(pf, pr, tt); - } + AddThreadToProfile(pf, pr, current); } DWORD AddThreadToProfile(Profile& pf, const ProcessRecord& pr, TextThread* thread) @@ -896,12 +544,6 @@ DWORD AddThreadToProfile(Profile& pf, const ProcessRecord& pr, TextThread* threa WORD iw = thread_profile_index & 0xFFFF; if (thread->Status() & CURRENT_SELECT) pf.SelectedIndex() = iw; - if (thread->Link()) - { - WORD to_index = AddThreadToProfile(pf, pr, thread->Link()) & 0xFFFF; - if (iw >= 0) - pf.AddLink(link_ptr(new LinkProfile(iw, to_index))); - } } return thread_profile_index; // in case more than one thread links to the same thread } diff --git a/vnr/texthook/host/hookman.h b/vnr/texthook/host/hookman.h index b54abcf..63bf5eb 100644 --- a/vnr/texthook/host/hookman.h +++ b/vnr/texthook/host/hookman.h @@ -4,9 +4,10 @@ // 8/23/2013 jichi // Branch: ITH/HookManager.h, rev 133 -#include "host/avl_p.h" +#include "config.h" #include "host/textthread.h" #include "winmutex/winmutex.h" +#include namespace pugi { class xml_node; @@ -25,58 +26,44 @@ struct ProcessRecord { HANDLE hookman_mutex; HANDLE hookman_section; LPVOID hookman_map; + HANDLE hostPipe; }; -class ThreadTable : public MyVector -{ -public: - virtual void SetThread(DWORD number, TextThread *ptr); - virtual TextThread *FindThread(DWORD number); -}; - -struct IHFSERVICE TCmp { char operator()(const ThreadParameter *t1, const ThreadParameter *t2); }; -struct IHFSERVICE TCpy { void operator()(ThreadParameter *t1, const ThreadParameter *t2); }; -struct IHFSERVICE TLen { int operator()(const ThreadParameter *t); }; - typedef DWORD (*ProcessEventCallback)(DWORD pid); -class IHFSERVICE HookManager : public AVLTree +struct ThreadParameterHasher +{ + size_t operator()(const ThreadParameter& tp) const + { + return std::hash()(tp.pid << 6) + std::hash()(tp.hook) + std::hash()(tp.retn) + std::hash()(tp.spl); + } +}; + +class IHFSERVICE HookManager { public: HookManager(); ~HookManager(); // jichi 12/26/2013: remove virtual modifiers - TextThread *FindSingle(DWORD pid, DWORD hook, DWORD retn, DWORD split); TextThread *FindSingle(DWORD number); ProcessRecord *GetProcessRecord(DWORD pid); - DWORD GetProcessIDByPath(LPCWSTR str); // private - void RemoveSingleThread(DWORD number); //void LockHookman(); //void UnlockHookman(); void ResetRepeatStatus(); void ClearCurrent(); - void AddLink(WORD from, WORD to); - void UnLink(WORD from); - void UnLinkAll(WORD from); void SelectCurrent(DWORD num); - void DetachProcess(DWORD pid); void SetCurrent(TextThread *it); void AddConsoleOutput(LPCWSTR text); // jichi 10/27/2013: Add const; add space. void DispatchText(DWORD pid, const BYTE *text, DWORD hook, DWORD retn, DWORD split, int len, bool space); - - void ClearText(DWORD pid, DWORD hook, DWORD retn, DWORD split); // private void RemoveProcessContext(DWORD pid); // private void RemoveSingleHook(DWORD pid, DWORD addr); - void RegisterThread(TextThread*, DWORD); // private - void RegisterPipe(HANDLE text, HANDLE cmd, HANDLE thread); - void RegisterProcess(DWORD pid); + void RegisterProcess(DWORD pid, HANDLE hostPipe); void UnRegisterProcess(DWORD pid); //void SetName(DWORD); - DWORD GetCurrentPID(); // private - HANDLE GetCmdHandleByPID(DWORD pid); + HANDLE GetHostPipeByPID(DWORD pid); ConsoleCallback RegisterConsoleCallback(ConsoleCallback cf) { return (ConsoleCallback)_InterlockedExchange((long*)&console,(long)cf); } @@ -102,25 +89,13 @@ public: ProcessEventCallback RegisterProcessDetachCallback(ProcessEventCallback cf) { return (ProcessEventCallback)_InterlockedExchange((long*)&detach,(long)cf); } - ProcessEventCallback RegisterProcessNewHookCallback(ProcessEventCallback cf) - { return (ProcessEventCallback)_InterlockedExchange((long*)&hook,(long)cf); } - - ProcessEventCallback ProcessNewHook() { return hook; } - TextThread *GetCurrentThread() { return current; } // private - ProcessRecord *Records() { return record; } // private - ThreadTable *Table() { return thread_table; } // private - - //DWORD& SplitTime() { return split_time; } - //DWORD& RepeatCount() { return repeat_count; } - //DWORD& CyclicRemove() { return cyclic_remove; } - //DWORD& GlobalFilter() { return global_filter; } - void ConsoleOutput(LPCSTR text) { if (console) console(text); } // not thread safe - void ConsoleOutputW(LPCWSTR text) { if (wconsole) wconsole(text); } // not thread safe - void OnThreadCreate(pugi::xml_node profile_node, TextThread* thread); void GetProfile(DWORD pid, pugi::xml_node profile_node); private: + std::unordered_map threadTable; + std::unordered_map processRecordsByIds; + typedef win_mutex mutex_type; mutex_type hmcs; @@ -135,7 +110,6 @@ private: detach, hook; DWORD current_pid; - ThreadTable *thread_table; HANDLE destroy_event; ProcessRecord record[MAX_REGISTER + 1]; HANDLE text_pipes[MAX_REGISTER + 1], @@ -144,9 +118,6 @@ private: WORD register_count, new_thread_number; - // jichi 1/16/2014: Stop adding new threads when full - bool IsFull() const; // { return new_thread_number >= MAX_HOOK; } - bool IsEmpty() const { return !new_thread_number; } void HookManager::AddThreadsToProfile(Profile& pf, const ProcessRecord& pr, DWORD pid); }; diff --git a/vnr/texthook/host/host.cc b/vnr/texthook/host/host.cc index b82240b..b663356 100644 --- a/vnr/texthook/host/host.cc +++ b/vnr/texthook/host/host.cc @@ -213,7 +213,7 @@ IHFSERVICE bool IHFAPI DetachProcessById(DWORD processId) { ITH_SYNC_HOOK; DWORD command = HOST_COMMAND_DETACH; - return WriteFile(man->GetCmdHandleByPID(processId), &command, sizeof(command), nullptr, nullptr); + return WriteFile(man->GetHostPipeByPID(processId), &command, sizeof(command), nullptr, nullptr); } IHFSERVICE void IHFAPI GetHostHookManager(HookManager** hookman) @@ -238,7 +238,7 @@ IHFSERVICE DWORD IHFAPI Host_InsertHook(DWORD pid, HookParam *hp, LPCSTR name) { ITH_SYNC_HOOK; - HANDLE hCmd = man->GetCmdHandleByPID(pid); + HANDLE hCmd = man->GetHostPipeByPID(pid); if (hCmd == 0) return -1; @@ -269,7 +269,7 @@ IHFSERVICE DWORD IHFAPI Host_RemoveHook(DWORD pid, DWORD addr) ITH_SYNC_HOOK; HANDLE hRemoved,hCmd; - hCmd = GetCmdHandleByPID(pid); + hCmd = man->GetHostPipeByPID(pid); if (hCmd == 0) return -1; hRemoved = CreateEventW(nullptr, TRUE, FALSE, ITH_REMOVEHOOK_EVENT); @@ -289,23 +289,4 @@ IHFSERVICE DWORD IHFAPI Host_RemoveHook(DWORD pid, DWORD addr) return 0; } -// 4/30/2015: Removed as not needed. Going to change to json -IHFSERVICE DWORD IHFAPI Host_AddLink(DWORD from, DWORD to) -{ - man->AddLink(from & 0xffff, to & 0xffff); - return 0; -} - -IHFSERVICE DWORD IHFAPI Host_UnLink(DWORD from) -{ - man->UnLink(from & 0xffff); - return 0; -} - -IHFSERVICE DWORD IHFAPI Host_UnLinkAll(DWORD from) -{ - man->UnLinkAll(from & 0xffff); - return 0; -} - // EOF diff --git a/vnr/texthook/host/host_p.h b/vnr/texthook/host/host_p.h index 1c16159..896497c 100644 --- a/vnr/texthook/host/host_p.h +++ b/vnr/texthook/host/host_p.h @@ -36,7 +36,7 @@ DWORD WINAPI CmdThread(LPVOID lpThreadParameter); DWORD GetCurrentPID(); //DWORD GetProcessIDByPath(LPWSTR str); -HANDLE GetCmdHandleByPID(DWORD pid); +HANDLE GetHostPipeByPID(DWORD pid); //DWORD Inject(HANDLE hProc); //DWORD InjectByPID(DWORD pid); //DWORD PIDByName(LPWSTR target); diff --git a/vnr/texthook/host/pipe.cc b/vnr/texthook/host/pipe.cc index 271da2e..9204dab 100644 --- a/vnr/texthook/host/pipe.cc +++ b/vnr/texthook/host/pipe.cc @@ -74,20 +74,26 @@ CRITICAL_SECTION detachCs; // jichi 9/27/2013: also used in main //HANDLE hDetachEvent; extern HANDLE pipeExistsEvent; +struct Pipes +{ + HANDLE hookPipe; + HANDLE hostPipe; +}; + void CreateNewPipe() { - HANDLE hookPipe, hostPipe, TextReceivingThread; - - hookPipe = CreateNamedPipeW(ITH_TEXT_PIPE, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, MAXDWORD, NULL); - hostPipe = CreateNamedPipeW(ITH_COMMAND_PIPE, PIPE_ACCESS_OUTBOUND, 0, PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, MAXDWORD, NULL); - TextReceivingThread = CreateThread(nullptr, 0, TextReceiver, hookPipe, 0, nullptr); - man->RegisterPipe(hookPipe, hostPipe, TextReceivingThread); + CreateThread(nullptr, 0, TextReceiver, new Pipes + { + CreateNamedPipeW(ITH_TEXT_PIPE, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, MAXDWORD, NULL), + CreateNamedPipeW(ITH_COMMAND_PIPE, PIPE_ACCESS_OUTBOUND, 0, PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, MAXDWORD, NULL) + }, + 0, nullptr); } DWORD WINAPI TextReceiver(LPVOID lpThreadParameter) { - HANDLE hookPipe = (HANDLE)lpThreadParameter; - ConnectNamedPipe(hookPipe, nullptr); + Pipes* pipes = (Pipes*)lpThreadParameter; + ConnectNamedPipe(pipes->hookPipe, nullptr); BYTE* buffer = new BYTE[PIPE_BUFFER_SIZE]; DWORD bytesRead, processId; @@ -98,8 +104,8 @@ DWORD WINAPI TextReceiver(LPVOID lpThreadParameter) // return 0; //} - ReadFile(hookPipe, &processId, sizeof(processId), &bytesRead, nullptr); - man->RegisterProcess(processId); + ReadFile(pipes->hookPipe, &processId, sizeof(processId), &bytesRead, nullptr); + man->RegisterProcess(processId, pipes->hostPipe); // jichi 9/27/2013: why recursion? // Artikash 5/20/2018: To create a new pipe for another process @@ -107,7 +113,7 @@ DWORD WINAPI TextReceiver(LPVOID lpThreadParameter) while (::running) { - if (!ReadFile(hookPipe, buffer, PIPE_BUFFER_SIZE, &bytesRead, nullptr)) + if (!ReadFile(pipes->hookPipe, buffer, PIPE_BUFFER_SIZE, &bytesRead, nullptr)) { break; } @@ -131,14 +137,8 @@ DWORD WINAPI TextReceiver(LPVOID lpThreadParameter) { switch (commandType) { - case HOST_NOTIFICATION_NEWHOOK: - { - static long lock; - while (InterlockedExchange(&lock, 1) == 1); - man->ProcessNewHook()(processId); - lock = 0; - } - break; + case HOST_NOTIFICATION_NEWHOOK: // Artikash 5/30/2018: Useless for now, but could be handy to implement something later + break; case HOST_NOTIFICATION_TEXT: USES_CONVERSION; man->AddConsoleOutput(A2W((LPCSTR)(buffer + 8))); @@ -167,12 +167,13 @@ DWORD WINAPI TextReceiver(LPVOID lpThreadParameter) EnterCriticalSection(&detachCs); - DisconnectNamedPipe(hookPipe); - DisconnectNamedPipe(man->GetCmdHandleByPID(processId)); + DisconnectNamedPipe(pipes->hookPipe); + DisconnectNamedPipe(pipes->hostPipe); man->UnRegisterProcess(processId); LeaveCriticalSection(&detachCs); delete[] buffer; + delete pipes; return 0; } diff --git a/vnr/texthook/host/textthread.cc b/vnr/texthook/host/textthread.cc index 91af4cc..eaa331b 100644 --- a/vnr/texthook/host/textthread.cc +++ b/vnr/texthook/host/textthread.cc @@ -468,29 +468,6 @@ void TextThread::AddText(const BYTE *con, int len, bool new_line, bool space) sentence_length = 0; } else { SetNewLineTimer(); - if (link) { - const BYTE *send = con; - int l = len; - if (status & USING_UNICODE) { // Although unlikely, a thread and its link may have different encoding. - if ((link->Status() & USING_UNICODE) == 0) { - send = new BYTE[l]; - //::memset(send, 0, l); // jichi 9/26/2013: zero memory - l = WC_MB((LPWSTR)con, (char *)send); - } - link->AddTextDirect(send, l, space); - } else { - if (link->Status() & USING_UNICODE) { - size_t sz = len * 2 + 2; - send = new BYTE[sz]; - //::memset(send, 0, sz); // jichi 9/26/2013: zero memory - l = MB_WC((char *)con, (LPWSTR)send) << 1; - } - link->AddTextDirect(send, l, space); - } - link->SetNewLineTimer(); - if (send != con) - delete[] send; - } sentence_length += len; } @@ -514,29 +491,6 @@ void TextThread::AddTextDirect(const BYTE* con, int len, bool space) // Add to s if (status & BUFF_NEWLINE) AddLineBreak(); //SetNewLineTimer(); - if (link) { - const BYTE *send = con; - int l = len; - if (status & USING_UNICODE) { - if ((link->Status()&USING_UNICODE) == 0) { - send = new BYTE[l]; - //::memset(send, 0, l); // jichi 9/26/2013: zero memory - l = WC_MB((LPWSTR)con,(char*)send); - } - link->AddText(send, l, false, space); // new_line is false - } else { - if (link->Status()&USING_UNICODE) { - size_t sz = len * 2 + 2; - send = new BYTE[sz]; - //::memset(send, 0, sz); // jichi 9/26/2013: zero memory - l = MB_WC((char *)con, (LPWSTR)send) << 1; - } - link->AddText(send, l, false, space); // new_line is false - } - link->SetNewLineTimer(); - if (send != con) - delete[] send; - } sentence_length += len; BYTE *data = const_cast(con); // jichi 10/27/2013: TODO: Figure out where con is modified @@ -723,12 +677,6 @@ void TextThread::DispatchLastSentence() void TextThread::SetNewLineFlag() { status |= BUFF_NEWLINE; } -bool TextThread::CheckCycle(TextThread* start) -{ - if (link==start||this==start) return true; - if (link==0) return false; - return link->CheckCycle(start); -} void TextThread::SetNewLineTimer() { if (thread_number == 0) @@ -765,11 +713,5 @@ DWORD TextThread::GetThreadString(LPSTR str, DWORD max) return len; } -void TextThread::UnLinkAll() -{ - if (link) link->UnLinkAll(); - link = 0; - link_number = -1; -} // EOF diff --git a/vnr/texthook/host/textthread.h b/vnr/texthook/host/textthread.h index 1f6f5f9..a2160bb 100644 --- a/vnr/texthook/host/textthread.h +++ b/vnr/texthook/host/textthread.h @@ -48,7 +48,6 @@ public: //virtual void SetComment(LPWSTR); //virtual void ExportTextToFile(LPWSTR filename); - virtual bool CheckCycle(TextThread *start); virtual DWORD GetThreadString(LPSTR str, DWORD max); virtual DWORD GetEntryString(LPSTR str, DWORD max = 0x200); @@ -83,7 +82,6 @@ public: WORD &LinkNumber() { return link_number; } UINT_PTR &Timer() { return timer; } ThreadParameter *GetThreadParameter() { return &tp; } - TextThread *&Link() { return link; } //LPCWSTR GetComment() { return comment; } ThreadOutputFilterCallback RegisterOutputCallBack(ThreadOutputFilterCallback cb, PVOID data)