diff --git a/internal.sln b/internal.sln new file mode 100644 index 0000000..74ff24d --- /dev/null +++ b/internal.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29613.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "internal", "internal\internal.vcxproj", "{A5A06423-4302-4CE2-A42C-D4416DD7B507}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A5A06423-4302-4CE2-A42C-D4416DD7B507}.Debug|x64.ActiveCfg = Debug|x64 + {A5A06423-4302-4CE2-A42C-D4416DD7B507}.Debug|x64.Build.0 = Debug|x64 + {A5A06423-4302-4CE2-A42C-D4416DD7B507}.Debug|x86.ActiveCfg = Debug|Win32 + {A5A06423-4302-4CE2-A42C-D4416DD7B507}.Debug|x86.Build.0 = Debug|Win32 + {A5A06423-4302-4CE2-A42C-D4416DD7B507}.Release|x64.ActiveCfg = Release|x64 + {A5A06423-4302-4CE2-A42C-D4416DD7B507}.Release|x64.Build.0 = Release|x64 + {A5A06423-4302-4CE2-A42C-D4416DD7B507}.Release|x86.ActiveCfg = Release|Win32 + {A5A06423-4302-4CE2-A42C-D4416DD7B507}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3F3A27AF-88C8-4517-B633-97CA6C558844} + EndGlobalSection +EndGlobal diff --git a/internal/direct.h b/internal/direct.h new file mode 100644 index 0000000..763f831 --- /dev/null +++ b/internal/direct.h @@ -0,0 +1,91 @@ +#pragma once +#include +#include +#include + +extern "C" NTSTATUS __protect_virtual_memory( + HANDLE p_handle, + void** base_addr, + std::size_t* bytes_to_protect, + std::uint32_t new_protect, + std::uint32_t* old_protect +); + +extern "C" NTSTATUS __write_virtual_memory( + HANDLE p_handle, + void* base_addr, + void* buffer, + std::size_t size, + std::size_t* bytes_written +); + +extern "C" NTSTATUS __read_virtual_memory( + HANDLE p_handle, + void* base_addr, + void* buffer, + std::size_t size, + std::size_t* bytes_written +); + +extern "C" NTSTATUS __alloc_virtual_memory( + HANDLE p_handle, + void** base_addr, + std::uint32_t zero_bits, + std::size_t* size, + std::uint32_t alloc_type, + std::uint32_t protect +); + +namespace direct +{ + __forceinline bool protect_virtual_memory( + HANDLE p_handle, + void* base_addr, + std::size_t size, + std::uint32_t protect, + std::uint32_t* old_protect + ) + { + return ERROR_SUCCESS == ::__protect_virtual_memory(p_handle, &base_addr, &size, protect, old_protect); + } + + __forceinline bool write_virtual_memory( + HANDLE p_handle, + void* base_addr, + void* buffer, + std::size_t size + ) + { + std::size_t bytes_written; + return ERROR_SUCCESS == __write_virtual_memory(p_handle, base_addr, buffer, size, &bytes_written); + } + + __forceinline bool read_virtual_memory( + HANDLE p_handle, + void* addr, + void* buffer, + std::size_t size + ) + { + std::size_t bytes_written; + return ERROR_SUCCESS == ::__read_virtual_memory(p_handle, addr, buffer, size, &bytes_written); + } + + __forceinline void* alloc_virtual_memory( + HANDLE p_handle, + std::size_t size, + std::uint32_t protect + ) + { + void* base_addr = NULL; + ::__alloc_virtual_memory( + p_handle, + &base_addr, + NULL, + &size, + MEM_COMMIT | MEM_RESERVE, + protect + ); + return base_addr; + } +} \ No newline at end of file diff --git a/internal/direct.lib b/internal/direct.lib new file mode 100644 index 0000000..690bb6a Binary files /dev/null and b/internal/direct.lib differ diff --git a/internal/image_base.asm b/internal/image_base.asm new file mode 100644 index 0000000..532b500 --- /dev/null +++ b/internal/image_base.asm @@ -0,0 +1,9 @@ +.code +__image_base proc + xor rax, rax + mov rax, gs:[30h] + mov rax, [rax + 60h] + mov rax, [rax + 10h] + ret +__image_base endp +end \ No newline at end of file diff --git a/internal/image_base.h b/internal/image_base.h new file mode 100644 index 0000000..d4ae914 --- /dev/null +++ b/internal/image_base.h @@ -0,0 +1,5 @@ +#pragma once +#include + +// TIB ---> TEB (linear address) ---> PEB (base address) +extern "C" std::uintptr_t __image_base(void); \ No newline at end of file diff --git a/internal/internal.filters b/internal/internal.filters new file mode 100644 index 0000000..46f9fff --- /dev/null +++ b/internal/internal.filters @@ -0,0 +1,84 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {3fc44ebb-cb8f-464a-a305-a69883fe7ca9} + + + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files\font + + + Header Files\font + + + Header Files\font + + + Header Files\font + + + Header Files\font + + + Header Files\font + + + Header Files\font + + + Header Files\font + + + Header Files\font + + + Header Files\font + + + Header Files\font + + + Header Files\font + + + Header Files\font + + + Header Files\font + + + Header Files\font + + + Header Files\font + + + Header Files + + + \ No newline at end of file diff --git a/internal/internal.vcxproj b/internal/internal.vcxproj new file mode 100644 index 0000000..a1ca47d --- /dev/null +++ b/internal/internal.vcxproj @@ -0,0 +1,255 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {A5A06423-4302-4CE2-A42C-D4416DD7B507} + Win32Proj + noalloc + 10.0 + + + + DynamicLibrary + true + ClangCL + Unicode + false + + + DynamicLibrary + false + ClangCL + true + Unicode + false + + + DynamicLibrary + true + ClangCL + Unicode + false + + + DynamicLibrary + false + v142 + true + Unicode + false + + + + + + + + + + + + + + + + + + + + + + true + true + + + true + true + + + false + true + + + false + true + C:\Users\Andreas Wehrmann\Desktop\xerox internal master\internal;$(IncludePath) + + + + + + TurnOffAllWarnings + true + _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING;_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS + true + stdcpp17 + false + MultiThreaded + false + Default + false + $(DXSDK_DIR)include;%(AdditionalIncludeDirectories) + false + false + false + Default + + + Windows + true + false + true + %(AdditionalDependencies) + + + true + + + + + + + TurnOffAllWarnings + true + _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING;_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS + true + stdcpp17 + false + MultiThreaded + false + Default + false + $(DXSDK_DIR)include;%(AdditionalIncludeDirectories) + false + false + false + Default + + + Windows + true + false + true + %(AdditionalDependencies) + + + true + + + + + + + TurnOffAllWarnings + true + false + true + _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING;_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS + true + stdcpp17 + false + MultiThreaded + false + Default + false + false + $(DXSDK_DIR)include;%(AdditionalIncludeDirectories) + false + false + + + Windows + true + true + true + false + true + %(AdditionalDependencies) + + + true + + + + + + + TurnOffAllWarnings + true + false + true + _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING;_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS + true + stdcpp17 + false + MultiThreaded + false + Default + false + false + $(DXSDK_DIR)include;%(AdditionalIncludeDirectories) + false + false + Disabled + + + Windows + true + true + true + false + true + ucrt.lib;direct.lib;%(AdditionalDependencies) + + + true + + + + + + + + + + + + + + + + + + + + + + Document + + + + + + + + + + \ No newline at end of file diff --git a/internal/internal.vcxproj.filters b/internal/internal.vcxproj.filters new file mode 100644 index 0000000..8f0494a --- /dev/null +++ b/internal/internal.vcxproj.filters @@ -0,0 +1,77 @@ + + + + + headers\no_alloc + + + headers\no_crt + + + headers + + + headers\no_gui + + + headers\no_gui + + + headers\no_gui + + + headers + + + headers + + + + + {7aa51226-3d6f-435f-a764-9cca554e94be} + + + {24b4469c-bcb2-4707-8486-f6e879654ae7} + + + {f2eca2b3-14df-46b7-a038-9476c6b9e7df} + + + {272d0338-6a74-47b1-b08f-16f4ea9bf110} + + + {9a4972bd-755f-4d8c-ab1a-3fa628113da4} + + + {ddbfbb9f-faf5-4c70-947f-4b157336dfd2} + + + {2ebed959-7c32-4b6e-883f-eb1f13647ef9} + + + {8e9f1673-a856-4c60-a04c-3b60a5dd1cfa} + + + + + source\no_gui + + + source\no_gui + + + source\no_crt + + + source\no_alloc + + + source + + + + + source + + + \ No newline at end of file diff --git a/internal/internal.vcxproj.user b/internal/internal.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/internal/internal.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/internal/no_alloc/no_alloc.cpp b/internal/no_alloc/no_alloc.cpp new file mode 100644 index 0000000..f0a33a9 --- /dev/null +++ b/internal/no_alloc/no_alloc.cpp @@ -0,0 +1,21 @@ +#include "no_alloc.hpp" + +void* malloc(std::size_t size) +{ + return heap.allocate(size); +} + +void free(void* ptr, std::size_t size) +{ + heap.deallocate((std::uint8_t*)ptr, size); +} + +void* operator new(std::size_t size) +{ + return malloc(size); +} + +void operator delete(void* ptr, unsigned __int64 size) +{ + free(ptr, size); +} \ No newline at end of file diff --git a/internal/no_alloc/no_alloc.hpp b/internal/no_alloc/no_alloc.hpp new file mode 100644 index 0000000..5fb36ca --- /dev/null +++ b/internal/no_alloc/no_alloc.hpp @@ -0,0 +1,138 @@ +/* + Author: xerox + Date: 4/23/2020 + + example: + std::vector> test; + test.reserve(30); +*/ + +#pragma once +#include + +#define HEAP_SIZE 0x2000 + +// taken from: +// https://github.com/charles-salvia/charles/blob/master/stack_allocator.hpp +template > +class no_alloc +{ +public: + + typedef typename std::allocator_traits::value_type value_type; + typedef typename std::allocator_traits::pointer pointer; + typedef typename std::allocator_traits::const_pointer const_pointer; + typedef typename Allocator::reference reference; + typedef typename Allocator::const_reference const_reference; + typedef typename std::allocator_traits::size_type size_type; + typedef typename std::allocator_traits::difference_type difference_type; + typedef typename std::allocator_traits::const_void_pointer const_void_pointer; + typedef Allocator allocator_type; + +public: + explicit no_alloc(const allocator_type& alloc = allocator_type()) + : m_allocator(alloc), m_begin(this->heap), m_end(this->heap + heap_size), + m_stack_pointer(this->heap) + { } + + template + no_alloc(const no_alloc& other) + : m_allocator(other.m_allocator), m_begin(other.m_begin), m_end(other.m_end), + m_stack_pointer(other.m_stack_pointer) + { } + + constexpr static size_type capacity() + { + return heap_size; + } + + pointer allocate(size_type n, const_void_pointer hint = const_void_pointer()) + { + pointer result = m_stack_pointer; + m_stack_pointer += n; + return result; + } + + void deallocate(pointer p, size_type n) + { + m_stack_pointer -= n; + } + + size_type max_size() const noexcept + { + return m_allocator.max_size(); + } + + template + void construct(U* p, Args&&... args) + { + m_allocator.construct(p, std::forward(args)...); + } + + template + void destroy(U* p) + { + m_allocator.destroy(p); + } + + pointer address(reference x) const noexcept + { + if (pointer_to_internal_buffer(std::addressof(x))) + { + return std::addressof(x); + } + + return m_allocator.address(x); + } + + const_pointer address(const_reference x) const noexcept + { + if (pointer_to_internal_buffer(std::addressof(x))) + { + return std::addressof(x); + } + + return m_allocator.address(x); + } + + template + struct rebind { typedef no_alloc other; }; + + pointer buffer() const noexcept + { + return m_begin; + } + +private: + + bool pointer_to_internal_buffer(const_pointer p) const + { + return (!(std::less()(p, m_begin)) && (std::less()(p, m_end))); + } + + allocator_type m_allocator; + pointer m_begin; + pointer m_end; + pointer m_stack_pointer; + T heap[heap_size]; +}; + +template +static bool operator == (const no_alloc& lhs, + const no_alloc& rhs) noexcept +{ + return lhs.buffer() == rhs.buffer(); +} + +template +static bool operator != (const no_alloc& lhs, + const no_alloc& rhs) noexcept +{ + return !(lhs == rhs); +} + +inline no_alloc heap; +void* operator new(std::size_t size); +void operator delete(void* ptr, unsigned __int64); +void* malloc(std::size_t size); +void free(void*, std::size_t size); \ No newline at end of file diff --git a/internal/no_crt/no_crt.cpp b/internal/no_crt/no_crt.cpp new file mode 100644 index 0000000..9a67817 --- /dev/null +++ b/internal/no_crt/no_crt.cpp @@ -0,0 +1,73 @@ +#include "no_crt.h" + +int atexit(void (*func) (void)) +{ + func(); + return NULL; +} + +int memcmp(const void* buf1, const void* buf2, size_t count) +{ + if (!count) + return(0); + + while (--count && *(char*)buf1 == *(char*)buf2) + { + buf1 = (char*)buf1 + 1; + + buf2 = (char*)buf2 + 1; + + } + return(*((unsigned char*)buf1) - *((unsigned char*)buf2)); + +} + +void* memcpy(void* memTo, const void* memFrom, size_t size) +{ + if (!memTo || !memFrom) + return nullptr; + const char* temFrom = (const char*)memFrom; + char* temTo = (char*)memTo; + while (size-- > 0) + *temTo++ = *temFrom++; + return memTo; +} + +void* memmove(void* dst, const void* src, size_t count) +{ + if (!dst || !src) + return nullptr; + void* ret = dst; + if (dst <= src || (char*)dst >= ((char*)src + count)) + { + while (count--) + { + *(char*)dst = *(char*)src; + dst = (char*)dst + 1; + src = (char*)src + 1; + } + } + else + { + + dst = (char*)dst + count - 1; + src = (char*)src + count - 1; + while (count--) + { + *(char*)dst = *(char*)src; + dst = (char*)dst - 1; + src = (char*)src - 1; + } + } + return ret; +} + +void* memset(void* dest, int c, size_t count) +{ + char* bytes = (char*)dest; + while (count--) + { + *bytes++ = (char)c; + } + return dest; +} \ No newline at end of file diff --git a/internal/no_crt/no_crt.h b/internal/no_crt/no_crt.h new file mode 100644 index 0000000..a343a9d --- /dev/null +++ b/internal/no_crt/no_crt.h @@ -0,0 +1,8 @@ +#pragma once +#include "../no_alloc/no_alloc.hpp" + +int atexit(void (*func) (void)); +int memcmp(const void* buf1, const void* buf2, size_t count); +void* memcpy(void* memTo, const void* memFrom, size_t size); +void* memmove(void* dst, const void* src, size_t count); +void* memset(void* dest, int c, size_t count); \ No newline at end of file diff --git a/internal/no_gui/no_gui.cpp b/internal/no_gui/no_gui.cpp new file mode 100644 index 0000000..949519b --- /dev/null +++ b/internal/no_gui/no_gui.cpp @@ -0,0 +1,383 @@ +#include "no_gui.h" + +bool no_gui::init(IDXGISwapChain* swapchain) +{ + HRESULT hr; + m_swap_chain = swapchain; + if (!m_swap_chain) + return false; + + m_swap_chain->GetDevice(__uuidof(m_device), (void**)&m_device); + m_device->GetImmediateContext(&m_device_context); + hr = m_device->CreateVertexShader(vs_blob, sizeof(vs_blob), NULL, &m_vertex_shader); + + D3D11_INPUT_ELEMENT_DESC layout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 } + }; + + hr = m_device->CreateInputLayout(layout, ARRAYSIZE(layout), vs_blob, sizeof(vs_blob), &m_input_layout); + hr = m_device->CreatePixelShader(ps_blob, sizeof(ps_blob), NULL, &m_pixel_shader); + + D3D11_BUFFER_DESC buffer_desc; + + buffer_desc.Usage = D3D11_USAGE_DYNAMIC; + buffer_desc.ByteWidth = 4 * sizeof(COLOR_VERTEX); + buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + buffer_desc.MiscFlags = 0; + + hr = m_device->CreateBuffer(&buffer_desc, NULL, &m_pvertex_buffer); + if (FAILED(hr)) + return false; + + D3D11_BLEND_DESC blend_state_desc; + ZeroMemory(&blend_state_desc, sizeof(blend_state_desc)); + blend_state_desc.AlphaToCoverageEnable = false; + blend_state_desc.RenderTarget[0].BlendEnable = true; + blend_state_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; + blend_state_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; + blend_state_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + blend_state_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; + blend_state_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; + blend_state_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + blend_state_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; + + hr = m_device->CreateBlendState(&blend_state_desc, &m_transparency); + if (FAILED(hr)) + return false; + + memset((void*)vs_blob, NULL, sizeof(vs_blob)); + memset((void*)ps_blob, NULL, sizeof(ps_blob)); + return true; +} + +void no_gui::reset() +{ + init(m_swap_chain); +} + +void no_gui::fill_rect(float x, float y, float w, float h, color color) +{ + if (!m_device_context) + return; + + int a = color.A & 0xff; + int r = color.R & 0xff; + int g = color.G & 0xff; + int b = color.B & 0xff; + + DXGI_SWAP_CHAIN_DESC swap_chain_desc; + memset(&swap_chain_desc, 0, sizeof(swap_chain_desc)); + + m_swap_chain->GetDesc(&swap_chain_desc); + float width = swap_chain_desc.BufferDesc.Width; + float height = swap_chain_desc.BufferDesc.Height; + + UINT numViewports = 1; + D3D11_VIEWPORT vp = { 0, 0, width, height, 1, 1 }; + m_device_context->RSSetViewports(numViewports, &vp); + + float x0 = x; + float y0 = y; + float x1 = x + w; + float y1 = y + h; + + float xx0 = 2.0f * (x0 - 0.5f) / vp.Width - 1.0f; + float yy0 = 1.0f - 2.0f * (y0 - 0.5f) / vp.Height; + float xx1 = 2.0f * (x1 - 0.5f) / vp.Width - 1.0f; + float yy1 = 1.0f - 2.0f * (y1 - 0.5f) / vp.Height; + + COLOR_VERTEX* v = NULL; + D3D11_MAPPED_SUBRESOURCE mapData; + + if (FAILED(m_device_context->Map(m_pvertex_buffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &mapData))) + return; + + v = (COLOR_VERTEX*)mapData.pData; + + v[0].Position.x = (float)x0; + v[0].Position.y = (float)y0; + v[0].Position.z = 0; + v[0].Color = vec4( + ((float)r / 255.0f), + ((float)g / 255.0f), + ((float)b / 255.0f), + ((float)a / 255.0f)); + + v[1].Position.x = (float)x1; + v[1].Position.y = (float)y1; + v[1].Position.z = 0; + v[1].Color = vec4( + ((float)r / 255.0f), + ((float)g / 255.0f), + ((float)b / 255.0f), + ((float)a / 255.0f)); + + v[0].Position.x = xx0; + v[0].Position.y = yy0; + v[0].Position.z = 0; + v[0].Color = vec4( + ((float)r / 255.0f), + ((float)g / 255.0f), + ((float)b / 255.0f), + ((float)a / 255.0f)); + + v[1].Position.x = xx1; + v[1].Position.y = yy0; + v[1].Position.z = 0; + v[1].Color = vec4( + ((float)r / 255.0f), + ((float)g / 255.0f), + ((float)b / 255.0f), + ((float)a / 255.0f)); + + v[2].Position.x = xx0; + v[2].Position.y = yy1; + v[2].Position.z = 0; + v[2].Color = vec4( + ((float)r / 255.0f), + ((float)g / 255.0f), + ((float)b / 255.0f), + ((float)a / 255.0f)); + + v[3].Position.x = xx1; + v[3].Position.y = yy1; + v[3].Position.z = 0; + v[3].Color = vec4( + ((float)r / 255.0f), + ((float)g / 255.0f), + ((float)b / 255.0f), + ((float)a / 255.0f)); + + + m_device_context->Unmap(m_pvertex_buffer, NULL); + + UINT Stride = sizeof(COLOR_VERTEX); + UINT Offset = 0; + + m_device_context->IASetVertexBuffers(0, 1, &m_pvertex_buffer, &Stride, &Offset); + m_device_context->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + m_device_context->IASetInputLayout(m_input_layout); + + m_device_context->VSSetShader(m_vertex_shader, 0, 0); + m_device_context->PSSetShader(m_pixel_shader, 0, 0); + m_device_context->GSSetShader(NULL, 0, 0); + m_device_context->Draw(4, 0); +} + +void no_gui::draw_line(float x1, float y1, float x2, float y2, color color) +{ + float blendFactor[] = { 1.0f, 1.0f, 1.0f, 1.0f }; + m_device_context->OMSetBlendState(m_transparency, blendFactor, 0xffffffff); + + if (m_device_context == NULL) { + return; + } + int a = color.A & 0xff; + int r = color.R & 0xff; + int g = color.G & 0xff; + int b = color.B & 0xff; + + UINT viewportNumber = 1; + + D3D11_VIEWPORT vp; + + m_device_context->RSGetViewports(&viewportNumber, &vp); + + float xx0 = 2.0f * (x1 - 0.5f) / vp.Width - 1.0f; + float yy0 = 1.0f - 2.0f * (y1 - 0.5f) / vp.Height; + float xx1 = 2.0f * (x2 - 0.5f) / vp.Width - 1.0f; + float yy1 = 1.0f - 2.0f * (y2 - 0.5f) / vp.Height; + + COLOR_VERTEX* v = NULL; + + D3D11_MAPPED_SUBRESOURCE mapData; + + if (FAILED(m_device_context->Map(m_pvertex_buffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &mapData))) + return; + + v = (COLOR_VERTEX*)mapData.pData; + v[0].Position.x = xx0; + v[0].Position.y = yy0; + + v[0].Position.z = 0; + v[0].Color = vec4( + ((float)r / 255.0f), + ((float)g / 255.0f), + ((float)b / 255.0f), + ((float)a / 255.0f)); + + v[1].Position.x = xx1; + v[1].Position.y = yy1; + v[1].Position.z = 0; + v[1].Color = vec4( + ((float)r / 255.0f), + ((float)g / 255.0f), + ((float)b / 255.0f), + ((float)a / 255.0f)); + + m_device_context->Unmap(m_pvertex_buffer, NULL); + UINT Stride = sizeof(COLOR_VERTEX); + UINT Offset = 0; + + m_device_context->IASetVertexBuffers(0, 1, &m_pvertex_buffer, &Stride, &Offset); + m_device_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP); + m_device_context->IASetInputLayout(m_input_layout); + + m_device_context->VSSetShader(m_vertex_shader, 0, 0); + m_device_context->PSSetShader(m_pixel_shader, 0, 0); + m_device_context->GSSetShader(NULL, 0, 0); + m_device_context->Draw(2, 0); +} + +void no_gui::draw_rect(float x, float y, float w, float h, color strokeColor) +{ + fill_rect(x, y, w, 1, strokeColor); + fill_rect(x, y + h - 1, w, 1, strokeColor); + fill_rect(x, y + 1, 1, h - 2 * 1, strokeColor); + fill_rect(x + w - 1, y + 1, 1, h - 2 * 1, strokeColor); +} + +void no_gui::draw_outlined_rect(const vec4& rect, const color& strokeColor, const color& color) +{ + fill_rect(rect.x, rect.y, rect.z, rect.w, color); + draw_rect(rect.x, rect.y, rect.z, rect.w, strokeColor); +} + +void no_gui::draw_corner_box(int x, int y, int w, int h, int borderPx, color& temp) +{ + fill_rect(x - (w / 2), (y - h + borderPx), w / 3, borderPx, temp); //top + fill_rect(x - (w / 2) + w - w / 3, (y - h + borderPx), w / 3, borderPx, temp); //top + fill_rect(x - (w / 2), (y - h + borderPx), borderPx, w / 3, temp); //left + fill_rect(x - (w / 2), (y - h + borderPx) + h - w / 3, borderPx, w / 3, temp); //left + fill_rect(x - (w / 2), y, w / 3, borderPx, temp); //bottom + fill_rect(x - (w / 2) + w - w / 3, y, w / 3, borderPx, temp); //bottom + fill_rect((x + w - borderPx) - (w / 2), (y - h + borderPx), borderPx, w / 3, temp); //right + fill_rect((x + w - borderPx) - (w / 2), (y - h + borderPx) + h - w / 3, borderPx, w / 3, temp); //right +} + +void no_gui::draw_border(int x, int y, int w, int h, int px, color& temp) +{ + fill_rect(x, (y + h - px), w, px, temp); + fill_rect(x, y, px, h, temp); + fill_rect(x, y, w, px, temp); + fill_rect((x + w - px), y, px, h, temp); +} + +void no_gui::draw_cross(float x, float y, float width, float height, const color& color) +{ + fill_rect(x - width, y - 0.5f, (width * 2.0f), 1.0f, color); + fill_rect(x - 0.5f, y - height, 1.0f, (height * 2.0f), color); +} + +void no_gui::draw_circle(float x0, float y0, float radius, const color& color, float thickness) +{ + int x = radius, y = 0; + int radius_error = 1 - x; + + while (x >= y) + { + fill_rect(x + x0, y + y0, thickness, thickness, color); + fill_rect(y + x0, x + y0, thickness, thickness, color); + fill_rect(-x + x0, y + y0, thickness, thickness, color); + fill_rect(-y + x0, x + y0, thickness, thickness, color); + fill_rect(-x + x0, -y + y0, thickness, thickness, color); + fill_rect(-y + x0, -x + y0, thickness, thickness, color); + fill_rect(x + x0, -y + y0, thickness, thickness, color); + fill_rect(y + x0, -x + y0, thickness, thickness, color); + y++; + + if (radius_error < 0) + radius_error += 2 * y + 1; + else + { + x--; + radius_error += 2 * (y - x + 1); + } + } +} + +void no_gui::draw_health_bar(int x, int y, float health, float max_health, int w, int h, bool is_shield) +{ + auto c_black = ::color(12, 12, 12, 228); + auto c_red = ::color(255, 0, 0, 255); + auto c_green = ::color(255, 0, 255, 0); + auto c_yellow = ::color(255, 255, 255, 0); + auto c_cyan = ::color(255, 0, 255, 255); + auto c_orange = ::color(255, 255, 153, 0); + + if (is_shield) + { + c_red = ::color(255, 102, 2, 209); + c_green = ::color(255, 19, 105, 244); + c_yellow = ::color(255, 13, 175, 229); + c_orange = ::color(255, 171, 13, 229); + } + + if (health > max_health) + health = max_health; + + FLOAT hp = health; + FLOAT factor = max_health / 4; + auto color = ::color(0.f, 0.f, 0.f, 0.f); + + if (hp <= factor) + color = c_red; + else if (hp <= factor * 2) + color = c_orange; + else if (hp <= factor * 3) + color = c_yellow; + else if (hp <= max_health) + color = c_green; + + fill_rect(x, y, w, h + 1, ::color(255, 0, 0, 0)); + UINT hw = (UINT)(((w - 2) * health) / max_health); + fill_rect(x + 1, y + 1, hw, h - 1, color); + +} + +HWND no_gui::get_window() +{ + return m_hwnd; +} + +float no_gui::get_width() +{ + return m_width; +} + +float no_gui::get_height() +{ + return m_height; +} + +void no_gui::begin_scene() +{ + m_swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&m_back_buffer); + ID3D11RenderTargetView* p_rtv; + m_device->CreateRenderTargetView(m_back_buffer, NULL, &p_rtv); + m_device_context->OMSetRenderTargets(1, &p_rtv, NULL); + + DXGI_SWAP_CHAIN_DESC swap_chain_desc; + memset(&swap_chain_desc, 0, sizeof(swap_chain_desc)); + m_swap_chain->GetDesc(&swap_chain_desc); + m_width = swap_chain_desc.BufferDesc.Width; + m_height = swap_chain_desc.BufferDesc.Height; + + m_restore_state = false; + if (SUCCEEDED(m_state_saver.save_current_state(m_device_context))) + m_restore_state = true; + m_device_context->IASetInputLayout(m_input_layout); +} + +void no_gui::end_scene() +{ + D3D11_TEXTURE2D_DESC backBufferDesc; + m_back_buffer->GetDesc(&backBufferDesc); + m_back_buffer->Release(); + + if (m_restore_state) + m_state_saver.restore_saved_state(); +} \ No newline at end of file diff --git a/internal/no_gui/no_gui.h b/internal/no_gui/no_gui.h new file mode 100644 index 0000000..ec23210 --- /dev/null +++ b/internal/no_gui/no_gui.h @@ -0,0 +1,150 @@ +#pragma once +#include +#include +#include +#include + +#include "no_shaders.h" +#include "no_state_saver.h" + +template inline void SAFE_DELETE(T*& p) +{ + if (p) + { + delete p; + p = NULL; + } +} + +template inline void SAFE_DELETE_ARRAY(T*& p) +{ + if (p) + { + delete[] p; + p = NULL; + } +} + +template inline void SAFE_RELEASE(T*& p) +{ + if (p) + { + p->Release(); + p = NULL; + } +} + +class vec3 +{ +public: + float x, y, z; + vec3(); + vec3(float, float, float); +}; + +inline vec3::vec3() +{ + x = y = z = 0.f; +} + +inline vec3::vec3(float _x, float _y, float _z) +{ + x = _x; + y = _y; + z = _z; +} +class vec4 +{ +public: + float x, y, z, w; + vec4(); + vec4(float, float, float, float); +}; + +inline vec4::vec4() +{ + x = y = z = w = 0.f; +} + +inline vec4::vec4(float _x, float _y, float _z, float _w) +{ + x = _x; + y = _y; + z = _z; + w = _w; +} +struct COLOR_VERTEX +{ + vec3 Position; + vec4 Color; +}; + +typedef unsigned char uchar; + +class color +{ +public: + uchar A, R, G, B; + + color() + { + A = R = G = B = 0; + } + + color(uchar A, uchar R, uchar G, uchar B) + { + this->A = A; + this->R = R; + this->G = G; + this->B = B; + } +}; + +enum _ALIGN : DWORD +{ + ALIGN_LEFT = 0, + ALIGN_RIGHT, + ALIGN_CENTER, +}; + + +class no_gui +{ +public: + + bool init(IDXGISwapChain* swap_chain); + void begin_scene(); + void end_scene(); + void reset(); + + void fill_rect(float x, float y, float w, float h, color color); + void draw_circle(float x0, float y0, float radius, const color& color, float thickness = 1.5f); + + void draw_outlined_rect(const vec4& rect, const color& stroke_color, const color& color); + void draw_line(float x1, float y1, float x2, float y2, color color); + void draw_rect(float x, float y, float w, float h, color stroke_color); + void draw_corner_box(int x, int y, int w, int h, int border_px, color& temp); + void draw_border(int x, int y, int w, int h, int px, color& temp); + void draw_cross(float X, float Y, float Width, float Height, const color& d_color); + void draw_health_bar(int x, int y, float health, float max_health, int w, int h, bool is_shield = false); + + float get_width(); + float get_height(); + HWND get_window(); + +private: + IDXGISwapChain* m_swap_chain; + ID3D11Device* m_device; + ID3D11DeviceContext* m_device_context; + ID3D11InputLayout* m_input_layout; + ID3D11Buffer* m_pvertex_buffer; + no_state_saver m_state_saver; + ID3D11VertexShader* m_vertex_shader; + ID3D11PixelShader* m_pixel_shader; + ID3D11BlendState* m_transparency; + ID3D11Texture2D* m_back_buffer; + + float m_width, m_height; + HWND m_hwnd; + bool m_restore_state; +}; diff --git a/internal/no_gui/no_shaders.h b/internal/no_gui/no_shaders.h new file mode 100644 index 0000000..90b51d6 --- /dev/null +++ b/internal/no_gui/no_shaders.h @@ -0,0 +1,124 @@ +#pragma once +// precompiled shaders +static const unsigned char vs_blob[] = { + 0x44, 0x58, 0x42, 0x43, 0x5f, 0x0b, 0x2c, 0x91, 0x23, 0xda, 0xe8, 0xae, + 0x94, 0x4b, 0x71, 0xfd, 0x64, 0x11, 0xb9, 0x13, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, + 0x94, 0x01, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x44, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x00, 0x04, 0xfe, 0xff, 0x00, 0x01, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, + 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, + 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, + 0x65, 0x72, 0x20, 0x31, 0x30, 0x2e, 0x31, 0x00, 0x49, 0x53, 0x47, 0x4e, + 0x48, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, + 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, + 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, + 0x4f, 0x4e, 0x00, 0xab, 0x4f, 0x53, 0x47, 0x4e, 0x4c, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x43, 0x4f, 0x4c, 0x4f, + 0x52, 0x00, 0x53, 0x56, 0x5f, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, + 0x4e, 0x00, 0xab, 0xab, 0x53, 0x48, 0x44, 0x52, 0x68, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, + 0xf2, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, + 0xf2, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, + 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x04, + 0xf2, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x05, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x1e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, + 0xf2, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, + 0x74, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char ps_blob[] = { + 0x44, 0x58, 0x42, 0x43, 0x71, 0xee, 0xb8, 0x3b, 0xe2, 0x77, 0xf8, 0x55, + 0x47, 0x8a, 0x89, 0xf3, 0x78, 0x2f, 0x06, 0xe9, 0x01, 0x00, 0x00, 0x00, + 0xa0, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, + 0x24, 0x01, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x44, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x00, 0x04, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, + 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, + 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, + 0x65, 0x72, 0x20, 0x31, 0x30, 0x2e, 0x31, 0x00, 0x49, 0x53, 0x47, 0x4e, + 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, + 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0xab, 0xab, 0x4f, 0x53, 0x47, 0x4e, + 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x53, 0x56, 0x5f, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x00, 0xab, 0xab, + 0x53, 0x48, 0x44, 0x52, 0x38, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, 0xf2, 0x10, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0xf2, 0x20, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x74, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0 +}; + + +/* +static char shader[] = { +"Texture2D g_texture : register(t0);" +"SamplerState g_sampler : register(s1);" + +"struct VSOut" +"{" +" float4 Pos : SV_POSITION;" +" float4 Col : COLOR;" +" float2 Uv : TEXCOORD;" +"};" + +"struct VSInput" +"{" +" float4 Pos : POSITION;" +" float4 Col : COLOR;" +" float2 Uv : TEXCOORD;" +"};" + +"VSOut VS( VSInput Input )" +"{" +" VSOut Result;" +" Result.Col = Input.Col;" +" Result.Pos = Input.Pos;" +" Result.Uv = Input.Uv;" +" return Result;" +"}" + +"float4 PS( VSOut Input ) : SV_TARGET" +"{" +" if(Input.Uv.x == 0 && Input.Uv.y == 0)" +" return Input.Col;" + + "return g_texture.Sample( g_sampler, Input.Uv ) * Input.Col;" +"};" +};*/ \ No newline at end of file diff --git a/internal/no_gui/no_state_saver.cpp b/internal/no_gui/no_state_saver.cpp new file mode 100644 index 0000000..04c6cbe --- /dev/null +++ b/internal/no_gui/no_state_saver.cpp @@ -0,0 +1,198 @@ +#include "no_gui.h" + +no_state_saver::no_state_saver() : + m_saved_state(false), + m_feature_level(D3D_FEATURE_LEVEL_11_0), + m_pcontext(NULL), + m_primitive_topology(D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED), + m_pinput_layout(NULL), + m_pblend_state(NULL), + m_sample_mask(0xffffffff), + m_pdepth_stencil_state(NULL), + m_stencilRef(0), + m_pRasterizerState(NULL), + m_pPSSRV(NULL), + m_pSamplerState(NULL), + m_pVS(NULL), + m_numVSClassInstances(0), + m_pVSConstantBuffer(NULL), + m_pGS(NULL), + m_numGSClassInstances(0), + m_pGSConstantBuffer(NULL), + m_pGSSRV(NULL), + m_pPS(NULL), + m_numPSClassInstances(0), + m_pHS(NULL), + m_numHSClassInstances(0), + m_pDS(NULL), + m_numDSClassInstances(0), + m_pVB(NULL), + m_vertexStride(0), + m_vertexOffset(0), + m_pIndexBuffer(NULL), + m_indexFormat(DXGI_FORMAT_UNKNOWN), + m_indexOffset(0) +{ + for (int i = 0; i < 4; ++i) + m_blend_factor[i] = 0.0f; + for (int i = 0; i < 256; ++i) + { + m_pVSClassInstances[i] = NULL; + m_pGSClassInstances[i] = NULL; + m_pPSClassInstances[i] = NULL; + m_pHSClassInstances[i] = NULL; + m_pDSClassInstances[i] = NULL; + } +} + +no_state_saver::~no_state_saver() +{ + release_saved_state(); +} + +HRESULT no_state_saver::save_current_state(ID3D11DeviceContext *pContext) +{ + if (m_saved_state) + release_saved_state(); + if (pContext == NULL) + return E_INVALIDARG; + + ID3D11Device *p_device; + pContext->GetDevice(&p_device); + if (p_device != NULL) { + m_feature_level = p_device->GetFeatureLevel(); + p_device->Release(); + } + + pContext->AddRef(); + m_pcontext = pContext; + + m_pcontext->IAGetPrimitiveTopology(&m_primitive_topology); + m_pcontext->IAGetInputLayout(&m_pinput_layout); + + m_pcontext->OMGetBlendState(&m_pblend_state, m_blend_factor, &m_sample_mask); + m_pcontext->OMGetDepthStencilState(&m_pdepth_stencil_state, &m_stencilRef); + + m_pcontext->RSGetState(&m_pRasterizerState); + + m_numVSClassInstances = 256; + m_pcontext->VSGetShader(&m_pVS, m_pVSClassInstances, &m_numVSClassInstances); + m_pcontext->VSGetConstantBuffers(0, 1, &m_pVSConstantBuffer); + + m_numPSClassInstances = 256; + m_pcontext->PSGetShader(&m_pPS, m_pPSClassInstances, &m_numPSClassInstances); + m_pcontext->PSGetShaderResources(0, 1, &m_pPSSRV); + pContext->PSGetSamplers(0, 1, &m_pSamplerState); + + if (m_feature_level >= D3D_FEATURE_LEVEL_10_0) + { + m_numGSClassInstances = 256; + m_pcontext->GSGetShader(&m_pGS, m_pGSClassInstances, &m_numGSClassInstances); + m_pcontext->GSGetConstantBuffers(0, 1, &m_pGSConstantBuffer); + + m_pcontext->GSGetShaderResources(0, 1, &m_pGSSRV); + + if (m_feature_level >= D3D_FEATURE_LEVEL_11_0) + { + m_numHSClassInstances = 256; + m_pcontext->HSGetShader(&m_pHS, m_pHSClassInstances, &m_numHSClassInstances); + + m_numDSClassInstances = 256; + m_pcontext->DSGetShader(&m_pDS, m_pDSClassInstances, &m_numDSClassInstances); + } + } + + m_pcontext->IAGetVertexBuffers(0, 1, &m_pVB, &m_vertexStride, &m_vertexOffset); + + m_pcontext->IAGetIndexBuffer(&m_pIndexBuffer, &m_indexFormat, &m_indexOffset); + + m_saved_state = true; + + return S_OK; +} + +HRESULT no_state_saver::restore_saved_state() +{ + if (!m_saved_state) + return E_FAIL; + + m_pcontext->IASetPrimitiveTopology(m_primitive_topology); + m_pcontext->IASetInputLayout(m_pinput_layout); + + m_pcontext->OMSetBlendState(m_pblend_state, m_blend_factor, m_sample_mask); + m_pcontext->OMSetDepthStencilState(m_pdepth_stencil_state, m_stencilRef); + + m_pcontext->RSSetState(m_pRasterizerState); + + m_pcontext->VSSetShader(m_pVS, m_pVSClassInstances, m_numVSClassInstances); + m_pcontext->VSSetConstantBuffers(0, 1, &m_pVSConstantBuffer); + + m_pcontext->PSSetShader(m_pPS, m_pPSClassInstances, m_numPSClassInstances); + m_pcontext->PSSetShaderResources(0, 1, &m_pPSSRV); + m_pcontext->PSSetSamplers(0, 1, &m_pSamplerState); + + if (m_feature_level >= D3D_FEATURE_LEVEL_10_0) + { + m_pcontext->GSSetShader(m_pGS, m_pGSClassInstances, m_numGSClassInstances); + m_pcontext->GSSetConstantBuffers(0, 1, &m_pGSConstantBuffer); + m_pcontext->GSSetShaderResources(0, 1, &m_pGSSRV); + + if (m_feature_level >= D3D_FEATURE_LEVEL_11_0) + { + m_pcontext->HSSetShader(m_pHS, m_pHSClassInstances, m_numHSClassInstances); + m_pcontext->DSSetShader(m_pDS, m_pDSClassInstances, m_numDSClassInstances); + } + } + + m_pcontext->IASetVertexBuffers(0, 1, &m_pVB, &m_vertexStride, &m_vertexOffset); + m_pcontext->IASetIndexBuffer(m_pIndexBuffer, m_indexFormat, m_indexOffset); + return S_OK; +} + +void no_state_saver::release_saved_state() +{ + m_primitive_topology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; + SAFE_RELEASE(m_pinput_layout); + SAFE_RELEASE(m_pblend_state); + for (int i = 0; i < 4; ++i) + m_blend_factor[i] = 0.0f; + m_sample_mask = 0xffffffff; + SAFE_RELEASE(m_pdepth_stencil_state); + m_stencilRef = 0; + SAFE_RELEASE(m_pRasterizerState); + SAFE_RELEASE(m_pPSSRV); + SAFE_RELEASE(m_pSamplerState); + SAFE_RELEASE(m_pVS); + for (UINT i = 0; i < m_numVSClassInstances; ++i) + SAFE_RELEASE(m_pVSClassInstances[i]); + m_numVSClassInstances = 0; + SAFE_RELEASE(m_pVSConstantBuffer); + SAFE_RELEASE(m_pGS); + for (UINT i = 0; i < m_numGSClassInstances; ++i) + SAFE_RELEASE(m_pGSClassInstances[i]); + m_numGSClassInstances = 0; + SAFE_RELEASE(m_pGSConstantBuffer); + SAFE_RELEASE(m_pGSSRV); + SAFE_RELEASE(m_pPS); + for (UINT i = 0; i < m_numPSClassInstances; ++i) + SAFE_RELEASE(m_pPSClassInstances[i]); + m_numPSClassInstances = 0; + SAFE_RELEASE(m_pHS); + for (UINT i = 0; i < m_numHSClassInstances; ++i) + SAFE_RELEASE(m_pHSClassInstances[i]); + m_numHSClassInstances = 0; + SAFE_RELEASE(m_pDS); + for (UINT i = 0; i < m_numDSClassInstances; ++i) + SAFE_RELEASE(m_pDSClassInstances[i]); + m_numDSClassInstances = 0; + SAFE_RELEASE(m_pVB); + m_vertexStride = 0; + m_vertexOffset = 0; + SAFE_RELEASE(m_pIndexBuffer); + m_indexFormat = DXGI_FORMAT_UNKNOWN; + m_indexOffset = 0; + + SAFE_RELEASE(m_pcontext); + m_feature_level = D3D_FEATURE_LEVEL_11_0; + m_saved_state = false; +} \ No newline at end of file diff --git a/internal/no_gui/no_state_saver.h b/internal/no_gui/no_state_saver.h new file mode 100644 index 0000000..bd42b13 --- /dev/null +++ b/internal/no_gui/no_state_saver.h @@ -0,0 +1,56 @@ +#pragma once +#include "no_gui.h" + +class no_state_saver +{ +private: + bool m_saved_state; + D3D_FEATURE_LEVEL m_feature_level; + ID3D11DeviceContext *m_pcontext; + D3D11_PRIMITIVE_TOPOLOGY m_primitive_topology; + ID3D11InputLayout *m_pinput_layout; + ID3D11BlendState *m_pblend_state; + float m_blend_factor[4]; + UINT m_sample_mask; + ID3D11DepthStencilState *m_pdepth_stencil_state; + UINT m_stencilRef; + ID3D11RasterizerState *m_pRasterizerState; + ID3D11ShaderResourceView *m_pPSSRV; + ID3D11SamplerState *m_pSamplerState; + ID3D11VertexShader *m_pVS; + ID3D11ClassInstance *m_pVSClassInstances[256]; + UINT m_numVSClassInstances; + ID3D11Buffer *m_pVSConstantBuffer; + ID3D11GeometryShader *m_pGS; + ID3D11ClassInstance *m_pGSClassInstances[256]; + UINT m_numGSClassInstances; + ID3D11Buffer *m_pGSConstantBuffer; + ID3D11ShaderResourceView *m_pGSSRV; + ID3D11PixelShader *m_pPS; + ID3D11ClassInstance *m_pPSClassInstances[256]; + UINT m_numPSClassInstances; + ID3D11HullShader *m_pHS; + ID3D11ClassInstance *m_pHSClassInstances[256]; + UINT m_numHSClassInstances; + ID3D11DomainShader *m_pDS; + ID3D11ClassInstance *m_pDSClassInstances[256]; + UINT m_numDSClassInstances; + ID3D11Buffer *m_pVB; + UINT m_vertexStride; + UINT m_vertexOffset; + ID3D11Buffer *m_pIndexBuffer; + DXGI_FORMAT m_indexFormat; + UINT m_indexOffset; + + no_state_saver(const no_state_saver&); + no_state_saver& operator=(const no_state_saver&); +public: + + no_state_saver(); + ~no_state_saver(); + + HRESULT save_current_state(ID3D11DeviceContext *p_context); + HRESULT restore_saved_state(); + void release_saved_state(); +}; + diff --git a/internal/no_imports.h b/internal/no_imports.h new file mode 100644 index 0000000..69325c3 --- /dev/null +++ b/internal/no_imports.h @@ -0,0 +1,658 @@ +/* + * Copyright 2018-2020 Justas Masiulis + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + // documentation is available at https://github.com/JustasMasiulis/lazy_importer + +#ifndef LAZY_IMPORTER_HPP +#define LAZY_IMPORTER_HPP + +#define LI_FN(name) \ + ::li::detail::lazy_function<::li::detail::khash(#name), decltype(&name)>() + +#define LI_FN_DEF(name) ::li::detail::lazy_function<::li::detail::khash(#name), name>() + +#define LI_MODULE(name) ::li::detail::lazy_module<::li::detail::khash(name)>() + + + +// NOTE only std::forward is used from this header. +// If there is a need to eliminate this dependency the function itself is very small. +#include +#include +#include + +#ifndef LAZY_IMPORTER_NO_FORCEINLINE +#if defined(_MSC_VER) +#define LAZY_IMPORTER_FORCEINLINE __forceinline +#elif defined(__GNUC__) && __GNUC__ > 3 +#define LAZY_IMPORTER_FORCEINLINE inline __attribute__((__always_inline__)) +#else +#define LAZY_IMPORTER_FORCEINLINE inline +#endif +#else +#define LAZY_IMPORTER_FORCEINLINE inline +#endif + +#ifdef LAZY_IMPORTER_CASE_INSENSITIVE +#define LAZY_IMPORTER_TOLOWER(c) (c >= 'A' && c <= 'Z' ? (c | (1 << 5)) : c) +#else +#define LAZY_IMPORTER_TOLOWER(c) (c) +#endif + +namespace li { + namespace detail { + + template + struct pair { + First first; + Second second; + }; + + namespace win { + + struct LIST_ENTRY_T { + const char* Flink; + const char* Blink; + }; + + struct UNICODE_STRING_T { + unsigned short Length; + unsigned short MaximumLength; + wchar_t* Buffer; + }; + + struct PEB_LDR_DATA_T { + unsigned long Length; + unsigned long Initialized; + const char* SsHandle; + LIST_ENTRY_T InLoadOrderModuleList; + }; + + struct PEB_T { + unsigned char Reserved1[2]; + unsigned char BeingDebugged; + unsigned char Reserved2[1]; + const char* Reserved3[2]; + PEB_LDR_DATA_T* Ldr; + }; + + struct LDR_DATA_TABLE_ENTRY_T { + LIST_ENTRY_T InLoadOrderLinks; + LIST_ENTRY_T InMemoryOrderLinks; + LIST_ENTRY_T InInitializationOrderLinks; + const char* DllBase; + const char* EntryPoint; + union { + unsigned long SizeOfImage; + const char* _dummy; + }; + UNICODE_STRING_T FullDllName; + UNICODE_STRING_T BaseDllName; + + LAZY_IMPORTER_FORCEINLINE const LDR_DATA_TABLE_ENTRY_T* + load_order_next() const noexcept + { + return reinterpret_cast( + InLoadOrderLinks.Flink); + } + }; + + struct IMAGE_DOS_HEADER { // DOS .EXE header + unsigned short e_magic; // Magic number + unsigned short e_cblp; // Bytes on last page of file + unsigned short e_cp; // Pages in file + unsigned short e_crlc; // Relocations + unsigned short e_cparhdr; // Size of header in paragraphs + unsigned short e_minalloc; // Minimum extra paragraphs needed + unsigned short e_maxalloc; // Maximum extra paragraphs needed + unsigned short e_ss; // Initial (relative) SS value + unsigned short e_sp; // Initial SP value + unsigned short e_csum; // Checksum + unsigned short e_ip; // Initial IP value + unsigned short e_cs; // Initial (relative) CS value + unsigned short e_lfarlc; // File address of relocation table + unsigned short e_ovno; // Overlay number + unsigned short e_res[4]; // Reserved words + unsigned short e_oemid; // OEM identifier (for e_oeminfo) + unsigned short e_oeminfo; // OEM information; e_oemid specific + unsigned short e_res2[10]; // Reserved words + long e_lfanew; // File address of new exe header + }; + + struct IMAGE_FILE_HEADER { + unsigned short Machine; + unsigned short NumberOfSections; + unsigned long TimeDateStamp; + unsigned long PointerToSymbolTable; + unsigned long NumberOfSymbols; + unsigned short SizeOfOptionalHeader; + unsigned short Characteristics; + }; + + struct IMAGE_EXPORT_DIRECTORY { + unsigned long Characteristics; + unsigned long TimeDateStamp; + unsigned short MajorVersion; + unsigned short MinorVersion; + unsigned long Name; + unsigned long Base; + unsigned long NumberOfFunctions; + unsigned long NumberOfNames; + unsigned long AddressOfFunctions; // RVA from base of image + unsigned long AddressOfNames; // RVA from base of image + unsigned long AddressOfNameOrdinals; // RVA from base of image + }; + + struct IMAGE_DATA_DIRECTORY { + unsigned long VirtualAddress; + unsigned long Size; + }; + + struct IMAGE_OPTIONAL_HEADER64 { + unsigned short Magic; + unsigned char MajorLinkerVersion; + unsigned char MinorLinkerVersion; + unsigned long SizeOfCode; + unsigned long SizeOfInitializedData; + unsigned long SizeOfUninitializedData; + unsigned long AddressOfEntryPoint; + unsigned long BaseOfCode; + unsigned long long ImageBase; + unsigned long SectionAlignment; + unsigned long FileAlignment; + unsigned short MajorOperatingSystemVersion; + unsigned short MinorOperatingSystemVersion; + unsigned short MajorImageVersion; + unsigned short MinorImageVersion; + unsigned short MajorSubsystemVersion; + unsigned short MinorSubsystemVersion; + unsigned long Win32VersionValue; + unsigned long SizeOfImage; + unsigned long SizeOfHeaders; + unsigned long CheckSum; + unsigned short Subsystem; + unsigned short DllCharacteristics; + unsigned long long SizeOfStackReserve; + unsigned long long SizeOfStackCommit; + unsigned long long SizeOfHeapReserve; + unsigned long long SizeOfHeapCommit; + unsigned long LoaderFlags; + unsigned long NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[16]; + }; + + struct IMAGE_OPTIONAL_HEADER32 { + unsigned short Magic; + unsigned char MajorLinkerVersion; + unsigned char MinorLinkerVersion; + unsigned long SizeOfCode; + unsigned long SizeOfInitializedData; + unsigned long SizeOfUninitializedData; + unsigned long AddressOfEntryPoint; + unsigned long BaseOfCode; + unsigned long BaseOfData; + unsigned long ImageBase; + unsigned long SectionAlignment; + unsigned long FileAlignment; + unsigned short MajorOperatingSystemVersion; + unsigned short MinorOperatingSystemVersion; + unsigned short MajorImageVersion; + unsigned short MinorImageVersion; + unsigned short MajorSubsystemVersion; + unsigned short MinorSubsystemVersion; + unsigned long Win32VersionValue; + unsigned long SizeOfImage; + unsigned long SizeOfHeaders; + unsigned long CheckSum; + unsigned short Subsystem; + unsigned short DllCharacteristics; + unsigned long SizeOfStackReserve; + unsigned long SizeOfStackCommit; + unsigned long SizeOfHeapReserve; + unsigned long SizeOfHeapCommit; + unsigned long LoaderFlags; + unsigned long NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[16]; + }; + + struct IMAGE_NT_HEADERS { + unsigned long Signature; + IMAGE_FILE_HEADER FileHeader; +#ifdef _WIN64 + IMAGE_OPTIONAL_HEADER64 OptionalHeader; +#else + IMAGE_OPTIONAL_HEADER32 OptionalHeader; +#endif + }; + + } // namespace win + + // hashing stuff + struct hash_t { + using value_type = unsigned long; + constexpr static value_type offset = 2166136261; + constexpr static value_type prime = 16777619; + constexpr static unsigned long long prime64 = prime; + + LAZY_IMPORTER_FORCEINLINE constexpr static value_type single(value_type value, + char c) noexcept + { + return static_cast( + (value ^ LAZY_IMPORTER_TOLOWER(c)) * + static_cast(prime)); + } + }; + + template + LAZY_IMPORTER_FORCEINLINE constexpr hash_t::value_type + khash(const CharT* str, hash_t::value_type value = hash_t::offset) noexcept + { + return (*str ? khash(str + 1, hash_t::single(value, *str)) : value); + } + + template + LAZY_IMPORTER_FORCEINLINE hash_t::value_type hash(const CharT* str) noexcept + { + hash_t::value_type value = hash_t::offset; + + for (;;) { + char c = *str++; + if (!c) + return value; + value = hash_t::single(value, c); + } + } + + LAZY_IMPORTER_FORCEINLINE hash_t::value_type hash( + const win::UNICODE_STRING_T& str) noexcept + { + auto first = str.Buffer; + const auto last = first + (str.Length / sizeof(wchar_t)); + auto value = hash_t::offset; + for (; first != last; ++first) + value = hash_t::single(value, static_cast(*first)); + + return value; + } + + LAZY_IMPORTER_FORCEINLINE pair hash_forwarded( + const char* str) noexcept + { + pair module_and_function{ + hash_t::offset, hash_t::offset + }; + + for (; *str != '.'; ++str) + module_and_function.first = hash_t::single(module_and_function.first, *str); + + ++str; + + for (; *str; ++str) + module_and_function.second = hash_t::single(module_and_function.second, *str); + + return module_and_function; + } + + + // some helper functions + LAZY_IMPORTER_FORCEINLINE const win::PEB_T* peb() noexcept + { +#if defined(_WIN64) + return reinterpret_cast(__readgsqword(0x60)); +#elif defined(_WIN32) + return reinterpret_cast(__readfsdword(0x30)); +#else +#error Unsupported platform. Open an issue and I'll probably add support. +#endif + } + + LAZY_IMPORTER_FORCEINLINE const win::PEB_LDR_DATA_T* ldr() + { + return reinterpret_cast(peb()->Ldr); + } + + LAZY_IMPORTER_FORCEINLINE const win::IMAGE_NT_HEADERS* nt_headers( + const char* base) noexcept + { + return reinterpret_cast( + base + reinterpret_cast(base)->e_lfanew); + } + + LAZY_IMPORTER_FORCEINLINE const win::IMAGE_EXPORT_DIRECTORY* image_export_dir( + const char* base) noexcept + { + return reinterpret_cast( + base + nt_headers(base)->OptionalHeader.DataDirectory->VirtualAddress); + } + + LAZY_IMPORTER_FORCEINLINE const win::LDR_DATA_TABLE_ENTRY_T* ldr_data_entry() noexcept + { + return reinterpret_cast( + ldr()->InLoadOrderModuleList.Flink); + } + + struct exports_directory { + const char* _base; + const win::IMAGE_EXPORT_DIRECTORY* _ied; + unsigned long _ied_size; + + public: + using size_type = unsigned long; + + LAZY_IMPORTER_FORCEINLINE + exports_directory(const char* base) noexcept : _base(base) + { + const auto ied_data_dir = nt_headers(base)->OptionalHeader.DataDirectory[0]; + _ied = reinterpret_cast( + base + ied_data_dir.VirtualAddress); + _ied_size = ied_data_dir.Size; + } + + LAZY_IMPORTER_FORCEINLINE explicit operator bool() const noexcept + { + return reinterpret_cast(_ied) != _base; + } + + LAZY_IMPORTER_FORCEINLINE size_type size() const noexcept + { + return _ied->NumberOfNames; + } + + LAZY_IMPORTER_FORCEINLINE const char* base() const noexcept { return _base; } + LAZY_IMPORTER_FORCEINLINE const win::IMAGE_EXPORT_DIRECTORY* ied() const noexcept + { + return _ied; + } + + LAZY_IMPORTER_FORCEINLINE const char* name(size_type index) const noexcept + { + return reinterpret_cast( + _base + reinterpret_cast( + _base + _ied->AddressOfNames)[index]); + } + + LAZY_IMPORTER_FORCEINLINE const char* address(size_type index) const noexcept + { + const auto* const rva_table = + reinterpret_cast(_base + _ied->AddressOfFunctions); + + const auto* const ord_table = reinterpret_cast( + _base + _ied->AddressOfNameOrdinals); + + return _base + rva_table[ord_table[index]]; + } + + LAZY_IMPORTER_FORCEINLINE bool is_forwarded(const char* export_address) const + noexcept + { + const auto ui_ied = reinterpret_cast(_ied); + return (export_address > ui_ied && export_address < ui_ied + _ied_size); + } + }; + + struct safe_module_enumerator { + using value_type = const detail::win::LDR_DATA_TABLE_ENTRY_T; + value_type* value; + value_type* const head; + + LAZY_IMPORTER_FORCEINLINE safe_module_enumerator() noexcept + : value(ldr_data_entry()), head(value) + {} + + LAZY_IMPORTER_FORCEINLINE void reset() noexcept { value = head; } + + LAZY_IMPORTER_FORCEINLINE bool next() noexcept + { + value = value->load_order_next(); + return value != head && value->DllBase; + } + }; + + struct unsafe_module_enumerator { + using value_type = const detail::win::LDR_DATA_TABLE_ENTRY_T*; + value_type value; + + LAZY_IMPORTER_FORCEINLINE unsafe_module_enumerator() noexcept + : value(ldr_data_entry()) + {} + + LAZY_IMPORTER_FORCEINLINE void reset() noexcept { value = ldr_data_entry(); } + + LAZY_IMPORTER_FORCEINLINE bool next() noexcept + { + value = value->load_order_next(); + return true; + } + }; + + // provides the cached functions which use Derive classes methods + template + class lazy_base { + protected: + // This function is needed because every templated function + // with different args has its own static buffer + LAZY_IMPORTER_FORCEINLINE static void*& _cache() noexcept + { + static void* value = nullptr; + return value; + } + + public: + template + LAZY_IMPORTER_FORCEINLINE static T safe() noexcept + { + return Derived::template get(); + } + + template + LAZY_IMPORTER_FORCEINLINE static T cached() noexcept + { + auto& cached = _cache(); + if (!cached) + cached = Derived::template get(); + + return (T)(cached); + } + + template + LAZY_IMPORTER_FORCEINLINE static T safe_cached() noexcept + { + return cached(); + } + }; + + template + struct lazy_module : lazy_base> { + template + LAZY_IMPORTER_FORCEINLINE static T get() noexcept + { + Enum e; + do { + if (hash(e.value->BaseDllName) == Hash) + return (T)(e.value->DllBase); + } while (e.next()); + return {}; + } + }; + + template + struct lazy_function : lazy_base, T> { + using base_type = lazy_base, T>; + + template + LAZY_IMPORTER_FORCEINLINE decltype(auto) operator()(Args&&... args) const + { +#ifndef LAZY_IMPORTER_CACHE_OPERATOR_PARENS + return get()(std::forward(args)...); +#else + return this->cached()(std::forward(args)...); +#endif + } + + template + LAZY_IMPORTER_FORCEINLINE static F get() noexcept + { + // for backwards compatability. + // Before 2.0 it was only possible to resolve forwarded exports when + // this macro was enabled +#ifdef LAZY_IMPORTER_RESOLVE_FORWARDED_EXPORTS + return forwarded(); +#else + Enum e; + do { + const exports_directory exports(e.value->DllBase); + + if (exports) { + auto export_index = exports.size(); + while (export_index--) + if (hash(exports.name(export_index)) == Hash) + return (F)(exports.address(export_index)); + } + } while (e.next()); + return {}; +#endif + } + + template + LAZY_IMPORTER_FORCEINLINE static F forwarded() noexcept + { + detail::win::UNICODE_STRING_T name; + hash_t::value_type module_hash = 0; + auto function_hash = Hash; + + Enum e; + do { + name = e.value->BaseDllName; + name.Length -= 8; // get rid of .dll extension + + if (!module_hash || hash(name) == module_hash) { + const exports_directory exports(e.value->DllBase); + + if (exports) { + auto export_index = exports.size(); + while (export_index--) + if (hash(exports.name(export_index)) == function_hash) { + const auto addr = exports.address(export_index); + + if (exports.is_forwarded(addr)) { + auto hashes = hash_forwarded( + reinterpret_cast(addr)); + + function_hash = hashes.second; + module_hash = hashes.first; + + e.reset(); + break; + } + return (F)(addr); + } + } + } + } while (e.next()); + return {}; + } + + template + LAZY_IMPORTER_FORCEINLINE static F forwarded_safe() noexcept + { + return forwarded(); + } + + template + LAZY_IMPORTER_FORCEINLINE static F forwarded_cached() noexcept + { + auto& value = base_type::_cache(); + if (!value) + value = forwarded(); + return (F)(value); + } + + template + LAZY_IMPORTER_FORCEINLINE static F forwarded_safe_cached() noexcept + { + return forwarded_cached(); + } + + template + LAZY_IMPORTER_FORCEINLINE static F in(Module m) noexcept + { + if (IsSafe && !m) + return {}; + + const exports_directory exports((const char*)(m)); + if (IsSafe && !exports) + return {}; + + for (unsigned long i{};; ++i) { + if (IsSafe && i == exports.size()) + break; + + if (hash(exports.name(i)) == Hash) + return (F)(exports.address(i)); + } + return {}; + } + + template + LAZY_IMPORTER_FORCEINLINE static F in_safe(Module m) noexcept + { + return in(m); + } + + template + LAZY_IMPORTER_FORCEINLINE static F in_cached(Module m) noexcept + { + auto& value = base_type::_cache(); + if (!value) + value = in(m); + return (F)(value); + } + + template + LAZY_IMPORTER_FORCEINLINE static F in_safe_cached(Module m) noexcept + { + return in_cached(m); + } + + template + LAZY_IMPORTER_FORCEINLINE static F nt() noexcept + { + return in(ldr_data_entry()->load_order_next()->DllBase); + } + + template + LAZY_IMPORTER_FORCEINLINE static F nt_safe() noexcept + { + return in_safe(ldr_data_entry()->load_order_next()->DllBase); + } + + template + LAZY_IMPORTER_FORCEINLINE static F nt_cached() noexcept + { + return in_cached(ldr_data_entry()->load_order_next()->DllBase); + } + + template + LAZY_IMPORTER_FORCEINLINE static F nt_safe_cached() noexcept + { + return in_safe_cached(ldr_data_entry()->load_order_next()->DllBase); + } + }; + + } +} // namespace li::detail + +#endif // include guard \ No newline at end of file diff --git a/internal/present.cpp b/internal/present.cpp new file mode 100644 index 0000000..98781c6 --- /dev/null +++ b/internal/present.cpp @@ -0,0 +1,65 @@ +#include +#include +#include "no_gui/no_gui.h" +#include "no_imports.h" + +no_gui gui; +std::atomic draw_first_init = true; +color blue(255, 0, 0, 255); +color red(255, 255, 0, 0); + +__declspec(dllexport) PHANDLE event_handle = nullptr; +using EtwEventUnregister = HANDLE(__fastcall*)(HANDLE); + +enum event_type +{ + present = 0x500100110000B2, + resize_buffers = 0x550200110000BD +}; + +void draw_handler(IDXGISwapChain* swapchain) +{ + if (draw_first_init.exchange(false)) + { + gui.init(swapchain); + const auto event_unregister = + LI_FN(GetProcAddress)( + LI_FN(GetModuleHandleA)("ntdll.dll"), + "EtwEventUnregister" + ); + + reinterpret_cast(event_unregister)(*event_handle); + } + + gui.begin_scene(); + { + gui.draw_circle(gui.get_width() / 2, gui.get_height() / 2, 100, blue); + gui.draw_cross(gui.get_width() / 2, gui.get_height() / 2, 100, 100, red); + } + gui.end_scene(); +} + +extern "C" __declspec(dllexport) ULONG event_handler +( + HANDLE handle, + event_type* event_des, + std::uint32_t data_count, + IDXGISwapChain*** swapchain +) +{ + if (event_des && swapchain) + { + // switch on the event, there is a present event + // a resize buffer event (if the window resizes) + // there are a bunch of other events you can get too... + switch (*event_des) + { + case present: + draw_handler(**swapchain); + break; + default: + break; + } + } + return true; +} \ No newline at end of file