2024-09-07 18:00:09 +06:00
|
|
|
#pragma once
|
|
|
|
#include <cstdint>
|
|
|
|
#include <type_traits>
|
|
|
|
#include <bit>
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
2024-09-07 18:21:08 +06:00
|
|
|
#include <windows.h>
|
2024-09-07 18:00:09 +06:00
|
|
|
#else
|
2024-09-07 18:21:08 +06:00
|
|
|
#define near
|
|
|
|
#define far
|
2024-09-07 18:00:09 +06:00
|
|
|
|
2024-09-07 18:21:08 +06:00
|
|
|
typedef char CHAR;
|
|
|
|
typedef wchar_t WCHAR;
|
|
|
|
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;
|
2024-09-07 18:00:09 +06:00
|
|
|
typedef unsigned long ULONG;
|
|
|
|
typedef ULONG* PULONG;
|
2024-09-07 18:21:08 +06:00
|
|
|
typedef signed long LONG;
|
2024-09-07 18:00:09 +06:00
|
|
|
typedef LONG* PLONG;
|
|
|
|
typedef unsigned long long ULONGLONG;
|
|
|
|
typedef ULONGLONG* PULONGLONG;
|
|
|
|
typedef unsigned short USHORT;
|
|
|
|
typedef USHORT* PUSHORT;
|
|
|
|
typedef unsigned char UCHAR;
|
|
|
|
typedef UCHAR* PUCHAR;
|
|
|
|
typedef char* PSZ;
|
|
|
|
typedef int INT;
|
|
|
|
typedef unsigned int UINT;
|
|
|
|
typedef unsigned int* PUINT;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// real win32 handles will never use the upper bits unless something goes really wrong
|
|
|
|
#define CHECK_GUEST_HANDLE(HANDLE) (((HANDLE) & 0x80000000) == 0x80000000)
|
|
|
|
#define GUEST_HANDLE(HANDLE) ((HANDLE) | 0x80000000)
|
|
|
|
#define HOST_HANDLE(HANDLE) ((HANDLE) & ~0x80000000)
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct be
|
|
|
|
{
|
|
|
|
T value;
|
|
|
|
|
|
|
|
be() : value(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
be(const T v)
|
|
|
|
{
|
|
|
|
set(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
static T byteswap(T value)
|
|
|
|
{
|
|
|
|
if constexpr (std::is_same_v<T, double>)
|
|
|
|
{
|
|
|
|
const uint64_t swapped = std::byteswap(*reinterpret_cast<uint64_t*>(&value));
|
|
|
|
return *reinterpret_cast<const T*>(&swapped);
|
|
|
|
}
|
|
|
|
else if constexpr (std::is_same_v<T, float>)
|
|
|
|
{
|
|
|
|
const uint32_t swapped = std::byteswap(*reinterpret_cast<uint32_t*>(&value));
|
|
|
|
return *reinterpret_cast<const T*>(&swapped);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return std::byteswap(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void set(const T v)
|
|
|
|
{
|
|
|
|
value = byteswap(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
T get() const
|
|
|
|
{
|
|
|
|
return byteswap(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
be& operator| (T value)
|
|
|
|
{
|
|
|
|
set(get() | value);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
be& operator& (T value)
|
|
|
|
{
|
|
|
|
set(get() & value);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
operator T() const
|
|
|
|
{
|
|
|
|
return get();
|
|
|
|
}
|
|
|
|
|
|
|
|
be& operator=(T v)
|
|
|
|
{
|
|
|
|
set(v);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct xpointer
|
|
|
|
{
|
|
|
|
be<uint32_t> ptr;
|
|
|
|
|
|
|
|
xpointer(T* ptr) : ptr(ptr)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
T* get() const
|
|
|
|
{
|
|
|
|
if (!ptr.value)
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return static_cast<T*>(ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
operator T* () const
|
|
|
|
{
|
|
|
|
return get();
|
|
|
|
}
|
|
|
|
|
|
|
|
T* operator->() const
|
|
|
|
{
|
|
|
|
return get();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef BYTE XBYTE;
|
|
|
|
typedef be<uint16_t> XWORD;
|
|
|
|
typedef be<uint32_t> XDWORD;
|
|
|
|
typedef be<uint64_t> XQWORD;
|
|
|
|
|
|
|
|
typedef XBYTE* XLPBYTE;
|
|
|
|
typedef XWORD* XLPWORD;
|
|
|
|
typedef XDWORD* XLPDWORD;
|
|
|
|
typedef XQWORD* XLPQWORD;
|
|
|
|
|
|
|
|
struct _XLIST_ENTRY;
|
|
|
|
typedef _XLIST_ENTRY XLIST_ENTRY;
|
|
|
|
typedef xpointer<XLIST_ENTRY> PXLIST_ENTRY;
|
|
|
|
|
2024-09-11 22:06:01 +06:00
|
|
|
typedef struct _IMAGE_CE_RUNTIME_FUNCTION
|
2024-09-11 21:21:23 +06:00
|
|
|
{
|
|
|
|
DWORD BeginAddress;
|
|
|
|
|
|
|
|
union
|
|
|
|
{
|
|
|
|
DWORD Data;
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
DWORD PrologLength : 8;
|
2024-09-11 22:06:01 +06:00
|
|
|
DWORD FunctionLength : 22;
|
|
|
|
DWORD ThirtyTwoBit : 1;
|
|
|
|
DWORD ExceptionFlag : 1;
|
2024-09-11 21:21:23 +06:00
|
|
|
};
|
|
|
|
};
|
2024-09-11 22:06:01 +06:00
|
|
|
} IMAGE_CE_RUNTIME_FUNCTION;
|
2024-09-11 21:21:23 +06:00
|
|
|
|
2024-09-11 22:06:01 +06:00
|
|
|
static_assert(sizeof(IMAGE_CE_RUNTIME_FUNCTION) == 8);
|
2024-09-11 21:21:23 +06:00
|
|
|
|
2024-09-07 18:00:09 +06:00
|
|
|
typedef struct _XLIST_ENTRY
|
|
|
|
{
|
|
|
|
XDWORD Flink;
|
|
|
|
XDWORD Blink;
|
|
|
|
} XLIST_ENTRY;
|
|
|
|
|
|
|
|
typedef struct _XDISPATCHER_HEADER
|
|
|
|
{
|
|
|
|
union
|
|
|
|
{
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
UCHAR Type;
|
|
|
|
union
|
|
|
|
{
|
|
|
|
UCHAR Abandoned;
|
|
|
|
UCHAR Absolute;
|
|
|
|
UCHAR NpxIrql;
|
|
|
|
UCHAR Signalling;
|
|
|
|
};
|
|
|
|
union
|
|
|
|
{
|
|
|
|
UCHAR Size;
|
|
|
|
UCHAR Hand;
|
|
|
|
};
|
|
|
|
union
|
|
|
|
{
|
|
|
|
UCHAR Inserted;
|
|
|
|
UCHAR DebugActive;
|
|
|
|
UCHAR DpcActive;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
XDWORD Lock;
|
|
|
|
};
|
|
|
|
|
|
|
|
XDWORD SignalState;
|
|
|
|
XLIST_ENTRY WaitListHead;
|
|
|
|
} XDISPATCHER_HEADER, * XPDISPATCHER_HEADER;
|
|
|
|
|
|
|
|
// These variables are never accessed in guest code, we can safely use them in little endian
|
|
|
|
typedef struct _XRTL_CRITICAL_SECTION
|
|
|
|
{
|
|
|
|
XDISPATCHER_HEADER Header;
|
|
|
|
long LockCount;
|
|
|
|
int32_t RecursionCount;
|
|
|
|
uint32_t OwningThread;
|
|
|
|
} XRTL_CRITICAL_SECTION;
|
|
|
|
|
|
|
|
typedef struct _XANSI_STRING {
|
|
|
|
XWORD Length;
|
|
|
|
XWORD MaximumLength;
|
|
|
|
xpointer<char> Buffer;
|
|
|
|
} XANSI_STRING;
|
|
|
|
|
|
|
|
typedef struct _XOBJECT_ATTRIBUTES
|
|
|
|
{
|
|
|
|
XDWORD RootDirectory;
|
|
|
|
xpointer<XANSI_STRING> Name;
|
|
|
|
xpointer<void> Attributes;
|
|
|
|
} XOBJECT_ATTRIBUTES;
|
|
|
|
|
|
|
|
typedef XDISPATCHER_HEADER XKEVENT;
|
|
|
|
|
|
|
|
typedef struct _XIO_STATUS_BLOCK
|
|
|
|
{
|
|
|
|
union {
|
|
|
|
XDWORD Status;
|
|
|
|
XDWORD Pointer;
|
|
|
|
};
|
|
|
|
be<uint32_t> Information;
|
|
|
|
} XIO_STATUS_BLOCK;
|
|
|
|
|
|
|
|
typedef struct _XOVERLAPPED {
|
|
|
|
XDWORD Internal;
|
|
|
|
XDWORD InternalHigh;
|
|
|
|
XDWORD Offset;
|
|
|
|
XDWORD OffsetHigh;
|
|
|
|
XDWORD hEvent;
|
|
|
|
} XOVERLAPPED;
|
|
|
|
|
|
|
|
// this name is so dumb
|
|
|
|
typedef struct _XXOVERLAPPED {
|
|
|
|
union
|
|
|
|
{
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
XDWORD Error;
|
|
|
|
XDWORD Length;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
uint32_t InternalLow;
|
|
|
|
uint32_t InternalHigh;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
uint32_t InternalContext;
|
|
|
|
XDWORD hEvent;
|
|
|
|
XDWORD pCompletionRoutine;
|
|
|
|
XDWORD dwCompletionContext;
|
|
|
|
XDWORD dwExtendedError;
|
|
|
|
} XXOVERLAPPED, *PXXOVERLAPPED;
|
|
|
|
|
|
|
|
static_assert(sizeof(_XXOVERLAPPED) == 0x1C);
|
|
|
|
|
|
|
|
typedef struct _XVIDEO_MODE
|
|
|
|
{
|
|
|
|
be<uint32_t> DisplayWidth;
|
|
|
|
be<uint32_t> DisplayHeight;
|
|
|
|
be<uint32_t> IsInterlaced;
|
|
|
|
be<uint32_t> IsWidescreen;
|
|
|
|
be<uint32_t> IsHighDefinition;
|
|
|
|
be<uint32_t> RefreshRate;
|
|
|
|
be<uint32_t> VideoStandard;
|
|
|
|
be<uint32_t> Unknown4A;
|
|
|
|
be<uint32_t> Unknown01;
|
|
|
|
be<uint32_t> reserved[3];
|
|
|
|
} XVIDEO_MODE;
|
|
|
|
|
|
|
|
typedef struct _XKSEMAPHORE
|
|
|
|
{
|
|
|
|
XDISPATCHER_HEADER Header;
|
|
|
|
XDWORD Limit;
|
2024-09-11 21:21:23 +06:00
|
|
|
} XKSEMAPHORE;
|