reorganize files
This commit is contained in:
parent
2065359a4e
commit
48450f9717
@ -1,7 +1,7 @@
|
|||||||
#include "ProcessWindow.h"
|
#include "ProcessWindow.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "host/host.h"
|
#include "host.h"
|
||||||
#include "host/hookman.h"
|
#include "hookman.h"
|
||||||
#include "ProfileManager.h"
|
#include "ProfileManager.h"
|
||||||
#include "profile/Profile.h"
|
#include "profile/Profile.h"
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "ProfileManager.h"
|
#include "ProfileManager.h"
|
||||||
#include "profile/Profile.h"
|
#include "profile/Profile.h"
|
||||||
#include "host/host.h"
|
#include "host.h"
|
||||||
#include "host/hookman.h"
|
#include "hookman.h"
|
||||||
#include "vnrhook/include/types.h"
|
#include "vnrhook/include/types.h"
|
||||||
#include "vnrhook/include/const.h"
|
#include "vnrhook/include/const.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ITH.h"
|
#include "ITH.h"
|
||||||
#include "host/host.h"
|
#include "host.h"
|
||||||
#include "vnrhook/include/const.h"
|
#include "vnrhook/include/const.h"
|
||||||
#include "vnrhook/include/types.h"
|
#include "vnrhook/include/types.h"
|
||||||
#include "language.h"
|
#include "language.h"
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ITH.h"
|
#include "ITH.h"
|
||||||
#include "host/host.h"
|
#include "host.h"
|
||||||
#include "host/hookman.h"
|
#include "hookman.h"
|
||||||
#include "profile/Profile.h"
|
#include "profile/Profile.h"
|
||||||
#include "ProfileManager.h"
|
#include "ProfileManager.h"
|
||||||
|
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "host/host.h"
|
#include "host.h"
|
||||||
#include "host/hookman.h"
|
#include "hookman.h"
|
||||||
#include "vnrhook/include/types.h"
|
#include "vnrhook/include/types.h"
|
||||||
#include "vnrhook/include/const.h"
|
#include "vnrhook/include/const.h"
|
||||||
#include "profile/misc.h"
|
#include "profile/misc.h"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ITH.h"
|
#include "ITH.h"
|
||||||
#include "texthook/host/textthread.h"
|
#include "textthread.h"
|
||||||
|
|
||||||
struct HookParam;
|
struct HookParam;
|
||||||
struct ProcessRecord;
|
struct ProcessRecord;
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
#include "ProcessWindow.h"
|
#include "ProcessWindow.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "language.h"
|
#include "language.h"
|
||||||
#include "host/host.h"
|
#include "host.h"
|
||||||
#include "host/hookman.h"
|
#include "hookman.h"
|
||||||
#include "vnrhook/include/const.h"
|
#include "vnrhook/include/const.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "ProfileManager.h"
|
#include "ProfileManager.h"
|
||||||
|
@ -24,5 +24,5 @@ include_directories(
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(vnrhook)
|
add_subdirectory(vnrhook)
|
||||||
add_subdirectory(texthook/host)
|
add_subdirectory(texthook)
|
||||||
add_subdirectory(profile)
|
add_subdirectory(profile)
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "host/host.h"
|
#include "host.h"
|
||||||
#include "host/hookman.h"
|
#include "hookman.h"
|
||||||
#include "vnrhook/include/types.h"
|
#include "vnrhook/include/types.h"
|
||||||
#include "vnrhook/include/const.h"
|
#include "vnrhook/include/const.h"
|
||||||
#include "Profile.h"
|
#include "Profile.h"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "host/host.h"
|
#include "host.h"
|
||||||
#include "vnrhook/include/const.h"
|
#include "vnrhook/include/const.h"
|
||||||
#include "vnrhook/include/types.h"
|
#include "vnrhook/include/types.h"
|
||||||
|
|
||||||
|
@ -1,85 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// growl.h
|
|
||||||
// 9/17/2013 jichi
|
|
||||||
|
|
||||||
//#ifdef GROWL_HAS_GROWL
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#define GROWL_MSG_A(_msg) MessageBoxA(nullptr, _msg, "VNR Message", MB_OK)
|
|
||||||
#define GROWL_MSG(_msg) MessageBoxW(nullptr, _msg, L"VNR Message", MB_OK)
|
|
||||||
#define GROWL_WARN(_msg) MessageBoxW(nullptr, _msg, L"VNR Warning", MB_OK)
|
|
||||||
#define GROWL_ERROR(_msg) MessageBoxW(nullptr, _msg, L"VNR Error", MB_OK)
|
|
||||||
|
|
||||||
inline void GROWL_DWORD(DWORD value)
|
|
||||||
{
|
|
||||||
WCHAR buf[100];
|
|
||||||
swprintf(buf, L"DWORD: %x", value);
|
|
||||||
GROWL_MSG(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void GROWL_DWORD2(DWORD v, DWORD v2)
|
|
||||||
{
|
|
||||||
WCHAR buf[100];
|
|
||||||
swprintf(buf, L"DWORD2: %x,%x", v, v2);
|
|
||||||
GROWL_MSG(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void GROWL_DWORD3(DWORD v, DWORD v2, DWORD v3)
|
|
||||||
{
|
|
||||||
WCHAR buf[100];
|
|
||||||
swprintf(buf, L"DWORD3: %x,%x,%x", v, v2, v3);
|
|
||||||
GROWL_MSG(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void GROWL_DWORD4(DWORD v, DWORD v2, DWORD v3, DWORD v4)
|
|
||||||
{
|
|
||||||
WCHAR buf[100];
|
|
||||||
swprintf(buf, L"DWORD4: %x,%x,%x,%x", v, v2, v3, v4);
|
|
||||||
GROWL_MSG(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void GROWL_DWORD5(DWORD v, DWORD v2, DWORD v3, DWORD v4, DWORD v5)
|
|
||||||
{
|
|
||||||
WCHAR buf[100];
|
|
||||||
swprintf(buf, L"DWORD5: %x,%x,%x,%x,%x", v, v2, v3, v4, v5);
|
|
||||||
GROWL_MSG(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void GROWL_DWORD6(DWORD v, DWORD v2, DWORD v3, DWORD v4, DWORD v5, DWORD v6)
|
|
||||||
{
|
|
||||||
WCHAR buf[100];
|
|
||||||
swprintf(buf, L"DWORD6: %x,%x,%x,%x,%x,%x", v, v2, v3, v4, v5, v6);
|
|
||||||
GROWL_MSG(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void GROWL_DWORD7(DWORD v, DWORD v2, DWORD v3, DWORD v4, DWORD v5, DWORD v6, DWORD v7)
|
|
||||||
{
|
|
||||||
WCHAR buf[100];
|
|
||||||
swprintf(buf, L"DWORD7: %x,%x,%x,%x,%x,%x,%x", v, v2, v3, v4, v5, v6, v7);
|
|
||||||
GROWL_MSG(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void GROWL_DWORD8(DWORD v, DWORD v2, DWORD v3, DWORD v4, DWORD v5, DWORD v6, DWORD v7, DWORD v8)
|
|
||||||
{
|
|
||||||
WCHAR buf[100];
|
|
||||||
swprintf(buf, L"DWORD8: %x,%x,%x,%x,%x,%x,%x,%x", v, v2, v3, v4, v5, v6, v7, v8);
|
|
||||||
GROWL_MSG(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void GROWL_DWORD9(DWORD v, DWORD v2, DWORD v3, DWORD v4, DWORD v5, DWORD v6, DWORD v7, DWORD v8, DWORD v9)
|
|
||||||
{
|
|
||||||
WCHAR buf[100];
|
|
||||||
swprintf(buf, L"DWORD9: %x,%x,%x,%x,%x,%x,%x,%x,%x", v, v2, v3, v4, v5, v6, v7, v8, v9);
|
|
||||||
GROWL_MSG(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void GROWL(DWORD v) { GROWL_DWORD(v); }
|
|
||||||
inline void GROWL(LPCWSTR v) { GROWL_MSG(v); }
|
|
||||||
inline void GROWL(LPCSTR v) { GROWL_MSG_A(v); }
|
|
||||||
|
|
||||||
//#endif // GROWL_HAS_GROWL
|
|
||||||
|
|
||||||
// EOF
|
|
@ -6,7 +6,6 @@
|
|||||||
#include "vnrhook/include/const.h"
|
#include "vnrhook/include/const.h"
|
||||||
#include "vnrhook/include/defs.h"
|
#include "vnrhook/include/defs.h"
|
||||||
#include "vnrhook/include/types.h"
|
#include "vnrhook/include/types.h"
|
||||||
#include <string>
|
|
||||||
#include "extensions/Extensions.h"
|
#include "extensions/Extensions.h"
|
||||||
|
|
||||||
HANDLE preventDuplicationMutex;
|
HANDLE preventDuplicationMutex;
|
||||||
@ -15,11 +14,10 @@ HookManager* man;
|
|||||||
HWND dummyWindow;
|
HWND dummyWindow;
|
||||||
bool running;
|
bool running;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{ // unnamed
|
{ // unnamed
|
||||||
|
void GetDebugPrivileges() // Artikash 5/19/2018: Is it just me or is this function 100% superfluous?
|
||||||
void GetDebugPrivileges()
|
{
|
||||||
{ // Artikash 5/19/2018: Is it just me or is this function 100% superfluous?
|
|
||||||
HANDLE processToken;
|
HANDLE processToken;
|
||||||
TOKEN_PRIVILEGES Privileges = { 1, {0x14, 0, SE_PRIVILEGE_ENABLED} };
|
TOKEN_PRIVILEGES Privileges = { 1, {0x14, 0, SE_PRIVILEGE_ENABLED} };
|
||||||
|
|
||||||
@ -27,7 +25,6 @@ namespace
|
|||||||
AdjustTokenPrivileges(processToken, FALSE, &Privileges, 0, nullptr, nullptr);
|
AdjustTokenPrivileges(processToken, FALSE, &Privileges, 0, nullptr, nullptr);
|
||||||
CloseHandle(processToken);
|
CloseHandle(processToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
|
|
||||||
void CreateNewPipe();
|
void CreateNewPipe();
|
||||||
@ -39,14 +36,11 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID unused)
|
|||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
DisableThreadLibraryCalls(hinstDLL);
|
DisableThreadLibraryCalls(hinstDLL);
|
||||||
GetDebugPrivileges();
|
GetDebugPrivileges();
|
||||||
// jichi 12/20/2013: Since I already have a GUI, I don't have to InitCommonControls()
|
|
||||||
// Used by timers.
|
|
||||||
// InitCommonControls();
|
|
||||||
// jichi 8/24/2013: Create hidden window so that ITH can access timer and events
|
// jichi 8/24/2013: Create hidden window so that ITH can access timer and events
|
||||||
dummyWindow = CreateWindowW(L"Button", L"InternalWindow", 0, 0, 0, 0, 0, 0, 0, hinstDLL, 0);
|
dummyWindow = CreateWindowW(L"Button", L"InternalWindow", 0, 0, 0, 0, 0, 0, 0, hinstDLL, 0);
|
||||||
break;
|
break;
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
if (::running) CloseHost();
|
CloseHost();
|
||||||
DestroyWindow(dummyWindow);
|
DestroyWindow(dummyWindow);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -60,7 +54,7 @@ DLLEXPORT bool StartHost()
|
|||||||
preventDuplicationMutex = CreateMutexW(nullptr, TRUE, ITH_SERVER_MUTEX);
|
preventDuplicationMutex = CreateMutexW(nullptr, TRUE, ITH_SERVER_MUTEX);
|
||||||
if (GetLastError() == ERROR_ALREADY_EXISTS || ::running)
|
if (GetLastError() == ERROR_ALREADY_EXISTS || ::running)
|
||||||
{
|
{
|
||||||
GROWL_WARN(L"I am sorry that this game is attached by some other VNR ><\nPlease restart the game and try again!");
|
MessageBoxW(nullptr, L"I am sorry that this game is attached by some other VNR ><\nPlease restart the game and try again!", L"Error", MB_ICONERROR);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -114,7 +108,7 @@ DLLEXPORT bool InjectProcessById(DWORD processId, DWORD timeout)
|
|||||||
CloseHandle(processHandle);
|
CloseHandle(processHandle);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
man->AddConsoleOutput(L"couldn't inject dll");
|
man->AddConsoleOutput(L"couldn't inject dll");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -128,44 +122,41 @@ DLLEXPORT bool DetachProcessById(DWORD processId)
|
|||||||
|
|
||||||
DLLEXPORT void GetHostHookManager(HookManager** hookman)
|
DLLEXPORT void GetHostHookManager(HookManager** hookman)
|
||||||
{
|
{
|
||||||
if (::running)
|
*hookman = man;
|
||||||
{
|
|
||||||
*hookman = man;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DLLEXPORT DWORD InsertHook(DWORD pid, const HookParam *hp, std::string name)
|
DLLEXPORT bool InsertHook(DWORD pid, const HookParam *hp, std::string name)
|
||||||
{
|
|
||||||
HANDLE commandPipe = man->GetHostPipe(pid);
|
|
||||||
if (commandPipe == nullptr)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
BYTE buffer[PIPE_BUFFER_SIZE] = {};
|
|
||||||
*(DWORD*)buffer = HOST_COMMAND_NEW_HOOK;
|
|
||||||
*(HookParam*)(buffer + sizeof(DWORD)) = *hp;
|
|
||||||
if (name.size()) strcpy((char*)buffer + sizeof(DWORD) + sizeof(HookParam), name.c_str());
|
|
||||||
|
|
||||||
DWORD unused;
|
|
||||||
WriteFile(commandPipe, buffer, sizeof(DWORD) + sizeof(HookParam) + name.size(), &unused, nullptr);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DLLEXPORT DWORD RemoveHook(DWORD pid, DWORD addr)
|
|
||||||
{
|
{
|
||||||
HANDLE commandPipe = man->GetHostPipe(pid);
|
HANDLE commandPipe = man->GetHostPipe(pid);
|
||||||
if (commandPipe == nullptr) return -1;
|
if (commandPipe == nullptr) return false;
|
||||||
|
|
||||||
|
BYTE buffer[PIPE_BUFFER_SIZE] = {};
|
||||||
|
*(DWORD*)buffer = HOST_COMMAND_NEW_HOOK;
|
||||||
|
*(HookParam*)(buffer + sizeof(DWORD)) = *hp;
|
||||||
|
if (name.size()) strcpy((char*)buffer + sizeof(DWORD) + sizeof(HookParam), name.c_str());
|
||||||
|
DWORD unused;
|
||||||
|
WriteFile(commandPipe, buffer, sizeof(DWORD) + sizeof(HookParam) + name.size(), &unused, nullptr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DLLEXPORT bool RemoveHook(DWORD pid, DWORD addr)
|
||||||
|
{
|
||||||
|
HANDLE commandPipe = man->GetHostPipe(pid);
|
||||||
|
if (commandPipe == nullptr) return false;
|
||||||
|
|
||||||
HANDLE hookRemovalEvent = CreateEventW(nullptr, TRUE, FALSE, ITH_REMOVEHOOK_EVENT);
|
HANDLE hookRemovalEvent = CreateEventW(nullptr, TRUE, FALSE, ITH_REMOVEHOOK_EVENT);
|
||||||
|
|
||||||
BYTE buffer[sizeof(DWORD) * 2] = {};
|
BYTE buffer[sizeof(DWORD) * 2] = {};
|
||||||
*(DWORD*)buffer = HOST_COMMAND_REMOVE_HOOK;
|
*(DWORD*)buffer = HOST_COMMAND_REMOVE_HOOK;
|
||||||
*(DWORD*)(buffer + sizeof(DWORD)) = addr;
|
*(DWORD*)(buffer + sizeof(DWORD)) = addr;
|
||||||
|
|
||||||
DWORD unused;
|
DWORD unused;
|
||||||
WriteFile(commandPipe, buffer, sizeof(DWORD) * 2, &unused, nullptr);
|
WriteFile(commandPipe, buffer, sizeof(DWORD) * 2, &unused, nullptr);
|
||||||
WaitForSingleObject(hookRemovalEvent, 1000);
|
|
||||||
CloseHandle(hookRemovalEvent);
|
WaitForSingleObject(hookRemovalEvent, 1000);
|
||||||
man->RemoveSingleHook(pid, addr);
|
CloseHandle(hookRemovalEvent);
|
||||||
return 0;
|
|
||||||
|
man->RemoveSingleHook(pid, addr);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
//#include "host/settings.h"
|
//#include "host/settings.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "host/hookman.h"
|
#include "hookman.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
struct HookParam;
|
struct HookParam;
|
||||||
@ -17,7 +17,7 @@ DLLEXPORT void CloseHost();
|
|||||||
DLLEXPORT void GetHostHookManager(HookManager **hookman);
|
DLLEXPORT void GetHostHookManager(HookManager **hookman);
|
||||||
DLLEXPORT bool InjectProcessById(DWORD pid, DWORD timeout = 5000);
|
DLLEXPORT bool InjectProcessById(DWORD pid, DWORD timeout = 5000);
|
||||||
DLLEXPORT bool DetachProcessById(DWORD pid);
|
DLLEXPORT bool DetachProcessById(DWORD pid);
|
||||||
DLLEXPORT DWORD InsertHook(DWORD pid, const HookParam *hp, std::string name = "");
|
DLLEXPORT bool InsertHook(DWORD pid, const HookParam *hp, std::string name = "");
|
||||||
DLLEXPORT DWORD RemoveHook(DWORD pid, DWORD addr);
|
DLLEXPORT bool RemoveHook(DWORD pid, DWORD addr);
|
||||||
|
|
||||||
// EOF
|
// EOF
|
@ -7,8 +7,6 @@
|
|||||||
#include "hookman.h"
|
#include "hookman.h"
|
||||||
#include "vnrhook/include/defs.h"
|
#include "vnrhook/include/defs.h"
|
||||||
#include "vnrhook/include/const.h"
|
#include "vnrhook/include/const.h"
|
||||||
#include <stdio.h>
|
|
||||||
#include "growl.h"
|
|
||||||
#include <atlbase.h>
|
#include <atlbase.h>
|
||||||
|
|
||||||
extern HookManager* man;
|
extern HookManager* man;
|
||||||
@ -38,13 +36,6 @@ DWORD WINAPI TextReceiver(LPVOID lpThreadParameter)
|
|||||||
|
|
||||||
BYTE buffer[PIPE_BUFFER_SIZE] = {};
|
BYTE buffer[PIPE_BUFFER_SIZE] = {};
|
||||||
DWORD bytesRead, processId;
|
DWORD bytesRead, processId;
|
||||||
|
|
||||||
// Artikash 5/20/2018: Shouldn't Windows automatically close the handles when the host process stops running?
|
|
||||||
//if (!::running) {
|
|
||||||
// NtClose(hookPipe);
|
|
||||||
// return 0;
|
|
||||||
//}
|
|
||||||
|
|
||||||
ReadFile(pipes->hookPipe, &processId, sizeof(processId), &bytesRead, nullptr);
|
ReadFile(pipes->hookPipe, &processId, sizeof(processId), &bytesRead, nullptr);
|
||||||
man->RegisterProcess(processId, pipes->hostPipe);
|
man->RegisterProcess(processId, pipes->hostPipe);
|
||||||
|
|
||||||
@ -91,9 +82,7 @@ DWORD WINAPI TextReceiver(LPVOID lpThreadParameter)
|
|||||||
man->UnRegisterProcess(processId);
|
man->UnRegisterProcess(processId);
|
||||||
CloseHandle(pipes->hookPipe);
|
CloseHandle(pipes->hookPipe);
|
||||||
CloseHandle(pipes->hostPipe);
|
CloseHandle(pipes->hostPipe);
|
||||||
|
|
||||||
delete pipes;
|
delete pipes;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -69,9 +69,9 @@ void TextThread::AddSentence(std::wstring sentence)
|
|||||||
void TextThread::AddText(const BYTE *con, int len)
|
void TextThread::AddText(const BYTE *con, int len)
|
||||||
{
|
{
|
||||||
TT_LOCK;
|
TT_LOCK;
|
||||||
sentenceBuffer.insert(sentenceBuffer.end(), con, con+len);
|
sentenceBuffer.insert(sentenceBuffer.end(), con, con + len);
|
||||||
SetTimer(dummyWindow, (UINT_PTR)this, splitDelay,
|
SetTimer(dummyWindow, (UINT_PTR)this, splitDelay,
|
||||||
[](HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
|
[](HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
|
||||||
{
|
{
|
||||||
KillTimer(hWnd, idEvent);
|
KillTimer(hWnd, idEvent);
|
||||||
((TextThread*)idEvent)->AddSentence();
|
((TextThread*)idEvent)->AddSentence();
|
Loading…
Reference in New Issue
Block a user