ffxi-boot source code?
Re: ffxi-boot source code?
If you still need it, or someone else - for educational purposes only. (PS: This not mine code, found it on old project forum)
Code: Select all
#define _WIN32_WINNT 0x501
#define WIN32_LEAN_AND_MEAN 1
#define UNICODE 1
#include <Windows.h>
#include <ObjBase.h>
#include <WinSock2.h>
#include <Ws2TcpIp.h>
#include <process.h>
#include <cstdio>
#include <cstdarg>
#include <ctime>
#pragma comment(lib, "Kernel32.lib")
#pragma comment(lib, "Ole32.lib")
#pragma comment(lib, "Ws2_32.lib")
/*
#import "C:\Program Files\PlayOnline\SquareEnix\PlayOnlineViewer\viewer\com\app.dll" raw_interfaces_only
#import "C:\Program Files\PlayOnline\SquareEnix\PlayOnlineViewer\viewer\com\polcore.dll" raw_interfaces_only
#import "C:\Program Files\PlayOnline\SquareEnix\FINAL FANTASY XI\FFXi.dll" raw_interfaces_only
#import "C:\Program Files\PlayOnline\SquareEnix\FINAL FANTASY XI\FFXiMain.dll" raw_interfaces_only
#import "C:\Program Files\PlayOnline\SquareEnix\FINAL FANTASY XI\FFXiVersions.dll" raw_interfaces_only
using namespace POLCORELib;
using namespace APPLib;
using namespace FFXILib;
using namespace FFXIMAINLib;
using namespace FFXIVERSIONSLib;
*/
struct IPOLCoreCom: IUnknown{ // IConnectionPointContainer
STDMETHOD( GethInstance )(HINSTANCE* hInstance) =0;
STDMETHOD( GetlpCmdLine )(LPSTR* lpCmdLine) =0;
STDMETHOD( SetParamInit )(HINSTANCE hInstance, LPSTR lpCmdLine) =0;
STDMETHOD( GetWindowsType )(ULONG* winType) =0;
STDMETHOD( GetCommonFunctionTable )(ULONG** ptr) =0;
STDMETHOD( PolViewerExec )(ULONG* inFunc) =0;
STDMETHOD( GetWindowsVersion )(ULONG* outPlatformId, ULONG* outMajor, ULONG* outMinor, ULONG* outSPMajor, BSTR* outOSName, ULONG inOSNameSize) =0;
STDMETHOD( PressAnyKey )(ULONG inType) =0;
STDMETHOD( PolconSetEnableWakeupFuncFlag )(ULONG inType, ULONG inBool) =0;
STDMETHOD( CreateInput )(HWND inWnd) =0;
STDMETHOD( UpdateInputState )() =0;
STDMETHOD( GetPadRepeat )(ULONG inPanNum, ULONG* outState) =0;
STDMETHOD( GetPadOn )(ULONG inPanNum, ULONG* outState) =0;
STDMETHOD( FinalCleanup )() =0;
STDMETHOD( SetParamInitW )(HINSTANCE hInstance, LPWSTR lpCmdLine) =0;
STDMETHOD( GetlpCmdLineW )(LPWSTR* lpCmdLine) =0;
STDMETHOD( PaintFriendList )(HDC hdc) =0;
STDMETHOD( CreateFriendList )() =0;
STDMETHOD( DestroyFriendList )() =0;
STDMETHOD( SetMaskWindowHandle )(HWND hWnd) =0;
STDMETHOD( GetPlayOnlineRegKeyNameW )(LPWSTR* outName) =0;
STDMETHOD( GetPlayOnlineRegKeyNameA )(LPSTR * outName) =0;
STDMETHOD( GetSquareEnixRegKeyNameW )(LPWSTR* outName) =0;
STDMETHOD( GetSquareEnixRegKeyNameA )(LPSTR* outName) =0;
STDMETHOD( SetAreaCode )(LONG inAreaCode) =0;
STDMETHOD( GetAreaCode )(LONG* outAreaCode) =0;
STDMETHOD( HideMaskWindow )(LONG inCode) =0;
STDMETHOD( ShowMaskWindow )(LONG inCode) =0;
STDMETHOD( IsVisibleMaskWindow )(LONG* outIsVisible) =0;
};
struct IFFXiEntry: IUnknown{ // IConnectionPointContainer
STDMETHOD( GameStart )(IUnknown* pPol, IUnknown** pFFXiMessage) =0;
STDMETHOD( get_FxFileManager )(/* IFxFileManager** */ IUnknown** pVal) =0;
STDMETHOD( getVersion )(ULONG* pVal) =0;
};
//----------------------------------------------------------------------------
void _put_time(){
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
SYSTEMTIME t;
GetLocalTime(&t);
fprintf(stdout, "[%02d/%02d/%02d %02d:%02d:%02d.%03d] ", t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond, t.wMilliseconds);
}
void _put_format_message(DWORD errcode){
char buffer[512];
int rv = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, errcode, LOCALE_USER_DEFAULT, buffer, sizeof(buffer), NULL);
if(rv>0){
fputs(buffer, stdout);
fputc('\n', stdout);
}
}
void errmsg(const char* fmt, ...){
_put_time();
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
fputs("ERROR::", stdout);
va_list va;
va_start(va, fmt);
vfprintf(stdout, fmt, va);
va_end(va);
fflush(stdout);
}
void errmsg_hresult(HRESULT errcode, const char* msg){
errmsg("%s (0x%08x)\n", msg, errcode);
_put_format_message( (DWORD)errcode );
fflush(stdout);
}
void errmsg_win32(DWORD errcode, const char* msg){
errmsg("%s (%d)\n", msg, errcode);
_put_format_message( (DWORD)errcode );
fflush(stdout);
}
void errmsg_wsa(int errcode, const char* msg){
errmsg("%s (%d)\n", msg, errcode);
_put_format_message( (DWORD)errcode );
fflush(stdout);
}
void infomsg(const char* fmt, ...){
_put_time();
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
va_list va;
va_start(va, fmt);
vfprintf(stdout, fmt, va);
va_end(va);
fflush(stdout);
}
//----------------------------------------------------------------------------
int g_ffxi_serv_address = 0x0100007F; //127.0.0.1
int g_pol_serv_address = 0x0100007F; //127.0.0.1
char g_ffxi_serv_name[128] = "127.0.0.1"; // ffxi00.pol.com
char g_pol_serv_name[128] = "127.0.0.1"; // pp000.pol.com
bool g_pol_serv_internal = true;
volatile bool g_is_new_char = false;
volatile HKEY g_reg_hook_key = (HKEY) 0x80000010;
struct UserData{
DWORD account_id;
void* charlist;
SOCKET login_sock;
char name [16+1];
char password [16+1];
DWORD config_values[35];
//
UserData(){
account_id = 0;
charlist = 0;
login_sock = INVALID_SOCKET;
memset(name, 0, sizeof(name));
memset(password, 0, sizeof(password));
memset(config_values, 0xFF, sizeof(config_values));
}
};
UserData g_user;
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
namespace ApiHook{
typedef HRESULT (WINAPI * type_CoCreateInstance)(REFCLSID, IUnknown*, DWORD, REFIID, void**);
typedef LONG (WINAPI * type_RegCreateKeyExA)(HKEY, LPCSTR, DWORD, LPCSTR, DWORD, REGSAM, SECURITY_ATTRIBUTES*, HKEY*, DWORD*);
typedef LONG (WINAPI * type_RegQueryValueExA)(HKEY, LPCSTR, DWORD*, DWORD*, BYTE*, DWORD*);
typedef LONG (WINAPI * type_RegCloseKey)(HKEY key);
typedef struct hostent* (WSAAPI * type_gethostbyname)(const char*);
type_CoCreateInstance orig_CoCreateInstance =0;
type_RegCreateKeyExA orig_RegCreateKeyExA =0;
type_RegQueryValueExA orig_RegQueryValueExA =0;
type_RegCloseKey orig_RegCloseKey =0;
type_gethostbyname orig_gethostbyname =0;
void _install_module(BYTE* head);
HRESULT WINAPI hook_CoCreateInstance(REFCLSID rclsid, IUnknown* outer, DWORD flags, REFIID riid, void** ppv){
HRESULT hr = orig_CoCreateInstance(rclsid, outer, flags, riid, ppv);
if(SUCCEEDED(hr)){
_install_module( (BYTE*)GetModuleHandleA("polcore.dll") );
_install_module( (BYTE*)GetModuleHandleA("polcoreE.dll") );
_install_module( (BYTE*)GetModuleHandleA("FFXi.dll") );
_install_module( (BYTE*)GetModuleHandleA("FFXiMain.dll") );
}
return hr;
}
LONG WINAPI hook_RegCreateKeyExA(HKEY key, LPCSTR subkey, DWORD reserved, LPCSTR classname, DWORD opt, REGSAM sam, SECURITY_ATTRIBUTES* sa, HKEY* pkey, DWORD* dispos){
LONG rv = orig_RegCreateKeyExA(key, subkey, reserved, classname, opt, sam, sa, pkey, dispos);
if(rv == ERROR_SUCCESS && key == HKEY_LOCAL_MACHINE){
if(_stricmp(subkey, "SOFTWARE\\PlayOnline\\SQUARE\\FinalFantasyXI") == 0 ||
_stricmp(subkey, "SOFTWARE\\PlayOnlineUS\\SQUARE\\FinalFantasyXI") == 0 ||
_stricmp(subkey, "SOFTWARE\\PlayOnlineEU\\SQUARE\\FinalFantasyXI") == 0){
g_reg_hook_key = *pkey;
}
}
return rv;
}
LONG WINAPI hook_RegQueryValueExA(HKEY key, LPCSTR name, DWORD* reserved, DWORD* type, BYTE* data, DWORD* cbdata){
if(g_reg_hook_key == key && name && type && data && cbdata){
if( *name == '0' && *cbdata >= sizeof(DWORD) ){
int id = atoi(name);
if(0 <= id && id < ARRAYSIZE(g_user.config_values)){
if(g_user.config_values[id] != 0xFFFFFFFF){
*((DWORD*)data) = g_user.config_values[id];
*type = REG_DWORD;
*cbdata = sizeof(DWORD);
return ERROR_SUCCESS;
}
}
}
}
return orig_RegQueryValueExA(key, name, reserved, type, data, cbdata);
}
LONG WINAPI hook_RegCloseKey(HKEY key){
if(g_reg_hook_key == key)
g_reg_hook_key = (HKEY) 0x80000010;
return orig_RegCloseKey(key);
}
struct hostent* WSAAPI hook_gethostbyname(const char* name){
if(name){
infomsg("Resolving %s\n", name);
static struct in_addr tmp_addr;
static struct in_addr* tmp_addrlist[2] = { &tmp_addr, NULL };
static struct hostent tmp = { NULL, NULL, AF_INET, 4, (char**)tmp_addrlist };
if(_stricmp(name, "ffxi00.pol.com") == 0){
tmp_addr.S_un.S_addr = g_ffxi_serv_address;
return &tmp;
}
else if(_stricmp(name, "pp000.pol.com") == 0){
tmp_addr.S_un.S_addr = g_pol_serv_address;
return &tmp;
}
}
return orig_gethostbyname(name);
}
//--------------------------------------------------------------------
void _install_func(IMAGE_THUNK_DATA* iat, DWORD hook){
if(iat->u1.Function != hook){
DWORD old;
if(VirtualProtect(&iat->u1.Function, 4, PAGE_EXECUTE_READWRITE, &old)){
iat->u1.Function = hook;
VirtualProtect(&iat->u1.Function, 4, old, &old);
}
}
}
void _install_module(BYTE* head){
if(!head) return;
IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)(head + 0);
IMAGE_NT_HEADERS* nt = (IMAGE_NT_HEADERS*)(head + dos->e_lfanew);
IMAGE_DATA_DIRECTORY* dir = nt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT;
if(!dir->VirtualAddress || !dir->Size) return;
IMAGE_IMPORT_DESCRIPTOR* imp = (IMAGE_IMPORT_DESCRIPTOR*)(head + dir->VirtualAddress);
for(; imp->FirstThunk; ++imp){
LPCSTR dllname = (LPCSTR)(head + imp->Name);
IMAGE_THUNK_DATA* pint = (IMAGE_THUNK_DATA*)(head + imp->OriginalFirstThunk);
IMAGE_THUNK_DATA* piat = (IMAGE_THUNK_DATA*)(head + imp->FirstThunk);
if(_stricmp(dllname, "Ole32.dll") == 0){
for(; piat->u1.Function; ++piat, ++pint){
if(IMAGE_SNAP_BY_ORDINAL(pint->u1.Ordinal)){
}
else{
LPCSTR procname = (LPCSTR) ((IMAGE_IMPORT_BY_NAME*)(head + pint->u1.AddressOfData))->Name;
if(strcmp(procname, "CoCreateInstance")==0){
_install_func(piat, (DWORD) hook_CoCreateInstance);
}
}
}
}
else if(_stricmp(dllname, "AdvApi32.dll") == 0){
for(; piat->u1.Function; ++piat, ++pint){
if(IMAGE_SNAP_BY_ORDINAL(pint->u1.Ordinal)){
}
else{
LPCSTR procname = (LPCSTR) ((IMAGE_IMPORT_BY_NAME*)(head + pint->u1.AddressOfData))->Name;
if(strcmp(procname, "RegCreateKeyExA")==0){
_install_func(piat, (DWORD) hook_RegCreateKeyExA);
}
else if(strcmp(procname, "RegQueryValueExA")==0){
_install_func(piat, (DWORD) hook_RegQueryValueExA);
}
else if(strcmp(procname, "RegCloseKey")==0){
_install_func(piat, (DWORD) hook_RegCloseKey);
}
}
}
}
else if(_stricmp(dllname, "Ws2_32.dll")==0){
for(; piat->u1.Function; ++piat, ++pint){
if(IMAGE_SNAP_BY_ORDINAL(pint->u1.Ordinal)){
DWORD id = IMAGE_ORDINAL(pint->u1.Ordinal);
if(id == 52){
_install_func(piat, (DWORD) hook_gethostbyname);
}
}
}
}
}
}
void Initialize(){
HMODULE self = GetModuleHandleA(0);
HMODULE ole = GetModuleHandleA("Ole32.dll");
HMODULE ws2 = GetModuleHandleA("Ws2_32.dll");
HMODULE adv = GetModuleHandleA("AdvApi32.dll");
orig_CoCreateInstance = (type_CoCreateInstance) GetProcAddress(ole, "CoCreateInstance");
orig_RegCreateKeyExA = (type_RegCreateKeyExA) GetProcAddress(adv, "RegCreateKeyExA");
orig_RegQueryValueExA = (type_RegQueryValueExA) GetProcAddress(adv, "RegQueryValueExA");
orig_RegCloseKey = (type_RegCloseKey) GetProcAddress(adv, "RegCloseKey");
orig_gethostbyname = (type_gethostbyname) GetProcAddress(ws2, "gethostbyname");
_install_module((BYTE*)self);
}
};//namespace ApiHook
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
SOCKET init_tcp_socket(const char* name, const char* port, bool is_server = false){
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if(is_server){
hints.ai_flags = AI_PASSIVE;
}
struct addrinfo* info = 0;
SOCKET result = INVALID_SOCKET;
SOCKET sock = INVALID_SOCKET;
int rv = getaddrinfo(name, port, &hints, &info);
if(rv){
}
else{
for(struct addrinfo* p = info; p; p = p->ai_next){
sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if(sock == INVALID_SOCKET){
}
else if(is_server){
rv = bind(sock, p->ai_addr, p->ai_addrlen);
if(rv == SOCKET_ERROR){
}
else{
rv = listen(sock, SOMAXCONN);
if(rv == SOCKET_ERROR){
}
else{
result = sock;
sock = INVALID_SOCKET;
break;
}
}
}
else{
rv = connect(sock, p->ai_addr, p->ai_addrlen);
if(rv == SOCKET_ERROR){
}
else{
result = sock;
sock = INVALID_SOCKET;
break;
}
}
}
}
rv = WSAGetLastError();
if(sock != INVALID_SOCKET)
closesocket(sock);
if(info != NULL)
freeaddrinfo(info);
WSASetLastError(rv);
return result;
}
int gen_data_packet(BYTE* output, BYTE* input){
int size = 0;
infomsg("FFXiLobbyClient::Incoming Packet %i\n", input[0]);
switch(input[0]){
case 1:
{
infomsg("FFXiLobbyClient::Sending Account-id... %d\n", g_user.account_id);
size = 9;
memset(output, 0, size);
output[0] = 0xA1;
memcpy(output+1, &g_user.account_id, 4);
memcpy(output+5, &g_ffxi_serv_address, 4);
}
break;
case 2:
case 21:
{
infomsg("FFXiLobbyClient::Sending Key...\n");
size = 25;
memset(output, 0, size);
output[0] = 0xA2;
output[17] = 0x58;
output[18] = 0xE0;
output[19] = 0x5D;
output[20] = 0xAD;
if(input[0]==21){
g_is_new_char = true;
}
}
break;
case 3:
{
infomsg("FFXiLobbyClient::Receiving Charlist...\n");
BYTE* dst = (BYTE*) g_user.charlist;
BYTE* src1 = input + 20;
BYTE* src2 = input + 16;
if(dst){
for(int i=0; i < input[1]; i++){
dst[0x00] = 0x01;
dst[0x02] = 0x01;
*((DWORD*)(dst+0x04)) = *((DWORD*)src1);
*((DWORD*)(dst+0x08)) = *((DWORD*)src2);
dst[0x10] = 0x00;
dst[0x11] = 0x80;
dst[0x18] = 0x20;
dst[0x28] = 0x20;
dst += 104;
src1 += 20;
src2 += 16;
}
}
}
break;
default:
break;
}
return size;
}
UINT CALLBACK FFXiLobbyClient(void* lp){
SOCKET sock = init_tcp_socket(g_ffxi_serv_name, "54230");
if(sock==INVALID_SOCKET){
errmsg_wsa(WSAGetLastError(), "FFXiLobbyClient::init_tcp_socket");
return 0;
}
infomsg("FFXiLobbyClient::Connected to server.\n");
BYTE recvbuf[4096], zone[4096];
int rv, size, socksize;
struct sockaddr_in client;
for(;;){
socksize = sizeof(client);
rv = recvfrom(sock, (char*)recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&client, &socksize);
if(rv == SOCKET_ERROR){
errmsg_wsa(WSAGetLastError(), "FFXiLobbyClient::recvfrom");
break;
}
size = gen_data_packet(zone, recvbuf);
if(size > 0){
Sleep(50);
rv = sendto(sock, (char*)zone, size, 0, (struct sockaddr*)&client, socksize);
if(rv == SOCKET_ERROR){
errmsg_wsa(WSAGetLastError(), "FFXiLobbyClient::sendto");
break;
}
if(size == 72){
break;
}
}
}
shutdown(sock, SD_SEND);
closesocket(sock);
infomsg("FFXiLobbyClient::terminate.\n");
return 0;
}
void getline(char* buffer, size_t size){
memset(buffer, 0, size);
fgets(buffer, size, stdin);
char* s = buffer;
while(*s < 0x21 || 0x7E < *s) s++;
char* e = s + strlen(s) -1;
while(*e < 0x21 || 0x7E < *e) *e-- = 0;
if(s > buffer) for(e=buffer; *s; *e++ = *s++);
}
bool FFXiLogIn(){
bool first = true;
for(;;){
SOCKET sock = init_tcp_socket(g_ffxi_serv_name, "54231");
if(sock==INVALID_SOCKET){
errmsg_wsa(WSAGetLastError(), "FFXiLogin::init_tcp_socket");
return false;
}
BYTE sendbuf[64], recvbuf[64];
char username[17], password[17], password2[17];
int rv, choise;
infomsg("FFXiLogin::Connected to server.\n");
if(first && g_user.name[0] && g_user.password[0]){
first = false;
memcpy(sendbuf+0, g_user.name, 16);
memcpy(sendbuf+16, g_user.password, 16);
sendbuf[32] = 0x10;
}
else{
MENU:
infomsg("-----------------------------------\n");
infomsg("What do you want to do?\n");
infomsg("1) Log in using an existing account\n");
infomsg("2) Create a new account\n");
infomsg("->");
getline(username, sizeof(username));
choise = atoi(username);
switch(choise){
default:
goto MENU;
case 1:
infomsg("Enter your username and password to login.\n");
infomsg("Username: ");
getline(username, sizeof(username));
infomsg("Password: ");
getline(password, sizeof(password));
sendbuf[32] = 0x10;
break;
case 2:
for(;;){
infomsg("Enter your desired username and password.\n");
infomsg("Username: ");
getline(username, sizeof(username));
infomsg("Password: ");
getline(password, sizeof(password));
infomsg("Repeat password: ");
getline(password2, sizeof(password2));
if(strlen(username) <= 0){
continue;
}
if(strlen(password) <= 0){
continue;
}
if(memcmp(password, password2, 16) != 0){
errmsg("Passwords do not match, please try again!\n");
continue;
}
break;
}
sendbuf[32] = 0x20;
break;
}
memcpy(sendbuf+0, username, 16);
memcpy(sendbuf+16, password, 16);
}
rv = send(sock, (char*)sendbuf, 33, 0);
if(rv == SOCKET_ERROR){
errmsg_wsa(WSAGetLastError(), "FFXiLogIn::send");
}
Sleep(50);
rv = recv(sock, (char*)recvbuf, 16, 0);
if(rv == SOCKET_ERROR){
errmsg_wsa(WSAGetLastError(), "FFXiLogIn::recv");
}
switch(recvbuf[0]){
case 0x01: //SUCCESS_LOGIN
infomsg("Successfully logged in\n");
g_user.account_id = *((DWORD*)(recvbuf+1));
g_user.login_sock = sock;
return true;
case 0x02: //ERROR_LOGIN
errmsg("You could not be logged in!\n");
errmsg("Did you enter the right password?\n");
break;
case 0x03: //SUCCESS_CREATE_ACCOUNT
infomsg("Account successfully created\n");
break;
case 0x04: //ERROR_CREATE_ACCOUNT
errmsg("Account could not be created!\n");
errmsg("The username is already taken\n");
break;
}
closesocket(sock);
}
return false;
}
UINT CALLBACK POLServer(void* lp){
SOCKET listenSock = init_tcp_socket("127.0.0.1", "51220", true);
if(listenSock == INVALID_SOCKET){
errmsg_wsa(WSAGetLastError(), "POLServer::init_tcp_socket");
return 0;
}
for(;;){
SOCKET clientSock = accept(listenSock, NULL, NULL);
if(clientSock == INVALID_SOCKET){
errmsg_wsa(WSAGetLastError(), "POLServer::accept");
break;
}
BYTE recvbuf[1024];
int rv, i=0;
for(;;){
rv = recv(clientSock, (char*) recvbuf, sizeof(recvbuf), 0);
if(rv < 1){
errmsg_wsa(WSAGetLastError(), "POLServer::recv");
break;
}
else{
infomsg("POLServer::recv idx=%d,cmd=%d\n", i, recvbuf[0]);
memset(recvbuf, 0, 32);
switch(i){
case 0:
rv = 24;
recvbuf[0] = 0x81;
_time64( (_int64*)(recvbuf+20) );
break;
case 1:
if(g_is_new_char){
g_is_new_char = false;
rv = 144;
}
else{
rv = 24;
}
recvbuf[0] = 0x28;
recvbuf[4] = 0x20;
recvbuf[8] = 0x01;
recvbuf[11] = 0x7F;
break;
}
Sleep(50);
//echo
rv = send(clientSock, (char*)recvbuf, rv, 0);
if(rv == SOCKET_ERROR){
errmsg_wsa(WSAGetLastError(), "POLServer::send");
break;
}
}
if(++i == 3) break;
}
infomsg("POLServer::client shutdown\n");
shutdown(clientSock, SD_SEND);
closesocket(clientSock);
}
closesocket(listenSock);
infomsg("POLServer::terminate.\n");
return 0;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
HMODULE POLCore_GetModule(){
static HMODULE module = 0;
if(!module){
module = GetModuleHandleA("polcore.dll");
if(!module)
module = GetModuleHandleA("polcoreE.dll");
}
return module;
}
void* POLCore_GetInitFunc(){
static const BYTE code[] = {
//0x83,0xC4,0x10 // add esp,10h
//0xE8, xx, xx, xx, xx // call xxxxxxxxh <-- target
0x8B,0x56,0x2C, // mov edx, [esi+2Ch];
0x8B,0x46,0x28, // mov eax, [esi+28h];
0x8B,0x4E,0x24, // mov ecx, [esi+24h];
0x52, // push edx;
0x50, // push eax;
0x51, // push ecx;
};
BYTE* head = (BYTE*) POLCore_GetModule();
if(head){
IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)(head + 0);
IMAGE_NT_HEADERS* nt = (IMAGE_NT_HEADERS*)(head + dos->e_lfanew);
IMAGE_SECTION_HEADER* section = IMAGE_FIRST_SECTION(nt);
BYTE* ptr = head + section->VirtualAddress + 4;
BYTE* end = ptr + section->Misc.VirtualSize - sizeof(code);
for(; ptr < end; ++ptr){
if(memcmp(ptr, code, sizeof(code)) == 0){
int* dw = (int*)(ptr-4);
return ptr + (*dw);
}
}
}
return 0;
}
void* POLCore_GetWorkArea(){
static const BYTE code[] = {
//nop
//push esi
//call 1002ACD0
//mov esi, 10402BC0 <-- target
//push esi
//call 10019D10
0x81,0xC6,0x38,0x03,0x00,0x00, //add esi, 0338h;
0x83,0xC4,0x04, //add esp, 4
0x81,0xFE, //cmp esi, 104028A0
//jl 1001DF3B
//call 1002AD10
//pop esi
//ret
//nop
};
BYTE* head = (BYTE*) POLCore_GetModule();
if(head){
IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)(head + 0);
IMAGE_NT_HEADERS* nt = (IMAGE_NT_HEADERS*)(head + dos->e_lfanew);
IMAGE_SECTION_HEADER* section = IMAGE_FIRST_SECTION(nt);
BYTE* ptr = head + section->VirtualAddress + 10;
BYTE* end = ptr + section->Misc.VirtualSize - sizeof(code);
for(; ptr < end; ++ptr){
if(memcmp(ptr, code, sizeof(code)) == 0){
void** vp = (void**)(ptr-10);
return (*vp);
}
}
}
return 0;
}
bool FFXiClientMain(){
static const CLSID CLSID_POLCoreCom[] = {
{0x07974581, 0x0df6, 0x4ef0, {0xbd, 0x05, 0x60, 0x4b, 0x3a, 0xda, 0x9b, 0xe9}}, // JP
{0x3501f5dd, 0x7894, 0x42df, {0x86, 0x6a, 0xa2, 0xb6, 0x52, 0x7d, 0x80, 0x49}}, // US
{0xe5966fb3, 0xc97b, 0x42eb, {0x84, 0xbf, 0x37, 0xf9, 0x5e, 0xe5, 0x4a, 0x9f}}, // EU
};
static const IID IID_IPOLCoreCom[] = {
{0x9a30d565, 0xa74c, 0x4b56, {0xb9, 0x71, 0xdc, 0xf0, 0x21, 0x85, 0xb1, 0x0d}}, // JP
{0xe0516654, 0xef77, 0x435d, {0xaa, 0x7d, 0x50, 0xd2, 0xc0, 0x69, 0xce, 0x34}}, // US
{0xdfec2e93, 0x4971, 0x4a54, {0xb8, 0xed, 0x63, 0x81, 0x5c, 0x20, 0x8c, 0x5a}}, // EU
};
static const CLSID CLSID_FFXiEntry = {0x989d790d, 0x6236,0x11d4,{0x80,0xe9,0x00,0x10,0x5a,0x81,0xe8,0x90}};
static const IID IID_FFXiEntry = {0x989d790c, 0x6236,0x11d4,{0x80,0xe9,0x00,0x10,0x5a,0x81,0xe8,0x90}};
IPOLCoreCom* polcore = 0;
IFFXiEntry* ffxi = 0;
IUnknown* errinfo = 0;//IErrorInfo?
HANDLE pol_serv_thread = 0;
HANDLE ffxi_lobby_thread = 0;
HRESULT hr;
bool result = true;
do{
hr = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
if(FAILED(hr)){
errmsg_hresult(hr, "CoInitializeEx");
break;
}
//if(SetCurrentDirectory(L"C:\\Program Files\\PlayOnline\\SquareEnix\\PlayOnlineViewer")){
//}
//if(SetCurrentDirectory(L"C:\\Program Files\\PlayOnline\\SquareEnix\\FINAL FANTASY XI")){
//}
int lang = 0; // 0=JA, 1=US, 2=EU
for(; lang < 3; ++lang){
hr = CoCreateInstance( CLSID_POLCoreCom[lang], NULL, 0x17, IID_IPOLCoreCom[lang], (void**)&polcore );
if(SUCCEEDED(hr)) break;
}
if(FAILED(hr)){
errmsg_hresult(hr, "CoCreateInstance(POLCore)");
break;
}
//
void** cmn_funcs;
hr = polcore->GetCommonFunctionTable( (unsigned long**) &cmn_funcs );
if(FAILED(hr)){
errmsg_hresult(hr, "IPOLCore::GetCommonFunctionTable");
break;
}
typedef int (_cdecl * FUNC0)();
typedef int (_cdecl * FUNC1)(int);
FUNC0 func0;
FUNC1 func1;
func0 = (FUNC0) POLCore_GetInitFunc();
if(!func0){
errmsg("POLCore_GetInitFunc\n");
break;
}
(*func0)();
void** ptr = (void**) POLCore_GetWorkArea();
if(!ptr){
errmsg("POLCore_GetWorkArea\n");
break;
}
memset(ptr, 0, 104);
void* buffer = malloc(0x1000);
memset(buffer, 0, 0x1000);
ptr[18] = buffer;
g_user.charlist = *( (void**)((BYTE*)cmn_funcs[211] + 0x1F) );
//infomsg("charlist %p %p\n", ptr, g_user.charlist);
func1 = (FUNC1) cmn_funcs[965];
if(!func1){
errmsg("POLCore::CommonFunction[965] NULL\n");
break;
}
(*func1)(lang);
func1 = (FUNC1) cmn_funcs[420];
if(!func1){
errmsg("POLCore::CommonFunction[420] NULL\n");
break;
}
(*func1)(lang);
hr = polcore->SetParamInitW(GetModuleHandle(0), L"");
if(FAILED(hr)){
errmsg_hresult(hr, "IPOLCore::SetParamInitW");
break;
}
hr = polcore->SetAreaCode(lang);
if(FAILED(hr)){
errmsg_hresult(hr, "IPOLCore::SetAreaCode");
break;
}
func0 = (FUNC0) cmn_funcs[815];
if(!func0){
errmsg("POLCore::CommonFunction[815] NULL\n");
break;
}
(*func0)();
hr = CoCreateInstance(CLSID_FFXiEntry, NULL, 0x17, IID_FFXiEntry, (void**)&ffxi);
if(FAILED(hr)){
errmsg_hresult(hr, "CoCreateInstance(FFXiEntry)");
break;
}
if(! FFXiLogIn() ){
break;
}
ffxi_lobby_thread = (HANDLE) _beginthreadex(0,0, FFXiLobbyClient,0, 0,0);
if(! ffxi_lobby_thread){
errmsg_win32(GetLastError(), "CreateThead(FFXiLobbyClient)");
break;
}
if(g_pol_serv_internal){
pol_serv_thread = (HANDLE) _beginthreadex(0,0, POLServer,0, 0,0);
if(! pol_serv_thread){
errmsg_win32(GetLastError(), "CreateThead(POLServer)");
break;
}
}
hr = ffxi->GameStart(polcore, &errinfo);
if(FAILED(hr)){
errmsg_hresult(hr, "IFFXiEntry::GameStart");
break;
}
result = true;
}while(0);
if(errinfo) errinfo->Release();
if(ffxi) ffxi->Release();
if(polcore) polcore->Release();
if(g_user.login_sock != INVALID_SOCKET){
closesocket(g_user.login_sock);
g_user.login_sock = INVALID_SOCKET;
}
if(ffxi_lobby_thread){
if(WaitForSingleObject(ffxi_lobby_thread, 100) == WAIT_TIMEOUT)
TerminateThread(ffxi_lobby_thread, 0);
CloseHandle(ffxi_lobby_thread);
}
if(pol_serv_thread){
if(WaitForSingleObject(pol_serv_thread, 100) == WAIT_TIMEOUT)
TerminateThread(pol_serv_thread, 0);
CloseHandle(pol_serv_thread);
}
CoUninitialize();
return result;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
bool resolve_hostname(const char* name, int* out_ip){
struct addrinfo hints, *info=0;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
int rv = getaddrinfo(name, "1000", &hints, &info);
if(rv) return false;
struct sockaddr_in* si = (struct sockaddr_in*) info->ai_addr;
*out_ip = si->sin_addr.S_un.S_addr;
freeaddrinfo(info);
return true;
}
int atobool(const char* value){
if(_stricmp(value, "yes") == 0 ||
_stricmp(value, "on") == 0 ||
_stricmp(value, "true") == 0)
return 1;
if(_stricmp(value, "off") == 0 ||
_stricmp(value, "no") == 0 ||
_stricmp(value, "false") == 0)
return 0;
int n = atoi(value);
return (n != 0) ? 1 : 0;
}
DWORD atodw(const char* value, int min, int max){
int n = atoi(value);
if(n < min) n = min;
else if(n > max) n = max;
return n;
}
DWORD atodw(const char* value, float min, float max){
float n = (float) atof(value);
if(n < min) n = min;
else if(n > max) n = max;
return *((DWORD*)&n);
}
char* trunc_ws(char* s){
while(*s < 0x21 || 0x7E < *s) s++;
char* e = s + strlen(s) -1;
while(*e < 0x21 || 0x7E < *e) *e-- = 0;
return s;
}
void LoadSettings(){
FILE *fp;
char *delm, *name, *value;
char line[MAX_PATH+8];
UINT len = GetModuleFileNameA(NULL, line, MAX_PATH);
if(len >= 4) line[len-4] = '\0';
strcat_s(line, sizeof(line), ".ini");
if(fopen_s(&fp, line, "r") == 0){
while(!feof(fp)){
line[0]=0;
fgets(line, sizeof(line), fp);
delm = strchr(line, '=');
if(delm){
*delm = 0;
name = trunc_ws(line);
value = trunc_ws(delm+1);
if(_stricmp(name, "FFXiServer")==0){
strcpy_s( g_ffxi_serv_name, sizeof(g_ffxi_serv_name), value );
}
else if(_stricmp(name, "POLServer")==0){
strcpy_s( g_pol_serv_name, sizeof(g_pol_serv_name), value );
}
else if(_stricmp(name, "POLServerInternal")==0){
g_pol_serv_internal = atodw(value, 0, 1) != 0;
}
else if(_stricmp(name, "Username")==0){
strcpy_s( g_user.name, sizeof(g_user.name), value );
}
else if(_stricmp(name, "Password")==0){
strcpy_s( g_user.password, sizeof(g_user.password), value );
}
//
else if(_stricmp(name, "Global.WindowedMode")==0){
g_user.config_values[34] = atobool(value);
}
else if(_stricmp(name, "Global.GammaBase")==0){
g_user.config_values[28] = atodw(value, -1.0f, +1.0f);
}
else if(_stricmp(name, "Screen.FrontBuffer.Width")==0){
g_user.config_values[1] = atodw(value, 320, 1920);
}
else if(_stricmp(name, "Screen.FrontBuffer.Height")==0){
g_user.config_values[2] = atodw(value, 240, 1200);
}
else if(_stricmp(name, "Screen.BackBuffer.Width")==0){
g_user.config_values[3] = atodw(value, 320, 1920);
}
else if(_stricmp(name, "Screen.BackBuffer.Height")==0){
g_user.config_values[4] = atodw(value, 240, 1200);
}
else if(_stricmp(name, "Texture.Compression")==0){
g_user.config_values[18] = atodw(value, 0, 2);
}
else if(_stricmp(name, "Texture.OnScreenMaps")==0){
g_user.config_values[19] = atodw(value, 0, 1);
}
else if(_stricmp(name, "3DMap.Mipmap")==0){
g_user.config_values[0] = atobool(value);
}
else if(_stricmp(name, "3DMap.Bumpmap")==0){
g_user.config_values[17] = atobool(value);
}
else if(_stricmp(name, "3DMap.DeformAnimation")==0){
g_user.config_values[11] = atodw(value, 0, 2);
}
else if(_stricmp(name, "Sound.Enable")==0){
g_user.config_values[7] = atobool(value);
}
else if(_stricmp(name, "Sound.EffectNum")==0){
g_user.config_values[29] = atodw(value, 12, 32);
}
else if(_stricmp(name, "Misc.ShowOpeningMovie")==0){
g_user.config_values[22] = atobool(value);
}
else if(_stricmp(name, "Misc.HardwareMouseCursor")==0){
g_user.config_values[21] = atobool(value);
}
else if(_stricmp(name, "Misc.SimpleCharacterCreation")==0){
g_user.config_values[23] = atobool(value);
}
}
}
fclose(fp);
}
resolve_hostname(g_ffxi_serv_name, &g_ffxi_serv_address);
if(! g_pol_serv_internal){
resolve_hostname(g_pol_serv_name, &g_pol_serv_address);
}
else{
g_pol_serv_address = inet_addr("127.0.0.1");
strcpy_s(g_pol_serv_name, sizeof(g_pol_serv_name), "127.0.0.1");
}
infomsg("FFXiServer \"%s\" (%s)\n", g_ffxi_serv_name, inet_ntoa(*((struct in_addr*)&g_ffxi_serv_address)));
infomsg("POLServer \"%s\" (%s)\n", g_pol_serv_name, inet_ntoa(*((struct in_addr*)&g_pol_serv_address)));
if(g_user.name[0])
infomsg("Username \"%s\"\n", g_user.name);
}
int wmain(int argc, wchar_t* argv[]){
WSADATA wsadata;
memset(&wsadata, 0, sizeof(wsadata));
int err = WSAStartup(MAKEWORD(2,2), &wsadata);
if(err){
errmsg_wsa(err, "WSAStartup");
}
else{
LoadSettings();
ApiHook::Initialize();
FFXiClientMain();
}
WSACleanup();
return 0;
}
//EOF
-
- Developer
- Posts: 539
- Joined: Sun Jul 22, 2012 12:17 am
Re: ffxi-boot source code?
Worth noting that FFXI-Boot Mod is built from completely different source, and that the original FFXI-Boot has some flaws.
Test Server: Hanekawa | Fantasy World: Naito
An occasionally updated list of what works
Bugs reports go here. | Project chat here.
Things I've found, but don't plan to work on.
An occasionally updated list of what works
Bugs reports go here. | Project chat here.
Things I've found, but don't plan to work on.
Re: ffxi-boot source code?
It's closed source. No, I don't have it.WiiStream wrote:well could we have the one that works?
-
- Developer
- Posts: 707
- Joined: Sun Jul 22, 2012 12:11 am
Re: ffxi-boot source code?
The code was given to me with the understanding that I not share it with the general public. I may not wholly agree with the wishes of the person who gave the code to me but I'll certainly respect them.