LunaHook-mirror/include/utils.h

145 lines
3.1 KiB
C
Raw Normal View History

2024-02-07 20:59:24 +08:00
#pragma once
#ifdef _WIN64
constexpr bool x64 = true;
#else
constexpr bool x64 = false;
#endif
2024-07-21 21:07:05 +08:00
template <typename T, typename... Xs>
struct ArrayImpl
{
using Type = std::tuple<T, Xs...>[];
};
template <typename T>
struct ArrayImpl<T>
{
using Type = T[];
};
template <typename... Ts>
using Array = typename ArrayImpl<Ts...>::Type;
2024-02-07 20:59:24 +08:00
2024-07-21 21:07:05 +08:00
template <auto F>
using Functor = std::integral_constant<std::remove_reference_t<decltype(F)>, F>; // shouldn't need remove_reference_t but MSVC is bugged
2024-02-07 20:59:24 +08:00
struct PermissivePointer
{
2024-07-21 21:07:05 +08:00
template <typename T>
operator T *() { return (T *)p; }
void *p;
2024-02-07 20:59:24 +08:00
};
template <typename HandleCloser = Functor<CloseHandle>>
class AutoHandle
{
public:
AutoHandle(HANDLE h) : h(h) {}
operator HANDLE() { return h.get(); }
2024-07-21 21:07:05 +08:00
PHANDLE operator&()
{
static_assert(sizeof(*this) == sizeof(HANDLE));
assert(!h);
return (PHANDLE)this;
}
2024-02-07 20:59:24 +08:00
operator bool() { return h.get() != NULL && h.get() != INVALID_HANDLE_VALUE; }
private:
2024-07-21 21:07:05 +08:00
struct HandleCleaner
{
void operator()(void *h)
{
if (h != INVALID_HANDLE_VALUE)
HandleCloser()(PermissivePointer{h});
}
};
2024-02-07 20:59:24 +08:00
std::unique_ptr<void, HandleCleaner> h;
};
2024-07-21 21:07:05 +08:00
template <typename T, typename M = std::mutex>
2024-02-07 20:59:24 +08:00
class Synchronized
{
public:
template <typename... Args>
2024-07-21 21:07:05 +08:00
Synchronized(Args &&...args) : contents(std::forward<Args>(args)...) {}
2024-02-07 20:59:24 +08:00
struct Locker
{
2024-07-21 21:07:05 +08:00
T *operator->() { return &contents; }
2024-02-07 20:59:24 +08:00
std::unique_lock<M> lock;
2024-07-21 21:07:05 +08:00
T &contents;
2024-02-07 20:59:24 +08:00
};
2024-07-21 21:07:05 +08:00
Locker Acquire() { return {std::unique_lock(m), contents}; }
2024-02-07 20:59:24 +08:00
Locker operator->() { return Acquire(); }
T Copy() { return Acquire().contents; }
private:
T contents;
M m;
};
template <typename F>
2024-07-21 21:07:05 +08:00
void SpawnThread(const F &f) // works in DllMain unlike std thread
2024-02-07 20:59:24 +08:00
{
2024-07-21 21:07:05 +08:00
F *copy = new F(f);
CloseHandle(CreateThread(nullptr, 0, [](void *copy)
{
2024-02-07 20:59:24 +08:00
(*(F*)copy)();
delete (F*)copy;
2024-07-21 21:07:05 +08:00
return 0UL; }, copy, 0, nullptr));
2024-02-07 20:59:24 +08:00
}
inline struct // should be inline but MSVC (linker) is bugged
{
inline static BYTE DUMMY[100];
2024-07-21 21:07:05 +08:00
template <typename T>
operator T *()
{
static_assert(sizeof(T) < sizeof(DUMMY));
return (T *)DUMMY;
}
2024-02-07 20:59:24 +08:00
} DUMMY;
2024-07-21 21:07:05 +08:00
inline auto Swallow = [](auto &&...) {};
2024-02-07 20:59:24 +08:00
2024-07-21 21:07:05 +08:00
template <typename T>
std::optional<std::remove_cv_t<T>> Copy(T *ptr)
{
if (ptr)
return *ptr;
return {};
}
2024-02-07 20:59:24 +08:00
2024-05-12 16:48:32 +08:00
inline std::optional<std::wstring> getModuleFilename(DWORD processId, HMODULE module = NULL)
2024-02-07 20:59:24 +08:00
{
std::vector<wchar_t> buffer(MAX_PATH);
if (AutoHandle<> process = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, processId))
2024-07-21 21:07:05 +08:00
if (GetModuleFileNameExW(process, module, buffer.data(), MAX_PATH))
return buffer.data();
2024-02-07 20:59:24 +08:00
return {};
}
2024-05-12 16:48:32 +08:00
inline std::optional<std::wstring> getModuleFilename(HMODULE module = NULL)
2024-02-07 20:59:24 +08:00
{
std::vector<wchar_t> buffer(MAX_PATH);
2024-07-21 21:07:05 +08:00
if (GetModuleFileNameW(module, buffer.data(), MAX_PATH))
return buffer.data();
2024-02-07 20:59:24 +08:00
return {};
}
2024-05-14 13:07:12 +08:00
2024-07-21 21:07:05 +08:00
template <typename T>
struct SafeFptr
{
2024-05-14 13:07:12 +08:00
T ptr;
uintptr_t errorvalue;
SafeFptr(T _ptr, uintptr_t v = {NULL}) : ptr(_ptr), errorvalue(v) {}
2024-07-21 21:07:05 +08:00
template <typename... Args>
std::invoke_result_t<T, Args...> operator()(Args... args)
{
if (!ptr)
return (std::invoke_result_t<T, Args...>)(errorvalue);
2024-05-14 13:07:12 +08:00
return ptr(std::forward<Args>(args)...);
}
};