ffxi-boot source code?

Any discussion not related to the other forum topics
Post Reply
WiiStream

ffxi-boot source code?

Post by WiiStream » Fri Feb 01, 2013 11:48 am

is there any way to get the ffxi-boot c++ source code?

amaneshi
Posts: 2
Joined: Wed Apr 03, 2013 10:13 am

Re: ffxi-boot source code?

Post by amaneshi » Mon Apr 29, 2013 7:13 am

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


PrBlahBlahtson
Developer
Posts: 539
Joined: Sun Jul 22, 2012 12:17 am

Re: ffxi-boot source code?

Post by PrBlahBlahtson » Sat May 04, 2013 8:44 pm

Worth noting that FFXI-Boot Mod is built from completely different source, and that the original FFXI-Boot has some flaws.

WiiStream

Re: ffxi-boot source code?

Post by WiiStream » Wed Jul 31, 2013 11:24 am

well could we have the one that works?

xipies
Posts: 119
Joined: Thu Aug 02, 2012 11:29 pm

Re: ffxi-boot source code?

Post by xipies » Wed Jul 31, 2013 11:27 pm

WiiStream wrote:well could we have the one that works?
It's closed source. No, I don't have it.

bluekirby0
Developer
Posts: 707
Joined: Sun Jul 22, 2012 12:11 am

Re: ffxi-boot source code?

Post by bluekirby0 » Sun Jan 26, 2014 5:08 am

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.

Post Reply