|
You last visited: Today at 23:10
Advertisement
changing chat text color ?
Discussion on changing chat text color ? within the Silkroad Online forum part of the Popular Games category.
08/08/2009, 19:41
|
#1
|
elite*gold: 0
Join Date: Feb 2008
Posts: 2
Received Thanks: 0
|
changing chat text color ?
is it possible to change chat text color ?
i tried to search but i didn't find anything.
|
|
|
08/08/2009, 20:44
|
#2
|
elite*gold: 260
Join Date: Aug 2008
Posts: 560
Received Thanks: 3,779
|
Quote:
Originally Posted by lalalagirl
is it possible to change chat text color ?
i tried to search but i didn't find anything.
|
I wrote code to do it a long time ago. The first way I did it was to perform client edits via WriteProcessMemory through a secondary program. That would work for all chat types except for All Chat right now due to how the client code is setup.
The second method I used was to create a codecave in the client to process the chat color logic. You can get the current chat type and then specify a custom color for it. That is much easier to work with, but requires the use of a loader and injected DLL. You could use my guides to do it though but I'm not going to myself.
Here's the code in the latest 205 client that has to deal with chat colors.
Code:
007A37C7 . 8078 04 00 CMP BYTE PTR DS:[EAX+4],0
007A37CB .^ 0F84 B2FEFFFF JE sro_clie.007A3683
007A37D1 > BD FEFF9FFF MOV EBP,FF9FFFFE ; Case A of switch 007A37B3
007A37D6 . EB 34 JMP SHORT sro_clie.007A380C
007A37D8 > BD 00FFFFFF MOV EBP,-100 ; Case 6 of switch 007A37B3
007A37DD . EB 2D JMP SHORT sro_clie.007A380C
007A37DF > BD C3AEFFFF MOV EBP,FFFFAEC3 ; Cases 3,7 of switch 007A37B3
007A37E4 . EB 26 JMP SHORT sro_clie.007A380C
007A37E6 > BD 41B5FFFF MOV EBP,FFFFB541 ; Case 5 of switch 007A37B3
007A37EB . EB 1F JMP SHORT sro_clie.007A380C
007A37ED > BD 73F5C2FF MOV EBP,FFC2F573 ; Case B of switch 007A37B3
007A37F2 . EB 18 JMP SHORT sro_clie.007A380C
007A37F4 > BD D0FF9AFF MOV EBP,FF9AFFD0 ; Case 4 of switch 007A37B3
007A37F9 . EB 11 JMP SHORT sro_clie.007A380C
007A37FB > BD F8ADDBFF MOV EBP,FFDBADF8 ; Case D of switch 007A37B3
007A3800 . EB 0A JMP SHORT sro_clie.007A380C
007A3802 > BD FFC764FF MOV EBP,FF64C7FF ; Case 10 of switch 007A37B3
007A3807 . EB 03 JMP SHORT sro_clie.007A380C
007A3809 > 83CD FF OR EBP,FFFFFFFF ; Default case of switch 007A37B3
007A380C > B8 07000000 MOV EAX,7
You should be able to follow the colors in a graphics program that allows you to use hex/decimal for RGB. The colors are stored backwards in memory so FEFF9FFF is color (ARGB) FF 9F FF FE, or the color for whisper chat.
Here's the updated code to the project I wrote back in Feb. 07. The concept is pretty simple. Just write out the new hex values for the colors in the Silkroad process. You need to be running the program in Administrator in Vista/Win7 as well.
SilkroadChatColor.cpp
Code:
#include "cProcess.h"
#include <windows.h>
#include <math.h>
#include <stdio.h>
#include <fstream>
#include <sstream>
// Main program window
HWND hwnd = 0;
// Array of addresses to make for easier access
unsigned long addrs[6];
unsigned long defs[6];
unsigned long curs[6];
HWND hwnds[6];
HWND preview[6];
// Whisper
HWND lblWhisper = 0;
HWND editWhisper = 0;
HWND btnDefWhisper = 0;
unsigned long addrWhisper = 0x7A37D1;
unsigned long defColorWhisper = 0xFF9FFFFE;
// Global
HWND lblGlobal = 0;
HWND editGlobal = 0;
HWND btnDefGlobal = 0;
unsigned long addrGlobal = 0x7A37D8;
unsigned long defColorGlobal = 0xFFFFFF00;
// Notice
HWND lblNotice = 0;
HWND editNotice = 0;
HWND btnDefNotice = 0;
unsigned long addrNotice = 0x7A37DF;
unsigned long defColorNotice = 0xFFFFAEC3;
// Guild
HWND lblGuild = 0;
HWND editGuild = 0;
HWND btnDefGuild = 0;
unsigned long addrGuild = 0x7A37E6;
unsigned long defColorGuild = 0xFFFFB541;
// Union
HWND lblUnion = 0;
HWND editUnion = 0;
HWND btnDefUnion = 0;
unsigned long addrUnion = 0x7A37ED;
unsigned long defColorUnion = 0xFFC2F573;
// Party
HWND lblParty = 0;
HWND editParty = 0;
HWND btnDefParty = 0;
unsigned long addrParty = 0x7A37F4;
unsigned long defColorParty = 0xFF9AFFD0;
// Set chat color button
HWND btnColorize = 0;
HWND btnPerm = 0;
// Get the current color a chat type
HWND btnGetWhisper = 0;
HWND btnGetGlobal = 0;
HWND btnGetNotice = 0;
HWND btnGetGuild = 0;
HWND btnGetUnion = 0;
HWND btnGetParty = 0;
HWND btnGetAll = 0;
// Defines for the button messages
#define BTN_DEF_COLOR_WHISPER 1
#define BTN_DEF_COLOR_GLOBAL 2
#define BTN_DEF_COLOR_NOTICE 3
#define BTN_DEF_COLOR_GUILD 4
#define BTN_DEF_COLOR_UNION 5
#define BTN_DEF_COLOR_PARTY 6
#define BTN_DEF_COLOR_ALL 7
#define BTN_COLORIZE_ON 8
#define BTN_COLORIZE_GET 9
#define BTN_PREVIEW_COLOR_WHSIPER 11
#define BTN_PREVIEW_COLOR_GLOBAL 12
#define BTN_PREVIEW_COLOR_NOTICE 13
#define BTN_PREVIEW_COLOR_GUILD 14
#define BTN_PREVIEW_COLOR_UNION 15
#define BTN_PREVIEW_COLOR_PARTY 16
#define BTN_PREVIEW_COLOR_ALL 17
#define BTN_GET_COLOR_WHISPER 18
#define BTN_GET_COLOR_GLOBAL 19
#define BTN_GET_COLOR_NOTICE 20
#define BTN_GET_COLOR_GUILD 21
#define BTN_GET_COLOR_UNION 22
#define BTN_GET_COLOR_PARTY 23
#define BTN_GET_COLOR_ALL 24
// cProcess class object used to make working with processes a lot easier ;)
cProcess sro;
unsigned long CaptionToHex(HWND h)
{
// Store the actual hex string
unsigned char data[5] = {0};
// Store the ascii-hex string
char temp[32] = {0};
// The alpha should be FF, opaque (don't think font supports alpha)
temp[0] = 'F';
temp[1] = 'F';
// Get the desired window's color
GetWindowText(h, temp + 2, 7);
// Store the final value
int value = 0;
// We have to reverse the digits for hex form
int index = 3;
// Loop though all tuples of characters
for(int y = 0; y < 8; y += 2)
{
int tuple1 = 15, tuple2 = 15;
// Store current character
unsigned char cur = temp[y];
// If it's A - F, convert it to 10 - 15
if(cur >= 'A' && cur <= 'F')
tuple1 = cur - 'A' + 10;
// If it's 0 - 9, convert it to 0 - 9
else if(cur >= '0' && cur <= '9')
tuple1 = cur - '0';
// Store current character
cur = temp[y + 1];
// If it's A - F, convert it to 10 - 15
if(cur >= 'A' && cur <= 'F')
tuple2 = cur - 'A' + 10;
// If it's 0 - 9, convert it to 0 - 9
else if(cur >= '0' && cur <= '9')
tuple2 = cur - '0';
// Convert the two numbers into a unsigned character
value = tuple2 + 16 * tuple1;
// Store the final color value for this color component
data[index--] = value;
}
// Store a pointer of the final color value as a unsigned long
unsigned long* ptr = (unsigned long*)data;
return *ptr;
}
void DrawColorPreview(HDC hdc, int x, int y, unsigned long color)
{
color = color & 0x00FFFFFF;
HBRUSH NewBrush = CreateSolidBrush(RGB(GetBValue(color),GetGValue(color),GetRValue(color)));
SelectObject(hdc, NewBrush);
Rectangle(hdc, x, y, x + 18, y + 18);
DeleteObject(NewBrush);
}
// Get the current chat colors
void GetCurrentChatColors(int x)
{
// Array to hold the data
unsigned char buffer[5] = {0};
// Read in the memory location
if(!sro.ReadArray(addrs[x], buffer, 5))
{
MessageBox(hwnd, "Memory address could not be read.", "Fatal Error", MB_OK | MB_ICONERROR);
return;
}
char temp[256] = {0};
// Store the color components into the array
_snprintf(temp, 255, "%.2X%.2X%.2X", buffer[3], buffer[2], buffer[1]);
// Write the entire RGB color string to the edit box
SetWindowText(hwnds[x], temp);
}
void GeneratePreview(HWND btn, int button)
{
curs[button] = CaptionToHex(btn);
RECT r;
r.left = 284;
r.right = r.left + 18;
r.top = 10 + button * 30;
r.bottom = r.top + 18;
InvalidateRect(hwnd, &r, true);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT Ps;
HDC hdc;
switch(msg)
{
case WM_PAINT:
{
hdc = BeginPaint(hwnd, &Ps);
for(int x = 0; x < 6; ++x)
DrawColorPreview(hdc, 284, 10 + x * 30, curs[x]);
EndPaint(hwnd, &Ps);
}
break;
case WM_COMMAND:
{
if(LOWORD(wParam) == BTN_COLORIZE_ON)
{
// Loop though all chat colors
for(int x = 0; x < 6; ++x)
{
int ptr = CaptionToHex(hwnds[x]);
// Write the color value to memory
sro.Write(addrs[x] + 1, ptr);
}
}
else if(LOWORD(wParam) >= BTN_GET_COLOR_WHISPER && LOWORD(wParam) <= BTN_GET_COLOR_ALL)
{
int button = LOWORD(wParam) - BTN_GET_COLOR_WHISPER;
GetCurrentChatColors(button);
GeneratePreview(hwnds[button], button);
}
else if(LOWORD(wParam) >= BTN_DEF_COLOR_WHISPER && LOWORD(wParam) <= BTN_DEF_COLOR_ALL)
{
// Save the real button #
int button = LOWORD(wParam) - 1;
// Buffer to hold the default value
char temp[256] = {0};
// Save the default value to the buffer
sprintf(temp, "%X", defs[button]);
// Write the default value to the window
SetWindowText(hwnds[button], temp + 2);
GeneratePreview(hwnds[button], button);
}
else if(LOWORD(wParam) >= BTN_PREVIEW_COLOR_WHSIPER && LOWORD(wParam) <= LOWORD(wParam))
{
int button = LOWORD(wParam) - BTN_PREVIEW_COLOR_WHSIPER;
GeneratePreview(hwnds[button], button);
}
}
break;
case WM_CLOSE:
{
DestroyWindow(hwnd);
}
break;
case WM_DESTROY:
{
PostQuitMessage(0);
}
break;
default:
{
return DefWindowProc(hwnd, msg, wParam, lParam);
}
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc = {0};
MSG msg = {0};
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(0);
wc.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(101));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+6);
wc.lpszMenuName = NULL;
wc.lpszClassName = "SROChatColor";
wc.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(101), IMAGE_ICON, 16, 16, 0);;
// Win32 stuff to create the program
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONERROR | MB_OK);
return 0;
}
// Create main window
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "SROChatColor", "Silkroad Chat Color - By: Drew Benton", WS_OVERLAPPEDWINDOW ^ WS_MAXIMIZEBOX ^ WS_THICKFRAME, CW_USEDEFAULT, CW_USEDEFAULT, 480, 290, NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONERROR | MB_OK);
return 0;
}
// Try to open the sro client
if(!sro.Open("sro_client.exe"))
{
MessageBox(0, "Cannot find your sro_client.exe", "Error!", MB_ICONERROR | MB_OK);
return -1;
}
// Store the addresses
addrs[0] = addrWhisper;
addrs[1] = addrGlobal;
addrs[2] = addrNotice;
addrs[3] = addrGuild;
addrs[4] = addrUnion;
addrs[5] = addrParty;
//addrs[6] = addrAll;
// Store default colors
defs[0] = defColorWhisper;
defs[1] = defColorGlobal;
defs[2] = defColorNotice;
defs[3] = defColorGuild;
defs[4] = defColorUnion;
defs[5] = defColorParty;
//defs[6] = defColorAll;
// Store defaults
for(int x = 0; x < 6; ++x)
curs[x] = defs[x];
// Coords of controls
int X = 0; int Y = 0; int W = 0; int H = 0;
// Whisper
X = 10; Y = 10; W = 125; H = 20;
lblWhisper = CreateWindowEx(0, "STATIC", "Whisper Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 110;
editWhisper = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 312; W = 70;
btnDefWhisper = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_WHISPER, NULL, 0);
X = 392;
btnGetWhisper = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_WHISPER, NULL, 0);
X = 250; W = 24;
preview[0] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_WHSIPER, NULL, 0);
// Global
X = 10; Y = 40; W = 125; H = 20;
lblGlobal = CreateWindowEx(0, "STATIC", "Global Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 110;
editGlobal = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 312; W = 70;
btnDefWhisper = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_GLOBAL, NULL, 0);
X = 392;
btnGetGlobal = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_GLOBAL, NULL, 0);
X = 250; W = 24;
preview[1] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_GLOBAL, NULL, 0);
// Notice
X = 10; Y = 70; W = 125; H = 20;
lblNotice = CreateWindowEx(0, "STATIC", "Notice Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 110;
editNotice = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 312; W = 70;
btnDefNotice = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_NOTICE, NULL, 0);
X = 392;
btnGetNotice = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_NOTICE, NULL, 0);
X = 250; W = 24;
preview[2] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_NOTICE, NULL, 0);
// Guild
X = 10; Y = 100; W = 125; H = 20;
lblGuild = CreateWindowEx(0, "STATIC", "Guild Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 110;
editGuild = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 312; W = 70;
btnDefGuild = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_GUILD, NULL, 0);
X = 392;
btnGetGuild = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_GUILD, NULL, 0);
X = 250; W = 24;
preview[3] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_GUILD, NULL, 0);
// Union
X = 10; Y = 130; W = 125; H = 20;
lblUnion = CreateWindowEx(0, "STATIC", "Union Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 110;
editUnion = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 312; W = 70;
btnDefUnion = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_UNION, NULL, 0);
X = 392;
btnGetUnion = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_UNION, NULL, 0);
X = 250; W = 24;
preview[4] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_UNION, NULL, 0);
// Party
X = 10; Y = 160; W = 125; H = 20;
lblParty = CreateWindowEx(0, "STATIC", "Party Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 110;
editParty = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 312; W = 70;
btnDefParty = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_PARTY, NULL, 0);
X = 392;
btnGetParty = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_PARTY, NULL, 0);
X = 250; W = 24;
preview[5] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_PARTY, NULL, 0);
// Set chat color button
X = 312; Y = 220; W = 150; H = 30;
btnColorize = CreateWindowEx(0, "BUTTON", "Change Chat Colors!", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_COLORIZE_ON, NULL, 0);
// Store the edit handles to make life easier
hwnds[0] = editWhisper;
hwnds[1] = editGlobal;
hwnds[2] = editNotice;
hwnds[3] = editGuild;
hwnds[4] = editUnion;
hwnds[5] = editParty;
//hwnds[6] = editAll;
// Start the program out by getting the current colors stored in memory
for(int x = 0; x < 6; ++x)
GetCurrentChatColors(x);
// Reactivate this program
SetForegroundWindow(hwnd);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
WaitMessage();
}
}
return 0;
}
cProcess.h
Code:
/*****************************************************************************/
/* cProcess
/* By; Drew Benton
/*
/* This class was written to make working with processes a lot easier. With
/* this class, the user will be able to open a process and read from memory
/* or write to memory. It is designed with simplicty and ease of use in mind.
/* If you have any questions or comments e-mail me at
/*
/******************************************************************************/
#ifndef CPROCESS_H_
#define CPROCESS_H_
#include <windows.h>
#include <tlhelp32.h>
#include <string>
// Display the current error to the user via a message box
void ShowError(LPTSTR lpszFunction);
// The callback function used for processing HWNDs
BOOL CALLBACK enumCallbackFunc(HWND hwnd, LPARAM lparam);
class cProcess
{
public:
// The process entry for the process
PROCESSENTRY32 pe32;
// Handle to the process
HANDLE handle;
// One of the HWNDs associated with the process
HWND hwnd;
public:
/******************************************************************************************/
// MEMBER FUNCTIONS REFERENCE //
/******************************************************************************************/
/* // This is the constructor for the cProcess class.
/* cProcess();
/* // This is the destructor for the cProcess class.
/* ~cProcess();
/*
/* // This function will open the desired executable's process.
/* bool Open(
/* const std::string& exeName,
/* bool lookForWindow = true,
/* DWORD dwDesiredAccess = PROCESS_ALL_ACCESS,
/* BOOL bInhereitHandle = FALSE);
/*
/* // This function will close the opened process.
/* void Close();
/*
/* // This function will read exactly 'one' unit of the passed datatype specified.
/* template <class type>
/* bool Read(
/* unsigned long address,
/* type& buffer);
/*
/* // This function will read exactly sizeOfBuffer units of the
/* // passed datatype specified or until 'stopValue' is read.
/* template <class type>
/* bool ReadArray(
/* unsigned long address,
/* type* buffer,
/* int sizeOfBuffer,
/* type stopValue);
/*
/* // This function will read exactly sizeOfBuffer units of the passed datatype specified.
/* template <class type>
/* bool ReadArray(
/* unsigned long address,
/* type* buffer,
/* int sizeOfBuffer);
/*
/* // This function will write the passed variable to memory.
/* template <class type>
/* bool Write(
/* unsigned long address,
/* type& buffer);
/*
/* // This function will write the buffer of passed datatype
/* // specified into the memory address specificed.
/* template <class type>
/* bool WriteArray(
/* unsigned long address,
/* type* buffer,
/* int sizeOfBuffer);
/*****************************************************************************************/
/******************************************************************************************/
// MEMBER FUNCTION IMPLEMENTATIONS //
/******************************************************************************************/
/**************************************************************************/
/* Function: cProcess */
/* */
/* Description: This is the constructor for the cProcess class. */
/* */
/* Return Type: None */
/* */
/* Parameters: None */
/**************************************************************************/
cProcess::cProcess()
{
// Simply clear all the memory of our variables
handle = 0;
hwnd = 0;
ZeroMemory(&pe32, sizeof(PROCESSENTRY32));
// This is a must in Win32 for this struct!
pe32.dwSize = sizeof(PROCESSENTRY32);
}
/**************************************************************************/
/* Function: cProcess */
/* */
/* Description: This is the destructor for the cProcess class. */
/* */
/* Return Type: None */
/* */
/* Parameters: None */
/**************************************************************************/
cProcess::~cProcess()
{
// Call the Close function on object destruction
Close();
}
/**************************************************************************/
/* Function: Open */
/* */
/* Description: This function will open the desired executable's process.*/
/* Since there could be many processes with the same executable, a */
/* feature exsits to help the user select the correct window. The hwnd is*/
/* activated and the user replies to a message box as to if it is correct*/
/* */
/* Return Type: bool: true = success, false = failure */
/* */
/* Parameters: */
/* const string& exeName - This parameter is the executable file of */
/* the process we with to open. */
/* bool lookForWindow - Should the class find the main HWND */
/* [Default: true] */
/* DWORD dwDesiredAccess - This is the optional desired access flag */
/* used to open the process. */
/* [Default: PROCESS_ALL_ACCESS] */
/* BOOL bInhereitHandle - This is the optional desired flag used to */
/* open the process */
/* [Default: FALSE] */
/**************************************************************************/
bool Open(const std::string& exeName, bool lookForWindow = true, DWORD dwDesiredAccess = PROCESS_ALL_ACCESS, BOOL bInhereitHandle = FALSE)
{
/****************************************/
/* First see if we can find the process */
/****************************************/
// Used to get our process snapshot
HANDLE hProcessSnap = 0;
// Current operating status
bool status = false;
// First wee if we can get a snapshot of all processes
if((hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) == INVALID_HANDLE_VALUE)
{
// If we cant, return false for failure
return false;
}
// If we were able to get the snapshot, call the Close function in case this particular
// Process object was already opened.
Close();
// Retrieve the information about the first process encountered in the system snapshot
if(Process32First(hProcessSnap, &pe32))
{
// Now get ready to loop though all of the processes
do
{
// First check to see if the exe file name matches the one we are looking for
if(std::string(pe32.szExeFile) == exeName)
{
// If we should find the window for this process
if(lookForWindow)
{
// Now we call the enumCallbackFunc in order to find the
// main HWND associated with the process. Note that a process could
// have more than one HWND, so this library just gets the first. We
// pass 'this' current object to the function in order to be able to
// assign the HWND back to this class object.
EnumWindows(enumCallbackFunc, (LPARAM)this);
// If the hwnd is not null, then we have found the main window and
// no longer need to continue this loop
if(hwnd)
{
status = true;
}
}
else
{
// Otherwise if there is no window being looked for,
// we take the first process we find
status = true;
}
}
}
// For our do-while we will loop while the HWND was not found and we have another process to check
while(!status && Process32Next(hProcessSnap, &pe32));
}
else
{
// If we reach this part there was a major error because Process32First has failed
ShowError("cProcess::Open - Process32First");
return false;
}
// Once we get here, we no longer need the snapshot because we looked though all the processes
CloseHandle(hProcessSnap);
// Now, we will check if we found the process or not. We set status to true above to indicate if we did
if(!status)
{
return false;
}
/****************************************/
/* If we found it, now we can open it */
/****************************************/
// Now we will try to open the process and store it
handle = OpenProcess(dwDesiredAccess, bInhereitHandle, pe32.th32ProcessID);
if(!handle)
{
// If we reach this part there was a problem because we could not open our process
ShowError("cProcess::Open - OpenProcess");
return false;
}
// If we get here, we have found our process and hwnd and are ready to use the clas object!
return true;
}
/**************************************************************************/
/* Function: Close */
/* */
/* Description: This function will close the opened process. */
/* */
/* Return Type: None */
/* */
/* Parameters: None */
/**************************************************************************/
void Close()
{
// First we will want to see if the handle we have is valid and close it
if(handle && CloseHandle(handle) != 0)
{
handle = 0;
}
// Next just clear out our variables
ZeroMemory(&pe32, sizeof(PROCESSENTRY32));
pe32.dwSize = sizeof(PROCESSENTRY32);
hwnd = 0;
}
/**************************************************************************/
/* Function: Read */
/* */
/* Description: This function will read exactly 'one' unit of the passed */
/* datatype specified. */
/* */
/* Return Type: bool: true = success, false = failure */
/* */
/* Parameters: */
/* unsigned long address - The address of the memory to read. */
/* type& buffer - The variable to store the read memory to. */
/**************************************************************************/
template <class type>
bool Read(unsigned long address, type& buffer)
{
// Holds the number of bytes read
SIZE_T read = 0;
// Try to read the memory and if there was a problem, show the error
if(!ReadProcessMemory(handle, (LPCVOID)address, (LPVOID)&buffer, sizeof(type), &read))
{
ShowError("cProcess::Read - ReadProcessMemory");
return false;
}
// Success! buffer now contains the memory read.
return true;
}
/**************************************************************************/
/* Function: ReadArray */
/* */
/* Description: This function will read exactly sizeOfBuffer units of the*/
/* passed datatype specified or until 'stopValue' is read. */
/* */
/* Return Type: bool: true = success, false = failure */
/* */
/* Parameters: */
/* unsigned long address - The address of the memory to read. */
/* type* buffer - The array of variables to store the read memory to.*/
/* int sizeOfBuffer - The number of elements the array has space for */
/* type stopValue - The value to signal to stop reading memory if */
/* the number of elements read is smaller than */
/* sizeOfBuffer. */
/**************************************************************************/
template <class type>
bool ReadArray(unsigned long address, type* buffer, int sizeOfBuffer, type stopValue)
{
// Holds the number of bytes read
SIZE_T read = 0;
// Precalcuate and store the size of the data type being used
SIZE_T dataSize = sizeof(type);
// Loop though all of the elements in the array and fill them in
for(int x = 0; x < sizeOfBuffer; ++x)
{
// Try to read the memory and if there was a problem, show the error
if(!ReadProcessMemory(handle, (LPCVOID)(address + (dataSize * x)), (LPVOID)&buffer[x], dataSize, &read))
{
ShowError("cProcess::ReadArray - ReadProcessMemory");
// We shouldn't try to continue
return false;
}
// Check to see if the current value read in is our stop value, if so, we are done
if(buffer[x] == stopValue)
{
// Success!
return true;
}
}
// Success!
return true;
}
/**************************************************************************/
/* Function: ReadArray */
/* */
/* Description: This function will read exactly sizeOfBuffer units of the*/
/* passed datatype specified. */
/* */
/* Return Type: bool: true = success, false = failure */
/* */
/* Parameters: */
/* unsigned long address - The address of the memory to read. */
/* type* buffer - The array of variables to store the read memory to.*/
/* int sizeOfBuffer - The number of elements the array has space for.*/
/**************************************************************************/
template <class type>
bool ReadArray(unsigned long address, type* buffer, int sizeOfBuffer)
{
// Holds the number of bytes read
SIZE_T read = 0;
// Precalcuate and store the size of the data type being used
SIZE_T dataSize = sizeof(type);
// Loop though all of the elements in the array and fill them in
for(int x = 0; x < sizeOfBuffer; ++x)
{
// Try to read the memory and if there was a problem, show the error
if(!ReadProcessMemory(handle, (LPCVOID)(address + (dataSize * x)), (LPVOID)&buffer[x], dataSize, &read))
{
return false;
}
}
// Success!
return true;
}
/**************************************************************************/
/* Function: Write */
/* */
/* Description: This function will write the passed variable to memory. */
/* */
/* Return Type: bool: true = success, false = failure */
/* */
/* Parameters: */
/* unsigned long address - The address of the memory to read. */
/* type& buffer - The variable to store in memory. */
/**************************************************************************/
template <class type>
bool Write(unsigned long address, type& buffer)
{
// Holds the number of bytes written
SIZE_T write = 0;
// Try to write the memory and if there was a problem, show the error and return a failure
if(!WriteProcessMemory(handle, (LPVOID)address, (LPVOID)&buffer, sizeof(type), &write))
{
ShowError("cProcess::Write - WriteProcessMemory");
return false;
}
// Success!
return true;
}
/**************************************************************************/
/* Function: WriteArray */
/* */
/* Description: This function will write the buffer of passed datatype */
/* specified into the memory address specificed. */
/* */
/* Return Type: bool: true = success, false = failure */
/* */
/* Parameters: */
/* unsigned long address - The address of the memory to read. */
/* type* buffer - The array of variables to write into memory. */
/* int sizeOfBuffer - The number of elements the array has. */
/**************************************************************************/
template <class type>
bool WriteArray(unsigned long address, type* buffer, int sizeOfBuffer)
{
// Holds the number of bytes written
SIZE_T write = 0;
// Precalcuate and store the size of the data type being used
SIZE_T dataSize = sizeof(type);
// Loop though all of the elements in the array and fill memory with them
for(int x = 0; x < sizeOfBuffer; ++x)
{
// Try to write the memory and if there was a problem, show the error
if(!WriteProcessMemory(handle, (LPVOID)(address + (dataSize * x)), (LPVOID)&buffer[x], dataSize, &write))
{
ShowError("cProcess::WriteArray - WriteProcessMemory");
// We shouldn't try to continue
return false;
}
}
// Success!
return true;
}
};
// Taken and modified from a MSDN example, it will present a messagebox
// to the user with the current error. Dont worry about this function.
void ShowError(LPTSTR lpszFunction)
{
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL );
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR));
wsprintf((LPTSTR)lpDisplayBuf, TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK | MB_ICONERROR);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
// This function is the callback function used for EnumWindows
BOOL CALLBACK enumCallbackFunc(HWND hwnd, LPARAM lparam)
{
// Since we passed the cProcess object we are working on, first retrieve it
cProcess* process = (cProcess*)lparam;
// Holds the process id of the window we are looking at
DWORD pid = 0;
// Get the process id
GetWindowThreadProcessId(hwnd, &pid);
// If the cProcess object's id equals the windows id
if(process->pe32.th32ProcessID == pid)
{
// Store the active window
HWND active = ::GetForegroundWindow();
// Bring the window we are looking at to the top
SetForegroundWindow(hwnd);
// Check with the user as to if this is the right window
if(MessageBox(hwnd, "Was the correct window activated?", "Desired Window?", MB_ICONQUESTION | MB_YESNO) == IDYES)
{
// If so, save the hwnd to the class object
process->hwnd = hwnd;
// Restore the old foreground window
SetForegroundWindow(active);
// Return false so we do not call this function anymore, we are done
return FALSE;
}
else
{
// Otherwise simply restore the old foreground window
SetForegroundWindow(active);
}
}
// Return true to keep on going though windows
return TRUE;
}
#endif
Remember the code is over 2 years old now and the setup of the program reflects not knowing too much about setting up programs in an easy to use and modify way lol. Anyways it should be enough to get the idea of what to do.
Here is what the process looks like after you compile and run.
Just sharing because I did this a long time ago. I'm not going to maintain the project or rerelease it again since I've got enough stuff I'm working on. Feel free to compile and play with it though.
|
|
|
08/08/2009, 21:41
|
#3
|
elite*gold: 20
Join Date: Jul 2008
Posts: 1,199
Received Thanks: 362
|
I doubt he will even read half of what you wrote... But GJ anyways
|
|
|
06/18/2012, 02:44
|
#4
|
elite*gold: 0
Join Date: May 2012
Posts: 3
Received Thanks: 0
|
Quote:
Originally Posted by pushedx
I wrote code to do it a long time ago. The first way I did it was to perform client edits via WriteProcessMemory through a secondary program. That would work for all chat types except for All Chat right now due to how the client code is setup.
The second method I used was to create a codecave in the client to process the chat color logic. You can get the current chat type and then specify a custom color for it. That is much easier to work with, but requires the use of a loader and injected DLL. You could use my guides to do it though but I'm not going to myself.
Here's the code in the latest 205 client that has to deal with chat colors.
Code:
007A37C7 . 8078 04 00 CMP BYTE PTR DS:[EAX+4],0
007A37CB .^ 0F84 B2FEFFFF JE sro_clie.007A3683
007A37D1 > BD FEFF9FFF MOV EBP,FF9FFFFE ; Case A of switch 007A37B3
007A37D6 . EB 34 JMP SHORT sro_clie.007A380C
007A37D8 > BD 00FFFFFF MOV EBP,-100 ; Case 6 of switch 007A37B3
007A37DD . EB 2D JMP SHORT sro_clie.007A380C
007A37DF > BD C3AEFFFF MOV EBP,FFFFAEC3 ; Cases 3,7 of switch 007A37B3
007A37E4 . EB 26 JMP SHORT sro_clie.007A380C
007A37E6 > BD 41B5FFFF MOV EBP,FFFFB541 ; Case 5 of switch 007A37B3
007A37EB . EB 1F JMP SHORT sro_clie.007A380C
007A37ED > BD 73F5C2FF MOV EBP,FFC2F573 ; Case B of switch 007A37B3
007A37F2 . EB 18 JMP SHORT sro_clie.007A380C
007A37F4 > BD D0FF9AFF MOV EBP,FF9AFFD0 ; Case 4 of switch 007A37B3
007A37F9 . EB 11 JMP SHORT sro_clie.007A380C
007A37FB > BD F8ADDBFF MOV EBP,FFDBADF8 ; Case D of switch 007A37B3
007A3800 . EB 0A JMP SHORT sro_clie.007A380C
007A3802 > BD FFC764FF MOV EBP,FF64C7FF ; Case 10 of switch 007A37B3
007A3807 . EB 03 JMP SHORT sro_clie.007A380C
007A3809 > 83CD FF OR EBP,FFFFFFFF ; Default case of switch 007A37B3
007A380C > B8 07000000 MOV EAX,7
You should be able to follow the colors in a graphics program that allows you to use hex/decimal for RGB. The colors are stored backwards in memory so FEFF9FFF is color (ARGB) FF 9F FF FE, or the color for whisper chat.
Here's the updated code to the project I wrote back in Feb. 07. The concept is pretty simple. Just write out the new hex values for the colors in the Silkroad process. You need to be running the program in Administrator in Vista/Win7 as well.
SilkroadChatColor.cpp
Code:
#include "cProcess.h"
#include <windows.h>
#include <math.h>
#include <stdio.h>
#include <fstream>
#include <sstream>
// Main program window
HWND hwnd = 0;
// Array of addresses to make for easier access
unsigned long addrs[6];
unsigned long defs[6];
unsigned long curs[6];
HWND hwnds[6];
HWND preview[6];
// Whisper
HWND lblWhisper = 0;
HWND editWhisper = 0;
HWND btnDefWhisper = 0;
unsigned long addrWhisper = 0x7A37D1;
unsigned long defColorWhisper = 0xFF9FFFFE;
// Global
HWND lblGlobal = 0;
HWND editGlobal = 0;
HWND btnDefGlobal = 0;
unsigned long addrGlobal = 0x7A37D8;
unsigned long defColorGlobal = 0xFFFFFF00;
// Notice
HWND lblNotice = 0;
HWND editNotice = 0;
HWND btnDefNotice = 0;
unsigned long addrNotice = 0x7A37DF;
unsigned long defColorNotice = 0xFFFFAEC3;
// Guild
HWND lblGuild = 0;
HWND editGuild = 0;
HWND btnDefGuild = 0;
unsigned long addrGuild = 0x7A37E6;
unsigned long defColorGuild = 0xFFFFB541;
// Union
HWND lblUnion = 0;
HWND editUnion = 0;
HWND btnDefUnion = 0;
unsigned long addrUnion = 0x7A37ED;
unsigned long defColorUnion = 0xFFC2F573;
// Party
HWND lblParty = 0;
HWND editParty = 0;
HWND btnDefParty = 0;
unsigned long addrParty = 0x7A37F4;
unsigned long defColorParty = 0xFF9AFFD0;
// Set chat color button
HWND btnColorize = 0;
HWND btnPerm = 0;
// Get the current color a chat type
HWND btnGetWhisper = 0;
HWND btnGetGlobal = 0;
HWND btnGetNotice = 0;
HWND btnGetGuild = 0;
HWND btnGetUnion = 0;
HWND btnGetParty = 0;
HWND btnGetAll = 0;
// Defines for the button messages
#define BTN_DEF_COLOR_WHISPER 1
#define BTN_DEF_COLOR_GLOBAL 2
#define BTN_DEF_COLOR_NOTICE 3
#define BTN_DEF_COLOR_GUILD 4
#define BTN_DEF_COLOR_UNION 5
#define BTN_DEF_COLOR_PARTY 6
#define BTN_DEF_COLOR_ALL 7
#define BTN_COLORIZE_ON 8
#define BTN_COLORIZE_GET 9
#define BTN_PREVIEW_COLOR_WHSIPER 11
#define BTN_PREVIEW_COLOR_GLOBAL 12
#define BTN_PREVIEW_COLOR_NOTICE 13
#define BTN_PREVIEW_COLOR_GUILD 14
#define BTN_PREVIEW_COLOR_UNION 15
#define BTN_PREVIEW_COLOR_PARTY 16
#define BTN_PREVIEW_COLOR_ALL 17
#define BTN_GET_COLOR_WHISPER 18
#define BTN_GET_COLOR_GLOBAL 19
#define BTN_GET_COLOR_NOTICE 20
#define BTN_GET_COLOR_GUILD 21
#define BTN_GET_COLOR_UNION 22
#define BTN_GET_COLOR_PARTY 23
#define BTN_GET_COLOR_ALL 24
// cProcess class object used to make working with processes a lot easier ;)
cProcess sro;
unsigned long CaptionToHex(HWND h)
{
// Store the actual hex string
unsigned char data[5] = {0};
// Store the ascii-hex string
char temp[32] = {0};
// The alpha should be FF, opaque (don't think font supports alpha)
temp[0] = 'F';
temp[1] = 'F';
// Get the desired window's color
GetWindowText(h, temp + 2, 7);
// Store the final value
int value = 0;
// We have to reverse the digits for hex form
int index = 3;
// Loop though all tuples of characters
for(int y = 0; y < 8; y += 2)
{
int tuple1 = 15, tuple2 = 15;
// Store current character
unsigned char cur = temp[y];
// If it's A - F, convert it to 10 - 15
if(cur >= 'A' && cur <= 'F')
tuple1 = cur - 'A' + 10;
// If it's 0 - 9, convert it to 0 - 9
else if(cur >= '0' && cur <= '9')
tuple1 = cur - '0';
// Store current character
cur = temp[y + 1];
// If it's A - F, convert it to 10 - 15
if(cur >= 'A' && cur <= 'F')
tuple2 = cur - 'A' + 10;
// If it's 0 - 9, convert it to 0 - 9
else if(cur >= '0' && cur <= '9')
tuple2 = cur - '0';
// Convert the two numbers into a unsigned character
value = tuple2 + 16 * tuple1;
// Store the final color value for this color component
data[index--] = value;
}
// Store a pointer of the final color value as a unsigned long
unsigned long* ptr = (unsigned long*)data;
return *ptr;
}
void DrawColorPreview(HDC hdc, int x, int y, unsigned long color)
{
color = color & 0x00FFFFFF;
HBRUSH NewBrush = CreateSolidBrush(RGB(GetBValue(color),GetGValue(color),GetRValue(color)));
SelectObject(hdc, NewBrush);
Rectangle(hdc, x, y, x + 18, y + 18);
DeleteObject(NewBrush);
}
// Get the current chat colors
void GetCurrentChatColors(int x)
{
// Array to hold the data
unsigned char buffer[5] = {0};
// Read in the memory location
if(!sro.ReadArray(addrs[x], buffer, 5))
{
MessageBox(hwnd, "Memory address could not be read.", "Fatal Error", MB_OK | MB_ICONERROR);
return;
}
char temp[256] = {0};
// Store the color components into the array
_snprintf(temp, 255, "%.2X%.2X%.2X", buffer[3], buffer[2], buffer[1]);
// Write the entire RGB color string to the edit box
SetWindowText(hwnds[x], temp);
}
void GeneratePreview(HWND btn, int button)
{
curs[button] = CaptionToHex(btn);
RECT r;
r.left = 284;
r.right = r.left + 18;
r.top = 10 + button * 30;
r.bottom = r.top + 18;
InvalidateRect(hwnd, &r, true);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT Ps;
HDC hdc;
switch(msg)
{
case WM_PAINT:
{
hdc = BeginPaint(hwnd, &Ps);
for(int x = 0; x < 6; ++x)
DrawColorPreview(hdc, 284, 10 + x * 30, curs[x]);
EndPaint(hwnd, &Ps);
}
break;
case WM_COMMAND:
{
if(LOWORD(wParam) == BTN_COLORIZE_ON)
{
// Loop though all chat colors
for(int x = 0; x < 6; ++x)
{
int ptr = CaptionToHex(hwnds[x]);
// Write the color value to memory
sro.Write(addrs[x] + 1, ptr);
}
}
else if(LOWORD(wParam) >= BTN_GET_COLOR_WHISPER && LOWORD(wParam) <= BTN_GET_COLOR_ALL)
{
int button = LOWORD(wParam) - BTN_GET_COLOR_WHISPER;
GetCurrentChatColors(button);
GeneratePreview(hwnds[button], button);
}
else if(LOWORD(wParam) >= BTN_DEF_COLOR_WHISPER && LOWORD(wParam) <= BTN_DEF_COLOR_ALL)
{
// Save the real button #
int button = LOWORD(wParam) - 1;
// Buffer to hold the default value
char temp[256] = {0};
// Save the default value to the buffer
sprintf(temp, "%X", defs[button]);
// Write the default value to the window
SetWindowText(hwnds[button], temp + 2);
GeneratePreview(hwnds[button], button);
}
else if(LOWORD(wParam) >= BTN_PREVIEW_COLOR_WHSIPER && LOWORD(wParam) <= LOWORD(wParam))
{
int button = LOWORD(wParam) - BTN_PREVIEW_COLOR_WHSIPER;
GeneratePreview(hwnds[button], button);
}
}
break;
case WM_CLOSE:
{
DestroyWindow(hwnd);
}
break;
case WM_DESTROY:
{
PostQuitMessage(0);
}
break;
default:
{
return DefWindowProc(hwnd, msg, wParam, lParam);
}
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc = {0};
MSG msg = {0};
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(0);
wc.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(101));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+6);
wc.lpszMenuName = NULL;
wc.lpszClassName = "SROChatColor";
wc.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(101), IMAGE_ICON, 16, 16, 0);;
// Win32 stuff to create the program
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONERROR | MB_OK);
return 0;
}
// Create main window
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "SROChatColor", "Silkroad Chat Color - By: Drew Benton", WS_OVERLAPPEDWINDOW ^ WS_MAXIMIZEBOX ^ WS_THICKFRAME, CW_USEDEFAULT, CW_USEDEFAULT, 480, 290, NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONERROR | MB_OK);
return 0;
}
// Try to open the sro client
if(!sro.Open("sro_client.exe"))
{
MessageBox(0, "Cannot find your sro_client.exe", "Error!", MB_ICONERROR | MB_OK);
return -1;
}
// Store the addresses
addrs[0] = addrWhisper;
addrs[1] = addrGlobal;
addrs[2] = addrNotice;
addrs[3] = addrGuild;
addrs[4] = addrUnion;
addrs[5] = addrParty;
//addrs[6] = addrAll;
// Store default colors
defs[0] = defColorWhisper;
defs[1] = defColorGlobal;
defs[2] = defColorNotice;
defs[3] = defColorGuild;
defs[4] = defColorUnion;
defs[5] = defColorParty;
//defs[6] = defColorAll;
// Store defaults
for(int x = 0; x < 6; ++x)
curs[x] = defs[x];
// Coords of controls
int X = 0; int Y = 0; int W = 0; int H = 0;
// Whisper
X = 10; Y = 10; W = 125; H = 20;
lblWhisper = CreateWindowEx(0, "STATIC", "Whisper Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 110;
editWhisper = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 312; W = 70;
btnDefWhisper = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_WHISPER, NULL, 0);
X = 392;
btnGetWhisper = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_WHISPER, NULL, 0);
X = 250; W = 24;
preview[0] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_WHSIPER, NULL, 0);
// Global
X = 10; Y = 40; W = 125; H = 20;
lblGlobal = CreateWindowEx(0, "STATIC", "Global Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 110;
editGlobal = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 312; W = 70;
btnDefWhisper = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_GLOBAL, NULL, 0);
X = 392;
btnGetGlobal = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_GLOBAL, NULL, 0);
X = 250; W = 24;
preview[1] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_GLOBAL, NULL, 0);
// Notice
X = 10; Y = 70; W = 125; H = 20;
lblNotice = CreateWindowEx(0, "STATIC", "Notice Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 110;
editNotice = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 312; W = 70;
btnDefNotice = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_NOTICE, NULL, 0);
X = 392;
btnGetNotice = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_NOTICE, NULL, 0);
X = 250; W = 24;
preview[2] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_NOTICE, NULL, 0);
// Guild
X = 10; Y = 100; W = 125; H = 20;
lblGuild = CreateWindowEx(0, "STATIC", "Guild Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 110;
editGuild = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 312; W = 70;
btnDefGuild = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_GUILD, NULL, 0);
X = 392;
btnGetGuild = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_GUILD, NULL, 0);
X = 250; W = 24;
preview[3] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_GUILD, NULL, 0);
// Union
X = 10; Y = 130; W = 125; H = 20;
lblUnion = CreateWindowEx(0, "STATIC", "Union Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 110;
editUnion = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 312; W = 70;
btnDefUnion = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_UNION, NULL, 0);
X = 392;
btnGetUnion = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_UNION, NULL, 0);
X = 250; W = 24;
preview[4] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_UNION, NULL, 0);
// Party
X = 10; Y = 160; W = 125; H = 20;
lblParty = CreateWindowEx(0, "STATIC", "Party Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 110;
editParty = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 312; W = 70;
btnDefParty = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_PARTY, NULL, 0);
X = 392;
btnGetParty = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_PARTY, NULL, 0);
X = 250; W = 24;
preview[5] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_PARTY, NULL, 0);
// Set chat color button
X = 312; Y = 220; W = 150; H = 30;
btnColorize = CreateWindowEx(0, "BUTTON", "Change Chat Colors!", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_COLORIZE_ON, NULL, 0);
// Store the edit handles to make life easier
hwnds[0] = editWhisper;
hwnds[1] = editGlobal;
hwnds[2] = editNotice;
hwnds[3] = editGuild;
hwnds[4] = editUnion;
hwnds[5] = editParty;
//hwnds[6] = editAll;
// Start the program out by getting the current colors stored in memory
for(int x = 0; x < 6; ++x)
GetCurrentChatColors(x);
// Reactivate this program
SetForegroundWindow(hwnd);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
WaitMessage();
}
}
return 0;
}
cProcess.h
Code:
/*****************************************************************************/
/* cProcess
/* By; Drew Benton
/*
/* This class was written to make working with processes a lot easier. With
/* this class, the user will be able to open a process and read from memory
/* or write to memory. It is designed with simplicty and ease of use in mind.
/* If you have any questions or comments e-mail me at
/*
/******************************************************************************/
#ifndef CPROCESS_H_
#define CPROCESS_H_
#include <windows.h>
#include <tlhelp32.h>
#include <string>
// Display the current error to the user via a message box
void ShowError(LPTSTR lpszFunction);
// The callback function used for processing HWNDs
BOOL CALLBACK enumCallbackFunc(HWND hwnd, LPARAM lparam);
class cProcess
{
public:
// The process entry for the process
PROCESSENTRY32 pe32;
// Handle to the process
HANDLE handle;
// One of the HWNDs associated with the process
HWND hwnd;
public:
/******************************************************************************************/
// MEMBER FUNCTIONS REFERENCE //
/******************************************************************************************/
/* // This is the constructor for the cProcess class.
/* cProcess();
/* // This is the destructor for the cProcess class.
/* ~cProcess();
/*
/* // This function will open the desired executable's process.
/* bool Open(
/* const std::string& exeName,
/* bool lookForWindow = true,
/* DWORD dwDesiredAccess = PROCESS_ALL_ACCESS,
/* BOOL bInhereitHandle = FALSE);
/*
/* // This function will close the opened process.
/* void Close();
/*
/* // This function will read exactly 'one' unit of the passed datatype specified.
/* template <class type>
/* bool Read(
/* unsigned long address,
/* type& buffer);
/*
/* // This function will read exactly sizeOfBuffer units of the
/* // passed datatype specified or until 'stopValue' is read.
/* template <class type>
/* bool ReadArray(
/* unsigned long address,
/* type* buffer,
/* int sizeOfBuffer,
/* type stopValue);
/*
/* // This function will read exactly sizeOfBuffer units of the passed datatype specified.
/* template <class type>
/* bool ReadArray(
/* unsigned long address,
/* type* buffer,
/* int sizeOfBuffer);
/*
/* // This function will write the passed variable to memory.
/* template <class type>
/* bool Write(
/* unsigned long address,
/* type& buffer);
/*
/* // This function will write the buffer of passed datatype
/* // specified into the memory address specificed.
/* template <class type>
/* bool WriteArray(
/* unsigned long address,
/* type* buffer,
/* int sizeOfBuffer);
/*****************************************************************************************/
/******************************************************************************************/
// MEMBER FUNCTION IMPLEMENTATIONS //
/******************************************************************************************/
/**************************************************************************/
/* Function: cProcess */
/* */
/* Description: This is the constructor for the cProcess class. */
/* */
/* Return Type: None */
/* */
/* Parameters: None */
/**************************************************************************/
cProcess::cProcess()
{
// Simply clear all the memory of our variables
handle = 0;
hwnd = 0;
ZeroMemory(&pe32, sizeof(PROCESSENTRY32));
// This is a must in Win32 for this struct!
pe32.dwSize = sizeof(PROCESSENTRY32);
}
/**************************************************************************/
/* Function: cProcess */
/* */
/* Description: This is the destructor for the cProcess class. */
/* */
/* Return Type: None */
/* */
/* Parameters: None */
/**************************************************************************/
cProcess::~cProcess()
{
// Call the Close function on object destruction
Close();
}
/**************************************************************************/
/* Function: Open */
/* */
/* Description: This function will open the desired executable's process.*/
/* Since there could be many processes with the same executable, a */
/* feature exsits to help the user select the correct window. The hwnd is*/
/* activated and the user replies to a message box as to if it is correct*/
/* */
/* Return Type: bool: true = success, false = failure */
/* */
/* Parameters: */
/* const string& exeName - This parameter is the executable file of */
/* the process we with to open. */
/* bool lookForWindow - Should the class find the main HWND */
/* [Default: true] */
/* DWORD dwDesiredAccess - This is the optional desired access flag */
/* used to open the process. */
/* [Default: PROCESS_ALL_ACCESS] */
/* BOOL bInhereitHandle - This is the optional desired flag used to */
/* open the process */
/* [Default: FALSE] */
/**************************************************************************/
bool Open(const std::string& exeName, bool lookForWindow = true, DWORD dwDesiredAccess = PROCESS_ALL_ACCESS, BOOL bInhereitHandle = FALSE)
{
/****************************************/
/* First see if we can find the process */
/****************************************/
// Used to get our process snapshot
HANDLE hProcessSnap = 0;
// Current operating status
bool status = false;
// First wee if we can get a snapshot of all processes
if((hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) == INVALID_HANDLE_VALUE)
{
// If we cant, return false for failure
return false;
}
// If we were able to get the snapshot, call the Close function in case this particular
// Process object was already opened.
Close();
// Retrieve the information about the first process encountered in the system snapshot
if(Process32First(hProcessSnap, &pe32))
{
// Now get ready to loop though all of the processes
do
{
// First check to see if the exe file name matches the one we are looking for
if(std::string(pe32.szExeFile) == exeName)
{
// If we should find the window for this process
if(lookForWindow)
{
// Now we call the enumCallbackFunc in order to find the
// main HWND associated with the process. Note that a process could
// have more than one HWND, so this library just gets the first. We
// pass 'this' current object to the function in order to be able to
// assign the HWND back to this class object.
EnumWindows(enumCallbackFunc, (LPARAM)this);
// If the hwnd is not null, then we have found the main window and
// no longer need to continue this loop
if(hwnd)
{
status = true;
}
}
else
{
// Otherwise if there is no window being looked for,
// we take the first process we find
status = true;
}
}
}
// For our do-while we will loop while the HWND was not found and we have another process to check
while(!status && Process32Next(hProcessSnap, &pe32));
}
else
{
// If we reach this part there was a major error because Process32First has failed
ShowError("cProcess::Open - Process32First");
return false;
}
// Once we get here, we no longer need the snapshot because we looked though all the processes
CloseHandle(hProcessSnap);
// Now, we will check if we found the process or not. We set status to true above to indicate if we did
if(!status)
{
return false;
}
/****************************************/
/* If we found it, now we can open it */
/****************************************/
// Now we will try to open the process and store it
handle = OpenProcess(dwDesiredAccess, bInhereitHandle, pe32.th32ProcessID);
if(!handle)
{
// If we reach this part there was a problem because we could not open our process
ShowError("cProcess::Open - OpenProcess");
return false;
}
// If we get here, we have found our process and hwnd and are ready to use the clas object!
return true;
}
/**************************************************************************/
/* Function: Close */
/* */
/* Description: This function will close the opened process. */
/* */
/* Return Type: None */
/* */
/* Parameters: None */
/**************************************************************************/
void Close()
{
// First we will want to see if the handle we have is valid and close it
if(handle && CloseHandle(handle) != 0)
{
handle = 0;
}
// Next just clear out our variables
ZeroMemory(&pe32, sizeof(PROCESSENTRY32));
pe32.dwSize = sizeof(PROCESSENTRY32);
hwnd = 0;
}
/**************************************************************************/
/* Function: Read */
/* */
/* Description: This function will read exactly 'one' unit of the passed */
/* datatype specified. */
/* */
/* Return Type: bool: true = success, false = failure */
/* */
/* Parameters: */
/* unsigned long address - The address of the memory to read. */
/* type& buffer - The variable to store the read memory to. */
/**************************************************************************/
template <class type>
bool Read(unsigned long address, type& buffer)
{
// Holds the number of bytes read
SIZE_T read = 0;
// Try to read the memory and if there was a problem, show the error
if(!ReadProcessMemory(handle, (LPCVOID)address, (LPVOID)&buffer, sizeof(type), &read))
{
ShowError("cProcess::Read - ReadProcessMemory");
return false;
}
// Success! buffer now contains the memory read.
return true;
}
/**************************************************************************/
/* Function: ReadArray */
/* */
/* Description: This function will read exactly sizeOfBuffer units of the*/
/* passed datatype specified or until 'stopValue' is read. */
/* */
/* Return Type: bool: true = success, false = failure */
/* */
/* Parameters: */
/* unsigned long address - The address of the memory to read. */
/* type* buffer - The array of variables to store the read memory to.*/
/* int sizeOfBuffer - The number of elements the array has space for */
/* type stopValue - The value to signal to stop reading memory if */
/* the number of elements read is smaller than */
/* sizeOfBuffer. */
/**************************************************************************/
template <class type>
bool ReadArray(unsigned long address, type* buffer, int sizeOfBuffer, type stopValue)
{
// Holds the number of bytes read
SIZE_T read = 0;
// Precalcuate and store the size of the data type being used
SIZE_T dataSize = sizeof(type);
// Loop though all of the elements in the array and fill them in
for(int x = 0; x < sizeOfBuffer; ++x)
{
// Try to read the memory and if there was a problem, show the error
if(!ReadProcessMemory(handle, (LPCVOID)(address + (dataSize * x)), (LPVOID)&buffer[x], dataSize, &read))
{
ShowError("cProcess::ReadArray - ReadProcessMemory");
// We shouldn't try to continue
return false;
}
// Check to see if the current value read in is our stop value, if so, we are done
if(buffer[x] == stopValue)
{
// Success!
return true;
}
}
// Success!
return true;
}
/**************************************************************************/
/* Function: ReadArray */
/* */
/* Description: This function will read exactly sizeOfBuffer units of the*/
/* passed datatype specified. */
/* */
/* Return Type: bool: true = success, false = failure */
/* */
/* Parameters: */
/* unsigned long address - The address of the memory to read. */
/* type* buffer - The array of variables to store the read memory to.*/
/* int sizeOfBuffer - The number of elements the array has space for.*/
/**************************************************************************/
template <class type>
bool ReadArray(unsigned long address, type* buffer, int sizeOfBuffer)
{
// Holds the number of bytes read
SIZE_T read = 0;
// Precalcuate and store the size of the data type being used
SIZE_T dataSize = sizeof(type);
// Loop though all of the elements in the array and fill them in
for(int x = 0; x < sizeOfBuffer; ++x)
{
// Try to read the memory and if there was a problem, show the error
if(!ReadProcessMemory(handle, (LPCVOID)(address + (dataSize * x)), (LPVOID)&buffer[x], dataSize, &read))
{
return false;
}
}
// Success!
return true;
}
/**************************************************************************/
/* Function: Write */
/* */
/* Description: This function will write the passed variable to memory. */
/* */
/* Return Type: bool: true = success, false = failure */
/* */
/* Parameters: */
/* unsigned long address - The address of the memory to read. */
/* type& buffer - The variable to store in memory. */
/**************************************************************************/
template <class type>
bool Write(unsigned long address, type& buffer)
{
// Holds the number of bytes written
SIZE_T write = 0;
// Try to write the memory and if there was a problem, show the error and return a failure
if(!WriteProcessMemory(handle, (LPVOID)address, (LPVOID)&buffer, sizeof(type), &write))
{
ShowError("cProcess::Write - WriteProcessMemory");
return false;
}
// Success!
return true;
}
/**************************************************************************/
/* Function: WriteArray */
/* */
/* Description: This function will write the buffer of passed datatype */
/* specified into the memory address specificed. */
/* */
/* Return Type: bool: true = success, false = failure */
/* */
/* Parameters: */
/* unsigned long address - The address of the memory to read. */
/* type* buffer - The array of variables to write into memory. */
/* int sizeOfBuffer - The number of elements the array has. */
/**************************************************************************/
template <class type>
bool WriteArray(unsigned long address, type* buffer, int sizeOfBuffer)
{
// Holds the number of bytes written
SIZE_T write = 0;
// Precalcuate and store the size of the data type being used
SIZE_T dataSize = sizeof(type);
// Loop though all of the elements in the array and fill memory with them
for(int x = 0; x < sizeOfBuffer; ++x)
{
// Try to write the memory and if there was a problem, show the error
if(!WriteProcessMemory(handle, (LPVOID)(address + (dataSize * x)), (LPVOID)&buffer[x], dataSize, &write))
{
ShowError("cProcess::WriteArray - WriteProcessMemory");
// We shouldn't try to continue
return false;
}
}
// Success!
return true;
}
};
// Taken and modified from a MSDN example, it will present a messagebox
// to the user with the current error. Dont worry about this function.
void ShowError(LPTSTR lpszFunction)
{
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL );
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR));
wsprintf((LPTSTR)lpDisplayBuf, TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK | MB_ICONERROR);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
// This function is the callback function used for EnumWindows
BOOL CALLBACK enumCallbackFunc(HWND hwnd, LPARAM lparam)
{
// Since we passed the cProcess object we are working on, first retrieve it
cProcess* process = (cProcess*)lparam;
// Holds the process id of the window we are looking at
DWORD pid = 0;
// Get the process id
GetWindowThreadProcessId(hwnd, &pid);
// If the cProcess object's id equals the windows id
if(process->pe32.th32ProcessID == pid)
{
// Store the active window
HWND active = ::GetForegroundWindow();
// Bring the window we are looking at to the top
SetForegroundWindow(hwnd);
// Check with the user as to if this is the right window
if(MessageBox(hwnd, "Was the correct window activated?", "Desired Window?", MB_ICONQUESTION | MB_YESNO) == IDYES)
{
// If so, save the hwnd to the class object
process->hwnd = hwnd;
// Restore the old foreground window
SetForegroundWindow(active);
// Return false so we do not call this function anymore, we are done
return FALSE;
}
else
{
// Otherwise simply restore the old foreground window
SetForegroundWindow(active);
}
}
// Return true to keep on going though windows
return TRUE;
}
#endif
Remember the code is over 2 years old now and the setup of the program reflects not knowing too much about setting up programs in an easy to use and modify way lol. Anyways it should be enough to get the idea of what to do.
Here is what the process looks like after you compile and run.
Just sharing because I did this a long time ago. I'm not going to maintain the project or rerelease it again since I've got enough stuff I'm working on. Feel free to compile and play with it though. 
|
please i need this program is necessary
|
|
|
06/18/2012, 05:49
|
#5
|
elite*gold: 260
Join Date: Aug 2008
Posts: 560
Received Thanks: 3,779
|
Quote:
Originally Posted by ™AmeerKing™
please i need this program is necessary
|
I'll reply here instead of the PM you sent me.
The source code for that program is in my post and in your quote. It's a pure Win32 API program, so it's a really simple project. You just have to make a new empty Win32 GUI application, then paste in the code to "main.cpp" then add "cProcess.h" to the project (also copy paste from the quote). The project should use a "Multi-Byte Character Set".
In order to get it to work on current versions of Silkroad, you have to go through and update all of the addresses for the chat colors. Since that code was written like 5 years ago, some of the new chat colors for different chat text are not supported. Further more there, might be issues with actually writing to process memory if XTrap or HackShield is enabled.
Finding the chat color logic in the client is still simple, just search for a color. This is the revelant code section in ISRO:
Code:
0090BFE3 . 8D70 FF LEA ESI, DWORD PTR DS:[EAX-1] ; Switch (cases 2..10)
0090BFE6 . 83FE 0F CMP ESI, 0F
0090BFE9 . 77 4E JA SHORT sro_clie.0090C039
0090BFEB . FF24B5 3CC890>JMP NEAR DWORD PTR DS:[ESI*4+90C83C]
0090BFF2 > E8 C973BEFF CALL sro_clie.004F33C0 ; Case 2 of switch 0090BFE3
0090BFF7 . 8078 04 00 CMP BYTE PTR DS:[EAX+4], 0
0090BFFB .^ 0F84 ABFEFFFF JE sro_clie.0090BEAC
0090C001 > BD FEFF9FFF MOV EBP, FF9FFFFE ; Case A of switch 0090BFE3
0090C006 . EB 34 JMP SHORT sro_clie.0090C03C
0090C008 > BD 00FFFFFF MOV EBP, -100 ; Case 6 of switch 0090BFE3
0090C00D . EB 2D JMP SHORT sro_clie.0090C03C
0090C00F > BD C3AEFFFF MOV EBP, FFFFAEC3 ; Cases 3,7 of switch 0090BFE3
0090C014 . EB 26 JMP SHORT sro_clie.0090C03C
0090C016 > BD 41B5FFFF MOV EBP, FFFFB541 ; Case 5 of switch 0090BFE3
0090C01B . EB 1F JMP SHORT sro_clie.0090C03C
0090C01D > BD 73F5C2FF MOV EBP, FFC2F573 ; Case B of switch 0090BFE3
0090C022 . EB 18 JMP SHORT sro_clie.0090C03C
0090C024 > BD D0FF9AFF MOV EBP, FF9AFFD0 ; Case 4 of switch 0090BFE3
0090C029 . EB 11 JMP SHORT sro_clie.0090C03C
0090C02B > BD F8ADDBFF MOV EBP, FFDBADF8 ; Case D of switch 0090BFE3
0090C030 . EB 0A JMP SHORT sro_clie.0090C03C
0090C032 > BD FFC764FF MOV EBP, FF64C7FF ; Case 10 of switch 0090BFE3
0090C037 . EB 03 JMP SHORT sro_clie.0090C03C
0090C039 > 83CD FF OR EBP, FFFFFFFF ; Default case of switch 0090BFE3
0090C03C > B8 07000000 MOV EAX, 7
Any place with a "MOV EBP, #" line is the client loading the color for that specific type of chat. For all chat, white, 0xFFFFFF is used by masking the entire color value. All this means is that if you want to change all chat, you have to use a codecave or some other method of fitting in a "mov ebp, new color #" instruction in.
Rather than use my program, you can just edit the client's colors another way though. I did a quick test with one color and it still works, but there's better ways to go about this nowadays I guess.
Test image:
|
|
|
07/31/2012, 20:19
|
#6
|
elite*gold: 0
Join Date: May 2012
Posts: 3
Received Thanks: 0
|
I'm sorry but the program does not work with me on the client vsro
Please tell me how to change the color of the chat client vsro by hex
I do not understand in the reverse engineering
|
|
|
Similar Threads
|
Flashy Chat Color Text
08/23/2009 - Aion Guides & Strategies - 4 Replies
=result will be >>> Hello!
(1)
End code to finish.
http://i297.photobucket.com/albums/mm228/Wickelle n/colortexts.jpg
1 1 1 =========White
1 0 0 =========Red
0 1 0 =========Darkgreen
|
WoW Color Hack (Use color-codes in text)
09/23/2007 - WoW Exploits, Hacks, Tools & Macros - 31 Replies
WoWColorHack.flt
-=Preamble=-
I'm quite surprised that no one has released
anything similar yet - the theory behind
this dates back to the alpha days. Hell,
I first used this filter on my own alpha
sandbox.
-=Theory=-
|
All times are GMT +1. The time now is 23:12.
|
|