/*
	This file is part of Fennix Kernel.

	Fennix Kernel is free software: you can redistribute it and/or
	modify it under the terms of the GNU General Public License as
	published by the Free Software Foundation, either version 3 of
	the License, or (at your option) any later version.

	Fennix Kernel is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/

#ifndef __FENNIX_KERNEL_MSEXEC_H__
#define __FENNIX_KERNEL_MSEXEC_H__

#include <types.h>

/* Some of the code is from: https://github.com/dotnet/llilc/blob/main/include/clr/ntimage.h */

#define near /* __near */
#define far  /* __far */
#define NEAR near
#define FAR far
#define CONST const

typedef char CHAR;
typedef unsigned char UCHAR;
typedef wchar_t WCHAR;
typedef unsigned short USHORT;
typedef long LONG;

typedef unsigned long DWORD;
typedef int BOOL;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef float FLOAT;
typedef FLOAT *PFLOAT;
typedef BOOL near *PBOOL;
typedef BOOL far *LPBOOL;
typedef BYTE near *PBYTE;
typedef BYTE far *LPBYTE;
typedef int near *PINT;
typedef int far *LPINT;
typedef WORD near *PWORD;
typedef WORD far *LPWORD;
typedef long far *LPLONG;
typedef DWORD near *PDWORD;
typedef DWORD far *LPDWORD;
typedef void far *LPVOID;
typedef CONST void far *LPCVOID;

typedef int INT;
typedef unsigned int UINT;
typedef unsigned int *PUINT;

typedef short SHORT;
typedef DWORD ULONG;
typedef double DOUBLE;

#define IMAGE_DOS_SIGNATURE 0x5A4D      /* MZ */
#define IMAGE_OS2_SIGNATURE 0x454E      /* NE */
#define IMAGE_OS2_SIGNATURE_LE 0x454C   /* LE */
#define IMAGE_NT_SIGNATURE 0x00004550   /* PE00 */
#define IMAGE_EDOS_SIGNATURE 0x44454550 /* PEED */

#define IMAGE_SIZEOF_FILE_HEADER 20

#define IMAGE_FILE_MACHINE_UNKNOWN 0
#define IMAGE_FILE_MACHINE_I860 0x14d
#define IMAGE_FILE_MACHINE_I386 0x14c
#define IMAGE_FILE_MACHINE_R3000 0x162
#define IMAGE_FILE_MACHINE_R4000 0x166
#define IMAGE_FILE_MACHINE_R10000 0x0168
#define IMAGE_FILE_MACHINE_ALPHA 0x184
#define IMAGE_FILE_MACHINE_POWERPC 0x01F0
#define IMAGE_FILE_MACHINE_POWERPCBE 0x01F2
#define IMAGE_FILE_MACHINE_SH3 0x01a2
#define IMAGE_FILE_MACHINE_SH3E 0x01a4
#define IMAGE_FILE_MACHINE_SH4 0x01a6
#define IMAGE_FILE_MACHINE_ARM 0x01c0
#define IMAGE_FILE_MACHINE_THUMB 0x01c2
#define IMAGE_FILE_MACHINE_IA64 0x0200
#define IMAGE_FILE_MACHINE_MIPS16 0x0266
#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366
#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466
#define IMAGE_FILE_MACHINE_ALPHA64 0x0284
#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64
#define IMAGE_FILE_MACHINE_AMD64 0x8664
#define IMAGE_FILE_MACHINE_CEF 0xC0EF

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1
#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
#define IMAGE_DIRECTORY_ENTRY_SECURITY 4
#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5
#define IMAGE_DIRECTORY_ENTRY_DEBUG 6
#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
#define IMAGE_DIRECTORY_ENTRY_TLS 9
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11
#define IMAGE_DIRECTORY_ENTRY_IAT 12
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14

