// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"

#include <iostream>
#include <windows.h>
#include <TlHelp32.h>
#include <string>

uintptr_t GetModuleBaseAddress(DWORD procId, const wchar_t* modName) {
	uintptr_t modBaseAddr = 0;
	HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, procId);
	if (hSnap != INVALID_HANDLE_VALUE) {
		MODULEENTRY32 modEntry;
		modEntry.dwSize = sizeof(modEntry);
		if (Module32First(hSnap, &modEntry)) {
			do {
				if (!_wcsicmp(modEntry.szModule, modName)) {
					modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
					break;
				}
			} while (Module32Next(hSnap, &modEntry));
		}
	}
	CloseHandle(hSnap);
	return modBaseAddr;
}

void show_message(std::string str) {
	std::wstring wstr = std::wstring(str.begin(), str.end());
	MessageBox(NULL, wstr.c_str(), L"", MB_OK | MB_SETFOREGROUND);
}

void __fastcall draw_bunch_of_strings(void* string_struct, int* DAT_1026e9c4) {
	int counter;

	counter = 0;
	if ((DAT_1026e9c4 == (int*)0x0) || (*DAT_1026e9c4 == 0)) {
		do {
			if (*(int*)((int)string_struct + counter * 4) != 0) {
				const char* rendered_text = *(char**)((int)string_struct + counter * 4 + 0x2400);
				// rendered_text holds all rendered_text on screen
				size_t len = strlen(rendered_text);
				std::string out;
				for (size_t i = 0; i < len; i++) 
					out += rendered_text[i];
				show_message(out);
			}
			counter = counter + 1;
		} while (counter != 0x900);
	}
	return;
}

int read_4_bytes(LPCVOID address) {
	int buf;
	LPCVOID test;
	ReadProcessMemory(GetCurrentProcess(), address, &buf, 4, NULL);
	return buf;
}

void init() {
	uintptr_t base = GetModuleBaseAddress(GetCurrentProcessId(), L"samp.dll");

	int DAT_1026ea24 = read_4_bytes((LPCVOID)(base + 0x26ea24));
	int DAT_1026ea0c = read_4_bytes((LPCVOID)(base + 0x26ea0c));

	show_message(std::to_string(DAT_1026ea24));

	if (DAT_1026ea24 != 0 && DAT_1026ea0c != 0x0) {
		void* string_struct = (void*)(read_4_bytes((LPCVOID)(read_4_bytes((LPCVOID)(DAT_1026ea0c + 0x3de)) + 0x20)));
		if (string_struct != 0x0) {	
			int* DAT_1026e9c4 = (int*)read_4_bytes((LPCVOID)(base + 0x26e9c4));
			draw_bunch_of_strings(string_struct, DAT_1026e9c4);
		}
	}
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
		init();
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

