refactor textthread

This commit is contained in:
Akash Mozumdar 2018-07-18 16:18:43 -04:00
parent 4368826f2a
commit 904804de28
11 changed files with 106 additions and 263 deletions

View File

@ -23,11 +23,10 @@ TextBuffer::~TextBuffer()
WaitForSingleObject(hThread.get(), 0);
}
void TextBuffer::AddText(LPCWSTR str, int len, bool line)
void TextBuffer::AddText(std::wstring text, bool line)
{
CSLock lock(cs);
if (len > 0)
this->str.append(str, len);
this->str.append(text);
line_break = line;
}

View File

@ -9,7 +9,7 @@ public:
TextBuffer(HWND edit);
~TextBuffer();
void Flush();
void AddText(LPCWSTR str, int len, bool line);
void AddText(std::wstring text, bool line);
void ClearBuffer();
bool Running() { return running; }
private:

View File

@ -292,3 +292,13 @@ int WC_MB(const wchar_t *wc, char* mb, int mb_length)
{
return WideCharToMultiByte(932, 0, wc, -1, mb, mb_length, NULL, NULL);
}
std::wstring GetEntryString(TextThread* thread)
{
ThreadParameter tp = thread->GetThreadParameter();
std::wstring buffer;
buffer.resize(200);
buffer.resize(swprintf(&buffer[0], L"%.4X:%.4d:0x%08X:0x%08X:0x%08X:", thread->Number(), tp.pid, tp.hook, tp.retn, tp.spl));
buffer += man->GetHook(tp.pid, tp.hook).name;
return buffer;
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "ITH.h"
#include "texthook/host/textthread.h"
struct HookParam;
struct ProcessRecord;
@ -56,6 +57,7 @@ HANDLE IthCreateFile(LPCWSTR name, DWORD option, DWORD share, DWORD disposition)
int MB_WC(const char* mb, wchar_t* wc, int wc_length);
int MB_WC_count(const char* mb, int mb_length);
int WC_MB(const wchar_t *wc, char* mb, int mb_length);
std::wstring GetEntryString(TextThread * thread);
bool Parse(const std::wstring& cmd, HookParam& hp);
// http://jrdodds.blogs.com/blog/2004/08/raii_in_c.html

View File

@ -347,16 +347,9 @@ void ClickButton(HWND hWnd, HWND h)
}
}
DWORD ThreadOutput(TextThread* thread, const BYTE* out, DWORD len, DWORD new_line)
void ThreadOutput(TextThread* thread, std::wstring output)
{
if (len == 0)
return len;
DWORD status = thread->Status();
if (status & CURRENT_SELECT)
{
texts->AddText((LPWSTR)out, len / 2, false);
}
return len;
if (thread->Status() & CURRENT_SELECT) texts->AddText(output, false);
}
bool GetHookParam(DWORD pid, DWORD hook_addr, HookParam& hp)
@ -367,28 +360,21 @@ bool GetHookParam(DWORD pid, DWORD hook_addr, HookParam& hp)
return true;
}
std::wstring GetEntryString(TextThread& thread)
{
CHAR entry[512];
thread.GetEntryString(entry, 512);
return toUnicodeString(entry);
}
std::wstring CreateEntryWithLink(TextThread& thread, std::wstring& entry)
std::wstring CreateEntryWithLink(ThreadParameter tp, std::wstring& entry)
{
std::wstring entryWithLink = entry;
if (thread.PID() == 0)
if (tp.pid == 0)
entryWithLink += L"ConsoleOutput";
HookParam hp = {};
if (GetHookParam(thread.PID(), thread.Addr(), hp))
entryWithLink += L" (" + GetCode(hp, thread.PID()) + L")";
if (GetHookParam(tp.pid, tp.hook, hp))
entryWithLink += L" (" + GetCode(hp, tp.hook) + L")";
return entryWithLink;
}
void AddToCombo(TextThread& thread, bool replace)
{
std::wstring entry = GetEntryString(thread);
std::wstring entryWithLink = CreateEntryWithLink(thread, entry);
std::wstring entry = GetEntryString(&thread);
std::wstring entryWithLink = CreateEntryWithLink(thread.GetThreadParameter(), entry);
int i = ComboBox_FindString(hwndCombo, -1, entry.c_str());
if (replace)
{
@ -410,12 +396,10 @@ void AddToCombo(TextThread& thread, bool replace)
void RemoveFromCombo(TextThread* thread)
{
CHAR entry[512];
thread->GetEntryString(entry, 512);
std::wstring unicodeEntry = toUnicodeString(entry);
if (thread->PID() == 0)
unicodeEntry += L"ConsoleOutput";
int i = ComboBox_FindString(hwndCombo, 0, unicodeEntry.c_str());
std::wstring entry = GetEntryString(thread);
if (thread->GetThreadParameter().pid == 0)
entry += L"ConsoleOutput";
int i = ComboBox_FindString(hwndCombo, 0, entry.c_str());
if (i != CB_ERR)
{
if (ComboBox_DeleteString(hwndCombo, i) == CB_ERR)
@ -423,7 +407,7 @@ void RemoveFromCombo(TextThread* thread)
}
}
DWORD SetEditText(LPWSTR wc)
DWORD SetEditText(LPCWSTR wc)
{
DWORD line;
Edit_SetText(hwndEdit, wc);
@ -435,21 +419,16 @@ DWORD SetEditText(LPWSTR wc)
DWORD ThreadReset(TextThread* thread)
{
texts->ClearBuffer();
man->SetCurrent(thread);
thread->LockVector();
man->SetCurrent(thread);;
DWORD len = 0;
LPWSTR wc = (LPWSTR)thread->GetStore(&len);
len /= 2;
wc[len] = L'\0';
SetEditText(wc);
std::wstring text = thread->GetStore();
SetEditText(text.c_str());
WCHAR buffer[16];
std::swprintf(buffer, L"%04X", thread->Number());
DWORD tmp = ComboBox_FindString(hwndCombo, 0, buffer);
if (tmp != CB_ERR)
ComboBox_SetCurSel(hwndCombo, tmp);
thread->UnlockVector();
return 0;
}
@ -463,20 +442,20 @@ bool IsUnicodeHook(const ProcessRecord& pr, DWORD hook);
DWORD ThreadCreate(TextThread* thread)
{
thread->RegisterOutputCallBack(ThreadOutput, 0);
thread->RegisterOutputCallBack(ThreadOutput);
//thread->RegisterFilterCallBack(ThreadFilter, 0);
AddToCombo(*thread, false);
const auto& tp = thread->GetThreadParameter();
auto pr = man->GetProcessRecord(tp->pid);
auto tp = thread->GetThreadParameter();
auto pr = man->GetProcessRecord(tp.pid);
if (pr == NULL)
return 0;
if (IsUnicodeHook(*pr, tp->hook))
if (IsUnicodeHook(*pr, tp.hook))
thread->Status() |= USING_UNICODE;
auto pf = pfman->GetProfile(tp->pid);
auto pf = pfman->GetProfile(tp.pid);
if (!pf)
return 0;
const std::wstring& hook_name = GetHookNameByAddress(*pr, thread->GetThreadParameter()->hook);
auto thread_profile = pf->FindThread(thread->GetThreadParameter(), hook_name);
const std::wstring& hook_name = GetHookNameByAddress(*pr, thread->GetThreadParameter().hook);
auto thread_profile = pf->FindThread(&thread->GetThreadParameter(), hook_name);
if (thread_profile != pf->Threads().end())
{
(*thread_profile)->HookManagerIndex() = thread->Number();
@ -579,7 +558,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
man->RegisterThreadRemoveCallback(ThreadRemove);
man->RegisterThreadResetCallback(ThreadReset);
TextThread* console = man->FindSingle(0);
console->RegisterOutputCallBack(ThreadOutput, NULL);
console->RegisterOutputCallBack(ThreadOutput);
AddToCombo(*console, false);
man->RegisterProcessAttachCallback(RegisterProcess);
man->RegisterProcessDetachCallback(RemoveProcessList);

View File

@ -18,7 +18,7 @@
#include "profile/pugixml.h"
#include "profile/misc.h"
#define HM_LOCK CriticalSectionLocker d_locker(hmcs) // Synchronized scope for accessing private data
#define HM_LOCK CriticalSectionLocker locker(hmcs) // Synchronized scope for accessing private data
HookManager::HookManager() :
current(nullptr),
@ -27,12 +27,11 @@ HookManager::HookManager() :
reset(nullptr),
attach(nullptr),
detach(nullptr),
hook(nullptr),
new_thread_number(0),
textThreadsByParams(),
processRecordsByIds()
{
TextThread* consoleTextThread = textThreadsByParams[{0, -1UL, -1UL, -1UL}] = new TextThread({ 0, -1UL, -1UL, -1UL }, new_thread_number++, splitDelay);
TextThread* consoleTextThread = textThreadsByParams[{ 0, -1UL, -1UL, -1UL }] = new TextThread({ 0, -1UL, -1UL, -1UL }, new_thread_number++, splitDelay);
consoleTextThread->Status() |= USING_UNICODE;
SetCurrent(consoleTextThread);
@ -79,7 +78,7 @@ void HookManager::RemoveSingleHook(DWORD pid, DWORD addr)
std::vector<ThreadParameter> removedThreads;
for (auto i : textThreadsByParams)
{
if (i.second->PID() == pid && i.second->Addr() == addr)
if (i.first.pid == pid && i.first.hook == addr)
{
if (remove)
{
@ -102,7 +101,7 @@ void HookManager::RemoveProcessContext(DWORD pid)
std::vector<ThreadParameter> removedThreads;
for (auto i : textThreadsByParams)
{
if (i.second->PID() == pid)
if (i.first.hook == pid)
{
if (remove)
{
@ -274,11 +273,11 @@ void HookManager::AddThreadsToProfile(Profile& pf, const ProcessRecord& pr, DWOR
DWORD AddThreadToProfile(Profile& pf, const ProcessRecord& pr, TextThread* thread)
{
const ThreadParameter* tp = thread->GetThreadParameter();
std::wstring hook_name = GetHookNameByAddress(pr, tp->hook);
ThreadParameter tp = thread->GetThreadParameter();
std::wstring hook_name = GetHookNameByAddress(pr, tp.hook);
if (hook_name.empty())
return -1;
auto thread_profile = new ThreadProfile(hook_name, tp->retn, tp->spl, 0, 0,
auto thread_profile = new ThreadProfile(hook_name, tp.retn, tp.spl, 0, 0,
THREAD_MASK_RETN | THREAD_MASK_SPLIT, L"");
DWORD threads_size = pf.Threads().size();
int thread_profile_index = pf.AddThread(thread_ptr(thread_profile));

View File

@ -5,7 +5,7 @@
// Branch: ITH/HookManager.h, rev 133
#include "config.h"
#include "host/textthread.h"
#include "textthread.h"
#include "winmutex/winmutex.h"
#include <unordered_map>
#include <string>
@ -16,9 +16,6 @@ namespace pugi {
}
class Profile;
enum { MAX_REGISTER = 0xf };
enum { MAX_PREV_REPEAT_LENGTH = 0x20 };
struct ProcessRecord {
HANDLE process_handle;
HANDLE hookman_mutex;
@ -33,7 +30,8 @@ struct Hook
std::wstring name;
};
typedef DWORD (*ProcessEventCallback)(DWORD pid);
typedef DWORD(*ProcessEventCallback)(DWORD pid);
typedef DWORD(*ThreadEventCallback)(TextThread*);
struct ThreadParameterHasher
{
@ -67,27 +65,14 @@ public:
HANDLE GetHostPipe(DWORD pid);
ThreadEventCallback RegisterThreadCreateCallback(ThreadEventCallback cf)
{ return (ThreadEventCallback)_InterlockedExchange((long*)&create,(long)cf); }
ThreadEventCallback RegisterThreadRemoveCallback(ThreadEventCallback cf)
{ return (ThreadEventCallback)_InterlockedExchange((long*)&remove,(long)cf); }
ThreadEventCallback RegisterThreadResetCallback(ThreadEventCallback cf)
{ return (ThreadEventCallback)_InterlockedExchange((long*)&reset,(long)cf); }
ThreadEventCallback RegisterAddRemoveLinkCallback(ThreadEventCallback cf)
{ return (ThreadEventCallback)_InterlockedExchange((long*)&addRemoveLink, (long)cf); }
ProcessEventCallback RegisterProcessAttachCallback(ProcessEventCallback cf)
{ return (ProcessEventCallback)_InterlockedExchange((long*)&attach,(long)cf); }
ProcessEventCallback RegisterProcessDetachCallback(ProcessEventCallback cf)
{ return (ProcessEventCallback)_InterlockedExchange((long*)&detach,(long)cf); }
void RegisterThreadCreateCallback(ThreadEventCallback cf) { create = cf; }
void RegisterThreadRemoveCallback(ThreadEventCallback cf) { remove = cf; }
void RegisterThreadResetCallback(ThreadEventCallback cf) { reset = cf; }
void RegisterProcessAttachCallback(ProcessEventCallback cf) { attach = cf; }
void RegisterProcessDetachCallback(ProcessEventCallback cf) { detach = cf; }
void SetSplitInterval(unsigned int splitDelay) { this->splitDelay = splitDelay; }
void OnThreadCreate(pugi::xml_node profile_node, TextThread* thread);
void GetProfile(DWORD pid, pugi::xml_node profile_node);
private:
@ -100,11 +85,9 @@ private:
TextThread *current;
ThreadEventCallback create,
remove,
reset,
addRemoveLink;
reset;
ProcessEventCallback attach,
detach,
hook;
detach;
WORD register_count,
new_thread_number;

View File

@ -66,9 +66,9 @@ DWORD WINAPI TextReceiver(LPVOID lpThreadParameter)
{
case HOST_NOTIFICATION_NEWHOOK:
man->SetHook(processId,
((HookParam*)(buffer + sizeof(DWORD) * 2))->address,
((HookParam*)(buffer + sizeof(DWORD) * 2))->address, // Hook address
{
*(HookParam*)(buffer + sizeof(DWORD) * 2), // Hook address
*(HookParam*)(buffer + sizeof(DWORD) * 2), // Hook parameter
std::wstring(A2W(
(const char*)buffer + sizeof(DWORD) * 2 + sizeof(HookParam) // Hook name
))

View File

@ -14,69 +14,46 @@
#include "vnrhook/include/types.h"
#include <stdio.h>
#include "extensions/Extensions.h"
#include "winmutex/winmutex.h"
extern HookManager* man;
DWORD GetHookName(LPSTR str, DWORD pid, DWORD hook_addr, DWORD max)
{
if (!pid)
return 0;
DWORD len = 0;
max--; //for '\0' magic marker.
//if (pid == 0) {
// len = wcslen(HookNameInitTable[0]);
// if (len >= max)
// len = max;
// memcpy(str, HookNameInitTable[0], len << 1);
// str[len] = 0;
// return len;
//}
//::man->LockProcessHookman(pid);
ProcessRecord *pr = ::man->GetProcessRecord(pid);
if (!pr)
return 0;
WaitForSingleObject(pr->hookman_mutex, 0);
const OldHook *hks = (const OldHook *)pr->hookman_map;
for (int i = 0; i < MAX_HOOK; i++)
if (hks[i].Address() == hook_addr) {
len = hks[i].NameLength();
if (len >= max)
len = max;
ReadProcessMemory(pr->process_handle, hks[i].Name(), str, len, &len);
if (str[len - 1] == 0)
len--;
else
str[len] = 0;
break;
}
ReleaseMutex(pr->hookman_mutex);
//::man->UnlockProcessHookman(pid);
return len;
}
extern HWND dummyWindow;
#define TT_LOCK CriticalSectionLocker locker(ttCs) // Synchronized scope for accessing private data
TextThread::TextThread(ThreadParameter tp, unsigned int threadNumber, unsigned int splitDelay) :
thread_number(threadNumber),
storage(),
sentenceBuffer(),
status(0),
threadNumber(threadNumber),
splitDelay(splitDelay),
output(nullptr),
status(0),
tp(tp),
sentenceBuffer()
tp(tp)
{
InitializeCriticalSection(&ttCs);
}
TextThread::~TextThread()
{
TT_LOCK;
DeleteCriticalSection(&ttCs);
}
void TextThread::Reset()
{
MyVector::Reset();
TT_LOCK;
storage.clear();
}
std::wstring TextThread::GetStore()
{
TT_LOCK;
return storage;
}
void TextThread::AddSentence()
{
TT_LOCK;
std::wstring sentence;
if (status & USING_UNICODE)
{
@ -94,13 +71,15 @@ void TextThread::AddSentence()
void TextThread::AddSentence(std::wstring sentence)
{
TT_LOCK;
sentence.append(L"\r\n");
if (output) output(this, (const BYTE*)sentence.c_str(), sentence.length() * 2, false);
AddToStore((const BYTE*)sentence.c_str(), sentence.length() * 2);
if (output) output(this, sentence);
storage.append(sentence);
}
void TextThread::AddText(const BYTE *con, int len)
{
TT_LOCK;
sentenceBuffer.insert(sentenceBuffer.end(), con, con+len);
SetTimer(dummyWindow, (UINT_PTR)this, splitDelay,
[](HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
@ -110,11 +89,4 @@ void TextThread::AddText(const BYTE *con, int len)
});
}
void TextThread::GetEntryString(LPSTR buffer, DWORD max)
{
int len = sprintf(buffer, "%.4X:%.4d:0x%08X:0x%08X:0x%08X:",
thread_number, tp. pid, tp.hook, tp.retn, tp.spl);
GetHookName(buffer + len, tp.pid, tp.hook, max - len);
}
// EOF

View File

@ -4,7 +4,8 @@
// 8/23/2013 jichi
// Branch: ITH/TextThread.h, rev 120
#include "host/textthread_p.h"
#include <Windows.h>
#include "config.h"
#include <intrin.h> // require _InterlockedExchange
#include <string>
#include <vector>
@ -25,41 +26,37 @@ struct ThreadParameter {
#define CURRENT_SELECT 0x1000
class TextThread;
typedef DWORD (* ThreadOutputFilterCallback)(TextThread *,const BYTE *, DWORD, DWORD);
typedef DWORD (* ThreadEventCallback)(TextThread *);
typedef void(*ThreadOutputCallback)(TextThread*, std::wstring data);
//extern DWORD split_time,repeat_count,global_filter,cyclic_remove;
class TextThread : public MyVector<BYTE, 0x200>
class DLLEXPORT TextThread
{
public:
TextThread(ThreadParameter tp, unsigned int threadNumber, unsigned int splitDelay);
virtual void GetEntryString(LPSTR buffer, DWORD max);
~TextThread();
void Reset();
void AddText(const BYTE *con,int len);
void AddText(const BYTE *con, int len);
void AddSentence();
void AddSentence(std::wstring sentence);
BYTE *GetStore(DWORD *len) { if (len) *len = used; return storage; }
DWORD PID() const { return tp.pid; }
DWORD Addr() const {return tp.hook; }
std::wstring GetStore();
DWORD &Status() { return status; }
WORD Number() const { return thread_number; }
ThreadParameter *GetThreadParameter() { return &tp; }
WORD Number() const { return threadNumber; }
ThreadParameter GetThreadParameter() { return tp; }
//LPCWSTR GetComment() { return comment; }
ThreadOutputFilterCallback RegisterOutputCallBack(ThreadOutputFilterCallback cb, PVOID data)
{
return (ThreadOutputFilterCallback)_InterlockedExchange((long*)&output,(long)cb);
}
void RegisterOutputCallBack(ThreadOutputCallback cb) { output = cb; }
private:
ThreadParameter tp;
ThreadOutputFilterCallback output;
CRITICAL_SECTION ttCs;
ThreadOutputCallback output;
std::vector<char> sentenceBuffer;
unsigned int thread_number;
std::wstring storage;
ThreadParameter tp;
unsigned int threadNumber;
unsigned int splitDelay;
DWORD status;
};

View File

@ -1,98 +0,0 @@
#pragma once
// textthread_p.h
// 8/14/2013 jichi
// Branch: ITH/main_template.h, rev 66
#include <windows.h>
template<class T, int default_size>
class MyVector
{
public:
void LockVector() { EnterCriticalSection(&cs_store); }
void UnlockVector() { LeaveCriticalSection(&cs_store); }
MyVector() : size(default_size), used(0)
{
InitializeCriticalSection(&cs_store);
storage = new T[size];
// jichi 9/21/2013: zero memory
// This would cause trouble if T is not an atomic type
::memset(storage, 0, sizeof(T) * size);
}
virtual ~MyVector()
{
if (storage)
delete[] storage;
DeleteCriticalSection(&cs_store);
storage = 0;
}
protected:
void Reset()
{
EnterCriticalSection(&cs_store);
for (int i = 0; i < used; i++) {
//Release<T>(storage[i]);
storage[i] = T();
}
used = 0;
LeaveCriticalSection(&cs_store);
}
void Remove(int index)
{
if (index>=used)
return;
//Release<T>(storage[index]);
for (int i = index; i < used; i++)
storage[i] = storage[i+1];
used--;
}
void ClearMemory(int offset, int clear_size)
{
if (clear_size < 0)
return;
EnterCriticalSection(&cs_store);
if (offset+clear_size <= size)
::memset(storage+offset, 0, clear_size * sizeof(T)); // jichi 11/30/2013: This is the original code of ITH
LeaveCriticalSection(&cs_store);
//else __asm int 3
}
int AddToStore(const T *con,int amount)
{
if (amount <= 0 || con == 0)
return 0;
int status = 0;
EnterCriticalSection(&cs_store);
if (amount + used + 2 >= size) {
while (amount + used + 2 >= size)
size<<=1;
T *temp;
if (size * sizeof(T) < 0x1000000) {
temp = new T[size];
if (size > used)
::memset(temp, 0, (size - used) * sizeof(T)); // jichi 9/25/2013: zero memory
memcpy(temp, storage, used * sizeof(T));
} else {
size = default_size;
temp = new T[size];
::memset(temp, 0, sizeof(T) * size); // jichi 9/25/2013: zero memory
used = 0;
status = 1;
}
delete[] storage;
storage = temp;
}
memcpy(storage+used, con, amount * sizeof(T));
used += amount;
LeaveCriticalSection(&cs_store);
return status;
}
CRITICAL_SECTION cs_store;
int size,
used;
T *storage;
};
// EOF