mirror of
https://github.com/SpeedBreakerProject/speedbreaker.git
synced 2026-10-18 09:01:21 +02:00
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
593 lines
17 KiB
C++
593 lines
17 KiB
C++
// Adapted from Unleashed Recompiled (https://github.com/hedge-dev/UnleashedRecomp),
|
|
// GPL-3.0-or-later. Modified for SpeedBreaker: only functions with real
|
|
// implementations are kept. Unleashed's silent "!!! STUB !!!" functions,
|
|
// its Sonic-specific hooks, and the audio/video exports (later phases) are
|
|
// removed, so those imports fall back to our loud stubs
|
|
// (scripts/gen_import_stubs.py).
|
|
#include <stdafx.h>
|
|
#include <kernel/overlapped.h>
|
|
#include <cpu/ppc_context.h>
|
|
#include <cpu/guest_thread.h>
|
|
#include <cpu/guest_time.h>
|
|
#include "dispatcher.h"
|
|
#include "function.h"
|
|
#include "xex.h"
|
|
#include "xbox.h"
|
|
#include "heap.h"
|
|
#include "memory.h"
|
|
#include <memory>
|
|
#include "xam.h"
|
|
#include "xdm.h"
|
|
|
|
#ifdef _WIN32
|
|
#include <ntstatus.h>
|
|
#endif
|
|
|
|
|
|
uint32_t XGetGameRegion()
|
|
{
|
|
return 0x03FF; // all regions
|
|
}
|
|
|
|
uint32_t XamUserGetSigninState(uint32_t userIndex)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
uint32_t XamGetSystemVersion()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
uint32_t XamContentGetCreator(uint32_t userIndex, const XCONTENT_DATA* contentData, be<uint32_t>* isCreator, be<uint64_t>* xuid, XXOVERLAPPED* overlapped)
|
|
{
|
|
if (isCreator)
|
|
*isCreator = true;
|
|
|
|
if (xuid)
|
|
*xuid = 0xB13EBABEBABEBABE;
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t XamContentGetDeviceState()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
uint32_t XamUserGetSigninInfo(uint32_t userIndex, uint32_t flags, XUSER_SIGNIN_INFO* info)
|
|
{
|
|
if (userIndex == 0)
|
|
{
|
|
memset(info, 0, sizeof(*info));
|
|
info->xuid = 0xB13EBABEBABEBABE;
|
|
info->SigninState = 1;
|
|
strcpy(info->Name, "Player");
|
|
return 0;
|
|
}
|
|
|
|
return 0x00000525; // ERROR_NO_SUCH_USER
|
|
}
|
|
|
|
uint32_t XamShowDeviceSelectorUI
|
|
(
|
|
uint32_t userIndex,
|
|
uint32_t contentType,
|
|
uint32_t contentFlags,
|
|
uint64_t totalRequested,
|
|
be<uint32_t>* deviceId,
|
|
XXOVERLAPPED* overlapped
|
|
)
|
|
{
|
|
// One storage device (the hard drive, id 1) is always "selected".
|
|
XamNotifyEnqueueEvent(9, true);
|
|
*deviceId = 1;
|
|
XamNotifyEnqueueEvent(9, false);
|
|
if (overlapped)
|
|
{
|
|
CompleteOverlapped(overlapped, 0);
|
|
return 0x3E5; // ERROR_IO_PENDING
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
uint32_t XGetLanguage()
|
|
{
|
|
return 1; // XC_LANGUAGE_ENGLISH (TODO: setting)
|
|
}
|
|
|
|
uint32_t XGetAVPack()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void RtlInitAnsiString(XANSI_STRING* destination, char* source)
|
|
{
|
|
const uint16_t length = source ? (uint16_t)strlen(source) : 0;
|
|
destination->Length = length;
|
|
destination->MaximumLength = length + 1;
|
|
destination->Buffer = source;
|
|
}
|
|
|
|
uint32_t NtClose(uint32_t handle)
|
|
{
|
|
if (handle == GUEST_INVALID_HANDLE_VALUE)
|
|
return 0xFFFFFFFF;
|
|
|
|
if (IsKernelObject(handle))
|
|
{
|
|
ReleaseKernelObject(GetKernelObject(handle));
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
assert(false && "Unrecognized kernel object.");
|
|
return 0xFFFFFFFF;
|
|
}
|
|
}
|
|
|
|
uint32_t FscSetCacheElementCount()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
uint32_t ExGetXConfigSetting(uint16_t Category, uint16_t Setting, void* Buffer, uint16_t SizeOfBuffer, be<uint32_t>* RequiredSize)
|
|
{
|
|
uint32_t data[4]{};
|
|
|
|
switch (Category)
|
|
{
|
|
// XCONFIG_SECURED_CATEGORY
|
|
case 0x0002:
|
|
{
|
|
switch (Setting)
|
|
{
|
|
// XCONFIG_SECURED_AV_REGION
|
|
case 0x0002:
|
|
data[0] = ByteSwap(0x00001000); // USA/Canada
|
|
break;
|
|
|
|
default:
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
case 0x0003:
|
|
{
|
|
switch (Setting)
|
|
{
|
|
case 0x0001: // XCONFIG_USER_TIME_ZONE_BIAS
|
|
case 0x0002: // XCONFIG_USER_TIME_ZONE_STD_NAME
|
|
case 0x0003: // XCONFIG_USER_TIME_ZONE_DLT_NAME
|
|
case 0x0004: // XCONFIG_USER_TIME_ZONE_STD_DATE
|
|
case 0x0005: // XCONFIG_USER_TIME_ZONE_DLT_DATE
|
|
case 0x0006: // XCONFIG_USER_TIME_ZONE_STD_BIAS
|
|
case 0x0007: // XCONFIG_USER_TIME_ZONE_DLT_BIAS
|
|
data[0] = 0;
|
|
break;
|
|
|
|
// XCONFIG_USER_LANGUAGE
|
|
case 0x0009:
|
|
data[0] = ByteSwap(1u); // English (TODO: setting)
|
|
break;
|
|
|
|
// XCONFIG_USER_VIDEO_FLAGS
|
|
case 0x000A:
|
|
data[0] = ByteSwap(0x00040000);
|
|
break;
|
|
|
|
// XCONFIG_USER_RETAIL_FLAGS
|
|
case 0x000C:
|
|
data[0] = ByteSwap(1);
|
|
break;
|
|
|
|
// XCONFIG_USER_COUNTRY
|
|
case 0x000E:
|
|
data[0] = ByteSwap(103);
|
|
break;
|
|
|
|
default:
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
*RequiredSize = 4;
|
|
memcpy(Buffer, data, std::min((size_t)SizeOfBuffer, sizeof(data)));
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t XexCheckExecutablePrivilege()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
uint32_t RtlUnicodeToMultiByteN(char* MultiByteString, uint32_t MaxBytesInMultiByteString, be<uint32_t>* BytesInMultiByteString, const be<uint16_t>* UnicodeString, uint32_t BytesInUnicodeString)
|
|
{
|
|
const auto reqSize = BytesInUnicodeString / sizeof(uint16_t);
|
|
|
|
if (BytesInMultiByteString)
|
|
*BytesInMultiByteString = reqSize;
|
|
|
|
if (reqSize > MaxBytesInMultiByteString)
|
|
return STATUS_FAIL_CHECK;
|
|
|
|
for (size_t i = 0; i < reqSize; i++)
|
|
{
|
|
const auto c = UnicodeString[i].get();
|
|
|
|
MultiByteString[i] = c < 256 ? c : '?';
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
void KeSetBasePriorityThread(GuestThreadHandle* hThread, int priority)
|
|
{
|
|
#ifdef _WIN32
|
|
if (priority == 16)
|
|
{
|
|
priority = 15;
|
|
}
|
|
else if (priority == -16)
|
|
{
|
|
priority = -15;
|
|
}
|
|
|
|
SetThreadPriority(hThread == GetKernelObject(CURRENT_THREAD_HANDLE) ? GetCurrentThread() : hThread->thread.native_handle(), priority);
|
|
#endif
|
|
}
|
|
|
|
uint32_t ObReferenceObjectByHandle(uint32_t handle, uint32_t objectType, be<uint32_t>* object)
|
|
{
|
|
*object = handle;
|
|
return 0;
|
|
}
|
|
|
|
uint32_t NtSuspendThread(GuestThreadHandle* hThread, uint32_t* suspendCount)
|
|
{
|
|
assert(hThread != GetKernelObject(CURRENT_THREAD_HANDLE) && hThread->GetThreadId() == GuestThread::GetCurrentThreadId());
|
|
|
|
hThread->suspended = true;
|
|
hThread->suspended.wait(true);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
uint32_t KeSetAffinityThread(uint32_t Thread, uint32_t Affinity, be<uint32_t>* lpPreviousAffinity)
|
|
{
|
|
if (lpPreviousAffinity)
|
|
*lpPreviousAffinity = 2;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void RtlLeaveCriticalSection(XRTL_CRITICAL_SECTION* cs)
|
|
{
|
|
cs->RecursionCount--;
|
|
|
|
if (cs->RecursionCount != 0)
|
|
return;
|
|
|
|
std::atomic_ref owningThread(cs->OwningThread);
|
|
owningThread.store(0);
|
|
owningThread.notify_one();
|
|
}
|
|
|
|
void RtlEnterCriticalSection(XRTL_CRITICAL_SECTION* cs)
|
|
{
|
|
uint32_t thisThread = g_ppcContext->r13.u32;
|
|
assert(thisThread != NULL);
|
|
|
|
std::atomic_ref owningThread(cs->OwningThread);
|
|
|
|
while (true)
|
|
{
|
|
uint32_t previousOwner = 0;
|
|
|
|
if (owningThread.compare_exchange_weak(previousOwner, thisThread) || previousOwner == thisThread)
|
|
{
|
|
cs->RecursionCount++;
|
|
return;
|
|
}
|
|
|
|
owningThread.wait(previousOwner);
|
|
}
|
|
}
|
|
|
|
void KeBugCheckEx()
|
|
{
|
|
__builtin_debugtrap();
|
|
}
|
|
|
|
uint32_t KeGetCurrentProcessType()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
uint32_t RtlInitializeCriticalSection(XRTL_CRITICAL_SECTION* cs)
|
|
{
|
|
cs->Header.Absolute = 0;
|
|
cs->LockCount = -1;
|
|
cs->RecursionCount = 0;
|
|
cs->OwningThread = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void KfReleaseSpinLock(uint32_t* spinLock)
|
|
{
|
|
std::atomic_ref spinLockRef(*spinLock);
|
|
spinLockRef = 0;
|
|
}
|
|
|
|
void KfAcquireSpinLock(uint32_t* spinLock)
|
|
{
|
|
std::atomic_ref spinLockRef(*spinLock);
|
|
|
|
while (true)
|
|
{
|
|
uint32_t expected = 0;
|
|
if (spinLockRef.compare_exchange_weak(expected, g_ppcContext->r13.u32))
|
|
break;
|
|
|
|
// SpeedBreaker: while the game is suspended the holder is likely
|
|
// parked until it's back; park too rather than spin a core on yield.
|
|
guesttime::WaitWhileSuspended();
|
|
std::this_thread::yield();
|
|
}
|
|
}
|
|
|
|
uint64_t KeQueryPerformanceFrequency()
|
|
{
|
|
return 49875000;
|
|
}
|
|
|
|
void KeReleaseSpinLockFromRaisedIrql(uint32_t* spinLock)
|
|
{
|
|
std::atomic_ref spinLockRef(*spinLock);
|
|
spinLockRef = 0;
|
|
}
|
|
|
|
void KeAcquireSpinLockAtRaisedIrql(uint32_t* spinLock)
|
|
{
|
|
std::atomic_ref spinLockRef(*spinLock);
|
|
|
|
while (true)
|
|
{
|
|
uint32_t expected = 0;
|
|
if (spinLockRef.compare_exchange_weak(expected, g_ppcContext->r13.u32))
|
|
break;
|
|
|
|
guesttime::WaitWhileSuspended(); // SpeedBreaker: as KfAcquireSpinLock
|
|
std::this_thread::yield();
|
|
}
|
|
}
|
|
|
|
uint32_t KiApcNormalRoutineNop()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void KeBugCheck()
|
|
{
|
|
__builtin_debugtrap();
|
|
}
|
|
|
|
static std::vector<size_t> g_tlsFreeIndices;
|
|
static size_t g_tlsNextIndex = 0;
|
|
static Mutex g_tlsAllocationMutex;
|
|
|
|
static uint32_t& KeTlsGetValueRef(size_t index)
|
|
{
|
|
// Having this a global thread_local variable
|
|
// for some reason crashes on boot in debug builds.
|
|
thread_local std::vector<uint32_t> s_tlsValues;
|
|
|
|
if (s_tlsValues.size() <= index)
|
|
{
|
|
s_tlsValues.resize(index + 1, 0);
|
|
}
|
|
|
|
return s_tlsValues[index];
|
|
}
|
|
|
|
uint32_t KeTlsGetValue(uint32_t dwTlsIndex)
|
|
{
|
|
return KeTlsGetValueRef(dwTlsIndex);
|
|
}
|
|
|
|
uint32_t KeTlsSetValue(uint32_t dwTlsIndex, uint32_t lpTlsValue)
|
|
{
|
|
KeTlsGetValueRef(dwTlsIndex) = lpTlsValue;
|
|
return TRUE;
|
|
}
|
|
|
|
uint32_t KeTlsAlloc()
|
|
{
|
|
std::lock_guard<Mutex> lock(g_tlsAllocationMutex);
|
|
if (!g_tlsFreeIndices.empty())
|
|
{
|
|
size_t index = g_tlsFreeIndices.back();
|
|
g_tlsFreeIndices.pop_back();
|
|
return index;
|
|
}
|
|
|
|
return g_tlsNextIndex++;
|
|
}
|
|
|
|
uint32_t KeTlsFree(uint32_t dwTlsIndex)
|
|
{
|
|
std::lock_guard<Mutex> lock(g_tlsAllocationMutex);
|
|
g_tlsFreeIndices.push_back(dwTlsIndex);
|
|
return TRUE;
|
|
}
|
|
|
|
bool RtlTryEnterCriticalSection(XRTL_CRITICAL_SECTION* cs)
|
|
{
|
|
uint32_t thisThread = g_ppcContext->r13.u32;
|
|
assert(thisThread != NULL);
|
|
|
|
std::atomic_ref owningThread(cs->OwningThread);
|
|
|
|
uint32_t previousOwner = 0;
|
|
|
|
if (owningThread.compare_exchange_weak(previousOwner, thisThread) || previousOwner == thisThread)
|
|
{
|
|
cs->RecursionCount++;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void RtlInitializeCriticalSectionAndSpinCount(XRTL_CRITICAL_SECTION* cs, uint32_t spinCount)
|
|
{
|
|
cs->Header.Absolute = (spinCount + 255) >> 8;
|
|
cs->LockCount = -1;
|
|
cs->RecursionCount = 0;
|
|
cs->OwningThread = 0;
|
|
}
|
|
|
|
uint32_t RtlMultiByteToUnicodeN(be<uint16_t>* UnicodeString, uint32_t MaxBytesInUnicodeString, be<uint32_t>* BytesInUnicodeString, const char* MultiByteString, uint32_t BytesInMultiByteString)
|
|
{
|
|
uint32_t length = std::min(MaxBytesInUnicodeString / 2, BytesInMultiByteString);
|
|
|
|
for (size_t i = 0; i < length; i++)
|
|
UnicodeString[i] = MultiByteString[i];
|
|
|
|
if (BytesInUnicodeString != nullptr)
|
|
*BytesInUnicodeString = length * 2;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
uint32_t NtResumeThread(GuestThreadHandle* hThread, uint32_t* suspendCount)
|
|
{
|
|
assert(hThread != GetKernelObject(CURRENT_THREAD_HANDLE));
|
|
|
|
hThread->suspended = false;
|
|
hThread->suspended.notify_all();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void KeQuerySystemTime(be<uint64_t>* time)
|
|
{
|
|
// SpeedBreaker: the guest's system time, which stands still while the
|
|
// game is suspended (the same clock as the kernel's absolute timeouts).
|
|
*time = uint64_t(dispatcher::GuestSystemTime());
|
|
}
|
|
|
|
uint32_t ExCreateThread(be<uint32_t>* handle, uint32_t stackSize, be<uint32_t>* threadId, uint32_t xApiThreadStartup, uint32_t startAddress, uint32_t startContext, uint32_t creationFlags)
|
|
{
|
|
LOGF_UTILITY("0x{:X}, 0x{:X}, 0x{:X}, 0x{:X}, 0x{:X}, 0x{:X}, 0x{:X}",
|
|
(intptr_t)handle, stackSize, (intptr_t)threadId, xApiThreadStartup, startAddress, startContext, creationFlags);
|
|
|
|
uint32_t hostThreadId;
|
|
|
|
// SpeedBreaker: honour the XAPI startup routine like the 360 kernel (and
|
|
// Xenia): it runs startup(startAddress, startContext) and sets up the
|
|
// thread's CRT state before calling the start address.
|
|
GuestThreadParams params = xApiThreadStartup != 0
|
|
? GuestThreadParams{ xApiThreadStartup, startAddress, creationFlags, startContext }
|
|
: GuestThreadParams{ startAddress, startContext, creationFlags };
|
|
*handle = GetKernelHandle(GuestThread::Start(params, &hostThreadId));
|
|
|
|
if (threadId != nullptr)
|
|
*threadId = hostThreadId;
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t KeRaiseIrqlToDpcLevel()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void KfLowerIrql() { }
|
|
|
|
uint32_t KeResumeThread(GuestThreadHandle* object)
|
|
{
|
|
assert(object != GetKernelObject(CURRENT_THREAD_HANDLE));
|
|
|
|
object->suspended = false;
|
|
object->suspended.notify_all();
|
|
return 0;
|
|
}
|
|
|
|
// uint32_t XAudioRegisterRenderDriverClient(be<uint32_t>* callback, be<uint32_t>* driver)
|
|
// {
|
|
// //printf("XAudioRegisterRenderDriverClient(): %x %x\n");
|
|
//
|
|
// *driver = apu::RegisterClient(callback[0], callback[1]);
|
|
// return 0;
|
|
// }
|
|
|
|
// void XAudioUnregisterRenderDriverClient()
|
|
// {
|
|
// printf("!!! STUB !!! XAudioUnregisterRenderDriverClient\n");
|
|
// }
|
|
|
|
// uint32_t XAudioSubmitRenderDriverFrame(uint32_t driver, void* samples)
|
|
// {
|
|
// // printf("!!! STUB !!! XAudioSubmitRenderDriverFrame\n");
|
|
// apu::SubmitFrames(samples);
|
|
//
|
|
// return 0;
|
|
// }
|
|
|
|
GUEST_FUNCTION_HOOK(__imp__XNotifyGetNext, XNotifyGetNext);
|
|
GUEST_FUNCTION_HOOK(__imp__XGetGameRegion, XGetGameRegion);
|
|
GUEST_FUNCTION_HOOK(__imp__XamUserGetSigninState, XamUserGetSigninState);
|
|
GUEST_FUNCTION_HOOK(__imp__XamGetSystemVersion, XamGetSystemVersion);
|
|
GUEST_FUNCTION_HOOK(__imp__XamContentCreateEx, XamContentCreateEx);
|
|
GUEST_FUNCTION_HOOK(__imp__XamContentClose, XamContentClose);
|
|
GUEST_FUNCTION_HOOK(__imp__XamContentGetCreator, XamContentGetCreator);
|
|
GUEST_FUNCTION_HOOK(__imp__XamContentCreateEnumerator, XamContentCreateEnumerator);
|
|
GUEST_FUNCTION_HOOK(__imp__XamContentGetDeviceState, XamContentGetDeviceState);
|
|
GUEST_FUNCTION_HOOK(__imp__XamContentGetDeviceData, XamContentGetDeviceData);
|
|
GUEST_FUNCTION_HOOK(__imp__XamEnumerate, XamEnumerate);
|
|
GUEST_FUNCTION_HOOK(__imp__XamNotifyCreateListener, XamNotifyCreateListener);
|
|
GUEST_FUNCTION_HOOK(__imp__XamUserGetSigninInfo, XamUserGetSigninInfo);
|
|
GUEST_FUNCTION_HOOK(__imp__XamShowDeviceSelectorUI, XamShowDeviceSelectorUI);
|
|
GUEST_FUNCTION_HOOK(__imp__XamShowMessageBoxUI, XamShowMessageBoxUI);
|
|
GUEST_FUNCTION_HOOK(__imp__XGetLanguage, XGetLanguage);
|
|
GUEST_FUNCTION_HOOK(__imp__XGetAVPack, XGetAVPack);
|
|
GUEST_FUNCTION_HOOK(__imp__RtlInitAnsiString, RtlInitAnsiString);
|
|
GUEST_FUNCTION_HOOK(__imp__NtClose, NtClose);
|
|
GUEST_FUNCTION_HOOK(__imp__FscSetCacheElementCount, FscSetCacheElementCount);
|
|
GUEST_FUNCTION_HOOK(__imp__ExGetXConfigSetting, ExGetXConfigSetting);
|
|
GUEST_FUNCTION_HOOK(__imp__XexCheckExecutablePrivilege, XexCheckExecutablePrivilege);
|
|
GUEST_FUNCTION_HOOK(__imp__RtlUnicodeToMultiByteN, RtlUnicodeToMultiByteN);
|
|
GUEST_FUNCTION_HOOK(__imp__KeSetBasePriorityThread, KeSetBasePriorityThread);
|
|
GUEST_FUNCTION_HOOK(__imp__ObReferenceObjectByHandle, ObReferenceObjectByHandle);
|
|
GUEST_FUNCTION_HOOK(__imp__NtSuspendThread, NtSuspendThread);
|
|
GUEST_FUNCTION_HOOK(__imp__KeSetAffinityThread, KeSetAffinityThread);
|
|
GUEST_FUNCTION_HOOK(__imp__RtlLeaveCriticalSection, RtlLeaveCriticalSection);
|
|
GUEST_FUNCTION_HOOK(__imp__RtlEnterCriticalSection, RtlEnterCriticalSection);
|
|
GUEST_FUNCTION_HOOK(__imp__KeBugCheckEx, KeBugCheckEx);
|
|
GUEST_FUNCTION_HOOK(__imp__KeGetCurrentProcessType, KeGetCurrentProcessType);
|
|
GUEST_FUNCTION_HOOK(__imp__RtlInitializeCriticalSection, RtlInitializeCriticalSection);
|
|
GUEST_FUNCTION_HOOK(__imp__KfReleaseSpinLock, KfReleaseSpinLock);
|
|
GUEST_FUNCTION_HOOK(__imp__KfAcquireSpinLock, KfAcquireSpinLock);
|
|
GUEST_FUNCTION_HOOK(__imp__KeQueryPerformanceFrequency, KeQueryPerformanceFrequency);
|
|
GUEST_FUNCTION_HOOK(__imp__KeReleaseSpinLockFromRaisedIrql, KeReleaseSpinLockFromRaisedIrql);
|
|
GUEST_FUNCTION_HOOK(__imp__KeAcquireSpinLockAtRaisedIrql, KeAcquireSpinLockAtRaisedIrql);
|
|
GUEST_FUNCTION_HOOK(__imp__KiApcNormalRoutineNop, KiApcNormalRoutineNop);
|
|
GUEST_FUNCTION_HOOK(__imp__KeBugCheck, KeBugCheck);
|
|
GUEST_FUNCTION_HOOK(__imp__KeTlsGetValue, KeTlsGetValue);
|
|
GUEST_FUNCTION_HOOK(__imp__KeTlsSetValue, KeTlsSetValue);
|
|
GUEST_FUNCTION_HOOK(__imp__KeTlsAlloc, KeTlsAlloc);
|
|
GUEST_FUNCTION_HOOK(__imp__KeTlsFree, KeTlsFree);
|
|
GUEST_FUNCTION_HOOK(__imp__RtlTryEnterCriticalSection, RtlTryEnterCriticalSection);
|
|
GUEST_FUNCTION_HOOK(__imp__RtlInitializeCriticalSectionAndSpinCount, RtlInitializeCriticalSectionAndSpinCount);
|
|
GUEST_FUNCTION_HOOK(__imp__RtlMultiByteToUnicodeN, RtlMultiByteToUnicodeN);
|
|
GUEST_FUNCTION_HOOK(__imp__NtResumeThread, NtResumeThread);
|
|
GUEST_FUNCTION_HOOK(__imp__KeQuerySystemTime, KeQuerySystemTime);
|
|
GUEST_FUNCTION_HOOK(__imp__ExCreateThread, ExCreateThread);
|
|
GUEST_FUNCTION_HOOK(__imp__KeRaiseIrqlToDpcLevel, KeRaiseIrqlToDpcLevel);
|
|
GUEST_FUNCTION_HOOK(__imp__KfLowerIrql, KfLowerIrql);
|
|
GUEST_FUNCTION_HOOK(__imp__KeResumeThread, KeResumeThread);
|