typedef struct _IMAGE_DOS_HEADER /* DOS .EXE header */
{
	USHORT e_magic;    /* Magic number */
	USHORT e_cblp;     /* Bytes on last page of file */
	USHORT e_cp;       /* Pages in file */
	USHORT e_crlc;     /* Relocations */
	USHORT e_cparhdr;  /* Size of header in paragraphs */
	USHORT e_minalloc; /* Minimum extra paragraphs needed */
	USHORT e_maxalloc; /* Maximum extra paragraphs needed */
	USHORT e_ss;       /* Initial (relative) SS value */
	USHORT e_sp;       /* Initial SP value */
	USHORT e_csum;     /* Checksum */
	USHORT e_ip;       /* Initial IP value */
	USHORT e_cs;       /* Initial (relative) CS value */
	USHORT e_lfarlc;   /* File address of relocation table */
	USHORT e_ovno;     /* Overlay number */
	USHORT e_res[4];   /* Reserved words */
	USHORT e_oemid;    /* OEM identifier (for e_oeminfo) */
	USHORT e_oeminfo;  /* OEM information; e_oemid specific */
	USHORT e_res2[10]; /* Reserved words */
	USHORT e_lfanew;   /* File address of new exe header */
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

typedef struct _IMAGE_OS2_HEADER /* OS/2 .EXE header */
{
	USHORT ne_magic;        /* Magic number */
	UCHAR ne_ver;           /* Version number */
	UCHAR ne_rev;           /* Revision number */
	USHORT ne_enttab;       /* Offset of Entry Table */
	USHORT ne_cbenttab;     /* Number of bytes in Entry Table */
	UINT ne_crc;            /* Checksum of whole file */
	USHORT ne_flags;        /* Flag word */
	USHORT ne_autodata;     /* Automatic data segment number */
	USHORT ne_heap;         /* Initial heap allocation */
	USHORT ne_stack;        /* Initial stack allocation */
	UINT ne_csip;           /* Initial CS:IP setting */
	UINT ne_sssp;           /* Initial SS:SP setting */
	USHORT ne_cseg;         /* Count of file segments */
	USHORT ne_cmod;         /* Entries in Module Reference Table */
	USHORT ne_cbnrestab;    /* Size of non-resident name table */
	USHORT ne_segtab;       /* Offset of Segment Table */
	USHORT ne_rsrctab;      /* Offset of Resource Table */
	USHORT ne_restab;       /* Offset of resident name table */
	USHORT ne_modtab;       /* Offset of Module Reference Table */
	USHORT ne_imptab;       /* Offset of Imported Names Table */
	UINT ne_nrestab;        /* Offset of Non-resident Names Table */
	USHORT ne_cmovent;      /* Count of movable entries */
	USHORT ne_align;        /* Segment alignment shift count */
	USHORT ne_cres;         /* Count of resource segments */
	UCHAR ne_exetyp;        /* Target Operating system */
	UCHAR ne_flagsothers;   /* Other .EXE flags */
	USHORT ne_pretthunks;   /* offset to return thunks */
	USHORT ne_psegrefbytes; /* offset to segment ref. bytes */
	USHORT ne_swaparea;     /* Minimum code swap area size */
	USHORT ne_expver;       /* Expected Windows version number */
} IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER;

typedef struct _IMAGE_SECTION_HEADER
{
#define IMAGE_SIZEOF_SHORT_NAME 8
	uint8_t Name[IMAGE_SIZEOF_SHORT_NAME];
	union
	{
		uint32_t PhysicalAddress;
		uint32_t VirtualSize;
	} Misc;
	uint32_t VirtualAddress;
	uint32_t SizeOfRawData;
	uint32_t PointerToRawData;
	uint32_t PointerToRelocations;
	uint32_t PointerToLinenumbers;
	uint16_t NumberOfRelocations;
	uint16_t NumberOfLinenumbers;
	uint32_t Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

typedef struct _IMAGE_FILE_HEADER
{
	uint16_t Machine;
	uint16_t NumberOfSections;
	uint32_t TimeDateStamp;
	uint32_t PointerToSymbolTable;
	uint32_t NumberOfSymbols;
	uint16_t SizeOfOptionalHeader;
	uint16_t Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

typedef struct _IMAGE_DATA_DIRECTORY
{
	uint32_t VirtualAddress;
	uint32_t Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

typedef struct _IMAGE_OPTIONAL_HEADER
{
	uint16_t Magic;
	uint8_t MajorLinkerVersion;
	uint8_t MinorLinkerVersion;
	uint32_t SizeOfCode;
	uint32_t SizeOfInitializedData;
	uint32_t SizeOfUninitializedData;
	uint32_t AddressOfEntryPoint;
	uint32_t BaseOfCode;
	uint32_t BaseOfData;
	uint32_t ImageBase;
	uint32_t SectionAlignment;
	uint32_t FileAlignment;
	uint16_t MajorOperatingSystemVersion;
	uint16_t MinorOperatingSystemVersion;
	uint16_t MajorImageVersion;
	uint16_t MinorImageVersion;
	uint16_t MajorSubsystemVersion;
	uint16_t MinorSubsystemVersion;
	uint32_t Win32VersionValue;
	uint32_t SizeOfImage;
	uint32_t SizeOfHeaders;
	uint32_t CheckSum;
	uint16_t Subsystem;
	uint16_t DllCharacteristics;
	uint32_t SizeOfStackReserve;
	uint32_t SizeOfStackCommit;
	uint32_t SizeOfHeapReserve;
	uint32_t SizeOfHeapCommit;
	uint32_t LoaderFlags;
	uint32_t NumberOfRvaAndSizes;
	IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;

typedef struct _IMAGE_NT_HEADERS
{
	uint32_t Signature;
	IMAGE_FILE_HEADER FileHeader;
	IMAGE_OPTIONAL_HEADER OptionalHeader;
} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;

#endif // !__FENNIX_KERNEL_MSEXEC_H__
