#pragma once #include "../Config.h" #include "../Include/Winheaders.h" #include #include extern "C" void* syscall_stub(); namespace blackbone { namespace syscall { template using to_int64 = std::conditional_t; #pragma warning(push) #pragma warning(disable : 4100) template R syscall( int index, Args... args ) { auto error = []( NTSTATUS status ) { if constexpr (std::is_same_v) return status; else return R(); }; #ifdef USE32 return error( STATUS_NOT_SUPPORTED ); #else static_assert(sizeof( R ) <= sizeof( void* ), "Return types larger than void* aren't supported"); if (index == -1) return error( STATUS_INVALID_PARAMETER_1 ); // Cast types that otherwise will be only half-initialized auto pfn = reinterpret_cast... )>(syscall_stub); return pfn( index, sizeof...( Args ), to_int64( args )... ); #endif } template NTSTATUS nt_syscall( int index, Args&&... args ) { return syscall( index, std::forward( args )... ); } inline int get_index( const wchar_t* modName, const char* func ) { #ifdef USE32 // Doesn't work for x86 return -1; #else const auto pfn = reinterpret_cast(GetProcAddress( GetModuleHandleW( modName ), func )); return pfn ? *reinterpret_cast(pfn + 4) : -1; #endif } inline int get_index( const char* func ) { return get_index( L"ntdll.dll", func ); } #pragma warning(pop) } }