forked from Public-Mirror/Textractor
Merge pull request #3 from Artikash/rewritetextthread
Rewrite textthread
This commit is contained in:
commit
2ea47a56cb
109
gui/window.cpp
109
gui/window.cpp
@ -128,10 +128,6 @@ BOOL CALLBACK OptionDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||||||
GetWindowText(GetDlgItem(hDlg, IDC_EDIT4), str, 0x80);
|
GetWindowText(GetDlgItem(hDlg, IDC_EDIT4), str, 0x80);
|
||||||
DWORD sd = std::stoul(str);
|
DWORD sd = std::stoul(str);
|
||||||
insert_delay = sd > 200 ? sd : 200;
|
insert_delay = sd > 200 ? sd : 200;
|
||||||
if (IsDlgButtonChecked(hDlg, IDC_CHECK6))
|
|
||||||
{
|
|
||||||
man->ResetRepeatStatus();
|
|
||||||
}
|
|
||||||
auto_inject = IsDlgButtonChecked(hDlg, IDC_CHECK1);
|
auto_inject = IsDlgButtonChecked(hDlg, IDC_CHECK1);
|
||||||
auto_insert = IsDlgButtonChecked(hDlg, IDC_CHECK2);
|
auto_insert = IsDlgButtonChecked(hDlg, IDC_CHECK2);
|
||||||
clipboard_flag = IsDlgButtonChecked(hDlg, IDC_CHECK3);
|
clipboard_flag = IsDlgButtonChecked(hDlg, IDC_CHECK3);
|
||||||
@ -376,58 +372,59 @@ void ClickButton(HWND hWnd, HWND h)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD ThreadFilter(TextThread* thread, BYTE* out, DWORD len, DWORD new_line, PVOID data, bool space)
|
// Artikash 6/10/2018: Removed because unused. Left commented to make cleaning up gui code easier later.
|
||||||
{
|
//DWORD ThreadFilter(TextThread* thread, BYTE* out, DWORD len, DWORD new_line, PVOID data, bool space)
|
||||||
DWORD status = thread->Status();
|
//{
|
||||||
if (global_filter && !new_line && thread->Number() != 0)
|
// DWORD status = thread->Status();
|
||||||
{
|
// if (global_filter && !new_line && thread->Number() != 0)
|
||||||
if (status & USING_UNICODE)
|
// {
|
||||||
{
|
// if (status & USING_UNICODE)
|
||||||
DWORD i, j;
|
// {
|
||||||
len /= 2;
|
// DWORD i, j;
|
||||||
LPWSTR str = (LPWSTR)out;
|
// len /= 2;
|
||||||
for (i = 0, j = 0; i < len; i++)
|
// LPWSTR str = (LPWSTR)out;
|
||||||
{
|
// for (i = 0, j = 0; i < len; i++)
|
||||||
WCHAR c = str[i];
|
// {
|
||||||
if (!uni_filter->Find(c))
|
// WCHAR c = str[i];
|
||||||
str[j++] = c;
|
// if (!uni_filter->Find(c))
|
||||||
}
|
// str[j++] = c;
|
||||||
memset(str + j, 0, (len - j) * 2);
|
// }
|
||||||
len = j * 2;
|
// memset(str + j, 0, (len - j) * 2);
|
||||||
}
|
// len = j * 2;
|
||||||
else
|
// }
|
||||||
{
|
// else
|
||||||
DWORD i, j;
|
// {
|
||||||
for (i = 0, j = 0; i < len; i++)
|
// DWORD i, j;
|
||||||
{
|
// for (i = 0, j = 0; i < len; i++)
|
||||||
WORD c = out[i];
|
// {
|
||||||
if (!IsDBCSLeadByte(c & 0xFF))
|
// WORD c = out[i];
|
||||||
{
|
// if (!IsDBCSLeadByte(c & 0xFF))
|
||||||
if (!mb_filter->Find(c))
|
// {
|
||||||
out[j++] = c & 0xFF;
|
// if (!mb_filter->Find(c))
|
||||||
}
|
// out[j++] = c & 0xFF;
|
||||||
else if (i + 1 < len)
|
// }
|
||||||
{
|
// else if (i + 1 < len)
|
||||||
|
// {
|
||||||
|
//
|
||||||
|
// c = out[i + 1];
|
||||||
|
// c <<= 8;
|
||||||
|
// c |= out[i];
|
||||||
|
// if (!mb_filter->Find(c))
|
||||||
|
// {
|
||||||
|
// out[j++] = c & 0xFF;
|
||||||
|
// out[j++] = c >> 8;
|
||||||
|
// }
|
||||||
|
// i++;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// memset(out + j, 0, len - j);
|
||||||
|
// len = j;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return len;
|
||||||
|
//}
|
||||||
|
|
||||||
c = out[i + 1];
|
DWORD ThreadOutput(TextThread* thread, BYTE* out, DWORD len, DWORD new_line, bool space)
|
||||||
c <<= 8;
|
|
||||||
c |= out[i];
|
|
||||||
if (!mb_filter->Find(c))
|
|
||||||
{
|
|
||||||
out[j++] = c & 0xFF;
|
|
||||||
out[j++] = c >> 8;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memset(out + j, 0, len - j);
|
|
||||||
len = j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD ThreadOutput(TextThread* thread, BYTE* out, DWORD len, DWORD new_line, PVOID data, bool space)
|
|
||||||
{
|
{
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return len;
|
return len;
|
||||||
@ -594,7 +591,7 @@ bool IsUnicodeHook(const ProcessRecord& pr, DWORD hook);
|
|||||||
DWORD ThreadCreate(TextThread* thread)
|
DWORD ThreadCreate(TextThread* thread)
|
||||||
{
|
{
|
||||||
thread->RegisterOutputCallBack(ThreadOutput, 0);
|
thread->RegisterOutputCallBack(ThreadOutput, 0);
|
||||||
thread->RegisterFilterCallBack(ThreadFilter, 0);
|
//thread->RegisterFilterCallBack(ThreadFilter, 0);
|
||||||
AddToCombo(*thread, false);
|
AddToCombo(*thread, false);
|
||||||
const auto& tp = thread->GetThreadParameter();
|
const auto& tp = thread->GetThreadParameter();
|
||||||
auto pr = man->GetProcessRecord(tp->pid);
|
auto pr = man->GetProcessRecord(tp->pid);
|
||||||
|
@ -88,21 +88,21 @@ bool operator==(const ThreadParameter& one, const ThreadParameter& two)
|
|||||||
#define NAMED_PIPE_DISCONNECT 1
|
#define NAMED_PIPE_DISCONNECT 1
|
||||||
//Class member of HookManger
|
//Class member of HookManger
|
||||||
HookManager::HookManager() :
|
HookManager::HookManager() :
|
||||||
// jichi 9/21/2013: Zero memory
|
// jichi 9/21/2013: Zero memory
|
||||||
//CRITICAL_SECTION hmcs;
|
//CRITICAL_SECTION hmcs;
|
||||||
current(nullptr)
|
current(nullptr)
|
||||||
, create(nullptr)
|
, create(nullptr)
|
||||||
, remove(nullptr)
|
, remove(nullptr)
|
||||||
, reset(nullptr)
|
, reset(nullptr)
|
||||||
, attach(nullptr)
|
, attach(nullptr)
|
||||||
, detach(nullptr)
|
, detach(nullptr)
|
||||||
, hook(nullptr)
|
, hook(nullptr)
|
||||||
, current_pid(0)
|
, current_pid(0)
|
||||||
, new_thread_number(0)
|
, new_thread_number(0)
|
||||||
, threadTable()
|
, threadTable()
|
||||||
, processRecordsByIds()
|
, processRecordsByIds()
|
||||||
{
|
{
|
||||||
TextThread* consoleTextThread = threadTable[{0, -1UL, -1UL, -1UL}] = new TextThread(0, -1, -1, -1, new_thread_number++);
|
TextThread* consoleTextThread = threadTable[{0, -1UL, -1UL, -1UL}] = new TextThread({ 0, -1UL, -1UL, -1UL }, new_thread_number++);
|
||||||
consoleTextThread->Status() |= USING_UNICODE;
|
consoleTextThread->Status() |= USING_UNICODE;
|
||||||
SetCurrent(consoleTextThread);
|
SetCurrent(consoleTextThread);
|
||||||
}
|
}
|
||||||
@ -304,7 +304,7 @@ void HookManager::DispatchText(DWORD pid, const BYTE *text, DWORD hook, DWORD re
|
|||||||
TextThread *it;
|
TextThread *it;
|
||||||
if (!(it = threadTable[tp]))
|
if (!(it = threadTable[tp]))
|
||||||
{
|
{
|
||||||
it = threadTable[tp] = new TextThread(pid, hook, retn, spl, new_thread_number++);
|
it = threadTable[tp] = new TextThread(tp, new_thread_number++);
|
||||||
if (create)
|
if (create)
|
||||||
{
|
{
|
||||||
create(it);
|
create(it);
|
||||||
@ -340,32 +340,6 @@ void HookManager::ClearCurrent()
|
|||||||
//LeaveCriticalSection(&hmcs);
|
//LeaveCriticalSection(&hmcs);
|
||||||
//ConsoleOutput("vnrhost:ClearCurrent: unlock");
|
//ConsoleOutput("vnrhost:ClearCurrent: unlock");
|
||||||
}
|
}
|
||||||
void HookManager::ResetRepeatStatus()
|
|
||||||
{
|
|
||||||
HM_LOCK;
|
|
||||||
//ConsoleOutput("vnrhost:ResetRepeatStatus: lock");
|
|
||||||
//EnterCriticalSection(&hmcs);
|
|
||||||
for (auto i : threadTable)
|
|
||||||
{
|
|
||||||
i.second->ResetRepeatStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
//LeaveCriticalSection(&hmcs);
|
|
||||||
//ConsoleOutput("vnrhost:ResetRepeatStatus: unlock");
|
|
||||||
}
|
|
||||||
//void HookManager::LockHookman(){ EnterCriticalSection(&hmcs); }
|
|
||||||
//void HookManager::UnlockHookman(){ LeaveCriticalSection(&hmcs); }
|
|
||||||
|
|
||||||
/*void HookManager::SetProcessEngineType(DWORD pid, DWORD type)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i=0;i<MAX_REGISTER;i++)
|
|
||||||
if (record[i].pid_register==pid) break;
|
|
||||||
if (i<MAX_REGISTER)
|
|
||||||
{
|
|
||||||
record[i].engine_register|=type;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
ProcessRecord *HookManager::GetProcessRecord(DWORD pid)
|
ProcessRecord *HookManager::GetProcessRecord(DWORD pid)
|
||||||
{
|
{
|
||||||
|
@ -49,7 +49,6 @@ public:
|
|||||||
ProcessRecord *GetProcessRecord(DWORD pid);
|
ProcessRecord *GetProcessRecord(DWORD pid);
|
||||||
//void LockHookman();
|
//void LockHookman();
|
||||||
//void UnlockHookman();
|
//void UnlockHookman();
|
||||||
void ResetRepeatStatus();
|
|
||||||
void ClearCurrent();
|
void ClearCurrent();
|
||||||
void SelectCurrent(DWORD num);
|
void SelectCurrent(DWORD num);
|
||||||
void SetCurrent(TextThread *it);
|
void SetCurrent(TextThread *it);
|
||||||
|
@ -43,82 +43,19 @@ void CALLBACK NewLineBuff(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
|
|||||||
id->SetNewLineFlag();
|
id->SetNewLineFlag();
|
||||||
}
|
}
|
||||||
|
|
||||||
// jichi 10/27/2013: removed
|
TextThread::TextThread(ThreadParameter tp, WORD num) :
|
||||||
//void CALLBACK NewLineConsole(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
|
|
||||||
//{
|
|
||||||
// KillTimer(hwnd,idEvent);
|
|
||||||
// TextThread *id=(TextThread*)idEvent;
|
|
||||||
// if (id->Status()&USING_UNICODE)
|
|
||||||
// id->AddText((BYTE*)L"\r\n",4,true,true);
|
|
||||||
// if (id->Status()&CURRENT_SELECT)
|
|
||||||
// {
|
|
||||||
// //texts->SetLine();
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
// jichi 10/27/2013: removed
|
|
||||||
//void ReplaceSentence(BYTE* text, int len)
|
|
||||||
//{
|
|
||||||
// __asm int 3
|
|
||||||
//}
|
|
||||||
|
|
||||||
TextThread::TextThread(DWORD id, DWORD hook, DWORD retn, DWORD spl, WORD num) :
|
|
||||||
//,tp
|
//,tp
|
||||||
thread_number(num)
|
thread_number(num)
|
||||||
// jichi 9/21/2013: zero all fields
|
|
||||||
, link_number(-1)
|
|
||||||
, last (0)
|
|
||||||
, align_space(0)
|
|
||||||
, repeat_single(0)
|
|
||||||
, repeat_single_current(0)
|
|
||||||
, repeat_single_count(0)
|
|
||||||
, repeat_detect_count(0)
|
|
||||||
, head(new RepeatCountNode())
|
|
||||||
, link(nullptr)
|
|
||||||
//, filter(nullptr)
|
|
||||||
, output(nullptr)
|
, output(nullptr)
|
||||||
, app_data(nullptr)
|
|
||||||
//, comment(nullptr)
|
//, comment(nullptr)
|
||||||
, thread_string(nullptr)
|
|
||||||
, timer(0)
|
, timer(0)
|
||||||
, status (0)
|
, status (0)
|
||||||
, repeat_detect_limit(0x80)
|
|
||||||
, last_sentence(0)
|
, last_sentence(0)
|
||||||
, prev_sentence(0)
|
|
||||||
, sentence_length(0)
|
, sentence_length(0)
|
||||||
, repeat_index(0)
|
, tp(tp)
|
||||||
, last_time(0)
|
|
||||||
// , tp({id, hook, retn, spl})
|
|
||||||
{
|
{
|
||||||
tp.pid = id;
|
|
||||||
tp.hook = hook;
|
|
||||||
tp.retn = retn;
|
|
||||||
tp.spl = spl;
|
|
||||||
//head = new RepeatCountNode;
|
|
||||||
//::memset(head, 0, sizeof(RepeatCountNode)); // jichi 9/21/2013: zero memory
|
|
||||||
//link_number = -1;
|
|
||||||
//repeat_detect_limit = 0x80;
|
|
||||||
//filter = nullptr;
|
|
||||||
//output = nullptr;
|
|
||||||
}
|
|
||||||
TextThread::~TextThread()
|
|
||||||
{
|
|
||||||
//KillTimer(dummyWindow,timer);
|
|
||||||
RepeatCountNode *t = head,
|
|
||||||
*tt;
|
|
||||||
while (t) {
|
|
||||||
tt = t;
|
|
||||||
t = tt->next;
|
|
||||||
delete tt;
|
|
||||||
}
|
|
||||||
head = nullptr;
|
|
||||||
//if (comment) {
|
|
||||||
// delete[] comment;
|
|
||||||
// comment = nullptr;
|
|
||||||
//}
|
|
||||||
if (thread_string)
|
|
||||||
delete[] thread_string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextThread::Reset()
|
void TextThread::Reset()
|
||||||
{
|
{
|
||||||
//timer=0;
|
//timer=0;
|
||||||
@ -129,339 +66,31 @@ void TextThread::Reset()
|
|||||||
//}
|
//}
|
||||||
MyVector::Reset();
|
MyVector::Reset();
|
||||||
}
|
}
|
||||||
void TextThread::RemoveSingleRepeatAuto(const BYTE *con, int &len)
|
|
||||||
{
|
|
||||||
#ifdef ITH_DISABLE_REPEAT // jichi 9/28/2013: only for debugging purpose
|
|
||||||
return;
|
|
||||||
#endif // ITH_DISABLE_REPEAT
|
|
||||||
WORD *text = (WORD *)con;
|
|
||||||
if (len <= 2) {
|
|
||||||
if (repeat_single) {
|
|
||||||
if (repeat_single_count<repeat_single&&
|
|
||||||
last == *text) {
|
|
||||||
len = 0;
|
|
||||||
repeat_single_count++;
|
|
||||||
} else {
|
|
||||||
last = *text;
|
|
||||||
repeat_single_count=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (status & REPEAT_NUMBER_DECIDED) {
|
|
||||||
if (++repeat_detect_count>MIN_REDETECT) {
|
|
||||||
repeat_detect_count = 0;
|
|
||||||
status ^= REPEAT_NUMBER_DECIDED;
|
|
||||||
last = 0;
|
|
||||||
RepeatCountNode *t = head,
|
|
||||||
*tt;
|
|
||||||
while (t) {
|
|
||||||
tt = t;
|
|
||||||
t = tt->next;
|
|
||||||
delete tt;
|
|
||||||
}
|
|
||||||
head = new RepeatCountNode;
|
|
||||||
::memset(head, 0, sizeof(RepeatCountNode)); // jichi 9/21/2013: zero memory
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
repeat_detect_count++;
|
|
||||||
if (last == *text)
|
|
||||||
repeat_single_current++;
|
|
||||||
else {
|
|
||||||
if (last == 0) {
|
|
||||||
last = *text;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (repeat_single_current == 0) {
|
|
||||||
status |= REPEAT_NUMBER_DECIDED;
|
|
||||||
repeat_single = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
last = *text;
|
|
||||||
RepeatCountNode *it = head;
|
|
||||||
if (repeat_detect_count > MIN_DETECT) {
|
|
||||||
while (it = it->next)
|
|
||||||
if (it->count>head->count) {
|
|
||||||
head->count=it->count;
|
|
||||||
head->repeat=it->repeat;
|
|
||||||
}
|
|
||||||
repeat_single = head->repeat;
|
|
||||||
repeat_single_current = 0;
|
|
||||||
repeat_detect_count = 0;
|
|
||||||
status |= REPEAT_NUMBER_DECIDED;
|
|
||||||
DWORD repeat_sc = repeat_single*4;
|
|
||||||
if (repeat_sc > MIN_DETECT) {
|
|
||||||
MIN_DETECT <<= 1;
|
|
||||||
MIN_REDETECT <<= 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bool flag=true;
|
|
||||||
while (it) {
|
|
||||||
if (it->repeat == repeat_single_current) {
|
|
||||||
it->count++;
|
|
||||||
flag = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
it=it->next;
|
|
||||||
}
|
|
||||||
if (flag) {
|
|
||||||
RepeatCountNode *n = new RepeatCountNode;
|
|
||||||
n->count = 1;
|
|
||||||
n->repeat = repeat_single_current;
|
|
||||||
n->next = head->next;
|
|
||||||
head->next = n;
|
|
||||||
}
|
|
||||||
repeat_single_current = 0;
|
|
||||||
} //Decide repeat_single
|
|
||||||
} //Check Repeat
|
|
||||||
} //repeat_single decided?
|
|
||||||
} //len
|
|
||||||
else {
|
|
||||||
status |= REPEAT_NUMBER_DECIDED;
|
|
||||||
repeat_single = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextThread::RemoveSingleRepeatForce(BYTE *con,int &len)
|
|
||||||
{
|
|
||||||
// jichi 9/1/2013: manual repetition count removed
|
|
||||||
WORD *text = (WORD *)con;
|
|
||||||
//if (repeat_single_count<setman->GetValue(SETTING_REPEAT_COUNT)&&last==*text) {
|
|
||||||
// len=0;
|
|
||||||
// repeat_single_count++;
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
{
|
|
||||||
last = *text;
|
|
||||||
repeat_single_count=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void TextThread::RemoveCyclicRepeat(BYTE* &con, int &len)
|
|
||||||
{
|
|
||||||
DWORD current_time = GetTickCount();
|
|
||||||
if (status & REPEAT_SUPPRESS) {
|
|
||||||
if (current_time - last_time < (unsigned)settings->splittingInterval &&
|
|
||||||
::memcmp(storage + last_sentence + repeat_index, con, len) == 0) {
|
|
||||||
repeat_index += len;
|
|
||||||
if (repeat_index>=sentence_length)
|
|
||||||
repeat_index -= sentence_length;
|
|
||||||
len = 0;
|
|
||||||
} else {
|
|
||||||
repeat_index = 0;
|
|
||||||
status &= ~REPEAT_SUPPRESS;
|
|
||||||
}
|
|
||||||
} else if (status & REPEAT_DETECT) {
|
|
||||||
if (::memcmp(storage + last_sentence + repeat_index, con, len) == 0) {
|
|
||||||
int half_length=repeat_index+len;
|
|
||||||
if (::memcmp(storage + last_sentence, storage + last_sentence + half_length, repeat_index) == 0) {
|
|
||||||
len=0;
|
|
||||||
sentence_length=half_length;
|
|
||||||
status&=~REPEAT_DETECT;
|
|
||||||
status|=REPEAT_SUPPRESS;
|
|
||||||
|
|
||||||
// jichi 10/27/2013: Not used
|
|
||||||
//if (status&CURRENT_SELECT)
|
|
||||||
// ReplaceSentence(storage+last_sentence+half_length,repeat_index);
|
|
||||||
ClearMemory(last_sentence+half_length,repeat_index);
|
|
||||||
used-=repeat_index;
|
|
||||||
repeat_index=0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
repeat_index += len;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
repeat_index=0;
|
|
||||||
status &= ~REPEAT_DETECT;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (sentence_length == 0)
|
|
||||||
return;
|
|
||||||
else if (len <= (int)sentence_length) {
|
|
||||||
if (memcmp(storage + last_sentence, con, len) == 0) {
|
|
||||||
status |= REPEAT_DETECT;
|
|
||||||
repeat_index = len;
|
|
||||||
if (repeat_index == sentence_length) {
|
|
||||||
repeat_index = 0;
|
|
||||||
len = 0;
|
|
||||||
}
|
|
||||||
} else if (sentence_length > repeat_detect_limit) {
|
|
||||||
if (len > 2) {
|
|
||||||
DWORD u = used;
|
|
||||||
while (memcmp(storage + u - len, con, len) == 0)
|
|
||||||
u -= len;
|
|
||||||
ClearMemory(u, used - u);
|
|
||||||
used = u;
|
|
||||||
repeat_index = 0;
|
|
||||||
// jichi 10/27/2013: Not used
|
|
||||||
//if (status & CURRENT_SELECT)
|
|
||||||
// ReplaceSentence(storage + last_sentence, used - u);
|
|
||||||
status |= REPEAT_SUPPRESS;
|
|
||||||
len = 0;
|
|
||||||
} else if (len <= 2)
|
|
||||||
{
|
|
||||||
WORD tmp = *(WORD *)(storage + last_sentence);
|
|
||||||
DWORD index, last_index, tmp_len;
|
|
||||||
index = used-len;
|
|
||||||
if (index < last_sentence)
|
|
||||||
index = last_sentence;
|
|
||||||
//Locate position of current input.
|
|
||||||
_again:
|
|
||||||
*(WORD *)(storage+last_sentence) = *(WORD *)con;
|
|
||||||
while (*(WORD *)(storage + index) != *(WORD *)con)
|
|
||||||
index--;
|
|
||||||
*(WORD *)(storage + last_sentence) = tmp;
|
|
||||||
if (index > last_sentence) {
|
|
||||||
tmp_len = used - index;
|
|
||||||
if (tmp_len <= 2) {
|
|
||||||
repeat_detect_limit += 0x40;
|
|
||||||
last_time = current_time;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (index - last_sentence >= tmp_len &&
|
|
||||||
memcmp(storage + index - tmp_len, storage + index, tmp_len) == 0) {
|
|
||||||
repeat_detect_limit = 0x80;
|
|
||||||
sentence_length =tmp_len;
|
|
||||||
index -= tmp_len;
|
|
||||||
while (memcmp(storage + index - sentence_length, storage + index, sentence_length) == 0)
|
|
||||||
index -= sentence_length;
|
|
||||||
repeat_index = 2;
|
|
||||||
len = 0;
|
|
||||||
last_index = index;
|
|
||||||
if (status&USING_UNICODE) {
|
|
||||||
while (storage[index] == storage[index + sentence_length])
|
|
||||||
index -= 2;
|
|
||||||
index += 2;
|
|
||||||
while (true) {
|
|
||||||
tmp = *(WORD *)(storage + index);
|
|
||||||
if (tmp >= 0x3000 && tmp < 0x3020)
|
|
||||||
index += 2;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DWORD last_char_len;
|
|
||||||
while (storage[index] == storage[index + sentence_length]) {
|
|
||||||
last_char_len = LeadByteTable[storage[index]];
|
|
||||||
index -= last_char_len;
|
|
||||||
}
|
|
||||||
index += last_char_len;
|
|
||||||
while (storage[index] == 0x81) {
|
|
||||||
if ((storage[index+1]>>4) == 4)
|
|
||||||
index += 2;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
repeat_index += last_index - index;
|
|
||||||
status |= REPEAT_SUPPRESS;
|
|
||||||
last_sentence = index;
|
|
||||||
|
|
||||||
index += sentence_length;
|
|
||||||
// jichi 10/27/2013: Not used
|
|
||||||
//if (status&CURRENT_SELECT)
|
|
||||||
// ReplaceSentence(storage + index, used - index);
|
|
||||||
|
|
||||||
ClearMemory(index, used - index);
|
|
||||||
//memset(storage + index, 0, used - index);
|
|
||||||
used = index;
|
|
||||||
} else {
|
|
||||||
index--;
|
|
||||||
goto _again;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
repeat_detect_limit += 0x40;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
last_time = current_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextThread::ResetRepeatStatus()
|
|
||||||
{
|
|
||||||
last=0;
|
|
||||||
repeat_single=0;
|
|
||||||
repeat_single_current=0;
|
|
||||||
repeat_single_count=0;
|
|
||||||
repeat_detect_count=0;
|
|
||||||
RepeatCountNode *t = head->next,
|
|
||||||
*tt;
|
|
||||||
while (t) {
|
|
||||||
tt = t;
|
|
||||||
t = tt->next;
|
|
||||||
delete tt;
|
|
||||||
}
|
|
||||||
//head=new RepeatCountNode;
|
|
||||||
head->count = head->repeat = 0;
|
|
||||||
status &= ~REPEAT_NUMBER_DECIDED;
|
|
||||||
}
|
|
||||||
void TextThread::AddLineBreak()
|
void TextThread::AddLineBreak()
|
||||||
{
|
{
|
||||||
if (sentence_length == 0) return;
|
if (sentence_length == 0) return;
|
||||||
if (status&BUFF_NEWLINE)
|
if (status&BUFF_NEWLINE)
|
||||||
{
|
{
|
||||||
prev_sentence=last_sentence;
|
|
||||||
sentence_length=0;
|
sentence_length=0;
|
||||||
if (status & USING_UNICODE)
|
if (status & USING_UNICODE)
|
||||||
AddToStore((BYTE *)L"\r\n\r\n", 8);
|
AddToStore((BYTE *)L"\r\n\r\n", 8);
|
||||||
else
|
else
|
||||||
AddToStore((BYTE *)"\r\n\r\n", 4);
|
AddToStore((BYTE *)"\r\n\r\n", 4);
|
||||||
if (output)
|
if (output)
|
||||||
output(this, 0, 8, TRUE, app_data, false); // jichi 10/27/2013: space is false
|
output(this, 0, 8, TRUE, false); // jichi 10/27/2013: space is false
|
||||||
last_sentence = used;
|
last_sentence = used;
|
||||||
status &= ~BUFF_NEWLINE;
|
status &= ~BUFF_NEWLINE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void TextThread::AddText(const BYTE *con, int len, bool new_line, bool space)
|
void TextThread::AddText(const BYTE *con, int len, bool new_line, bool space)
|
||||||
{
|
{
|
||||||
if (!con || (len <= 0 && !space))
|
|
||||||
return;
|
|
||||||
if (len && !new_line) {
|
|
||||||
// jichi 9/1/2013: manual repetition count removed
|
|
||||||
//if (setman->GetValue(SETTING_REPEAT_COUNT)) {
|
|
||||||
// status|=REPEAT_NUMBER_DECIDED;
|
|
||||||
// RemoveSingleRepeatForce(con,len);
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
RemoveSingleRepeatAuto(con, len);
|
|
||||||
if (len <= 0 && !space)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 9/1/2013: manual repetition count removed
|
|
||||||
//if(setman->GetValue(SETTING_CYCLIC_REMOVE)) {
|
|
||||||
// //if (status & REPEAT_NUMBER_DECIDED)
|
|
||||||
// RemoveCyclicRepeat(con,len);
|
|
||||||
//}
|
|
||||||
//if (len <= 0)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// jichi 10/27/2013: User-defined filter callback is disabled
|
|
||||||
//if (filter)
|
|
||||||
// len = filter(this, con,len, new_line, app_data);
|
|
||||||
//if (len <= 0)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
if (len && sentence_length == 0) {
|
|
||||||
if (status & USING_UNICODE) {
|
|
||||||
if (*(WORD *)con == 0x3000) { // jichi 10/27/2013: why skip unicode space?!
|
|
||||||
con += 2;
|
|
||||||
len -= 2;
|
|
||||||
}
|
|
||||||
} else if (*(WORD *)con == 0x4081) {
|
|
||||||
con += 2;
|
|
||||||
len -= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len <= 0 && !space)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status & BUFF_NEWLINE)
|
if (status & BUFF_NEWLINE)
|
||||||
AddLineBreak();
|
AddLineBreak();
|
||||||
|
|
||||||
if (len)
|
if (len)
|
||||||
if (new_line) {
|
if (new_line) {
|
||||||
prev_sentence = last_sentence;
|
|
||||||
last_sentence = used + 4;
|
last_sentence = used + 4;
|
||||||
if (status & USING_UNICODE)
|
if (status & USING_UNICODE)
|
||||||
last_sentence += 4;
|
last_sentence += 4;
|
||||||
@ -471,9 +100,10 @@ void TextThread::AddText(const BYTE *con, int len, bool new_line, bool space)
|
|||||||
sentence_length += len;
|
sentence_length += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (len <= 0) return;
|
||||||
BYTE *data = const_cast<BYTE *>(con); // jichi 10/27/2013: TODO: Figure out where con is modified
|
BYTE *data = const_cast<BYTE *>(con); // jichi 10/27/2013: TODO: Figure out where con is modified
|
||||||
if (output)
|
if (output)
|
||||||
len = output(this, data, len, new_line, app_data, space);
|
len = output(this, data, len, new_line, space);
|
||||||
if (AddToStore(data, len)) {
|
if (AddToStore(data, len)) {
|
||||||
//sentence_length += len;
|
//sentence_length += len;
|
||||||
/*ResetRepeatStatus();
|
/*ResetRepeatStatus();
|
||||||
@ -485,54 +115,11 @@ void TextThread::AddText(const BYTE *con, int len, bool new_line, bool space)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextThread::AddTextDirect(const BYTE* con, int len, bool space) // Add to store directly, penetrating repetition filters.
|
void TextThread::GetEntryString(LPSTR buffer, DWORD max)
|
||||||
{
|
{
|
||||||
// jichi 10/27/2013: Accordig to the logic, both len and con must be > 0
|
int len = sprintf(buffer, "%.4X:%.4d:0x%08X:0x%08X:0x%08X:",
|
||||||
if (status & BUFF_NEWLINE)
|
|
||||||
AddLineBreak();
|
|
||||||
//SetNewLineTimer();
|
|
||||||
sentence_length += len;
|
|
||||||
|
|
||||||
BYTE *data = const_cast<BYTE *>(con); // jichi 10/27/2013: TODO: Figure out where con is modified
|
|
||||||
if (output)
|
|
||||||
len = output(this, data, len, false, app_data, space);
|
|
||||||
AddToStore(data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD TextThread::GetEntryString(LPSTR str, DWORD max)
|
|
||||||
{
|
|
||||||
DWORD len = 0;
|
|
||||||
if (str && max > 0x40) {
|
|
||||||
max--;
|
|
||||||
if (thread_string) {
|
|
||||||
len = ::strlen(thread_string);
|
|
||||||
len = len < max ? len : max;
|
|
||||||
memcpy(str, thread_string, len);
|
|
||||||
str[len] = 0;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
len = ::sprintf(str, "%.4X:%.4d:0x%08X:0x%08X:0x%08X:",
|
|
||||||
thread_number, tp. pid, tp.hook, tp.retn, tp.spl);
|
thread_number, tp. pid, tp.hook, tp.retn, tp.spl);
|
||||||
|
GetHookName(buffer + len, tp.pid, tp.hook, max - len);
|
||||||
len += GetHookName(str + len, tp.pid, tp.hook, max - len);
|
|
||||||
thread_string = new char[len + 1];
|
|
||||||
//::memset(thread_string, 0, (len+1) * sizeof(wchar_t)); // jichi 9/26/2013: zero memory
|
|
||||||
thread_string[len] = 0;
|
|
||||||
::memcpy(thread_string, str, len);
|
|
||||||
}
|
|
||||||
//if (comment) {
|
|
||||||
// str += len;
|
|
||||||
// max--;
|
|
||||||
// DWORD cl = wcslen(comment);
|
|
||||||
// if (len + cl >= max)
|
|
||||||
// cl = max - len;
|
|
||||||
// *str++ = L'-';
|
|
||||||
// memcpy(str, comment, cl << 1);
|
|
||||||
// str[cl] = 0;
|
|
||||||
// len += cl;
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
// jichi 9/28/2013: removed
|
// jichi 9/28/2013: removed
|
||||||
//void TextThread::CopyLastSentence(LPWSTR str)
|
//void TextThread::CopyLastSentence(LPWSTR str)
|
||||||
@ -631,50 +218,6 @@ void TextThread::DispatchLastSentence()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//void TextThread::ResetEditText()
|
|
||||||
//{
|
|
||||||
// //__asm int 3;
|
|
||||||
// WCHAR str[0x20];
|
|
||||||
// swprintf(str,L"%.8X",_ReturnAddress());
|
|
||||||
//}
|
|
||||||
|
|
||||||
// jichi 9/25/2013: Removed
|
|
||||||
//void TextThread::ExportTextToFile(LPWSTR) //filename)
|
|
||||||
//{
|
|
||||||
// HANDLE hFile=IthCreateFile(filename,FILE_WRITE_DATA,0,FILE_OPEN_IF);
|
|
||||||
// if (hFile==INVALID_HANDLE_VALUE) return;
|
|
||||||
// EnterCriticalSection(&cs_store);
|
|
||||||
// IO_STATUS_BLOCK ios;
|
|
||||||
// LPVOID buffer=storage;
|
|
||||||
// DWORD len=used;
|
|
||||||
// BYTE bom[4]={0xFF,0xFE,0,0};
|
|
||||||
// LARGE_INTEGER offset={2,0};
|
|
||||||
// if ((status&USING_UNICODE)==0)
|
|
||||||
// {
|
|
||||||
// len=MB_WC_count((char*)storage,used);
|
|
||||||
// buffer = new wchar_t[len+1];
|
|
||||||
// MB_WC((char*)storage,(wchar_t*)buffer);
|
|
||||||
// len<<=1;
|
|
||||||
// }
|
|
||||||
// NtWriteFile(hFile,0,0,0,&ios,bom,2,0,0);
|
|
||||||
// NtWriteFile(hFile,0,0,0,&ios,buffer,len,&offset,0);
|
|
||||||
// NtFlushBuffersFile(hFile,&ios);
|
|
||||||
// if (buffer !=storage)
|
|
||||||
// delete[] buffer;
|
|
||||||
// NtClose(hFile);
|
|
||||||
// LeaveCriticalSection(&cs_store);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//void TextThread::SetComment(LPWSTR str)
|
|
||||||
//{
|
|
||||||
// if (comment)
|
|
||||||
// delete[] comment;
|
|
||||||
// size_t sz = wcslen(str);
|
|
||||||
// comment = new wchar_t[sz + 1];
|
|
||||||
// comment[sz] = 0;
|
|
||||||
// wcscpy(comment, str);
|
|
||||||
//}
|
|
||||||
|
|
||||||
void TextThread::SetNewLineFlag() { status |= BUFF_NEWLINE; }
|
void TextThread::SetNewLineFlag() { status |= BUFF_NEWLINE; }
|
||||||
|
|
||||||
void TextThread::SetNewLineTimer()
|
void TextThread::SetNewLineTimer()
|
||||||
@ -686,32 +229,4 @@ void TextThread::SetNewLineTimer()
|
|||||||
timer = SetTimer(dummyWindow, (UINT_PTR)this, settings->splittingInterval, NewLineBuff);
|
timer = SetTimer(dummyWindow, (UINT_PTR)this, settings->splittingInterval, NewLineBuff);
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD TextThread::GetThreadString(LPSTR str, DWORD max)
|
|
||||||
{
|
|
||||||
DWORD len = 0;
|
|
||||||
if (max) {
|
|
||||||
char buffer[0x200];
|
|
||||||
char c;
|
|
||||||
if (thread_string == nullptr)
|
|
||||||
GetEntryString(buffer, 0x200); //This will allocate thread_string.
|
|
||||||
LPSTR end = thread_string;
|
|
||||||
for (; *end; end++);
|
|
||||||
c = thread_string[0];
|
|
||||||
thread_string[0] = ':';
|
|
||||||
LPSTR p1 = end;
|
|
||||||
for (; *p1 != ':'; p1--);
|
|
||||||
thread_string[0] = c;
|
|
||||||
if (p1 == thread_string)
|
|
||||||
return 0;
|
|
||||||
p1++;
|
|
||||||
len = end - p1;
|
|
||||||
if (len >= max)
|
|
||||||
len = max - 1;
|
|
||||||
::memcpy(str, p1, len);
|
|
||||||
str[len] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
@ -34,7 +34,7 @@ struct ThreadParameter {
|
|||||||
class TextThread;
|
class TextThread;
|
||||||
typedef void (* ConsoleCallback)(LPCSTR text);
|
typedef void (* ConsoleCallback)(LPCSTR text);
|
||||||
typedef void (* ConsoleWCallback)(LPCWSTR text);
|
typedef void (* ConsoleWCallback)(LPCWSTR text);
|
||||||
typedef DWORD (* ThreadOutputFilterCallback)(TextThread *, BYTE *, DWORD, DWORD, PVOID, bool space); // jichi 10/27/2013: Add space
|
typedef DWORD (* ThreadOutputFilterCallback)(TextThread *, BYTE *, DWORD, DWORD, bool space); // jichi 10/27/2013: Add space
|
||||||
typedef DWORD (* ThreadEventCallback)(TextThread *);
|
typedef DWORD (* ThreadEventCallback)(TextThread *);
|
||||||
|
|
||||||
//extern DWORD split_time,repeat_count,global_filter,cyclic_remove;
|
//extern DWORD split_time,repeat_count,global_filter,cyclic_remove;
|
||||||
@ -42,33 +42,15 @@ typedef DWORD (* ThreadEventCallback)(TextThread *);
|
|||||||
class TextThread : public MyVector<BYTE, 0x200>
|
class TextThread : public MyVector<BYTE, 0x200>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TextThread(DWORD pid, DWORD hook, DWORD retn, DWORD spl, WORD num);
|
TextThread(ThreadParameter tp, WORD num);
|
||||||
~TextThread();
|
|
||||||
//virtual void CopyLastSentence(LPWSTR str);
|
|
||||||
//virtual void SetComment(LPWSTR);
|
|
||||||
//virtual void ExportTextToFile(LPWSTR filename);
|
|
||||||
|
|
||||||
virtual DWORD GetThreadString(LPSTR str, DWORD max);
|
virtual void GetEntryString(LPSTR buffer, DWORD max);
|
||||||
virtual DWORD GetEntryString(LPSTR str, DWORD max = 0x200);
|
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
void AddText(const BYTE *con,int len, bool new_line, bool space); // jichi 10/27/2013: add const; remove console; add space
|
void AddText(const BYTE *con,int len, bool new_line, bool space); // jichi 10/27/2013: add const; remove console; add space
|
||||||
void RemoveSingleRepeatAuto(const BYTE *con, int &len); // jichi 10/27/2013: add const
|
|
||||||
void RemoveSingleRepeatForce(BYTE *con, int &len);
|
|
||||||
void RemoveCyclicRepeat(BYTE *&con, int &len);
|
|
||||||
void ResetRepeatStatus();
|
|
||||||
void AddLineBreak();
|
void AddLineBreak();
|
||||||
//void ResetEditText();
|
|
||||||
void ComboSelectCurrent();
|
|
||||||
void UnLinkAll();
|
|
||||||
void DispatchLastSentence();
|
void DispatchLastSentence();
|
||||||
|
|
||||||
//void AdjustPrevRepeat(DWORD len);
|
|
||||||
//void PrevRepeatLength(DWORD &len);
|
|
||||||
|
|
||||||
//bool AddToCombo();
|
|
||||||
bool RemoveFromCombo();
|
|
||||||
|
|
||||||
void SetNewLineFlag();
|
void SetNewLineFlag();
|
||||||
void SetNewLineTimer();
|
void SetNewLineTimer();
|
||||||
|
|
||||||
@ -78,56 +60,23 @@ public:
|
|||||||
DWORD Addr() const {return tp.hook; }
|
DWORD Addr() const {return tp.hook; }
|
||||||
DWORD &Status() { return status; }
|
DWORD &Status() { return status; }
|
||||||
WORD Number() const { return thread_number; }
|
WORD Number() const { return thread_number; }
|
||||||
WORD &Last() { return last; }
|
|
||||||
WORD &LinkNumber() { return link_number; }
|
|
||||||
UINT_PTR &Timer() { return timer; }
|
|
||||||
ThreadParameter *GetThreadParameter() { return &tp; }
|
ThreadParameter *GetThreadParameter() { return &tp; }
|
||||||
//LPCWSTR GetComment() { return comment; }
|
//LPCWSTR GetComment() { return comment; }
|
||||||
|
|
||||||
ThreadOutputFilterCallback RegisterOutputCallBack(ThreadOutputFilterCallback cb, PVOID data)
|
ThreadOutputFilterCallback RegisterOutputCallBack(ThreadOutputFilterCallback cb, PVOID data)
|
||||||
{
|
{
|
||||||
app_data = data;
|
|
||||||
return (ThreadOutputFilterCallback)_InterlockedExchange((long*)&output,(long)cb);
|
return (ThreadOutputFilterCallback)_InterlockedExchange((long*)&output,(long)cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadOutputFilterCallback RegisterFilterCallBack(ThreadOutputFilterCallback cb, PVOID data)
|
|
||||||
{
|
|
||||||
app_data = data;
|
|
||||||
return (ThreadOutputFilterCallback)_InterlockedExchange((long*)&filter,(long)cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetRepeatFlag() { status |= CYCLIC_REPEAT; }
|
|
||||||
void ClearNewLineFlag() { status &= ~BUFF_NEWLINE; }
|
|
||||||
void ClearRepeatFlag() { status &= ~CYCLIC_REPEAT; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void AddTextDirect(const BYTE *con, int len, bool space); // jichi 10/27/2013: add const; add space; change to protected
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ThreadParameter tp;
|
ThreadParameter tp;
|
||||||
|
|
||||||
WORD thread_number,
|
WORD thread_number;
|
||||||
link_number;
|
|
||||||
WORD last,
|
|
||||||
align_space;
|
|
||||||
WORD repeat_single;
|
|
||||||
WORD repeat_single_current;
|
|
||||||
WORD repeat_single_count;
|
|
||||||
WORD repeat_detect_count;
|
|
||||||
RepeatCountNode *head;
|
|
||||||
|
|
||||||
TextThread *link;
|
|
||||||
ThreadOutputFilterCallback filter; // jichi 10/27/2013: Remove filter
|
|
||||||
ThreadOutputFilterCallback output;
|
ThreadOutputFilterCallback output;
|
||||||
PVOID app_data;
|
|
||||||
LPSTR thread_string;
|
|
||||||
UINT_PTR timer;
|
UINT_PTR timer;
|
||||||
DWORD status,repeat_detect_limit;
|
DWORD status;
|
||||||
DWORD last_sentence,
|
DWORD last_sentence,
|
||||||
prev_sentence,
|
sentence_length;
|
||||||
sentence_length,
|
|
||||||
repeat_index,
|
|
||||||
last_time;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
Loading…
x
Reference in New Issue
Block a user