添加项目文件。
This commit is contained in:
31
csgo2.sln
Normal file
31
csgo2.sln
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.33130.400
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "csgo2", "csgo2\csgo2.vcxproj", "{0AF170B6-CC8D-4A56-9879-5064F3D3EBDB}"
|
||||||
|
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
|
||||||
|
{0AF170B6-CC8D-4A56-9879-5064F3D3EBDB}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{0AF170B6-CC8D-4A56-9879-5064F3D3EBDB}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{0AF170B6-CC8D-4A56-9879-5064F3D3EBDB}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{0AF170B6-CC8D-4A56-9879-5064F3D3EBDB}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{0AF170B6-CC8D-4A56-9879-5064F3D3EBDB}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{0AF170B6-CC8D-4A56-9879-5064F3D3EBDB}.Release|x64.Build.0 = Release|x64
|
||||||
|
{0AF170B6-CC8D-4A56-9879-5064F3D3EBDB}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{0AF170B6-CC8D-4A56-9879-5064F3D3EBDB}.Release|x86.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {14904916-41DB-45E6-A72D-6AE7FD145050}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
1
csgo2/MinHook/.gitkeep
Normal file
1
csgo2/MinHook/.gitkeep
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
186
csgo2/MinHook/include/MinHook.h
Normal file
186
csgo2/MinHook/include/MinHook.h
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* MinHook - The Minimalistic API Hooking Library for x64/x86
|
||||||
|
* Copyright (C) 2009-2017 Tsuda Kageyu.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__)
|
||||||
|
#error MinHook supports only x86 and x64 systems.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
// MinHook Error Codes.
|
||||||
|
typedef enum MH_STATUS
|
||||||
|
{
|
||||||
|
// Unknown error. Should not be returned.
|
||||||
|
MH_UNKNOWN = -1,
|
||||||
|
|
||||||
|
// Successful.
|
||||||
|
MH_OK = 0,
|
||||||
|
|
||||||
|
// MinHook is already initialized.
|
||||||
|
MH_ERROR_ALREADY_INITIALIZED,
|
||||||
|
|
||||||
|
// MinHook is not initialized yet, or already uninitialized.
|
||||||
|
MH_ERROR_NOT_INITIALIZED,
|
||||||
|
|
||||||
|
// The hook for the specified target function is already created.
|
||||||
|
MH_ERROR_ALREADY_CREATED,
|
||||||
|
|
||||||
|
// The hook for the specified target function is not created yet.
|
||||||
|
MH_ERROR_NOT_CREATED,
|
||||||
|
|
||||||
|
// The hook for the specified target function is already enabled.
|
||||||
|
MH_ERROR_ENABLED,
|
||||||
|
|
||||||
|
// The hook for the specified target function is not enabled yet, or already
|
||||||
|
// disabled.
|
||||||
|
MH_ERROR_DISABLED,
|
||||||
|
|
||||||
|
// The specified pointer is invalid. It points the address of non-allocated
|
||||||
|
// and/or non-executable region.
|
||||||
|
MH_ERROR_NOT_EXECUTABLE,
|
||||||
|
|
||||||
|
// The specified target function cannot be hooked.
|
||||||
|
MH_ERROR_UNSUPPORTED_FUNCTION,
|
||||||
|
|
||||||
|
// Failed to allocate memory.
|
||||||
|
MH_ERROR_MEMORY_ALLOC,
|
||||||
|
|
||||||
|
// Failed to change the memory protection.
|
||||||
|
MH_ERROR_MEMORY_PROTECT,
|
||||||
|
|
||||||
|
// The specified module is not loaded.
|
||||||
|
MH_ERROR_MODULE_NOT_FOUND,
|
||||||
|
|
||||||
|
// The specified function is not found.
|
||||||
|
MH_ERROR_FUNCTION_NOT_FOUND
|
||||||
|
}
|
||||||
|
MH_STATUS;
|
||||||
|
|
||||||
|
// Can be passed as a parameter to MH_EnableHook, MH_DisableHook,
|
||||||
|
// MH_QueueEnableHook or MH_QueueDisableHook.
|
||||||
|
#define MH_ALL_HOOKS NULL
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialize the MinHook library. You must call this function EXACTLY ONCE
|
||||||
|
// at the beginning of your program.
|
||||||
|
MH_STATUS WINAPI MH_Initialize(VOID);
|
||||||
|
|
||||||
|
// Uninitialize the MinHook library. You must call this function EXACTLY
|
||||||
|
// ONCE at the end of your program.
|
||||||
|
MH_STATUS WINAPI MH_Uninitialize(VOID);
|
||||||
|
|
||||||
|
// Creates a Hook for the specified target function, in disabled state.
|
||||||
|
// Parameters:
|
||||||
|
// pTarget [in] A pointer to the target function, which will be
|
||||||
|
// overridden by the detour function.
|
||||||
|
// pDetour [in] A pointer to the detour function, which will override
|
||||||
|
// the target function.
|
||||||
|
// ppOriginal [out] A pointer to the trampoline function, which will be
|
||||||
|
// used to call the original target function.
|
||||||
|
// This parameter can be NULL.
|
||||||
|
MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal);
|
||||||
|
|
||||||
|
// Creates a Hook for the specified API function, in disabled state.
|
||||||
|
// Parameters:
|
||||||
|
// pszModule [in] A pointer to the loaded module name which contains the
|
||||||
|
// target function.
|
||||||
|
// pszTarget [in] A pointer to the target function name, which will be
|
||||||
|
// overridden by the detour function.
|
||||||
|
// pDetour [in] A pointer to the detour function, which will override
|
||||||
|
// the target function.
|
||||||
|
// ppOriginal [out] A pointer to the trampoline function, which will be
|
||||||
|
// used to call the original target function.
|
||||||
|
// This parameter can be NULL.
|
||||||
|
MH_STATUS WINAPI MH_CreateHookApi(
|
||||||
|
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal);
|
||||||
|
|
||||||
|
// Creates a Hook for the specified API function, in disabled state.
|
||||||
|
// Parameters:
|
||||||
|
// pszModule [in] A pointer to the loaded module name which contains the
|
||||||
|
// target function.
|
||||||
|
// pszTarget [in] A pointer to the target function name, which will be
|
||||||
|
// overridden by the detour function.
|
||||||
|
// pDetour [in] A pointer to the detour function, which will override
|
||||||
|
// the target function.
|
||||||
|
// ppOriginal [out] A pointer to the trampoline function, which will be
|
||||||
|
// used to call the original target function.
|
||||||
|
// This parameter can be NULL.
|
||||||
|
// ppTarget [out] A pointer to the target function, which will be used
|
||||||
|
// with other functions.
|
||||||
|
// This parameter can be NULL.
|
||||||
|
MH_STATUS WINAPI MH_CreateHookApiEx(
|
||||||
|
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget);
|
||||||
|
|
||||||
|
// Removes an already created hook.
|
||||||
|
// Parameters:
|
||||||
|
// pTarget [in] A pointer to the target function.
|
||||||
|
MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget);
|
||||||
|
|
||||||
|
// Enables an already created hook.
|
||||||
|
// Parameters:
|
||||||
|
// pTarget [in] A pointer to the target function.
|
||||||
|
// If this parameter is MH_ALL_HOOKS, all created hooks are
|
||||||
|
// enabled in one go.
|
||||||
|
MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget);
|
||||||
|
|
||||||
|
// Disables an already created hook.
|
||||||
|
// Parameters:
|
||||||
|
// pTarget [in] A pointer to the target function.
|
||||||
|
// If this parameter is MH_ALL_HOOKS, all created hooks are
|
||||||
|
// disabled in one go.
|
||||||
|
MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget);
|
||||||
|
|
||||||
|
// Queues to enable an already created hook.
|
||||||
|
// Parameters:
|
||||||
|
// pTarget [in] A pointer to the target function.
|
||||||
|
// If this parameter is MH_ALL_HOOKS, all created hooks are
|
||||||
|
// queued to be enabled.
|
||||||
|
MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget);
|
||||||
|
|
||||||
|
// Queues to disable an already created hook.
|
||||||
|
// Parameters:
|
||||||
|
// pTarget [in] A pointer to the target function.
|
||||||
|
// If this parameter is MH_ALL_HOOKS, all created hooks are
|
||||||
|
// queued to be disabled.
|
||||||
|
MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget);
|
||||||
|
|
||||||
|
// Applies all queued changes in one go.
|
||||||
|
MH_STATUS WINAPI MH_ApplyQueued(VOID);
|
||||||
|
|
||||||
|
// Translates the MH_STATUS to its name as a string.
|
||||||
|
const char * WINAPI MH_StatusToString(MH_STATUS status);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
326
csgo2/MinHook/src/HDE/hde32.c
Normal file
326
csgo2/MinHook/src/HDE/hde32.c
Normal file
@@ -0,0 +1,326 @@
|
|||||||
|
/*
|
||||||
|
* Hacker Disassembler Engine 32 C
|
||||||
|
* Copyright (c) 2008-2009, Vyacheslav Patkov.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(_M_IX86) || defined(__i386__)
|
||||||
|
|
||||||
|
#include "hde32.h"
|
||||||
|
#include "table32.h"
|
||||||
|
|
||||||
|
unsigned int hde32_disasm(const void *code, hde32s *hs)
|
||||||
|
{
|
||||||
|
uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0;
|
||||||
|
uint8_t *ht = hde32_table, m_mod, m_reg, m_rm, disp_size = 0;
|
||||||
|
|
||||||
|
// Avoid using memset to reduce the footprint.
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
memset((LPBYTE)hs, 0, sizeof(hde32s));
|
||||||
|
#else
|
||||||
|
__stosb((LPBYTE)hs, 0, sizeof(hde32s));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (x = 16; x; x--)
|
||||||
|
switch (c = *p++) {
|
||||||
|
case 0xf3:
|
||||||
|
hs->p_rep = c;
|
||||||
|
pref |= PRE_F3;
|
||||||
|
break;
|
||||||
|
case 0xf2:
|
||||||
|
hs->p_rep = c;
|
||||||
|
pref |= PRE_F2;
|
||||||
|
break;
|
||||||
|
case 0xf0:
|
||||||
|
hs->p_lock = c;
|
||||||
|
pref |= PRE_LOCK;
|
||||||
|
break;
|
||||||
|
case 0x26: case 0x2e: case 0x36:
|
||||||
|
case 0x3e: case 0x64: case 0x65:
|
||||||
|
hs->p_seg = c;
|
||||||
|
pref |= PRE_SEG;
|
||||||
|
break;
|
||||||
|
case 0x66:
|
||||||
|
hs->p_66 = c;
|
||||||
|
pref |= PRE_66;
|
||||||
|
break;
|
||||||
|
case 0x67:
|
||||||
|
hs->p_67 = c;
|
||||||
|
pref |= PRE_67;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto pref_done;
|
||||||
|
}
|
||||||
|
pref_done:
|
||||||
|
|
||||||
|
hs->flags = (uint32_t)pref << 23;
|
||||||
|
|
||||||
|
if (!pref)
|
||||||
|
pref |= PRE_NONE;
|
||||||
|
|
||||||
|
if ((hs->opcode = c) == 0x0f) {
|
||||||
|
hs->opcode2 = c = *p++;
|
||||||
|
ht += DELTA_OPCODES;
|
||||||
|
} else if (c >= 0xa0 && c <= 0xa3) {
|
||||||
|
if (pref & PRE_67)
|
||||||
|
pref |= PRE_66;
|
||||||
|
else
|
||||||
|
pref &= ~PRE_66;
|
||||||
|
}
|
||||||
|
|
||||||
|
opcode = c;
|
||||||
|
cflags = ht[ht[opcode / 4] + (opcode % 4)];
|
||||||
|
|
||||||
|
if (cflags == C_ERROR) {
|
||||||
|
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||||
|
cflags = 0;
|
||||||
|
if ((opcode & -3) == 0x24)
|
||||||
|
cflags++;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = 0;
|
||||||
|
if (cflags & C_GROUP) {
|
||||||
|
uint16_t t;
|
||||||
|
t = *(uint16_t *)(ht + (cflags & 0x7f));
|
||||||
|
cflags = (uint8_t)t;
|
||||||
|
x = (uint8_t)(t >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hs->opcode2) {
|
||||||
|
ht = hde32_table + DELTA_PREFIXES;
|
||||||
|
if (ht[ht[opcode / 4] + (opcode % 4)] & pref)
|
||||||
|
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cflags & C_MODRM) {
|
||||||
|
hs->flags |= F_MODRM;
|
||||||
|
hs->modrm = c = *p++;
|
||||||
|
hs->modrm_mod = m_mod = c >> 6;
|
||||||
|
hs->modrm_rm = m_rm = c & 7;
|
||||||
|
hs->modrm_reg = m_reg = (c & 0x3f) >> 3;
|
||||||
|
|
||||||
|
if (x && ((x << m_reg) & 0x80))
|
||||||
|
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||||
|
|
||||||
|
if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) {
|
||||||
|
uint8_t t = opcode - 0xd9;
|
||||||
|
if (m_mod == 3) {
|
||||||
|
ht = hde32_table + DELTA_FPU_MODRM + t*8;
|
||||||
|
t = ht[m_reg] << m_rm;
|
||||||
|
} else {
|
||||||
|
ht = hde32_table + DELTA_FPU_REG;
|
||||||
|
t = ht[t] << m_reg;
|
||||||
|
}
|
||||||
|
if (t & 0x80)
|
||||||
|
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pref & PRE_LOCK) {
|
||||||
|
if (m_mod == 3) {
|
||||||
|
hs->flags |= F_ERROR | F_ERROR_LOCK;
|
||||||
|
} else {
|
||||||
|
uint8_t *table_end, op = opcode;
|
||||||
|
if (hs->opcode2) {
|
||||||
|
ht = hde32_table + DELTA_OP2_LOCK_OK;
|
||||||
|
table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK;
|
||||||
|
} else {
|
||||||
|
ht = hde32_table + DELTA_OP_LOCK_OK;
|
||||||
|
table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK;
|
||||||
|
op &= -2;
|
||||||
|
}
|
||||||
|
for (; ht != table_end; ht++)
|
||||||
|
if (*ht++ == op) {
|
||||||
|
if (!((*ht << m_reg) & 0x80))
|
||||||
|
goto no_lock_error;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hs->flags |= F_ERROR | F_ERROR_LOCK;
|
||||||
|
no_lock_error:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hs->opcode2) {
|
||||||
|
switch (opcode) {
|
||||||
|
case 0x20: case 0x22:
|
||||||
|
m_mod = 3;
|
||||||
|
if (m_reg > 4 || m_reg == 1)
|
||||||
|
goto error_operand;
|
||||||
|
else
|
||||||
|
goto no_error_operand;
|
||||||
|
case 0x21: case 0x23:
|
||||||
|
m_mod = 3;
|
||||||
|
if (m_reg == 4 || m_reg == 5)
|
||||||
|
goto error_operand;
|
||||||
|
else
|
||||||
|
goto no_error_operand;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (opcode) {
|
||||||
|
case 0x8c:
|
||||||
|
if (m_reg > 5)
|
||||||
|
goto error_operand;
|
||||||
|
else
|
||||||
|
goto no_error_operand;
|
||||||
|
case 0x8e:
|
||||||
|
if (m_reg == 1 || m_reg > 5)
|
||||||
|
goto error_operand;
|
||||||
|
else
|
||||||
|
goto no_error_operand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_mod == 3) {
|
||||||
|
uint8_t *table_end;
|
||||||
|
if (hs->opcode2) {
|
||||||
|
ht = hde32_table + DELTA_OP2_ONLY_MEM;
|
||||||
|
table_end = ht + sizeof(hde32_table) - DELTA_OP2_ONLY_MEM;
|
||||||
|
} else {
|
||||||
|
ht = hde32_table + DELTA_OP_ONLY_MEM;
|
||||||
|
table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM;
|
||||||
|
}
|
||||||
|
for (; ht != table_end; ht += 2)
|
||||||
|
if (*ht++ == opcode) {
|
||||||
|
if (*ht++ & pref && !((*ht << m_reg) & 0x80))
|
||||||
|
goto error_operand;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
goto no_error_operand;
|
||||||
|
} else if (hs->opcode2) {
|
||||||
|
switch (opcode) {
|
||||||
|
case 0x50: case 0xd7: case 0xf7:
|
||||||
|
if (pref & (PRE_NONE | PRE_66))
|
||||||
|
goto error_operand;
|
||||||
|
break;
|
||||||
|
case 0xd6:
|
||||||
|
if (pref & (PRE_F2 | PRE_F3))
|
||||||
|
goto error_operand;
|
||||||
|
break;
|
||||||
|
case 0xc5:
|
||||||
|
goto error_operand;
|
||||||
|
}
|
||||||
|
goto no_error_operand;
|
||||||
|
} else
|
||||||
|
goto no_error_operand;
|
||||||
|
|
||||||
|
error_operand:
|
||||||
|
hs->flags |= F_ERROR | F_ERROR_OPERAND;
|
||||||
|
no_error_operand:
|
||||||
|
|
||||||
|
c = *p++;
|
||||||
|
if (m_reg <= 1) {
|
||||||
|
if (opcode == 0xf6)
|
||||||
|
cflags |= C_IMM8;
|
||||||
|
else if (opcode == 0xf7)
|
||||||
|
cflags |= C_IMM_P66;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (m_mod) {
|
||||||
|
case 0:
|
||||||
|
if (pref & PRE_67) {
|
||||||
|
if (m_rm == 6)
|
||||||
|
disp_size = 2;
|
||||||
|
} else
|
||||||
|
if (m_rm == 5)
|
||||||
|
disp_size = 4;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
disp_size = 1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
disp_size = 2;
|
||||||
|
if (!(pref & PRE_67))
|
||||||
|
disp_size <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_mod != 3 && m_rm == 4 && !(pref & PRE_67)) {
|
||||||
|
hs->flags |= F_SIB;
|
||||||
|
p++;
|
||||||
|
hs->sib = c;
|
||||||
|
hs->sib_scale = c >> 6;
|
||||||
|
hs->sib_index = (c & 0x3f) >> 3;
|
||||||
|
if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1))
|
||||||
|
disp_size = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
p--;
|
||||||
|
switch (disp_size) {
|
||||||
|
case 1:
|
||||||
|
hs->flags |= F_DISP8;
|
||||||
|
hs->disp.disp8 = *p;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
hs->flags |= F_DISP16;
|
||||||
|
hs->disp.disp16 = *(uint16_t *)p;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
hs->flags |= F_DISP32;
|
||||||
|
hs->disp.disp32 = *(uint32_t *)p;
|
||||||
|
}
|
||||||
|
p += disp_size;
|
||||||
|
} else if (pref & PRE_LOCK)
|
||||||
|
hs->flags |= F_ERROR | F_ERROR_LOCK;
|
||||||
|
|
||||||
|
if (cflags & C_IMM_P66) {
|
||||||
|
if (cflags & C_REL32) {
|
||||||
|
if (pref & PRE_66) {
|
||||||
|
hs->flags |= F_IMM16 | F_RELATIVE;
|
||||||
|
hs->imm.imm16 = *(uint16_t *)p;
|
||||||
|
p += 2;
|
||||||
|
goto disasm_done;
|
||||||
|
}
|
||||||
|
goto rel32_ok;
|
||||||
|
}
|
||||||
|
if (pref & PRE_66) {
|
||||||
|
hs->flags |= F_IMM16;
|
||||||
|
hs->imm.imm16 = *(uint16_t *)p;
|
||||||
|
p += 2;
|
||||||
|
} else {
|
||||||
|
hs->flags |= F_IMM32;
|
||||||
|
hs->imm.imm32 = *(uint32_t *)p;
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cflags & C_IMM16) {
|
||||||
|
if (hs->flags & F_IMM32) {
|
||||||
|
hs->flags |= F_IMM16;
|
||||||
|
hs->disp.disp16 = *(uint16_t *)p;
|
||||||
|
} else if (hs->flags & F_IMM16) {
|
||||||
|
hs->flags |= F_2IMM16;
|
||||||
|
hs->disp.disp16 = *(uint16_t *)p;
|
||||||
|
} else {
|
||||||
|
hs->flags |= F_IMM16;
|
||||||
|
hs->imm.imm16 = *(uint16_t *)p;
|
||||||
|
}
|
||||||
|
p += 2;
|
||||||
|
}
|
||||||
|
if (cflags & C_IMM8) {
|
||||||
|
hs->flags |= F_IMM8;
|
||||||
|
hs->imm.imm8 = *p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cflags & C_REL32) {
|
||||||
|
rel32_ok:
|
||||||
|
hs->flags |= F_IMM32 | F_RELATIVE;
|
||||||
|
hs->imm.imm32 = *(uint32_t *)p;
|
||||||
|
p += 4;
|
||||||
|
} else if (cflags & C_REL8) {
|
||||||
|
hs->flags |= F_IMM8 | F_RELATIVE;
|
||||||
|
hs->imm.imm8 = *p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
disasm_done:
|
||||||
|
|
||||||
|
if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) {
|
||||||
|
hs->flags |= F_ERROR | F_ERROR_LENGTH;
|
||||||
|
hs->len = 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (unsigned int)hs->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // defined(_M_IX86) || defined(__i386__)
|
||||||
105
csgo2/MinHook/src/HDE/hde32.h
Normal file
105
csgo2/MinHook/src/HDE/hde32.h
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Hacker Disassembler Engine 32
|
||||||
|
* Copyright (c) 2006-2009, Vyacheslav Patkov.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* hde32.h: C/C++ header file
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _HDE32_H_
|
||||||
|
#define _HDE32_H_
|
||||||
|
|
||||||
|
/* stdint.h - C99 standard header
|
||||||
|
* http://en.wikipedia.org/wiki/stdint.h
|
||||||
|
*
|
||||||
|
* if your compiler doesn't contain "stdint.h" header (for
|
||||||
|
* example, Microsoft Visual C++), you can download file:
|
||||||
|
* http://www.azillionmonkeys.com/qed/pstdint.h
|
||||||
|
* and change next line to:
|
||||||
|
* #include "pstdint.h"
|
||||||
|
*/
|
||||||
|
#include "pstdint.h"
|
||||||
|
|
||||||
|
#define F_MODRM 0x00000001
|
||||||
|
#define F_SIB 0x00000002
|
||||||
|
#define F_IMM8 0x00000004
|
||||||
|
#define F_IMM16 0x00000008
|
||||||
|
#define F_IMM32 0x00000010
|
||||||
|
#define F_DISP8 0x00000020
|
||||||
|
#define F_DISP16 0x00000040
|
||||||
|
#define F_DISP32 0x00000080
|
||||||
|
#define F_RELATIVE 0x00000100
|
||||||
|
#define F_2IMM16 0x00000800
|
||||||
|
#define F_ERROR 0x00001000
|
||||||
|
#define F_ERROR_OPCODE 0x00002000
|
||||||
|
#define F_ERROR_LENGTH 0x00004000
|
||||||
|
#define F_ERROR_LOCK 0x00008000
|
||||||
|
#define F_ERROR_OPERAND 0x00010000
|
||||||
|
#define F_PREFIX_REPNZ 0x01000000
|
||||||
|
#define F_PREFIX_REPX 0x02000000
|
||||||
|
#define F_PREFIX_REP 0x03000000
|
||||||
|
#define F_PREFIX_66 0x04000000
|
||||||
|
#define F_PREFIX_67 0x08000000
|
||||||
|
#define F_PREFIX_LOCK 0x10000000
|
||||||
|
#define F_PREFIX_SEG 0x20000000
|
||||||
|
#define F_PREFIX_ANY 0x3f000000
|
||||||
|
|
||||||
|
#define PREFIX_SEGMENT_CS 0x2e
|
||||||
|
#define PREFIX_SEGMENT_SS 0x36
|
||||||
|
#define PREFIX_SEGMENT_DS 0x3e
|
||||||
|
#define PREFIX_SEGMENT_ES 0x26
|
||||||
|
#define PREFIX_SEGMENT_FS 0x64
|
||||||
|
#define PREFIX_SEGMENT_GS 0x65
|
||||||
|
#define PREFIX_LOCK 0xf0
|
||||||
|
#define PREFIX_REPNZ 0xf2
|
||||||
|
#define PREFIX_REPX 0xf3
|
||||||
|
#define PREFIX_OPERAND_SIZE 0x66
|
||||||
|
#define PREFIX_ADDRESS_SIZE 0x67
|
||||||
|
|
||||||
|
#pragma pack(push,1)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t len;
|
||||||
|
uint8_t p_rep;
|
||||||
|
uint8_t p_lock;
|
||||||
|
uint8_t p_seg;
|
||||||
|
uint8_t p_66;
|
||||||
|
uint8_t p_67;
|
||||||
|
uint8_t opcode;
|
||||||
|
uint8_t opcode2;
|
||||||
|
uint8_t modrm;
|
||||||
|
uint8_t modrm_mod;
|
||||||
|
uint8_t modrm_reg;
|
||||||
|
uint8_t modrm_rm;
|
||||||
|
uint8_t sib;
|
||||||
|
uint8_t sib_scale;
|
||||||
|
uint8_t sib_index;
|
||||||
|
uint8_t sib_base;
|
||||||
|
union {
|
||||||
|
uint8_t imm8;
|
||||||
|
uint16_t imm16;
|
||||||
|
uint32_t imm32;
|
||||||
|
} imm;
|
||||||
|
union {
|
||||||
|
uint8_t disp8;
|
||||||
|
uint16_t disp16;
|
||||||
|
uint32_t disp32;
|
||||||
|
} disp;
|
||||||
|
uint32_t flags;
|
||||||
|
} hde32s;
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* __cdecl */
|
||||||
|
unsigned int hde32_disasm(const void *code, hde32s *hs);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _HDE32_H_ */
|
||||||
337
csgo2/MinHook/src/HDE/hde64.c
Normal file
337
csgo2/MinHook/src/HDE/hde64.c
Normal file
@@ -0,0 +1,337 @@
|
|||||||
|
/*
|
||||||
|
* Hacker Disassembler Engine 64 C
|
||||||
|
* Copyright (c) 2008-2009, Vyacheslav Patkov.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
|
||||||
|
#include "hde64.h"
|
||||||
|
#include "table64.h"
|
||||||
|
|
||||||
|
unsigned int hde64_disasm(const void *code, hde64s *hs)
|
||||||
|
{
|
||||||
|
uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0;
|
||||||
|
uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0;
|
||||||
|
uint8_t op64 = 0;
|
||||||
|
|
||||||
|
// Avoid using memset to reduce the footprint.
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
memset((LPBYTE)hs, 0, sizeof(hde64s));
|
||||||
|
#else
|
||||||
|
__stosb((LPBYTE)hs, 0, sizeof(hde64s));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (x = 16; x; x--)
|
||||||
|
switch (c = *p++) {
|
||||||
|
case 0xf3:
|
||||||
|
hs->p_rep = c;
|
||||||
|
pref |= PRE_F3;
|
||||||
|
break;
|
||||||
|
case 0xf2:
|
||||||
|
hs->p_rep = c;
|
||||||
|
pref |= PRE_F2;
|
||||||
|
break;
|
||||||
|
case 0xf0:
|
||||||
|
hs->p_lock = c;
|
||||||
|
pref |= PRE_LOCK;
|
||||||
|
break;
|
||||||
|
case 0x26: case 0x2e: case 0x36:
|
||||||
|
case 0x3e: case 0x64: case 0x65:
|
||||||
|
hs->p_seg = c;
|
||||||
|
pref |= PRE_SEG;
|
||||||
|
break;
|
||||||
|
case 0x66:
|
||||||
|
hs->p_66 = c;
|
||||||
|
pref |= PRE_66;
|
||||||
|
break;
|
||||||
|
case 0x67:
|
||||||
|
hs->p_67 = c;
|
||||||
|
pref |= PRE_67;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto pref_done;
|
||||||
|
}
|
||||||
|
pref_done:
|
||||||
|
|
||||||
|
hs->flags = (uint32_t)pref << 23;
|
||||||
|
|
||||||
|
if (!pref)
|
||||||
|
pref |= PRE_NONE;
|
||||||
|
|
||||||
|
if ((c & 0xf0) == 0x40) {
|
||||||
|
hs->flags |= F_PREFIX_REX;
|
||||||
|
if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8)
|
||||||
|
op64++;
|
||||||
|
hs->rex_r = (c & 7) >> 2;
|
||||||
|
hs->rex_x = (c & 3) >> 1;
|
||||||
|
hs->rex_b = c & 1;
|
||||||
|
if (((c = *p++) & 0xf0) == 0x40) {
|
||||||
|
opcode = c;
|
||||||
|
goto error_opcode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((hs->opcode = c) == 0x0f) {
|
||||||
|
hs->opcode2 = c = *p++;
|
||||||
|
ht += DELTA_OPCODES;
|
||||||
|
} else if (c >= 0xa0 && c <= 0xa3) {
|
||||||
|
op64++;
|
||||||
|
if (pref & PRE_67)
|
||||||
|
pref |= PRE_66;
|
||||||
|
else
|
||||||
|
pref &= ~PRE_66;
|
||||||
|
}
|
||||||
|
|
||||||
|
opcode = c;
|
||||||
|
cflags = ht[ht[opcode / 4] + (opcode % 4)];
|
||||||
|
|
||||||
|
if (cflags == C_ERROR) {
|
||||||
|
error_opcode:
|
||||||
|
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||||
|
cflags = 0;
|
||||||
|
if ((opcode & -3) == 0x24)
|
||||||
|
cflags++;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = 0;
|
||||||
|
if (cflags & C_GROUP) {
|
||||||
|
uint16_t t;
|
||||||
|
t = *(uint16_t *)(ht + (cflags & 0x7f));
|
||||||
|
cflags = (uint8_t)t;
|
||||||
|
x = (uint8_t)(t >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hs->opcode2) {
|
||||||
|
ht = hde64_table + DELTA_PREFIXES;
|
||||||
|
if (ht[ht[opcode / 4] + (opcode % 4)] & pref)
|
||||||
|
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cflags & C_MODRM) {
|
||||||
|
hs->flags |= F_MODRM;
|
||||||
|
hs->modrm = c = *p++;
|
||||||
|
hs->modrm_mod = m_mod = c >> 6;
|
||||||
|
hs->modrm_rm = m_rm = c & 7;
|
||||||
|
hs->modrm_reg = m_reg = (c & 0x3f) >> 3;
|
||||||
|
|
||||||
|
if (x && ((x << m_reg) & 0x80))
|
||||||
|
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||||
|
|
||||||
|
if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) {
|
||||||
|
uint8_t t = opcode - 0xd9;
|
||||||
|
if (m_mod == 3) {
|
||||||
|
ht = hde64_table + DELTA_FPU_MODRM + t*8;
|
||||||
|
t = ht[m_reg] << m_rm;
|
||||||
|
} else {
|
||||||
|
ht = hde64_table + DELTA_FPU_REG;
|
||||||
|
t = ht[t] << m_reg;
|
||||||
|
}
|
||||||
|
if (t & 0x80)
|
||||||
|
hs->flags |= F_ERROR | F_ERROR_OPCODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pref & PRE_LOCK) {
|
||||||
|
if (m_mod == 3) {
|
||||||
|
hs->flags |= F_ERROR | F_ERROR_LOCK;
|
||||||
|
} else {
|
||||||
|
uint8_t *table_end, op = opcode;
|
||||||
|
if (hs->opcode2) {
|
||||||
|
ht = hde64_table + DELTA_OP2_LOCK_OK;
|
||||||
|
table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK;
|
||||||
|
} else {
|
||||||
|
ht = hde64_table + DELTA_OP_LOCK_OK;
|
||||||
|
table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK;
|
||||||
|
op &= -2;
|
||||||
|
}
|
||||||
|
for (; ht != table_end; ht++)
|
||||||
|
if (*ht++ == op) {
|
||||||
|
if (!((*ht << m_reg) & 0x80))
|
||||||
|
goto no_lock_error;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hs->flags |= F_ERROR | F_ERROR_LOCK;
|
||||||
|
no_lock_error:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hs->opcode2) {
|
||||||
|
switch (opcode) {
|
||||||
|
case 0x20: case 0x22:
|
||||||
|
m_mod = 3;
|
||||||
|
if (m_reg > 4 || m_reg == 1)
|
||||||
|
goto error_operand;
|
||||||
|
else
|
||||||
|
goto no_error_operand;
|
||||||
|
case 0x21: case 0x23:
|
||||||
|
m_mod = 3;
|
||||||
|
if (m_reg == 4 || m_reg == 5)
|
||||||
|
goto error_operand;
|
||||||
|
else
|
||||||
|
goto no_error_operand;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (opcode) {
|
||||||
|
case 0x8c:
|
||||||
|
if (m_reg > 5)
|
||||||
|
goto error_operand;
|
||||||
|
else
|
||||||
|
goto no_error_operand;
|
||||||
|
case 0x8e:
|
||||||
|
if (m_reg == 1 || m_reg > 5)
|
||||||
|
goto error_operand;
|
||||||
|
else
|
||||||
|
goto no_error_operand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_mod == 3) {
|
||||||
|
uint8_t *table_end;
|
||||||
|
if (hs->opcode2) {
|
||||||
|
ht = hde64_table + DELTA_OP2_ONLY_MEM;
|
||||||
|
table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM;
|
||||||
|
} else {
|
||||||
|
ht = hde64_table + DELTA_OP_ONLY_MEM;
|
||||||
|
table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM;
|
||||||
|
}
|
||||||
|
for (; ht != table_end; ht += 2)
|
||||||
|
if (*ht++ == opcode) {
|
||||||
|
if (*ht++ & pref && !((*ht << m_reg) & 0x80))
|
||||||
|
goto error_operand;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
goto no_error_operand;
|
||||||
|
} else if (hs->opcode2) {
|
||||||
|
switch (opcode) {
|
||||||
|
case 0x50: case 0xd7: case 0xf7:
|
||||||
|
if (pref & (PRE_NONE | PRE_66))
|
||||||
|
goto error_operand;
|
||||||
|
break;
|
||||||
|
case 0xd6:
|
||||||
|
if (pref & (PRE_F2 | PRE_F3))
|
||||||
|
goto error_operand;
|
||||||
|
break;
|
||||||
|
case 0xc5:
|
||||||
|
goto error_operand;
|
||||||
|
}
|
||||||
|
goto no_error_operand;
|
||||||
|
} else
|
||||||
|
goto no_error_operand;
|
||||||
|
|
||||||
|
error_operand:
|
||||||
|
hs->flags |= F_ERROR | F_ERROR_OPERAND;
|
||||||
|
no_error_operand:
|
||||||
|
|
||||||
|
c = *p++;
|
||||||
|
if (m_reg <= 1) {
|
||||||
|
if (opcode == 0xf6)
|
||||||
|
cflags |= C_IMM8;
|
||||||
|
else if (opcode == 0xf7)
|
||||||
|
cflags |= C_IMM_P66;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (m_mod) {
|
||||||
|
case 0:
|
||||||
|
if (pref & PRE_67) {
|
||||||
|
if (m_rm == 6)
|
||||||
|
disp_size = 2;
|
||||||
|
} else
|
||||||
|
if (m_rm == 5)
|
||||||
|
disp_size = 4;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
disp_size = 1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
disp_size = 2;
|
||||||
|
if (!(pref & PRE_67))
|
||||||
|
disp_size <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_mod != 3 && m_rm == 4) {
|
||||||
|
hs->flags |= F_SIB;
|
||||||
|
p++;
|
||||||
|
hs->sib = c;
|
||||||
|
hs->sib_scale = c >> 6;
|
||||||
|
hs->sib_index = (c & 0x3f) >> 3;
|
||||||
|
if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1))
|
||||||
|
disp_size = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
p--;
|
||||||
|
switch (disp_size) {
|
||||||
|
case 1:
|
||||||
|
hs->flags |= F_DISP8;
|
||||||
|
hs->disp.disp8 = *p;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
hs->flags |= F_DISP16;
|
||||||
|
hs->disp.disp16 = *(uint16_t *)p;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
hs->flags |= F_DISP32;
|
||||||
|
hs->disp.disp32 = *(uint32_t *)p;
|
||||||
|
}
|
||||||
|
p += disp_size;
|
||||||
|
} else if (pref & PRE_LOCK)
|
||||||
|
hs->flags |= F_ERROR | F_ERROR_LOCK;
|
||||||
|
|
||||||
|
if (cflags & C_IMM_P66) {
|
||||||
|
if (cflags & C_REL32) {
|
||||||
|
if (pref & PRE_66) {
|
||||||
|
hs->flags |= F_IMM16 | F_RELATIVE;
|
||||||
|
hs->imm.imm16 = *(uint16_t *)p;
|
||||||
|
p += 2;
|
||||||
|
goto disasm_done;
|
||||||
|
}
|
||||||
|
goto rel32_ok;
|
||||||
|
}
|
||||||
|
if (op64) {
|
||||||
|
hs->flags |= F_IMM64;
|
||||||
|
hs->imm.imm64 = *(uint64_t *)p;
|
||||||
|
p += 8;
|
||||||
|
} else if (!(pref & PRE_66)) {
|
||||||
|
hs->flags |= F_IMM32;
|
||||||
|
hs->imm.imm32 = *(uint32_t *)p;
|
||||||
|
p += 4;
|
||||||
|
} else
|
||||||
|
goto imm16_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (cflags & C_IMM16) {
|
||||||
|
imm16_ok:
|
||||||
|
hs->flags |= F_IMM16;
|
||||||
|
hs->imm.imm16 = *(uint16_t *)p;
|
||||||
|
p += 2;
|
||||||
|
}
|
||||||
|
if (cflags & C_IMM8) {
|
||||||
|
hs->flags |= F_IMM8;
|
||||||
|
hs->imm.imm8 = *p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cflags & C_REL32) {
|
||||||
|
rel32_ok:
|
||||||
|
hs->flags |= F_IMM32 | F_RELATIVE;
|
||||||
|
hs->imm.imm32 = *(uint32_t *)p;
|
||||||
|
p += 4;
|
||||||
|
} else if (cflags & C_REL8) {
|
||||||
|
hs->flags |= F_IMM8 | F_RELATIVE;
|
||||||
|
hs->imm.imm8 = *p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
disasm_done:
|
||||||
|
|
||||||
|
if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) {
|
||||||
|
hs->flags |= F_ERROR | F_ERROR_LENGTH;
|
||||||
|
hs->len = 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (unsigned int)hs->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // defined(_M_X64) || defined(__x86_64__)
|
||||||
112
csgo2/MinHook/src/HDE/hde64.h
Normal file
112
csgo2/MinHook/src/HDE/hde64.h
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* Hacker Disassembler Engine 64
|
||||||
|
* Copyright (c) 2008-2009, Vyacheslav Patkov.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* hde64.h: C/C++ header file
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _HDE64_H_
|
||||||
|
#define _HDE64_H_
|
||||||
|
|
||||||
|
/* stdint.h - C99 standard header
|
||||||
|
* http://en.wikipedia.org/wiki/stdint.h
|
||||||
|
*
|
||||||
|
* if your compiler doesn't contain "stdint.h" header (for
|
||||||
|
* example, Microsoft Visual C++), you can download file:
|
||||||
|
* http://www.azillionmonkeys.com/qed/pstdint.h
|
||||||
|
* and change next line to:
|
||||||
|
* #include "pstdint.h"
|
||||||
|
*/
|
||||||
|
#include "pstdint.h"
|
||||||
|
|
||||||
|
#define F_MODRM 0x00000001
|
||||||
|
#define F_SIB 0x00000002
|
||||||
|
#define F_IMM8 0x00000004
|
||||||
|
#define F_IMM16 0x00000008
|
||||||
|
#define F_IMM32 0x00000010
|
||||||
|
#define F_IMM64 0x00000020
|
||||||
|
#define F_DISP8 0x00000040
|
||||||
|
#define F_DISP16 0x00000080
|
||||||
|
#define F_DISP32 0x00000100
|
||||||
|
#define F_RELATIVE 0x00000200
|
||||||
|
#define F_ERROR 0x00001000
|
||||||
|
#define F_ERROR_OPCODE 0x00002000
|
||||||
|
#define F_ERROR_LENGTH 0x00004000
|
||||||
|
#define F_ERROR_LOCK 0x00008000
|
||||||
|
#define F_ERROR_OPERAND 0x00010000
|
||||||
|
#define F_PREFIX_REPNZ 0x01000000
|
||||||
|
#define F_PREFIX_REPX 0x02000000
|
||||||
|
#define F_PREFIX_REP 0x03000000
|
||||||
|
#define F_PREFIX_66 0x04000000
|
||||||
|
#define F_PREFIX_67 0x08000000
|
||||||
|
#define F_PREFIX_LOCK 0x10000000
|
||||||
|
#define F_PREFIX_SEG 0x20000000
|
||||||
|
#define F_PREFIX_REX 0x40000000
|
||||||
|
#define F_PREFIX_ANY 0x7f000000
|
||||||
|
|
||||||
|
#define PREFIX_SEGMENT_CS 0x2e
|
||||||
|
#define PREFIX_SEGMENT_SS 0x36
|
||||||
|
#define PREFIX_SEGMENT_DS 0x3e
|
||||||
|
#define PREFIX_SEGMENT_ES 0x26
|
||||||
|
#define PREFIX_SEGMENT_FS 0x64
|
||||||
|
#define PREFIX_SEGMENT_GS 0x65
|
||||||
|
#define PREFIX_LOCK 0xf0
|
||||||
|
#define PREFIX_REPNZ 0xf2
|
||||||
|
#define PREFIX_REPX 0xf3
|
||||||
|
#define PREFIX_OPERAND_SIZE 0x66
|
||||||
|
#define PREFIX_ADDRESS_SIZE 0x67
|
||||||
|
|
||||||
|
#pragma pack(push,1)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t len;
|
||||||
|
uint8_t p_rep;
|
||||||
|
uint8_t p_lock;
|
||||||
|
uint8_t p_seg;
|
||||||
|
uint8_t p_66;
|
||||||
|
uint8_t p_67;
|
||||||
|
uint8_t rex;
|
||||||
|
uint8_t rex_w;
|
||||||
|
uint8_t rex_r;
|
||||||
|
uint8_t rex_x;
|
||||||
|
uint8_t rex_b;
|
||||||
|
uint8_t opcode;
|
||||||
|
uint8_t opcode2;
|
||||||
|
uint8_t modrm;
|
||||||
|
uint8_t modrm_mod;
|
||||||
|
uint8_t modrm_reg;
|
||||||
|
uint8_t modrm_rm;
|
||||||
|
uint8_t sib;
|
||||||
|
uint8_t sib_scale;
|
||||||
|
uint8_t sib_index;
|
||||||
|
uint8_t sib_base;
|
||||||
|
union {
|
||||||
|
uint8_t imm8;
|
||||||
|
uint16_t imm16;
|
||||||
|
uint32_t imm32;
|
||||||
|
uint64_t imm64;
|
||||||
|
} imm;
|
||||||
|
union {
|
||||||
|
uint8_t disp8;
|
||||||
|
uint16_t disp16;
|
||||||
|
uint32_t disp32;
|
||||||
|
} disp;
|
||||||
|
uint32_t flags;
|
||||||
|
} hde64s;
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* __cdecl */
|
||||||
|
unsigned int hde64_disasm(const void *code, hde64s *hs);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _HDE64_H_ */
|
||||||
39
csgo2/MinHook/src/HDE/pstdint.h
Normal file
39
csgo2/MinHook/src/HDE/pstdint.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* MinHook - The Minimalistic API Hooking Library for x64/x86
|
||||||
|
* Copyright (C) 2009-2017 Tsuda Kageyu. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
// Integer types for HDE.
|
||||||
|
typedef INT8 int8_t;
|
||||||
|
typedef INT16 int16_t;
|
||||||
|
typedef INT32 int32_t;
|
||||||
|
typedef INT64 int64_t;
|
||||||
|
typedef UINT8 uint8_t;
|
||||||
|
typedef UINT16 uint16_t;
|
||||||
|
typedef UINT32 uint32_t;
|
||||||
|
typedef UINT64 uint64_t;
|
||||||
73
csgo2/MinHook/src/HDE/table32.h
Normal file
73
csgo2/MinHook/src/HDE/table32.h
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Hacker Disassembler Engine 32 C
|
||||||
|
* Copyright (c) 2008-2009, Vyacheslav Patkov.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define C_NONE 0x00
|
||||||
|
#define C_MODRM 0x01
|
||||||
|
#define C_IMM8 0x02
|
||||||
|
#define C_IMM16 0x04
|
||||||
|
#define C_IMM_P66 0x10
|
||||||
|
#define C_REL8 0x20
|
||||||
|
#define C_REL32 0x40
|
||||||
|
#define C_GROUP 0x80
|
||||||
|
#define C_ERROR 0xff
|
||||||
|
|
||||||
|
#define PRE_ANY 0x00
|
||||||
|
#define PRE_NONE 0x01
|
||||||
|
#define PRE_F2 0x02
|
||||||
|
#define PRE_F3 0x04
|
||||||
|
#define PRE_66 0x08
|
||||||
|
#define PRE_67 0x10
|
||||||
|
#define PRE_LOCK 0x20
|
||||||
|
#define PRE_SEG 0x40
|
||||||
|
#define PRE_ALL 0xff
|
||||||
|
|
||||||
|
#define DELTA_OPCODES 0x4a
|
||||||
|
#define DELTA_FPU_REG 0xf1
|
||||||
|
#define DELTA_FPU_MODRM 0xf8
|
||||||
|
#define DELTA_PREFIXES 0x130
|
||||||
|
#define DELTA_OP_LOCK_OK 0x1a1
|
||||||
|
#define DELTA_OP2_LOCK_OK 0x1b9
|
||||||
|
#define DELTA_OP_ONLY_MEM 0x1cb
|
||||||
|
#define DELTA_OP2_ONLY_MEM 0x1da
|
||||||
|
|
||||||
|
unsigned char hde32_table[] = {
|
||||||
|
0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,
|
||||||
|
0xa8,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xac,0xaa,0xb2,0xaa,0x9f,0x9f,
|
||||||
|
0x9f,0x9f,0xb5,0xa3,0xa3,0xa4,0xaa,0xaa,0xba,0xaa,0x96,0xaa,0xa8,0xaa,0xc3,
|
||||||
|
0xc3,0x96,0x96,0xb7,0xae,0xd6,0xbd,0xa3,0xc5,0xa3,0xa3,0x9f,0xc3,0x9c,0xaa,
|
||||||
|
0xaa,0xac,0xaa,0xbf,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0x90,
|
||||||
|
0x82,0x7d,0x97,0x59,0x59,0x59,0x59,0x59,0x7f,0x59,0x59,0x60,0x7d,0x7f,0x7f,
|
||||||
|
0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x9a,0x88,0x7d,
|
||||||
|
0x59,0x50,0x50,0x50,0x50,0x59,0x59,0x59,0x59,0x61,0x94,0x61,0x9e,0x59,0x59,
|
||||||
|
0x85,0x59,0x92,0xa3,0x60,0x60,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,
|
||||||
|
0x59,0x59,0x9f,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xcc,0x01,0xbc,0x03,0xf0,
|
||||||
|
0x10,0x10,0x10,0x10,0x50,0x50,0x50,0x50,0x14,0x20,0x20,0x20,0x20,0x01,0x01,
|
||||||
|
0x01,0x01,0xc4,0x02,0x10,0x00,0x00,0x00,0x00,0x01,0x01,0xc0,0xc2,0x10,0x11,
|
||||||
|
0x02,0x03,0x11,0x03,0x03,0x04,0x00,0x00,0x14,0x00,0x02,0x00,0x00,0xc6,0xc8,
|
||||||
|
0x02,0x02,0x02,0x02,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xca,
|
||||||
|
0x01,0x01,0x01,0x00,0x06,0x00,0x04,0x00,0xc0,0xc2,0x01,0x01,0x03,0x01,0xff,
|
||||||
|
0xff,0x01,0x00,0x03,0xc4,0xc4,0xc6,0x03,0x01,0x01,0x01,0xff,0x03,0x03,0x03,
|
||||||
|
0xc8,0x40,0x00,0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,
|
||||||
|
0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0xff,0xff,0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x7f,0x00,0x00,0xff,0x4a,0x4a,0x4a,0x4a,0x4b,0x52,0x4a,0x4a,0x4a,0x4a,0x4f,
|
||||||
|
0x4c,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x55,0x45,0x40,0x4a,0x4a,0x4a,
|
||||||
|
0x45,0x59,0x4d,0x46,0x4a,0x5d,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,
|
||||||
|
0x4a,0x4a,0x4a,0x4a,0x4a,0x61,0x63,0x67,0x4e,0x4a,0x4a,0x6b,0x6d,0x4a,0x4a,
|
||||||
|
0x45,0x6d,0x4a,0x4a,0x44,0x45,0x4a,0x4a,0x00,0x00,0x00,0x02,0x0d,0x06,0x06,
|
||||||
|
0x06,0x06,0x0e,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x00,0x06,0x06,0x02,0x06,
|
||||||
|
0x00,0x0a,0x0a,0x07,0x07,0x06,0x02,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04,
|
||||||
|
0x04,0x04,0x00,0x00,0x00,0x0e,0x05,0x06,0x06,0x06,0x01,0x06,0x00,0x00,0x08,
|
||||||
|
0x00,0x10,0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,
|
||||||
|
0x86,0x00,0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,
|
||||||
|
0xf8,0xbb,0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,
|
||||||
|
0xc4,0xff,0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,
|
||||||
|
0x13,0x09,0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,
|
||||||
|
0xb2,0xff,0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,
|
||||||
|
0xe7,0x08,0x00,0xf0,0x02,0x00
|
||||||
|
};
|
||||||
74
csgo2/MinHook/src/HDE/table64.h
Normal file
74
csgo2/MinHook/src/HDE/table64.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Hacker Disassembler Engine 64 C
|
||||||
|
* Copyright (c) 2008-2009, Vyacheslav Patkov.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define C_NONE 0x00
|
||||||
|
#define C_MODRM 0x01
|
||||||
|
#define C_IMM8 0x02
|
||||||
|
#define C_IMM16 0x04
|
||||||
|
#define C_IMM_P66 0x10
|
||||||
|
#define C_REL8 0x20
|
||||||
|
#define C_REL32 0x40
|
||||||
|
#define C_GROUP 0x80
|
||||||
|
#define C_ERROR 0xff
|
||||||
|
|
||||||
|
#define PRE_ANY 0x00
|
||||||
|
#define PRE_NONE 0x01
|
||||||
|
#define PRE_F2 0x02
|
||||||
|
#define PRE_F3 0x04
|
||||||
|
#define PRE_66 0x08
|
||||||
|
#define PRE_67 0x10
|
||||||
|
#define PRE_LOCK 0x20
|
||||||
|
#define PRE_SEG 0x40
|
||||||
|
#define PRE_ALL 0xff
|
||||||
|
|
||||||
|
#define DELTA_OPCODES 0x4a
|
||||||
|
#define DELTA_FPU_REG 0xfd
|
||||||
|
#define DELTA_FPU_MODRM 0x104
|
||||||
|
#define DELTA_PREFIXES 0x13c
|
||||||
|
#define DELTA_OP_LOCK_OK 0x1ae
|
||||||
|
#define DELTA_OP2_LOCK_OK 0x1c6
|
||||||
|
#define DELTA_OP_ONLY_MEM 0x1d8
|
||||||
|
#define DELTA_OP2_ONLY_MEM 0x1e7
|
||||||
|
|
||||||
|
unsigned char hde64_table[] = {
|
||||||
|
0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5,
|
||||||
|
0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1,
|
||||||
|
0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea,
|
||||||
|
0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0,
|
||||||
|
0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab,
|
||||||
|
0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92,
|
||||||
|
0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90,
|
||||||
|
0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b,
|
||||||
|
0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,
|
||||||
|
0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc,
|
||||||
|
0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20,
|
||||||
|
0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff,
|
||||||
|
0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00,
|
||||||
|
0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01,
|
||||||
|
0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10,
|
||||||
|
0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00,
|
||||||
|
0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00,
|
||||||
|
0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,
|
||||||
|
0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00,
|
||||||
|
0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40,
|
||||||
|
0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43,
|
||||||
|
0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
|
||||||
|
0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40,
|
||||||
|
0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06,
|
||||||
|
0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07,
|
||||||
|
0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04,
|
||||||
|
0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10,
|
||||||
|
0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00,
|
||||||
|
0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb,
|
||||||
|
0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff,
|
||||||
|
0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09,
|
||||||
|
0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff,
|
||||||
|
0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08,
|
||||||
|
0x00,0xf0,0x02,0x00
|
||||||
|
};
|
||||||
312
csgo2/MinHook/src/buffer.c
Normal file
312
csgo2/MinHook/src/buffer.c
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
/*
|
||||||
|
* MinHook - The Minimalistic API Hooking Library for x64/x86
|
||||||
|
* Copyright (C) 2009-2017 Tsuda Kageyu.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
|
// Size of each memory block. (= page size of VirtualAlloc)
|
||||||
|
#define MEMORY_BLOCK_SIZE 0x1000
|
||||||
|
|
||||||
|
// Max range for seeking a memory block. (= 1024MB)
|
||||||
|
#define MAX_MEMORY_RANGE 0x40000000
|
||||||
|
|
||||||
|
// Memory protection flags to check the executable address.
|
||||||
|
#define PAGE_EXECUTE_FLAGS \
|
||||||
|
(PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)
|
||||||
|
|
||||||
|
// Memory slot.
|
||||||
|
typedef struct _MEMORY_SLOT
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct _MEMORY_SLOT *pNext;
|
||||||
|
UINT8 buffer[MEMORY_SLOT_SIZE];
|
||||||
|
};
|
||||||
|
} MEMORY_SLOT, *PMEMORY_SLOT;
|
||||||
|
|
||||||
|
// Memory block info. Placed at the head of each block.
|
||||||
|
typedef struct _MEMORY_BLOCK
|
||||||
|
{
|
||||||
|
struct _MEMORY_BLOCK *pNext;
|
||||||
|
PMEMORY_SLOT pFree; // First element of the free slot list.
|
||||||
|
UINT usedCount;
|
||||||
|
} MEMORY_BLOCK, *PMEMORY_BLOCK;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Global Variables:
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// First element of the memory block list.
|
||||||
|
PMEMORY_BLOCK g_pMemoryBlocks;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
VOID InitializeBuffer(VOID)
|
||||||
|
{
|
||||||
|
// Nothing to do for now.
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
VOID UninitializeBuffer(VOID)
|
||||||
|
{
|
||||||
|
PMEMORY_BLOCK pBlock = g_pMemoryBlocks;
|
||||||
|
g_pMemoryBlocks = NULL;
|
||||||
|
|
||||||
|
while (pBlock)
|
||||||
|
{
|
||||||
|
PMEMORY_BLOCK pNext = pBlock->pNext;
|
||||||
|
VirtualFree(pBlock, 0, MEM_RELEASE);
|
||||||
|
pBlock = pNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
static LPVOID FindPrevFreeRegion(LPVOID pAddress, LPVOID pMinAddr, DWORD dwAllocationGranularity)
|
||||||
|
{
|
||||||
|
ULONG_PTR tryAddr = (ULONG_PTR)pAddress;
|
||||||
|
|
||||||
|
// Round down to the allocation granularity.
|
||||||
|
tryAddr -= tryAddr % dwAllocationGranularity;
|
||||||
|
|
||||||
|
// Start from the previous allocation granularity multiply.
|
||||||
|
tryAddr -= dwAllocationGranularity;
|
||||||
|
|
||||||
|
while (tryAddr >= (ULONG_PTR)pMinAddr)
|
||||||
|
{
|
||||||
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
|
if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (mbi.State == MEM_FREE)
|
||||||
|
return (LPVOID)tryAddr;
|
||||||
|
|
||||||
|
if ((ULONG_PTR)mbi.AllocationBase < dwAllocationGranularity)
|
||||||
|
break;
|
||||||
|
|
||||||
|
tryAddr = (ULONG_PTR)mbi.AllocationBase - dwAllocationGranularity;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
static LPVOID FindNextFreeRegion(LPVOID pAddress, LPVOID pMaxAddr, DWORD dwAllocationGranularity)
|
||||||
|
{
|
||||||
|
ULONG_PTR tryAddr = (ULONG_PTR)pAddress;
|
||||||
|
|
||||||
|
// Round down to the allocation granularity.
|
||||||
|
tryAddr -= tryAddr % dwAllocationGranularity;
|
||||||
|
|
||||||
|
// Start from the next allocation granularity multiply.
|
||||||
|
tryAddr += dwAllocationGranularity;
|
||||||
|
|
||||||
|
while (tryAddr <= (ULONG_PTR)pMaxAddr)
|
||||||
|
{
|
||||||
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
|
if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (mbi.State == MEM_FREE)
|
||||||
|
return (LPVOID)tryAddr;
|
||||||
|
|
||||||
|
tryAddr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize;
|
||||||
|
|
||||||
|
// Round up to the next allocation granularity.
|
||||||
|
tryAddr += dwAllocationGranularity - 1;
|
||||||
|
tryAddr -= tryAddr % dwAllocationGranularity;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static PMEMORY_BLOCK GetMemoryBlock(LPVOID pOrigin)
|
||||||
|
{
|
||||||
|
PMEMORY_BLOCK pBlock;
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
ULONG_PTR minAddr;
|
||||||
|
ULONG_PTR maxAddr;
|
||||||
|
|
||||||
|
SYSTEM_INFO si;
|
||||||
|
GetSystemInfo(&si);
|
||||||
|
minAddr = (ULONG_PTR)si.lpMinimumApplicationAddress;
|
||||||
|
maxAddr = (ULONG_PTR)si.lpMaximumApplicationAddress;
|
||||||
|
|
||||||
|
// pOrigin ± 512MB
|
||||||
|
if ((ULONG_PTR)pOrigin > MAX_MEMORY_RANGE && minAddr < (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE)
|
||||||
|
minAddr = (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE;
|
||||||
|
|
||||||
|
if (maxAddr > (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE)
|
||||||
|
maxAddr = (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE;
|
||||||
|
|
||||||
|
// Make room for MEMORY_BLOCK_SIZE bytes.
|
||||||
|
maxAddr -= MEMORY_BLOCK_SIZE - 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Look the registered blocks for a reachable one.
|
||||||
|
for (pBlock = g_pMemoryBlocks; pBlock != NULL; pBlock = pBlock->pNext)
|
||||||
|
{
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
// Ignore the blocks too far.
|
||||||
|
if ((ULONG_PTR)pBlock < minAddr || (ULONG_PTR)pBlock >= maxAddr)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
// The block has at least one unused slot.
|
||||||
|
if (pBlock->pFree != NULL)
|
||||||
|
return pBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
// Alloc a new block above if not found.
|
||||||
|
{
|
||||||
|
LPVOID pAlloc = pOrigin;
|
||||||
|
while ((ULONG_PTR)pAlloc >= minAddr)
|
||||||
|
{
|
||||||
|
pAlloc = FindPrevFreeRegion(pAlloc, (LPVOID)minAddr, si.dwAllocationGranularity);
|
||||||
|
if (pAlloc == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
pBlock = (PMEMORY_BLOCK)VirtualAlloc(
|
||||||
|
pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||||
|
if (pBlock != NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alloc a new block below if not found.
|
||||||
|
if (pBlock == NULL)
|
||||||
|
{
|
||||||
|
LPVOID pAlloc = pOrigin;
|
||||||
|
while ((ULONG_PTR)pAlloc <= maxAddr)
|
||||||
|
{
|
||||||
|
pAlloc = FindNextFreeRegion(pAlloc, (LPVOID)maxAddr, si.dwAllocationGranularity);
|
||||||
|
if (pAlloc == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
pBlock = (PMEMORY_BLOCK)VirtualAlloc(
|
||||||
|
pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||||
|
if (pBlock != NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// In x86 mode, a memory block can be placed anywhere.
|
||||||
|
pBlock = (PMEMORY_BLOCK)VirtualAlloc(
|
||||||
|
NULL, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (pBlock != NULL)
|
||||||
|
{
|
||||||
|
// Build a linked list of all the slots.
|
||||||
|
PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBlock + 1;
|
||||||
|
pBlock->pFree = NULL;
|
||||||
|
pBlock->usedCount = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
pSlot->pNext = pBlock->pFree;
|
||||||
|
pBlock->pFree = pSlot;
|
||||||
|
pSlot++;
|
||||||
|
} while ((ULONG_PTR)pSlot - (ULONG_PTR)pBlock <= MEMORY_BLOCK_SIZE - MEMORY_SLOT_SIZE);
|
||||||
|
|
||||||
|
pBlock->pNext = g_pMemoryBlocks;
|
||||||
|
g_pMemoryBlocks = pBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
LPVOID AllocateBuffer(LPVOID pOrigin)
|
||||||
|
{
|
||||||
|
PMEMORY_SLOT pSlot;
|
||||||
|
PMEMORY_BLOCK pBlock = GetMemoryBlock(pOrigin);
|
||||||
|
if (pBlock == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Remove an unused slot from the list.
|
||||||
|
pSlot = pBlock->pFree;
|
||||||
|
pBlock->pFree = pSlot->pNext;
|
||||||
|
pBlock->usedCount++;
|
||||||
|
#ifdef _DEBUG
|
||||||
|
// Fill the slot with INT3 for debugging.
|
||||||
|
memset(pSlot, 0xCC, sizeof(MEMORY_SLOT));
|
||||||
|
#endif
|
||||||
|
return pSlot;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
VOID FreeBuffer(LPVOID pBuffer)
|
||||||
|
{
|
||||||
|
PMEMORY_BLOCK pBlock = g_pMemoryBlocks;
|
||||||
|
PMEMORY_BLOCK pPrev = NULL;
|
||||||
|
ULONG_PTR pTargetBlock = ((ULONG_PTR)pBuffer / MEMORY_BLOCK_SIZE) * MEMORY_BLOCK_SIZE;
|
||||||
|
|
||||||
|
while (pBlock != NULL)
|
||||||
|
{
|
||||||
|
if ((ULONG_PTR)pBlock == pTargetBlock)
|
||||||
|
{
|
||||||
|
PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBuffer;
|
||||||
|
#ifdef _DEBUG
|
||||||
|
// Clear the released slot for debugging.
|
||||||
|
memset(pSlot, 0x00, sizeof(*pSlot));
|
||||||
|
#endif
|
||||||
|
// Restore the released slot to the list.
|
||||||
|
pSlot->pNext = pBlock->pFree;
|
||||||
|
pBlock->pFree = pSlot;
|
||||||
|
pBlock->usedCount--;
|
||||||
|
|
||||||
|
// Free if unused.
|
||||||
|
if (pBlock->usedCount == 0)
|
||||||
|
{
|
||||||
|
if (pPrev)
|
||||||
|
pPrev->pNext = pBlock->pNext;
|
||||||
|
else
|
||||||
|
g_pMemoryBlocks = pBlock->pNext;
|
||||||
|
|
||||||
|
VirtualFree(pBlock, 0, MEM_RELEASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pPrev = pBlock;
|
||||||
|
pBlock = pBlock->pNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
BOOL IsExecutableAddress(LPVOID pAddress)
|
||||||
|
{
|
||||||
|
MEMORY_BASIC_INFORMATION mi;
|
||||||
|
VirtualQuery(pAddress, &mi, sizeof(mi));
|
||||||
|
|
||||||
|
return (mi.State == MEM_COMMIT && (mi.Protect & PAGE_EXECUTE_FLAGS));
|
||||||
|
}
|
||||||
42
csgo2/MinHook/src/buffer.h
Normal file
42
csgo2/MinHook/src/buffer.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* MinHook - The Minimalistic API Hooking Library for x64/x86
|
||||||
|
* Copyright (C) 2009-2017 Tsuda Kageyu.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Size of each memory slot.
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
#define MEMORY_SLOT_SIZE 64
|
||||||
|
#else
|
||||||
|
#define MEMORY_SLOT_SIZE 32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
VOID InitializeBuffer(VOID);
|
||||||
|
VOID UninitializeBuffer(VOID);
|
||||||
|
LPVOID AllocateBuffer(LPVOID pOrigin);
|
||||||
|
VOID FreeBuffer(LPVOID pBuffer);
|
||||||
|
BOOL IsExecutableAddress(LPVOID pAddress);
|
||||||
888
csgo2/MinHook/src/hook.c
Normal file
888
csgo2/MinHook/src/hook.c
Normal file
@@ -0,0 +1,888 @@
|
|||||||
|
/*
|
||||||
|
* MinHook - The Minimalistic API Hooking Library for x64/x86
|
||||||
|
* Copyright (C) 2009-2017 Tsuda Kageyu.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <tlhelp32.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "../include/MinHook.h"
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "trampoline.h"
|
||||||
|
#ifndef ARRAYSIZE
|
||||||
|
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initial capacity of the HOOK_ENTRY buffer.
|
||||||
|
#define INITIAL_HOOK_CAPACITY 32
|
||||||
|
|
||||||
|
// Initial capacity of the thread IDs buffer.
|
||||||
|
#define INITIAL_THREAD_CAPACITY 128
|
||||||
|
|
||||||
|
// Special hook position values.
|
||||||
|
#define INVALID_HOOK_POS UINT_MAX
|
||||||
|
#define ALL_HOOKS_POS UINT_MAX
|
||||||
|
|
||||||
|
// Freeze() action argument defines.
|
||||||
|
#define ACTION_DISABLE 0
|
||||||
|
#define ACTION_ENABLE 1
|
||||||
|
#define ACTION_APPLY_QUEUED 2
|
||||||
|
|
||||||
|
// Thread access rights for suspending/resuming threads.
|
||||||
|
#define THREAD_ACCESS \
|
||||||
|
(THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION | THREAD_SET_CONTEXT)
|
||||||
|
|
||||||
|
// Hook information.
|
||||||
|
typedef struct _HOOK_ENTRY
|
||||||
|
{
|
||||||
|
LPVOID pTarget; // Address of the target function.
|
||||||
|
LPVOID pDetour; // Address of the detour or relay function.
|
||||||
|
LPVOID pTrampoline; // Address of the trampoline function.
|
||||||
|
UINT8 backup[8]; // Original prologue of the target function.
|
||||||
|
|
||||||
|
UINT8 patchAbove : 1; // Uses the hot patch area.
|
||||||
|
UINT8 isEnabled : 1; // Enabled.
|
||||||
|
UINT8 queueEnable : 1; // Queued for enabling/disabling when != isEnabled.
|
||||||
|
|
||||||
|
UINT nIP : 4; // Count of the instruction boundaries.
|
||||||
|
UINT8 oldIPs[8]; // Instruction boundaries of the target function.
|
||||||
|
UINT8 newIPs[8]; // Instruction boundaries of the trampoline function.
|
||||||
|
} HOOK_ENTRY, *PHOOK_ENTRY;
|
||||||
|
|
||||||
|
// Suspended threads for Freeze()/Unfreeze().
|
||||||
|
typedef struct _FROZEN_THREADS
|
||||||
|
{
|
||||||
|
LPDWORD pItems; // Data heap
|
||||||
|
UINT capacity; // Size of allocated data heap, items
|
||||||
|
UINT size; // Actual number of data items
|
||||||
|
} FROZEN_THREADS, *PFROZEN_THREADS;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Global Variables:
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Spin lock flag for EnterSpinLock()/LeaveSpinLock().
|
||||||
|
volatile LONG g_isLocked = FALSE;
|
||||||
|
|
||||||
|
// Private heap handle. If not NULL, this library is initialized.
|
||||||
|
HANDLE g_hHeap = NULL;
|
||||||
|
|
||||||
|
// Hook entries.
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
PHOOK_ENTRY pItems; // Data heap
|
||||||
|
UINT capacity; // Size of allocated data heap, items
|
||||||
|
UINT size; // Actual number of data items
|
||||||
|
} g_hooks;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Returns INVALID_HOOK_POS if not found.
|
||||||
|
static UINT FindHookEntry(LPVOID pTarget)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
for (i = 0; i < g_hooks.size; ++i)
|
||||||
|
{
|
||||||
|
if ((ULONG_PTR)pTarget == (ULONG_PTR)g_hooks.pItems[i].pTarget)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return INVALID_HOOK_POS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static PHOOK_ENTRY AddHookEntry()
|
||||||
|
{
|
||||||
|
if (g_hooks.pItems == NULL)
|
||||||
|
{
|
||||||
|
g_hooks.capacity = INITIAL_HOOK_CAPACITY;
|
||||||
|
g_hooks.pItems = (PHOOK_ENTRY)HeapAlloc(
|
||||||
|
g_hHeap, 0, g_hooks.capacity * sizeof(HOOK_ENTRY));
|
||||||
|
if (g_hooks.pItems == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if (g_hooks.size >= g_hooks.capacity)
|
||||||
|
{
|
||||||
|
PHOOK_ENTRY p = (PHOOK_ENTRY)HeapReAlloc(
|
||||||
|
g_hHeap, 0, g_hooks.pItems, (g_hooks.capacity * 2) * sizeof(HOOK_ENTRY));
|
||||||
|
if (p == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
g_hooks.capacity *= 2;
|
||||||
|
g_hooks.pItems = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &g_hooks.pItems[g_hooks.size++];
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static void DeleteHookEntry(UINT pos)
|
||||||
|
{
|
||||||
|
if (pos < g_hooks.size - 1)
|
||||||
|
g_hooks.pItems[pos] = g_hooks.pItems[g_hooks.size - 1];
|
||||||
|
|
||||||
|
g_hooks.size--;
|
||||||
|
|
||||||
|
if (g_hooks.capacity / 2 >= INITIAL_HOOK_CAPACITY && g_hooks.capacity / 2 >= g_hooks.size)
|
||||||
|
{
|
||||||
|
PHOOK_ENTRY p = (PHOOK_ENTRY)HeapReAlloc(
|
||||||
|
g_hHeap, 0, g_hooks.pItems, (g_hooks.capacity / 2) * sizeof(HOOK_ENTRY));
|
||||||
|
if (p == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_hooks.capacity /= 2;
|
||||||
|
g_hooks.pItems = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static DWORD_PTR FindOldIP(PHOOK_ENTRY pHook, DWORD_PTR ip)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
|
||||||
|
if (pHook->patchAbove && ip == ((DWORD_PTR)pHook->pTarget - sizeof(JMP_REL)))
|
||||||
|
return (DWORD_PTR)pHook->pTarget;
|
||||||
|
|
||||||
|
for (i = 0; i < pHook->nIP; ++i)
|
||||||
|
{
|
||||||
|
if (ip == ((DWORD_PTR)pHook->pTrampoline + pHook->newIPs[i]))
|
||||||
|
return (DWORD_PTR)pHook->pTarget + pHook->oldIPs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
// Check relay function.
|
||||||
|
if (ip == (DWORD_PTR)pHook->pDetour)
|
||||||
|
return (DWORD_PTR)pHook->pTarget;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static DWORD_PTR FindNewIP(PHOOK_ENTRY pHook, DWORD_PTR ip)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
for (i = 0; i < pHook->nIP; ++i)
|
||||||
|
{
|
||||||
|
if (ip == ((DWORD_PTR)pHook->pTarget + pHook->oldIPs[i]))
|
||||||
|
return (DWORD_PTR)pHook->pTrampoline + pHook->newIPs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static void ProcessThreadIPs(HANDLE hThread, UINT pos, UINT action)
|
||||||
|
{
|
||||||
|
// If the thread suspended in the overwritten area,
|
||||||
|
// move IP to the proper address.
|
||||||
|
|
||||||
|
CONTEXT c;
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
DWORD64 *pIP = &c.Rip;
|
||||||
|
#else
|
||||||
|
DWORD *pIP = &c.Eip;
|
||||||
|
#endif
|
||||||
|
UINT count;
|
||||||
|
|
||||||
|
c.ContextFlags = CONTEXT_CONTROL;
|
||||||
|
if (!GetThreadContext(hThread, &c))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pos == ALL_HOOKS_POS)
|
||||||
|
{
|
||||||
|
pos = 0;
|
||||||
|
count = g_hooks.size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count = pos + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; pos < count; ++pos)
|
||||||
|
{
|
||||||
|
PHOOK_ENTRY pHook = &g_hooks.pItems[pos];
|
||||||
|
BOOL enable;
|
||||||
|
DWORD_PTR ip;
|
||||||
|
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case ACTION_DISABLE:
|
||||||
|
enable = FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACTION_ENABLE:
|
||||||
|
enable = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: // ACTION_APPLY_QUEUED
|
||||||
|
enable = pHook->queueEnable;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pHook->isEnabled == enable)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
ip = FindNewIP(pHook, *pIP);
|
||||||
|
else
|
||||||
|
ip = FindOldIP(pHook, *pIP);
|
||||||
|
|
||||||
|
if (ip != 0)
|
||||||
|
{
|
||||||
|
*pIP = ip;
|
||||||
|
SetThreadContext(hThread, &c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static VOID EnumerateThreads(PFROZEN_THREADS pThreads)
|
||||||
|
{
|
||||||
|
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
||||||
|
if (hSnapshot != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
THREADENTRY32 te;
|
||||||
|
te.dwSize = sizeof(THREADENTRY32);
|
||||||
|
if (Thread32First(hSnapshot, &te))
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (te.dwSize >= (FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(DWORD))
|
||||||
|
&& te.th32OwnerProcessID == GetCurrentProcessId()
|
||||||
|
&& te.th32ThreadID != GetCurrentThreadId())
|
||||||
|
{
|
||||||
|
if (pThreads->pItems == NULL)
|
||||||
|
{
|
||||||
|
pThreads->capacity = INITIAL_THREAD_CAPACITY;
|
||||||
|
pThreads->pItems
|
||||||
|
= (LPDWORD)HeapAlloc(g_hHeap, 0, pThreads->capacity * sizeof(DWORD));
|
||||||
|
if (pThreads->pItems == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (pThreads->size >= pThreads->capacity)
|
||||||
|
{
|
||||||
|
LPDWORD p = (LPDWORD)HeapReAlloc(
|
||||||
|
g_hHeap, 0, pThreads->pItems, (pThreads->capacity * 2) * sizeof(DWORD));
|
||||||
|
if (p == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
pThreads->capacity *= 2;
|
||||||
|
pThreads->pItems = p;
|
||||||
|
}
|
||||||
|
pThreads->pItems[pThreads->size++] = te.th32ThreadID;
|
||||||
|
}
|
||||||
|
|
||||||
|
te.dwSize = sizeof(THREADENTRY32);
|
||||||
|
} while (Thread32Next(hSnapshot, &te));
|
||||||
|
}
|
||||||
|
CloseHandle(hSnapshot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static VOID Freeze(PFROZEN_THREADS pThreads, UINT pos, UINT action)
|
||||||
|
{
|
||||||
|
pThreads->pItems = NULL;
|
||||||
|
pThreads->capacity = 0;
|
||||||
|
pThreads->size = 0;
|
||||||
|
EnumerateThreads(pThreads);
|
||||||
|
|
||||||
|
if (pThreads->pItems != NULL)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
for (i = 0; i < pThreads->size; ++i)
|
||||||
|
{
|
||||||
|
HANDLE hThread = OpenThread(THREAD_ACCESS, FALSE, pThreads->pItems[i]);
|
||||||
|
if (hThread != NULL)
|
||||||
|
{
|
||||||
|
SuspendThread(hThread);
|
||||||
|
ProcessThreadIPs(hThread, pos, action);
|
||||||
|
CloseHandle(hThread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static VOID Unfreeze(PFROZEN_THREADS pThreads)
|
||||||
|
{
|
||||||
|
if (pThreads->pItems != NULL)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
for (i = 0; i < pThreads->size; ++i)
|
||||||
|
{
|
||||||
|
HANDLE hThread = OpenThread(THREAD_ACCESS, FALSE, pThreads->pItems[i]);
|
||||||
|
if (hThread != NULL)
|
||||||
|
{
|
||||||
|
ResumeThread(hThread);
|
||||||
|
CloseHandle(hThread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapFree(g_hHeap, 0, pThreads->pItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static MH_STATUS EnableHookLL(UINT pos, BOOL enable)
|
||||||
|
{
|
||||||
|
PHOOK_ENTRY pHook = &g_hooks.pItems[pos];
|
||||||
|
DWORD oldProtect;
|
||||||
|
SIZE_T patchSize = sizeof(JMP_REL);
|
||||||
|
LPBYTE pPatchTarget = (LPBYTE)pHook->pTarget;
|
||||||
|
|
||||||
|
if (pHook->patchAbove)
|
||||||
|
{
|
||||||
|
pPatchTarget -= sizeof(JMP_REL);
|
||||||
|
patchSize += sizeof(JMP_REL_SHORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!VirtualProtect(pPatchTarget, patchSize, PAGE_EXECUTE_READWRITE, &oldProtect))
|
||||||
|
return MH_ERROR_MEMORY_PROTECT;
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
PJMP_REL pJmp = (PJMP_REL)pPatchTarget;
|
||||||
|
pJmp->opcode = 0xE9;
|
||||||
|
pJmp->operand = (UINT32)((LPBYTE)pHook->pDetour - (pPatchTarget + sizeof(JMP_REL)));
|
||||||
|
|
||||||
|
if (pHook->patchAbove)
|
||||||
|
{
|
||||||
|
PJMP_REL_SHORT pShortJmp = (PJMP_REL_SHORT)pHook->pTarget;
|
||||||
|
pShortJmp->opcode = 0xEB;
|
||||||
|
pShortJmp->operand = (UINT8)(0 - (sizeof(JMP_REL_SHORT) + sizeof(JMP_REL)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pHook->patchAbove)
|
||||||
|
memcpy(pPatchTarget, pHook->backup, sizeof(JMP_REL) + sizeof(JMP_REL_SHORT));
|
||||||
|
else
|
||||||
|
memcpy(pPatchTarget, pHook->backup, sizeof(JMP_REL));
|
||||||
|
}
|
||||||
|
|
||||||
|
VirtualProtect(pPatchTarget, patchSize, oldProtect, &oldProtect);
|
||||||
|
|
||||||
|
// Just-in-case measure.
|
||||||
|
FlushInstructionCache(GetCurrentProcess(), pPatchTarget, patchSize);
|
||||||
|
|
||||||
|
pHook->isEnabled = enable;
|
||||||
|
pHook->queueEnable = enable;
|
||||||
|
|
||||||
|
return MH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static MH_STATUS EnableAllHooksLL(BOOL enable)
|
||||||
|
{
|
||||||
|
MH_STATUS status = MH_OK;
|
||||||
|
UINT i, first = INVALID_HOOK_POS;
|
||||||
|
|
||||||
|
for (i = 0; i < g_hooks.size; ++i)
|
||||||
|
{
|
||||||
|
if (g_hooks.pItems[i].isEnabled != enable)
|
||||||
|
{
|
||||||
|
first = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first != INVALID_HOOK_POS)
|
||||||
|
{
|
||||||
|
FROZEN_THREADS threads;
|
||||||
|
Freeze(&threads, ALL_HOOKS_POS, enable ? ACTION_ENABLE : ACTION_DISABLE);
|
||||||
|
|
||||||
|
for (i = first; i < g_hooks.size; ++i)
|
||||||
|
{
|
||||||
|
if (g_hooks.pItems[i].isEnabled != enable)
|
||||||
|
{
|
||||||
|
status = EnableHookLL(i, enable);
|
||||||
|
if (status != MH_OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Unfreeze(&threads);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static VOID EnterSpinLock(VOID)
|
||||||
|
{
|
||||||
|
SIZE_T spinCount = 0;
|
||||||
|
|
||||||
|
// Wait until the flag is FALSE.
|
||||||
|
while (InterlockedCompareExchange(&g_isLocked, TRUE, FALSE) != FALSE)
|
||||||
|
{
|
||||||
|
// No need to generate a memory barrier here, since InterlockedCompareExchange()
|
||||||
|
// generates a full memory barrier itself.
|
||||||
|
|
||||||
|
// Prevent the loop from being too busy.
|
||||||
|
if (spinCount < 32)
|
||||||
|
Sleep(0);
|
||||||
|
else
|
||||||
|
Sleep(1);
|
||||||
|
|
||||||
|
spinCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static VOID LeaveSpinLock(VOID)
|
||||||
|
{
|
||||||
|
// No need to generate a memory barrier here, since InterlockedExchange()
|
||||||
|
// generates a full memory barrier itself.
|
||||||
|
|
||||||
|
InterlockedExchange(&g_isLocked, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
MH_STATUS WINAPI MH_Initialize(VOID)
|
||||||
|
{
|
||||||
|
MH_STATUS status = MH_OK;
|
||||||
|
|
||||||
|
EnterSpinLock();
|
||||||
|
|
||||||
|
if (g_hHeap == NULL)
|
||||||
|
{
|
||||||
|
g_hHeap = HeapCreate(0, 0, 0);
|
||||||
|
if (g_hHeap != NULL)
|
||||||
|
{
|
||||||
|
// Initialize the internal function buffer.
|
||||||
|
InitializeBuffer();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = MH_ERROR_MEMORY_ALLOC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = MH_ERROR_ALREADY_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveSpinLock();
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
MH_STATUS WINAPI MH_Uninitialize(VOID)
|
||||||
|
{
|
||||||
|
MH_STATUS status = MH_OK;
|
||||||
|
|
||||||
|
EnterSpinLock();
|
||||||
|
|
||||||
|
if (g_hHeap != NULL)
|
||||||
|
{
|
||||||
|
status = EnableAllHooksLL(FALSE);
|
||||||
|
if (status == MH_OK)
|
||||||
|
{
|
||||||
|
// Free the internal function buffer.
|
||||||
|
|
||||||
|
// HeapFree is actually not required, but some tools detect a false
|
||||||
|
// memory leak without HeapFree.
|
||||||
|
|
||||||
|
UninitializeBuffer();
|
||||||
|
|
||||||
|
HeapFree(g_hHeap, 0, g_hooks.pItems);
|
||||||
|
HeapDestroy(g_hHeap);
|
||||||
|
|
||||||
|
g_hHeap = NULL;
|
||||||
|
|
||||||
|
g_hooks.pItems = NULL;
|
||||||
|
g_hooks.capacity = 0;
|
||||||
|
g_hooks.size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = MH_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveSpinLock();
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal)
|
||||||
|
{
|
||||||
|
MH_STATUS status = MH_OK;
|
||||||
|
|
||||||
|
EnterSpinLock();
|
||||||
|
|
||||||
|
if (g_hHeap != NULL)
|
||||||
|
{
|
||||||
|
if (IsExecutableAddress(pTarget)/* && IsExecutableAddress(pDetour)*/)
|
||||||
|
{
|
||||||
|
UINT pos = FindHookEntry(pTarget);
|
||||||
|
if (pos == INVALID_HOOK_POS)
|
||||||
|
{
|
||||||
|
LPVOID pBuffer = AllocateBuffer(pTarget);
|
||||||
|
if (pBuffer != NULL)
|
||||||
|
{
|
||||||
|
TRAMPOLINE ct;
|
||||||
|
|
||||||
|
ct.pTarget = pTarget;
|
||||||
|
ct.pDetour = pDetour;
|
||||||
|
ct.pTrampoline = pBuffer;
|
||||||
|
if (CreateTrampolineFunction(&ct))
|
||||||
|
{
|
||||||
|
PHOOK_ENTRY pHook = AddHookEntry();
|
||||||
|
if (pHook != NULL)
|
||||||
|
{
|
||||||
|
pHook->pTarget = ct.pTarget;
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
pHook->pDetour = ct.pRelay;
|
||||||
|
#else
|
||||||
|
pHook->pDetour = ct.pDetour;
|
||||||
|
#endif
|
||||||
|
pHook->pTrampoline = ct.pTrampoline;
|
||||||
|
pHook->patchAbove = ct.patchAbove;
|
||||||
|
pHook->isEnabled = FALSE;
|
||||||
|
pHook->queueEnable = FALSE;
|
||||||
|
pHook->nIP = ct.nIP;
|
||||||
|
memcpy(pHook->oldIPs, ct.oldIPs, ARRAYSIZE(ct.oldIPs));
|
||||||
|
memcpy(pHook->newIPs, ct.newIPs, ARRAYSIZE(ct.newIPs));
|
||||||
|
|
||||||
|
// Back up the target function.
|
||||||
|
|
||||||
|
if (ct.patchAbove)
|
||||||
|
{
|
||||||
|
memcpy(
|
||||||
|
pHook->backup,
|
||||||
|
(LPBYTE)pTarget - sizeof(JMP_REL),
|
||||||
|
sizeof(JMP_REL) + sizeof(JMP_REL_SHORT));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(pHook->backup, pTarget, sizeof(JMP_REL));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ppOriginal != NULL)
|
||||||
|
*ppOriginal = pHook->pTrampoline;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = MH_ERROR_MEMORY_ALLOC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = MH_ERROR_UNSUPPORTED_FUNCTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != MH_OK)
|
||||||
|
{
|
||||||
|
FreeBuffer(pBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = MH_ERROR_MEMORY_ALLOC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = MH_ERROR_ALREADY_CREATED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = MH_ERROR_NOT_EXECUTABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = MH_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveSpinLock();
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget)
|
||||||
|
{
|
||||||
|
MH_STATUS status = MH_OK;
|
||||||
|
|
||||||
|
EnterSpinLock();
|
||||||
|
|
||||||
|
if (g_hHeap != NULL)
|
||||||
|
{
|
||||||
|
UINT pos = FindHookEntry(pTarget);
|
||||||
|
if (pos != INVALID_HOOK_POS)
|
||||||
|
{
|
||||||
|
if (g_hooks.pItems[pos].isEnabled)
|
||||||
|
{
|
||||||
|
FROZEN_THREADS threads;
|
||||||
|
Freeze(&threads, pos, ACTION_DISABLE);
|
||||||
|
|
||||||
|
status = EnableHookLL(pos, FALSE);
|
||||||
|
|
||||||
|
Unfreeze(&threads);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == MH_OK)
|
||||||
|
{
|
||||||
|
FreeBuffer(g_hooks.pItems[pos].pTrampoline);
|
||||||
|
DeleteHookEntry(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = MH_ERROR_NOT_CREATED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = MH_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveSpinLock();
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static MH_STATUS EnableHook(LPVOID pTarget, BOOL enable)
|
||||||
|
{
|
||||||
|
MH_STATUS status = MH_OK;
|
||||||
|
|
||||||
|
EnterSpinLock();
|
||||||
|
|
||||||
|
if (g_hHeap != NULL)
|
||||||
|
{
|
||||||
|
if (pTarget == MH_ALL_HOOKS)
|
||||||
|
{
|
||||||
|
status = EnableAllHooksLL(enable);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FROZEN_THREADS threads;
|
||||||
|
UINT pos = FindHookEntry(pTarget);
|
||||||
|
if (pos != INVALID_HOOK_POS)
|
||||||
|
{
|
||||||
|
if (g_hooks.pItems[pos].isEnabled != enable)
|
||||||
|
{
|
||||||
|
Freeze(&threads, pos, ACTION_ENABLE);
|
||||||
|
|
||||||
|
status = EnableHookLL(pos, enable);
|
||||||
|
|
||||||
|
Unfreeze(&threads);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = enable ? MH_ERROR_ENABLED : MH_ERROR_DISABLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = MH_ERROR_NOT_CREATED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = MH_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveSpinLock();
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget)
|
||||||
|
{
|
||||||
|
return EnableHook(pTarget, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget)
|
||||||
|
{
|
||||||
|
return EnableHook(pTarget, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static MH_STATUS QueueHook(LPVOID pTarget, BOOL queueEnable)
|
||||||
|
{
|
||||||
|
MH_STATUS status = MH_OK;
|
||||||
|
|
||||||
|
EnterSpinLock();
|
||||||
|
|
||||||
|
if (g_hHeap != NULL)
|
||||||
|
{
|
||||||
|
if (pTarget == MH_ALL_HOOKS)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
for (i = 0; i < g_hooks.size; ++i)
|
||||||
|
g_hooks.pItems[i].queueEnable = queueEnable;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UINT pos = FindHookEntry(pTarget);
|
||||||
|
if (pos != INVALID_HOOK_POS)
|
||||||
|
{
|
||||||
|
g_hooks.pItems[pos].queueEnable = queueEnable;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = MH_ERROR_NOT_CREATED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = MH_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveSpinLock();
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget)
|
||||||
|
{
|
||||||
|
return QueueHook(pTarget, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget)
|
||||||
|
{
|
||||||
|
return QueueHook(pTarget, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
MH_STATUS WINAPI MH_ApplyQueued(VOID)
|
||||||
|
{
|
||||||
|
MH_STATUS status = MH_OK;
|
||||||
|
UINT i, first = INVALID_HOOK_POS;
|
||||||
|
|
||||||
|
EnterSpinLock();
|
||||||
|
|
||||||
|
if (g_hHeap != NULL)
|
||||||
|
{
|
||||||
|
for (i = 0; i < g_hooks.size; ++i)
|
||||||
|
{
|
||||||
|
if (g_hooks.pItems[i].isEnabled != g_hooks.pItems[i].queueEnable)
|
||||||
|
{
|
||||||
|
first = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first != INVALID_HOOK_POS)
|
||||||
|
{
|
||||||
|
FROZEN_THREADS threads;
|
||||||
|
Freeze(&threads, ALL_HOOKS_POS, ACTION_APPLY_QUEUED);
|
||||||
|
|
||||||
|
for (i = first; i < g_hooks.size; ++i)
|
||||||
|
{
|
||||||
|
PHOOK_ENTRY pHook = &g_hooks.pItems[i];
|
||||||
|
if (pHook->isEnabled != pHook->queueEnable)
|
||||||
|
{
|
||||||
|
status = EnableHookLL(i, pHook->queueEnable);
|
||||||
|
if (status != MH_OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Unfreeze(&threads);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = MH_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveSpinLock();
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
MH_STATUS WINAPI MH_CreateHookApiEx(
|
||||||
|
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour,
|
||||||
|
LPVOID *ppOriginal, LPVOID *ppTarget)
|
||||||
|
{
|
||||||
|
HMODULE hModule;
|
||||||
|
LPVOID pTarget;
|
||||||
|
|
||||||
|
hModule = GetModuleHandleW(pszModule);
|
||||||
|
if (hModule == NULL)
|
||||||
|
return MH_ERROR_MODULE_NOT_FOUND;
|
||||||
|
|
||||||
|
pTarget = (LPVOID)GetProcAddress(hModule, pszProcName);
|
||||||
|
if (pTarget == NULL)
|
||||||
|
return MH_ERROR_FUNCTION_NOT_FOUND;
|
||||||
|
|
||||||
|
if(ppTarget != NULL)
|
||||||
|
*ppTarget = pTarget;
|
||||||
|
|
||||||
|
return MH_CreateHook(pTarget, pDetour, ppOriginal);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
MH_STATUS WINAPI MH_CreateHookApi(
|
||||||
|
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal)
|
||||||
|
{
|
||||||
|
return MH_CreateHookApiEx(pszModule, pszProcName, pDetour, ppOriginal, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
const char * WINAPI MH_StatusToString(MH_STATUS status)
|
||||||
|
{
|
||||||
|
#define MH_ST2STR(x) \
|
||||||
|
case x: \
|
||||||
|
return #x;
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
MH_ST2STR(MH_UNKNOWN)
|
||||||
|
MH_ST2STR(MH_OK)
|
||||||
|
MH_ST2STR(MH_ERROR_ALREADY_INITIALIZED)
|
||||||
|
MH_ST2STR(MH_ERROR_NOT_INITIALIZED)
|
||||||
|
MH_ST2STR(MH_ERROR_ALREADY_CREATED)
|
||||||
|
MH_ST2STR(MH_ERROR_NOT_CREATED)
|
||||||
|
MH_ST2STR(MH_ERROR_ENABLED)
|
||||||
|
MH_ST2STR(MH_ERROR_DISABLED)
|
||||||
|
MH_ST2STR(MH_ERROR_NOT_EXECUTABLE)
|
||||||
|
MH_ST2STR(MH_ERROR_UNSUPPORTED_FUNCTION)
|
||||||
|
MH_ST2STR(MH_ERROR_MEMORY_ALLOC)
|
||||||
|
MH_ST2STR(MH_ERROR_MEMORY_PROTECT)
|
||||||
|
MH_ST2STR(MH_ERROR_MODULE_NOT_FOUND)
|
||||||
|
MH_ST2STR(MH_ERROR_FUNCTION_NOT_FOUND)
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef MH_ST2STR
|
||||||
|
|
||||||
|
return "(unknown)";
|
||||||
|
}
|
||||||
316
csgo2/MinHook/src/trampoline.c
Normal file
316
csgo2/MinHook/src/trampoline.c
Normal file
@@ -0,0 +1,316 @@
|
|||||||
|
/*
|
||||||
|
* MinHook - The Minimalistic API Hooking Library for x64/x86
|
||||||
|
* Copyright (C) 2009-2017 Tsuda Kageyu.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#ifndef ARRAYSIZE
|
||||||
|
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
#include "./hde/hde64.h"
|
||||||
|
typedef hde64s HDE;
|
||||||
|
#define HDE_DISASM(code, hs) hde64_disasm(code, hs)
|
||||||
|
#else
|
||||||
|
#include "./hde/hde32.h"
|
||||||
|
typedef hde32s HDE;
|
||||||
|
#define HDE_DISASM(code, hs) hde32_disasm(code, hs)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "trampoline.h"
|
||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
|
// Maximum size of a trampoline function.
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
#define TRAMPOLINE_MAX_SIZE (MEMORY_SLOT_SIZE - sizeof(JMP_ABS))
|
||||||
|
#else
|
||||||
|
#define TRAMPOLINE_MAX_SIZE MEMORY_SLOT_SIZE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static BOOL IsCodePadding(LPBYTE pInst, UINT size)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
|
||||||
|
if (pInst[0] != 0x00 && pInst[0] != 0x90 && pInst[0] != 0xCC)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (i = 1; i < size; ++i)
|
||||||
|
{
|
||||||
|
if (pInst[i] != pInst[0])
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
BOOL CreateTrampolineFunction(PTRAMPOLINE ct)
|
||||||
|
{
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
CALL_ABS call = {
|
||||||
|
0xFF, 0x15, 0x00000002, // FF15 00000002: CALL [RIP+8]
|
||||||
|
0xEB, 0x08, // EB 08: JMP +10
|
||||||
|
0x0000000000000000ULL // Absolute destination address
|
||||||
|
};
|
||||||
|
JMP_ABS jmp = {
|
||||||
|
0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6]
|
||||||
|
0x0000000000000000ULL // Absolute destination address
|
||||||
|
};
|
||||||
|
JCC_ABS jcc = {
|
||||||
|
0x70, 0x0E, // 7* 0E: J** +16
|
||||||
|
0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6]
|
||||||
|
0x0000000000000000ULL // Absolute destination address
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
CALL_REL call = {
|
||||||
|
0xE8, // E8 xxxxxxxx: CALL +5+xxxxxxxx
|
||||||
|
0x00000000 // Relative destination address
|
||||||
|
};
|
||||||
|
JMP_REL jmp = {
|
||||||
|
0xE9, // E9 xxxxxxxx: JMP +5+xxxxxxxx
|
||||||
|
0x00000000 // Relative destination address
|
||||||
|
};
|
||||||
|
JCC_REL jcc = {
|
||||||
|
0x0F, 0x80, // 0F8* xxxxxxxx: J** +6+xxxxxxxx
|
||||||
|
0x00000000 // Relative destination address
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
UINT8 oldPos = 0;
|
||||||
|
UINT8 newPos = 0;
|
||||||
|
ULONG_PTR jmpDest = 0; // Destination address of an internal jump.
|
||||||
|
BOOL finished = FALSE; // Is the function completed?
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
UINT8 instBuf[16];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ct->patchAbove = FALSE;
|
||||||
|
ct->nIP = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
HDE hs;
|
||||||
|
UINT copySize;
|
||||||
|
LPVOID pCopySrc;
|
||||||
|
ULONG_PTR pOldInst = (ULONG_PTR)ct->pTarget + oldPos;
|
||||||
|
ULONG_PTR pNewInst = (ULONG_PTR)ct->pTrampoline + newPos;
|
||||||
|
|
||||||
|
copySize = HDE_DISASM((LPVOID)pOldInst, &hs);
|
||||||
|
if (hs.flags & F_ERROR)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
pCopySrc = (LPVOID)pOldInst;
|
||||||
|
if (oldPos >= sizeof(JMP_REL))
|
||||||
|
{
|
||||||
|
// The trampoline function is long enough.
|
||||||
|
// Complete the function with the jump to the target function.
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
jmp.address = pOldInst;
|
||||||
|
#else
|
||||||
|
jmp.operand = (UINT32)(pOldInst - (pNewInst + sizeof(jmp)));
|
||||||
|
#endif
|
||||||
|
pCopySrc = &jmp;
|
||||||
|
copySize = sizeof(jmp);
|
||||||
|
|
||||||
|
finished = TRUE;
|
||||||
|
}
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
else if ((hs.modrm & 0xC7) == 0x05)
|
||||||
|
{
|
||||||
|
// Instructions using RIP relative addressing. (ModR/M = 00???101B)
|
||||||
|
|
||||||
|
// Modify the RIP relative address.
|
||||||
|
PUINT32 pRelAddr;
|
||||||
|
|
||||||
|
// Avoid using memcpy to reduce the footprint.
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
memcpy(instBuf, (LPBYTE)pOldInst, copySize);
|
||||||
|
#else
|
||||||
|
__movsb(instBuf, (LPBYTE)pOldInst, copySize);
|
||||||
|
#endif
|
||||||
|
pCopySrc = instBuf;
|
||||||
|
|
||||||
|
// Relative address is stored at (instruction length - immediate value length - 4).
|
||||||
|
pRelAddr = (PUINT32)(instBuf + hs.len - ((hs.flags & 0x3C) >> 2) - 4);
|
||||||
|
*pRelAddr
|
||||||
|
= (UINT32)((pOldInst + hs.len + (INT32)hs.disp.disp32) - (pNewInst + hs.len));
|
||||||
|
|
||||||
|
// Complete the function if JMP (FF /4).
|
||||||
|
if (hs.opcode == 0xFF && hs.modrm_reg == 4)
|
||||||
|
finished = TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else if (hs.opcode == 0xE8)
|
||||||
|
{
|
||||||
|
// Direct relative CALL
|
||||||
|
ULONG_PTR dest = pOldInst + hs.len + (INT32)hs.imm.imm32;
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
call.address = dest;
|
||||||
|
#else
|
||||||
|
call.operand = (UINT32)(dest - (pNewInst + sizeof(call)));
|
||||||
|
#endif
|
||||||
|
pCopySrc = &call;
|
||||||
|
copySize = sizeof(call);
|
||||||
|
}
|
||||||
|
else if ((hs.opcode & 0xFD) == 0xE9)
|
||||||
|
{
|
||||||
|
// Direct relative JMP (EB or E9)
|
||||||
|
ULONG_PTR dest = pOldInst + hs.len;
|
||||||
|
|
||||||
|
if (hs.opcode == 0xEB) // isShort jmp
|
||||||
|
dest += (INT8)hs.imm.imm8;
|
||||||
|
else
|
||||||
|
dest += (INT32)hs.imm.imm32;
|
||||||
|
|
||||||
|
// Simply copy an internal jump.
|
||||||
|
if ((ULONG_PTR)ct->pTarget <= dest
|
||||||
|
&& dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL)))
|
||||||
|
{
|
||||||
|
if (jmpDest < dest)
|
||||||
|
jmpDest = dest;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
jmp.address = dest;
|
||||||
|
#else
|
||||||
|
jmp.operand = (UINT32)(dest - (pNewInst + sizeof(jmp)));
|
||||||
|
#endif
|
||||||
|
pCopySrc = &jmp;
|
||||||
|
copySize = sizeof(jmp);
|
||||||
|
|
||||||
|
// Exit the function If it is not in the branch
|
||||||
|
finished = (pOldInst >= jmpDest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((hs.opcode & 0xF0) == 0x70
|
||||||
|
|| (hs.opcode & 0xFC) == 0xE0
|
||||||
|
|| (hs.opcode2 & 0xF0) == 0x80)
|
||||||
|
{
|
||||||
|
// Direct relative Jcc
|
||||||
|
ULONG_PTR dest = pOldInst + hs.len;
|
||||||
|
|
||||||
|
if ((hs.opcode & 0xF0) == 0x70 // Jcc
|
||||||
|
|| (hs.opcode & 0xFC) == 0xE0) // LOOPNZ/LOOPZ/LOOP/JECXZ
|
||||||
|
dest += (INT8)hs.imm.imm8;
|
||||||
|
else
|
||||||
|
dest += (INT32)hs.imm.imm32;
|
||||||
|
|
||||||
|
// Simply copy an internal jump.
|
||||||
|
if ((ULONG_PTR)ct->pTarget <= dest
|
||||||
|
&& dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL)))
|
||||||
|
{
|
||||||
|
if (jmpDest < dest)
|
||||||
|
jmpDest = dest;
|
||||||
|
}
|
||||||
|
else if ((hs.opcode & 0xFC) == 0xE0)
|
||||||
|
{
|
||||||
|
// LOOPNZ/LOOPZ/LOOP/JCXZ/JECXZ to the outside are not supported.
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UINT8 cond = ((hs.opcode != 0x0F ? hs.opcode : hs.opcode2) & 0x0F);
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
// Invert the condition in x64 mode to simplify the conditional jump logic.
|
||||||
|
jcc.opcode = 0x71 ^ cond;
|
||||||
|
jcc.address = dest;
|
||||||
|
#else
|
||||||
|
jcc.opcode1 = 0x80 | cond;
|
||||||
|
jcc.operand = (UINT32)(dest - (pNewInst + sizeof(jcc)));
|
||||||
|
#endif
|
||||||
|
pCopySrc = &jcc;
|
||||||
|
copySize = sizeof(jcc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((hs.opcode & 0xFE) == 0xC2)
|
||||||
|
{
|
||||||
|
// RET (C2 or C3)
|
||||||
|
|
||||||
|
// Complete the function if not in a branch.
|
||||||
|
finished = (pOldInst >= jmpDest);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can't alter the instruction length in a branch.
|
||||||
|
if (pOldInst < jmpDest && copySize != hs.len)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// Trampoline function is too large.
|
||||||
|
if ((newPos + copySize) > TRAMPOLINE_MAX_SIZE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// Trampoline function has too many instructions.
|
||||||
|
if (ct->nIP >= ARRAYSIZE(ct->oldIPs))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
ct->oldIPs[ct->nIP] = oldPos;
|
||||||
|
ct->newIPs[ct->nIP] = newPos;
|
||||||
|
ct->nIP++;
|
||||||
|
|
||||||
|
// Avoid using memcpy to reduce the footprint.
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
memcpy((LPBYTE)ct->pTrampoline + newPos, pCopySrc, copySize);
|
||||||
|
#else
|
||||||
|
__movsb((LPBYTE)ct->pTrampoline + newPos, pCopySrc, copySize);
|
||||||
|
#endif
|
||||||
|
newPos += copySize;
|
||||||
|
oldPos += hs.len;
|
||||||
|
}
|
||||||
|
while (!finished);
|
||||||
|
|
||||||
|
// Is there enough place for a long jump?
|
||||||
|
if (oldPos < sizeof(JMP_REL)
|
||||||
|
&& !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL) - oldPos))
|
||||||
|
{
|
||||||
|
// Is there enough place for a short jump?
|
||||||
|
if (oldPos < sizeof(JMP_REL_SHORT)
|
||||||
|
&& !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL_SHORT) - oldPos))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can we place the long jump above the function?
|
||||||
|
if (!IsExecutableAddress((LPBYTE)ct->pTarget - sizeof(JMP_REL)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!IsCodePadding((LPBYTE)ct->pTarget - sizeof(JMP_REL), sizeof(JMP_REL)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
ct->patchAbove = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
// Create a relay function.
|
||||||
|
jmp.address = (ULONG_PTR)ct->pDetour;
|
||||||
|
|
||||||
|
ct->pRelay = (LPBYTE)ct->pTrampoline + newPos;
|
||||||
|
memcpy(ct->pRelay, &jmp, sizeof(jmp));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
105
csgo2/MinHook/src/trampoline.h
Normal file
105
csgo2/MinHook/src/trampoline.h
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* MinHook - The Minimalistic API Hooking Library for x64/x86
|
||||||
|
* Copyright (C) 2009-2017 Tsuda Kageyu.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
// Structs for writing x86/x64 instructions.
|
||||||
|
|
||||||
|
// 8-bit relative jump.
|
||||||
|
typedef struct _JMP_REL_SHORT
|
||||||
|
{
|
||||||
|
UINT8 opcode; // EB xx: JMP +2+xx
|
||||||
|
UINT8 operand;
|
||||||
|
} JMP_REL_SHORT, *PJMP_REL_SHORT;
|
||||||
|
|
||||||
|
// 32-bit direct relative jump/call.
|
||||||
|
typedef struct _JMP_REL
|
||||||
|
{
|
||||||
|
UINT8 opcode; // E9/E8 xxxxxxxx: JMP/CALL +5+xxxxxxxx
|
||||||
|
UINT32 operand; // Relative destination address
|
||||||
|
} JMP_REL, *PJMP_REL, CALL_REL;
|
||||||
|
|
||||||
|
// 64-bit indirect absolute jump.
|
||||||
|
typedef struct _JMP_ABS
|
||||||
|
{
|
||||||
|
UINT8 opcode0; // FF25 00000000: JMP [+6]
|
||||||
|
UINT8 opcode1;
|
||||||
|
UINT32 dummy;
|
||||||
|
UINT64 address; // Absolute destination address
|
||||||
|
} JMP_ABS, *PJMP_ABS;
|
||||||
|
|
||||||
|
// 64-bit indirect absolute call.
|
||||||
|
typedef struct _CALL_ABS
|
||||||
|
{
|
||||||
|
UINT8 opcode0; // FF15 00000002: CALL [+6]
|
||||||
|
UINT8 opcode1;
|
||||||
|
UINT32 dummy0;
|
||||||
|
UINT8 dummy1; // EB 08: JMP +10
|
||||||
|
UINT8 dummy2;
|
||||||
|
UINT64 address; // Absolute destination address
|
||||||
|
} CALL_ABS;
|
||||||
|
|
||||||
|
// 32-bit direct relative conditional jumps.
|
||||||
|
typedef struct _JCC_REL
|
||||||
|
{
|
||||||
|
UINT8 opcode0; // 0F8* xxxxxxxx: J** +6+xxxxxxxx
|
||||||
|
UINT8 opcode1;
|
||||||
|
UINT32 operand; // Relative destination address
|
||||||
|
} JCC_REL;
|
||||||
|
|
||||||
|
// 64bit indirect absolute conditional jumps that x64 lacks.
|
||||||
|
typedef struct _JCC_ABS
|
||||||
|
{
|
||||||
|
UINT8 opcode; // 7* 0E: J** +16
|
||||||
|
UINT8 dummy0;
|
||||||
|
UINT8 dummy1; // FF25 00000000: JMP [+6]
|
||||||
|
UINT8 dummy2;
|
||||||
|
UINT32 dummy3;
|
||||||
|
UINT64 address; // Absolute destination address
|
||||||
|
} JCC_ABS;
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
typedef struct _TRAMPOLINE
|
||||||
|
{
|
||||||
|
LPVOID pTarget; // [In] Address of the target function.
|
||||||
|
LPVOID pDetour; // [In] Address of the detour function.
|
||||||
|
LPVOID pTrampoline; // [In] Buffer address for the trampoline and relay function.
|
||||||
|
|
||||||
|
#if defined(_M_X64) || defined(__x86_64__)
|
||||||
|
LPVOID pRelay; // [Out] Address of the relay function.
|
||||||
|
#endif
|
||||||
|
BOOL patchAbove; // [Out] Should use the hot patch area?
|
||||||
|
UINT nIP; // [Out] Number of the instruction boundaries.
|
||||||
|
UINT8 oldIPs[8]; // [Out] Instruction boundaries of the target function.
|
||||||
|
UINT8 newIPs[8]; // [Out] Instruction boundaries of the trampoline function.
|
||||||
|
} TRAMPOLINE, *PTRAMPOLINE;
|
||||||
|
|
||||||
|
BOOL CreateTrampolineFunction(PTRAMPOLINE ct);
|
||||||
100
csgo2/VTHook.h
Normal file
100
csgo2/VTHook.h
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "pch.h"
|
||||||
|
class VTHook
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VTHook()
|
||||||
|
{
|
||||||
|
memset( this, 0, sizeof( VTHook) );
|
||||||
|
}
|
||||||
|
|
||||||
|
VTHook( PDWORD64* ppdwClassBase )
|
||||||
|
{
|
||||||
|
bInitialize( ppdwClassBase );
|
||||||
|
}
|
||||||
|
|
||||||
|
~VTHook()
|
||||||
|
{
|
||||||
|
UnHook();
|
||||||
|
}
|
||||||
|
void ClearClassBase()
|
||||||
|
{
|
||||||
|
m_ClassBase = NULL;
|
||||||
|
}
|
||||||
|
bool bInitialize( PDWORD64* ppdwClassBase )
|
||||||
|
{
|
||||||
|
m_ClassBase = ppdwClassBase;
|
||||||
|
m_OldVT = *ppdwClassBase;
|
||||||
|
m_VTSize = GetVTCount( *ppdwClassBase );
|
||||||
|
m_NewVT = new DWORD64[ m_VTSize ];
|
||||||
|
memcpy( m_NewVT, m_OldVT, sizeof( DWORD64) * m_VTSize );
|
||||||
|
*ppdwClassBase = m_NewVT;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bInitialize( PDWORD64** pppdwClassBase ) // fix for pp
|
||||||
|
{
|
||||||
|
return bInitialize( *pppdwClassBase );
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnHook()
|
||||||
|
{
|
||||||
|
if( m_ClassBase )
|
||||||
|
{
|
||||||
|
*m_ClassBase = m_OldVT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReHook()
|
||||||
|
{
|
||||||
|
if( m_ClassBase )
|
||||||
|
{
|
||||||
|
*m_ClassBase = m_NewVT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int iGetFuncCount()
|
||||||
|
{
|
||||||
|
return ( int )m_VTSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD64 GetFuncAddress( int Index )
|
||||||
|
{
|
||||||
|
if( Index >= 0 && Index <= ( int )m_VTSize && m_OldVT != NULL )
|
||||||
|
{
|
||||||
|
return m_OldVT[ Index ];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDWORD64 GetOldVT()
|
||||||
|
{
|
||||||
|
return m_OldVT;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD64 HookFunction( DWORD64 dwNewFunc, unsigned int iIndex )
|
||||||
|
{
|
||||||
|
if( m_NewVT && m_OldVT && iIndex <= m_VTSize && iIndex >= 0 )
|
||||||
|
{
|
||||||
|
m_NewVT[ iIndex ] = dwNewFunc;
|
||||||
|
return m_OldVT[ iIndex ];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DWORD64 GetVTCount( PDWORD64 pdwVMT )
|
||||||
|
{
|
||||||
|
DWORD64 dwIndex = 0;
|
||||||
|
|
||||||
|
while (IsBadCodePtr((FARPROC)pdwVMT[dwIndex]) == false) {
|
||||||
|
dwIndex++;
|
||||||
|
}
|
||||||
|
return dwIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDWORD64* m_ClassBase;
|
||||||
|
PDWORD64 m_NewVT, m_OldVT;
|
||||||
|
DWORD64 m_VTSize;
|
||||||
|
};
|
||||||
4
csgo2/cpp.hint
Normal file
4
csgo2/cpp.hint
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
// 提示文件帮助 Visual Studio IDE 解释 Visual C++ 标识符,
|
||||||
|
// 如函数和宏的名称。
|
||||||
|
// 有关详细信息,请参见 https://go.microsoft.com/fwlink/?linkid=865984
|
||||||
|
#define SCHEMA_FIELD(type, varName) SCHEMA_FIELD_OFFSET(type, varName, 0)
|
||||||
234
csgo2/csgo2.vcxproj
Normal file
234
csgo2/csgo2.vcxproj
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<ProjectGuid>{0af170b6-cc8d-4a56-9879-5064f3d3ebdb}</ProjectGuid>
|
||||||
|
<RootNamespace>csgo2</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;CSGO2_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableUAC>false</EnableUAC>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;CSGO2_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableUAC>false</EnableUAC>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;CSGO2_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableUAC>false</EnableUAC>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;CSGO2_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableUAC>false</EnableUAC>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="events.h" />
|
||||||
|
<ClInclude Include="framework.h" />
|
||||||
|
<ClInclude Include="global.h" />
|
||||||
|
<ClInclude Include="hooks.h" />
|
||||||
|
<ClInclude Include="interface.h" />
|
||||||
|
<ClInclude Include="math\types\vector.hpp" />
|
||||||
|
<ClInclude Include="math\types\vmatrix.hpp" />
|
||||||
|
<ClInclude Include="memory.h" />
|
||||||
|
<ClInclude Include="MinHook\include\MinHook.h" />
|
||||||
|
<ClInclude Include="MinHook\src\buffer.h" />
|
||||||
|
<ClInclude Include="MinHook\src\HDE\hde32.h" />
|
||||||
|
<ClInclude Include="MinHook\src\HDE\hde64.h" />
|
||||||
|
<ClInclude Include="MinHook\src\HDE\pstdint.h" />
|
||||||
|
<ClInclude Include="MinHook\src\HDE\table32.h" />
|
||||||
|
<ClInclude Include="MinHook\src\HDE\table64.h" />
|
||||||
|
<ClInclude Include="MinHook\src\trampoline.h" />
|
||||||
|
<ClInclude Include="module.h" />
|
||||||
|
<ClInclude Include="native_sdk\cgameentitysystem.h" />
|
||||||
|
<ClInclude Include="native_sdk\cgameresourceserviceserver.h" />
|
||||||
|
<ClInclude Include="native_sdk\cschemasystem.h" />
|
||||||
|
<ClInclude Include="native_sdk\entity\cbaseentity.h" />
|
||||||
|
<ClInclude Include="native_sdk\entity\cbaseplayercontroller.h" />
|
||||||
|
<ClInclude Include="native_sdk\handle\handle.h" />
|
||||||
|
<ClInclude Include="offset.h" />
|
||||||
|
<ClInclude Include="pch.h" />
|
||||||
|
<ClInclude Include="player.h" />
|
||||||
|
<ClInclude Include="schema.h" />
|
||||||
|
<ClInclude Include="sdk\convar\convar.hpp" />
|
||||||
|
<ClInclude Include="sdk\gameevent\IGameEvent.h" />
|
||||||
|
<ClInclude Include="sdk\handle\basehandle.h" />
|
||||||
|
<ClInclude Include="sdk\interfaces\interfaces.h" />
|
||||||
|
<ClInclude Include="sdk\player\player.h" />
|
||||||
|
<ClInclude Include="sdk\player\playerslot.h" />
|
||||||
|
<ClInclude Include="sdk\public\eiface.h" />
|
||||||
|
<ClInclude Include="sdk\public\IAppSystem.h" />
|
||||||
|
<ClInclude Include="sdk\sdk.h" />
|
||||||
|
<ClInclude Include="sdk\tier1\bufferstring.h" />
|
||||||
|
<ClInclude Include="sdk\tier1\UtlMemory.hpp" />
|
||||||
|
<ClInclude Include="sdk\tier1\UtlString.hpp" />
|
||||||
|
<ClInclude Include="sdk\tier1\UtlVector.hpp" />
|
||||||
|
<ClInclude Include="stb.hh" />
|
||||||
|
<ClInclude Include="vmt.h" />
|
||||||
|
<ClInclude Include="VTHook.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="dllmain.cpp" />
|
||||||
|
<ClCompile Include="events.cpp" />
|
||||||
|
<ClCompile Include="global.cpp" />
|
||||||
|
<ClCompile Include="hooks.cpp" />
|
||||||
|
<ClCompile Include="interface.cpp" />
|
||||||
|
<ClCompile Include="memory.cpp" />
|
||||||
|
<ClCompile Include="MinHook\src\buffer.c" />
|
||||||
|
<ClCompile Include="MinHook\src\HDE\hde32.c" />
|
||||||
|
<ClCompile Include="MinHook\src\HDE\hde64.c" />
|
||||||
|
<ClCompile Include="MinHook\src\hook.c" />
|
||||||
|
<ClCompile Include="MinHook\src\trampoline.c" />
|
||||||
|
<ClCompile Include="native_sdk\cgameentitysystem.cpp" />
|
||||||
|
<ClCompile Include="native_sdk\cschemasystem.cpp" />
|
||||||
|
<ClCompile Include="native_sdk\handle\handle.cpp" />
|
||||||
|
<ClCompile Include="offset.cpp" />
|
||||||
|
<ClCompile Include="pch.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="player.cpp" />
|
||||||
|
<ClCompile Include="schema.cpp" />
|
||||||
|
<ClCompile Include="sdk\convar\convar.cpp" />
|
||||||
|
<ClCompile Include="sdk\tier1\UtlString.cpp" />
|
||||||
|
<ClCompile Include="vmt.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="cpp.hint" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
||||||
282
csgo2/csgo2.vcxproj.filters
Normal file
282
csgo2/csgo2.vcxproj.filters
Normal file
@@ -0,0 +1,282 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="源文件">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="资源文件">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件\minhook">
|
||||||
|
<UniqueIdentifier>{89393917-f155-4ae6-9e03-2529967f88c3}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件\sdk">
|
||||||
|
<UniqueIdentifier>{88318acc-d490-446b-8333-f20a22d748a6}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件\math">
|
||||||
|
<UniqueIdentifier>{aed2a097-5c17-4c61-a5de-65cde80a84a4}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件\memory">
|
||||||
|
<UniqueIdentifier>{c3ddaa59-6f23-48e1-b43c-03e626960a5e}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="源文件\memory">
|
||||||
|
<UniqueIdentifier>{d8b32656-ba7f-49d3-be6d-c97f9bc02ba0}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件\sdk\gameevent">
|
||||||
|
<UniqueIdentifier>{87180362-2725-4f7b-a702-17cb8cff94d3}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件\sdk\handle">
|
||||||
|
<UniqueIdentifier>{8ce5a064-6e56-4bfb-9c12-b6da38016dbc}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件\sdk\player">
|
||||||
|
<UniqueIdentifier>{b8db59a4-0a74-4cd8-9f3d-5e30e04a52f3}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件\events">
|
||||||
|
<UniqueIdentifier>{a4fd0778-933c-4ac7-a724-70b62977c3f9}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="源文件\events">
|
||||||
|
<UniqueIdentifier>{341ff6a7-81b6-4c44-9d66-ac9c4fbe8684}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件\sdk\interfaces">
|
||||||
|
<UniqueIdentifier>{76acdb22-3f64-4cf6-8447-986ab46533ae}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="源文件\native_sdk">
|
||||||
|
<UniqueIdentifier>{c28f9f29-7571-4821-9cbd-11f27692566a}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="源文件\native_sdk\interfaces">
|
||||||
|
<UniqueIdentifier>{e26bdf5e-ad8d-4ed2-965c-1fdb958a6098}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件\native_sdk">
|
||||||
|
<UniqueIdentifier>{c5938a38-9035-4f7a-952c-156a8549bb54}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件\native_sdk\interfaces">
|
||||||
|
<UniqueIdentifier>{ec02337e-1abc-42a9-b29c-355278bf4bf2}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="源文件\native_sdk\entity">
|
||||||
|
<UniqueIdentifier>{6c9da4be-92c5-4504-8c46-ab0cc612bfe5}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件\native_sdk\entity">
|
||||||
|
<UniqueIdentifier>{f1101bd0-b17e-4c9e-87f1-e34d97979e77}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件\native_sdk\handle">
|
||||||
|
<UniqueIdentifier>{63beb427-0b96-4062-83e0-752efb2ed5f0}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="源文件\native_sdk\handle">
|
||||||
|
<UniqueIdentifier>{68556c7c-97c0-4e1e-82f0-e4b45b9ad40d}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件\sdk\convar">
|
||||||
|
<UniqueIdentifier>{befb97b4-a3ba-48a8-84a8-c36a74d2d48c}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件\sdk\tier1">
|
||||||
|
<UniqueIdentifier>{a403d20d-862c-4c26-965b-9cc23e67745f}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件\sdk\public">
|
||||||
|
<UniqueIdentifier>{c359acb2-cc33-4be0-b5dd-3dfef50ba594}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="framework.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="pch.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="MinHook\include\MinHook.h">
|
||||||
|
<Filter>头文件\minhook</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="MinHook\src\buffer.h">
|
||||||
|
<Filter>头文件\minhook</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="MinHook\src\trampoline.h">
|
||||||
|
<Filter>头文件\minhook</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="MinHook\src\HDE\hde32.h">
|
||||||
|
<Filter>头文件\minhook</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="MinHook\src\HDE\hde64.h">
|
||||||
|
<Filter>头文件\minhook</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="MinHook\src\HDE\pstdint.h">
|
||||||
|
<Filter>头文件\minhook</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="MinHook\src\HDE\table32.h">
|
||||||
|
<Filter>头文件\minhook</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="MinHook\src\HDE\table64.h">
|
||||||
|
<Filter>头文件\minhook</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="interface.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="stb.hh">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="math\types\vector.hpp">
|
||||||
|
<Filter>头文件\math</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="math\types\vmatrix.hpp">
|
||||||
|
<Filter>头文件\math</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="global.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="vmt.h">
|
||||||
|
<Filter>头文件\memory</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="memory.h">
|
||||||
|
<Filter>头文件\memory</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="hooks.h">
|
||||||
|
<Filter>头文件\memory</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="module.h">
|
||||||
|
<Filter>头文件\memory</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="offset.h">
|
||||||
|
<Filter>头文件\memory</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\sdk.h">
|
||||||
|
<Filter>头文件\sdk</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\gameevent\IGameEvent.h">
|
||||||
|
<Filter>头文件\sdk\gameevent</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\handle\basehandle.h">
|
||||||
|
<Filter>头文件\sdk\handle</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\player\playerslot.h">
|
||||||
|
<Filter>头文件\sdk\player</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\player\player.h">
|
||||||
|
<Filter>头文件\sdk\player</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="events.h">
|
||||||
|
<Filter>头文件\events</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\interfaces\interfaces.h">
|
||||||
|
<Filter>头文件\sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="schema.h">
|
||||||
|
<Filter>头文件\native_sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="native_sdk\cschemasystem.h">
|
||||||
|
<Filter>头文件\native_sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="native_sdk\cgameentitysystem.h">
|
||||||
|
<Filter>头文件\native_sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="native_sdk\entity\cbaseentity.h">
|
||||||
|
<Filter>头文件\native_sdk\entity</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="VTHook.h">
|
||||||
|
<Filter>头文件\memory</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="native_sdk\entity\cbaseplayercontroller.h">
|
||||||
|
<Filter>头文件\native_sdk\entity</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="native_sdk\handle\handle.h">
|
||||||
|
<Filter>头文件\native_sdk\handle</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="player.h">
|
||||||
|
<Filter>头文件\native_sdk\entity</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="native_sdk\cgameresourceserviceserver.h">
|
||||||
|
<Filter>头文件\native_sdk\interfaces</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\convar\convar.hpp">
|
||||||
|
<Filter>头文件\sdk\convar</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\tier1\UtlMemory.hpp">
|
||||||
|
<Filter>头文件\sdk\tier1</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\tier1\UtlString.hpp">
|
||||||
|
<Filter>头文件\sdk\tier1</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\tier1\UtlVector.hpp">
|
||||||
|
<Filter>头文件\sdk\tier1</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\public\eiface.h">
|
||||||
|
<Filter>头文件\sdk\public</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\public\IAppSystem.h">
|
||||||
|
<Filter>头文件\sdk\public</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="sdk\tier1\bufferstring.h">
|
||||||
|
<Filter>头文件\sdk\tier1</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="dllmain.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="pch.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="MinHook\src\buffer.c">
|
||||||
|
<Filter>头文件\minhook</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="MinHook\src\hook.c">
|
||||||
|
<Filter>头文件\minhook</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="MinHook\src\trampoline.c">
|
||||||
|
<Filter>头文件\minhook</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="MinHook\src\HDE\hde32.c">
|
||||||
|
<Filter>头文件\minhook</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="MinHook\src\HDE\hde64.c">
|
||||||
|
<Filter>头文件\minhook</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="interface.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="global.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="offset.cpp">
|
||||||
|
<Filter>源文件\memory</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="memory.cpp">
|
||||||
|
<Filter>源文件\memory</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="hooks.cpp">
|
||||||
|
<Filter>源文件\memory</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="events.cpp">
|
||||||
|
<Filter>源文件\events</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="schema.cpp">
|
||||||
|
<Filter>源文件\native_sdk\interfaces</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="vmt.cpp">
|
||||||
|
<Filter>源文件\memory</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="native_sdk\cschemasystem.cpp">
|
||||||
|
<Filter>源文件\native_sdk\interfaces</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="native_sdk\cgameentitysystem.cpp">
|
||||||
|
<Filter>源文件\native_sdk\interfaces</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="player.cpp">
|
||||||
|
<Filter>源文件\native_sdk\entity</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="native_sdk\handle\handle.cpp">
|
||||||
|
<Filter>源文件\native_sdk\handle</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="sdk\convar\convar.cpp">
|
||||||
|
<Filter>头文件\sdk\convar</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="sdk\tier1\UtlString.cpp">
|
||||||
|
<Filter>头文件\sdk\tier1</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="cpp.hint" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
62
csgo2/dllmain.cpp
Normal file
62
csgo2/dllmain.cpp
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
// dllmain.cpp : 定义 DLL 应用程序的入口点。
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
auto unload() -> void {
|
||||||
|
hooks::unload();
|
||||||
|
LOG("unload \n");
|
||||||
|
}
|
||||||
|
auto WatchExitThread(void *ctx) -> void {
|
||||||
|
while (true) {
|
||||||
|
if (GetAsyncKeyState(VK_END) & 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Sleep(100);
|
||||||
|
}
|
||||||
|
global::Exit = true;
|
||||||
|
unload();
|
||||||
|
}
|
||||||
|
auto init(void* ctx) -> bool {
|
||||||
|
AllocConsole();
|
||||||
|
SetConsoleTitleA("huoji debug console");
|
||||||
|
freopen_s(reinterpret_cast<FILE**> stdout, "CONOUT$", "w", stdout);
|
||||||
|
CreateThread(NULL, 0,
|
||||||
|
reinterpret_cast<LPTHREAD_START_ROUTINE>(WatchExitThread),
|
||||||
|
NULL, 0, NULL);
|
||||||
|
|
||||||
|
while (Offset::Module_tier0 == 0)
|
||||||
|
{
|
||||||
|
if (global::Exit) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Offset::Module_tier0 = reinterpret_cast<uint64_t>(GetModuleHandleA("tier0"));
|
||||||
|
Sleep(200);
|
||||||
|
}
|
||||||
|
if (Offset::Init() == false) {
|
||||||
|
LOG("Offset::Init() == false !\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LOG("hacked by huoji 2023.9.14 \n");
|
||||||
|
bool isSuccess = false;
|
||||||
|
isSuccess = hooks::init();
|
||||||
|
if (isSuccess) {
|
||||||
|
LOG("plugin install success !\n");
|
||||||
|
}
|
||||||
|
return isSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call,
|
||||||
|
LPVOID lpReserved) {
|
||||||
|
bool result = true;
|
||||||
|
switch (ul_reason_for_call) {
|
||||||
|
case DLL_PROCESS_ATTACH:
|
||||||
|
CreateThread(NULL, 0,
|
||||||
|
reinterpret_cast<LPTHREAD_START_ROUTINE>(init),
|
||||||
|
NULL, 0, NULL);
|
||||||
|
break;
|
||||||
|
case DLL_THREAD_ATTACH:
|
||||||
|
case DLL_THREAD_DETACH:
|
||||||
|
case DLL_PROCESS_DETACH:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
28
csgo2/events.cpp
Normal file
28
csgo2/events.cpp
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#include "events.h"
|
||||||
|
#include "native_sdk/entity/cbaseplayercontroller.h"
|
||||||
|
#include "player.h"
|
||||||
|
namespace events {
|
||||||
|
auto OnPlayerDeathEvent(IGameEvent* event) -> void {
|
||||||
|
UnkGameEventStruct_t userIdNameParams{ "userid" };
|
||||||
|
UnkGameEventStruct_t attackerNameParams{ "attacker" };
|
||||||
|
|
||||||
|
const auto victim = reinterpret_cast<CCSPlayerController*>(event->GetPlayerPawn(&userIdNameParams));
|
||||||
|
const auto attacker = reinterpret_cast<CCSPlayerController*>(event->GetPlayerPawn(&attackerNameParams));
|
||||||
|
auto victimName = &victim->m_iszPlayerName();
|
||||||
|
//victimBasePlayer->ForceRespawn();
|
||||||
|
printf("victim %s\n", victimName);
|
||||||
|
printf("attacker %s\n", attacker->m_iszPlayerName());
|
||||||
|
|
||||||
|
}
|
||||||
|
auto OnPlayerChat(IGameEvent* event) -> void
|
||||||
|
{
|
||||||
|
UnkGameEventStruct_t userIdNameParams{ "userid" };
|
||||||
|
const auto chater = reinterpret_cast<CCSPlayerController*>(event->GetPlayer(&userIdNameParams));
|
||||||
|
const auto text = event->GetString("text");
|
||||||
|
const auto chaterName = chater->m_iszPlayerName();
|
||||||
|
|
||||||
|
LOG("player: %s say: %s \n", chaterName, text);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
8
csgo2/events.h
Normal file
8
csgo2/events.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "pch.h"
|
||||||
|
#include "sdk/gameevent/IGameEvent.h"
|
||||||
|
|
||||||
|
namespace events {
|
||||||
|
auto OnPlayerDeathEvent(IGameEvent* event) -> void;
|
||||||
|
auto OnPlayerChat(IGameEvent* event) -> void;
|
||||||
|
}
|
||||||
5
csgo2/framework.h
Normal file
5
csgo2/framework.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容
|
||||||
|
// Windows 头文件
|
||||||
|
#include <windows.h>
|
||||||
4
csgo2/global.cpp
Normal file
4
csgo2/global.cpp
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#include "global.h"
|
||||||
|
namespace global {
|
||||||
|
bool Exit;
|
||||||
|
}
|
||||||
5
csgo2/global.h
Normal file
5
csgo2/global.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "pch.h"
|
||||||
|
namespace global {
|
||||||
|
extern bool Exit;
|
||||||
|
}
|
||||||
15
csgo2/hash_fnv1a_constexpr.h
Normal file
15
csgo2/hash_fnv1a_constexpr.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// FNV1a c++11 constexpr compile time hash functions, 32 and 64 bit
|
||||||
|
// str should be a null terminated string literal, value should be left out
|
||||||
|
// e.g hash_32_fnv1a_const("example")
|
||||||
|
// code license: public domain or equivalent
|
||||||
|
// post: https://notes.underscorediscovery.com/constexpr-fnv1a/
|
||||||
|
|
||||||
|
constexpr uint32_t val_32_const = 0x811c9dc5;
|
||||||
|
constexpr uint32_t prime_32_const = 0x1000193;
|
||||||
|
|
||||||
|
inline constexpr uint32_t hash_32_fnv1a_const(const char* const str, const uint32_t value = val_32_const) noexcept {
|
||||||
|
return (str[0] == '\0') ? value : hash_32_fnv1a_const(&str[1], (value ^ uint32_t(str[0])) * prime_32_const);
|
||||||
|
}
|
||||||
120
csgo2/hooks.cpp
Normal file
120
csgo2/hooks.cpp
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
#include "hooks.h"
|
||||||
|
#include "native_sdk/entity/cbaseentity.h"
|
||||||
|
#include "sdk/convar/convar.hpp"
|
||||||
|
FireEventServerSide_t original_FireEventServerSide = NULL;
|
||||||
|
OnClientConnect_t original_OnClientConnected = NULL;
|
||||||
|
Host_Say_t original_Host_Say = NULL;
|
||||||
|
|
||||||
|
namespace hooks {
|
||||||
|
VTHook* HIServerGameClient;
|
||||||
|
bool __fastcall hook_OnClientConnected(CPlayerSlot slot, const char* pszName, uint64_t xuid, const char* pszNetworkID, bool unk1, CBufferString* pRejectReason)
|
||||||
|
{
|
||||||
|
LOG("Hook_OnClientConnected(%d, \"%s\", %d, \"%s\")\n", slot, pszName, xuid, pszNetworkID);
|
||||||
|
return original_OnClientConnected(slot, pszName, xuid, pszNetworkID, unk1, pRejectReason);
|
||||||
|
}
|
||||||
|
void __fastcall hook_Host_Say(void* pEntity, void* args, bool teamonly, int unk1, const char* unk2)
|
||||||
|
{
|
||||||
|
const auto theArgs = reinterpret_cast<CCommand*>(args);
|
||||||
|
const auto theEntity = reinterpret_cast<CBaseEntity*>(pEntity);
|
||||||
|
char* pos = nullptr;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (theArgs == nullptr || theEntity == nullptr) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto message = std::string(theArgs->GetCommandString());
|
||||||
|
printf("messageNoZero: %s \n", message.c_str());
|
||||||
|
} while (false);
|
||||||
|
/*
|
||||||
|
if (*pMessage == '!' || *pMessage == '/')
|
||||||
|
ParseChatCommand(pMessage, pEntity);
|
||||||
|
|
||||||
|
if (*pMessage == '/')
|
||||||
|
return;
|
||||||
|
*/
|
||||||
|
return original_Host_Say(pEntity, args, teamonly, unk1, unk2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __fastcall hook_FireEventServerSide(CGameEventManager* rcx, IGameEvent* event,
|
||||||
|
bool serverSide) {
|
||||||
|
do {
|
||||||
|
if (!event) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* eventName = event->GetName();
|
||||||
|
if (!eventName) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
static constexpr auto player_death =
|
||||||
|
hash_32_fnv1a_const("player_death");
|
||||||
|
static constexpr auto player_chat =
|
||||||
|
hash_32_fnv1a_const("player_chat");
|
||||||
|
switch (hash_32_fnv1a_const(eventName))
|
||||||
|
{
|
||||||
|
case player_death:
|
||||||
|
events::OnPlayerDeathEvent(event);
|
||||||
|
break;
|
||||||
|
//V<><56>bug,<2C>ⲻ<EFBFBD><E2B2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
/*
|
||||||
|
case player_chat:
|
||||||
|
events::OnPlayerChat(event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (false);
|
||||||
|
return original_FireEventServerSide(rcx, event, serverSide);
|
||||||
|
}
|
||||||
|
auto initMinHook() -> bool {
|
||||||
|
bool isSuccess = false;
|
||||||
|
// <20><>ʼ<EFBFBD><CABC>MiniHook
|
||||||
|
do {
|
||||||
|
if (MH_Initialize() != MH_OK) {
|
||||||
|
LOG("MH_Initialize() != MH_OK\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
if (MH_CreateHook((LPVOID)Offset::FireEventServerSidePtr,
|
||||||
|
&hook_FireEventServerSide,
|
||||||
|
reinterpret_cast<LPVOID*>(
|
||||||
|
&original_FireEventServerSide)) != MH_OK) {
|
||||||
|
LOG("MH_CreateHook original_FireEventServerSide\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (MH_CreateHook((LPVOID)Offset::Host_SayPtr,
|
||||||
|
&hook_Host_Say,
|
||||||
|
reinterpret_cast<LPVOID*>(
|
||||||
|
&original_Host_Say)) != MH_OK) {
|
||||||
|
LOG("MH_CreateHook original_Host_Say\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// <20><><EFBFBD>ù<EFBFBD><C3B9><EFBFBD>
|
||||||
|
if (MH_EnableHook(MH_ALL_HOOKS) != MH_OK) {
|
||||||
|
LOG("MH_EnableHook \n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
isSuccess = true;
|
||||||
|
} while (false);
|
||||||
|
return isSuccess;
|
||||||
|
|
||||||
|
}
|
||||||
|
auto initVmtHook() -> bool {
|
||||||
|
|
||||||
|
HIServerGameClient = new VTHook((DWORD64**)Offset::InterFaces::IServerGameClient);
|
||||||
|
original_OnClientConnected = (OnClientConnect_t)HIServerGameClient->HookFunction((DWORD64)hook_OnClientConnected, 1);
|
||||||
|
return original_OnClientConnected != nullptr;
|
||||||
|
}
|
||||||
|
auto init() -> bool {
|
||||||
|
bool isSuccess = initMinHook() && initVmtHook();
|
||||||
|
//bool isSuccess = initVmtHook();
|
||||||
|
return isSuccess;
|
||||||
|
}
|
||||||
|
auto unload() -> void
|
||||||
|
{
|
||||||
|
MH_DisableHook(MH_ALL_HOOKS);
|
||||||
|
MH_RemoveHook(MH_ALL_HOOKS);
|
||||||
|
MH_Uninitialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
15
csgo2/hooks.h
Normal file
15
csgo2/hooks.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "pch.h"
|
||||||
|
#include "sdk/gameevent/IGameEvent.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef bool(__fastcall* FireEventServerSide_t)(CGameEventManager*, IGameEvent*, bool);
|
||||||
|
typedef void(__fastcall* Host_Say_t)(void*, void*, bool, int, const char*);
|
||||||
|
typedef bool(__fastcall* OnClientConnect_t)(CPlayerSlot, const char*, uint64_t, const char*, bool unk1, CBufferString*);
|
||||||
|
|
||||||
|
extern FireEventServerSide_t original_FireEventServerSide;
|
||||||
|
extern Host_Say_t original_Host_Say;
|
||||||
|
namespace hooks {
|
||||||
|
auto init() -> bool;
|
||||||
|
auto unload() -> void;
|
||||||
|
}
|
||||||
4
csgo2/interface.cpp
Normal file
4
csgo2/interface.cpp
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
namespace interfaces {
|
||||||
|
|
||||||
|
} // namespace interfaces
|
||||||
5
csgo2/interface.h
Normal file
5
csgo2/interface.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "pch.h"
|
||||||
|
namespace interfaces {
|
||||||
|
|
||||||
|
} // namespace interfaces
|
||||||
0
csgo2/memory.cpp
Normal file
0
csgo2/memory.cpp
Normal file
18
csgo2/memory.h
Normal file
18
csgo2/memory.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "pch.h"
|
||||||
|
namespace Memory {
|
||||||
|
template<class T>
|
||||||
|
void write(uintptr_t address, T value)
|
||||||
|
{
|
||||||
|
WriteProcessMemory(GetCurrentProcess(), (void*)address, &value, sizeof(T), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
T read(uintptr_t address)
|
||||||
|
{
|
||||||
|
T buffer{};
|
||||||
|
ReadProcessMemory(GetCurrentProcess(), (void*)address, &buffer, sizeof(T), 0);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
146
csgo2/module.h
Normal file
146
csgo2/module.h
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "pch.h"
|
||||||
|
#define IS_WINDOWS 1
|
||||||
|
class InterfaceReg;
|
||||||
|
// Pointer arithmetic utility class.
|
||||||
|
struct UTILPtr {
|
||||||
|
public:
|
||||||
|
template <typename T>
|
||||||
|
UTILPtr(T val) {
|
||||||
|
m_val = (uintptr_t)(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T = void*>
|
||||||
|
T Get(const char* variableName = nullptr) {
|
||||||
|
#ifdef CS2_SDK_ENABLE_LOGGING
|
||||||
|
if (variableName) LOG("%s found at -> %llX\n", variableName, m_val);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (T)(m_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void Get(T& dst, const char* variableName = nullptr) {
|
||||||
|
dst = Get<T>(variableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
UTILPtr& AddOffset(int offset) {
|
||||||
|
if (m_val) m_val += offset;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
UTILPtr& ToAbsolute(int preOffset, int postOffset) {
|
||||||
|
if (m_val) {
|
||||||
|
AddOffset(preOffset);
|
||||||
|
m_val = m_val + sizeof(int) + *(int*)(m_val);
|
||||||
|
AddOffset(postOffset);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
UTILPtr& Dereference(int dereferences) {
|
||||||
|
if (m_val)
|
||||||
|
while (dereferences-- != 0) m_val = *(uintptr_t*)(m_val);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValid() { return m_val != 0; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uintptr_t m_val;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CModule {
|
||||||
|
public:
|
||||||
|
// CS2TODO: Maybe write a simple caching system
|
||||||
|
|
||||||
|
CModule(CModule&&) = delete;
|
||||||
|
CModule(const CModule&) = delete;
|
||||||
|
|
||||||
|
explicit CModule(const char* name) : m_name(name) { this->Load(); }
|
||||||
|
|
||||||
|
void Load() {
|
||||||
|
this->InitializeHandle();
|
||||||
|
this->InitializeBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
UTILPtr GetProcAddress(const char* procName) const {
|
||||||
|
UTILPtr rv = 0;
|
||||||
|
if (this->IsLoaded()) {
|
||||||
|
#ifdef IS_WINDOWS
|
||||||
|
rv = ::GetProcAddress(static_cast<HMODULE>(this->m_handle),
|
||||||
|
procName);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
UTILPtr FindInterface(const char* version) const {
|
||||||
|
UTILPtr rv = 0;
|
||||||
|
if (this->IsLoaded()) {
|
||||||
|
UTILPtr pCreateInterface = this->GetProcAddress("CreateInterface");
|
||||||
|
if (!pCreateInterface.IsValid()) return rv;
|
||||||
|
|
||||||
|
InterfaceReg* s_pInterfaceRegs = pCreateInterface.ToAbsolute(3, 0)
|
||||||
|
.Dereference(1)
|
||||||
|
.Get<InterfaceReg*>();
|
||||||
|
|
||||||
|
for (; s_pInterfaceRegs;
|
||||||
|
s_pInterfaceRegs = s_pInterfaceRegs->m_pNext) {
|
||||||
|
if (strcmp(version, s_pInterfaceRegs->m_pName) == 0) {
|
||||||
|
rv = s_pInterfaceRegs->m_CreateFn();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
template <size_t N>
|
||||||
|
UTILPtr FindPattern(const std::array<int, N>& signature) const {
|
||||||
|
UTILPtr rv = 0;
|
||||||
|
if (this->IsLoaded()) {
|
||||||
|
const int* pSigData = signature.data();
|
||||||
|
uint8_t* pBytes = reinterpret_cast<uint8_t*>(this->m_start);
|
||||||
|
for (size_t i = 0; i < this->m_end - N; ++i) {
|
||||||
|
bool found = true;
|
||||||
|
for (size_t j = 0; j < N; ++j) {
|
||||||
|
if (pBytes[i + j] != pSigData[j] && pSigData[j] != -1) {
|
||||||
|
found = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
rv = reinterpret_cast<uintptr_t>(&pBytes[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
const char* GetName() const { return this->m_name; }
|
||||||
|
bool IsLoaded() const { return this->m_handle != 0; }
|
||||||
|
void* GetBase() const { return this->m_handle; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void InitializeHandle() {
|
||||||
|
#ifdef IS_WINDOWS
|
||||||
|
this->m_handle = static_cast<void*>(GetModuleHandleA(this->GetName()));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
void InitializeBounds() {
|
||||||
|
if (!this->IsLoaded()) return;
|
||||||
|
|
||||||
|
#ifdef IS_WINDOWS
|
||||||
|
MODULEINFO mi;
|
||||||
|
BOOL status = GetModuleInformation(GetCurrentProcess(),
|
||||||
|
static_cast<HMODULE>(this->m_handle),
|
||||||
|
&mi, sizeof(mi));
|
||||||
|
if (status != 0) {
|
||||||
|
this->m_start = reinterpret_cast<uintptr_t>(this->m_handle);
|
||||||
|
this->m_end = static_cast<uintptr_t>(mi.SizeOfImage);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void* m_handle = nullptr;
|
||||||
|
uintptr_t m_start = 0, m_end = 0;
|
||||||
|
const char* m_name = "";
|
||||||
|
};
|
||||||
6
csgo2/native_sdk/cgameentitysystem.cpp
Normal file
6
csgo2/native_sdk/cgameentitysystem.cpp
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#include "cgameentitysystem.h"
|
||||||
|
#include "../pch.h"
|
||||||
|
|
||||||
|
CGameEntitySystem* CGameEntitySystem::GetInstance(){
|
||||||
|
return Offset::InterFaces::GameResourceServiceServer->GetGameEntitySystem();
|
||||||
|
}
|
||||||
63
csgo2/native_sdk/cgameentitysystem.h
Normal file
63
csgo2/native_sdk/cgameentitysystem.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "entity/cbaseentity.h"
|
||||||
|
|
||||||
|
#define MAX_ENTITIES_IN_LIST 512
|
||||||
|
#define MAX_ENTITY_LISTS 64
|
||||||
|
#define MAX_TOTAL_ENTITIES MAX_ENTITIES_IN_LIST *MAX_ENTITY_LISTS
|
||||||
|
|
||||||
|
class CEntityIdentity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CBaseEntity *entity;
|
||||||
|
void *dunno;
|
||||||
|
int64_t unk0;
|
||||||
|
int64_t unk1;
|
||||||
|
const char *internalName;
|
||||||
|
const char *entityName;
|
||||||
|
void *unk2;
|
||||||
|
void *unk3;
|
||||||
|
void *unk4;
|
||||||
|
void *unk5;
|
||||||
|
CEntityIdentity *prevValid;
|
||||||
|
CEntityIdentity *nextValid;
|
||||||
|
void *unkptr;
|
||||||
|
void *unkptr2;
|
||||||
|
void *unkptr3;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CEntityIdentities
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CEntityIdentity m_pIdentities[MAX_ENTITIES_IN_LIST];
|
||||||
|
};
|
||||||
|
|
||||||
|
class EntityIdentityList
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CEntityIdentities *m_pIdentityList;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CGameEntitySystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void n_0();
|
||||||
|
void *unk;
|
||||||
|
CEntityIdentities *m_pEntityList[MAX_ENTITY_LISTS];
|
||||||
|
|
||||||
|
CBaseEntity *GetBaseEntity(int index)
|
||||||
|
{
|
||||||
|
if (index <= -1 || index >= MAX_TOTAL_ENTITIES)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
int listToUse = (index / MAX_ENTITIES_IN_LIST);
|
||||||
|
if (!m_pEntityList[listToUse])
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (m_pEntityList[listToUse]->m_pIdentities[index % MAX_ENTITIES_IN_LIST].entity)
|
||||||
|
return m_pEntityList[listToUse]->m_pIdentities[index % MAX_ENTITIES_IN_LIST].entity;
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CGameEntitySystem *GetInstance();
|
||||||
|
};
|
||||||
12
csgo2/native_sdk/cgameresourceserviceserver.h
Normal file
12
csgo2/native_sdk/cgameresourceserviceserver.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../pch.h"
|
||||||
|
class CGameEntitySystem;
|
||||||
|
|
||||||
|
class CGameResourceService
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CGameEntitySystem *GetGameEntitySystem()
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<CGameEntitySystem **>((uintptr_t)(this) + 0x58);
|
||||||
|
}
|
||||||
|
};
|
||||||
13
csgo2/native_sdk/cschemasystem.cpp
Normal file
13
csgo2/native_sdk/cschemasystem.cpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include "cschemasystem.h"
|
||||||
|
|
||||||
|
auto CSchemaSystemTypeScope::FindDeclaredClass(const char* pClass) -> SchemaClassInfoData_t*
|
||||||
|
{
|
||||||
|
SchemaClassInfoData_t* rv = nullptr;
|
||||||
|
CALL_VIRTUAL(void, 2, this, &rv, pClass);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto CSchemaSystem::FindTypeScopeForModule(const char* module) -> CSchemaSystemTypeScope*
|
||||||
|
{
|
||||||
|
return CALL_VIRTUAL(CSchemaSystemTypeScope*, 13, this, module, nullptr);
|
||||||
|
}
|
||||||
77
csgo2/native_sdk/cschemasystem.h
Normal file
77
csgo2/native_sdk/cschemasystem.h
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../pch.h"
|
||||||
|
#include "../vmt.h"
|
||||||
|
|
||||||
|
struct SchemaClassFieldData_t
|
||||||
|
{
|
||||||
|
const char *m_name;
|
||||||
|
char pad0[0x8];
|
||||||
|
short m_offset;
|
||||||
|
char pad1[0xE];
|
||||||
|
};
|
||||||
|
|
||||||
|
class SchemaClassInfoData_t;
|
||||||
|
|
||||||
|
struct SchemaBaseClassInfoData_t
|
||||||
|
{
|
||||||
|
unsigned int m_offset;
|
||||||
|
SchemaClassInfoData_t *m_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SchemaClassInfoData_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
auto GetName()
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GetFieldsSize()
|
||||||
|
{
|
||||||
|
return m_align;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GetFields()
|
||||||
|
{
|
||||||
|
return m_fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GetParent()
|
||||||
|
{
|
||||||
|
return m_schema_parent->m_class;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
char pad_0x0000[0x8]; // 0x0000
|
||||||
|
|
||||||
|
const char *m_name; // 0x0008
|
||||||
|
char *m_module; // 0x0010
|
||||||
|
|
||||||
|
int m_size; // 0x0018
|
||||||
|
std::int16_t m_align; // 0x001C
|
||||||
|
|
||||||
|
std::int16_t m_static_size; // 0x001E
|
||||||
|
std::int16_t m_metadata_size; // 0x0020
|
||||||
|
std::int16_t m_i_unk1; // 0x0022
|
||||||
|
std::int16_t m_i_unk2; // 0x0024
|
||||||
|
std::int16_t m_i_unk3; // 0x0026
|
||||||
|
|
||||||
|
SchemaClassFieldData_t *m_fields; // 0x0028
|
||||||
|
|
||||||
|
char pad_0x0030[0x8]; // 0x0030
|
||||||
|
SchemaBaseClassInfoData_t *m_schema_parent; // 0x0038
|
||||||
|
|
||||||
|
char pad_0x0038[0x10]; // 0x0038
|
||||||
|
};
|
||||||
|
|
||||||
|
class CSchemaSystemTypeScope
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
auto FindDeclaredClass(const char* pClass) -> SchemaClassInfoData_t*;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CSchemaSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
auto FindTypeScopeForModule(const char* module) ->CSchemaSystemTypeScope*;
|
||||||
|
};
|
||||||
37
csgo2/native_sdk/entity/cbaseentity.h
Normal file
37
csgo2/native_sdk/entity/cbaseentity.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../schema.h"
|
||||||
|
#include "ccollisionproperty.h"
|
||||||
|
#include "../handle/handle.h"
|
||||||
|
#include "../cgameentitysystem.h"
|
||||||
|
class CEntityIdentity;
|
||||||
|
class CEntityInstance {
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS(CEntityInstance);
|
||||||
|
|
||||||
|
auto Schema_DynamicBinding() {
|
||||||
|
SchemaClassInfoData_t* rv = nullptr;
|
||||||
|
CALL_VIRTUAL(void, 0, this, &rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GetRefEHandle() {
|
||||||
|
CHandle handle;
|
||||||
|
CALL_VIRTUAL(void*, 2, this, &handle);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCHEMA_FIELD(CEntityIdentity*, m_pEntity);
|
||||||
|
SCHEMA_FIELD(const char*, m_designerName);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class CBaseEntity : CEntityInstance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS(CBaseEntity);
|
||||||
|
|
||||||
|
SCHEMA_FIELD(int, m_iHealth)
|
||||||
|
//SCHEMA_FIELD(Vector, m_vecBaseVelocity)
|
||||||
|
SCHEMA_FIELD(CCollisionProperty*, m_pCollision)
|
||||||
|
};
|
||||||
24
csgo2/native_sdk/entity/cbaseplayercontroller.h
Normal file
24
csgo2/native_sdk/entity/cbaseplayercontroller.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../../pch.h"
|
||||||
|
#include "../handle/handle.h"
|
||||||
|
#include "cbaseentity.h"
|
||||||
|
class CBasePlayerController : public CBaseEntity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS(CBasePlayerController);
|
||||||
|
|
||||||
|
SCHEMA_FIELD(uint64_t, m_steamID)
|
||||||
|
SCHEMA_FIELD(CHandle, m_hPawn)
|
||||||
|
SCHEMA_FIELD(char, m_iszPlayerName)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class CCSPlayerController : public CBasePlayerController {
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS(CCSPlayerController)
|
||||||
|
|
||||||
|
SCHEMA_FIELD(uint32_t, m_iPawnHealth)
|
||||||
|
SCHEMA_FIELD(bool, m_bPawnIsAlive)
|
||||||
|
SCHEMA_FIELD(const char*, m_szClanName)
|
||||||
|
|
||||||
|
};
|
||||||
14
csgo2/native_sdk/entity/cbaseplayerpawn.h
Normal file
14
csgo2/native_sdk/entity/cbaseplayerpawn.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cbaseentity.h"
|
||||||
|
#include "services.h"
|
||||||
|
|
||||||
|
class CBasePlayerPawn : public CBaseEntity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS(CBasePlayerPawn);
|
||||||
|
|
||||||
|
SCHEMA_FIELD(CPlayer_MovementServices*, m_pMovementServices)
|
||||||
|
SCHEMA_FIELD(uint8*, m_pWeaponServices)
|
||||||
|
SCHEMA_FIELD(uint8**, m_pItemServices)
|
||||||
|
};
|
||||||
21
csgo2/native_sdk/entity/ccollisionproperty.h
Normal file
21
csgo2/native_sdk/entity/ccollisionproperty.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../../pch.h"
|
||||||
|
#include "../../schema.h"
|
||||||
|
|
||||||
|
struct VPhysicsCollisionAttribute_t
|
||||||
|
{
|
||||||
|
DECLARE_CLASS(VPhysicsCollisionAttribute_t)
|
||||||
|
|
||||||
|
SCHEMA_FIELD(uint8_t, m_nCollisionGroup)
|
||||||
|
};
|
||||||
|
|
||||||
|
class CCollisionProperty
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS(CCollisionProperty)
|
||||||
|
|
||||||
|
SCHEMA_FIELD(VPhysicsCollisionAttribute_t, m_collisionAttribute)
|
||||||
|
//SCHEMA_FIELD(SolidType_t, m_nSolidType)
|
||||||
|
SCHEMA_FIELD(uint8_t, m_usSolidFlags)
|
||||||
|
SCHEMA_FIELD(uint8_t, m_CollisionGroup)
|
||||||
|
};
|
||||||
12
csgo2/native_sdk/entity/ccsplayercontroller.h
Normal file
12
csgo2/native_sdk/entity/ccsplayercontroller.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cbaseplayercontroller.h"
|
||||||
|
#include "services.h"
|
||||||
|
|
||||||
|
class CCSPlayerController : public CBasePlayerController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS(CCSPlayerController);
|
||||||
|
|
||||||
|
SCHEMA_FIELD(CCSPlayerController_InGameMoneyServices*, m_pInGameMoneyServices)
|
||||||
|
};
|
||||||
9
csgo2/native_sdk/entity/ccsplayerpawn.h
Normal file
9
csgo2/native_sdk/entity/ccsplayerpawn.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cbaseplayerpawn.h"
|
||||||
|
|
||||||
|
class CCSPlayerPawn : public CBasePlayerPawn
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS(CCSPlayerPawn);
|
||||||
|
};
|
||||||
18
csgo2/native_sdk/entity/services.h
Normal file
18
csgo2/native_sdk/entity/services.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <platform.h>
|
||||||
|
|
||||||
|
#include "../schema.h"
|
||||||
|
|
||||||
|
class CPlayer_MovementServices
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS(CPlayer_MovementServices);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CCSPlayerController_InGameMoneyServices
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS(CCSPlayerController_InGameMoneyServices);
|
||||||
|
|
||||||
|
SCHEMA_FIELD(int, m_iAccount)
|
||||||
|
};
|
||||||
11
csgo2/native_sdk/handle/handle.cpp
Normal file
11
csgo2/native_sdk/handle/handle.cpp
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#include "handle.h"
|
||||||
|
#include "../cgameentitysystem.h"
|
||||||
|
|
||||||
|
CBaseEntity* CHandle::GetBaseEntity() const
|
||||||
|
{
|
||||||
|
CGameEntitySystem* pEntitySystem = CGameEntitySystem::GetInstance();
|
||||||
|
if (!pEntitySystem)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return pEntitySystem->GetBaseEntity(GetEntryIndex());
|
||||||
|
}
|
||||||
26
csgo2/native_sdk/handle/handle.h
Normal file
26
csgo2/native_sdk/handle/handle.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
#define INVALID_EHANDLE_INDEX 0xFFFFFFFF
|
||||||
|
#define ENT_ENTRY_MASK 0x7FFF
|
||||||
|
|
||||||
|
class CBaseEntity;
|
||||||
|
|
||||||
|
class CHandle
|
||||||
|
{
|
||||||
|
CBaseEntity* GetBaseEntity() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool operator==(CHandle rhs) const { return m_Index == rhs.m_Index; }
|
||||||
|
|
||||||
|
bool IsValid() const { return m_Index != INVALID_EHANDLE_INDEX; }
|
||||||
|
|
||||||
|
int GetEntryIndex() const { return m_Index & ENT_ENTRY_MASK; }
|
||||||
|
|
||||||
|
template <typename T = CBaseEntity>
|
||||||
|
T* Get() const
|
||||||
|
{
|
||||||
|
return reinterpret_cast<T*>(GetBaseEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t m_Index;
|
||||||
|
};
|
||||||
56
csgo2/offset.cpp
Normal file
56
csgo2/offset.cpp
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#include "offset.h"
|
||||||
|
|
||||||
|
namespace Offset {
|
||||||
|
uint64_t GameResourceServicePtr;
|
||||||
|
uint64_t FireEventServerSidePtr;
|
||||||
|
uint64_t NetworkStateChangedPtr;
|
||||||
|
uint64_t CGameEventManagerPtr;
|
||||||
|
uint64_t Host_SayPtr;
|
||||||
|
uint64_t Module_tier0;
|
||||||
|
namespace InterFaces {
|
||||||
|
CSchemaSystem* SchemaSystem;
|
||||||
|
IGameEventManager2* GameEventManager;
|
||||||
|
CGameEventManager* CGameEventManger;
|
||||||
|
CGameResourceService* GameResourceServiceServer;
|
||||||
|
IServerGameClients* IServerGameClient;
|
||||||
|
};
|
||||||
|
auto Init() -> bool {
|
||||||
|
CModule server("server.dll");
|
||||||
|
CModule schemasystem("schemasystem.dll");
|
||||||
|
CModule engine("engine2.dll");
|
||||||
|
|
||||||
|
// server.dll
|
||||||
|
server.FindPattern(pattern_FireEventServerSide).Get(FireEventServerSidePtr);
|
||||||
|
server.FindPattern(pattern_NetworkStateChanged).Get(NetworkStateChangedPtr);
|
||||||
|
//48 8D 05 4A 30 82 00 lea rax, ??_7CGameEventManager@@6B@
|
||||||
|
server.FindPattern(pattern_CGameEventManager).ToAbsolute(3, 0).Get(CGameEventManagerPtr);
|
||||||
|
server.FindPattern(pattern_fnHost_SayPtr).Get(Host_SayPtr);
|
||||||
|
|
||||||
|
//schemasystem
|
||||||
|
InterFaces::SchemaSystem = reinterpret_cast<CSchemaSystem*>(schemasystem.FindInterface("SchemaSystem_001").Get());
|
||||||
|
// engine.dll
|
||||||
|
InterFaces::GameEventManager = reinterpret_cast<IGameEventManager2*>(engine.FindInterface("GameEventSystemServerV001").Get());
|
||||||
|
InterFaces::GameResourceServiceServer = reinterpret_cast<CGameResourceService*>(engine.FindInterface("Source2GameClients001").Get());
|
||||||
|
|
||||||
|
// server.dll
|
||||||
|
InterFaces::IServerGameClient = reinterpret_cast<IServerGameClients*>(server.FindInterface("GameResourceServiceServerV001").Get());
|
||||||
|
// only init in console server
|
||||||
|
InterFaces::CGameEventManger = reinterpret_cast<CGameEventManager*>(CGameEventManagerPtr);
|
||||||
|
|
||||||
|
|
||||||
|
//client.FindPattern(pattern_FireEventServerSide).Get(FireEventServerSidePtr);
|
||||||
|
LOG("[huoji]FireEventServerSidePtr : %llx \n", FireEventServerSidePtr);
|
||||||
|
LOG("[huoji]NetworkStateChangedPtr : %llx \n", NetworkStateChangedPtr);
|
||||||
|
LOG("[huoji]Host_SayPtr : %llx \n", Host_SayPtr);
|
||||||
|
|
||||||
|
LOG("[huoji]InterFaces::SchemaSystem : %llx \n", InterFaces::SchemaSystem);
|
||||||
|
LOG("[huoji]InterFaces::GameEventManager : %llx \n", InterFaces::GameEventManager);
|
||||||
|
LOG("[huoji]InterFaces::CGameEventManger : %llx \n", InterFaces::CGameEventManger);
|
||||||
|
LOG("[huoji]InterFaces::GameResourceServiceServer : %llx \n", InterFaces::GameResourceServiceServer);
|
||||||
|
LOG("[huoji]InterFaces::IServerGameClient : %llx \n", InterFaces::IServerGameClient);
|
||||||
|
|
||||||
|
//GetOffsets();
|
||||||
|
LOG("init offset success !\n");
|
||||||
|
return Host_SayPtr && InterFaces::GameResourceServiceServer && InterFaces::IServerGameClient && InterFaces::GameEventManager && InterFaces::SchemaSystem && FireEventServerSidePtr && NetworkStateChangedPtr;
|
||||||
|
}
|
||||||
|
} // namespace Offset
|
||||||
38
csgo2/offset.h
Normal file
38
csgo2/offset.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "pch.h"
|
||||||
|
#include "native_sdk/cschemasystem.h"
|
||||||
|
#include "native_sdk/cgameresourceserviceserver.h"
|
||||||
|
#include "sdk/public/eiface.h"
|
||||||
|
class CSchemaSystem;
|
||||||
|
|
||||||
|
namespace Offset {
|
||||||
|
namespace InterFaces {
|
||||||
|
extern CSchemaSystem* SchemaSystem;
|
||||||
|
extern IGameEventManager2* GameEventManager;
|
||||||
|
extern CGameEventManager* CGameEventManger;
|
||||||
|
extern CGameResourceService* GameResourceServiceServer;
|
||||||
|
extern IServerGameClients* IServerGameClient;
|
||||||
|
};
|
||||||
|
static const auto pattern_CGameEventManager = THE_GAME_SIG("48 ?? ?? ?? ?? ?? ?? 48 89 ?? ?? ?? 48 89 01 48 8B D9 48 ?? ?? ?? ?? ?? ?? 48 89 ?? ?? E8 ?? ?? ?? ?? 48 ?? ?? ?? ?? ?? ??");
|
||||||
|
static const auto pattern_NetworkStateChanged = THE_GAME_SIG("4C 8B C9 48 8B 09 48 85 C9 74 ? 48 8B 41 10");
|
||||||
|
static const auto pattern_FireEventServerSide = THE_GAME_SIG(
|
||||||
|
"40 53 57 41 54 41 55 41 56 48 ?? ?? ?? 4C 8B F2 4C 8B E1 BA ?? ?? ?? "
|
||||||
|
"?? 48 ?? ?? ?? ?? ?? ?? 45 0F B6 E8 E8 ?? ?? ?? ?? 48 85 C0 75 ?? 48 "
|
||||||
|
"?? ?? ?? ?? ?? ?? 48 8B ?? ?? 80 ?? ?? 74 ?? 49 8B 06 49 8B CE FF ?? "
|
||||||
|
"?? 48 8B D0 48 ?? ?? ?? ?? ?? ?? FF ?? ?? ?? ?? ??");
|
||||||
|
static const auto pattern_fnGetBaseEntity =
|
||||||
|
THE_GAME_SIG("8B D3 E8 ? ? ? ? 48 8B F8 48 85 C0 74 76");
|
||||||
|
static const auto pattern_fnGetHighestEntityIndex =
|
||||||
|
THE_GAME_SIG("33 DB E8 ? ? ? ? 8B 08");
|
||||||
|
static const auto pattern_fnGetLocalPlayerController =
|
||||||
|
THE_GAME_SIG("E8 ? ? ? ? 49 89 47 08");
|
||||||
|
//"\"Console<0>\" say \"%s\"\n"
|
||||||
|
static const auto pattern_fnHost_SayPtr =
|
||||||
|
THE_GAME_SIG("44 89 4C 24 ?? 44 88 44 24 ?? 55 53 56 57 41 54 41 55");
|
||||||
|
extern uint64_t GameResourceServicePtr;
|
||||||
|
extern uint64_t FireEventServerSidePtr;
|
||||||
|
extern uint64_t Module_tier0;
|
||||||
|
extern uint64_t NetworkStateChangedPtr;
|
||||||
|
extern uint64_t Host_SayPtr;
|
||||||
|
auto Init() -> bool;
|
||||||
|
}; // namespace Offset
|
||||||
17
csgo2/pch.cpp
Normal file
17
csgo2/pch.cpp
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// pch.cpp: 与预编译标头对应的源文件
|
||||||
|
|
||||||
|
#include "pch.h"
|
||||||
|
void DebugPrintA(const char* format, ...) {
|
||||||
|
std::string temp;
|
||||||
|
va_list marker = { 0 };
|
||||||
|
va_start(marker, format);
|
||||||
|
size_t num_of_chars = _vscprintf(format, marker);
|
||||||
|
if (num_of_chars > temp.capacity()) {
|
||||||
|
temp.reserve(num_of_chars + 1);
|
||||||
|
}
|
||||||
|
vsprintf_s(const_cast<char*>(temp.c_str()), num_of_chars + 1, format,
|
||||||
|
marker);
|
||||||
|
OutputDebugStringA(temp.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 当使用预编译的头时,需要使用此源文件,编译才能成功。
|
||||||
34
csgo2/pch.h
Normal file
34
csgo2/pch.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// pch.h: 这是预编译标头文件。
|
||||||
|
// 下方列出的文件仅编译一次,提高了将来生成的生成性能。
|
||||||
|
// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。
|
||||||
|
// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
|
||||||
|
// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。
|
||||||
|
#include <string>
|
||||||
|
#include <array>
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <Psapi.h>
|
||||||
|
#include <thread>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "framework.h"
|
||||||
|
#include "stb.hh"
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
|
extern void DebugPrintA(const char* format, ...);
|
||||||
|
//#define LOG DebugPrintA
|
||||||
|
#define LOG(...) printf(__VA_ARGS__)
|
||||||
|
#define THE_GAME_SIG(sig) \
|
||||||
|
stb::simple_conversion::build<stb::fixed_string{sig}>::value
|
||||||
|
#include "vmt.h"
|
||||||
|
|
||||||
|
#include "./MinHook/include/MinHook.h"
|
||||||
|
#include "sdk/sdk.h"
|
||||||
|
#include "interface.h"
|
||||||
|
#include "module.h"
|
||||||
|
#include "hash_fnv1a_constexpr.h"
|
||||||
|
#include "global.h"
|
||||||
|
|
||||||
|
#include "offset.h"
|
||||||
|
#include "events.h"
|
||||||
|
#include "hooks.h"
|
||||||
|
#include "VTHook.h"
|
||||||
6
csgo2/player.cpp
Normal file
6
csgo2/player.cpp
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#include "player.h"
|
||||||
|
|
||||||
|
auto CBasePlayer::ForceRespawn() -> void
|
||||||
|
{
|
||||||
|
return CALL_VIRTUAL(void, 26, this);
|
||||||
|
}
|
||||||
38
csgo2/player.h
Normal file
38
csgo2/player.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "pch.h"
|
||||||
|
#include "schema.h"
|
||||||
|
#include "native_sdk/entity/cbaseentity.h"
|
||||||
|
class CBasePlayer {
|
||||||
|
public:
|
||||||
|
auto ForceRespawn() -> void;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CPlayer_MovementServices
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS(CPlayer_MovementServices);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CCSPlayerController_InGameMoneyServices
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS(CCSPlayerController_InGameMoneyServices);
|
||||||
|
|
||||||
|
SCHEMA_FIELD(int, m_iAccount)
|
||||||
|
};
|
||||||
|
class CBasePlayerPawn : public CBaseEntity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS(CBasePlayerPawn);
|
||||||
|
|
||||||
|
SCHEMA_FIELD(CPlayer_MovementServices*, m_pMovementServices)
|
||||||
|
SCHEMA_FIELD(uint8_t*, m_pWeaponServices)
|
||||||
|
SCHEMA_FIELD(uint8_t**, m_pItemServices)
|
||||||
|
};
|
||||||
|
class CCSPlayerPawn : public CBasePlayerPawn
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS(CCSPlayerPawn);
|
||||||
|
SCHEMA_FIELD(const char*, m_szLastPlaceName)
|
||||||
|
|
||||||
|
};
|
||||||
81
csgo2/schema.cpp
Normal file
81
csgo2/schema.cpp
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#include "schema.h"
|
||||||
|
#include "native_sdk/cgameentitysystem.h"
|
||||||
|
#include "native_sdk/cschemasystem.h"
|
||||||
|
using SchemaKeyValueMap_t = std::unordered_map<uint32_t, int16_t>;
|
||||||
|
using SchemaTableMap_t = std::unordered_map<uint32_t, SchemaKeyValueMap_t>;
|
||||||
|
|
||||||
|
static bool InitSchemaFieldsForClass(SchemaTableMap_t& tableMap,
|
||||||
|
const char* className, uint32_t classKey) {
|
||||||
|
CSchemaSystemTypeScope* pType =
|
||||||
|
Offset::InterFaces::SchemaSystem->FindTypeScopeForModule("server.dll");
|
||||||
|
if (!pType) return false;
|
||||||
|
|
||||||
|
SchemaClassInfoData_t* pClassInfo = pType->FindDeclaredClass(className);
|
||||||
|
if (!pClassInfo) {
|
||||||
|
tableMap.emplace(classKey, SchemaKeyValueMap_t{});
|
||||||
|
|
||||||
|
LOG("InitSchemaFieldsForClass(): '%s' was not found!\n", className);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
short fieldsSize = pClassInfo->GetFieldsSize();
|
||||||
|
SchemaClassFieldData_t* pFields = pClassInfo->GetFields();
|
||||||
|
|
||||||
|
auto& keyValueMap = tableMap[classKey];
|
||||||
|
keyValueMap.reserve(fieldsSize);
|
||||||
|
|
||||||
|
for (int i = 0; i < fieldsSize; ++i) {
|
||||||
|
SchemaClassFieldData_t& field = pFields[i];
|
||||||
|
LOG("%s::%s found at -> 0x%X\n", className, field.m_name,
|
||||||
|
field.m_offset);
|
||||||
|
keyValueMap.emplace(hash_32_fnv1a_const(field.m_name), field.m_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t schema::FindChainOffset(const char* className)
|
||||||
|
{
|
||||||
|
CSchemaSystemTypeScope* pType =
|
||||||
|
Offset::InterFaces::SchemaSystem->FindTypeScopeForModule("server.dll");
|
||||||
|
if (!pType) return false;
|
||||||
|
|
||||||
|
SchemaClassInfoData_t* pClassInfo = pType->FindDeclaredClass(className);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
SchemaClassFieldData_t* pFields = pClassInfo->GetFields();
|
||||||
|
short fieldsSize = pClassInfo->GetFieldsSize();
|
||||||
|
for (int i = 0; i < fieldsSize; ++i) {
|
||||||
|
SchemaClassFieldData_t& field = pFields[i];
|
||||||
|
|
||||||
|
if (strcmp(field.m_name, "__m_pChainEntity") == 0)
|
||||||
|
{
|
||||||
|
return field.m_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} while ((pClassInfo = pClassInfo->GetParent()) != nullptr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t schema::GetOffset(const char* className, uint32_t classKey,
|
||||||
|
const char* memberName, uint32_t memberKey) {
|
||||||
|
static SchemaTableMap_t schemaTableMap;
|
||||||
|
const auto& tableMapIt = schemaTableMap.find(classKey);
|
||||||
|
if (tableMapIt == schemaTableMap.cend()) {
|
||||||
|
if (InitSchemaFieldsForClass(schemaTableMap, className, classKey))
|
||||||
|
return GetOffset(className, classKey, memberName, memberKey);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SchemaKeyValueMap_t& tableMap = tableMapIt->second;
|
||||||
|
if (tableMap.find(memberKey) == tableMap.cend()) {
|
||||||
|
LOG("schema::GetOffset(): '%s' was not found in '%s'!\n", memberName, className);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tableMap.at(memberKey);
|
||||||
|
}
|
||||||
60
csgo2/schema.h
Normal file
60
csgo2/schema.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "pch.h"
|
||||||
|
typedef void(__fastcall* FnNetworkStateChanged)(uintptr_t chainEntity, uintptr_t offset, uintptr_t a3);
|
||||||
|
|
||||||
|
#define SCHEMA_FIELD_OFFSET(type, varName, extra_offset) \
|
||||||
|
std::add_lvalue_reference_t<type> varName() \
|
||||||
|
{ \
|
||||||
|
static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClass); \
|
||||||
|
static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \
|
||||||
|
\
|
||||||
|
static const auto m_offset = \
|
||||||
|
schema::GetOffset(ThisClass, datatable_hash, #varName, prop_hash); \
|
||||||
|
\
|
||||||
|
return *reinterpret_cast<std::add_pointer_t<type>>( \
|
||||||
|
(uintptr_t)(this) + m_offset + extra_offset); \
|
||||||
|
} \
|
||||||
|
void varName(type val) \
|
||||||
|
{ \
|
||||||
|
static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClass); \
|
||||||
|
static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \
|
||||||
|
\
|
||||||
|
static const auto m_offset = \
|
||||||
|
schema::GetOffset(ThisClass, datatable_hash, #varName, prop_hash); \
|
||||||
|
\
|
||||||
|
static const auto m_chain = \
|
||||||
|
schema::FindChainOffset(ThisClass); \
|
||||||
|
\
|
||||||
|
if (m_chain != 0) \
|
||||||
|
{ \
|
||||||
|
reinterpret_cast<FnNetworkStateChanged>(Offset::NetworkStateChangedPtr)((uintptr_t)(this) + m_chain, m_offset + extra_offset, 0xFFFFFFFF); \
|
||||||
|
} \
|
||||||
|
*reinterpret_cast<std::add_pointer_t<type>>((uintptr_t)(this) + m_offset + extra_offset) = val; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SCHEMA_FIELD(type, varName) \
|
||||||
|
SCHEMA_FIELD_OFFSET(type, varName, 0)
|
||||||
|
|
||||||
|
#define PSCHEMA_FIELD_OFFSET(type, varName, extra_offset) \
|
||||||
|
auto varName() \
|
||||||
|
{ \
|
||||||
|
static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClass); \
|
||||||
|
static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \
|
||||||
|
\
|
||||||
|
static const auto m_offset = \
|
||||||
|
schema::GetOffset(ThisClass, datatable_hash, #varName, prop_hash); \
|
||||||
|
\
|
||||||
|
return reinterpret_cast<std::add_pointer_t<type>>( \
|
||||||
|
(uintptr_t)(this) + m_offset + extra_offset); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PSCHEMA_FIELD(type, varName) \
|
||||||
|
PSCHEMA_FIELD_OFFSET(type, varName, 0)
|
||||||
|
|
||||||
|
namespace schema
|
||||||
|
{
|
||||||
|
int16_t FindChainOffset(const char* className);
|
||||||
|
int16_t GetOffset(const char* className, uint32_t classKey, const char* memberName, uint32_t memberKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DECLARE_CLASS(className) static constexpr auto ThisClass = #className;
|
||||||
18
csgo2/sdk/convar/convar.cpp
Normal file
18
csgo2/sdk/convar/convar.cpp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#include "convar.hpp"
|
||||||
|
|
||||||
|
inline const char** CCommand::ArgV() const
|
||||||
|
{
|
||||||
|
return ArgC() ? (const char**)m_Args.Base() : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char* CCommand::ArgS() const
|
||||||
|
{
|
||||||
|
return m_nArgv0Size ? (m_ArgSBuffer.Base() + m_nArgv0Size) : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
inline const char* CCommand::operator[](int nIndex) const
|
||||||
|
{
|
||||||
|
return Arg(nIndex);
|
||||||
|
}
|
||||||
128
csgo2/sdk/convar/convar.hpp
Normal file
128
csgo2/sdk/convar/convar.hpp
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
#include "../sdk.h"
|
||||||
|
#include "../tier1/UtlVector.hpp"
|
||||||
|
struct characterset_t
|
||||||
|
{
|
||||||
|
char set[256];
|
||||||
|
};
|
||||||
|
class ConCommandBase
|
||||||
|
{
|
||||||
|
friend class CCvar;
|
||||||
|
friend class ConCommand;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ConCommandBase(void);
|
||||||
|
public:
|
||||||
|
|
||||||
|
~ConCommandBase(void);
|
||||||
|
// Check flag
|
||||||
|
bool IsFlagSet(int64_t flag) const;
|
||||||
|
// Set flag
|
||||||
|
void AddFlags(int64_t flags);
|
||||||
|
// Clear flag
|
||||||
|
void RemoveFlags(int64_t flags);
|
||||||
|
|
||||||
|
int64_t GetFlags() const;
|
||||||
|
|
||||||
|
// Return name of cvar
|
||||||
|
const char* GetName(void) const;
|
||||||
|
|
||||||
|
// Return help text for cvar
|
||||||
|
const char* GetHelpText(void) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Static data
|
||||||
|
const char* m_pszName;
|
||||||
|
const char* m_pszHelpString;
|
||||||
|
|
||||||
|
// ConVar flags
|
||||||
|
int64_t m_nFlags;
|
||||||
|
};
|
||||||
|
|
||||||
|
template< class T, size_t SIZE, class I = int >
|
||||||
|
class CUtlMemoryFixedGrowable : public CUtlMemory< T, I >
|
||||||
|
{
|
||||||
|
typedef CUtlMemory< T, I > BaseClass;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CUtlMemoryFixedGrowable(int nGrowSize = 0, int nInitSize = SIZE) : BaseClass(m_pFixedMemory, SIZE)
|
||||||
|
{
|
||||||
|
Assert(nInitSize == 0 || nInitSize == SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnsureCapacity(int num)
|
||||||
|
{
|
||||||
|
if (CUtlMemory<T>::m_nAllocationCount >= num)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BaseClass::EnsureCapacity(num);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T m_pFixedMemory[SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
template< class T, size_t MAX_SIZE >
|
||||||
|
class CUtlVectorFixedGrowable : public CUtlVector< T, CUtlMemoryFixedGrowable<T, MAX_SIZE > >
|
||||||
|
{
|
||||||
|
typedef CUtlVector< T, CUtlMemoryFixedGrowable<T, MAX_SIZE > > BaseClass;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// constructor, destructor
|
||||||
|
CUtlVectorFixedGrowable(int growSize = 0) : BaseClass(growSize, MAX_SIZE) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CCommand();
|
||||||
|
CCommand(int nArgC, const char** ppArgV);
|
||||||
|
virtual bool Tokenize(const char* pCommand, characterset_t* pBreakSet = NULL);
|
||||||
|
virtual void Reset();
|
||||||
|
|
||||||
|
int ArgC() const {
|
||||||
|
return m_Args.Count();
|
||||||
|
}
|
||||||
|
const char** ArgV() const;
|
||||||
|
const char* ArgS() const; // All args that occur after the 0th arg, in string form
|
||||||
|
const char* GetCommandString() const
|
||||||
|
{
|
||||||
|
return ArgC() ? m_ArgSBuffer.Base() : "";
|
||||||
|
}
|
||||||
|
const char* operator[](int nIndex) const; // Gets at arguments
|
||||||
|
const char* Arg(int nIndex) const {
|
||||||
|
// FIXME: Many command handlers appear to not be particularly careful
|
||||||
|
// about checking for valid argc range. For now, we're going to
|
||||||
|
// do the extra check and return an empty string if it's out of range
|
||||||
|
if (nIndex < 0 || nIndex >= ArgC())
|
||||||
|
return "";
|
||||||
|
return m_Args[nIndex];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper functions to parse arguments to commands.
|
||||||
|
//
|
||||||
|
// Returns index of argument, or -1 if no such argument.
|
||||||
|
int FindArg(const char* pName) const;
|
||||||
|
|
||||||
|
int FindArgInt(const char* pName, int nDefaultVal) const;
|
||||||
|
|
||||||
|
static int MaxCommandLength()
|
||||||
|
{
|
||||||
|
return COMMAND_MAX_LENGTH - 1;
|
||||||
|
}
|
||||||
|
static characterset_t* DefaultBreakSet();
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
COMMAND_MAX_ARGC = 64,
|
||||||
|
COMMAND_MAX_LENGTH = 512,
|
||||||
|
};
|
||||||
|
|
||||||
|
int m_nArgv0Size;
|
||||||
|
CUtlVectorFixedGrowable<char, COMMAND_MAX_LENGTH> m_ArgSBuffer;
|
||||||
|
CUtlVectorFixedGrowable<char, COMMAND_MAX_LENGTH> m_ArgvBuffer;
|
||||||
|
CUtlVectorFixedGrowable<char*, COMMAND_MAX_ARGC> m_Args;
|
||||||
|
};
|
||||||
|
|
||||||
151
csgo2/sdk/gameevent/IGameEvent.h
Normal file
151
csgo2/sdk/gameevent/IGameEvent.h
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../sdk.h"
|
||||||
|
#include "../player/playerslot.h"
|
||||||
|
#include "../player/player.h"
|
||||||
|
#include "../handle/basehandle.h"
|
||||||
|
#include "../interfaces/interfaces.h"
|
||||||
|
class CMsgSource1LegacyGameEvent;
|
||||||
|
class CUtlString;
|
||||||
|
class IToolGameEventAPI
|
||||||
|
{
|
||||||
|
virtual void unk001(void*) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UnkGameEventStruct_t {
|
||||||
|
UnkGameEventStruct_t(const char* keyName) {
|
||||||
|
m_Unk = 0;
|
||||||
|
m_Key = keyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t m_Unk;
|
||||||
|
const char* m_Key;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IGameEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IGameEvent() {};
|
||||||
|
virtual const char* GetName() const = 0; // get event name
|
||||||
|
virtual int GetID() const = 0;
|
||||||
|
|
||||||
|
virtual bool IsReliable() const = 0; // if event handled reliable
|
||||||
|
virtual bool IsLocal() const = 0; // if event is never networked
|
||||||
|
virtual bool IsEmpty(const char* keyName = NULL) = 0; // check if data field exists
|
||||||
|
|
||||||
|
// Data access
|
||||||
|
virtual bool GetBool(const char* keyName = NULL, bool defaultValue = false) = 0;
|
||||||
|
virtual int GetInt(const char* keyName = NULL, int defaultValue = 0) = 0;
|
||||||
|
virtual uint64_t GetUint64(const char* keyName = NULL, uint64_t defaultValue = 0) = 0;
|
||||||
|
virtual float GetFloat(const char* keyName = NULL, float defaultValue = 0.0f) = 0;
|
||||||
|
virtual const char* GetString(const char* keyName = NULL, const char* defaultValue = "") = 0;
|
||||||
|
virtual void* GetPtr(const char* keyName = NULL, void* defaultValue = NULL) = 0;
|
||||||
|
|
||||||
|
/* These function prototypes and names are very speculative and might be incorrect */
|
||||||
|
virtual CEntityHandle GetEHandle(UnkGameEventStruct_t* keyName, CEntityHandle defaultValue) = 0;
|
||||||
|
virtual CEntityHandle GetStrictEHandle(UnkGameEventStruct_t* keyName, CEntityHandle defaultValue) = 0;
|
||||||
|
virtual CEntityHandle GetEHandle2(UnkGameEventStruct_t* keyName, CEntityHandle defaultValue) = 0;
|
||||||
|
|
||||||
|
virtual CPlayerSlot* GetPlayerSlot(UnkGameEventStruct_t* keyName = NULL) = 0;
|
||||||
|
virtual CBasePlayer* GetPlayer(UnkGameEventStruct_t* keyName = NULL) = 0;
|
||||||
|
|
||||||
|
virtual void* GetPlayerPawn(UnkGameEventStruct_t* keyName = NULL) = 0;
|
||||||
|
virtual CEntityHandle GetPlayerControllerEHandle(UnkGameEventStruct_t* keyName = NULL) = 0;
|
||||||
|
virtual CEntityHandle GetPlayerControllerEHandle2(UnkGameEventStruct_t* keyName = NULL) = 0;
|
||||||
|
/* ============================================================ */
|
||||||
|
|
||||||
|
virtual void SetBool(const char* keyName, bool value) = 0;
|
||||||
|
virtual void SetInt(const char* keyName, int value) = 0;
|
||||||
|
virtual void SetUint64(const char* keyName, uint64_t value) = 0;
|
||||||
|
virtual void SetFloat(const char* keyName, float value) = 0;
|
||||||
|
virtual void SetString(const char* keyName, const char* value) = 0;
|
||||||
|
virtual void SetPtr(const char* keyName, void* value) = 0;
|
||||||
|
|
||||||
|
/* These function prototypes and names are very speculative and might be incorrect */
|
||||||
|
virtual void SetEHandleStrict(const char* keyName, CEntityHandle handle) = 0;
|
||||||
|
virtual void SetEHandle(const char* keyName, CEntityHandle handle) = 0;
|
||||||
|
|
||||||
|
// Also sets the _pawn key
|
||||||
|
virtual void SetPlayerSlot(const char* keyName, CPlayerSlot value) = 0;
|
||||||
|
virtual void SetPlayer(const char* keyName, CBasePlayer* value) = 0;
|
||||||
|
/* ============================================================ */
|
||||||
|
|
||||||
|
virtual bool HasKey(const char* keyName) = 0;
|
||||||
|
|
||||||
|
// Something script vm related
|
||||||
|
virtual void unk001() = 0;
|
||||||
|
|
||||||
|
//virtual KeyValues* GetDataKeys() const = 0;
|
||||||
|
};
|
||||||
|
class IGameEventListener2
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IGameEventListener2(void) {};
|
||||||
|
|
||||||
|
// FireEvent is called by EventManager if event just occured
|
||||||
|
// KeyValue memory will be freed by manager if not needed anymore
|
||||||
|
virtual void FireGameEvent(IGameEvent* event) = 0;
|
||||||
|
};
|
||||||
|
class IGameEventManager2 : public IBaseInterface, public IToolGameEventAPI
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IGameEventManager2(void) {};
|
||||||
|
|
||||||
|
// load game event descriptions from a file eg "resource\gameevents.res"
|
||||||
|
virtual int LoadEventsFromFile(const char* filename, bool bSearchAll) = 0;
|
||||||
|
|
||||||
|
// removes all and anything
|
||||||
|
virtual void Reset() = 0;
|
||||||
|
|
||||||
|
// adds a listener for a particular event
|
||||||
|
virtual bool AddListener(IGameEventListener2* listener, const char* name, bool bServerSide) = 0;
|
||||||
|
|
||||||
|
// returns true if this listener is listens to given event
|
||||||
|
virtual bool FindListener(IGameEventListener2* listener, const char* name) = 0;
|
||||||
|
|
||||||
|
// removes a listener
|
||||||
|
virtual void RemoveListener(IGameEventListener2* listener) = 0;
|
||||||
|
|
||||||
|
// create an event by name, but doesn't fire it. returns NULL is event is not
|
||||||
|
// known or no listener is registered for it. bForce forces the creation even if no listener is active
|
||||||
|
virtual IGameEvent* CreateEvent(const char* name, bool bForce = false, int* pCookie = NULL) = 0;
|
||||||
|
|
||||||
|
// fires a server event created earlier, if bDontBroadcast is set, event is not send to clients
|
||||||
|
virtual bool FireEvent(IGameEvent* event, bool bDontBroadcast = false) = 0;
|
||||||
|
|
||||||
|
// fires an event for the local client only, should be used only by client code
|
||||||
|
virtual bool FireEventClientSide(IGameEvent* event) = 0;
|
||||||
|
|
||||||
|
// create a new copy of this event, must be free later
|
||||||
|
virtual IGameEvent* DuplicateEvent(IGameEvent* event) = 0;
|
||||||
|
|
||||||
|
// if an event was created but not fired for some reason, it has to bee freed, same UnserializeEvent
|
||||||
|
virtual void FreeEvent(IGameEvent* event) = 0;
|
||||||
|
|
||||||
|
// write/read event to/from bitbuffer
|
||||||
|
virtual bool SerializeEvent(IGameEvent* event, CMsgSource1LegacyGameEvent* ev) = 0;
|
||||||
|
virtual IGameEvent* UnserializeEvent(const CMsgSource1LegacyGameEvent& ev) = 0; // create new KeyValues, must be deleted
|
||||||
|
|
||||||
|
virtual int LookupEventId(const char* name) = 0;
|
||||||
|
|
||||||
|
virtual void PrintEventToString(IGameEvent* event, CUtlString& out) = 0;
|
||||||
|
|
||||||
|
virtual bool HasEventDescriptor(const char* name) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CGameEventManager : public IGameEventManager2
|
||||||
|
{
|
||||||
|
public: // IGameEventManager functions
|
||||||
|
virtual ~CGameEventManager() = 0;
|
||||||
|
|
||||||
|
virtual int LoadEventsFromFile(const char* filename) = 0;
|
||||||
|
virtual void Reset() = 0;
|
||||||
|
|
||||||
|
virtual bool AddListener(IGameEventListener2* listener, const char* name, bool bServerSide) = 0;
|
||||||
|
virtual bool FindListener(IGameEventListener2* listener, const char* name) = 0;
|
||||||
|
virtual void RemoveListener(IGameEventListener2* listener) = 0;
|
||||||
|
|
||||||
|
virtual IGameEvent* CreateEvent(const char* name, bool bForce = false) = 0;
|
||||||
|
virtual IGameEvent* DuplicateEvent(IGameEvent* event) = 0;
|
||||||
|
virtual bool FireEvent(IGameEvent* event, bool bDontBroadcast = false) = 0;
|
||||||
|
virtual bool FireEventClientSide(IGameEvent* event) = 0;
|
||||||
|
};
|
||||||
16
csgo2/sdk/handle/basehandle.h
Normal file
16
csgo2/sdk/handle/basehandle.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../sdk.h"
|
||||||
|
|
||||||
|
class CEntityHandle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint32_t m_Index;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t m_EntityIndex : 15;
|
||||||
|
uint32_t m_Serial : 17;
|
||||||
|
} m_Parts;
|
||||||
|
};
|
||||||
|
};
|
||||||
21
csgo2/sdk/interfaces/interfaces.h
Normal file
21
csgo2/sdk/interfaces/interfaces.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#include "../sdk.h"
|
||||||
|
class IBaseInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IBaseInterface() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void* (*InstantiateInterfaceFn)();
|
||||||
|
|
||||||
|
// Used internally to register classes.
|
||||||
|
class InterfaceReg
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InterfaceReg(InstantiateInterfaceFn fn, const char* pName);
|
||||||
|
|
||||||
|
public:
|
||||||
|
InstantiateInterfaceFn m_CreateFn;
|
||||||
|
const char* m_pName;
|
||||||
|
|
||||||
|
InterfaceReg* m_pNext; // For the global list.
|
||||||
|
};
|
||||||
3
csgo2/sdk/player/player.h
Normal file
3
csgo2/sdk/player/player.h
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../sdk.h"
|
||||||
|
class CBasePlayer;
|
||||||
24
csgo2/sdk/player/playerslot.h
Normal file
24
csgo2/sdk/player/playerslot.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../sdk.h"
|
||||||
|
class CPlayerSlot
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CPlayerSlot(int slot) : m_Data(slot)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int Get() const
|
||||||
|
{
|
||||||
|
return m_Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const CPlayerSlot& other) const {
|
||||||
|
return other.m_Data == m_Data;
|
||||||
|
}
|
||||||
|
bool operator!=(const CPlayerSlot& other) const {
|
||||||
|
return other.m_Data != m_Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_Data;
|
||||||
|
};
|
||||||
63
csgo2/sdk/public/IAppSystem.h
Normal file
63
csgo2/sdk/public/IAppSystem.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../sdk.h"
|
||||||
|
struct AppSystemInfo_t
|
||||||
|
{
|
||||||
|
const char* m_pModuleName;
|
||||||
|
const char* m_pInterfaceName;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum InitReturnVal_t
|
||||||
|
{
|
||||||
|
INIT_FAILED = 0,
|
||||||
|
INIT_OK,
|
||||||
|
|
||||||
|
INIT_LAST_VAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum AppSystemTier_t
|
||||||
|
{
|
||||||
|
APP_SYSTEM_TIER0 = 0,
|
||||||
|
APP_SYSTEM_TIER1,
|
||||||
|
APP_SYSTEM_TIER2,
|
||||||
|
APP_SYSTEM_TIER3,
|
||||||
|
APP_SYSTEM_TIER4,
|
||||||
|
|
||||||
|
APP_SYSTEM_TIER_OTHER,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum BuildType_t
|
||||||
|
{
|
||||||
|
kBuildTypeRelease = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class IAppSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Here's where the app systems get to learn about each other
|
||||||
|
virtual bool Connect(void* factory) = 0;
|
||||||
|
virtual void Disconnect() = 0;
|
||||||
|
|
||||||
|
// Here's where systems can access other interfaces implemented by this object
|
||||||
|
// Returns NULL if it doesn't implement the requested interface
|
||||||
|
virtual void* QueryInterface(const char* pInterfaceName) = 0;
|
||||||
|
|
||||||
|
// Init, shutdown
|
||||||
|
virtual InitReturnVal_t Init() = 0;
|
||||||
|
virtual void Shutdown() = 0;
|
||||||
|
virtual void PreShutdown() = 0;
|
||||||
|
|
||||||
|
// Returns all dependent libraries
|
||||||
|
virtual const AppSystemInfo_t* GetDependencies() = 0;
|
||||||
|
|
||||||
|
// Returns the tier
|
||||||
|
virtual AppSystemTier_t GetTier() = 0;
|
||||||
|
|
||||||
|
// Reconnect to a particular interface
|
||||||
|
virtual void Reconnect(void* factory, const char* pInterfaceName) = 0;
|
||||||
|
|
||||||
|
// Returns whether or not the app system is a singleton
|
||||||
|
virtual bool IsSingleton() = 0;
|
||||||
|
|
||||||
|
virtual BuildType_t GetBuildType() = 0;
|
||||||
|
};
|
||||||
119
csgo2/sdk/public/eiface.h
Normal file
119
csgo2/sdk/public/eiface.h
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../sdk.h"
|
||||||
|
#include "IAppSystem.h"
|
||||||
|
#include "../tier1/bufferstring.h"
|
||||||
|
#include "../convar/convar.hpp"
|
||||||
|
struct vis_info_t;
|
||||||
|
class IHLTVServer;
|
||||||
|
class IHLTVDirector;
|
||||||
|
class CSteamID;
|
||||||
|
|
||||||
|
struct CEntityIndex
|
||||||
|
{
|
||||||
|
CEntityIndex(int index)
|
||||||
|
{
|
||||||
|
_index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Get() const
|
||||||
|
{
|
||||||
|
return _index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _index;
|
||||||
|
|
||||||
|
bool operator==(const CEntityIndex& other) const { return other._index == _index; }
|
||||||
|
bool operator!=(const CEntityIndex& other) const { return other._index != _index; }
|
||||||
|
};
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Player / Client related functions
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class ISource2GameClients : public IAppSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void OnClientConnected(CPlayerSlot slot, const char* pszName, uint64_t xuid, const char* pszNetworkID, const char* pszAddress, bool bFakePlayer) = 0;
|
||||||
|
|
||||||
|
// Called when the client attempts to connect (doesn't get called for bots)
|
||||||
|
// returning false would reject the connection with the pRejectReason message
|
||||||
|
virtual bool ClientConnect(CPlayerSlot slot, const char* pszName, uint64_t xuid, const char* pszNetworkID, bool unk1, CBufferString* pRejectReason);
|
||||||
|
|
||||||
|
// Client is connected and should be put in the game
|
||||||
|
// type values could be:
|
||||||
|
// 0 - player
|
||||||
|
// 1 - fake player (bot)
|
||||||
|
// 2 - unknown
|
||||||
|
virtual void ClientPutInServer(CPlayerSlot slot, char const* pszName, int type, uint64_t xuid) = 0;
|
||||||
|
|
||||||
|
// Client is going active
|
||||||
|
// If bLoadGame is true, don't spawn the player because its state is already setup.
|
||||||
|
virtual void ClientActive(CPlayerSlot slot, bool bLoadGame, const char* pszName, uint64_t xuid) = 0;
|
||||||
|
|
||||||
|
virtual void ClientFullyConnect(CPlayerSlot slot) = 0;
|
||||||
|
|
||||||
|
// Client is disconnecting from server
|
||||||
|
virtual void ClientDisconnect(CPlayerSlot slot, /* ENetworkDisconnectionReason */ int reason,
|
||||||
|
const char* pszName, uint64_t xuid, const char* pszNetworkID) = 0;
|
||||||
|
|
||||||
|
// Sets the client index for the client who typed the command into his/her console
|
||||||
|
// virtual void SetCommandClient( CPlayerSlot slot) = 0;
|
||||||
|
|
||||||
|
// The client has typed a command at the console
|
||||||
|
virtual void ClientCommand(CPlayerSlot slot, const CCommand& args) = 0;
|
||||||
|
|
||||||
|
// A player changed one/several replicated cvars (name etc)
|
||||||
|
virtual void ClientSettingsChanged(CPlayerSlot slot) = 0;
|
||||||
|
|
||||||
|
// Determine PVS origin and set PVS for the player/viewentity
|
||||||
|
virtual void ClientSetupVisibility(CPlayerSlot slot, vis_info_t* visinfo) = 0;
|
||||||
|
|
||||||
|
// A block of CUserCmds has arrived from the user, decode them and buffer for execution during player simulation
|
||||||
|
virtual float ProcessUsercmds(CPlayerSlot slot, void* buf, int numcmds, bool ignore, bool paused) = 0;
|
||||||
|
|
||||||
|
virtual bool IsPlayerSlotOccupied(CPlayerSlot slot) = 0;
|
||||||
|
|
||||||
|
virtual bool IsPlayerAlive(CPlayerSlot slot) = 0;
|
||||||
|
|
||||||
|
virtual int GetPlayerScore(CPlayerSlot slot) = 0;
|
||||||
|
|
||||||
|
// Get the ear position for a specified client
|
||||||
|
virtual void ClientEarPosition(CPlayerSlot slot, void* pEarOrigin) = 0;
|
||||||
|
|
||||||
|
// Anything this game .dll wants to add to the bug reporter text (e.g., the entity/model under the picker crosshair)
|
||||||
|
// can be added here
|
||||||
|
virtual void GetBugReportInfo(CBufferString& buf) = 0;
|
||||||
|
|
||||||
|
// TERROR: A player sent a voice packet
|
||||||
|
virtual void ClientVoice(CPlayerSlot slot) = 0;
|
||||||
|
|
||||||
|
// A user has had their network id setup and validated
|
||||||
|
virtual void NetworkIDValidated(const char* pszUserName, const char* pszNetworkID) = 0;
|
||||||
|
|
||||||
|
// The client has submitted a keyvalues command
|
||||||
|
virtual void ClientCommandKeyValues(CPlayerSlot slot, void* pKeyValues) = 0;
|
||||||
|
|
||||||
|
virtual bool ClientCanPause(CPlayerSlot slot) = 0;
|
||||||
|
|
||||||
|
virtual void HLTVClientFullyConnect(int index, const CSteamID& steamID) = 0;
|
||||||
|
|
||||||
|
virtual bool CanHLTVClientConnect(int index, const CSteamID& steamID, int* pRejectReason) = 0;
|
||||||
|
|
||||||
|
virtual void StartHLTVServer(CEntityIndex index) = 0;
|
||||||
|
|
||||||
|
virtual void SendHLTVStatusMessage(IHLTVServer*, bool, bool, const char*, int, int, int) = 0;
|
||||||
|
|
||||||
|
virtual IHLTVDirector* GetHLTVDirector(void) = 0;
|
||||||
|
|
||||||
|
virtual void unk002(CPlayerSlot slot) = 0;
|
||||||
|
virtual void unk003(CPlayerSlot slot) = 0;
|
||||||
|
|
||||||
|
// Something NetMessage related
|
||||||
|
virtual void unk004() = 0;
|
||||||
|
|
||||||
|
// Something pawn related
|
||||||
|
virtual void unk005() = 0;
|
||||||
|
virtual void unk006() = 0;
|
||||||
|
|
||||||
|
virtual void unk007() = 0;
|
||||||
|
virtual void unk008() = 0;
|
||||||
|
};
|
||||||
|
typedef ISource2GameClients IServerGameClients;
|
||||||
21
csgo2/sdk/sdk.h
Normal file
21
csgo2/sdk/sdk.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
#define CORRECT_PATH_SEPARATOR '\\'
|
||||||
|
#define CORRECT_PATH_SEPARATOR_S "\\"
|
||||||
|
#define INCORRECT_PATH_SEPARATOR '/'
|
||||||
|
#define INCORRECT_PATH_SEPARATOR_S "/"
|
||||||
|
#define FMTFUNCTION( a, b )
|
||||||
|
enum EStringConvertErrorPolicy
|
||||||
|
{
|
||||||
|
_STRINGCONVERTFLAG_SKIP = 1,
|
||||||
|
_STRINGCONVERTFLAG_FAIL = 2,
|
||||||
|
_STRINGCONVERTFLAG_ASSERT = 4,
|
||||||
|
|
||||||
|
STRINGCONVERT_REPLACE = 0,
|
||||||
|
STRINGCONVERT_SKIP = _STRINGCONVERTFLAG_SKIP,
|
||||||
|
STRINGCONVERT_FAIL = _STRINGCONVERTFLAG_FAIL,
|
||||||
|
|
||||||
|
STRINGCONVERT_ASSERT_REPLACE = _STRINGCONVERTFLAG_ASSERT + STRINGCONVERT_REPLACE,
|
||||||
|
STRINGCONVERT_ASSERT_SKIP = _STRINGCONVERTFLAG_ASSERT + STRINGCONVERT_SKIP,
|
||||||
|
STRINGCONVERT_ASSERT_FAIL = _STRINGCONVERTFLAG_ASSERT + STRINGCONVERT_FAIL,
|
||||||
|
};
|
||||||
|
#include "../pch.h"
|
||||||
699
csgo2/sdk/tier1/UtlMemory.hpp
Normal file
699
csgo2/sdk/tier1/UtlMemory.hpp
Normal file
@@ -0,0 +1,699 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <malloc.h>
|
||||||
|
#define UTLMEMORY_TRACK_ALLOC()
|
||||||
|
#define MEM_ALLOC_CREDIT_CLASS()
|
||||||
|
#define UTLMEMORY_TRACK_FREE()
|
||||||
|
#define assert
|
||||||
|
template< class T, class I = int >
|
||||||
|
class CUtlMemory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor, destructor
|
||||||
|
CUtlMemory(int nGrowSize = 0, int nInitSize = 0);
|
||||||
|
CUtlMemory(T* pMemory, int numElements);
|
||||||
|
CUtlMemory(const T* pMemory, int numElements);
|
||||||
|
~CUtlMemory();
|
||||||
|
|
||||||
|
// Set the size by which the memory grows
|
||||||
|
void Init(int nGrowSize = 0, int nInitSize = 0);
|
||||||
|
|
||||||
|
class Iterator_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Iterator_t(I i) : index(i) {}
|
||||||
|
I index;
|
||||||
|
|
||||||
|
bool operator==(const Iterator_t it) const { return index == it.index; }
|
||||||
|
bool operator!=(const Iterator_t it) const { return index != it.index; }
|
||||||
|
};
|
||||||
|
Iterator_t First() const { return Iterator_t(IsIdxValid(0) ? 0 : InvalidIndex()); }
|
||||||
|
Iterator_t Next(const Iterator_t &it) const { return Iterator_t(IsIdxValid(it.index + 1) ? it.index + 1 : InvalidIndex()); }
|
||||||
|
I GetIndex(const Iterator_t &it) const { return it.index; }
|
||||||
|
bool IsIdxAfter(I i, const Iterator_t &it) const { return i > it.index; }
|
||||||
|
bool IsValidIterator(const Iterator_t &it) const { return IsIdxValid(it.index); }
|
||||||
|
Iterator_t InvalidIterator() const { return Iterator_t(InvalidIndex()); }
|
||||||
|
|
||||||
|
// element access
|
||||||
|
T& operator[](I i);
|
||||||
|
const T& operator[](I i) const;
|
||||||
|
T& Element(I i);
|
||||||
|
const T& Element(I i) const;
|
||||||
|
|
||||||
|
bool IsIdxValid(I i) const;
|
||||||
|
|
||||||
|
static const I INVALID_INDEX = (I)-1; // For use with COMPILE_TIME_ASSERT
|
||||||
|
static I InvalidIndex() { return INVALID_INDEX; }
|
||||||
|
|
||||||
|
T* Base();
|
||||||
|
const T* Base() const;
|
||||||
|
|
||||||
|
void SetExternalBuffer(T* pMemory, int numElements);
|
||||||
|
void SetExternalBuffer(const T* pMemory, int numElements);
|
||||||
|
void AssumeMemory(T *pMemory, int nSize);
|
||||||
|
T* Detach();
|
||||||
|
void *DetachMemory();
|
||||||
|
|
||||||
|
void Swap(CUtlMemory< T, I > &mem);
|
||||||
|
void ConvertToGrowableMemory(int nGrowSize);
|
||||||
|
int NumAllocated() const;
|
||||||
|
int Count() const;
|
||||||
|
void Grow(int num = 1);
|
||||||
|
void EnsureCapacity(int num);
|
||||||
|
void Purge();
|
||||||
|
void Purge(int numElements);
|
||||||
|
bool IsExternallyAllocated() const;
|
||||||
|
bool IsReadOnly() const;
|
||||||
|
void SetGrowSize(int size);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void ValidateGrowSize()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
EXTERNAL_BUFFER_MARKER = -1,
|
||||||
|
EXTERNAL_CONST_BUFFER_MARKER = -2,
|
||||||
|
};
|
||||||
|
|
||||||
|
T* m_pMemory;
|
||||||
|
int m_nAllocationCount;
|
||||||
|
int m_nGrowSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// constructor, destructor
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template< class T, class I >
|
||||||
|
CUtlMemory<T, I>::CUtlMemory(int nGrowSize, int nInitAllocationCount) : m_pMemory(0),
|
||||||
|
m_nAllocationCount(nInitAllocationCount), m_nGrowSize(nGrowSize)
|
||||||
|
{
|
||||||
|
ValidateGrowSize();
|
||||||
|
assert(nGrowSize >= 0);
|
||||||
|
if(m_nAllocationCount) {
|
||||||
|
m_pMemory = (T*)new unsigned char[m_nAllocationCount * sizeof(T)];
|
||||||
|
//m_pMemory = (T*)malloc(m_nAllocationCount * sizeof(T));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class I >
|
||||||
|
CUtlMemory<T, I>::CUtlMemory(T* pMemory, int numElements) : m_pMemory(pMemory),
|
||||||
|
m_nAllocationCount(numElements)
|
||||||
|
{
|
||||||
|
// Special marker indicating externally supplied modifyable memory
|
||||||
|
m_nGrowSize = EXTERNAL_BUFFER_MARKER;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class I >
|
||||||
|
CUtlMemory<T, I>::CUtlMemory(const T* pMemory, int numElements) : m_pMemory((T*)pMemory),
|
||||||
|
m_nAllocationCount(numElements)
|
||||||
|
{
|
||||||
|
// Special marker indicating externally supplied modifyable memory
|
||||||
|
m_nGrowSize = EXTERNAL_CONST_BUFFER_MARKER;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class I >
|
||||||
|
CUtlMemory<T, I>::~CUtlMemory()
|
||||||
|
{
|
||||||
|
Purge();
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class I >
|
||||||
|
void CUtlMemory<T, I>::Init(int nGrowSize /*= 0*/, int nInitSize /*= 0*/)
|
||||||
|
{
|
||||||
|
Purge();
|
||||||
|
|
||||||
|
m_nGrowSize = nGrowSize;
|
||||||
|
m_nAllocationCount = nInitSize;
|
||||||
|
ValidateGrowSize();
|
||||||
|
assert(nGrowSize >= 0);
|
||||||
|
if(m_nAllocationCount) {
|
||||||
|
UTLMEMORY_TRACK_ALLOC();
|
||||||
|
MEM_ALLOC_CREDIT_CLASS();
|
||||||
|
m_pMemory = (T*)malloc(m_nAllocationCount * sizeof(T));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Fast swap
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< class T, class I >
|
||||||
|
void CUtlMemory<T, I>::Swap(CUtlMemory<T, I> &mem)
|
||||||
|
{
|
||||||
|
V_swap(m_nGrowSize, mem.m_nGrowSize);
|
||||||
|
V_swap(m_pMemory, mem.m_pMemory);
|
||||||
|
V_swap(m_nAllocationCount, mem.m_nAllocationCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Switches the buffer from an external memory buffer to a reallocatable buffer
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< class T, class I >
|
||||||
|
void CUtlMemory<T, I>::ConvertToGrowableMemory(int nGrowSize)
|
||||||
|
{
|
||||||
|
if(!IsExternallyAllocated())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_nGrowSize = nGrowSize;
|
||||||
|
if(m_nAllocationCount) {
|
||||||
|
int nNumBytes = m_nAllocationCount * sizeof(T);
|
||||||
|
T *pMemory = (T*)malloc(nNumBytes);
|
||||||
|
memcpy(pMemory, m_pMemory, nNumBytes);
|
||||||
|
m_pMemory = pMemory;
|
||||||
|
} else {
|
||||||
|
m_pMemory = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Attaches the buffer to external memory....
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< class T, class I >
|
||||||
|
void CUtlMemory<T, I>::SetExternalBuffer(T* pMemory, int numElements)
|
||||||
|
{
|
||||||
|
// Blow away any existing allocated memory
|
||||||
|
Purge();
|
||||||
|
|
||||||
|
m_pMemory = pMemory;
|
||||||
|
m_nAllocationCount = numElements;
|
||||||
|
|
||||||
|
// Indicate that we don't own the memory
|
||||||
|
m_nGrowSize = EXTERNAL_BUFFER_MARKER;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class I >
|
||||||
|
void CUtlMemory<T, I>::SetExternalBuffer(const T* pMemory, int numElements)
|
||||||
|
{
|
||||||
|
// Blow away any existing allocated memory
|
||||||
|
Purge();
|
||||||
|
|
||||||
|
m_pMemory = const_cast<T*>(pMemory);
|
||||||
|
m_nAllocationCount = numElements;
|
||||||
|
|
||||||
|
// Indicate that we don't own the memory
|
||||||
|
m_nGrowSize = EXTERNAL_CONST_BUFFER_MARKER;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class I >
|
||||||
|
void CUtlMemory<T, I>::AssumeMemory(T* pMemory, int numElements)
|
||||||
|
{
|
||||||
|
// Blow away any existing allocated memory
|
||||||
|
Purge();
|
||||||
|
|
||||||
|
// Simply take the pointer but don't mark us as external
|
||||||
|
m_pMemory = pMemory;
|
||||||
|
m_nAllocationCount = numElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class I >
|
||||||
|
void *CUtlMemory<T, I>::DetachMemory()
|
||||||
|
{
|
||||||
|
if(IsExternallyAllocated())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
void *pMemory = m_pMemory;
|
||||||
|
m_pMemory = 0;
|
||||||
|
m_nAllocationCount = 0;
|
||||||
|
return pMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class I >
|
||||||
|
inline T* CUtlMemory<T, I>::Detach()
|
||||||
|
{
|
||||||
|
return (T*)DetachMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// element access
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< class T, class I >
|
||||||
|
inline T& CUtlMemory<T, I>::operator[](I i)
|
||||||
|
{
|
||||||
|
assert(!IsReadOnly());
|
||||||
|
assert(IsIdxValid(i));
|
||||||
|
return m_pMemory[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class I >
|
||||||
|
inline const T& CUtlMemory<T, I>::operator[](I i) const
|
||||||
|
{
|
||||||
|
assert(IsIdxValid(i));
|
||||||
|
return m_pMemory[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class I >
|
||||||
|
inline T& CUtlMemory<T, I>::Element(I i)
|
||||||
|
{
|
||||||
|
assert(!IsReadOnly());
|
||||||
|
assert(IsIdxValid(i));
|
||||||
|
return m_pMemory[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class I >
|
||||||
|
inline const T& CUtlMemory<T, I>::Element(I i) const
|
||||||
|
{
|
||||||
|
assert(IsIdxValid(i));
|
||||||
|
return m_pMemory[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// is the memory externally allocated?
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< class T, class I >
|
||||||
|
bool CUtlMemory<T, I>::IsExternallyAllocated() const
|
||||||
|
{
|
||||||
|
return (m_nGrowSize < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// is the memory read only?
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< class T, class I >
|
||||||
|
bool CUtlMemory<T, I>::IsReadOnly() const
|
||||||
|
{
|
||||||
|
return (m_nGrowSize == EXTERNAL_CONST_BUFFER_MARKER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template< class T, class I >
|
||||||
|
void CUtlMemory<T, I>::SetGrowSize(int nSize)
|
||||||
|
{
|
||||||
|
assert(!IsExternallyAllocated());
|
||||||
|
assert(nSize >= 0);
|
||||||
|
m_nGrowSize = nSize;
|
||||||
|
ValidateGrowSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Gets the base address (can change when adding elements!)
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< class T, class I >
|
||||||
|
inline T* CUtlMemory<T, I>::Base()
|
||||||
|
{
|
||||||
|
assert(!IsReadOnly());
|
||||||
|
return m_pMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class I >
|
||||||
|
inline const T *CUtlMemory<T, I>::Base() const
|
||||||
|
{
|
||||||
|
return m_pMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Size
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< class T, class I >
|
||||||
|
inline int CUtlMemory<T, I>::NumAllocated() const
|
||||||
|
{
|
||||||
|
return m_nAllocationCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class I >
|
||||||
|
inline int CUtlMemory<T, I>::Count() const
|
||||||
|
{
|
||||||
|
return m_nAllocationCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Is element index valid?
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< class T, class I >
|
||||||
|
inline bool CUtlMemory<T, I>::IsIdxValid(I i) const
|
||||||
|
{
|
||||||
|
// GCC warns if I is an unsigned type and we do a ">= 0" against it (since the comparison is always 0).
|
||||||
|
// We Get the warning even if we cast inside the expression. It only goes away if we assign to another variable.
|
||||||
|
long x = i;
|
||||||
|
return (x >= 0) && (x < m_nAllocationCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Grows the memory
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
inline int UtlMemory_CalcNewAllocationCount(int nAllocationCount, int nGrowSize, int nNewSize, int nBytesItem)
|
||||||
|
{
|
||||||
|
if(nGrowSize) {
|
||||||
|
nAllocationCount = ((1 + ((nNewSize - 1) / nGrowSize)) * nGrowSize);
|
||||||
|
} else {
|
||||||
|
if(!nAllocationCount) {
|
||||||
|
// Compute an allocation which is at least as big as a cache line...
|
||||||
|
nAllocationCount = (31 + nBytesItem) / nBytesItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(nAllocationCount < nNewSize) {
|
||||||
|
#ifndef _X360
|
||||||
|
nAllocationCount *= 2;
|
||||||
|
#else
|
||||||
|
int nNewAllocationCount = (nAllocationCount * 9) / 8; // 12.5 %
|
||||||
|
if(nNewAllocationCount > nAllocationCount)
|
||||||
|
nAllocationCount = nNewAllocationCount;
|
||||||
|
else
|
||||||
|
nAllocationCount *= 2;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nAllocationCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class I >
|
||||||
|
void CUtlMemory<T, I>::Grow(int num)
|
||||||
|
{
|
||||||
|
assert(num > 0);
|
||||||
|
|
||||||
|
if(IsExternallyAllocated()) {
|
||||||
|
// Can't grow a buffer whose memory was externally allocated
|
||||||
|
assert(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
auto oldAllocationCount = m_nAllocationCount;
|
||||||
|
// Make sure we have at least numallocated + num allocations.
|
||||||
|
// Use the grow rules specified for this memory (in m_nGrowSize)
|
||||||
|
int nAllocationRequested = m_nAllocationCount + num;
|
||||||
|
|
||||||
|
int nNewAllocationCount = UtlMemory_CalcNewAllocationCount(m_nAllocationCount, m_nGrowSize, nAllocationRequested, sizeof(T));
|
||||||
|
|
||||||
|
// if m_nAllocationRequested wraps index type I, recalculate
|
||||||
|
if((int)(I)nNewAllocationCount < nAllocationRequested) {
|
||||||
|
if((int)(I)nNewAllocationCount == 0 && (int)(I)(nNewAllocationCount - 1) >= nAllocationRequested) {
|
||||||
|
--nNewAllocationCount; // deal w/ the common case of m_nAllocationCount == MAX_USHORT + 1
|
||||||
|
} else {
|
||||||
|
if((int)(I)nAllocationRequested != nAllocationRequested) {
|
||||||
|
// we've been asked to grow memory to a size s.t. the index type can't address the requested amount of memory
|
||||||
|
assert(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while((int)(I)nNewAllocationCount < nAllocationRequested) {
|
||||||
|
nNewAllocationCount = (nNewAllocationCount + nAllocationRequested) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_nAllocationCount = nNewAllocationCount;
|
||||||
|
|
||||||
|
if(m_pMemory) {
|
||||||
|
auto ptr = new unsigned char[m_nAllocationCount * sizeof(T)];
|
||||||
|
|
||||||
|
memcpy(ptr, m_pMemory, oldAllocationCount * sizeof(T));
|
||||||
|
m_pMemory = (T*)ptr;
|
||||||
|
} else {
|
||||||
|
m_pMemory = (T*)new unsigned char[m_nAllocationCount * sizeof(T)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Makes sure we've got at least this much memory
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< class T, class I >
|
||||||
|
inline void CUtlMemory<T, I>::EnsureCapacity(int num)
|
||||||
|
{
|
||||||
|
if(m_nAllocationCount >= num)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(IsExternallyAllocated()) {
|
||||||
|
// Can't grow a buffer whose memory was externally allocated
|
||||||
|
assert(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_nAllocationCount = num;
|
||||||
|
|
||||||
|
if(m_pMemory) {
|
||||||
|
m_pMemory = (T*)realloc(m_pMemory, m_nAllocationCount * sizeof(T));
|
||||||
|
} else {
|
||||||
|
m_pMemory = (T*)malloc(m_nAllocationCount * sizeof(T));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Memory deallocation
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< class T, class I >
|
||||||
|
void CUtlMemory<T, I>::Purge()
|
||||||
|
{
|
||||||
|
if(!IsExternallyAllocated()) {
|
||||||
|
if(m_pMemory) {
|
||||||
|
free((void*)m_pMemory);
|
||||||
|
m_pMemory = 0;
|
||||||
|
}
|
||||||
|
m_nAllocationCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class I >
|
||||||
|
void CUtlMemory<T, I>::Purge(int numElements)
|
||||||
|
{
|
||||||
|
assert(numElements >= 0);
|
||||||
|
|
||||||
|
if(numElements > m_nAllocationCount) {
|
||||||
|
// Ensure this isn't a grow request in disguise.
|
||||||
|
assert(numElements <= m_nAllocationCount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have zero elements, simply do a purge:
|
||||||
|
if(numElements == 0) {
|
||||||
|
Purge();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(IsExternallyAllocated()) {
|
||||||
|
// Can't shrink a buffer whose memory was externally allocated, fail silently like purge
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the number of elements is the same as the allocation count, we are done.
|
||||||
|
if(numElements == m_nAllocationCount) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(!m_pMemory) {
|
||||||
|
// Allocation count is non zero, but memory is null.
|
||||||
|
assert(m_pMemory);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_nAllocationCount = numElements;
|
||||||
|
m_pMemory = (T*)realloc(m_pMemory, m_nAllocationCount * sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// The CUtlMemory class:
|
||||||
|
// A growable memory class which doubles in size by default.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< class T, int nAlignment >
|
||||||
|
class CUtlMemoryAligned : public CUtlMemory<T>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor, destructor
|
||||||
|
CUtlMemoryAligned(int nGrowSize = 0, int nInitSize = 0);
|
||||||
|
CUtlMemoryAligned(T* pMemory, int numElements);
|
||||||
|
CUtlMemoryAligned(const T* pMemory, int numElements);
|
||||||
|
~CUtlMemoryAligned();
|
||||||
|
|
||||||
|
// Attaches the buffer to external memory....
|
||||||
|
void SetExternalBuffer(T* pMemory, int numElements);
|
||||||
|
void SetExternalBuffer(const T* pMemory, int numElements);
|
||||||
|
|
||||||
|
// Grows the memory, so that at least allocated + num elements are allocated
|
||||||
|
void Grow(int num = 1);
|
||||||
|
|
||||||
|
// Makes sure we've got at least this much memory
|
||||||
|
void EnsureCapacity(int num);
|
||||||
|
|
||||||
|
// Memory deallocation
|
||||||
|
void Purge();
|
||||||
|
|
||||||
|
// Purge all but the given number of elements (NOT IMPLEMENTED IN CUtlMemoryAligned)
|
||||||
|
void Purge(int numElements) { assert(0); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void *Align(const void *pAddr);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Aligns a pointer
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< class T, int nAlignment >
|
||||||
|
void *CUtlMemoryAligned<T, nAlignment>::Align(const void *pAddr)
|
||||||
|
{
|
||||||
|
size_t nAlignmentMask = nAlignment - 1;
|
||||||
|
return (void*)(((size_t)pAddr + nAlignmentMask) & (~nAlignmentMask));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// constructor, destructor
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< class T, int nAlignment >
|
||||||
|
CUtlMemoryAligned<T, nAlignment>::CUtlMemoryAligned(int nGrowSize, int nInitAllocationCount)
|
||||||
|
{
|
||||||
|
CUtlMemory<T>::m_pMemory = 0;
|
||||||
|
CUtlMemory<T>::m_nAllocationCount = nInitAllocationCount;
|
||||||
|
CUtlMemory<T>::m_nGrowSize = nGrowSize;
|
||||||
|
this->ValidateGrowSize();
|
||||||
|
|
||||||
|
// Alignment must be a power of two
|
||||||
|
COMPILE_TIME_ASSERT((nAlignment & (nAlignment - 1)) == 0);
|
||||||
|
assert((nGrowSize >= 0) && (nGrowSize != CUtlMemory<T>::EXTERNAL_BUFFER_MARKER));
|
||||||
|
if(CUtlMemory<T>::m_nAllocationCount) {
|
||||||
|
UTLMEMORY_TRACK_ALLOC();
|
||||||
|
MEM_ALLOC_CREDIT_CLASS();
|
||||||
|
CUtlMemory<T>::m_pMemory = (T*)_aligned_malloc(nInitAllocationCount * sizeof(T), nAlignment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, int nAlignment >
|
||||||
|
CUtlMemoryAligned<T, nAlignment>::CUtlMemoryAligned(T* pMemory, int numElements)
|
||||||
|
{
|
||||||
|
// Special marker indicating externally supplied memory
|
||||||
|
CUtlMemory<T>::m_nGrowSize = CUtlMemory<T>::EXTERNAL_BUFFER_MARKER;
|
||||||
|
|
||||||
|
CUtlMemory<T>::m_pMemory = (T*)Align(pMemory);
|
||||||
|
CUtlMemory<T>::m_nAllocationCount = ((int)(pMemory + numElements) - (int)CUtlMemory<T>::m_pMemory) / sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, int nAlignment >
|
||||||
|
CUtlMemoryAligned<T, nAlignment>::CUtlMemoryAligned(const T* pMemory, int numElements)
|
||||||
|
{
|
||||||
|
// Special marker indicating externally supplied memory
|
||||||
|
CUtlMemory<T>::m_nGrowSize = CUtlMemory<T>::EXTERNAL_CONST_BUFFER_MARKER;
|
||||||
|
|
||||||
|
CUtlMemory<T>::m_pMemory = (T*)Align(pMemory);
|
||||||
|
CUtlMemory<T>::m_nAllocationCount = ((int)(pMemory + numElements) - (int)CUtlMemory<T>::m_pMemory) / sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, int nAlignment >
|
||||||
|
CUtlMemoryAligned<T, nAlignment>::~CUtlMemoryAligned()
|
||||||
|
{
|
||||||
|
Purge();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Attaches the buffer to external memory....
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< class T, int nAlignment >
|
||||||
|
void CUtlMemoryAligned<T, nAlignment>::SetExternalBuffer(T* pMemory, int numElements)
|
||||||
|
{
|
||||||
|
// Blow away any existing allocated memory
|
||||||
|
Purge();
|
||||||
|
|
||||||
|
CUtlMemory<T>::m_pMemory = (T*)Align(pMemory);
|
||||||
|
CUtlMemory<T>::m_nAllocationCount = ((int)(pMemory + numElements) - (int)CUtlMemory<T>::m_pMemory) / sizeof(T);
|
||||||
|
|
||||||
|
// Indicate that we don't own the memory
|
||||||
|
CUtlMemory<T>::m_nGrowSize = CUtlMemory<T>::EXTERNAL_BUFFER_MARKER;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, int nAlignment >
|
||||||
|
void CUtlMemoryAligned<T, nAlignment>::SetExternalBuffer(const T* pMemory, int numElements)
|
||||||
|
{
|
||||||
|
// Blow away any existing allocated memory
|
||||||
|
Purge();
|
||||||
|
|
||||||
|
CUtlMemory<T>::m_pMemory = (T*)Align(pMemory);
|
||||||
|
CUtlMemory<T>::m_nAllocationCount = ((int)(pMemory + numElements) - (int)CUtlMemory<T>::m_pMemory) / sizeof(T);
|
||||||
|
|
||||||
|
// Indicate that we don't own the memory
|
||||||
|
CUtlMemory<T>::m_nGrowSize = CUtlMemory<T>::EXTERNAL_CONST_BUFFER_MARKER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Grows the memory
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< class T, int nAlignment >
|
||||||
|
void CUtlMemoryAligned<T, nAlignment>::Grow(int num)
|
||||||
|
{
|
||||||
|
assert(num > 0);
|
||||||
|
|
||||||
|
if(this->IsExternallyAllocated()) {
|
||||||
|
// Can't grow a buffer whose memory was externally allocated
|
||||||
|
assert(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UTLMEMORY_TRACK_FREE();
|
||||||
|
|
||||||
|
// Make sure we have at least numallocated + num allocations.
|
||||||
|
// Use the grow rules specified for this memory (in m_nGrowSize)
|
||||||
|
int nAllocationRequested = CUtlMemory<T>::m_nAllocationCount + num;
|
||||||
|
|
||||||
|
CUtlMemory<T>::m_nAllocationCount = UtlMemory_CalcNewAllocationCount(CUtlMemory<T>::m_nAllocationCount, CUtlMemory<T>::m_nGrowSize, nAllocationRequested, sizeof(T));
|
||||||
|
|
||||||
|
UTLMEMORY_TRACK_ALLOC();
|
||||||
|
|
||||||
|
if(CUtlMemory<T>::m_pMemory) {
|
||||||
|
MEM_ALLOC_CREDIT_CLASS();
|
||||||
|
CUtlMemory<T>::m_pMemory = (T*)MemAlloc_ReallocAligned(CUtlMemory<T>::m_pMemory, CUtlMemory<T>::m_nAllocationCount * sizeof(T), nAlignment);
|
||||||
|
assert(CUtlMemory<T>::m_pMemory);
|
||||||
|
} else {
|
||||||
|
MEM_ALLOC_CREDIT_CLASS();
|
||||||
|
CUtlMemory<T>::m_pMemory = (T*)MemAlloc_AllocAligned(CUtlMemory<T>::m_nAllocationCount * sizeof(T), nAlignment);
|
||||||
|
assert(CUtlMemory<T>::m_pMemory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Makes sure we've got at least this much memory
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< class T, int nAlignment >
|
||||||
|
inline void CUtlMemoryAligned<T, nAlignment>::EnsureCapacity(int num)
|
||||||
|
{
|
||||||
|
if(CUtlMemory<T>::m_nAllocationCount >= num)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(this->IsExternallyAllocated()) {
|
||||||
|
// Can't grow a buffer whose memory was externally allocated
|
||||||
|
assert(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UTLMEMORY_TRACK_FREE();
|
||||||
|
|
||||||
|
CUtlMemory<T>::m_nAllocationCount = num;
|
||||||
|
|
||||||
|
UTLMEMORY_TRACK_ALLOC();
|
||||||
|
|
||||||
|
if(CUtlMemory<T>::m_pMemory) {
|
||||||
|
MEM_ALLOC_CREDIT_CLASS();
|
||||||
|
CUtlMemory<T>::m_pMemory = (T*)MemAlloc_ReallocAligned(CUtlMemory<T>::m_pMemory, CUtlMemory<T>::m_nAllocationCount * sizeof(T), nAlignment);
|
||||||
|
} else {
|
||||||
|
MEM_ALLOC_CREDIT_CLASS();
|
||||||
|
CUtlMemory<T>::m_pMemory = (T*)MemAlloc_AllocAligned(CUtlMemory<T>::m_nAllocationCount * sizeof(T), nAlignment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Memory deallocation
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< class T, int nAlignment >
|
||||||
|
void CUtlMemoryAligned<T, nAlignment>::Purge()
|
||||||
|
{
|
||||||
|
if(!this->IsExternallyAllocated()) {
|
||||||
|
if(CUtlMemory<T>::m_pMemory) {
|
||||||
|
UTLMEMORY_TRACK_FREE();
|
||||||
|
MemAlloc_FreeAligned(CUtlMemory<T>::m_pMemory);
|
||||||
|
CUtlMemory<T>::m_pMemory = 0;
|
||||||
|
}
|
||||||
|
CUtlMemory<T>::m_nAllocationCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
309
csgo2/sdk/tier1/UtlString.cpp
Normal file
309
csgo2/sdk/tier1/UtlString.cpp
Normal file
@@ -0,0 +1,309 @@
|
|||||||
|
#include "UtlString.hpp"
|
||||||
|
|
||||||
|
#define NOMINMAX
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Base class, containing simple memory management
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
CUtlBinaryBlock::CUtlBinaryBlock(int growSize, int initSize) : m_Memory(growSize, initSize)
|
||||||
|
{
|
||||||
|
m_nActualLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlBinaryBlock::CUtlBinaryBlock(void* pMemory, int nSizeInBytes, int nInitialLength) : m_Memory((unsigned char*)pMemory, nSizeInBytes)
|
||||||
|
{
|
||||||
|
m_nActualLength = nInitialLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlBinaryBlock::CUtlBinaryBlock(const void* pMemory, int nSizeInBytes) : m_Memory((const unsigned char*)pMemory, nSizeInBytes)
|
||||||
|
{
|
||||||
|
m_nActualLength = nSizeInBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlBinaryBlock::CUtlBinaryBlock(const CUtlBinaryBlock& src)
|
||||||
|
{
|
||||||
|
Set(src.Get(), src.Length());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CUtlBinaryBlock::Get(void *pValue, int nLen) const
|
||||||
|
{
|
||||||
|
assert(nLen > 0);
|
||||||
|
if(m_nActualLength < nLen) {
|
||||||
|
nLen = m_nActualLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nLen > 0) {
|
||||||
|
memcpy(pValue, m_Memory.Base(), nLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CUtlBinaryBlock::SetLength(int nLength)
|
||||||
|
{
|
||||||
|
assert(!m_Memory.IsReadOnly());
|
||||||
|
|
||||||
|
m_nActualLength = nLength;
|
||||||
|
if(nLength > m_Memory.NumAllocated()) {
|
||||||
|
int nOverFlow = nLength - m_Memory.NumAllocated();
|
||||||
|
m_Memory.Grow(nOverFlow);
|
||||||
|
|
||||||
|
// If the reallocation failed, clamp length
|
||||||
|
if(nLength > m_Memory.NumAllocated()) {
|
||||||
|
m_nActualLength = m_Memory.NumAllocated();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
if(m_Memory.NumAllocated() > m_nActualLength) {
|
||||||
|
memset(((char *)m_Memory.Base()) + m_nActualLength, 0xEB, m_Memory.NumAllocated() - m_nActualLength);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CUtlBinaryBlock::Set(const void *pValue, int nLen)
|
||||||
|
{
|
||||||
|
assert(!m_Memory.IsReadOnly());
|
||||||
|
|
||||||
|
if(!pValue) {
|
||||||
|
nLen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetLength(nLen);
|
||||||
|
|
||||||
|
if(m_nActualLength) {
|
||||||
|
if(((const char *)m_Memory.Base()) >= ((const char *)pValue) + nLen ||
|
||||||
|
((const char *)m_Memory.Base()) + m_nActualLength <= ((const char *)pValue)) {
|
||||||
|
memcpy(m_Memory.Base(), pValue, m_nActualLength);
|
||||||
|
} else {
|
||||||
|
memmove(m_Memory.Base(), pValue, m_nActualLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CUtlBinaryBlock &CUtlBinaryBlock::operator=(const CUtlBinaryBlock &src)
|
||||||
|
{
|
||||||
|
assert(!m_Memory.IsReadOnly());
|
||||||
|
Set(src.Get(), src.Length());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CUtlBinaryBlock::operator==(const CUtlBinaryBlock &src) const
|
||||||
|
{
|
||||||
|
if(src.Length() != Length())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !memcmp(src.Get(), Get(), Length());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Simple string class.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
CUtlString::CUtlString()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlString::CUtlString(const char *pString)
|
||||||
|
{
|
||||||
|
Set(pString);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlString::CUtlString(const CUtlString& string)
|
||||||
|
{
|
||||||
|
Set(string.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attaches the string to external memory. Useful for avoiding a copy
|
||||||
|
CUtlString::CUtlString(void* pMemory, int nSizeInBytes, int nInitialLength) : m_Storage(pMemory, nSizeInBytes, nInitialLength)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlString::CUtlString(const void* pMemory, int nSizeInBytes) : m_Storage(pMemory, nSizeInBytes)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CUtlString::Set(const char *pValue)
|
||||||
|
{
|
||||||
|
assert(!m_Storage.IsReadOnly());
|
||||||
|
int nLen = pValue ? strlen(pValue) + 1 : 0;
|
||||||
|
m_Storage.Set(pValue, nLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns strlen
|
||||||
|
int CUtlString::Length() const
|
||||||
|
{
|
||||||
|
return m_Storage.Length() ? m_Storage.Length() - 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the length (used to serialize into the buffer )
|
||||||
|
void CUtlString::SetLength(int nLen)
|
||||||
|
{
|
||||||
|
assert(!m_Storage.IsReadOnly());
|
||||||
|
|
||||||
|
// Add 1 to account for the NULL
|
||||||
|
m_Storage.SetLength(nLen > 0 ? nLen + 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *CUtlString::Get() const
|
||||||
|
{
|
||||||
|
if(m_Storage.Length() == 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<const char*>(m_Storage.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts to c-strings
|
||||||
|
CUtlString::operator const char*() const
|
||||||
|
{
|
||||||
|
return Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
char *CUtlString::Get()
|
||||||
|
{
|
||||||
|
assert(!m_Storage.IsReadOnly());
|
||||||
|
|
||||||
|
if(m_Storage.Length() == 0) {
|
||||||
|
// In general, we optimise away small mallocs for empty strings
|
||||||
|
// but if you ask for the non-const bytes, they must be writable
|
||||||
|
// so we can't return "" here, like we do for the const version - jd
|
||||||
|
m_Storage.SetLength(1);
|
||||||
|
m_Storage[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<char*>(m_Storage.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlString &CUtlString::operator=(const CUtlString &src)
|
||||||
|
{
|
||||||
|
assert(!m_Storage.IsReadOnly());
|
||||||
|
m_Storage = src.m_Storage;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlString &CUtlString::operator=(const char *src)
|
||||||
|
{
|
||||||
|
assert(!m_Storage.IsReadOnly());
|
||||||
|
Set(src);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CUtlString::operator==(const CUtlString &src) const
|
||||||
|
{
|
||||||
|
return m_Storage == src.m_Storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CUtlString::operator==(const char *src) const
|
||||||
|
{
|
||||||
|
return (strcmp(Get(), src) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlString &CUtlString::operator+=(const CUtlString &rhs)
|
||||||
|
{
|
||||||
|
assert(!m_Storage.IsReadOnly());
|
||||||
|
|
||||||
|
const int lhsLength(Length());
|
||||||
|
const int rhsLength(rhs.Length());
|
||||||
|
const int requestedLength(lhsLength + rhsLength);
|
||||||
|
|
||||||
|
SetLength(requestedLength);
|
||||||
|
const int allocatedLength(Length());
|
||||||
|
const int copyLength(allocatedLength - lhsLength < rhsLength ? allocatedLength - lhsLength : rhsLength);
|
||||||
|
memcpy(Get() + lhsLength, rhs.Get(), copyLength);
|
||||||
|
m_Storage[allocatedLength] = '\0';
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlString &CUtlString::operator+=(const char *rhs)
|
||||||
|
{
|
||||||
|
assert(!m_Storage.IsReadOnly());
|
||||||
|
|
||||||
|
const int lhsLength(Length());
|
||||||
|
const int rhsLength(strlen(rhs));
|
||||||
|
const int requestedLength(lhsLength + rhsLength);
|
||||||
|
|
||||||
|
SetLength(requestedLength);
|
||||||
|
const int allocatedLength(Length());
|
||||||
|
const int copyLength(allocatedLength - lhsLength < rhsLength ? allocatedLength - lhsLength : rhsLength);
|
||||||
|
memcpy(Get() + lhsLength, rhs, copyLength);
|
||||||
|
m_Storage[allocatedLength] = '\0';
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlString &CUtlString::operator+=(char c)
|
||||||
|
{
|
||||||
|
assert(!m_Storage.IsReadOnly());
|
||||||
|
|
||||||
|
int nLength = Length();
|
||||||
|
SetLength(nLength + 1);
|
||||||
|
m_Storage[nLength] = c;
|
||||||
|
m_Storage[nLength + 1] = '\0';
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlString &CUtlString::operator+=(int rhs)
|
||||||
|
{
|
||||||
|
assert(!m_Storage.IsReadOnly());
|
||||||
|
assert(sizeof(rhs) == 4);
|
||||||
|
|
||||||
|
char tmpBuf[12]; // Sufficient for a signed 32 bit integer [ -2147483648 to +2147483647 ]
|
||||||
|
snprintf(tmpBuf, sizeof(tmpBuf), "%d", rhs);
|
||||||
|
tmpBuf[sizeof(tmpBuf) - 1] = '\0';
|
||||||
|
|
||||||
|
return operator+=(tmpBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlString &CUtlString::operator+=(double rhs)
|
||||||
|
{
|
||||||
|
assert(!m_Storage.IsReadOnly());
|
||||||
|
|
||||||
|
char tmpBuf[256]; // How big can doubles be??? Dunno.
|
||||||
|
snprintf(tmpBuf, sizeof(tmpBuf), "%lg", rhs);
|
||||||
|
tmpBuf[sizeof(tmpBuf) - 1] = '\0';
|
||||||
|
|
||||||
|
return operator+=(tmpBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CUtlString::Format(const char *pFormat, ...)
|
||||||
|
{
|
||||||
|
assert(!m_Storage.IsReadOnly());
|
||||||
|
|
||||||
|
char tmpBuf[4096]; //< Nice big 4k buffer, as much memory as my first computer had, a Radio Shack Color Computer
|
||||||
|
|
||||||
|
va_list marker;
|
||||||
|
|
||||||
|
va_start(marker, pFormat);
|
||||||
|
int len = _vsnprintf_s(tmpBuf, 4096, sizeof(tmpBuf) - 1, pFormat, marker);
|
||||||
|
va_end(marker);
|
||||||
|
|
||||||
|
// Len < 0 represents an overflow
|
||||||
|
if(len < 0) {
|
||||||
|
len = sizeof(tmpBuf) - 1;
|
||||||
|
tmpBuf[sizeof(tmpBuf) - 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set(tmpBuf);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Strips the trailing slash
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CUtlString::StripTrailingSlash()
|
||||||
|
{
|
||||||
|
if(IsEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int nLastChar = Length() - 1;
|
||||||
|
char c = m_Storage[nLastChar];
|
||||||
|
if(c == '\\' || c == '/') {
|
||||||
|
m_Storage[nLastChar] = 0;
|
||||||
|
m_Storage.SetLength(m_Storage.Length() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
204
csgo2/sdk/tier1/UtlString.hpp
Normal file
204
csgo2/sdk/tier1/UtlString.hpp
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "UtlMemory.hpp"
|
||||||
|
|
||||||
|
class CUtlBinaryBlock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CUtlBinaryBlock(int growSize = 0, int initSize = 0);
|
||||||
|
|
||||||
|
// NOTE: nInitialLength indicates how much of the buffer starts full
|
||||||
|
CUtlBinaryBlock(void* pMemory, int nSizeInBytes, int nInitialLength);
|
||||||
|
CUtlBinaryBlock(const void* pMemory, int nSizeInBytes);
|
||||||
|
CUtlBinaryBlock(const CUtlBinaryBlock& src);
|
||||||
|
|
||||||
|
void Get(void *pValue, int nMaxLen) const;
|
||||||
|
void Set(const void *pValue, int nLen);
|
||||||
|
const void *Get() const;
|
||||||
|
void *Get();
|
||||||
|
|
||||||
|
unsigned char& operator[](int i);
|
||||||
|
const unsigned char& operator[](int i) const;
|
||||||
|
|
||||||
|
int Length() const;
|
||||||
|
void SetLength(int nLength); // Undefined memory will result
|
||||||
|
bool IsEmpty() const;
|
||||||
|
void Clear();
|
||||||
|
void Purge();
|
||||||
|
|
||||||
|
bool IsReadOnly() const;
|
||||||
|
|
||||||
|
CUtlBinaryBlock &operator=(const CUtlBinaryBlock &src);
|
||||||
|
|
||||||
|
// Test for equality
|
||||||
|
bool operator==(const CUtlBinaryBlock &src) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CUtlMemory<unsigned char> m_Memory;
|
||||||
|
int m_nActualLength;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// class inlines
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
inline const void *CUtlBinaryBlock::Get() const
|
||||||
|
{
|
||||||
|
return m_Memory.Base();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void *CUtlBinaryBlock::Get()
|
||||||
|
{
|
||||||
|
return m_Memory.Base();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int CUtlBinaryBlock::Length() const
|
||||||
|
{
|
||||||
|
return m_nActualLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned char& CUtlBinaryBlock::operator[](int i)
|
||||||
|
{
|
||||||
|
return m_Memory[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const unsigned char& CUtlBinaryBlock::operator[](int i) const
|
||||||
|
{
|
||||||
|
return m_Memory[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool CUtlBinaryBlock::IsReadOnly() const
|
||||||
|
{
|
||||||
|
return m_Memory.IsReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool CUtlBinaryBlock::IsEmpty() const
|
||||||
|
{
|
||||||
|
return Length() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CUtlBinaryBlock::Clear()
|
||||||
|
{
|
||||||
|
SetLength(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CUtlBinaryBlock::Purge()
|
||||||
|
{
|
||||||
|
SetLength(0);
|
||||||
|
m_Memory.Purge();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Simple string class.
|
||||||
|
// NOTE: This is *not* optimal! Use in tools, but not runtime code
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class CUtlString
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CUtlString();
|
||||||
|
CUtlString(const char *pString);
|
||||||
|
CUtlString(const CUtlString& string);
|
||||||
|
|
||||||
|
// Attaches the string to external memory. Useful for avoiding a copy
|
||||||
|
CUtlString(void* pMemory, int nSizeInBytes, int nInitialLength);
|
||||||
|
CUtlString(const void* pMemory, int nSizeInBytes);
|
||||||
|
|
||||||
|
const char *Get() const;
|
||||||
|
void Set(const char *pValue);
|
||||||
|
|
||||||
|
// Set directly and don't look for a null terminator in pValue.
|
||||||
|
void SetDirect(const char *pValue, int nChars);
|
||||||
|
|
||||||
|
// Converts to c-strings
|
||||||
|
operator const char*() const;
|
||||||
|
|
||||||
|
// for compatibility switching items from UtlSymbol
|
||||||
|
const char *String() const { return Get(); }
|
||||||
|
|
||||||
|
// Returns strlen
|
||||||
|
int Length() const;
|
||||||
|
bool IsEmpty() const;
|
||||||
|
|
||||||
|
// Sets the length (used to serialize into the buffer )
|
||||||
|
// Note: If nLen != 0, then this adds an extra uint8_t for a null-terminator.
|
||||||
|
void SetLength(int nLen);
|
||||||
|
char *Get();
|
||||||
|
void Clear();
|
||||||
|
void Purge();
|
||||||
|
|
||||||
|
// Strips the trailing slash
|
||||||
|
void StripTrailingSlash();
|
||||||
|
|
||||||
|
CUtlString &operator=(const CUtlString &src);
|
||||||
|
CUtlString &operator=(const char *src);
|
||||||
|
|
||||||
|
// Test for equality
|
||||||
|
bool operator==(const CUtlString &src) const;
|
||||||
|
bool operator==(const char *src) const;
|
||||||
|
bool operator!=(const CUtlString &src) const { return !operator==(src); }
|
||||||
|
bool operator!=(const char *src) const { return !operator==(src); }
|
||||||
|
|
||||||
|
CUtlString &operator+=(const CUtlString &rhs);
|
||||||
|
CUtlString &operator+=(const char *rhs);
|
||||||
|
CUtlString &operator+=(char c);
|
||||||
|
CUtlString &operator+=(int rhs);
|
||||||
|
CUtlString &operator+=(double rhs);
|
||||||
|
|
||||||
|
CUtlString operator+(const char *pOther);
|
||||||
|
CUtlString operator+(int rhs);
|
||||||
|
|
||||||
|
int Format(const char *pFormat, ...);
|
||||||
|
|
||||||
|
// Take a piece out of the string.
|
||||||
|
// If you only specify nStart, it'll go from nStart to the end.
|
||||||
|
// You can use negative numbers and it'll wrap around to the start.
|
||||||
|
CUtlString Slice(int32_t nStart = 0, int32_t nEnd = INT32_MAX);
|
||||||
|
|
||||||
|
// Grab a substring starting from the left or the right side.
|
||||||
|
CUtlString Left(int32_t nChars);
|
||||||
|
CUtlString Right(int32_t nChars);
|
||||||
|
|
||||||
|
// Replace all instances of one character with another.
|
||||||
|
CUtlString Replace(char cFrom, char cTo);
|
||||||
|
|
||||||
|
// Calls right through to V_MakeAbsolutePath.
|
||||||
|
CUtlString AbsPath(const char *pStartingDir = NULL);
|
||||||
|
|
||||||
|
// Gets the filename (everything except the path.. c:\a\b\c\somefile.txt -> somefile.txt).
|
||||||
|
CUtlString UnqualifiedFilename();
|
||||||
|
|
||||||
|
// Strips off one directory. Uses V_StripLastDir but strips the last slash also!
|
||||||
|
CUtlString DirName();
|
||||||
|
|
||||||
|
// Works like V_ComposeFileName.
|
||||||
|
static CUtlString PathJoin(const char *pStr1, const char *pStr2);
|
||||||
|
|
||||||
|
// These can be used for utlvector sorts.
|
||||||
|
static int __cdecl SortCaseInsensitive(const CUtlString *pString1, const CUtlString *pString2);
|
||||||
|
static int __cdecl SortCaseSensitive(const CUtlString *pString1, const CUtlString *pString2);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CUtlBinaryBlock m_Storage;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Inline methods
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
inline bool CUtlString::IsEmpty() const
|
||||||
|
{
|
||||||
|
return Length() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int __cdecl CUtlString::SortCaseInsensitive(const CUtlString *pString1, const CUtlString *pString2)
|
||||||
|
{
|
||||||
|
return _stricmp(pString1->String(), pString2->String());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int __cdecl CUtlString::SortCaseSensitive(const CUtlString *pString1, const CUtlString *pString2)
|
||||||
|
{
|
||||||
|
return strcmp(pString1->String(), pString2->String());
|
||||||
|
}
|
||||||
766
csgo2/sdk/tier1/UtlVector.hpp
Normal file
766
csgo2/sdk/tier1/UtlVector.hpp
Normal file
@@ -0,0 +1,766 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include "UtlMemory.hpp"
|
||||||
|
template <class T>
|
||||||
|
inline T* CopyConstruct(T* pMemory, T const& src)
|
||||||
|
{
|
||||||
|
return ::new(pMemory) T(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class T, class A = CUtlMemory<T> >
|
||||||
|
class CUtlVector
|
||||||
|
{
|
||||||
|
typedef T *iterator;
|
||||||
|
typedef const T *const_iterator;
|
||||||
|
typedef A CAllocator;
|
||||||
|
public:
|
||||||
|
typedef T ElemType_t;
|
||||||
|
|
||||||
|
// constructor, destructor
|
||||||
|
CUtlVector(int growSize = 0, int initSize = 0);
|
||||||
|
CUtlVector(T* pMemory, int allocationCount, int numElements = 0);
|
||||||
|
~CUtlVector();
|
||||||
|
|
||||||
|
// Copy the array.
|
||||||
|
CUtlVector<T, A>& operator=(const CUtlVector<T, A> &other);
|
||||||
|
|
||||||
|
// element access
|
||||||
|
T& operator[](int i);
|
||||||
|
const T& operator[](int i) const;
|
||||||
|
T& Element(int i);
|
||||||
|
const T& Element(int i) const;
|
||||||
|
T& Head();
|
||||||
|
const T& Head() const;
|
||||||
|
T& Tail();
|
||||||
|
const T& Tail() const;
|
||||||
|
|
||||||
|
// Gets the base address (can change when adding elements!)
|
||||||
|
T* Base() { return m_Memory.Base(); }
|
||||||
|
const T* Base() const { return m_Memory.Base(); }
|
||||||
|
// Returns the number of elements in the vector
|
||||||
|
int Count() const;
|
||||||
|
// Is element index valid?
|
||||||
|
bool IsValidIndex(int i) const;
|
||||||
|
static int InvalidIndex();
|
||||||
|
// Adds an element, uses default constructor
|
||||||
|
int AddToHead();
|
||||||
|
int AddToTail();
|
||||||
|
int InsertBefore(int elem);
|
||||||
|
int InsertAfter(int elem);
|
||||||
|
// Adds an element, uses copy constructor
|
||||||
|
int AddToHead(const T& src);
|
||||||
|
int AddToTail(const T& src);
|
||||||
|
int InsertBefore(int elem, const T& src);
|
||||||
|
int InsertAfter(int elem, const T& src);
|
||||||
|
// Adds multiple elements, uses default constructor
|
||||||
|
int AddMultipleToHead(int num);
|
||||||
|
int AddMultipleToTail(int num);
|
||||||
|
int AddMultipleToTail(int num, const T *pToCopy);
|
||||||
|
int InsertMultipleBefore(int elem, int num);
|
||||||
|
int InsertMultipleBefore(int elem, int num, const T *pToCopy);
|
||||||
|
int InsertMultipleAfter(int elem, int num);
|
||||||
|
// Calls RemoveAll() then AddMultipleToTail.
|
||||||
|
void SetSize(int size);
|
||||||
|
void SetCount(int count);
|
||||||
|
void SetCountNonDestructively(int count); //sets count by adding or removing elements to tail TODO: This should probably be the default behavior for SetCount
|
||||||
|
void CopyArray(const T *pArray, int size); //Calls SetSize and copies each element.
|
||||||
|
// Fast swap
|
||||||
|
void Swap(CUtlVector< T, A > &vec);
|
||||||
|
// Add the specified array to the tail.
|
||||||
|
int AddVectorToTail(CUtlVector<T, A> const &src);
|
||||||
|
// Finds an element (element needs operator== defined)
|
||||||
|
int GetOffset(const T& src) const;
|
||||||
|
void FillWithValue(const T& src);
|
||||||
|
bool HasElement(const T& src) const;
|
||||||
|
// Makes sure we have enough memory allocated to store a requested # of elements
|
||||||
|
void EnsureCapacity(int num);
|
||||||
|
// Makes sure we have at least this many elements
|
||||||
|
void EnsureCount(int num);
|
||||||
|
// Element removal
|
||||||
|
void FastRemove(int elem); // doesn't preserve order
|
||||||
|
void Remove(int elem); // preserves order, shifts elements
|
||||||
|
bool FindAndRemove(const T& src); // removes first occurrence of src, preserves order, shifts elements
|
||||||
|
bool FindAndFastRemove(const T& src); // removes first occurrence of src, doesn't preserve order
|
||||||
|
void RemoveMultiple(int elem, int num); // preserves order, shifts elements
|
||||||
|
void RemoveMultipleFromHead(int num); // removes num elements from tail
|
||||||
|
void RemoveMultipleFromTail(int num); // removes num elements from tail
|
||||||
|
void RemoveAll(); // doesn't deallocate memory
|
||||||
|
void Purge(); // Memory deallocation
|
||||||
|
// Purges the list and calls delete on each element in it.
|
||||||
|
void PurgeAndDeleteElements();
|
||||||
|
// Compacts the vector to the number of elements actually in use
|
||||||
|
void Compact();
|
||||||
|
// Set the size by which it grows when it needs to allocate more memory.
|
||||||
|
void SetGrowSize(int size) { m_Memory.SetGrowSize(size); }
|
||||||
|
int NumAllocated() const; // Only use this if you really know what you're doing!
|
||||||
|
void Sort(int(__cdecl *pfnCompare)(const T *, const T *));
|
||||||
|
|
||||||
|
iterator begin() { return Base(); }
|
||||||
|
const_iterator begin() const { return Base(); }
|
||||||
|
iterator end() { return Base() + Count(); }
|
||||||
|
const_iterator end() const { return Base() + Count(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Can't copy this unless we explicitly do it!
|
||||||
|
CUtlVector(CUtlVector const& vec) { assert(0); }
|
||||||
|
|
||||||
|
// Grows the vector
|
||||||
|
void GrowVector(int num = 1);
|
||||||
|
|
||||||
|
// Shifts elements....
|
||||||
|
void ShiftElementsRight(int elem, int num = 1);
|
||||||
|
void ShiftElementsLeft(int elem, int num = 1);
|
||||||
|
|
||||||
|
public:
|
||||||
|
CAllocator m_Memory;
|
||||||
|
int m_Size;
|
||||||
|
|
||||||
|
// For easier access to the elements through the debugger
|
||||||
|
// it's in release builds so this can be used in libraries correctly
|
||||||
|
T *m_pElements;
|
||||||
|
|
||||||
|
inline void ResetDbgInfo()
|
||||||
|
{
|
||||||
|
m_pElements = Base();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// constructor, destructor
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< typename T, class A >
|
||||||
|
inline CUtlVector<T, A>::CUtlVector(int growSize, int initSize) :
|
||||||
|
m_Memory(growSize, initSize), m_Size(0)
|
||||||
|
{
|
||||||
|
ResetDbgInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline CUtlVector<T, A>::CUtlVector(T* pMemory, int allocationCount, int numElements) :
|
||||||
|
m_Memory(pMemory, allocationCount), m_Size(numElements)
|
||||||
|
{
|
||||||
|
ResetDbgInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline CUtlVector<T, A>::~CUtlVector()
|
||||||
|
{
|
||||||
|
Purge();
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline CUtlVector<T, A>& CUtlVector<T, A>::operator=(const CUtlVector<T, A> &other)
|
||||||
|
{
|
||||||
|
int nCount = other.Count();
|
||||||
|
SetSize(nCount);
|
||||||
|
for(int i = 0; i < nCount; i++) {
|
||||||
|
(*this)[i] = other[i];
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// element access
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< typename T, class A >
|
||||||
|
inline T& CUtlVector<T, A>::operator[](int i)
|
||||||
|
{
|
||||||
|
assert(i < m_Size);
|
||||||
|
return m_Memory[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline const T& CUtlVector<T, A>::operator[](int i) const
|
||||||
|
{
|
||||||
|
assert(i < m_Size);
|
||||||
|
return m_Memory[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline T& CUtlVector<T, A>::Element(int i)
|
||||||
|
{
|
||||||
|
assert(i < m_Size);
|
||||||
|
return m_Memory[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline const T& CUtlVector<T, A>::Element(int i) const
|
||||||
|
{
|
||||||
|
assert(i < m_Size);
|
||||||
|
return m_Memory[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline T& CUtlVector<T, A>::Head()
|
||||||
|
{
|
||||||
|
assert(m_Size > 0);
|
||||||
|
return m_Memory[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline const T& CUtlVector<T, A>::Head() const
|
||||||
|
{
|
||||||
|
assert(m_Size > 0);
|
||||||
|
return m_Memory[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline T& CUtlVector<T, A>::Tail()
|
||||||
|
{
|
||||||
|
assert(m_Size > 0);
|
||||||
|
return m_Memory[m_Size - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline const T& CUtlVector<T, A>::Tail() const
|
||||||
|
{
|
||||||
|
assert(m_Size > 0);
|
||||||
|
return m_Memory[m_Size - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Count
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< typename T, class A >
|
||||||
|
inline int CUtlVector<T, A>::Count() const
|
||||||
|
{
|
||||||
|
return m_Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Is element index valid?
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< typename T, class A >
|
||||||
|
inline bool CUtlVector<T, A>::IsValidIndex(int i) const
|
||||||
|
{
|
||||||
|
return (i >= 0) && (i < m_Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Returns in invalid index
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< typename T, class A >
|
||||||
|
inline int CUtlVector<T, A>::InvalidIndex()
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Grows the vector
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< typename T, class A >
|
||||||
|
void CUtlVector<T, A>::GrowVector(int num)
|
||||||
|
{
|
||||||
|
if(m_Size + num > m_Memory.NumAllocated()) {
|
||||||
|
m_Memory.Grow(m_Size + num - m_Memory.NumAllocated());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Size += num;
|
||||||
|
ResetDbgInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Sorts the vector
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< typename T, class A >
|
||||||
|
void CUtlVector<T, A>::Sort(int(__cdecl *pfnCompare)(const T *, const T *))
|
||||||
|
{
|
||||||
|
typedef int(__cdecl *QSortCompareFunc_t)(const void *, const void *);
|
||||||
|
if(Count() <= 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(Base()) {
|
||||||
|
qsort(Base(), Count(), sizeof(T), (QSortCompareFunc_t)(pfnCompare));
|
||||||
|
} else {
|
||||||
|
assert(0);
|
||||||
|
// this path is untested
|
||||||
|
// if you want to sort vectors that use a non-sequential memory allocator,
|
||||||
|
// you'll probably want to patch in a quicksort algorithm here
|
||||||
|
// I just threw in this bubble sort to have something just in case...
|
||||||
|
|
||||||
|
for(int i = m_Size - 1; i >= 0; --i) {
|
||||||
|
for(int j = 1; j <= i; ++j) {
|
||||||
|
if(pfnCompare(&Element(j - 1), &Element(j)) < 0) {
|
||||||
|
V_swap(Element(j - 1), Element(j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Makes sure we have enough memory allocated to store a requested # of elements
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< typename T, class A >
|
||||||
|
void CUtlVector<T, A>::EnsureCapacity(int num)
|
||||||
|
{
|
||||||
|
MEM_ALLOC_CREDIT_CLASS();
|
||||||
|
m_Memory.EnsureCapacity(num);
|
||||||
|
ResetDbgInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Makes sure we have at least this many elements
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< typename T, class A >
|
||||||
|
void CUtlVector<T, A>::EnsureCount(int num)
|
||||||
|
{
|
||||||
|
if(Count() < num) {
|
||||||
|
AddMultipleToTail(num - Count());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Shifts elements
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< typename T, class A >
|
||||||
|
void CUtlVector<T, A>::ShiftElementsRight(int elem, int num)
|
||||||
|
{
|
||||||
|
assert(IsValidIndex(elem) || (m_Size == 0) || (num == 0));
|
||||||
|
int numToMove = m_Size - elem - num;
|
||||||
|
if((numToMove > 0) && (num > 0))
|
||||||
|
memmove(&Element(elem + num), &Element(elem), numToMove * sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
void CUtlVector<T, A>::ShiftElementsLeft(int elem, int num)
|
||||||
|
{
|
||||||
|
assert(IsValidIndex(elem) || (m_Size == 0) || (num == 0));
|
||||||
|
int numToMove = m_Size - elem - num;
|
||||||
|
if((numToMove > 0) && (num > 0)) {
|
||||||
|
memmove(&Element(elem), &Element(elem + num), numToMove * sizeof(T));
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
memset(&Element(m_Size - num), 0xDD, num * sizeof(T));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Adds an element, uses default constructor
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< typename T, class A >
|
||||||
|
inline int CUtlVector<T, A>::AddToHead()
|
||||||
|
{
|
||||||
|
return InsertBefore(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline int CUtlVector<T, A>::AddToTail()
|
||||||
|
{
|
||||||
|
return InsertBefore(m_Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline int CUtlVector<T, A>::InsertAfter(int elem)
|
||||||
|
{
|
||||||
|
return InsertBefore(elem + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
int CUtlVector<T, A>::InsertBefore(int elem)
|
||||||
|
{
|
||||||
|
// Can insert at the end
|
||||||
|
assert((elem == Count()) || IsValidIndex(elem));
|
||||||
|
|
||||||
|
GrowVector();
|
||||||
|
ShiftElementsRight(elem);
|
||||||
|
Construct(&Element(elem));
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Adds an element, uses copy constructor
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< typename T, class A >
|
||||||
|
inline int CUtlVector<T, A>::AddToHead(const T& src)
|
||||||
|
{
|
||||||
|
// Can't insert something that's in the list... reallocation may hose us
|
||||||
|
assert((Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count())));
|
||||||
|
return InsertBefore(0, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline int CUtlVector<T, A>::AddToTail(const T& src)
|
||||||
|
{
|
||||||
|
// Can't insert something that's in the list... reallocation may hose us
|
||||||
|
assert((Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count())));
|
||||||
|
return InsertBefore(m_Size, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline int CUtlVector<T, A>::InsertAfter(int elem, const T& src)
|
||||||
|
{
|
||||||
|
// Can't insert something that's in the list... reallocation may hose us
|
||||||
|
assert((Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count())));
|
||||||
|
return InsertBefore(elem + 1, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
int CUtlVector<T, A>::InsertBefore(int elem, const T& src)
|
||||||
|
{
|
||||||
|
// Can't insert something that's in the list... reallocation may hose us
|
||||||
|
assert((Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count())));
|
||||||
|
|
||||||
|
// Can insert at the end
|
||||||
|
assert((elem == Count()) || IsValidIndex(elem));
|
||||||
|
|
||||||
|
GrowVector();
|
||||||
|
ShiftElementsRight(elem);
|
||||||
|
CopyConstruct(&Element(elem), src);
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Adds multiple elements, uses default constructor
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< typename T, class A >
|
||||||
|
inline int CUtlVector<T, A>::AddMultipleToHead(int num)
|
||||||
|
{
|
||||||
|
return InsertMultipleBefore(0, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline int CUtlVector<T, A>::AddMultipleToTail(int num)
|
||||||
|
{
|
||||||
|
return InsertMultipleBefore(m_Size, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline int CUtlVector<T, A>::AddMultipleToTail(int num, const T *pToCopy)
|
||||||
|
{
|
||||||
|
// Can't insert something that's in the list... reallocation may hose us
|
||||||
|
assert((Base() == NULL) || !pToCopy || (pToCopy + num <= Base()) || (pToCopy >= (Base() + Count())));
|
||||||
|
|
||||||
|
return InsertMultipleBefore(m_Size, num, pToCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
int CUtlVector<T, A>::InsertMultipleAfter(int elem, int num)
|
||||||
|
{
|
||||||
|
return InsertMultipleBefore(elem + 1, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
void CUtlVector<T, A>::SetCount(int count)
|
||||||
|
{
|
||||||
|
RemoveAll();
|
||||||
|
AddMultipleToTail(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline void CUtlVector<T, A>::SetSize(int size)
|
||||||
|
{
|
||||||
|
SetCount(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
void CUtlVector<T, A>::SetCountNonDestructively(int count)
|
||||||
|
{
|
||||||
|
int delta = count - m_Size;
|
||||||
|
if(delta > 0) AddMultipleToTail(delta);
|
||||||
|
else if(delta < 0) RemoveMultipleFromTail(-delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
void CUtlVector<T, A>::CopyArray(const T *pArray, int size)
|
||||||
|
{
|
||||||
|
// Can't insert something that's in the list... reallocation may hose us
|
||||||
|
assert((Base() == NULL) || !pArray || (Base() >= (pArray + size)) || (pArray >= (Base() + Count())));
|
||||||
|
|
||||||
|
SetSize(size);
|
||||||
|
for(int i = 0; i < size; i++) {
|
||||||
|
(*this)[i] = pArray[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
void CUtlVector<T, A>::Swap(CUtlVector< T, A > &vec)
|
||||||
|
{
|
||||||
|
m_Memory.Swap(vec.m_Memory);
|
||||||
|
V_swap(m_Size, vec.m_Size);
|
||||||
|
#ifndef _X360
|
||||||
|
V_swap(m_pElements, vec.m_pElements);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
int CUtlVector<T, A>::AddVectorToTail(CUtlVector const &src)
|
||||||
|
{
|
||||||
|
assert(&src != this);
|
||||||
|
|
||||||
|
int base = Count();
|
||||||
|
|
||||||
|
// Make space.
|
||||||
|
int nSrcCount = src.Count();
|
||||||
|
EnsureCapacity(base + nSrcCount);
|
||||||
|
|
||||||
|
// Copy the elements.
|
||||||
|
m_Size += nSrcCount;
|
||||||
|
for(int i = 0; i < nSrcCount; i++) {
|
||||||
|
CopyConstruct(&Element(base + i), src[i]);
|
||||||
|
}
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline int CUtlVector<T, A>::InsertMultipleBefore(int elem, int num)
|
||||||
|
{
|
||||||
|
if(num == 0)
|
||||||
|
return elem;
|
||||||
|
|
||||||
|
// Can insert at the end
|
||||||
|
assert((elem == Count()) || IsValidIndex(elem));
|
||||||
|
|
||||||
|
GrowVector(num);
|
||||||
|
ShiftElementsRight(elem, num);
|
||||||
|
|
||||||
|
// Invoke default constructors
|
||||||
|
for(int i = 0; i < num; ++i) {
|
||||||
|
Construct(&Element(elem + i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline int CUtlVector<T, A>::InsertMultipleBefore(int elem, int num, const T *pToInsert)
|
||||||
|
{
|
||||||
|
if(num == 0)
|
||||||
|
return elem;
|
||||||
|
|
||||||
|
// Can insert at the end
|
||||||
|
assert((elem == Count()) || IsValidIndex(elem));
|
||||||
|
|
||||||
|
GrowVector(num);
|
||||||
|
ShiftElementsRight(elem, num);
|
||||||
|
|
||||||
|
// Invoke default constructors
|
||||||
|
if(!pToInsert) {
|
||||||
|
for(int i = 0; i < num; ++i) {
|
||||||
|
Construct(&Element(elem + i));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(int i = 0; i < num; i++) {
|
||||||
|
CopyConstruct(&Element(elem + i), pToInsert[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Finds an element (element needs operator== defined)
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< typename T, class A >
|
||||||
|
int CUtlVector<T, A>::GetOffset(const T& src) const
|
||||||
|
{
|
||||||
|
for(int i = 0; i < Count(); ++i) {
|
||||||
|
if(Element(i) == src)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
void CUtlVector<T, A>::FillWithValue(const T& src)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < Count(); i++) {
|
||||||
|
Element(i) = src;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
bool CUtlVector<T, A>::HasElement(const T& src) const
|
||||||
|
{
|
||||||
|
return (GetOffset(src) >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Element removal
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template< typename T, class A >
|
||||||
|
void CUtlVector<T, A>::FastRemove(int elem)
|
||||||
|
{
|
||||||
|
assert(IsValidIndex(elem));
|
||||||
|
|
||||||
|
Destruct(&Element(elem));
|
||||||
|
if(m_Size > 0) {
|
||||||
|
if(elem != m_Size - 1)
|
||||||
|
memcpy(&Element(elem), &Element(m_Size - 1), sizeof(T));
|
||||||
|
--m_Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
void CUtlVector<T, A>::Remove(int elem)
|
||||||
|
{
|
||||||
|
Destruct(&Element(elem));
|
||||||
|
ShiftElementsLeft(elem);
|
||||||
|
--m_Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
bool CUtlVector<T, A>::FindAndRemove(const T& src)
|
||||||
|
{
|
||||||
|
int elem = GetOffset(src);
|
||||||
|
if(elem != -1) {
|
||||||
|
Remove(elem);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
bool CUtlVector<T, A>::FindAndFastRemove(const T& src)
|
||||||
|
{
|
||||||
|
int elem = GetOffset(src);
|
||||||
|
if(elem != -1) {
|
||||||
|
FastRemove(elem);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
void CUtlVector<T, A>::RemoveMultiple(int elem, int num)
|
||||||
|
{
|
||||||
|
assert(elem >= 0);
|
||||||
|
assert(elem + num <= Count());
|
||||||
|
|
||||||
|
for(int i = elem + num; --i >= elem; )
|
||||||
|
Destruct(&Element(i));
|
||||||
|
|
||||||
|
ShiftElementsLeft(elem, num);
|
||||||
|
m_Size -= num;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
void CUtlVector<T, A>::RemoveMultipleFromHead(int num)
|
||||||
|
{
|
||||||
|
assert(num <= Count());
|
||||||
|
|
||||||
|
for(int i = num; --i >= 0; )
|
||||||
|
Destruct(&Element(i));
|
||||||
|
|
||||||
|
ShiftElementsLeft(0, num);
|
||||||
|
m_Size -= num;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
void CUtlVector<T, A>::RemoveMultipleFromTail(int num)
|
||||||
|
{
|
||||||
|
assert(num <= Count());
|
||||||
|
|
||||||
|
for(int i = m_Size - num; i < m_Size; i++)
|
||||||
|
Destruct(&Element(i));
|
||||||
|
|
||||||
|
m_Size -= num;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
void CUtlVector<T, A>::RemoveAll()
|
||||||
|
{
|
||||||
|
for(int i = m_Size; --i >= 0; ) {
|
||||||
|
Destruct(&Element(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Memory deallocation
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline void CUtlVector<T, A>::Purge()
|
||||||
|
{
|
||||||
|
RemoveAll();
|
||||||
|
m_Memory.Purge();
|
||||||
|
ResetDbgInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline void CUtlVector<T, A>::PurgeAndDeleteElements()
|
||||||
|
{
|
||||||
|
for(int i = 0; i < m_Size; i++) {
|
||||||
|
delete Element(i);
|
||||||
|
}
|
||||||
|
Purge();
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline void CUtlVector<T, A>::Compact()
|
||||||
|
{
|
||||||
|
m_Memory.Purge(m_Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T, class A >
|
||||||
|
inline int CUtlVector<T, A>::NumAllocated() const
|
||||||
|
{
|
||||||
|
return m_Memory.NumAllocated();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Data and memory validation
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifdef DBGFLAG_VALIDATE
|
||||||
|
template< typename T, class A >
|
||||||
|
void CUtlVector<T, A>::Validate(CValidator &validator, char *pchName)
|
||||||
|
{
|
||||||
|
validator.Push(typeid(*this).name(), this, pchName);
|
||||||
|
|
||||||
|
m_Memory.Validate(validator, "m_Memory");
|
||||||
|
|
||||||
|
validator.Pop();
|
||||||
|
}
|
||||||
|
#endif // DBGFLAG_VALIDATE
|
||||||
|
|
||||||
|
// A vector class for storing pointers, so that the elements pointed to by the pointers are deleted
|
||||||
|
// on exit.
|
||||||
|
template<class T> class CUtlVectorAutoPurge : public CUtlVector< T, CUtlMemory< T, int> >
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~CUtlVectorAutoPurge(void)
|
||||||
|
{
|
||||||
|
this->PurgeAndDeleteElements();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// easy string list class with dynamically allocated strings. For use with V_SplitString, etc.
|
||||||
|
// Frees the dynamic strings in destructor.
|
||||||
|
class CUtlStringList : public CUtlVectorAutoPurge< char *>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void CopyAndAddToTail(char const *pString) // clone the string and add to the end
|
||||||
|
{
|
||||||
|
char *pNewStr = new char[1 + strlen(pString)];
|
||||||
|
strcpy_s(pNewStr, 1 + strlen(pString), pString);
|
||||||
|
AddToTail(pNewStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __cdecl SortFunc(char * const * sz1, char * const * sz2)
|
||||||
|
{
|
||||||
|
return strcmp(*sz1, *sz2);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
272
csgo2/sdk/tier1/bufferstring.h
Normal file
272
csgo2/sdk/tier1/bufferstring.h
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../sdk.h"
|
||||||
|
#define DLL_CLASS_IMPORT __declspec( dllimport )
|
||||||
|
|
||||||
|
class CFormatStringElement;
|
||||||
|
class IFormatOutputStream;
|
||||||
|
|
||||||
|
template<size_t MAX_SIZE, bool AllowHeapAllocation>
|
||||||
|
class CBufferStringGrowable;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Main idea of CBufferString is to provide the base class for the CBufferStringGrowable wich implements stack allocation
|
||||||
|
with the ability to convert to the heap allocation if allowed.
|
||||||
|
|
||||||
|
Example usage of CBufferStringGrowable class:
|
||||||
|
|
||||||
|
* Basic buffer allocation:
|
||||||
|
```
|
||||||
|
CBufferStringGrowable<256> buff;
|
||||||
|
buff.Insert(0, "Hello World!");
|
||||||
|
printf("Result: %s\n", buff.Get());
|
||||||
|
```
|
||||||
|
additionaly the heap allocation of the buffer could be disabled, by providing ``AllowHeapAllocation`` template argument,
|
||||||
|
by disabling heap allocation, if the buffer capacity is not enough to perform the operation, the app would exit with an Assert;
|
||||||
|
|
||||||
|
* Additional usage:
|
||||||
|
CBufferString::IsStackAllocated() - could be used to check if the buffer is stack allocated;
|
||||||
|
CBufferString::IsHeapAllocated() - could be used to check if the buffer is heap allocated;
|
||||||
|
CBufferString::Get() - would return a pointer to the data, or an empty string if it's not allocated.
|
||||||
|
|
||||||
|
* Additionaly current length of the buffer could be read via CBufferString::GetTotalNumber()
|
||||||
|
and currently allocated amount of bytes could be read via CBufferString::GetAllocatedNumber()
|
||||||
|
|
||||||
|
* Most, if not all the functions would ensure the buffer capacity and enlarge it when needed,
|
||||||
|
in case of stack allocated buffers, it would switch to heap allocation instead.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class CBufferString
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
// You shouldn't be initializing this class, use CBufferStringGrowable instead.
|
||||||
|
CBufferString() {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum EAllocationOption_t
|
||||||
|
{
|
||||||
|
UNK1 = -1,
|
||||||
|
UNK2 = 0,
|
||||||
|
UNK3 = (1 << 1),
|
||||||
|
UNK4 = (1 << 8),
|
||||||
|
UNK5 = (1 << 9),
|
||||||
|
ALLOW_HEAP_ALLOCATION = (1 << 31)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EAllocationFlags_t
|
||||||
|
{
|
||||||
|
LENGTH_MASK = (1 << 30) - 1,
|
||||||
|
FLAGS_MASK = ~LENGTH_MASK,
|
||||||
|
|
||||||
|
STACK_ALLOCATION_MARKER = (1 << 30),
|
||||||
|
HEAP_ALLOCATION_MARKER = (1 << 31)
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
DLL_CLASS_IMPORT const char *AppendConcat(int, const char * const *, const int *, bool bIgnoreAlignment = false);
|
||||||
|
DLL_CLASS_IMPORT const char *AppendConcat(const char *, const char *, ...) FMTFUNCTION(3, 4);
|
||||||
|
DLL_CLASS_IMPORT const char *AppendConcatV(const char *, const char *, va_list, bool bIgnoreAlignment = false);
|
||||||
|
DLL_CLASS_IMPORT const char *Concat(const char *, const char *, ...) FMTFUNCTION(3, 4);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT int AppendFormat(const char *pFormat, ...) FMTFUNCTION(2, 3);
|
||||||
|
DLL_CLASS_IMPORT int AppendFormatV(const char *pFormat, va_list pData);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT const char *AppendRepeat(char cChar, int nChars, bool bIgnoreAlignment = false);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT const char *ComposeFileName(const char *pPath, const char *pFile, char cSeparator);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT const char *ConvertIn(unsigned int const *pData, int nSize, bool bIgnoreAlignment = false);
|
||||||
|
DLL_CLASS_IMPORT const char *ConvertIn(wchar_t const *pData, int nSize, bool bIgnoreAlignment = false);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT const char *DefaultExtension(const char *pExt);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT bool EndsWith(const char *pMatch) const;
|
||||||
|
DLL_CLASS_IMPORT bool EndsWith_FastCaseInsensitive(const char *pMatch) const;
|
||||||
|
|
||||||
|
// Ensures the nCapacity condition is met and grows the local buffer if needed.
|
||||||
|
// Returns pResultingBuffer pointer to the newly allocated data, as well as resulting capacity that was allocated in bytes.
|
||||||
|
DLL_CLASS_IMPORT int EnsureCapacity(int nCapacity, char **pResultingBuffer, bool bIgnoreAlignment = false, bool bForceGrow = true);
|
||||||
|
DLL_CLASS_IMPORT int EnsureAddedCapacity(int nCapacity, char **pResultingBuffer, bool bIgnoreAlignment = false, bool bForceGrow = true);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT char *EnsureLength(int nCapacity, bool bIgnoreAlignment = false, int *pNewCapacity = NULL);
|
||||||
|
DLL_CLASS_IMPORT char *EnsureOwnedAllocation(CBufferString::EAllocationOption_t eAlloc);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT const char *EnsureTrailingSlash(char cSeparator, bool bDontAppendIfEmpty = true);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT const char *ExtendPath(const char *pPath, char cSeparator);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT const char *ExtractFileBase(const char *pPath);
|
||||||
|
DLL_CLASS_IMPORT const char *ExtractFileExtension(const char *pPath);
|
||||||
|
DLL_CLASS_IMPORT const char *ExtractFilePath(const char *pPath, bool);
|
||||||
|
DLL_CLASS_IMPORT const char *ExtractFirstDir(const char *pPath);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT const char *FixSlashes(char cSeparator = CORRECT_PATH_SEPARATOR);
|
||||||
|
DLL_CLASS_IMPORT const char *FixupPathName(char cSeparator);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT int Format(const char *pFormat, ...) FMTFUNCTION(2, 3);
|
||||||
|
DLL_CLASS_IMPORT void FormatTo(IFormatOutputStream* pOutputStream, CFormatStringElement pElement) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Returns aligned size based on capacity requested
|
||||||
|
DLL_CLASS_IMPORT static int GetAllocChars(int nSize, int nCapacity);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Inserts the nCount bytes of data from pBuf buffer at nIndex position.
|
||||||
|
// If nCount is -1, it would count the bytes of the input buffer manualy.
|
||||||
|
// Returns the resulting char buffer (Same as to what CBufferString->Get() returns).
|
||||||
|
DLL_CLASS_IMPORT const char *Insert(int nIndex, const char *pBuf, int nCount = -1, bool bIgnoreAlignment = false);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT char *GetInsertPtr(int nIndex, int nChars, bool bIgnoreAlignment = false, int *pNewCapacity = NULL);
|
||||||
|
DLL_CLASS_IMPORT char *GetReplacePtr(int nIndex, int nOldChars, int nNewChars, bool bIgnoreAlignment = false, int *pNewCapacity = NULL);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT int GrowByChunks(int, int);
|
||||||
|
|
||||||
|
// Wrapper around V_MakeAbsolutePath()
|
||||||
|
DLL_CLASS_IMPORT const char *MakeAbsolutePath(const char *pPath, const char *pStartingDir);
|
||||||
|
// Wrapper around V_MakeAbsolutePath() but also does separator fixup
|
||||||
|
DLL_CLASS_IMPORT const char *MakeFixedAbsolutePath(const char *pPath, const char *pStartingDir, char cSeparator = CORRECT_PATH_SEPARATOR);
|
||||||
|
// Wrapper around V_MakeRelativePath()
|
||||||
|
DLL_CLASS_IMPORT const char *MakeRelativePath(const char *pFullPath, const char *pDirectory);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT void MoveFrom(CBufferString &pOther);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT void Purge(int nLength);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT char *Relinquish(CBufferString::EAllocationOption_t eAlloc);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT const char *RemoveAt(int nIndex, int nChars);
|
||||||
|
DLL_CLASS_IMPORT const char *RemoveAtUTF8(int nByteIndex, int nCharacters);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT const char *RemoveDotSlashes(char cSeparator);
|
||||||
|
DLL_CLASS_IMPORT int RemoveWhitespace();
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT const char *RemoveFilePath();
|
||||||
|
DLL_CLASS_IMPORT const char *RemoveFirstDir(CBufferString *pRemovedDir);
|
||||||
|
DLL_CLASS_IMPORT const char *RemoveToFileBase();
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT bool RemovePartialUTF8Tail(bool);
|
||||||
|
DLL_CLASS_IMPORT const char *RemoveTailUTF8(int nIndex);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT int Replace(char cFrom, char cTo);
|
||||||
|
DLL_CLASS_IMPORT int Replace(const char *pMatch, const char *pReplace, bool bDontUseStrStr = false);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT const char *ReplaceAt(int nIndex, int nOldChars, const char *pData, int nDataLen = -1, bool bIgnoreAlignment = false);
|
||||||
|
DLL_CLASS_IMPORT const char *ReplaceAt(int nIndex, const char *pData, int nDataLen = -1, bool bIgnoreAlignment = false);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT const char *ReverseChars(int nIndex, int nChars);
|
||||||
|
|
||||||
|
// Appends the pExt to the local buffer, also appends '.' in between even if it wasn't provided in pExt.
|
||||||
|
DLL_CLASS_IMPORT const char *SetExtension(const char *pExt);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT char *SetLength(int nLen, bool bIgnoreAlignment = false, int *pNewCapacity = NULL);
|
||||||
|
DLL_CLASS_IMPORT void SetPtr(char *pBuf, int nBufferChars, int, bool, bool);
|
||||||
|
|
||||||
|
// Frees the buffer (if it was heap allocated) and writes "~DSTRCT" to the local buffer.
|
||||||
|
DLL_CLASS_IMPORT void SetUnusable();
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT const char *ShortenPath(bool);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT bool StartsWith(const char *pMatch) const;
|
||||||
|
DLL_CLASS_IMPORT bool StartsWith_FastCaseInsensitive(const char *pMatch) const;
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT const char *StrAppendFormat(const char *pFormat, ...) FMTFUNCTION(2, 3);
|
||||||
|
DLL_CLASS_IMPORT const char *StrFormat(const char *pFormat, ...) FMTFUNCTION(2, 3);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT const char *StripExtension();
|
||||||
|
DLL_CLASS_IMPORT const char *StripTrailingSlash();
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT void ToLowerFast(int nStart);
|
||||||
|
DLL_CLASS_IMPORT void ToUpperFast(int nStart);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT const char *Trim(const char *pTrimChars = "\t\r\n ");
|
||||||
|
DLL_CLASS_IMPORT const char *TrimHead(const char *pTrimChars = "\t\r\n ");
|
||||||
|
DLL_CLASS_IMPORT const char *TrimTail(const char *pTrimChars = "\t\r\n ");
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT const char *TruncateAt(int nIndex, bool bIgnoreAlignment = false);
|
||||||
|
DLL_CLASS_IMPORT const char *TruncateAt(const char *pStr, bool bIgnoreAlignment = false);
|
||||||
|
|
||||||
|
DLL_CLASS_IMPORT int UnicodeCaseConvert(int, EStringConvertErrorPolicy eErrorPolicy);
|
||||||
|
|
||||||
|
// Casts to CBufferStringGrowable. Very dirty solution until someone figures out the sane one.
|
||||||
|
template<size_t MAX_SIZE = 8, bool AllowHeapAllocation = true, typename T = CBufferStringGrowable<MAX_SIZE, AllowHeapAllocation>>
|
||||||
|
T *ToGrowable()
|
||||||
|
{
|
||||||
|
return (T *)this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<size_t MAX_SIZE, bool AllowHeapAllocation = true>
|
||||||
|
class CBufferStringGrowable : public CBufferString
|
||||||
|
{
|
||||||
|
friend class CBufferString;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CBufferStringGrowable() : m_nAllocated(STACK_ALLOCATION_MARKER | (MAX_SIZE & LENGTH_MASK)), m_nTotalCount(0), m_Memory()
|
||||||
|
{
|
||||||
|
if (AllowHeapAllocation)
|
||||||
|
{
|
||||||
|
m_nAllocated |= ALLOW_HEAP_ALLOCATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~CBufferStringGrowable()
|
||||||
|
{
|
||||||
|
if (IsHeapAllocated() && m_Memory.m_pString)
|
||||||
|
{
|
||||||
|
#if PLATFORM_WINDOWS
|
||||||
|
g_pMemAlloc->Free((void*)m_Memory.m_pString);
|
||||||
|
#else
|
||||||
|
delete[] m_Memory.m_pString;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int GetAllocatedNumber() const
|
||||||
|
{
|
||||||
|
return m_nAllocated & LENGTH_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int GetTotalNumber() const
|
||||||
|
{
|
||||||
|
return m_nTotalCount & LENGTH_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsStackAllocated() const
|
||||||
|
{
|
||||||
|
return (m_nAllocated & STACK_ALLOCATION_MARKER) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsHeapAllocated() const
|
||||||
|
{
|
||||||
|
return (m_nTotalCount & HEAP_ALLOCATION_MARKER) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsInputStringUnsafe(const char *pData) const
|
||||||
|
{
|
||||||
|
return ((void *)pData >= this && (void *)pData < &this[1]) ||
|
||||||
|
(GetAllocatedNumber() != 0 && pData >= Get() && pData < (Get() + GetAllocatedNumber()));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *Get() const
|
||||||
|
{
|
||||||
|
if (IsStackAllocated())
|
||||||
|
{
|
||||||
|
return m_Memory.m_szString;
|
||||||
|
}
|
||||||
|
else if (GetAllocatedNumber() != 0)
|
||||||
|
{
|
||||||
|
return m_Memory.m_pString;
|
||||||
|
}
|
||||||
|
|
||||||
|
return StringFuncs<char>::EmptyString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_nTotalCount;
|
||||||
|
int m_nAllocated;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
const char *m_pString;
|
||||||
|
const char m_szString[MAX_SIZE];
|
||||||
|
} m_Memory;
|
||||||
|
};
|
||||||
226
csgo2/stb.hh
Normal file
226
csgo2/stb.hh
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
/**
|
||||||
|
* @file stb.hh
|
||||||
|
* @author Cristei Gabriel-Marian (cristei.g772@gmail.com)
|
||||||
|
* @brief Compile-time String To Bytes (STB)
|
||||||
|
* @version 1.0
|
||||||
|
* @date 2023-03-23
|
||||||
|
*
|
||||||
|
* Last update: 03/23/2023 (mm/dd/yyyy): [Breaking update]
|
||||||
|
* Modernize, undo some cancer, change some naming, file structure,
|
||||||
|
* implement tests directly in file.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef STB_DEFINED
|
||||||
|
#define STB_DEFINED
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
namespace stb {
|
||||||
|
namespace detail {
|
||||||
|
// detail methods assume null terminator.
|
||||||
|
|
||||||
|
template<std::size_t N>
|
||||||
|
constexpr auto find_first_of_start(std::array<char, N> const& data, std::size_t start, char ch) noexcept {
|
||||||
|
std::size_t idx = start;
|
||||||
|
while (data[idx] != ch && idx < N)
|
||||||
|
++idx;
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N>
|
||||||
|
constexpr auto find_first_not_of_start(std::array<char, N> const& data, std::size_t start, char ch) noexcept {
|
||||||
|
if (start < N && data[start] != ch)
|
||||||
|
return start;
|
||||||
|
|
||||||
|
std::size_t idx = start;
|
||||||
|
while (data[idx] == ch && idx < N)
|
||||||
|
++idx;
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N>
|
||||||
|
constexpr auto find_last_of(std::array<char, N> const& data, char ch) noexcept {
|
||||||
|
std::size_t idx = data.size() - 2;
|
||||||
|
while (data[idx] != ch && idx >= 0)
|
||||||
|
--idx;
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N>
|
||||||
|
constexpr auto find_last_not_of(std::array<char, N> const& data, char ch) noexcept {
|
||||||
|
std::size_t idx = data.size() - 2;
|
||||||
|
while (data[idx] == ch && idx >= 0)
|
||||||
|
--idx;
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto char_to_hex(char ch) noexcept {
|
||||||
|
if (ch >= '0' && ch <= '9')
|
||||||
|
return ch - '0';
|
||||||
|
|
||||||
|
if (ch >= 'A' && ch <= 'F')
|
||||||
|
return ch - 'A' + 10;
|
||||||
|
|
||||||
|
return ch - 'a' + 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, T F = 16>
|
||||||
|
constexpr T concat_hex(T lhs, T rhs) noexcept {
|
||||||
|
return F * lhs + rhs;
|
||||||
|
}
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<auto V>
|
||||||
|
struct consteval_value {
|
||||||
|
constexpr static decltype(V) value = V;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<std::size_t N>
|
||||||
|
struct fixed_string: public std::array<char, N + 1> {
|
||||||
|
using std::array<char, N + 1>::array;
|
||||||
|
|
||||||
|
constexpr fixed_string(const char* str) noexcept
|
||||||
|
: std::array<char, N + 1>() {
|
||||||
|
for (auto i = 0; i != N; ++i)
|
||||||
|
(*this)[i] = str[i];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<std::size_t N>
|
||||||
|
fixed_string(const char (&)[N]) noexcept -> fixed_string<N - 1>;
|
||||||
|
|
||||||
|
template<char delimiter, char mask, typename element_type, element_type masked>
|
||||||
|
struct basic_hex_string_array_conversion {
|
||||||
|
template<fixed_string str>
|
||||||
|
struct build {
|
||||||
|
private:
|
||||||
|
struct parse {
|
||||||
|
struct result {
|
||||||
|
std::size_t delimiter_count;
|
||||||
|
std::size_t start;
|
||||||
|
std::size_t next;
|
||||||
|
std::size_t end;
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr static auto get() noexcept {
|
||||||
|
std::size_t count = 1;
|
||||||
|
|
||||||
|
constexpr std::size_t start = detail::find_first_not_of_start(str, 0, delimiter);
|
||||||
|
constexpr std::size_t next = detail::find_first_of_start(str, start, delimiter);
|
||||||
|
constexpr std::size_t end = detail::find_last_not_of(str, delimiter);
|
||||||
|
|
||||||
|
bool previous_delimiter = false;
|
||||||
|
for (auto i = next; i < end; ++i) {
|
||||||
|
if (str[i] == delimiter) {
|
||||||
|
if (!previous_delimiter)
|
||||||
|
++count;
|
||||||
|
|
||||||
|
previous_delimiter = true;
|
||||||
|
} else
|
||||||
|
previous_delimiter = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result {
|
||||||
|
count,
|
||||||
|
start,
|
||||||
|
next,
|
||||||
|
end};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr static auto make() noexcept {
|
||||||
|
constexpr auto data = parse::get();
|
||||||
|
constexpr auto count = data.delimiter_count;
|
||||||
|
constexpr auto start = data.start;
|
||||||
|
constexpr auto next = data.next;
|
||||||
|
constexpr auto end = data.end;
|
||||||
|
|
||||||
|
std::array<element_type, count> result = {};
|
||||||
|
std::array<std::size_t, count> skips = {};
|
||||||
|
std::size_t skipped = 0;
|
||||||
|
std::size_t traversed = start;
|
||||||
|
|
||||||
|
bool previous_skip = false;
|
||||||
|
for (auto i = start; i < end; ++i) {
|
||||||
|
if (str[i] == delimiter) {
|
||||||
|
if (!previous_skip)
|
||||||
|
skips[skipped++] = traversed;
|
||||||
|
|
||||||
|
previous_skip = true;
|
||||||
|
} else
|
||||||
|
previous_skip = false;
|
||||||
|
|
||||||
|
++traversed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool one_char = str[start + 1] == delimiter;
|
||||||
|
result[0] = static_cast<element_type>(str[start] == mask ? masked : (one_char ? detail::char_to_hex(str[start]) : detail::concat_hex(detail::char_to_hex(str[start]), detail::char_to_hex(str[start + 1]))));
|
||||||
|
|
||||||
|
std::size_t conversions = 1;
|
||||||
|
for (auto i = next; i < end; ++i) {
|
||||||
|
for (auto entry : skips) {
|
||||||
|
if (entry == i && entry < end) {
|
||||||
|
std::size_t idx = detail::find_first_not_of_start(str, i + 1, delimiter);
|
||||||
|
one_char = str[idx + 1] == delimiter;
|
||||||
|
result[conversions++] = static_cast<element_type>(str[idx] == mask ? masked : (one_char ? detail::char_to_hex(str[idx]) : detail::concat_hex(detail::char_to_hex(str[idx]), detail::char_to_hex(str[idx + 1]))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr static auto value = consteval_value<make()>::value;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
using hex_string_array_conversion = basic_hex_string_array_conversion<' ', '?', int, -1>;
|
||||||
|
using simple_conversion = hex_string_array_conversion;
|
||||||
|
} // namespace stb
|
||||||
|
|
||||||
|
#ifndef STB_OMIT_TESTS
|
||||||
|
struct _ignore_me_stb_compliance_tests {
|
||||||
|
using conv_type = stb::simple_conversion;
|
||||||
|
|
||||||
|
constexpr static auto value_1 = conv_type::build<"AA BB CC DD EE FF">::value;
|
||||||
|
static_assert(value_1[0] == 0xAA);
|
||||||
|
static_assert(value_1[1] == 0xBB);
|
||||||
|
static_assert(value_1[2] == 0xCC);
|
||||||
|
static_assert(value_1[3] == 0xDD);
|
||||||
|
static_assert(value_1[4] == 0xEE);
|
||||||
|
static_assert(value_1[5] == 0xFF);
|
||||||
|
static_assert(value_1.size() == 6);
|
||||||
|
|
||||||
|
constexpr static auto value_2 = conv_type::build<" C 0f C a B ef ">::value;
|
||||||
|
static_assert(value_2[0] == 0x0C);
|
||||||
|
static_assert(value_2[1] == 0x0F);
|
||||||
|
static_assert(value_2[2] == 0x0C);
|
||||||
|
static_assert(value_2[3] == 0x0A);
|
||||||
|
static_assert(value_2[4] == 0x0B);
|
||||||
|
static_assert(value_2[5] == 0xEF);
|
||||||
|
static_assert(value_2.size() == 6);
|
||||||
|
|
||||||
|
constexpr static auto value_3 = conv_type::build<"AA bb CC dd ">::value;
|
||||||
|
static_assert(value_3[0] == 0xAA);
|
||||||
|
static_assert(value_3[1] == 0xBB);
|
||||||
|
static_assert(value_3[2] == 0xCC);
|
||||||
|
static_assert(value_3[3] == 0xDD);
|
||||||
|
static_assert(value_3.size() == 4);
|
||||||
|
|
||||||
|
constexpr static auto value_4 = conv_type::build<" aa bb ee ff">::value;
|
||||||
|
static_assert(value_4[0] == 0xAA);
|
||||||
|
static_assert(value_4[1] == 0xBB);
|
||||||
|
static_assert(value_4[2] == 0xEE);
|
||||||
|
static_assert(value_4[3] == 0xFF);
|
||||||
|
static_assert(value_4.size() == 4);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
1
csgo2/vmt.cpp
Normal file
1
csgo2/vmt.cpp
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#include "vmt.h"
|
||||||
19
csgo2/vmt.h
Normal file
19
csgo2/vmt.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#define CALL_VIRTUAL(retType, idx, ...) \
|
||||||
|
vmt::CallVirtual<retType>(idx, __VA_ARGS__)
|
||||||
|
namespace vmt {
|
||||||
|
template <typename T = void*>
|
||||||
|
inline T GetVMethod(uint32_t uIndex, void* pClass) {
|
||||||
|
void** pVTable = *static_cast<void***>(pClass);
|
||||||
|
return reinterpret_cast<T>(pVTable[uIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
inline T CallVirtual(uint32_t uIndex, void* pClass, Args... args) {
|
||||||
|
auto pFunc = GetVMethod<T(__thiscall*)(void*, Args...)>(uIndex, pClass);
|
||||||
|
return pFunc(pClass, args...);
|
||||||
|
}
|
||||||
|
} // namespace vmt
|
||||||
|
|
||||||
Reference in New Issue
Block a user