mirror of
https://github.com/CrazyRedMachine/popnhax.git
synced 2024-11-23 22:00:57 +01:00
Omnimix v2
This commit is contained in:
parent
86d7046bbc
commit
698e9c5476
275
Makefile
Normal file
275
Makefile
Normal file
@ -0,0 +1,275 @@
|
||||
# vim: noexpandtab sts=8 sw=8 ts=8
|
||||
|
||||
#
|
||||
# Overridable variables
|
||||
#
|
||||
|
||||
export SHELL := /bin/bash
|
||||
BUILDDIR ?= build
|
||||
|
||||
#
|
||||
# Internal variables
|
||||
#
|
||||
|
||||
export TZ := /usr/share/zoneinfo/Japan
|
||||
|
||||
ifeq ($(USE_CCACHE),yes)
|
||||
ccache := ccache
|
||||
else
|
||||
ccache :=
|
||||
endif
|
||||
|
||||
depdir := $(BUILDDIR)/dep
|
||||
objdir := $(BUILDDIR)/obj
|
||||
bindir := $(BUILDDIR)/bin
|
||||
|
||||
toolchain_32 := i686-w64-mingw32-
|
||||
toolchain_64 := x86_64-w64-mingw32-
|
||||
|
||||
cppflags := -I. \
|
||||
-DNDEBUG \
|
||||
-D_NEED_FULLVERSION_INFO=1 -D_SECURE_SCL=1 \
|
||||
-D_CRT_SECURE_NO_WARNINGS=1 -D_NO_CRT_STDIO_INLINE=1 \
|
||||
-D_WINSOCK_DEPRECATED_NO_WARNINGS=1 \
|
||||
-DFKG_FORCED_USAGE=1 -DOFFICIAL_BUILD=1 -DBETA=1 -DDEVL=1
|
||||
|
||||
com_wflags := -Wall -Werror -Wpointer-arith -Wreturn-type \
|
||||
-Wwrite-strings -Wswitch -Wcast-align -Wchar-subscripts \
|
||||
-Wredundant-decls -Wunreachable-code -Wno-pedantic \
|
||||
-Wshadow -Winline -Wno-cast-qual -Wno-multichar \
|
||||
-fstrict-aliasing -Wno-unused-function \
|
||||
-Warray-bounds=2 -Wno-redundant-decls
|
||||
|
||||
wflags := $(com_wflags) -Wno-strict-prototypes -Wnested-externs \
|
||||
-Wno-discarded-qualifiers
|
||||
wxxflags := $(com_wflags) -Wno-old-style-cast
|
||||
|
||||
cflags := -O3 -pipe -ffunction-sections -fdata-sections \
|
||||
-std=gnu11 $(wflags)
|
||||
cxxflags := -O3 -pipe -ffunction-sections -fdata-sections \
|
||||
-std=c++11 $(wxxflags)
|
||||
|
||||
ldflags := -Wl,--gc-sections -static -static-libgcc -lstdc++ \
|
||||
-fdiagnostics-color -Werror \
|
||||
-Wl,--gc-keep-exported \
|
||||
-Wl,--enable-auto-image-base \
|
||||
-Wl,--exclude-all-symbols \
|
||||
-Wl,--dynamicbase \
|
||||
-Wl,--nxcompat \
|
||||
-Wl,-s
|
||||
|
||||
#
|
||||
# The first target that GNU Make encounters becomes the default target.
|
||||
# Define our ultimate target (`all') here, and also some helpers
|
||||
#
|
||||
|
||||
all:
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)
|
||||
|
||||
#
|
||||
# Pull in module definitions
|
||||
#
|
||||
|
||||
deps :=
|
||||
|
||||
dlls :=
|
||||
exes :=
|
||||
imps :=
|
||||
libs :=
|
||||
|
||||
avsdlls :=
|
||||
avsexes :=
|
||||
|
||||
include Module.mk
|
||||
|
||||
modules := $(dlls) $(exes) $(libs) $(avsdlls) $(avsexes)
|
||||
|
||||
#
|
||||
# $1: Bitness
|
||||
# $2: AVS2 minor version
|
||||
# $3: Module
|
||||
#
|
||||
|
||||
optflags_64 += -mfpmath=sse -march=x86-64 \
|
||||
-mtune=generic -mabi=ms -malign-data=cacheline \
|
||||
-minline-stringops-dynamically -funswitch-loops \
|
||||
-funroll-loops -fschedule-insns2 -fsched-pressure \
|
||||
-fprefetch-loop-arrays --param prefetch-latency=300 \
|
||||
-fsel-sched-pipelining -fselective-scheduling \
|
||||
-ftree-vectorize -fbranch-target-load-optimize \
|
||||
-flive-range-shrinkage -falign-functions=16 \
|
||||
-flto -fno-use-linker-plugin -masm=intel
|
||||
|
||||
optflags_32 += -mfpmath=sse -march=pentium-m -mtune=generic \
|
||||
-mabi=ms -malign-data=cacheline \
|
||||
-minline-stringops-dynamically -funswitch-loops \
|
||||
-funroll-loops -fschedule-insns2 -fsched-pressure \
|
||||
-fprefetch-loop-arrays --param prefetch-latency=300 \
|
||||
-fsel-sched-pipelining -fselective-scheduling \
|
||||
-ftree-vectorize -fbranch-target-load-optimize \
|
||||
-flive-range-shrinkage -falign-functions=16 \
|
||||
-flto -fno-use-linker-plugin -masm=intel
|
||||
|
||||
cflags_32 := $(optflags_32)
|
||||
cxxflags_32 := $(optflags_32)
|
||||
cflags_64 := $(optflags_64)
|
||||
cxxflags_64 := $(optflags_64)
|
||||
|
||||
define t_moddefs
|
||||
|
||||
cppflags_$3 += $(cppflags) -DBUILD_MODULE=$3
|
||||
cflags_$3 += $(cflags)
|
||||
cxxflags_$3 += $(cxxflags)
|
||||
ldflags_$3 += $(ldflags)
|
||||
srcdir_$3 := $3
|
||||
|
||||
endef
|
||||
|
||||
$(eval $(foreach module,$(modules),$(call t_moddefs,_,_,$(module))))
|
||||
|
||||
##############################################################################
|
||||
|
||||
define t_bitness
|
||||
|
||||
subdir_$1_indep := indep-$1
|
||||
bindir_$1_indep := $(bindir)/$$(subdir_$1_indep)
|
||||
|
||||
$$(bindir_$1_indep):
|
||||
mkdir -p $$@
|
||||
|
||||
$$(eval $$(foreach imp,$(imps),$$(call t_import,$1,indep,$$(imp))))
|
||||
$$(eval $$(foreach dll,$(dlls),$$(call t_linkdll,$1,indep,$$(dll))))
|
||||
$$(eval $$(foreach exe,$(exes),$$(call t_linkexe,$1,indep,$$(exe))))
|
||||
$$(eval $$(foreach lib,$(libs),$$(call t_archive,$1,indep,$$(lib))))
|
||||
|
||||
$$(eval $$(foreach avsver,$$(avsvers_$1),$$(call t_avsver,$1,$$(avsver))))
|
||||
|
||||
endef
|
||||
|
||||
##############################################################################
|
||||
|
||||
define t_avsver
|
||||
|
||||
subdir_$1_$2 := avs2_$2-$1
|
||||
bindir_$1_$2 := $(bindir)/$$(subdir_$1_$2)
|
||||
|
||||
$$(bindir_$1_$2):
|
||||
mkdir -p $$@
|
||||
|
||||
$$(eval $$(foreach imp,$(imps),$$(call t_import,$1,$2,$$(imp))))
|
||||
$$(eval $$(foreach dll,$(avsdlls),$$(call t_linkdll,$1,$2,$$(dll))))
|
||||
$$(eval $$(foreach exe,$(avsexes),$$(call t_linkexe,$1,$2,$$(exe))))
|
||||
|
||||
endef
|
||||
|
||||
##############################################################################
|
||||
|
||||
define t_compile
|
||||
|
||||
depdir_$1_$2_$3 := $(depdir)/$$(subdir_$1_$2)/$3
|
||||
abslib_$1_$2_$3 := $$(libs_$3:%=$$(bindir_$1_indep)/lib%.a)
|
||||
absdpl_$1_$2_$3 := $$(deplibs_$3:%=$$(bindir_$1_$2)/lib%.a)
|
||||
objdir_$1_$2_$3 := $(objdir)/$$(subdir_$1_$2)/$3
|
||||
obj_$1_$2_$3 := $$(src_$3:%.c=$$(objdir_$1_$2_$3)/%.o) \
|
||||
$$(rc_$3:%.rc=$$(objdir_$1_$2_$3)/%_rc.o) \
|
||||
$$(srcpp_$3:%.cc=$$(objdir_$1_$2_$3)/%.o)
|
||||
|
||||
deps += $$(src_$3:%.c=$$(depdir_$1_$2_$3)/%.d) \
|
||||
$$(srcpp_$3:%.cc=$$(depdir_$1_$2_$3)/%.d)
|
||||
|
||||
$$(depdir_$1_$2_$3):
|
||||
mkdir -p $$@
|
||||
|
||||
$$(objdir_$1_$2_$3):
|
||||
mkdir -p $$@
|
||||
|
||||
$$(objdir_$1_$2_$3)/%.o: $$(srcdir_$3)/%.c \
|
||||
| $$(depdir_$1_$2_$3) $$(objdir_$1_$2_$3)
|
||||
$(ccache) $$(toolchain_$1)gcc $$(cflags_$3) $$(cflags_$1) $$(cppflags_$3) \
|
||||
-MMD -MF $$(depdir_$1_$2_$3)/$$*.d -MT $$@ -MP \
|
||||
-DAVS_VERSION=$2 -c -o $$@ $$<
|
||||
|
||||
$$(objdir_$1_$2_$3)/%.o: $$(srcdir_$3)/%.cc \
|
||||
| $$(depdir_$1_$2_$3) $$(objdir_$1_$2_$3)
|
||||
$(ccache) $$(toolchain_$1)g++ $$(cxxflags_$3) $$(cxxflags_$1) $$(cppflags_$3) \
|
||||
-MMD -MF $$(depdir_$1_$2_$3)/$$*.d -MT $$@ -MP \
|
||||
-DAVS_VERSION=$2 -c -o $$@ $$<
|
||||
|
||||
$$(objdir_$1_$2_$3)/%_rc.o: $$(srcdir_$3)/%.rc \
|
||||
| $$(depdir_$1_$2_$3) $$(objdir_$1_$2_$3)
|
||||
$$(toolchain_$1)windres $$(cppflags_$3) $$< $$@
|
||||
|
||||
endef
|
||||
|
||||
##############################################################################
|
||||
|
||||
define t_archive
|
||||
|
||||
$(t_compile)
|
||||
|
||||
$$(bindir_$1_$2)/lib$3.a: $$(obj_$1_$2_$3) | $$(bindir_$1_$2)
|
||||
$$(toolchain_$1)gcc-ar r $$@ $$^ 2> /dev/null
|
||||
$$(toolchain_$1)gcc-ranlib $$@
|
||||
|
||||
endef
|
||||
|
||||
##############################################################################
|
||||
|
||||
define t_linkdll
|
||||
|
||||
$(t_compile)
|
||||
|
||||
dll_$1_$2_$3 := $$(bindir_$1_$2)/$3.dll
|
||||
implib_$1_$2_$3 := $$(bindir_$1_$2)/lib$3.a
|
||||
|
||||
$$(dll_$1_$2_$3) $$(implib_$1_$2_$3): $$(obj_$1_$2_$3) $$(abslib_$1_$2_$3) \
|
||||
$$(absdpl_$1_$2_$3) \
|
||||
$$(srcdir_$3)/$3.def | $$(bindir_$1_$2)
|
||||
$(ccache) $$(toolchain_$1)gcc -shared $$(srcdir_$3)/$3.def \
|
||||
-o $$(dll_$1_$2_$3) -Wl,--out-implib,$$(implib_$1_$2_$3) \
|
||||
$$^ $$(ldflags_$3) $(optflags_$1)
|
||||
$$(toolchain_$1)strip -s $$(dll_$1_$2_$3)
|
||||
$$(toolchain_$1)ranlib $$(implib_$1_$2_$3)
|
||||
|
||||
endef
|
||||
|
||||
##############################################################################
|
||||
|
||||
define t_linkexe
|
||||
|
||||
$(t_compile)
|
||||
|
||||
exe_$1_$2_$3 := $$(bindir_$1_$2)/$3.exe
|
||||
|
||||
$$(exe_$1_$2_$3): $$(obj_$1_$2_$3) $$(abslib_$1_$2_$3) $$(absdpl_$1_$2_$3) \
|
||||
| $$(bindir_$1_$2)
|
||||
$(ccache) $$(toolchain_$1)gcc -o $$@ $$^ $$(ldflags_$3) $(optflags_$1)
|
||||
$$(toolchain_$1)strip -s $$@
|
||||
|
||||
endef
|
||||
|
||||
##############################################################################
|
||||
|
||||
define t_import
|
||||
|
||||
impdef_$1_$2_$3 ?= imports/import_$1_$2_$3.def
|
||||
|
||||
$$(bindir_$1_$2)/lib$3.a: $$(impdef_$1_$2_$3) | $$(bindir_$1_$2)
|
||||
$$(toolchain_$1)dlltool -l $$@ -d $$<
|
||||
|
||||
endef
|
||||
|
||||
##############################################################################
|
||||
|
||||
$(eval $(foreach bitness,32 64,$(call t_bitness,$(bitness))))
|
||||
|
||||
#
|
||||
# Pull in GCC-generated dependency files
|
||||
#
|
||||
|
||||
-include $(deps)
|
||||
|
34
Module.mk
Normal file
34
Module.mk
Normal file
@ -0,0 +1,34 @@
|
||||
cflags += -DWIN32_LEAN_AND_MEAN -DCOBJMACROS -Ipkcs11 -Wno-attributes
|
||||
|
||||
avsvers_32 := 1700 1508
|
||||
avsvers_64 := 1700 1509
|
||||
|
||||
imps += avs avs-ea3
|
||||
|
||||
include util/Module.mk
|
||||
include minhook/Module.mk
|
||||
include popnhax/Module.mk
|
||||
|
||||
#
|
||||
# Distribution build rules
|
||||
#
|
||||
|
||||
zipdir := $(BUILDDIR)/zip
|
||||
|
||||
$(zipdir)/:
|
||||
mkdir -p $@
|
||||
|
||||
$(BUILDDIR)/popnhax.zip: \
|
||||
build/bin/avs2_1508-32/popnhax.dll \
|
||||
dist/popnhax/popnhax.xml \
|
||||
| $(zipdir)/
|
||||
echo ... $@
|
||||
zip -j $@ $^
|
||||
|
||||
$(BUILDDIR)/bemanihax.zip: \
|
||||
$(BUILDDIR)/popnhax.zip \
|
||||
| $(zipdir)/
|
||||
echo ... $@
|
||||
zip -9 -q -j $@ $^
|
||||
|
||||
all: $(BUILDDIR)/bemanihax.zip
|
11
README.md
11
README.md
@ -1,2 +1,11 @@
|
||||
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/donate?hosted_button_id=WT735CX4UMZ9U)
|
||||
|
||||
# popnhax
|
||||
popnhax
|
||||
|
||||
Arcade game patcher.
|
||||
|
||||
Based on [bemanihax](https://github.com/windyfairy/bemanihax) whose an updated version was included with omnimix v1
|
||||
|
||||
### Build Instructions
|
||||
|
||||
Should be working out of the box with MSYS2/MinGW32. Just run `make`.
|
||||
|
30
clang-format.py
Normal file
30
clang-format.py
Normal file
@ -0,0 +1,30 @@
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
ignore_folders = [".git", "build", "dist", "minhook"]
|
||||
cpp_extensions = (".cpp", ".cxx", ".c++", ".h++", ".hpp", ".hxx")
|
||||
|
||||
for root, dirs, files in os.walk(".", topdown=True):
|
||||
dirs[:] = [d for d in dirs if d not in ignore_folders]
|
||||
|
||||
for filename in files:
|
||||
if filename.endswith(cpp_extensions):
|
||||
print(filename)
|
||||
subprocess.check_call(["clang-format", "-i", "-style=file", root + "/" + filename])
|
||||
# print(" ".join(["clang-tidy", root + "/" + filename, "--", "-I."]))
|
||||
subprocess.check_call(["./clang-tidy.sh", root + "/" + filename, "c++11"])
|
||||
print()
|
||||
|
||||
|
||||
cpp_extensions = (".cc", ".cp", ".c", ".i", ".ii", ".h")
|
||||
|
||||
for root, dirs, files in os.walk(".", topdown=True):
|
||||
dirs[:] = [d for d in dirs if d not in ignore_folders]
|
||||
|
||||
for filename in files:
|
||||
if filename.endswith(cpp_extensions):
|
||||
print(filename)
|
||||
subprocess.check_call(["clang-format", "-i", "-style=file", root + "/" + filename])
|
||||
# print(" ".join(["clang-tidy", root + "/" + filename, "--", "-I."]))
|
||||
subprocess.check_call(["./clang-tidy.sh", root + "/" + filename, "c11"])
|
||||
print()
|
36
clang-tidy.sh
Normal file
36
clang-tidy.sh
Normal file
@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
# Run clang-tidy on a source file
|
||||
TOOLCHAIN_PREFIX=i686-w64-mingw32
|
||||
|
||||
CLANG_TIDY=clang-tidy
|
||||
SYSROOT=$($TOOLCHAIN_PREFIX-gcc -print-sysroot)/mingw
|
||||
|
||||
if [ ! -f $SYSROOT/include/windows.h ]; then
|
||||
SYSROOT=/usr/i686-w64-mingw32
|
||||
if [ ! -f $SYSROOT/include/windows.h ]; then
|
||||
SYSROOT=/usr/local/i686-w64-mingw32
|
||||
fi
|
||||
fi
|
||||
|
||||
CPP_HEADERS="/usr/share/mingw-w64/include/"
|
||||
|
||||
# echo "System root: $SYSROOT"
|
||||
# echo "C++ headers: $CPP_HEADERS"
|
||||
|
||||
$CLANG_TIDY $1 \
|
||||
-- \
|
||||
-target i686-w64-mingw32 \
|
||||
-std=$2 \
|
||||
--sysroot $SYSROOT \
|
||||
-isysroot $SYSROOT \
|
||||
-I $CPP_HEADERS \
|
||||
-I. \
|
||||
-Iinclude \
|
||||
-Dssize_t=int \
|
||||
-DAVS_VERSION=1700 \
|
||||
-D_CRT_SECURE_NO_WARNINGS=1 \
|
||||
-Di386=1 \
|
||||
-D__i386=1 \
|
||||
-D__i386__=1 \
|
||||
-D_WIN32=1 \
|
||||
-DCOBJMACROS
|
26
dist/popnhax/popnhax.xml
vendored
Normal file
26
dist/popnhax/popnhax.xml
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version='1.0' encoding='shift-jis'?>
|
||||
<popnhax>
|
||||
<!-- Force unlock music, charts, characters, and deco parts -->
|
||||
<force_unlocks __type="bool">1</force_unlocks>
|
||||
<!-- Prevent Windows volume from being reset on boot -->
|
||||
<unset_volume __type="bool">0</unset_volume>
|
||||
<!-- Force booting directly into event mode -->
|
||||
<event_mode __type="bool">1</event_mode>
|
||||
<!-- Remove the timer completely without event mode -->
|
||||
<remove_timer __type="bool">0</remove_timer>
|
||||
<!-- or Freeze the timer at 10 seconds after counting down -->
|
||||
<freeze_timer __type="bool">0</freeze_timer>
|
||||
<!-- Force skip menu and long note tutorials without a card -->
|
||||
<skip_tutorials __type="bool">1</skip_tutorials>
|
||||
<!-- Settings for database hooking patches follow: -->
|
||||
<!-- Enable database modifications -->
|
||||
<patch_db __type="bool">1</patch_db>
|
||||
<!-- Force the newly created buffers to be the same size as the original buffers -->
|
||||
<disable_expansions __type="bool">0</disable_expansions>
|
||||
<!-- Copy the new table information over top the old tables (automatically enables disable_expansions) -->
|
||||
<disable_redirection __type="bool">0</disable_redirection>
|
||||
<!-- Autoload latest patch file (highest datecode) from data_mods folder -->
|
||||
<patch_xml_auto __type="bool">1</patch_xml_auto>
|
||||
<!-- Manually set XML file containing patches (requires patch_xml_auto to be disabled) -->
|
||||
<patch_xml_filename __type="str"></patch_xml_filename>
|
||||
</popnhax>
|
92
imports/avs-ea3.h
Normal file
92
imports/avs-ea3.h
Normal file
@ -0,0 +1,92 @@
|
||||
#ifndef IMPORTS_AVS_EA3_H
|
||||
#define IMPORTS_AVS_EA3_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined(AVS_VERSION)
|
||||
|
||||
#error "Can't build AVS-dependent project using AVS-independent make rules"
|
||||
|
||||
#elif AVS_VERSION == 1509
|
||||
|
||||
#define ea3_xrpc_apply XE592acd000057
|
||||
#define ea3_xrpc_module_register XE592acd000060
|
||||
#define ea3_xrpc_new XE592acd000052
|
||||
#define ea3_xrpc_destroy XE592acd000007
|
||||
#define ea3_boot XE592acd00008c
|
||||
#define ea3_shutdown XE592acd00005a
|
||||
|
||||
#else
|
||||
|
||||
#error AVS obfuscated import macros have not been declared for this version
|
||||
|
||||
#endif
|
||||
|
||||
#define XRPC_STATUS_SERVER_FAULT_ERROR (-17)
|
||||
#define XRPC_STATUS_SERVER_RESPONSE_ERROR (-18)
|
||||
|
||||
void ea3_boot(struct property_node *conf);
|
||||
void ea3_shutdown(void);
|
||||
|
||||
struct xrpc_handle;
|
||||
struct xrpc_server_handle;
|
||||
|
||||
struct xrpc_status {
|
||||
int16_t status;
|
||||
int16_t subcode;
|
||||
int16_t status_code;
|
||||
int16_t fault_code;
|
||||
} __attribute__((gcc_struct, packed));
|
||||
|
||||
struct xrpc_arg_list {
|
||||
const char *name;
|
||||
const char *property_path;
|
||||
bool omittable;
|
||||
} __attribute__((gcc_struct, packed));
|
||||
|
||||
/*
|
||||
* The following defines the codes used inside the 'status@' attribute
|
||||
* used in a xrpc response.
|
||||
*/
|
||||
|
||||
enum ea3_general_status_codes {
|
||||
XRPC_OK = 0, /* No error */
|
||||
};
|
||||
|
||||
enum xrpc_method_types {
|
||||
HTTPAC_HTTP10 = 0x1,
|
||||
};
|
||||
|
||||
struct xrpc_method {
|
||||
const char *xrpc_meth_name;
|
||||
bool(__cdecl *xrpc_cb_init)(void *shmem, char *buffer);
|
||||
bool(__cdecl *xrpc_cb_sender)(void *shmem, struct property_node *node);
|
||||
bool(__cdecl *xrpc_cb_receiver)(void *shmem, struct property_node *node);
|
||||
char crypt_level;
|
||||
char padding_00;
|
||||
bool use_xrpc11;
|
||||
bool use_esign;
|
||||
bool use_ssl;
|
||||
char compress_type;
|
||||
char method_type;
|
||||
char padding_01;
|
||||
struct xrpc_arg_list *arg_list;
|
||||
} __attribute__((gcc_struct, packed));
|
||||
|
||||
typedef int (*xrpc_apply_exit_callback_t)(void *buffer, struct xrpc_status status, void *param);
|
||||
|
||||
int ea3_xrpc_apply(struct xrpc_handle *handle, const char *name, void *shmem,
|
||||
xrpc_apply_exit_callback_t cbexit, void *cbexit_data, ...);
|
||||
|
||||
struct xrpc_handle *ea3_xrpc_new(size_t sz_xrpc_buf, const char *xrpc_encoding, uint32_t flags);
|
||||
void ea3_xrpc_destroy(struct xrpc_handle *handle);
|
||||
int ea3_xrpc_module_register(const char *xrpc_endpoint, const char *services_url, uint32_t flags,
|
||||
struct xrpc_method *method_array);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
188
imports/avs.h
Normal file
188
imports/avs.h
Normal file
@ -0,0 +1,188 @@
|
||||
#ifndef IMPORTS_AVS_H
|
||||
#define IMPORTS_AVS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#if !defined(AVS_VERSION)
|
||||
|
||||
#error "Can't build AVS-dependent project using AVS-independent make rules"
|
||||
|
||||
#elif AVS_VERSION == 1508 || AVS_VERSION == 1509
|
||||
|
||||
#define avs_thread_delay XCd229cc00012b
|
||||
#define property_search XCd229cc00012e
|
||||
#define boot XCd229cc0000aa
|
||||
#define shutdown XCd229cc00001d
|
||||
#define property_desc_to_buffer XCd229cc0000fd
|
||||
#define property_destroy XCd229cc00013c
|
||||
#define property_read_query_memsize XCd229cc0000ff
|
||||
#define property_create XCd229cc000126
|
||||
#define property_insert_read XCd229cc00009a
|
||||
#define property_node_create XCd229cc00002c
|
||||
#define property_node_remove XCd229cc000028
|
||||
#define property_node_refer XCd229cc000009
|
||||
#define std_setenv XCd229cc000094
|
||||
#define avs_fs_open XCd229cc000090
|
||||
#define avs_fs_copy XCd229cc0000eb
|
||||
#define avs_fs_close XCd229cc00011f
|
||||
#define avs_fs_dump_mountpoint XCd229cc0000e9
|
||||
#define avs_fs_mount XCd229cc0000ce
|
||||
#define avs_fs_fstat XCd229cc0000c3
|
||||
#define avs_fs_lstat XCd229cc0000c0
|
||||
#define avs_fs_lseek XCd229cc00004d
|
||||
#define avs_fs_read XCd229cc00010d
|
||||
#define avs_fs_opendir XCd229cc0000f0
|
||||
#define avs_fs_readdir XCd229cc0000bb
|
||||
#define avs_fs_closedir XCd229cc0000b8
|
||||
#define cstream_create XCd229cc000141
|
||||
#define cstream_operate XCd229cc00008c
|
||||
#define cstream_finish XCd229cc000025
|
||||
#define cstream_destroy XCd229cc0000e3
|
||||
#define property_node_read XCd229cc0000f3
|
||||
#define property_node_write XCd229cc00002d
|
||||
#define property_file_write XCd229cc000052
|
||||
#define property_node_traversal XCd229cc000046
|
||||
#define property_psmap_export XCd229cc000006
|
||||
#define property_psmap_import XCd229cc000005
|
||||
#define property_node_name XCd229cc000049
|
||||
#define property_node_get_desc XCd229cc000165
|
||||
#define property_get_error XCd229cc0000b5
|
||||
#define property_node_clone XCd229cc00010a
|
||||
#define property_query_size XCd229cc000032
|
||||
#define property_node_query_stat XCd229cc0000b1
|
||||
#define property_node_datasize XCd229cc000083
|
||||
#define property_mem_write XCd229cc000033
|
||||
#define property_part_write XCd229cc000024
|
||||
#define property_node_absolute_path XCd229cc00007c
|
||||
#define property_node_has XCd229cc00008a
|
||||
#define property_node_is_array XCd229cc000142
|
||||
#define property_node_type XCd229cc000071
|
||||
#define property_get_attribute_bool XCd229cc000043
|
||||
#define property_node_get_attribute_bool XCd229cc000110
|
||||
#define property_node_get_attribute_u32 XCd229cc0000db
|
||||
#define property_node_get_attribute_s32 XCd229cc00011a
|
||||
#define property_node_rename XCd229cc0000af
|
||||
#define property_query_freesize XCd229cc000144
|
||||
#define property_clear_error XCd229cc00014b
|
||||
#define property_lookup_encode XCd229cc0000fc
|
||||
#define property_unlock_flag XCd229cc000145
|
||||
#define property_lock_flag XCd229cc000121
|
||||
#define property_set_flag XCd229cc000035
|
||||
#define property_part_write_meta XCd229cc00004f
|
||||
#define property_part_write_meta2 XCd229cc000107
|
||||
#define property_read_data XCd229cc0000de
|
||||
#define property_read_meta XCd229cc00010e
|
||||
#define property_get_attribute_u32 XCd229cc000148
|
||||
#define property_get_attribute_s32 XCd229cc00005f
|
||||
#define property_get_fingerprint XCd229cc000057
|
||||
#define property_node_refdata XCd229cc00009f
|
||||
#define property_insert_read_with_filename XCd229cc0000cd
|
||||
#define property_mem_read XCd229cc000039
|
||||
#define property_read_query_memsize_long XCd229cc00002b
|
||||
#define property_clear XCd229cc0000c2
|
||||
#define avs_net_add_protocol XCd229cc000156
|
||||
#define avs_net_del_protocol XCd229cc00000f
|
||||
#define avs_net_addrinfobyaddr XCd229cc000040
|
||||
#define avs_net_socket XCd229cc000026
|
||||
#define avs_net_setsockopt XCd229cc000092
|
||||
#define avs_net_getsockopt XCd229cc000084
|
||||
#define avs_net_connect XCd229cc000038
|
||||
#define avs_net_send XCd229cc00011d
|
||||
#define avs_net_recv XCd229cc000131
|
||||
#define avs_net_pollfds_add XCd229cc00004b
|
||||
#define avs_net_pollfds_get XCd229cc000105
|
||||
#define avs_net_bind XCd229cc00007e
|
||||
#define avs_net_close XCd229cc00009c
|
||||
#define avs_net_shutdown XCd229cc0000ac
|
||||
#define avs_net_get_peername XCd229cc000085
|
||||
#define avs_net_get_sockname XCd229cc0000b0
|
||||
|
||||
#elif AVS_VERSION == 1700
|
||||
|
||||
#define property_create XCgsqzn0000090
|
||||
#define property_insert_read XCgsqzn0000094
|
||||
#define property_read_query_memsize XCgsqzn00000b0
|
||||
#define property_psmap_import XCgsqzn00000b2
|
||||
|
||||
#else
|
||||
|
||||
#error AVS obfuscated import macros have not been declared for this version
|
||||
|
||||
#endif
|
||||
|
||||
enum property_type {
|
||||
PROPERTY_TYPE_VOID = 1,
|
||||
PROPERTY_TYPE_S8 = 2,
|
||||
PROPERTY_TYPE_U8 = 3,
|
||||
PROPERTY_TYPE_S16 = 4,
|
||||
PROPERTY_TYPE_U16 = 5,
|
||||
PROPERTY_TYPE_S32 = 6,
|
||||
PROPERTY_TYPE_U32 = 7,
|
||||
PROPERTY_TYPE_S64 = 8,
|
||||
PROPERTY_TYPE_U64 = 9,
|
||||
PROPERTY_TYPE_BIN = 10,
|
||||
PROPERTY_TYPE_STR = 11,
|
||||
PROPERTY_TYPE_FLOAT = 14,
|
||||
PROPERTY_TYPE_ATTR = 46,
|
||||
PROPERTY_TYPE_BOOL = 52,
|
||||
};
|
||||
|
||||
enum property_node_traversal {
|
||||
TRAVERSE_PARENT = 0,
|
||||
TRAVERSE_FIRST_CHILD = 1,
|
||||
TRAVERSE_FIRST_ATTR = 2,
|
||||
TRAVERSE_FIRST_SIBLING = 3,
|
||||
TRAVERSE_NEXT_SIBLING = 4,
|
||||
TRAVERSE_PREVIOUS_SIBLING = 5,
|
||||
TRAVERSE_LAST_SIBLING = 6,
|
||||
TRAVERSE_NEXT_SEARCH_RESULT = 7,
|
||||
TRAVERSE_PREV_SEARCH_RESULT = 8,
|
||||
};
|
||||
|
||||
struct property;
|
||||
struct property_node;
|
||||
struct property_psmap;
|
||||
|
||||
typedef int (*avs_reader_t)(uint32_t context, void *bytes, size_t nbytes);
|
||||
|
||||
uint32_t property_read_query_memsize(avs_reader_t reader, uint32_t context, int *nodes, int *total);
|
||||
struct property *property_create(int flags, void *buffer, uint32_t buffer_size);
|
||||
int property_insert_read(struct property *prop, struct property_node *node, avs_reader_t reader,
|
||||
uint32_t context);
|
||||
int property_psmap_import(struct property *prop, struct property_node *root, void *dest,
|
||||
const struct property_psmap *psmap);
|
||||
struct property_node *property_node_create(struct property *prop, struct property_node *parent,
|
||||
int type, const char *key, ...);
|
||||
struct property_node *property_search(
|
||||
struct property *prop, struct property_node *root, const char *path);
|
||||
|
||||
int property_mem_write(struct property *prop, void *bytes, int nbytes);
|
||||
void *property_desc_to_buffer(struct property *prop);
|
||||
void property_file_write(struct property *prop, const char *path);
|
||||
int property_set_flag(struct property *prop, int flags, int mask);
|
||||
void property_destroy(struct property *prop);
|
||||
|
||||
int property_node_refer(
|
||||
struct property *prop,
|
||||
struct property_node *node,
|
||||
const char *name,
|
||||
enum property_type type,
|
||||
void *bytes,
|
||||
uint32_t nbytes);
|
||||
struct property_node *property_node_traversal(
|
||||
struct property_node *node, enum property_node_traversal direction);
|
||||
void avs_thread_delay(size_t ms, int zero);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
36
imports/import_32_0_avs.def
Normal file
36
imports/import_32_0_avs.def
Normal file
@ -0,0 +1,36 @@
|
||||
LIBRARY libavs-win32
|
||||
|
||||
EXPORTS
|
||||
avs_boot
|
||||
avs_net_ctrl
|
||||
avs_shutdown
|
||||
avs_thread_create
|
||||
avs_thread_destroy
|
||||
avs_thread_exit
|
||||
avs_thread_join
|
||||
log_body_fatal
|
||||
log_body_info
|
||||
log_body_misc
|
||||
log_body_warning
|
||||
log_boot
|
||||
log_change_level
|
||||
property_create
|
||||
property_desc_to_buffer
|
||||
property_destroy
|
||||
property_file_write
|
||||
property_insert_read
|
||||
property_mem_write
|
||||
property_read_query_memsize
|
||||
property_search
|
||||
property_set_flag
|
||||
property_node_clone
|
||||
property_node_create
|
||||
property_node_name
|
||||
property_node_refer
|
||||
property_node_remove
|
||||
property_node_type
|
||||
property_node_traversal
|
||||
property_node_refdata
|
||||
std_getenv
|
||||
std_setenv
|
||||
|
28
imports/import_32_1101_avs.def
Normal file
28
imports/import_32_1101_avs.def
Normal file
@ -0,0 +1,28 @@
|
||||
LIBRARY libavs-win32
|
||||
|
||||
EXPORTS
|
||||
avs_boot @22 NONAME
|
||||
avs_net_ctrl @107 NONAME
|
||||
avs_shutdown @140 NONAME
|
||||
avs_thread_create @156 NONAME
|
||||
avs_thread_destroy @158 NONAME
|
||||
avs_thread_exit @159 NONAME
|
||||
avs_thread_join @161 NONAME
|
||||
log_assert_body @196 NONAME
|
||||
log_body_misc @199 NONAME
|
||||
log_body_info @198 NONAME
|
||||
log_body_warning @200 NONAME
|
||||
log_body_fatal @197 NONAME
|
||||
property_create @245 NONAME
|
||||
property_desc_to_buffer @246 NONAME
|
||||
property_destroy @247 NONAME
|
||||
property_insert_read @255 NONAME
|
||||
property_node_create @266 NONAME
|
||||
property_node_refer @278 NONAME
|
||||
property_node_remove @279 NONAME
|
||||
property_psmap_import @288 NONAME
|
||||
property_psmap_export @287 NONAME
|
||||
property_read_query_memsize @291 NONAME
|
||||
property_search @294 NONAME
|
||||
std_getenv @308 NONAME
|
||||
std_setenv @322 NONAME
|
27
imports/import_32_1304_avs.def
Normal file
27
imports/import_32_1304_avs.def
Normal file
@ -0,0 +1,27 @@
|
||||
LIBRARY libavs-win32
|
||||
|
||||
EXPORTS
|
||||
avs_boot @237 NONAME
|
||||
avs_net_ctrl @15 NONAME
|
||||
avs_shutdown @333 NONAME
|
||||
avs_thread_create @183 NONAME
|
||||
avs_thread_destroy @76 NONAME
|
||||
avs_thread_exit @147 NONAME
|
||||
avs_thread_join @92 NONAME
|
||||
log_body_misc @44 NONAME
|
||||
log_body_info @339 NONAME
|
||||
log_body_warning @219 NONAME
|
||||
log_body_fatal @128 NONAME
|
||||
property_create @256 NONAME
|
||||
property_desc_to_buffer @201 NONAME
|
||||
property_destroy @264 NONAME
|
||||
property_insert_read @23 NONAME
|
||||
property_node_create @316 NONAME
|
||||
property_node_refer @268 NONAME
|
||||
property_node_remove @129 NONAME
|
||||
property_psmap_import @102 NONAME
|
||||
property_psmap_export @110 NONAME
|
||||
property_read_query_memsize @100 NONAME
|
||||
property_search @244 NONAME
|
||||
std_getenv @226 NONAME
|
||||
std_setenv @114 NONAME
|
24
imports/import_32_1403_avs.def
Normal file
24
imports/import_32_1403_avs.def
Normal file
@ -0,0 +1,24 @@
|
||||
LIBRARY libavs-win32
|
||||
|
||||
EXPORTS
|
||||
avs_boot @298 NONAME
|
||||
avs_net_ctrl @100 NONAME
|
||||
avs_shutdown @299 NONAME
|
||||
avs_thread_create @6 NONAME
|
||||
avs_thread_destroy @8 NONAME
|
||||
avs_thread_join @13 NONAME
|
||||
log_body_info @363 NONAME
|
||||
log_body_misc @364 NONAME
|
||||
log_body_warning @362 NONAME
|
||||
log_body_fatal @365 NONAME
|
||||
property_create @129 NONAME
|
||||
property_desc_to_buffer @131 NONAME
|
||||
property_destroy @130 NONAME
|
||||
property_insert_read @133 NONAME
|
||||
property_node_remove @148 NONAME
|
||||
property_psmap_import @163 NONAME
|
||||
property_psmap_export @164 NONAME
|
||||
property_read_query_memsize @161 NONAME
|
||||
property_search @146 NONAME
|
||||
std_getenv @208 NONAME
|
||||
std_setenv @209 NONAME
|
91
imports/import_32_1508_avs.def
Normal file
91
imports/import_32_1508_avs.def
Normal file
@ -0,0 +1,91 @@
|
||||
LIBRARY libavs-win32
|
||||
|
||||
EXPORTS
|
||||
XCd229cc00012e
|
||||
XCd229cc0000aa
|
||||
XCd229cc00001d
|
||||
XCd229cc0000fd
|
||||
XCd229cc00013c
|
||||
XCd229cc0000ff
|
||||
XCd229cc000126
|
||||
XCd229cc00009a
|
||||
XCd229cc00002c
|
||||
XCd229cc000028
|
||||
XCd229cc000009
|
||||
XCd229cc000094
|
||||
XCd229cc000090
|
||||
XCd229cc0000eb
|
||||
XCd229cc00011f
|
||||
XCd229cc0000e9
|
||||
XCd229cc0000ce
|
||||
XCd229cc0000c3
|
||||
XCd229cc0000c0
|
||||
XCd229cc00004d
|
||||
XCd229cc00010d
|
||||
XCd229cc0000f0
|
||||
XCd229cc0000bb
|
||||
XCd229cc0000b8
|
||||
XCd229cc000141
|
||||
XCd229cc00008c
|
||||
XCd229cc000025
|
||||
XCd229cc0000e3
|
||||
XCd229cc0000f3
|
||||
XCd229cc00002d
|
||||
XCd229cc000052
|
||||
XCd229cc000046
|
||||
XCd229cc000006
|
||||
XCd229cc000005
|
||||
XCd229cc000049
|
||||
XCd229cc000165
|
||||
XCd229cc0000b5
|
||||
XCd229cc00010a
|
||||
XCd229cc000032
|
||||
XCd229cc0000b1
|
||||
XCd229cc000083
|
||||
XCd229cc000033
|
||||
XCd229cc000024
|
||||
XCd229cc00007c
|
||||
XCd229cc00008a
|
||||
XCd229cc000142
|
||||
XCd229cc000071
|
||||
XCd229cc000043
|
||||
XCd229cc000110
|
||||
XCd229cc0000db
|
||||
XCd229cc00011a
|
||||
XCd229cc0000af
|
||||
XCd229cc000144
|
||||
XCd229cc00014b
|
||||
XCd229cc0000fc
|
||||
XCd229cc000145
|
||||
XCd229cc000121
|
||||
XCd229cc000035
|
||||
XCd229cc00004f
|
||||
XCd229cc000107
|
||||
XCd229cc0000de
|
||||
XCd229cc00010e
|
||||
XCd229cc000148
|
||||
XCd229cc00005f
|
||||
XCd229cc000057
|
||||
XCd229cc00009f
|
||||
XCd229cc0000cd
|
||||
XCd229cc000039
|
||||
XCd229cc00002b
|
||||
XCd229cc0000c2
|
||||
XCd229cc000156
|
||||
XCd229cc00000f
|
||||
XCd229cc000040
|
||||
XCd229cc000026
|
||||
XCd229cc000092
|
||||
XCd229cc000084
|
||||
XCd229cc000038
|
||||
XCd229cc00011d
|
||||
XCd229cc000131
|
||||
XCd229cc00004b
|
||||
XCd229cc000105
|
||||
XCd229cc00007e
|
||||
XCd229cc00009c
|
||||
XCd229cc0000ac
|
||||
XCd229cc000085
|
||||
XCd229cc0000b0
|
||||
|
||||
|
28
imports/import_32_1601_avs.def
Normal file
28
imports/import_32_1601_avs.def
Normal file
@ -0,0 +1,28 @@
|
||||
LIBRARY libavs-win32
|
||||
|
||||
EXPORTS
|
||||
avs_thread_create @5 NONAME
|
||||
avs_thread_destroy @7 NONAME
|
||||
avs_thread_exit @11 NONAME
|
||||
avs_thread_join @12 NONAME
|
||||
avs_net_ctrl @98 NONAME
|
||||
property_create @124 NONAME
|
||||
property_destroy @125 NONAME
|
||||
property_desc_to_buffer @126 NONAME
|
||||
property_insert_read @128 NONAME
|
||||
property_search @141 NONAME
|
||||
property_node_create @142 NONAME
|
||||
property_node_remove @143 NONAME
|
||||
property_node_refer @155 NONAME
|
||||
property_read_query_memsize @156 NONAME
|
||||
property_psmap_export @159 NONAME
|
||||
property_psmap_import @158 NONAME
|
||||
std_getenv @204 NONAME
|
||||
std_setenv @205 NONAME
|
||||
avs_boot @283 NONAME
|
||||
avs_shutdown @284 NONAME
|
||||
log_body_fatal @361 NONAME
|
||||
log_body_warning @362 NONAME
|
||||
log_body_info @363 NONAME
|
||||
log_body_misc @364 NONAME
|
||||
|
27
imports/import_32_1603_avs.def
Normal file
27
imports/import_32_1603_avs.def
Normal file
@ -0,0 +1,27 @@
|
||||
LIBRARY libavs-win32
|
||||
|
||||
EXPORTS
|
||||
avs_thread_create @5 NONAME
|
||||
avs_thread_destroy @7 NONAME
|
||||
avs_thread_exit @11 NONAME
|
||||
avs_thread_join @12 NONAME
|
||||
avs_net_ctrl @119 NONAME
|
||||
property_create @145 NONAME
|
||||
property_destroy @146 NONAME
|
||||
property_desc_to_buffer @147 NONAME
|
||||
property_insert_read @149 NONAME
|
||||
property_search @162 NONAME
|
||||
property_node_create @163 NONAME
|
||||
property_node_remove @164 NONAME
|
||||
property_node_refer @176 NONAME
|
||||
property_read_query_memsize @177 NONAME
|
||||
property_psmap_import @179 NONAME
|
||||
property_psmap_export @180 NONAME
|
||||
std_getenv @212 NONAME
|
||||
std_setenv @213 NONAME
|
||||
avs_boot @298 NONAME
|
||||
avs_shutdown @299 NONAME
|
||||
log_body_fatal @379 NONAME
|
||||
log_body_warning @380 NONAME
|
||||
log_body_info @381 NONAME
|
||||
log_body_misc @382 NONAME
|
53
imports/import_32_1700_avs.def
Normal file
53
imports/import_32_1700_avs.def
Normal file
@ -0,0 +1,53 @@
|
||||
LIBRARY avs2-core
|
||||
|
||||
EXPORTS
|
||||
XCgsqzn0000007
|
||||
XCgsqzn0000004
|
||||
XCgsqzn0000006
|
||||
XCgsqzn000000a
|
||||
XCgsqzn000000b
|
||||
XCgsqzn0000076
|
||||
XCgsqzn0000090
|
||||
XCgsqzn0000091
|
||||
XCgsqzn0000092
|
||||
XCgsqzn0000094
|
||||
XCgsqzn00000a1
|
||||
XCgsqzn00000a2
|
||||
XCgsqzn00000a3
|
||||
XCgsqzn00000af
|
||||
XCgsqzn00000b0
|
||||
XCgsqzn00000b2
|
||||
XCgsqzn00000b3
|
||||
XCgsqzn00000d3
|
||||
XCgsqzn00000d4
|
||||
XCgsqzn0000129
|
||||
XCgsqzn000012a
|
||||
XCgsqzn000017a
|
||||
XCgsqzn000017b
|
||||
XCgsqzn000017c
|
||||
XCgsqzn000017d
|
||||
XCgsqzn000004e
|
||||
XCgsqzn0000055
|
||||
XCgsqzn0000065
|
||||
XCgsqzn0000068
|
||||
XCgsqzn00000d5
|
||||
XCgsqzn0000051
|
||||
XCgsqzn00000a6
|
||||
XCgsqzn0000144
|
||||
XCgsqzn0000077
|
||||
XCgsqzn0000079
|
||||
XCgsqzn000007a
|
||||
XCgsqzn000007b
|
||||
XCgsqzn000007c
|
||||
XCgsqzn000007d
|
||||
XCgsqzn000007e
|
||||
XCgsqzn000007f
|
||||
XCgsqzn0000080
|
||||
XCgsqzn0000081
|
||||
XCgsqzn0000082
|
||||
XCgsqzn0000086
|
||||
XCgsqzn000008c
|
||||
XCgsqzn000008d
|
||||
XCgsqzn000008e
|
||||
XCgsqzn000008f
|
||||
XCgsqzn0000078
|
37
imports/import_32_803_avs.def
Normal file
37
imports/import_32_803_avs.def
Normal file
@ -0,0 +1,37 @@
|
||||
LIBRARY libavs-win32
|
||||
|
||||
EXPORTS
|
||||
avs_boot
|
||||
avs_net_ctrl
|
||||
avs_shutdown
|
||||
avs_thread_create
|
||||
avs_thread_destroy
|
||||
avs_thread_exit
|
||||
avs_thread_join
|
||||
log_body_fatal
|
||||
log_body_info
|
||||
log_body_misc
|
||||
log_body_warning
|
||||
log_boot
|
||||
log_change_level
|
||||
property_create
|
||||
property_desc_to_buffer
|
||||
property_destroy
|
||||
property_file_write
|
||||
property_insert_read
|
||||
property_mem_write
|
||||
property_read_query_memsize
|
||||
property_search
|
||||
property_set_flag
|
||||
property_node_clone
|
||||
property_node_create
|
||||
property_node_datasize
|
||||
property_node_name
|
||||
property_node_refer
|
||||
property_node_remove
|
||||
property_node_type
|
||||
property_node_traversal
|
||||
property_node_refdata
|
||||
std_getenv
|
||||
std_setenv
|
||||
|
142
imports/import_64_1509_avs-ea3.def
Normal file
142
imports/import_64_1509_avs-ea3.def
Normal file
@ -0,0 +1,142 @@
|
||||
LIBRARY libavs-win64-ea3
|
||||
|
||||
EXPORTS
|
||||
XE592acd000000
|
||||
XE592acd000001
|
||||
XE592acd000002
|
||||
XE592acd000003
|
||||
XE592acd000004
|
||||
XE592acd000005
|
||||
XE592acd000006
|
||||
XE592acd000007
|
||||
XE592acd000008
|
||||
XE592acd000009
|
||||
XE592acd00000a
|
||||
XE592acd00000b
|
||||
XE592acd00000c
|
||||
XE592acd00000d
|
||||
XE592acd000010
|
||||
XE592acd000011
|
||||
XE592acd000012
|
||||
XE592acd000013
|
||||
XE592acd000014
|
||||
XE592acd000015
|
||||
XE592acd000016
|
||||
XE592acd000017
|
||||
XE592acd000019
|
||||
XE592acd00001a
|
||||
XE592acd00001b
|
||||
XE592acd00001c
|
||||
XE592acd00001d
|
||||
XE592acd00001e
|
||||
XE592acd00001f
|
||||
XE592acd000020
|
||||
XE592acd000021
|
||||
XE592acd000022
|
||||
XE592acd000023
|
||||
XE592acd000024
|
||||
XE592acd000025
|
||||
XE592acd000026
|
||||
XE592acd000027
|
||||
XE592acd000028
|
||||
XE592acd000029
|
||||
XE592acd00002a
|
||||
XE592acd00002b
|
||||
XE592acd00002c
|
||||
XE592acd00002d
|
||||
XE592acd00002e
|
||||
XE592acd00002f
|
||||
XE592acd000030
|
||||
XE592acd000031
|
||||
XE592acd000032
|
||||
XE592acd000033
|
||||
XE592acd000034
|
||||
XE592acd000035
|
||||
XE592acd000036
|
||||
XE592acd000037
|
||||
XE592acd000038
|
||||
XE592acd00003a
|
||||
XE592acd00003b
|
||||
XE592acd00003c
|
||||
XE592acd00003d
|
||||
XE592acd00003e
|
||||
XE592acd00003f
|
||||
XE592acd000040
|
||||
XE592acd000041
|
||||
XE592acd000042
|
||||
XE592acd000043
|
||||
XE592acd000044
|
||||
XE592acd000046
|
||||
XE592acd000047
|
||||
XE592acd000048
|
||||
XE592acd000049
|
||||
XE592acd00004a
|
||||
XE592acd00004b
|
||||
XE592acd00004c
|
||||
XE592acd00004d
|
||||
XE592acd00004f
|
||||
XE592acd000050
|
||||
XE592acd000051
|
||||
XE592acd000052
|
||||
XE592acd000053
|
||||
XE592acd000054
|
||||
XE592acd000055
|
||||
XE592acd000056
|
||||
XE592acd000057
|
||||
XE592acd000058
|
||||
XE592acd000059
|
||||
XE592acd00005a
|
||||
XE592acd00005c
|
||||
XE592acd00005d
|
||||
XE592acd00005e
|
||||
XE592acd00005f
|
||||
XE592acd000060
|
||||
XE592acd000061
|
||||
XE592acd000062
|
||||
XE592acd000063
|
||||
XE592acd000064
|
||||
XE592acd000065
|
||||
XE592acd000066
|
||||
XE592acd000067
|
||||
XE592acd000068
|
||||
XE592acd000069
|
||||
XE592acd00006a
|
||||
XE592acd00006b
|
||||
XE592acd00006c
|
||||
XE592acd00006d
|
||||
XE592acd00006e
|
||||
XE592acd00006f
|
||||
XE592acd000070
|
||||
XE592acd000071
|
||||
XE592acd000072
|
||||
XE592acd000073
|
||||
XE592acd000074
|
||||
XE592acd000075
|
||||
XE592acd000076
|
||||
XE592acd000077
|
||||
XE592acd000078
|
||||
XE592acd000079
|
||||
XE592acd00007a
|
||||
XE592acd00007b
|
||||
XE592acd00007c
|
||||
XE592acd00007d
|
||||
XE592acd00007e
|
||||
XE592acd00007f
|
||||
XE592acd000080
|
||||
XE592acd000081
|
||||
XE592acd000082
|
||||
XE592acd000083
|
||||
XE592acd000084
|
||||
XE592acd000085
|
||||
XE592acd000086
|
||||
XE592acd000087
|
||||
XE592acd000088
|
||||
XE592acd000089
|
||||
XE592acd00008b
|
||||
XE592acd00008c
|
||||
XE592acd00008d
|
||||
XE592acd00008e
|
||||
XE592acd00008f
|
||||
XE592acd000090
|
||||
XE592acd000091
|
||||
XE592acd000092
|
365
imports/import_64_1509_avs.def
Normal file
365
imports/import_64_1509_avs.def
Normal file
@ -0,0 +1,365 @@
|
||||
LIBRARY libavs-win64
|
||||
|
||||
EXPORTS
|
||||
XCd229cc000000
|
||||
XCd229cc000001
|
||||
XCd229cc000002
|
||||
XCd229cc000003
|
||||
XCd229cc000004
|
||||
XCd229cc000005
|
||||
XCd229cc000006
|
||||
XCd229cc000007
|
||||
XCd229cc000009
|
||||
XCd229cc00000a
|
||||
XCd229cc00000b
|
||||
XCd229cc00000c
|
||||
XCd229cc00000d
|
||||
XCd229cc00000e
|
||||
XCd229cc00000f
|
||||
XCd229cc000010
|
||||
XCd229cc000011
|
||||
XCd229cc000012
|
||||
XCd229cc000013
|
||||
XCd229cc000014
|
||||
XCd229cc000015
|
||||
XCd229cc000016
|
||||
XCd229cc000017
|
||||
XCd229cc000018
|
||||
XCd229cc000019
|
||||
XCd229cc00001a
|
||||
XCd229cc00001b
|
||||
XCd229cc00001d
|
||||
XCd229cc00001e
|
||||
XCd229cc00001f
|
||||
XCd229cc000020
|
||||
XCd229cc000021
|
||||
XCd229cc000022
|
||||
XCd229cc000023
|
||||
XCd229cc000024
|
||||
XCd229cc000025
|
||||
XCd229cc000026
|
||||
XCd229cc000027
|
||||
XCd229cc000028
|
||||
XCd229cc000029
|
||||
XCd229cc00002a
|
||||
XCd229cc00002b
|
||||
XCd229cc00002c
|
||||
XCd229cc00002d
|
||||
XCd229cc00002e
|
||||
XCd229cc00002f
|
||||
XCd229cc000030
|
||||
XCd229cc000031
|
||||
XCd229cc000032
|
||||
XCd229cc000033
|
||||
XCd229cc000034
|
||||
XCd229cc000035
|
||||
XCd229cc000036
|
||||
XCd229cc000037
|
||||
XCd229cc000038
|
||||
XCd229cc000039
|
||||
XCd229cc00003a
|
||||
XCd229cc00003b
|
||||
XCd229cc00003c
|
||||
XCd229cc00003d
|
||||
XCd229cc00003e
|
||||
XCd229cc00003f
|
||||
XCd229cc000040
|
||||
XCd229cc000041
|
||||
XCd229cc000042
|
||||
XCd229cc000043
|
||||
XCd229cc000044
|
||||
XCd229cc000045
|
||||
XCd229cc000046
|
||||
XCd229cc000047
|
||||
XCd229cc000048
|
||||
XCd229cc000049
|
||||
XCd229cc00004a
|
||||
XCd229cc00004b
|
||||
XCd229cc00004c
|
||||
XCd229cc00004d
|
||||
XCd229cc00004e
|
||||
XCd229cc00004f
|
||||
XCd229cc000050
|
||||
XCd229cc000051
|
||||
XCd229cc000052
|
||||
XCd229cc000053
|
||||
XCd229cc000054
|
||||
XCd229cc000055
|
||||
XCd229cc000056
|
||||
XCd229cc000057
|
||||
XCd229cc000058
|
||||
XCd229cc000059
|
||||
XCd229cc00005a
|
||||
XCd229cc00005b
|
||||
XCd229cc00005c
|
||||
XCd229cc00005d
|
||||
XCd229cc00005e
|
||||
XCd229cc00005f
|
||||
XCd229cc000060
|
||||
XCd229cc000061
|
||||
XCd229cc000062
|
||||
XCd229cc000063
|
||||
XCd229cc000064
|
||||
XCd229cc000065
|
||||
XCd229cc000066
|
||||
XCd229cc000067
|
||||
XCd229cc000068
|
||||
XCd229cc000069
|
||||
XCd229cc00006a
|
||||
XCd229cc00006b
|
||||
XCd229cc00006c
|
||||
XCd229cc00006d
|
||||
XCd229cc00006e
|
||||
XCd229cc00006f
|
||||
XCd229cc000070
|
||||
XCd229cc000071
|
||||
XCd229cc000072
|
||||
XCd229cc000073
|
||||
XCd229cc000074
|
||||
XCd229cc000075
|
||||
XCd229cc000076
|
||||
XCd229cc000077
|
||||
XCd229cc000078
|
||||
XCd229cc000079
|
||||
XCd229cc00007a
|
||||
XCd229cc00007b
|
||||
XCd229cc00007c
|
||||
XCd229cc00007d
|
||||
XCd229cc00007e
|
||||
XCd229cc00007f
|
||||
XCd229cc000080
|
||||
XCd229cc000081
|
||||
XCd229cc000082
|
||||
XCd229cc000083
|
||||
XCd229cc000084
|
||||
XCd229cc000085
|
||||
XCd229cc000086
|
||||
XCd229cc000087
|
||||
XCd229cc000088
|
||||
XCd229cc000089
|
||||
XCd229cc00008a
|
||||
XCd229cc00008b
|
||||
XCd229cc00008c
|
||||
XCd229cc00008d
|
||||
XCd229cc00008e
|
||||
XCd229cc00008f
|
||||
XCd229cc000090
|
||||
XCd229cc000091
|
||||
XCd229cc000092
|
||||
XCd229cc000093
|
||||
XCd229cc000094
|
||||
XCd229cc000095
|
||||
XCd229cc000096
|
||||
XCd229cc000097
|
||||
XCd229cc000098
|
||||
XCd229cc000099
|
||||
XCd229cc00009a
|
||||
XCd229cc00009b
|
||||
XCd229cc00009c
|
||||
XCd229cc00009d
|
||||
XCd229cc00009e
|
||||
XCd229cc00009f
|
||||
XCd229cc0000a0
|
||||
XCd229cc0000a1
|
||||
XCd229cc0000a2
|
||||
XCd229cc0000a3
|
||||
XCd229cc0000a4
|
||||
XCd229cc0000a5
|
||||
XCd229cc0000a6
|
||||
XCd229cc0000a7
|
||||
XCd229cc0000a8
|
||||
XCd229cc0000a9
|
||||
XCd229cc0000aa
|
||||
XCd229cc0000ab
|
||||
XCd229cc0000ac
|
||||
XCd229cc0000ad
|
||||
XCd229cc0000ae
|
||||
XCd229cc0000af
|
||||
XCd229cc0000b0
|
||||
XCd229cc0000b1
|
||||
XCd229cc0000b2
|
||||
XCd229cc0000b3
|
||||
XCd229cc0000b4
|
||||
XCd229cc0000b5
|
||||
XCd229cc0000b6
|
||||
XCd229cc0000b7
|
||||
XCd229cc0000b8
|
||||
XCd229cc0000b9
|
||||
XCd229cc0000ba
|
||||
XCd229cc0000bb
|
||||
XCd229cc0000bc
|
||||
XCd229cc0000bd
|
||||
XCd229cc0000be
|
||||
XCd229cc0000bf
|
||||
XCd229cc0000c0
|
||||
XCd229cc0000c1
|
||||
XCd229cc0000c2
|
||||
XCd229cc0000c3
|
||||
XCd229cc0000c4
|
||||
XCd229cc0000c5
|
||||
XCd229cc0000c6
|
||||
XCd229cc0000c7
|
||||
XCd229cc0000c8
|
||||
XCd229cc0000c9
|
||||
XCd229cc0000ca
|
||||
XCd229cc0000cb
|
||||
XCd229cc0000cc
|
||||
XCd229cc0000cd
|
||||
XCd229cc0000ce
|
||||
XCd229cc0000cf
|
||||
XCd229cc0000d0
|
||||
XCd229cc0000d1
|
||||
XCd229cc0000d2
|
||||
XCd229cc0000d3
|
||||
XCd229cc0000d4
|
||||
XCd229cc0000d5
|
||||
XCd229cc0000d6
|
||||
XCd229cc0000d7
|
||||
XCd229cc0000d8
|
||||
XCd229cc0000d9
|
||||
XCd229cc0000da
|
||||
XCd229cc0000db
|
||||
XCd229cc0000dc
|
||||
XCd229cc0000dd
|
||||
XCd229cc0000de
|
||||
XCd229cc0000df
|
||||
XCd229cc0000e0
|
||||
XCd229cc0000e1
|
||||
XCd229cc0000e2
|
||||
XCd229cc0000e3
|
||||
XCd229cc0000e4
|
||||
XCd229cc0000e5
|
||||
XCd229cc0000e6
|
||||
XCd229cc0000e7
|
||||
XCd229cc0000e8
|
||||
XCd229cc0000e9
|
||||
XCd229cc0000ea
|
||||
XCd229cc0000eb
|
||||
XCd229cc0000ec
|
||||
XCd229cc0000ed
|
||||
XCd229cc0000ee
|
||||
XCd229cc0000ef
|
||||
XCd229cc0000f0
|
||||
XCd229cc0000f1
|
||||
XCd229cc0000f2
|
||||
XCd229cc0000f3
|
||||
XCd229cc0000f4
|
||||
XCd229cc0000f6
|
||||
XCd229cc0000f7
|
||||
XCd229cc0000f8
|
||||
XCd229cc0000f9
|
||||
XCd229cc0000fa
|
||||
XCd229cc0000fb
|
||||
XCd229cc0000fc
|
||||
XCd229cc0000fd
|
||||
XCd229cc0000fe
|
||||
XCd229cc0000ff
|
||||
XCd229cc000100
|
||||
XCd229cc000102
|
||||
XCd229cc000103
|
||||
XCd229cc000104
|
||||
XCd229cc000105
|
||||
XCd229cc000106
|
||||
XCd229cc000107
|
||||
XCd229cc000108
|
||||
XCd229cc000109
|
||||
XCd229cc00010a
|
||||
XCd229cc00010b
|
||||
XCd229cc00010c
|
||||
XCd229cc00010d
|
||||
XCd229cc00010e
|
||||
XCd229cc00010f
|
||||
XCd229cc000110
|
||||
XCd229cc000111
|
||||
XCd229cc000112
|
||||
XCd229cc000113
|
||||
XCd229cc000114
|
||||
XCd229cc000115
|
||||
XCd229cc000116
|
||||
XCd229cc000117
|
||||
XCd229cc000118
|
||||
XCd229cc000119
|
||||
XCd229cc00011a
|
||||
XCd229cc00011b
|
||||
XCd229cc00011c
|
||||
XCd229cc00011d
|
||||
XCd229cc00011e
|
||||
XCd229cc00011f
|
||||
XCd229cc000120
|
||||
XCd229cc000121
|
||||
XCd229cc000122
|
||||
XCd229cc000123
|
||||
XCd229cc000124
|
||||
XCd229cc000125
|
||||
XCd229cc000126
|
||||
XCd229cc000127
|
||||
XCd229cc000128
|
||||
XCd229cc000129
|
||||
XCd229cc00012a
|
||||
XCd229cc00012b
|
||||
XCd229cc00012c
|
||||
XCd229cc00012d
|
||||
XCd229cc00012e
|
||||
XCd229cc00012f
|
||||
XCd229cc000130
|
||||
XCd229cc000131
|
||||
XCd229cc000132
|
||||
XCd229cc000133
|
||||
XCd229cc000134
|
||||
XCd229cc000135
|
||||
XCd229cc000136
|
||||
XCd229cc000137
|
||||
XCd229cc000138
|
||||
XCd229cc000139
|
||||
XCd229cc00013a
|
||||
XCd229cc00013b
|
||||
XCd229cc00013c
|
||||
XCd229cc00013d
|
||||
XCd229cc00013e
|
||||
XCd229cc00013f
|
||||
XCd229cc000140
|
||||
XCd229cc000141
|
||||
XCd229cc000142
|
||||
XCd229cc000143
|
||||
XCd229cc000144
|
||||
XCd229cc000145
|
||||
XCd229cc000146
|
||||
XCd229cc000147
|
||||
XCd229cc000148
|
||||
XCd229cc000149
|
||||
XCd229cc00014b
|
||||
XCd229cc00014c
|
||||
XCd229cc00014d
|
||||
XCd229cc00014e
|
||||
XCd229cc00014f
|
||||
XCd229cc000150
|
||||
XCd229cc000151
|
||||
XCd229cc000152
|
||||
XCd229cc000153
|
||||
XCd229cc000154
|
||||
XCd229cc000155
|
||||
XCd229cc000156
|
||||
XCd229cc000157
|
||||
XCd229cc000158
|
||||
XCd229cc000159
|
||||
XCd229cc00015a
|
||||
XCd229cc00015b
|
||||
XCd229cc00015c
|
||||
XCd229cc00015d
|
||||
XCd229cc00015e
|
||||
XCd229cc00015f
|
||||
XCd229cc000160
|
||||
XCd229cc000161
|
||||
XCd229cc000162
|
||||
XCd229cc000163
|
||||
XCd229cc000164
|
||||
XCd229cc000165
|
||||
XCd229cc000166
|
||||
XCd229cc000167
|
||||
XCd229cc000168
|
||||
XCd229cc000169
|
||||
XCd229cc00016a
|
||||
XCd229cc00016b
|
||||
XCd229cc00016c
|
||||
XCd229cc000170
|
||||
XCd229cc000171
|
53
imports/import_64_1700_avs.def
Normal file
53
imports/import_64_1700_avs.def
Normal file
@ -0,0 +1,53 @@
|
||||
LIBRARY avs2-core
|
||||
|
||||
EXPORTS
|
||||
XCgsqzn0000007
|
||||
XCgsqzn0000004
|
||||
XCgsqzn0000006
|
||||
XCgsqzn000000a
|
||||
XCgsqzn000000b
|
||||
XCgsqzn0000076
|
||||
XCgsqzn0000090
|
||||
XCgsqzn0000091
|
||||
XCgsqzn0000092
|
||||
XCgsqzn0000094
|
||||
XCgsqzn00000a1
|
||||
XCgsqzn00000a2
|
||||
XCgsqzn00000a3
|
||||
XCgsqzn00000af
|
||||
XCgsqzn00000b0
|
||||
XCgsqzn00000b2
|
||||
XCgsqzn00000b3
|
||||
XCgsqzn00000d3
|
||||
XCgsqzn00000d4
|
||||
XCgsqzn0000129
|
||||
XCgsqzn000012a
|
||||
XCgsqzn000017a
|
||||
XCgsqzn000017b
|
||||
XCgsqzn000017c
|
||||
XCgsqzn000017d
|
||||
XCgsqzn000004e
|
||||
XCgsqzn0000055
|
||||
XCgsqzn0000065
|
||||
XCgsqzn0000068
|
||||
XCgsqzn00000d5
|
||||
XCgsqzn0000051
|
||||
XCgsqzn00000a6
|
||||
XCgsqzn0000144
|
||||
XCgsqzn0000077
|
||||
XCgsqzn0000079
|
||||
XCgsqzn000007a
|
||||
XCgsqzn000007b
|
||||
XCgsqzn000007c
|
||||
XCgsqzn000007d
|
||||
XCgsqzn000007e
|
||||
XCgsqzn000007f
|
||||
XCgsqzn0000080
|
||||
XCgsqzn0000081
|
||||
XCgsqzn0000082
|
||||
XCgsqzn0000086
|
||||
XCgsqzn000008c
|
||||
XCgsqzn000008d
|
||||
XCgsqzn000008e
|
||||
XCgsqzn000008f
|
||||
XCgsqzn0000078
|
81
minhook/LICENSE.txt
Normal file
81
minhook/LICENSE.txt
Normal file
@ -0,0 +1,81 @@
|
||||
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.
|
||||
|
||||
================================================================================
|
||||
Portions of this software are Copyright (c) 2008-2009, Vyacheslav Patkov.
|
||||
================================================================================
|
||||
Hacker Disassembler Engine 32 C
|
||||
Copyright (c) 2008-2009, Vyacheslav Patkov.
|
||||
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 REGENTS 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.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Hacker Disassembler Engine 64 C
|
||||
Copyright (c) 2008-2009, Vyacheslav Patkov.
|
||||
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 REGENTS 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.
|
8
minhook/Module.mk
Normal file
8
minhook/Module.mk
Normal file
@ -0,0 +1,8 @@
|
||||
libs += minhook
|
||||
|
||||
src_minhook := \
|
||||
hook.c \
|
||||
buffer.c \
|
||||
trampoline.c \
|
||||
hde32.c \
|
||||
hde64.c \
|
312
minhook/buffer.c
Normal file
312
minhook/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
minhook/buffer.h
Normal file
42
minhook/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);
|
326
minhook/hde32.c
Normal file
326
minhook/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
minhook/hde32.h
Normal file
105
minhook/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
minhook/hde64.c
Normal file
337
minhook/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
minhook/hde64.h
Normal file
112
minhook/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_ */
|
889
minhook/hook.c
Normal file
889
minhook/hook.c
Normal file
@ -0,0 +1,889 @@
|
||||
/*
|
||||
* 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)";
|
||||
}
|
186
minhook/include/MinHook.h
Normal file
186
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
|
||||
|
39
minhook/pstdint.h
Normal file
39
minhook/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
minhook/table32.h
Normal file
73
minhook/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
minhook/table64.h
Normal file
74
minhook/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
|
||||
};
|
316
minhook/trampoline.c
Normal file
316
minhook/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 "hde64.h"
|
||||
typedef hde64s HDE;
|
||||
#define HDE_DISASM(code, hs) hde64_disasm(code, hs)
|
||||
#else
|
||||
#include "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
minhook/trampoline.h
Normal file
105
minhook/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);
|
16
popnhax/Module.mk
Normal file
16
popnhax/Module.mk
Normal file
@ -0,0 +1,16 @@
|
||||
avsdlls += popnhax
|
||||
|
||||
deplibs_popnhax := \
|
||||
avs \
|
||||
|
||||
ldflags_popnhax := \
|
||||
-lwinmm -lpsapi
|
||||
|
||||
libs_popnhax := \
|
||||
util \
|
||||
minhook
|
||||
|
||||
srcpp_popnhax := \
|
||||
dllmain.cc \
|
||||
loader.cc \
|
||||
SearchFile.cc
|
49
popnhax/SearchFile.cc
Normal file
49
popnhax/SearchFile.cc
Normal file
@ -0,0 +1,49 @@
|
||||
|
||||
#include <windows.h>
|
||||
#include "SearchFile.h"
|
||||
|
||||
vector<string> SearchFile::getResult()
|
||||
{
|
||||
auto t = result;
|
||||
result.clear();
|
||||
return t;
|
||||
}
|
||||
|
||||
bool SearchFile::search(const char *path, const char *ext, bool subfolders_only)
|
||||
{
|
||||
HANDLE hFile;
|
||||
char buffer[MAX_PATH]={0,};
|
||||
WIN32_FIND_DATA pNextInfo;
|
||||
string t;
|
||||
|
||||
sprintf(buffer,"%s\\*.*",path);
|
||||
hFile = FindFirstFileA(buffer,&pNextInfo);
|
||||
if(!hFile){
|
||||
return false;
|
||||
}
|
||||
|
||||
while(FindNextFileA(hFile,&pNextInfo))
|
||||
{
|
||||
if(pNextInfo.cFileName[0] == '.')// . and ..
|
||||
continue;
|
||||
|
||||
if(pNextInfo.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY && subfolders_only)
|
||||
{
|
||||
ZeroMemory(buffer,MAX_PATH);
|
||||
sprintf(buffer,"%s\\%s",path,pNextInfo.cFileName);
|
||||
search(buffer,ext,false);
|
||||
}
|
||||
if (!subfolders_only)
|
||||
{
|
||||
t.assign(path);
|
||||
t+='\\';
|
||||
t.append(pNextInfo.cFileName);
|
||||
if(t.substr(t.size()-strlen(ext))==ext)
|
||||
{
|
||||
result.push_back(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
14
popnhax/SearchFile.h
Normal file
14
popnhax/SearchFile.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef __SEARCHFILE_H_
|
||||
#define __SEARCHFILE_H_
|
||||
#include <vector>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
class SearchFile
|
||||
{
|
||||
private:
|
||||
vector<string> result;
|
||||
public:
|
||||
vector<string> getResult();
|
||||
bool search(const char *path,const char *ext,bool subfolders_only);
|
||||
};
|
||||
#endif
|
21
popnhax/config.h
Normal file
21
popnhax/config.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef __POPNHAX_CONFIG__
|
||||
#define __POPNHAX_CONFIG__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct popnhax_config {
|
||||
bool force_unlocks;
|
||||
bool unset_volume;
|
||||
bool event_mode;
|
||||
bool remove_timer;
|
||||
bool freeze_timer;
|
||||
bool skip_tutorials;
|
||||
|
||||
bool patch_db;
|
||||
bool disable_expansions;
|
||||
bool disable_redirection;
|
||||
bool patch_xml_auto;
|
||||
char patch_xml_filename[MAX_PATH];
|
||||
};
|
||||
|
||||
#endif
|
1078
popnhax/dllmain.cc
Normal file
1078
popnhax/dllmain.cc
Normal file
File diff suppressed because it is too large
Load Diff
1282
popnhax/loader.cc
Normal file
1282
popnhax/loader.cc
Normal file
File diff suppressed because it is too large
Load Diff
18
popnhax/loader.h
Normal file
18
popnhax/loader.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef __LOADER_H__
|
||||
#define __LOADER_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int8_t get_chart_type_override(uint8_t *, uint32_t, uint32_t);
|
||||
|
||||
void musichax_core_init(bool force_unlocks, bool is_expansion_allowed, bool is_redirection_allowed,
|
||||
char *target_datecode, char *base_data, uint64_t music_size,
|
||||
uint64_t *new_music_size, char *orig_music_data, uint8_t **new_music_table,
|
||||
uint64_t chart_size, uint64_t *new_chart_size, char *orig_chart_data,
|
||||
uint8_t **new_chart_table, uint64_t style_size, uint64_t *new_style_size,
|
||||
char *orig_style_data, uint8_t **new_style_table, uint64_t flavor_size,
|
||||
uint64_t *new_flavor_size, char *orig_flavor_data,
|
||||
uint8_t **new_flavor_table, uint64_t chara_size, uint64_t *new_chara_size,
|
||||
char *orig_chara_data, uint8_t **new_chara_table);
|
||||
|
||||
#endif
|
2
popnhax/popnhax.def
Normal file
2
popnhax/popnhax.def
Normal file
@ -0,0 +1,2 @@
|
||||
LIBRARY popnhax
|
||||
EXPORTS
|
95
popnhax/tableinfo.h
Normal file
95
popnhax/tableinfo.h
Normal file
@ -0,0 +1,95 @@
|
||||
#ifndef __TABLEINFO_H__
|
||||
#define __TABLEINFO_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t *folder_ptr;
|
||||
uint8_t *filename_ptr;
|
||||
int32_t audio_param1;
|
||||
int32_t audio_param2;
|
||||
int32_t audio_param3;
|
||||
int32_t audio_param4;
|
||||
uint32_t file_type;
|
||||
uint16_t used_keys;
|
||||
uint8_t pad[2];
|
||||
} chart_entry;
|
||||
|
||||
typedef struct {
|
||||
uint32_t fontface;
|
||||
uint32_t color;
|
||||
uint32_t height;
|
||||
uint32_t width;
|
||||
} fontstyle_entry;
|
||||
|
||||
typedef struct {
|
||||
uint8_t phrase1[13];
|
||||
uint8_t phrase2[13];
|
||||
uint8_t phrase3[13];
|
||||
uint8_t phrase4[13];
|
||||
uint8_t phrase5[13];
|
||||
uint8_t phrase6[13];
|
||||
uint8_t _pad1[2];
|
||||
uint8_t *birthday_ptr;
|
||||
uint8_t chara1_birth_month;
|
||||
uint8_t chara2_birth_month;
|
||||
uint8_t chara3_birth_month;
|
||||
uint8_t chara1_birth_date;
|
||||
uint8_t chara2_birth_date;
|
||||
uint8_t chara3_birth_date;
|
||||
uint16_t style1;
|
||||
uint16_t style2;
|
||||
uint16_t style3;
|
||||
} flavor_entry;
|
||||
|
||||
typedef struct {
|
||||
uint8_t *chara_id_ptr;
|
||||
uint32_t flags;
|
||||
uint8_t *folder_ptr;
|
||||
uint8_t *gg_ptr;
|
||||
uint8_t *cs_ptr;
|
||||
uint8_t *icon1_ptr;
|
||||
uint8_t *icon2_ptr;
|
||||
uint16_t chara_xw;
|
||||
uint16_t chara_yh;
|
||||
uint32_t display_flags;
|
||||
int16_t flavor_idx;
|
||||
uint8_t chara_variation_num;
|
||||
uint8_t _pad1[1];
|
||||
uint8_t *sort_name_ptr;
|
||||
uint8_t *disp_name_ptr;
|
||||
uint32_t file_type;
|
||||
uint32_t lapis_shape;
|
||||
uint8_t lapis_color;
|
||||
uint8_t _pad2[3];
|
||||
uint8_t *ha_ptr;
|
||||
uint8_t *catchtext_ptr;
|
||||
int16_t win2_trigger;
|
||||
uint8_t _pad3[2];
|
||||
uint32_t game_version;
|
||||
} character_entry;
|
||||
|
||||
typedef struct {
|
||||
uint8_t *fw_genre_ptr;
|
||||
uint8_t *fw_title_ptr;
|
||||
uint8_t *fw_artist_ptr;
|
||||
uint8_t *genre_ptr;
|
||||
uint8_t *title_ptr;
|
||||
uint8_t *artist_ptr;
|
||||
uint16_t chara1;
|
||||
uint16_t chara2;
|
||||
uint32_t mask;
|
||||
uint32_t folder;
|
||||
uint32_t cs_version;
|
||||
uint32_t categories;
|
||||
uint8_t diffs[6];
|
||||
uint16_t charts[7];
|
||||
uint8_t *ha_ptr;
|
||||
uint32_t chara_x;
|
||||
uint32_t chara_y;
|
||||
uint16_t unk1[32];
|
||||
uint16_t display_bpm[12];
|
||||
uint8_t hold_flags[8];
|
||||
} music_entry;
|
||||
|
||||
#endif
|
134
popnhax/xmlhelper.h
Normal file
134
popnhax/xmlhelper.h
Normal file
@ -0,0 +1,134 @@
|
||||
#define READ_HEX(_xml, _prop, _prop_name, _var_output) \
|
||||
{unsigned char _temp[256] = {}; \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_STR, _temp, sizeof(_temp)); \
|
||||
_var_output = strtol((const char*)_temp, NULL, 16); \
|
||||
} \
|
||||
|
||||
#define READ_STR_RAW(_xml, _prop, _prop_name, _var_name) \
|
||||
unsigned char _var_name[256] = {}; \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_STR, _var_name, sizeof(_var_name)); \
|
||||
|
||||
#define READ_STR(_xml, _prop, _prop_name, _var_name, _var_output) \
|
||||
unsigned char _var_name[256] = {}; \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_STR, _var_name, sizeof(_var_name)); \
|
||||
uint8_t *_var_output = add_string(_var_name);
|
||||
|
||||
#define READ_U8_ARR(_xml, _prop, _prop_name, _var_name, _elm_cnt) \
|
||||
uint8_t _var_name[_elm_cnt] = {}; \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_U8, (char*)&_var_name, sizeof(_var_name[0]) * _elm_cnt);
|
||||
|
||||
#define READ_U8(_xml, _prop, _prop_name, _var_name) \
|
||||
uint8_t _var_name = 0; \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_U8, (char*)&_var_name, sizeof(_var_name));
|
||||
|
||||
#define READ_S8(_xml, _prop, _prop_name, _var_name) \
|
||||
int8_t _var_name = 0; \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_U8, (char*)&_var_name, sizeof(_var_name));
|
||||
|
||||
#define READ_U16_ARR(_xml, _prop, _prop_name, _var_name, _elm_cnt) \
|
||||
uint16_t _var_name[_elm_cnt] = {}; \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_U16, (char*)&_var_name, sizeof(_var_name[0]) * _elm_cnt);
|
||||
|
||||
#define READ_U16(_xml, _prop, _prop_name, _var_name) \
|
||||
uint16_t _var_name = 0; \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_U16, (char*)&_var_name, sizeof(_var_name));
|
||||
|
||||
#define READ_S16(_xml, _prop, _prop_name, _var_name) \
|
||||
int16_t _var_name = 0; \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_S16, (char*)&_var_name, sizeof(_var_name));
|
||||
|
||||
#define READ_U32(_xml, _prop, _prop_name, _var_name) \
|
||||
uint32_t _var_name = 0; \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_U32, (char*)&_var_name, sizeof(_var_name));
|
||||
|
||||
#define READ_S32(_xml, _prop, _prop_name, _var_name) \
|
||||
uint32_t _var_name = 0; \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_S32, (char*)&_var_name, sizeof(_var_name));
|
||||
|
||||
|
||||
// Optionals: Update _var_output if _prop_name exists
|
||||
#define READ_STR_OPT(_xml, _prop, _prop_name, _var_output) \
|
||||
{ \
|
||||
if (property_search(_xml, _prop, _prop_name)) { \
|
||||
unsigned char _var_tempname[256] = {}; \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_STR, _var_tempname, sizeof(_var_tempname)); \
|
||||
_var_output = add_string(_var_tempname); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_U32_OPT(_xml, _prop, _prop_name, _var_output) \
|
||||
{ \
|
||||
if (property_search(_xml, _prop, _prop_name)) { \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_U32, (char*)&_var_output, sizeof(_var_output)); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_S32_OPT(_xml, _prop, _prop_name, _var_output) \
|
||||
{ \
|
||||
if (property_search(_xml, _prop, _prop_name)) { \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_S32, (char*)&_var_output, sizeof(_var_output)); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_U16_OPT(_xml, _prop, _prop_name, _var_output) \
|
||||
{ \
|
||||
if (property_search(_xml, _prop, _prop_name)) { \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_U16, (char*)&_var_output, sizeof(_var_output)); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_S16_OPT(_xml, _prop, _prop_name, _var_output) \
|
||||
{ \
|
||||
if (property_search(_xml, _prop, _prop_name)) { \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_S16, (char*)&_var_output, sizeof(_var_output)); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_U8_OPT(_xml, _prop, _prop_name, _var_output) \
|
||||
{ \
|
||||
if (property_search(_xml, _prop, _prop_name)) { \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_U8, (char*)&_var_output, sizeof(_var_output)); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_U8_ARR_OPT(_xml, _prop, _prop_name, _var_output, _elm_cnt) \
|
||||
{ \
|
||||
if (property_search(_xml, _prop, _prop_name)) { \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_U8, (char*)&_var_output, sizeof(_var_output[0]) * _elm_cnt); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_U16_ARR_OPT(_xml, _prop, _prop_name, _var_output, _elm_cnt) \
|
||||
{ \
|
||||
if (property_search(_xml, _prop, _prop_name)) { \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_U16, (char*)&_var_output, sizeof(_var_output[0]) * _elm_cnt); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
#define READ_CHARA_OPT(_xml, _prop, _prop_name, _var_output) \
|
||||
{ \
|
||||
if (property_search(_xml, _prop, _prop_name)) { \
|
||||
unsigned char _var_tempname[256] = {}; \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_STR, _var_tempname, sizeof(_var_tempname)); \
|
||||
_var_output = get_chara_idx(_var_tempname); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_LAPIS_SHAPE_OPT(_xml, _prop, _prop_name, _var_output) \
|
||||
{ \
|
||||
if (property_search(_xml, _prop, _prop_name)) { \
|
||||
unsigned char _var_tempname[256] = {}; \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_STR, _var_tempname, sizeof(_var_tempname)); \
|
||||
_var_output = get_lapis_shape_id(_var_tempname); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_LAPIS_COLOR_OPT(_xml, _prop, _prop_name, _var_output) \
|
||||
{ \
|
||||
if (property_search(_xml, _prop, _prop_name)) { \
|
||||
unsigned char _var_tempname[256] = {}; \
|
||||
property_node_refer(_xml, _prop, _prop_name, PROPERTY_TYPE_STR, _var_tempname, sizeof(_var_tempname)); \
|
||||
_var_output = get_lapis_color_id(_var_tempname); \
|
||||
} \
|
||||
}
|
6
util/Module.mk
Normal file
6
util/Module.mk
Normal file
@ -0,0 +1,6 @@
|
||||
libs += util
|
||||
|
||||
srcpp_util := \
|
||||
fuzzy_search.cc \
|
||||
cmdline.cc \
|
||||
patch.cc \
|
95
util/cmdline.cc
Normal file
95
util/cmdline.cc
Normal file
@ -0,0 +1,95 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
void *xmalloc(size_t nbytes) {
|
||||
void *mem;
|
||||
|
||||
mem = malloc(nbytes);
|
||||
|
||||
if (mem == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
void *xrealloc(void *mem, size_t nbytes) {
|
||||
void *newmem;
|
||||
|
||||
newmem = realloc(mem, nbytes);
|
||||
|
||||
if (newmem == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return newmem;
|
||||
}
|
||||
|
||||
static void push_argv(int *argc, char ***argv, const char *begin, const char *end) {
|
||||
size_t nchars;
|
||||
char *str;
|
||||
|
||||
(*argc)++;
|
||||
*argv = (char **)xrealloc(*argv, *argc * sizeof(char **));
|
||||
|
||||
nchars = end - begin;
|
||||
str = (char *)xmalloc(nchars + 1);
|
||||
memcpy(str, begin, nchars);
|
||||
str[nchars] = '\0';
|
||||
|
||||
(*argv)[*argc - 1] = str;
|
||||
}
|
||||
|
||||
void args_recover(int *argc_out, char ***argv_out) {
|
||||
int argc;
|
||||
char **argv;
|
||||
char *begin;
|
||||
char *pos;
|
||||
bool quote;
|
||||
|
||||
argc = 0;
|
||||
argv = NULL;
|
||||
quote = false;
|
||||
|
||||
for (begin = pos = GetCommandLine(); *pos; pos++) {
|
||||
switch (*pos) {
|
||||
case '"':
|
||||
if (!quote) {
|
||||
quote = true;
|
||||
begin = pos + 1;
|
||||
} else {
|
||||
push_argv(&argc, &argv, begin, pos);
|
||||
|
||||
quote = false;
|
||||
begin = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
if (!quote && begin != NULL) {
|
||||
push_argv(&argc, &argv, begin, pos);
|
||||
begin = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if (begin == NULL) {
|
||||
begin = pos;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (begin != NULL && !quote) {
|
||||
push_argv(&argc, &argv, begin, pos);
|
||||
}
|
||||
|
||||
*argc_out = argc;
|
||||
*argv_out = argv;
|
||||
}
|
7
util/cmdline.h
Normal file
7
util/cmdline.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef UTIL_CMDLINE_H
|
||||
#define UTIL_CMDLINE_H
|
||||
|
||||
void args_recover(int *argc, char ***argv);
|
||||
void args_free(int argc, char **argv);
|
||||
|
||||
#endif
|
62
util/fuzzy_search.cc
Normal file
62
util/fuzzy_search.cc
Normal file
@ -0,0 +1,62 @@
|
||||
#include <memory.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "util/fuzzy_search.h"
|
||||
|
||||
int find_block_core(char *haystack, size_t haystack_size, fuzzy_search_task *needle,
|
||||
size_t orig_offset, int dir) {
|
||||
size_t offset = orig_offset;
|
||||
haystack_size += orig_offset;
|
||||
while (offset + 1 < orig_offset + haystack_size) {
|
||||
size_t offset_temp = offset;
|
||||
int found = 1;
|
||||
|
||||
if (needle->count <= 0) {
|
||||
found = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < needle->count; i++) {
|
||||
int subfound = -1;
|
||||
|
||||
if (needle->blocks[i].type == 1) {
|
||||
offset_temp += needle->blocks[i].length;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < needle->blocks[i].count; j++) {
|
||||
if (haystack + offset_temp + needle->blocks[i].data[j].length <
|
||||
haystack + haystack_size &&
|
||||
memcmp(haystack + offset_temp, needle->blocks[i].data[j].block,
|
||||
needle->blocks[i].data[j].length) == 0) {
|
||||
subfound = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (subfound == -1) {
|
||||
found = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
offset_temp += needle->blocks[i].data[subfound].length;
|
||||
}
|
||||
|
||||
if (found == 1) {
|
||||
return offset;
|
||||
} else {
|
||||
offset += dir;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int find_block(char *haystack, size_t haystack_size, fuzzy_search_task *needle,
|
||||
size_t orig_offset) {
|
||||
return find_block_core(haystack, haystack_size, needle, orig_offset, 1);
|
||||
}
|
||||
|
||||
int find_block_back(char *haystack, size_t haystack_size, fuzzy_search_task *needle,
|
||||
size_t orig_offset) {
|
||||
return find_block_core(haystack, haystack_size, needle, orig_offset, -1);
|
||||
}
|
53
util/fuzzy_search.h
Normal file
53
util/fuzzy_search.h
Normal file
@ -0,0 +1,53 @@
|
||||
#ifndef __FUZZY_SEARCH_H__
|
||||
#define __FUZZY_SEARCH_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define FUZZY_START(task, _count) \
|
||||
{ \
|
||||
task.count = _count; \
|
||||
task.blocks = (fuzzy_search_block *)calloc(task.count, sizeof(fuzzy_search_block)); \
|
||||
}
|
||||
|
||||
#define FUZZY_CODE(task, id, code, len) \
|
||||
{ \
|
||||
task.blocks[id].count = 1; \
|
||||
task.blocks[id].data[0].type = 0; \
|
||||
task.blocks[id].data[0].length = len; \
|
||||
task.blocks[id].data[0].block = \
|
||||
(char *)calloc(task.blocks[id].data[0].length, sizeof(char)); \
|
||||
memcpy(task.blocks[id].data[0].block, code, task.blocks[id].data[0].length); \
|
||||
}
|
||||
|
||||
#define FUZZY_WILDCARD(task, id, len) \
|
||||
{ \
|
||||
task.blocks[id].count = 1; \
|
||||
task.blocks[id].type = 1; \
|
||||
task.blocks[id].length = len; \
|
||||
task.blocks[id].data[0].length = len; \
|
||||
}
|
||||
|
||||
#define FUZZY_SIZE(task, id) (task.blocks[id].data[0].length)
|
||||
|
||||
typedef struct fuzzy_search_block_data {
|
||||
int type;
|
||||
int length;
|
||||
char *block;
|
||||
} fuzzy_search_block_data;
|
||||
|
||||
typedef struct fuzzy_search_block {
|
||||
int type;
|
||||
int length;
|
||||
int count;
|
||||
fuzzy_search_block_data data[0x10];
|
||||
} fuzzy_search_block;
|
||||
|
||||
typedef struct fuzzy_search_task {
|
||||
int count;
|
||||
fuzzy_search_block *blocks;
|
||||
} fuzzy_search_task;
|
||||
|
||||
int find_block(char *haystack, size_t haystack_size, fuzzy_search_task *needle, size_t offset);
|
||||
int find_block_back(char *haystack, size_t haystack_size, fuzzy_search_task *needle, size_t offset);
|
||||
|
||||
#endif
|
27
util/patch.cc
Normal file
27
util/patch.cc
Normal file
@ -0,0 +1,27 @@
|
||||
// clang-format off
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
// clang-format on
|
||||
|
||||
#include "patch.h"
|
||||
|
||||
void patch_memory(uint64_t patch_addr, char *data, size_t len) {
|
||||
DWORD old_prot;
|
||||
VirtualProtect((LPVOID)patch_addr, len, PAGE_EXECUTE_READWRITE, &old_prot);
|
||||
memcpy((LPVOID)patch_addr, data, len);
|
||||
VirtualProtect((LPVOID)patch_addr, len, old_prot, &old_prot);
|
||||
}
|
||||
|
||||
char *getDllData(const char *dllFilename, DWORD *dllSize) {
|
||||
HMODULE _moduleBase = GetModuleHandle(dllFilename);
|
||||
MODULEINFO module_info;
|
||||
|
||||
memset(&module_info, 0, sizeof(module_info));
|
||||
if (!GetModuleInformation(GetCurrentProcess(), _moduleBase, &module_info,
|
||||
sizeof(module_info))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*dllSize = module_info.SizeOfImage;
|
||||
return (char *)module_info.lpBaseOfDll;
|
||||
}
|
13
util/patch.h
Normal file
13
util/patch.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef __PATCH_H__
|
||||
#define __PATCH_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef unsigned long DWORD;
|
||||
|
||||
void patch_memory(uint64_t patch_addr, char *data, size_t len);
|
||||
char *getDllData(const char *dllFilename, DWORD *dllSize);
|
||||
|
||||
#endif
|
100
util/xmlprop.hpp
Normal file
100
util/xmlprop.hpp
Normal file
@ -0,0 +1,100 @@
|
||||
#ifndef __XML_H__
|
||||
#define __XML_H__
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "imports/avs.h"
|
||||
|
||||
struct property_psmap {
|
||||
uint8_t type;
|
||||
uint8_t has_default;
|
||||
uint16_t field_offset;
|
||||
uint32_t member_width;
|
||||
const char *path;
|
||||
uintptr_t default_value;
|
||||
} __attribute__((packed));
|
||||
|
||||
enum psmap_property_type {
|
||||
PSMAP_PROPERTY_TYPE_S8 = 0x02,
|
||||
PSMAP_PROPERTY_TYPE_U8 = 0x03,
|
||||
PSMAP_PROPERTY_TYPE_S16 = 0x04,
|
||||
PSMAP_PROPERTY_TYPE_U16 = 0x05,
|
||||
PSMAP_PROPERTY_TYPE_S32 = 0x06,
|
||||
PSMAP_PROPERTY_TYPE_U32 = 0x07,
|
||||
PSMAP_PROPERTY_TYPE_S64 = 0x08,
|
||||
PSMAP_PROPERTY_TYPE_U64 = 0x09,
|
||||
PSMAP_PROPERTY_TYPE_STR = 0x0A,
|
||||
PSMAP_PROPERTY_TYPE_FLOAT = 0x0D,
|
||||
PSMAP_PROPERTY_TYPE_ATTR = 0x2D,
|
||||
PSMAP_PROPERTY_TYPE_BOOL = 0x32,
|
||||
};
|
||||
|
||||
#ifndef __offsetof
|
||||
#define __offsetof(_s, _f) __builtin_offsetof(_s, _f)
|
||||
#endif
|
||||
|
||||
#ifndef __fieldwidth
|
||||
#define __fieldwidth(_s, _f) sizeof((((_s *)NULL)->_f))
|
||||
#endif
|
||||
|
||||
#define PSMAP_BEGIN(_name, _type) const _type struct property_psmap _name[] = {
|
||||
#define PSMAP_MEMBER_REQ(_type, _struct, _member, _path) \
|
||||
{_type, false, __offsetof(_struct, _member), __fieldwidth(_struct, _member), _path, 0},
|
||||
#define PSMAP_MEMBER_OPT(_type, _struct, _member, _path, _def) \
|
||||
{_type, true, __offsetof(_struct, _member), __fieldwidth(_struct, _member), \
|
||||
_path, (uintptr_t)_def},
|
||||
#define PSMAP_END \
|
||||
{ 0xff, false, 0, 0, "NULL", 0 } \
|
||||
} \
|
||||
;
|
||||
|
||||
int reader_callback(uint32_t context, void *bytes, size_t nbytes) {
|
||||
return fread(bytes, 1, nbytes, (FILE *)TlsGetValue(context));
|
||||
}
|
||||
|
||||
struct property *load_prop_file(const char *filename) {
|
||||
FILE *file = fopen(filename, "rb");
|
||||
DWORD tlsIndex = TlsAlloc();
|
||||
|
||||
TlsSetValue(tlsIndex, (void *)file);
|
||||
|
||||
if (!file) {
|
||||
printf("Could not open config file: %s\n", filename);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const size_t size = property_read_query_memsize(reader_callback, tlsIndex, NULL, NULL);
|
||||
rewind(file);
|
||||
|
||||
struct property_node *buffer =
|
||||
(struct property_node *)calloc(size + 0x10000, sizeof(unsigned char));
|
||||
struct property *config_data = property_create(0x17, buffer, size + 0x10000);
|
||||
|
||||
if (size > 0) {
|
||||
const int ret = property_insert_read(config_data, 0, reader_callback, tlsIndex);
|
||||
|
||||
if (ret) {
|
||||
fclose(file);
|
||||
} else {
|
||||
printf("Could not load %s\n", filename);
|
||||
exit(-6);
|
||||
}
|
||||
}
|
||||
|
||||
return config_data;
|
||||
}
|
||||
|
||||
void _load_config(const char *filename, void *dest, const struct property_psmap *psmap) {
|
||||
struct property *config_xml = load_prop_file(filename);
|
||||
|
||||
if (!config_xml) {
|
||||
printf("Couldn't load xml file: %s\n", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(property_psmap_import(config_xml, nullptr, dest, psmap))) {
|
||||
printf("Couldn't parse psmap\n");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user