aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--build.bat50
-rw-r--r--compile_flags.txt10
-rw-r--r--src/main.c601
4 files changed, 662 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/build.bat b/build.bat
new file mode 100644
index 0000000..8b3fc6c
--- /dev/null
+++ b/build.bat
@@ -0,0 +1,50 @@
+@ECHO OFF
+
+:: Unpack Arguments
+set release=0
+for %%a in (%*) do set "%%a=1"
+
+set BUILD_DIR=build
+
+:: Clean directory
+IF EXIST %BUILD_DIR% rmdir %BUILD_DIR%\ /S /Q
+
+mkdir build
+
+set VS2022_COM="C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat"
+set VS2022_PRO="C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvars64.bat"
+
+if EXIST %VS2022_COM% (
+ call %VS2022_COM%
+ goto compilation
+)
+if EXIST %VS2022_PRO% (
+ call %VS2022_PRO%
+ goto compilation
+)
+
+
+:compilation
+set C_FLAGS=/nologo /W4 /WX /Zi /GS- /GR- /Gs1000000000 /Fo:%BUILD_DIR%\ /Iinclude /Isrc /std:clatest /c /Tc
+set L_FLAGS=/WX /SUBSYSTEM:CONSOLE /NODEFAULTLIB /stack:0x100000,0x100000
+
+if "%release%"=="0" (
+ set C_FLAGS=/Od %C_FLAGS%
+ set L_FLAGS=/DEBUG %L_FLAGS%
+)
+
+
+:: DBG
+:: Compile
+cl /Fd:%BUILD_DIR%\main.pdb %C_FLAGS% src\main.c
+
+:: Link
+link %L_FLAGS% /OUT:%BUILD_DIR%\main.exe %BUILD_DIR%\main.obj kernel32.lib
+
+:: Test program
+REM set SRC_FILE=test
+:: Compile
+REM cl /Fd:%BUILD_DIR%\%SRC_FILE%.pdb %C_FLAGS% src/%SRC_FILE%.c
+
+:: Link
+REM link %L_FLAGS% %BUILD_DIR%\%SRC_FILE%.obj /OUT:%BUILD_DIR%\%SRC_FILE%.exe kernel32.lib
diff --git a/compile_flags.txt b/compile_flags.txt
new file mode 100644
index 0000000..9ffefff
--- /dev/null
+++ b/compile_flags.txt
@@ -0,0 +1,10 @@
+/W4
+/WX
+/Zi
+/GS-
+/GR-
+/Gs1000000000
+/Fo:%BUILD_DIR%\
+/Iinclude
+/Isrc
+/std:clatest
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..c8a9899
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,601 @@
+// #include <winternl.h>
+#include <Windows.h>
+#include <strsafe.h>
+
+#include <stdint.h>
+#include <winnt.h>
+
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+
+typedef int8_t i8;
+typedef int16_t i16;
+typedef int32_t i32;
+typedef int64_t i64;
+
+const u32 TEXT_SECTION_FLAGS = (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ);
+const u32 DRECTVE_SECTION_FLAGS = (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE);
+const u64 lib_signature = 0x0A3E686372613C21; // IMAGE_ARCHIVE_START
+
+#define ALIGN(x, align) (((x) + (align - 1U)) / (align)) * (align)
+
+struct coff_header {
+ u16 machine_type;
+ u16 sections_count;
+ u32 timestamp;
+ u32 symbol_table_offset;
+ u32 symbols_count;
+ u16 optional_header_size;
+ u16 characteristics;
+};
+
+#pragma pack(1)
+struct coff_symbol {
+ union {
+ u8 name[8U];
+ struct {
+ u32 zeroes;
+ u32 offset;
+ };
+ };
+ u32 value;
+ i16 section_number;
+ u16 type;
+ u8 storage_class;
+ u8 number_of_aux_symbols;
+};
+
+// https://learn.microsoft.com/en-us/windows/win32/Debug/pe-format#section-table-section-headers
+struct section_header {
+ u8 name[8U];
+ u32 virtual_size;
+ u32 virtual_addr;
+ u32 size_of_raw_data;
+ u32 pointer_to_raw_data;
+ u32 pointer_to_relocations;
+ u32 pointer_to_line_numbers;
+ u16 number_of_relocations;
+ u16 number_of_line_numbers;
+ u32 characteristics;
+};
+
+struct base_relocation_block {
+ u32 page_rva;
+ u32 block_size;
+};
+
+struct relocation_entry {
+ // u16 type: 4;
+ // u16 offset: 12;
+
+ u32 virtual_address;
+ u32 symbol_index;
+ u16 type;
+};
+
+u8 is_alpha(char c) {
+ return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
+}
+
+u8 is_decimal_digit(char c) {
+ return '0' <= c && c <= '9';
+}
+
+u8 is_hexadecimal_digit(char c) {
+ return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F');
+}
+
+void u64toa(u64 number, char* str, u32 base) {
+ static char codes[16U] = {
+ '0',
+ '1',
+ '2',
+ '3',
+ '4',
+ '5',
+ '6',
+ '7',
+ '8',
+ '9',
+ 'A',
+ 'B',
+ 'C',
+ 'D',
+ 'E',
+ 'F',
+ };
+ u32 remainder = 0U;
+ u32 size = 0U;
+
+ if (number == 0) {
+ str[0U] = codes[0U];
+ return;
+ }
+
+ for(; number != 0U; size++) {
+ remainder = number % base;
+ number /= base;
+ str[size] = codes[remainder];
+ }
+
+ for(u32 i = 0; i < size / 2U; i++) {
+ char c = str[i];
+ str[i] = str[size - i - 1];
+ str[size - i - 1] = c;
+ }
+}
+
+u64 atou64(const char* str, u32 len) {
+ u64 number = 0U;
+ u32 base = 10U;
+ const char* c = str;
+
+ if (str[0] == '0' && str[1] == 'x') {
+ base = 16U;
+ c += 2U;
+ }
+
+ for (; (u32)(c - str) < len; c++) {
+ number *= base;
+ u32 offset = 0U;
+ if ('0' <= *c && *c <= '9') {
+ offset = 48U;
+ } else if ('a' <= *c && *c <= 'f') {
+ offset = 87U;
+ } else if ('A' <= *c && *c <= 'F') {
+ offset = 55U;
+ } else {
+ return 0U;
+ }
+
+ number += (*c - offset);
+ }
+
+ return number;
+}
+
+void print(const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ char formatted_str[4096U] = { 0 };
+ STRSAFE_LPSTR cur_char = formatted_str;
+
+ const char* cur_fmt = format;
+ while(*cur_fmt != '\0') {
+ if(*cur_fmt == '%') {
+ cur_fmt++;
+ if (*cur_fmt == 's') {
+ const char* str = va_arg(args, const char*);
+ size_t length = 0U;
+ if (cur_fmt[1U] == '.') {
+ const char* number_start = &cur_fmt[2U];
+ u32 size = 0U;
+ while(is_decimal_digit(*(number_start + size))) {
+ size++;
+ }
+ if (size > 0U) {
+ length = (size_t)atou64(number_start, size);
+ }
+ cur_fmt += size + 1U;
+ }
+ if (length == 0U) {
+ StringCchLengthA(str, sizeof(formatted_str), &length);
+ }
+ if(str != NULL) {
+ StringCchCatA(cur_char, length + 1U, str);
+ cur_char += length;
+ }
+ } else if(*cur_fmt == 'c') {
+ char c = va_arg(args, char);
+ StringCchCatA(cur_char, 1U, &c);
+ cur_char += 1U;
+ } else if (*cur_fmt == 'x' && is_alpha(cur_fmt[1])) {
+ u32 base = 16U;
+ *cur_char = '0';
+ cur_char++;
+ *cur_char = 'x';
+ cur_char++;
+ cur_fmt++;
+
+ if(*cur_fmt == 'b') {
+ u8 number = va_arg(args, u8);
+ u64toa((u64)number, cur_char, base);
+ size_t length = 0U;
+ StringCchLengthA(formatted_str, sizeof(formatted_str), &length);
+ cur_char = formatted_str + length;
+ } else if(*cur_fmt == 'u') {
+ u64 number = va_arg(args, u64);
+ u64toa(number, cur_char, base);
+ size_t length = 0U;
+ StringCchLengthA(formatted_str, sizeof(formatted_str), &length);
+ cur_char = formatted_str + length;
+ }
+ } else if(*cur_fmt == 'b') {
+ u8 number = va_arg(args, u8);
+ u64toa((u64)number, cur_char, 10U);
+ size_t length = 0U;
+ StringCchLengthA(formatted_str, sizeof(formatted_str), &length);
+ cur_char = formatted_str + length;
+ } else if(*cur_fmt == 'u') {
+ u64 number = va_arg(args, u64);
+ u64toa(number, cur_char, 10U);
+ size_t length = 0U;
+ StringCchLengthA(formatted_str, sizeof(formatted_str), &length);
+ cur_char = formatted_str + length;
+ }
+ } else {
+ *cur_char = *cur_fmt;
+ cur_char++;
+ }
+ cur_fmt++;
+ }
+ va_end(args);
+
+ HANDLE standard_err = GetStdHandle(STD_ERROR_HANDLE);
+ size_t length = (u8*)cur_char - (u8*)formatted_str;
+ SUCCEEDED(WriteFile(standard_err, formatted_str, (DWORD)length, NULL, NULL));
+}
+
+void read_COFF(u8* buffer) {
+ u8* next_byte = buffer;
+ struct coff_header header = *(struct coff_header*)next_byte;
+ next_byte += sizeof(header);
+
+ if (header.machine_type == IMAGE_FILE_MACHINE_AMD64) {
+ print("MACHINE: x64\n");
+ }
+
+ print("SECTIONS: %u\n", header.sections_count);
+ print("SYMBOLS COUNT: %u\n", header.symbols_count);
+
+ if (header.optional_header_size > 0U) {
+ IMAGE_OPTIONAL_HEADER64 optional_header = *(IMAGE_OPTIONAL_HEADER64*)next_byte;
+ print("MAGIC: %u\n", optional_header.Magic);
+ next_byte += header.optional_header_size;
+ }
+
+ struct coff_symbol* symbol_table = (struct coff_symbol*)(buffer + header.symbol_table_offset);
+ u8* string_table = (u8*)symbol_table + sizeof(*symbol_table) * header.symbols_count;
+
+ struct section_header* sections = (struct section_header*)next_byte;
+ next_byte += sizeof(sections[0]) * header.sections_count;
+ for (u32 section_index = 0U; section_index < header.sections_count; section_index++) {
+ struct section_header* section = &sections[section_index];
+ print("SECTION NAME: %s\n", section->name);
+ print("SECTION OFFSET: %u\n", section->pointer_to_raw_data);
+ print("SECTION SIZE: %u\n", section->size_of_raw_data);
+ print("SECTION RELOCATIONS COUNT: %u\n", section->number_of_relocations);
+
+ u8* reloc_start = &buffer[section->pointer_to_relocations];
+ struct relocation_entry* cur_reloc_entry = (struct relocation_entry*)reloc_start;
+
+ for (u32 reloc_index = 0U; reloc_index < section->number_of_relocations; reloc_index++, cur_reloc_entry++) {
+ print("SYMBOL INDEX : %u\n", cur_reloc_entry->symbol_index);
+
+ struct coff_symbol* sym = symbol_table;
+ for (u32 symbol_index = 0U; symbol_index < cur_reloc_entry->symbol_index; symbol_index++, sym++) {
+ }
+ if (sym->zeroes == 0U) {
+ print("SYMBOL NAME : %s\n", string_table + sym->offset);
+ } else {
+ print("SYMBOL NAME : %s.8\n", sym->name);
+ }
+
+ // if (cur_reloc_entry->type == IMAGE_REL_AMD64_ABSOLUTE) {
+ // print("IMAGE_REL_AMD64_ABSOLUTE\n");
+ // } else if (cur_reloc_entry->type == IMAGE_REL_AMD64_ADDR64) {
+ // print("IMAGE_REL_AMD64_ADDR64\n");
+ // } else if (cur_reloc_entry->type == IMAGE_REL_AMD64_ADDR32) {
+ // print("IMAGE_REL_AMD64_ADDR32\n");
+ // } else if (cur_reloc_entry->type == IMAGE_REL_AMD64_ADDR32NB) {
+ // print("IMAGE_REL_AMD64_ADDR32NB\n");
+ // } else if (cur_reloc_entry->type == IMAGE_REL_AMD64_REL32) {
+ // print("IMAGE_REL_AMD64_REL32\n");
+ // } else if (cur_reloc_entry->type == IMAGE_REL_AMD64_REL32_1) {
+ // print("IMAGE_REL_AMD64_REL32_1\n");
+ // } else if (cur_reloc_entry->type == IMAGE_REL_AMD64_REL32_2) {
+ // print("IMAGE_REL_AMD64_REL32_2\n");
+ // } else if (cur_reloc_entry->type == IMAGE_REL_AMD64_REL32_3) {
+ // print("IMAGE_REL_AMD64_REL32_3\n");
+ // } else if (cur_reloc_entry->type == IMAGE_REL_AMD64_REL32_4) {
+ // print("IMAGE_REL_AMD64_REL32_4\n");
+ // } else if (cur_reloc_entry->type == IMAGE_REL_AMD64_REL32_5) {
+ // print("IMAGE_REL_AMD64_REL32_5\n");
+ // } else if (cur_reloc_entry->type == IMAGE_REL_AMD64_SECTION) {
+ // print("IMAGE_REL_AMD64_SECTION\n");
+ // } else if (cur_reloc_entry->type == IMAGE_REL_AMD64_SECREL) {
+ // print("IMAGE_REL_AMD64_SECREL\n");
+ // } else if (cur_reloc_entry->type == IMAGE_REL_AMD64_SECREL7) {
+ // print("IMAGE_REL_AMD64_SECREL7\n");
+ // } else if (cur_reloc_entry->type == IMAGE_REL_AMD64_TOKEN) {
+ // print("IMAGE_REL_AMD64_TOKEN\n");
+ // } else if (cur_reloc_entry->type == IMAGE_REL_AMD64_SREL32) {
+ // print("IMAGE_REL_AMD64_SREL32\n");
+ // } else if (cur_reloc_entry->type == IMAGE_REL_AMD64_PAIR) {
+ // print("IMAGE_REL_AMD64_PAIR\n");
+ // } else if (cur_reloc_entry->type == IMAGE_REL_AMD64_SSPAN32) {
+ // print("IMAGE_REL_AMD64_SSPAN32\n");
+ // }
+ }
+
+ if (section->characteristics & IMAGE_SCN_LNK_INFO) // .drectve
+ {
+ u8* drectve_start = &buffer[section->pointer_to_raw_data];
+ print("%s\n", drectve_start);
+ } else if ((section->characteristics & DRECTVE_SECTION_FLAGS) == DRECTVE_SECTION_FLAGS) { // .data
+ u8* data_start = &buffer[section->pointer_to_raw_data];
+ u8* cur_data = data_start;
+ while ((cur_data - data_start) < section->size_of_raw_data) {
+ size_t len = 0U;
+ StringCchLengthA((STRSAFE_LPSTR)cur_data, section->size_of_raw_data, &len);
+ if (len == 0U) {
+ cur_data++;
+ } else {
+ print("%s\n", cur_data);
+ cur_data += len;
+ }
+ }
+ } else if ((section->characteristics & TEXT_SECTION_FLAGS) == TEXT_SECTION_FLAGS) { // .text
+ // u8* text_start = &buffer[section->pointer_to_raw_data];
+ }
+ }
+
+ struct coff_symbol* cur_symbol = symbol_table;
+ for (u32 symbol_index = 0U; symbol_index < header.symbols_count; symbol_index++, cur_symbol++) {
+
+ if (cur_symbol->zeroes == 0U) {
+ print("SYMBOL NAME : %s\n", string_table + cur_symbol->offset);
+ } else {
+ print("SYMBOL NAME : %s.8\n", cur_symbol->name);
+ }
+
+ if (cur_symbol->section_number > 1) {
+ print("SECTION: %s\n", sections[cur_symbol->section_number - 1U].name);
+ } else if (cur_symbol->section_number == IMAGE_SYM_UNDEFINED) {
+ print("SECTION: EXTERNAL SYMBOL\n");
+ } else if (cur_symbol->section_number == IMAGE_SYM_ABSOLUTE) {
+ print("SECTION: ABSOLUTE\n");
+ } else if (cur_symbol->section_number == IMAGE_SYM_DEBUG) {
+ print("SECTION: DEBUG\n");
+ }
+
+ if (cur_symbol->number_of_aux_symbols > 0U) {
+ cur_symbol += cur_symbol->number_of_aux_symbols;
+ symbol_index++;
+ }
+ }
+}
+
+struct archive_member_header {
+ u8 name[16U];
+ u8 data[12U];
+ u8 userID[6U];
+ u8 groupID[6U];
+ u64 mode;
+ u8 size[10U];
+ u16 end;
+};
+
+struct import_header {
+ u16 sig1;
+ u16 sig2;
+ u16 version;
+ u16 machine;
+ u32 timestamp;
+ u32 size;
+ u16 ordinal;
+ u16 import_type: 2;
+ u16 name_type: 3;
+ u16 reserved: 11;
+};
+
+#define BSWAP32(x) ((x & 0x000000FF) << 24U) | ((x & 0x0000FF00) << 8U) | ((x & 0x00FF0000) >> 8U) | ((x & 0xFF000000) >> 24U)
+
+void read_lib(u8* buffer) {
+ u8* next_byte = buffer;
+
+ {
+ print("FIRST LINKER MEMBER\n");
+ struct archive_member_header* first_linker_member = (struct archive_member_header*)next_byte;
+ next_byte += sizeof(*first_linker_member);
+ if (first_linker_member->name[0U] != '/') { // IMAGE_ARCHIVE_LINKER_MEMBER
+ return;
+ }
+
+ u32 symbols_count = BSWAP32(*(u32*)next_byte);
+ next_byte += sizeof(symbols_count);
+
+ u32* first_linker_offsets = (u32*)next_byte;
+ next_byte += sizeof(*first_linker_offsets) * symbols_count;
+
+ u8* first_linker_string_table = next_byte;
+ u8* cur_string = first_linker_string_table;
+ for (u32 index = 0U; index < symbols_count; index++) {
+ size_t size = 0U;
+ StringCchLengthA((const char*)cur_string, 256U, &size);
+ print("%s\n", cur_string);
+ cur_string += size + 1U;
+ }
+
+ next_byte += cur_string - first_linker_string_table;
+ }
+
+ u32 archive_members_count = 0U;
+ {
+ print("SECOND LINKER MEMBER\n");
+ struct archive_member_header* second_linker_member = (struct archive_member_header*)next_byte;
+ next_byte += sizeof(*second_linker_member);
+ if (second_linker_member->name[0U] != '/') { // IMAGE_ARCHIVE_LINKER_MEMBER
+ return;
+ }
+
+ archive_members_count = *(u32*)next_byte;
+ next_byte += sizeof(archive_members_count);
+
+ u32* archive_members_offsets = (u32*)next_byte;
+ next_byte += sizeof(*archive_members_offsets) * archive_members_count;
+
+ u32 symbols_count = *(u32*)next_byte;
+ next_byte += sizeof(symbols_count);
+
+ u16* symbols_indices = (u16*)next_byte;
+ next_byte += sizeof(*symbols_indices) * symbols_count;
+
+ u8* second_linker_string_table = next_byte;
+ u8* cur_string = second_linker_string_table;
+ for (u32 index = 0U; index < symbols_count; index++) {
+ size_t size = 0U;
+ StringCchLengthA((const char*)cur_string, 256U, &size);
+ print("%s\n", cur_string);
+ cur_string += size + 1U;
+ }
+ next_byte += cur_string - second_linker_string_table;
+ }
+
+ {
+ struct archive_member_header* longnames_member = (struct archive_member_header*)next_byte;
+ if (longnames_member->name[0U] == '/' && longnames_member->name[1U] == '/') { // IMAGE_ARCHIVE_LONGNAMES_MEMBER
+ next_byte += sizeof(*longnames_member);
+ }
+ }
+
+ print("ARCHIVE COUNT: %u\n", archive_members_count);
+ for (u32 archive_index = 0U; archive_index < archive_members_count; archive_index++) {
+ next_byte += (u64)next_byte % 2U;
+ struct archive_member_header* header = (struct archive_member_header*)next_byte;
+ next_byte += sizeof(*header);
+
+ u32 size = 0U;
+ for (u8* c = (u8*)header->size; *c != 0x20 && size< sizeof(header->size) / sizeof(header->size[0U]); c++, size++) {
+ }
+ u64 archive_size = atou64((char*)header->size, size);
+
+
+ print("ARCHIVE NAME: %s.16\n", header->name);
+ print("ARCHIVE SIZE: %s.10, %u\n", header->size, archive_size);
+
+ if (header->name[0U] == '/') { // Special member
+ next_byte += archive_size;
+ continue;
+ }
+
+ if (*(u16*)next_byte == 0U) {
+ struct import_header* import_header = (struct import_header*)next_byte;
+ char* import_name = (char*)next_byte + sizeof(*import_header);
+
+ size_t len = 0U;
+ StringCchLengthA((char*)import_name, 256U, &len);
+ print("IMPORT NAME: %s\n", import_name);
+
+ char* dll_name = import_name + len + 1U;
+ print("DLL NAME: %s\n", dll_name);
+ } else {
+ read_COFF(next_byte);
+ }
+ next_byte += archive_size;
+ }
+}
+
+int mainCRTStartup(void) {
+ char* args_string = VirtualAlloc(NULL, 4096U, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+ char** argv = VirtualAlloc(NULL, 4096U, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+ argv[0U] = args_string;
+ u32 argc = 1U;
+
+ {
+ LPSTR args = GetCommandLineA();
+
+ for (u32 char_index = 0U; *(args + char_index) != '\0'; char_index++) {
+ char c = *(args + char_index);
+ if (c == ' ') {
+ args_string[char_index] = '\0';
+ argv[argc] = &args_string[char_index + 1U];
+ argc++;
+ } else
+ {
+ args_string[char_index] = c;
+ }
+ }
+ }
+
+
+ char* libs[64U] = {};
+ u32 libs_count = 0U;
+ char* lib_paths = VirtualAlloc(NULL, 4096U, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+ {
+ HRESULT ret = GetEnvironmentVariableA("LIB", (char*)lib_paths, 4096U);
+ if (ret != 0U) {
+ print("LIB: %s\n", lib_paths);
+ libs[0U] = lib_paths;
+
+ for (u32 char_index = 0U; *(lib_paths + char_index) != '\0'; char_index++) {
+ char c = *(lib_paths + char_index);
+ if (c == ';') {
+ libs_count++;
+ lib_paths[char_index] = '\0';
+ libs[libs_count] = &lib_paths[char_index + 1U];
+ }
+ }
+
+ if (libs[libs_count][0U] != '\0') {
+ libs_count++;
+ }
+ }
+ }
+
+ for (u32 index = 0U; index < libs_count; index++) {
+ print("LIB %u: %s\n", index, libs[index]);
+ }
+
+ char* filepath = VirtualAlloc(NULL, 4096, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+ for (u32 arg_index = 1U; arg_index < argc; arg_index++) {
+ // NtCreateFile(".\build\main.obj", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0U, NULL);
+ print("ARG %u: %s\n", arg_index, argv[arg_index]);
+
+ u32 pathsize = SearchPathA(".", argv[arg_index], NULL, 4096U, filepath, NULL);
+ if (pathsize == 0U) {
+ for (u32 lib_index = 0U; lib_index < libs_count && pathsize == 0U; lib_index++) {
+ pathsize = SearchPathA(libs[lib_index], argv[arg_index], NULL, 4096U, filepath, NULL);
+ }
+ }
+
+ if (pathsize != 0U) {
+ print("FOUND: %s\n", filepath);
+ } else {
+ print("COULD NOT FOUND %s\n", argv[arg_index]);
+ continue;
+ }
+
+ HANDLE file = CreateFile(filepath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0U, NULL);
+
+ if (!file && file != INVALID_HANDLE_VALUE) {
+ continue;
+ }
+
+ LARGE_INTEGER file_size = { 0 };
+ GetFileSizeEx(file, &file_size);
+
+ u8* buffer = VirtualAlloc(NULL, file_size.LowPart, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+
+ DWORD bread = 0U;
+ ReadFile(file, buffer, file_size.LowPart, &bread, NULL);
+
+ if (*(u64*)buffer == lib_signature) {
+ read_lib(buffer + sizeof(lib_signature));
+ } else {
+ read_COFF(buffer);
+ }
+ VirtualFree(buffer, 0U, MEM_RELEASE);
+ }
+
+ __debugbreak();
+
+ VirtualFree(filepath, 0U, MEM_RELEASE);
+ VirtualFree(lib_paths, 0U, MEM_RELEASE);
+ VirtualFree(argv, 0U, MEM_RELEASE);
+ VirtualFree(args_string, 0U, MEM_RELEASE);
+
+ return 0;
+}