GraphicsCaptureHook.h change #define OLDHOOKS : 0 for new hooking methods, 1 for original hooking methods

master
Sean Stanek 2014-03-31 00:36:33 -05:00
parent c677ecf263
commit f4b30120e5
39 changed files with 5650 additions and 3 deletions

View File

@ -915,11 +915,14 @@ ULONG STDMETHODCALLTYPE D3D9Release(IDirect3DDevice9 *device)
return (*(RELEASEPROC)oldD3D9Release)(device);
}
typedef HRESULT(STDMETHODCALLTYPE *D3D9EndScenePROC)(IDirect3DDevice9 *device);
HRESULT STDMETHODCALLTYPE D3D9EndScene(IDirect3DDevice9 *device)
{
EnterCriticalSection(&d3d9EndMutex);
#if OLDHOOKS
d3d9EndScene.Unhook();
#endif
RUNEVERYRESET logOutput << CurrentTimeString() << "D3D9EndScene called" << endl;
@ -942,8 +945,12 @@ HRESULT STDMETHODCALLTYPE D3D9EndScene(IDirect3DDevice9 *device)
}
}
#if OLDHOOKS
HRESULT hRes = device->EndScene();
d3d9EndScene.Rehook();
#else
HRESULT hRes = ((D3D9EndScenePROC)d3d9EndScene.origFunc)(device);
#endif
LeaveCriticalSection(&d3d9EndMutex);
@ -952,7 +959,9 @@ HRESULT STDMETHODCALLTYPE D3D9EndScene(IDirect3DDevice9 *device)
HRESULT STDMETHODCALLTYPE D3D9Present(IDirect3DDevice9 *device, CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion)
{
#if OLDHOOKS
d3d9Present.Unhook();
#endif
RUNEVERYRESET logOutput << CurrentTimeString() << "D3D9Present called" << endl;
@ -961,17 +970,25 @@ HRESULT STDMETHODCALLTYPE D3D9Present(IDirect3DDevice9 *device, CONST RECT* pSou
presentRecurse++;
#if OLDHOOKS
HRESULT hRes = device->Present(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);
#else
HRESULT hRes = ((PRESENTPROC)d3d9Present.origFunc)(device, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);
#endif
presentRecurse--;
#if OLDHOOKS
d3d9Present.Rehook();
#endif
return hRes;
}
HRESULT STDMETHODCALLTYPE D3D9PresentEx(IDirect3DDevice9Ex *device, CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion, DWORD dwFlags)
{
#if OLDHOOKS
d3d9PresentEx.Unhook();
#endif
RUNEVERYRESET logOutput << CurrentTimeString() << "D3D9PresentEx called" << endl;
@ -980,17 +997,25 @@ HRESULT STDMETHODCALLTYPE D3D9PresentEx(IDirect3DDevice9Ex *device, CONST RECT*
presentRecurse++;
#if OLDHOOKS
HRESULT hRes = device->PresentEx(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags);
#else
HRESULT hRes = ((PRESENTEXPROC)d3d9PresentEx.origFunc)(device, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags);
#endif
presentRecurse--;
#if OLDHOOKS
d3d9PresentEx.Rehook();
#endif
return hRes;
}
HRESULT STDMETHODCALLTYPE D3D9SwapPresent(IDirect3DSwapChain9 *swap, CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion, DWORD dwFlags)
{
#if OLDHOOKS
d3d9SwapPresent.Unhook();
#endif
RUNEVERYRESET logOutput << CurrentTimeString() << "D3D9SwapPresent called" << endl;
@ -999,23 +1024,37 @@ HRESULT STDMETHODCALLTYPE D3D9SwapPresent(IDirect3DSwapChain9 *swap, CONST RECT*
presentRecurse++;
#if OLDHOOKS
HRESULT hRes = swap->Present(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags);
#else
HRESULT hRes = ((SWAPPRESENTPROC)d3d9SwapPresent.origFunc)(swap, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags);
#endif
presentRecurse--;
#if OLDHOOKS
d3d9SwapPresent.Rehook();
#endif
return hRes;
}
typedef HRESULT(STDMETHODCALLTYPE *D3D9ResetPROC)(IDirect3DDevice9 *device, D3DPRESENT_PARAMETERS *params);
HRESULT STDMETHODCALLTYPE D3D9Reset(IDirect3DDevice9 *device, D3DPRESENT_PARAMETERS *params)
{
#if OLDHOOKS
d3d9Reset.Unhook();
#endif
RUNEVERYRESET logOutput << CurrentTimeString() << "D3D9Reset called" << endl;
ClearD3D9Data();
#if OLDHOOKS
HRESULT hRes = device->Reset(params);
#else
HRESULT hRes = ((D3D9ResetPROC)d3d9Reset.origFunc)(device, params);
#endif
if(lpCurrentDevice == NULL && !bTargetAcquired)
{
@ -1026,21 +1065,31 @@ HRESULT STDMETHODCALLTYPE D3D9Reset(IDirect3DDevice9 *device, D3DPRESENT_PARAMET
if(lpCurrentDevice == device)
SetupD3D9(device);
#if OLDHOOKS
d3d9Reset.Rehook();
#endif
return hRes;
}
typedef HRESULT(STDMETHODCALLTYPE *D3D9ResetExPROC)(IDirect3DDevice9Ex *device, D3DPRESENT_PARAMETERS *params, D3DDISPLAYMODEEX *fullscreenData);
HRESULT STDMETHODCALLTYPE D3D9ResetEx(IDirect3DDevice9Ex *device, D3DPRESENT_PARAMETERS *params, D3DDISPLAYMODEEX *fullscreenData)
{
#if OLDHOOKS
d3d9ResetEx.Unhook();
d3d9Reset.Unhook();
#endif
RUNEVERYRESET logOutput << CurrentTimeString() << "D3D9ResetEx called" << endl;
ClearD3D9Data();
#if OLDHOOKS
HRESULT hRes = device->ResetEx(params, fullscreenData);
#else
HRESULT hRes = ((D3D9ResetExPROC)d3d9ResetEx.origFunc)(device, params, fullscreenData);
#endif
if(lpCurrentDevice == NULL && !bTargetAcquired)
{
@ -1052,8 +1101,10 @@ HRESULT STDMETHODCALLTYPE D3D9ResetEx(IDirect3DDevice9Ex *device, D3DPRESENT_PAR
if(lpCurrentDevice == device)
SetupD3D9(device);
#if OLDHOOKS
d3d9Reset.Rehook();
d3d9ResetEx.Rehook();
#endif
return hRes;
}
@ -1209,7 +1260,9 @@ bool InitD3D9Capture()
void CheckD3D9Capture()
{
EnterCriticalSection(&d3d9EndMutex);
#if OLDHOOKS
d3d9EndScene.Rehook(true);
#endif
LeaveCriticalSection(&d3d9EndMutex);
}

View File

@ -100,6 +100,8 @@ void SetupDXGIStuff(IDXGISwapChain *swap)
bTargetAcquired = true;
}
typedef HRESULT(STDMETHODCALLTYPE *DXGISwapResizeBuffersHookPROC)(IDXGISwapChain *swap, UINT bufferCount, UINT width, UINT height, DXGI_FORMAT giFormat, UINT flags);
HRESULT STDMETHODCALLTYPE DXGISwapResizeBuffersHook(IDXGISwapChain *swap, UINT bufferCount, UINT width, UINT height, DXGI_FORMAT giFormat, UINT flags)
{
if(clearProc)
@ -111,13 +113,19 @@ HRESULT STDMETHODCALLTYPE DXGISwapResizeBuffersHook(IDXGISwapChain *swap, UINT b
lpCurrentDevice = NULL;
bTargetAcquired = false;
#if OLDHOOKS
giswapResizeBuffers.Unhook();
HRESULT hRes = swap->ResizeBuffers(bufferCount, width, height, giFormat, flags);
giswapResizeBuffers.Rehook();
#else
HRESULT hRes = ((DXGISwapResizeBuffersHookPROC)giswapResizeBuffers.origFunc)(swap, bufferCount, width, height, giFormat, flags);
#endif
return hRes;
}
typedef HRESULT(STDMETHODCALLTYPE *DXGISwapPresentHookPROC)(IDXGISwapChain *swap, UINT syncInterval, UINT flags);
HRESULT STDMETHODCALLTYPE DXGISwapPresentHook(IDXGISwapChain *swap, UINT syncInterval, UINT flags)
{
if(lpCurrentSwap == NULL && !bTargetAcquired)
@ -126,9 +134,13 @@ HRESULT STDMETHODCALLTYPE DXGISwapPresentHook(IDXGISwapChain *swap, UINT syncInt
if(lpCurrentSwap == swap && captureProc)
(*captureProc)(swap);
#if OLDHOOKS
giswapPresent.Unhook();
HRESULT hRes = swap->Present(syncInterval, flags);
giswapPresent.Rehook();
#else
HRESULT hRes = ((DXGISwapPresentHookPROC)giswapPresent.origFunc)(swap, syncInterval, flags);
#endif
return hRes;
}

View File

@ -38,6 +38,11 @@
#include <fstream>
using namespace std;
#define OLDHOOKS 0
#if (!OLDHOOKS)
#include "../../minhook/include/minhook.h"
#endif
//arghh I hate defines like this
#define RUNONCE static bool bRunOnce = false; if(!bRunOnce && (bRunOnce = true))
@ -63,7 +68,15 @@ class HookData
bool b64bitJump;
public:
#if OLDHOOKS
inline HookData() : bHooked(false), func(NULL), hookFunc(NULL), b64bitJump(false) {}
#else
inline HookData() : bHooked(false), func(NULL), hookFunc(NULL), b64bitJump(false), origFunc(NULL)
{
MH_Initialize();
}
FARPROC origFunc;
#endif
inline bool Hook(FARPROC funcIn, FARPROC hookFuncIn)
{
@ -104,6 +117,8 @@ public:
UPARAM targetAddr = UPARAM(hookFunc);
UPARAM offset = targetAddr - (startAddr+5);
#if OLDHOOKS
DWORD oldProtect;
#ifdef _WIN64
@ -129,6 +144,12 @@ public:
*(DWORD*)(addrData+1) = DWORD(offset);
//VirtualProtect((LPVOID)func, 5, oldProtect, &oldProtect);
}
#else
// redirect function at startAddr to targetAddr
MH_CreateHook(func, hookFunc, (void**)&origFunc);
MH_EnableHook(func);
#endif
bHooked = true;
}
@ -138,11 +159,16 @@ public:
if(!bHooked || !func)
return;
#if OLDHOOKS
UINT count = b64bitJump ? 14 : 5;
DWORD oldProtect;
VirtualProtect((LPVOID)func, count, PAGE_EXECUTE_READWRITE, &oldProtect);
memcpy((void*)func, data, count);
//VirtualProtect((LPVOID)func, count, oldProtect, &oldProtect);
#else
MH_DisableHook(func);
MH_RemoveHook(func);
#endif
bHooked = false;
}

View File

@ -121,13 +121,14 @@
<PrecompiledHeaderFile>GraphicsCaptureHook.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<AdditionalDependencies>psapi.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>psapi.lib;dxguid.lib;libminhook.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>..\..\rundir\pdb32\$(TargetName).pdb</ProgramDatabaseFile>
<StripPrivateSymbols>
</StripPrivateSymbols>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalLibraryDirectories>../../minhook/build/$(Configuration)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>copy $(OutDir)$(ProjectName).dll ..\..\rundir\plugins\GraphicsCapture</Command>
@ -183,7 +184,7 @@
<AdditionalOptions>/d2Zi+ %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<AdditionalDependencies>psapi.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>psapi.lib;dxguid.lib;libminhook.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>..\..\rundir\pdb32\$(TargetName).pdb</ProgramDatabaseFile>
<StripPrivateSymbols>
@ -192,6 +193,7 @@
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalLibraryDirectories>../../minhook/build/$(Configuration)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>copy $(OutDir)$(ProjectName).dll ..\..\rundir\plugins\GraphicsCapture</Command>
@ -254,6 +256,11 @@
<ItemGroup>
<ResourceCompile Include="GraphicsCaptureHook.rc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\minhook\build\libMinHook.vcxproj">
<Project>{65021938-d251-46fa-bc3d-85c385d4c06d}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@ -1039,9 +1039,13 @@ static BOOL WINAPI SwapBuffersHook(HDC hDC)
HandleGLSceneUpdate(hDC);
#if OLDHOOKS
glHookSwapBuffers.Unhook();
BOOL bResult = SwapBuffers(hDC);
glHookSwapBuffers.Rehook();
#else
BOOL bResult = ((WGLSWAPBUFFERSPROC)glHookSwapBuffers.origFunc)(hDC);
#endif
//LeaveCriticalSection(&glMutex);
@ -1056,9 +1060,13 @@ static BOOL WINAPI wglSwapLayerBuffersHook(HDC hDC, UINT fuPlanes)
HandleGLSceneUpdate(hDC);
#if OLDHOOKS
glHookSwapLayerBuffers.Unhook();
BOOL bResult = jimglSwapLayerBuffers(hDC, fuPlanes);
glHookSwapLayerBuffers.Rehook();
#else
BOOL bResult = ((WGLSWAPLAYERBUFFERSPROC)glHookSwapLayerBuffers.origFunc)(hDC, fuPlanes);
#endif
//LeaveCriticalSection(&glMutex);
@ -1073,9 +1081,13 @@ static BOOL WINAPI wglSwapBuffersHook(HDC hDC)
HandleGLSceneUpdate(hDC);
#if OLDHOOKS
glHookwglSwapBuffers.Unhook();
BOOL bResult = jimglSwapBuffers(hDC);
glHookwglSwapBuffers.Rehook();
#else
BOOL bResult = ((WGLSWAPBUFFERSPROC)glHookwglSwapBuffers.origFunc)(hDC);
#endif
//LeaveCriticalSection(&glMutex);
@ -1098,9 +1110,13 @@ static BOOL WINAPI wglDeleteContextHook(HGLRC hRC)
jimglMakeCurrent(hLastHDC, hLastHGLRC);
}
#if OLDHOOKS
glHookDeleteContext.Unhook();
BOOL bResult = jimglDeleteContext(hRC);
glHookDeleteContext.Rehook();
#else
BOOL bResult = ((WGLDELETECONTEXTPROC)glHookDeleteContext.origFunc)(hRC);
#endif
//LeaveCriticalSection(&glMutex);

View File

@ -5,6 +5,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OBS", "OBS.vcxproj", "{221C
ProjectSection(ProjectDependencies) = postProject
{9E7B3527-11AA-46BA-A82F-C58761F9B56F} = {9E7B3527-11AA-46BA-A82F-C58761F9B56F}
{11A35235-DD48-41E2-8F40-825C78024BC0} = {11A35235-DD48-41E2-8F40-825C78024BC0}
{65021938-D251-46FA-BC3D-85C385D4C06D} = {65021938-D251-46FA-BC3D-85C385D4C06D}
{9CC48C6E-92EB-4814-AD37-97AB3622AB65} = {9CC48C6E-92EB-4814-AD37-97AB3622AB65}
{22BF0EE3-CDCD-4925-A5F6-0A94CB5D4DB1} = {22BF0EE3-CDCD-4925-A5F6-0A94CB5D4DB1}
EndProjectSection
@ -56,6 +57,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ObsNvenc", "ObsNvenc\ObsNve
{11A35235-DD48-41E2-8F40-825C78024BC0} = {11A35235-DD48-41E2-8F40-825C78024BC0}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libMinHook", "minhook\build\libMinHook.vcxproj", "{65021938-D251-46FA-BC3D-85C385D4C06D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -176,6 +179,14 @@ Global
{0F2A21A8-8A04-4F51-BFEC-5C5331C218C4}.Release|Win32.Build.0 = Release|Win32
{0F2A21A8-8A04-4F51-BFEC-5C5331C218C4}.Release|x64.ActiveCfg = Release|x64
{0F2A21A8-8A04-4F51-BFEC-5C5331C218C4}.Release|x64.Build.0 = Release|x64
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Win32.ActiveCfg = Debug|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Win32.Build.0 = Debug|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|x64.ActiveCfg = Debug|x64
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|x64.Build.0 = Debug|x64
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.ActiveCfg = Release|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.Build.0 = Release|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.ActiveCfg = Release|x64
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

32
minhook/.gitignore vendored Normal file
View File

@ -0,0 +1,32 @@
#OS junk files
[Tt]humbs.db
*.DS_Store
#Visual Studio files
*.[Oo]bj
*.user
*.aps
*.pch
*.vspscc
*.vssscc
*_i.c
*_p.c
*.ncb
*.suo
*.tlb
*.tlh
*.bak
*.[Cc]ache
*.ilk
*.log
*.sbr
*.sdf
*.opensdf
*.unsuccessfulbuild
ipch/
obj/
[Ll]ib
[Bb]in
[Dd]ebug*/
[Rr]elease*/
Ankh.NoLoad

79
minhook/COPYING.txt Normal file
View File

@ -0,0 +1,79 @@
/*
* MinHook - The Minimalistic API Hooking Library for x64/x86
* Copyright (c) 2009 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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.
*/
================================================================================
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.
*
*/
/*
* Hacker Disassembler Engine 64 C
* Copyright (c) 2008-2009, Vyacheslav Patkov.
* All rights reserved.
*
*/
================================================================================
Portions of this software are Copyright (c) 2005-2007 Paul Hsieh.
================================================================================
/* A portable stdint.h
****************************************************************************
* BSD License:
****************************************************************************
*
* Copyright (c) 2005-2007 Paul Hsieh
* 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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.

14
minhook/README.md Normal file
View File

@ -0,0 +1,14 @@
# MinHook
A Windows API hooking library originally written by Tsuda Kageyu.
http://www.codeproject.com/KB/winsdk/LibMinHook.aspx
## Main differences from original v1.1
* Removed boost dependency ([jarredholman](https://github.com/jarredholman/minhook)).
* Fixed a small bug in the GetRelativeBranchDestination function ([pillbug99](http://www.codeproject.com/Messages/4058892/Small-Bug-Found.aspx)).
* Added the `MH_RemoveHook` function, which removes a hook created with the `MH_CreateHook` function.
* Added the following functions to enable or disable multiple hooks in one go: `MH_QueueEnableHook`, `MH_QueueDisableHook`, `MH_ApplyQueued`. This is the preferred way of handling multiple hooks as every call to `MH_EnableHook` or `MH_DisableHook` suspends and resumes all threads.
* Made the functions `MH_EnableHook` and `MH_DisableHook` enable/disable all created hooks when the `MH_ALL_HOOKS` parameter is passed. This, too, is an efficient way of handling multiple hooks.
* If the target function is too small to be patched with a jump, MinHook tries to place the jump above the function. If that fails as well, the `MH_CreateHook` function returns `MH_ERROR_UNSUPPORTED_FUNCTION`. This fixes an issue of hooking the LoadLibraryExW function on Windows 7 x64 ([reported by Obble](http://www.codeproject.com/Messages/4578613/Re-Bug-LoadLibraryExW-hook-fails-on-windows-2008-r.aspx)).

View File

@ -0,0 +1,384 @@
<?xml version="1.0" encoding="shift_jis"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="MinHook"
ProjectGUID="{CA4EE302-D012-4826-86D6-80D23641AB4E}"
RootNamespace="MinHook"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)\..\bin"
IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\$(ProjectName).x86.dll"
LinkIncremental="2"
ModuleDefinitionFile="..\dll_resources\MinHook.def"
GenerateDebugInformation="true"
SubSystem="2"
BaseAddress="0x68000000"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)\..\bin"
IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="2"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\$(ProjectName).x86.dll"
LinkIncremental="1"
ModuleDefinitionFile="..\dll_resources\MinHook.def"
GenerateDebugInformation="false"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
BaseAddress="0x68000000"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)\..\bin"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\$(ProjectName).x64.dll"
LinkIncremental="2"
ModuleDefinitionFile="..\dll_resources\MinHook.def"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)\..\bin"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="2"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\$(ProjectName).x64.dll"
LinkIncremental="1"
ModuleDefinitionFile="..\dll_resources\MinHook.def"
GenerateDebugInformation="false"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
BaseAddress="0x68000000"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\dll_resources\dllmain.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
CompileAsManaged="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
CompileAsManaged="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
CompileAsManaged="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
CompileAsManaged="0"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\dll_resources\MinHook.def"
>
</File>
<File
RelativePath="..\dll_resources\MinHook.rc"
>
</File>
<File
RelativePath="..\dll_resources\resource.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,216 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{CA4EE302-D012-4826-86D6-80D23641AB4E}</ProjectGuid>
<RootNamespace>MinHook</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)\..\bin\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)\..\bin\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)\..\bin\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)\..\bin\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\$(ProjectName)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\$(ProjectName)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName).x86</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName).x86</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectName).x64</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectName).x64</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<ModuleDefinitionFile>..\dll_resources\MinHook.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<BaseAddress>0x68000000</BaseAddress>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<ModuleDefinitionFile>..\dll_resources\MinHook.def</ModuleDefinitionFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<BaseAddress>0x68000000</BaseAddress>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<ModuleDefinitionFile>..\dll_resources\MinHook.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MINHOOK_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<ModuleDefinitionFile>..\dll_resources\MinHook.def</ModuleDefinitionFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<BaseAddress>0x68000000</BaseAddress>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\dll_resources\dllmain.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\dll_resources\MinHook.def" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\dll_resources\MinHook.rc" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\dll_resources\resource.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libMinHook.vcxproj">
<Project>{65021938-d251-46fa-bc3d-85c385d4c06d}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,36 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libMinHook", "libMinHook.vcxproj", "{65021938-D251-46FA-BC3D-85C385D4C06D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MinHook", "MinHook.vcxproj", "{CA4EE302-D012-4826-86D6-80D23641AB4E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Win32.ActiveCfg = Debug|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Win32.Build.0 = Debug|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|x64.ActiveCfg = Debug|x64
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|x64.Build.0 = Debug|x64
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.ActiveCfg = Release|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.Build.0 = Release|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.ActiveCfg = Release|x64
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.Build.0 = Release|x64
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|Win32.ActiveCfg = Debug|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|Win32.Build.0 = Debug|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|x64.ActiveCfg = Debug|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|x64.Build.0 = Debug|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|Win32.ActiveCfg = Release|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|Win32.Build.0 = Release|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|x64.ActiveCfg = Release|x64
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,36 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libMinHook", "libMinHook.vcxproj", "{65021938-D251-46FA-BC3D-85C385D4C06D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MinHook", "MinHook.vcxproj", "{CA4EE302-D012-4826-86D6-80D23641AB4E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Win32.ActiveCfg = Debug|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Win32.Build.0 = Debug|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|x64.ActiveCfg = Debug|x64
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|x64.Build.0 = Debug|x64
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.ActiveCfg = Release|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.Build.0 = Release|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.ActiveCfg = Release|x64
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.Build.0 = Release|x64
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|Win32.ActiveCfg = Debug|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|Win32.Build.0 = Debug|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|x64.ActiveCfg = Debug|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|x64.Build.0 = Debug|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|Win32.ActiveCfg = Release|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|Win32.Build.0 = Release|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|x64.ActiveCfg = Release|x64
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,38 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libMinHook", "libMinHook.vcxproj", "{65021938-D251-46FA-BC3D-85C385D4C06D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MinHook", "MinHook.vcxproj", "{CA4EE302-D012-4826-86D6-80D23641AB4E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Win32.ActiveCfg = Debug|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Win32.Build.0 = Debug|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|x64.ActiveCfg = Debug|x64
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|x64.Build.0 = Debug|x64
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.ActiveCfg = Release|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.Build.0 = Release|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.ActiveCfg = Release|x64
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.Build.0 = Release|x64
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|Win32.ActiveCfg = Debug|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|Win32.Build.0 = Debug|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|x64.ActiveCfg = Debug|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|x64.Build.0 = Debug|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|Win32.ActiveCfg = Release|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|Win32.Build.0 = Release|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|x64.ActiveCfg = Release|x64
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,39 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libMinHook", "libMinHook.vcproj", "{65021938-D251-46FA-BC3D-85C385D4C06D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MinHook", "MinHook.vcproj", "{CA4EE302-D012-4826-86D6-80D23641AB4E}"
ProjectSection(ProjectDependencies) = postProject
{65021938-D251-46FA-BC3D-85C385D4C06D} = {65021938-D251-46FA-BC3D-85C385D4C06D}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Win32.ActiveCfg = Debug|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|Win32.Build.0 = Debug|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|x64.ActiveCfg = Debug|x64
{65021938-D251-46FA-BC3D-85C385D4C06D}.Debug|x64.Build.0 = Debug|x64
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.ActiveCfg = Release|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.Build.0 = Release|Win32
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.ActiveCfg = Release|x64
{65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.Build.0 = Release|x64
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|Win32.ActiveCfg = Debug|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|Win32.Build.0 = Debug|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|x64.ActiveCfg = Debug|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Debug|x64.Build.0 = Debug|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|Win32.ActiveCfg = Release|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|Win32.Build.0 = Release|Win32
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|x64.ActiveCfg = Release|x64
{CA4EE302-D012-4826-86D6-80D23641AB4E}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,377 @@
<?xml version="1.0" encoding="shift_jis"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="libMinHook"
ProjectGUID="{65021938-D251-46FA-BC3D-85C385D4C06D}"
RootNamespace="libMinHook"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)\..\lib"
IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
ConfigurationType="4"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\include&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)\$(ProjectName).x86.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)\..\lib"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="4"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\include&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)\$(ProjectName).x64.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)\..\lib"
IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
ConfigurationType="4"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\include&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)\$(ProjectName).x86.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)\..\lib"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
ConfigurationType="4"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\include&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)\$(ProjectName).x64.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="src"
>
<Filter
Name="HDE32"
>
<File
RelativePath="..\src\HDE32\hde32.c"
>
</File>
<File
RelativePath="..\src\HDE32\hde32.h"
>
</File>
<File
RelativePath="..\src\HDE32\table32.h"
>
</File>
</Filter>
<Filter
Name="HDE64"
>
<File
RelativePath="..\src\HDE64\src\hde64.c"
>
</File>
<File
RelativePath="..\src\HDE64\include\hde64.h"
>
</File>
<File
RelativePath="..\src\HDE64\src\table64.h"
>
</File>
</Filter>
<Filter
Name="Source Files"
>
<File
RelativePath="..\src\buffer.cpp"
>
</File>
<File
RelativePath="..\src\export.cpp"
>
</File>
<File
RelativePath="..\src\hook.cpp"
>
</File>
<File
RelativePath="..\src\thread.cpp"
>
</File>
<File
RelativePath="..\src\trampoline.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
>
<File
RelativePath="..\src\buffer.h"
>
</File>
<File
RelativePath="..\src\hook.h"
>
</File>
<File
RelativePath="..\src\pstdint.h"
>
</File>
<File
RelativePath="..\src\thread.h"
>
</File>
<File
RelativePath="..\src\trampoline.h"
>
</File>
</Filter>
</Filter>
<File
RelativePath="..\COPYING.txt"
>
</File>
<File
RelativePath="..\include\MinHook.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,187 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{65021938-D251-46FA-BC3D-85C385D4C06D}</ProjectGuid>
<RootNamespace>libMinHook</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)\..\lib\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)\..\lib\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName)</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectName).x64</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectName).x64</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(ProjectDir)\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
</ClCompile>
<Lib />
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(ProjectDir)\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Lib />
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>$(ProjectDir)\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
</ClCompile>
<Lib />
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>$(ProjectDir)\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Lib />
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\src\HDE32\hde32.c" />
<ClCompile Include="..\src\HDE64\src\hde64.c" />
<ClCompile Include="..\src\buffer.cpp" />
<ClCompile Include="..\src\export.cpp" />
<ClCompile Include="..\src\hook.cpp" />
<ClCompile Include="..\src\thread.cpp" />
<ClCompile Include="..\src\trampoline.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\HDE32\hde32.h" />
<ClInclude Include="..\src\HDE32\table32.h" />
<ClInclude Include="..\src\HDE64\include\hde64.h" />
<ClInclude Include="..\src\HDE64\src\table64.h" />
<ClInclude Include="..\src\buffer.h" />
<ClInclude Include="..\src\hook.h" />
<ClInclude Include="..\src\pstdint.h" />
<ClInclude Include="..\src\thread.h" />
<ClInclude Include="..\src\trampoline.h" />
<ClInclude Include="..\include\MinHook.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\COPYING.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="src">
<UniqueIdentifier>{d2fc03a6-683a-49e0-87fa-844d1529a19c}</UniqueIdentifier>
</Filter>
<Filter Include="src\HDE32">
<UniqueIdentifier>{76b54476-8b6d-4556-84dc-311115cff274}</UniqueIdentifier>
</Filter>
<Filter Include="src\HDE64">
<UniqueIdentifier>{b2dbe4c4-a42e-40cd-b744-92327b9acf3e}</UniqueIdentifier>
</Filter>
<Filter Include="src\Source Files">
<UniqueIdentifier>{df59be5b-00d3-495b-8a79-ea0c6df20e74}</UniqueIdentifier>
</Filter>
<Filter Include="src\Header Files">
<UniqueIdentifier>{c5cf3151-e815-430f-9743-6ec94394b47d}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\HDE32\hde32.c">
<Filter>src\HDE32</Filter>
</ClCompile>
<ClCompile Include="..\src\HDE64\src\hde64.c">
<Filter>src\HDE64</Filter>
</ClCompile>
<ClCompile Include="..\src\buffer.cpp">
<Filter>src\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\export.cpp">
<Filter>src\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\hook.cpp">
<Filter>src\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\thread.cpp">
<Filter>src\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\trampoline.cpp">
<Filter>src\Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\HDE32\hde32.h">
<Filter>src\HDE32</Filter>
</ClInclude>
<ClInclude Include="..\src\HDE32\table32.h">
<Filter>src\HDE32</Filter>
</ClInclude>
<ClInclude Include="..\src\HDE64\include\hde64.h">
<Filter>src\HDE64</Filter>
</ClInclude>
<ClInclude Include="..\src\HDE64\src\table64.h">
<Filter>src\HDE64</Filter>
</ClInclude>
<ClInclude Include="..\src\buffer.h">
<Filter>src\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\hook.h">
<Filter>src\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\pstdint.h">
<Filter>src\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\thread.h">
<Filter>src\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\trampoline.h">
<Filter>src\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\MinHook.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\COPYING.txt" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,11 @@
EXPORTS
MH_Initialize
MH_Uninitialize
MH_CreateHook
MH_RemoveHook
MH_EnableHook
MH_DisableHook
MH_QueueEnableHook
MH_QueueDisableHook
MH_ApplyQueued

View File

@ -0,0 +1,102 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// “ú–{Œê resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
#ifdef _WIN32
LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
#pragma code_page(932)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,2,1,0
PRODUCTVERSION 1,2,1,0
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "000004b0"
BEGIN
VALUE "CompanyName", "Tsuda Kageyu"
VALUE "FileDescription", "MinHook - The Minimalistic API Hook Library for x64/x86"
VALUE "FileVersion", "1, 2, 1, 0"
VALUE "InternalName", "MinHookD"
VALUE "LegalCopyright", "Copyright (c) 2009 Tsuda Kageyu. All rights reserved."
VALUE "LegalTrademarks", "Tsuda Kageyu"
VALUE "ProductName", "MinHook DLL"
VALUE "ProductVersion", "1, 2, 1, 0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0, 1200
END
END
#endif // “ú–{Œê resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -0,0 +1,7 @@
#include <Windows.h>
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
return TRUE;
}

View File

@ -0,0 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by MinHook.rc
// 新しいオブジェクトの次の既定値
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

129
minhook/include/MinHook.h Normal file
View File

@ -0,0 +1,129 @@
/*
* MinHook - Minimalistic API Hook Library
* Copyright (C) 2009 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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>
// 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
}
MH_STATUS;
// Can be passed as a parameter to MH_EnableHook, MH_DisableHook, MH_QueueEnableHook or MH_QueueDisableHook.
#define MH_ALL_HOOKS NULL
#if defined __cplusplus
extern "C" {
#endif
// Initialize the MinHook library.
MH_STATUS WINAPI MH_Initialize();
// Uninitialize the MinHook library.
MH_STATUS WINAPI MH_Uninitialize();
// Creates the 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.
MH_STATUS WINAPI MH_CreateHook(void* pTarget, void* const pDetour, void** ppOriginal);
// Removes the already created hook.
// Parameters:
// pTarget [in] A pointer to the target function.
MH_STATUS WINAPI MH_RemoveHook(void* pTarget);
// Enables the 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(void* pTarget);
// Disables the 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(void* pTarget);
// Queues to enable the 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(void* pTarget);
// Queues to disable the 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(void* pTarget);
// Applies all queued changes in one go.
MH_STATUS WINAPI MH_ApplyQueued();
#if defined __cplusplus
}
#endif

320
minhook/src/HDE32/hde32.c Normal file
View File

@ -0,0 +1,320 @@
/*
* Hacker Disassembler Engine 32 C
* Copyright (c) 2008-2009, Vyacheslav Patkov.
* All rights reserved.
*
*/
/* #include <stdint.h> */
#include <string.h>
#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;
memset(hs,0,sizeof(hde32s));
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;
}

106
minhook/src/HDE32/hde32.h Normal file
View File

@ -0,0 +1,106 @@
/*
* 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 <stdint.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_ */

View 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
};

View File

@ -0,0 +1,113 @@
/*
* 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 <stdint.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_ */

View File

@ -0,0 +1,331 @@
/*
* Hacker Disassembler Engine 64 C
* Copyright (c) 2008-2009, Vyacheslav Patkov.
* All rights reserved.
*
*/
/* #include <stdint.h> */
#include <string.h>
#include "../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;
memset(hs,0,sizeof(hde64s));
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;
}

View 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
};

318
minhook/src/buffer.cpp Normal file
View File

@ -0,0 +1,318 @@
/*
* MinHook - Minimalistic API Hook Library
* Copyright (C) 2009 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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.
*/
#include <cassert>
#include <vector>
#include <algorithm>
#include <Windows.h>
#include "buffer.h"
namespace MinHook { namespace
{
struct MEMORY_BLOCK
{
void* pAddress;
DWORD protect;
size_t uncommittedSize;
size_t uncommittedCount;
size_t fixedSize;
size_t fixedCount;
};
template <typename T>
bool operator <(const MEMORY_BLOCK& lhs, const T& rhs);
template <typename T>
bool operator <(const T& lhs, const MEMORY_BLOCK& rhs);
bool operator <(const MEMORY_BLOCK& lhs, const MEMORY_BLOCK& rhs);
void* AllocateBuffer(void* const pOrigin, DWORD protect, size_t size);
MEMORY_BLOCK* GetMemoryBlock(void* const pOrigin, DWORD protect, size_t capacity);
const size_t BlockSize = 0x10000;
#if defined _M_X64
intptr_t gMinAddress;
intptr_t gMaxAddress;
#endif
std::vector<MEMORY_BLOCK> gMemoryBlocks;
}}
namespace MinHook
{
void InitializeBuffer()
{
#if defined _M_X64
SYSTEM_INFO si;
GetSystemInfo(&si);
gMinAddress = reinterpret_cast<intptr_t>(si.lpMinimumApplicationAddress);
gMaxAddress = reinterpret_cast<intptr_t>(si.lpMaximumApplicationAddress);
#endif
}
void UninitializeBuffer()
{
for (size_t i = 0, count = gMemoryBlocks.size(); i < count; ++i)
{
MEMORY_BLOCK& block = gMemoryBlocks[i];
VirtualFree(block.pAddress, 0, MEM_RELEASE);
}
std::vector<MEMORY_BLOCK> v;
gMemoryBlocks.swap(v);
}
void* AllocateCodeBuffer(void* const pOrigin, size_t size)
{
assert(("AllocateBuffer", (size > 0)));
return AllocateBuffer(pOrigin, PAGE_EXECUTE_READ, size);
}
void* AllocateDataBuffer(void* const pOrigin, size_t size)
{
assert(("AllocateBuffer", (size > 0)));
return AllocateBuffer(pOrigin, PAGE_READONLY, size);
}
void FreeBuffer(void* const pBuffer)
{
for (size_t i = 0, count = gMemoryBlocks.size(); i < count; ++i)
{
MEMORY_BLOCK& block = gMemoryBlocks[i];
void* pBlockEnd = reinterpret_cast<char*>(block.pAddress) + block.fixedSize;
if (pBuffer >= block.pAddress && pBuffer < pBlockEnd)
{
assert(("FreeBuffer", (block.uncommittedSize == 0 && block.uncommittedCount == 0)));
block.fixedCount--;
if (block.fixedCount == 0)
{
VirtualFree(block.pAddress, 0, MEM_RELEASE);
gMemoryBlocks.erase(gMemoryBlocks.begin()+i);
}
return;
}
}
assert(("FreeBuffer", 0));
}
void RollbackBuffer()
{
for (size_t i = 0, count = gMemoryBlocks.size(); i < count; ++i)
{
MEMORY_BLOCK& block = gMemoryBlocks[i];
if (block.uncommittedSize == 0)
{
continue;
}
block.uncommittedSize = 0;
block.uncommittedCount = 0;
if (block.fixedCount == 0)
{
VirtualFree(block.pAddress, 0, MEM_RELEASE);
gMemoryBlocks.erase(gMemoryBlocks.begin()+i);
i--;
count--;
}
}
}
void CommitBuffer()
{
for (size_t i = 0, count = gMemoryBlocks.size(); i < count; ++i)
{
MEMORY_BLOCK& block = gMemoryBlocks[i];
if (block.uncommittedSize == 0)
{
continue;
}
void* pBuffer = reinterpret_cast<char*>(block.pAddress) + block.fixedSize;
size_t size = block.uncommittedSize;
DWORD op;
VirtualProtect(pBuffer, size, block.protect, &op);
block.fixedSize += size;
block.uncommittedSize = 0;
block.fixedCount += block.uncommittedCount;
block.uncommittedCount = 0;
}
}
}
namespace MinHook { namespace
{
void* AllocateBuffer(void* const pOrigin, DWORD protect, size_t size)
{
assert(("AllocateBuffer", (protect == PAGE_EXECUTE_READ || protect == PAGE_READONLY)));
assert(("AllocateBuffer", (size > 0)));
// アライメント境界に切り上げ
size = (size + TYPE_ALIGNMENT(void*) - 1) & ~(TYPE_ALIGNMENT(void*) - 1);
MEMORY_BLOCK* pBlock = GetMemoryBlock(pOrigin, protect, size);
if (pBlock == NULL)
{
return NULL;
}
void* pBuffer = reinterpret_cast<char*>(pBlock->pAddress) + pBlock->fixedSize + pBlock->uncommittedSize;
if (VirtualAlloc(pBuffer, size, MEM_COMMIT, pBlock->protect) == NULL)
{
return NULL;
}
DWORD oldProtect;
// PAGE_EXECUTE_READ -> PAGE_EXECUTE_READWRITE, PAGE_READONLY -> PAGE_READWRITE
if (!VirtualProtect(pBuffer, size, (pBlock->protect << 1), &oldProtect))
{
return NULL;
}
pBlock->uncommittedSize += size;
pBlock->uncommittedCount++;
return pBuffer;
}
MEMORY_BLOCK* GetMemoryBlock(void* const pOrigin, DWORD protect, size_t capacity)
{
assert(("GetMemoryBlock", (protect == PAGE_EXECUTE_READ || protect == PAGE_READONLY)));
assert(("GetMemoryBlock", (capacity > 0)));
typedef std::vector<MEMORY_BLOCK>::iterator mb_iter;
#if defined _M_X64
intptr_t minAddr = gMinAddress;
intptr_t maxAddr = gMaxAddress;
if (pOrigin != NULL)
{
// pOrigin ± 512MB の範囲
minAddr = std::max<intptr_t>(minAddr, reinterpret_cast<intptr_t>(pOrigin) - 0x20000000);
maxAddr = std::min<intptr_t>(maxAddr, reinterpret_cast<intptr_t>(pOrigin) + 0x20000000);
}
#endif
// すでに登録済みの領域の中から使用可能なものが見つかれば、それを返す
MEMORY_BLOCK* pBlock = NULL;
{
mb_iter ib = gMemoryBlocks.begin();
mb_iter ie = gMemoryBlocks.end();
#if defined _M_X64
if (pOrigin != NULL)
{
// 検索前にアドレス範囲で絞り込み
ib = std::lower_bound(ib, ie, minAddr);
ie = std::lower_bound(ib, ie, maxAddr);
}
#endif
for (mb_iter i = ib; i != ie; ++i)
{
if (i->protect == protect && i->fixedSize + i->uncommittedSize + capacity <= BlockSize)
{
return &(*i);
}
}
}
// 見つからなければ、新たなアドレス領域を確保
void* pAlloc = NULL;
#if defined _M_X64
if (pOrigin != NULL)
{
// 検索範囲の中心から外側へ空き領域を探していく
intptr_t min = minAddr / BlockSize;
intptr_t max = maxAddr / BlockSize;
int rel = 0;
MEMORY_BASIC_INFORMATION mi = { 0 };
for (int i = 0; i < (max - min + 1); ++i)
{
rel = -rel + (i & 1);
void* pQuery = reinterpret_cast<void*>(((min + max) / 2 + rel) * BlockSize);
VirtualQuery(pQuery, &mi, sizeof(mi));
if (mi.State == MEM_FREE)
{
pAlloc = VirtualAlloc(pQuery, BlockSize, MEM_RESERVE, protect);
if (pAlloc != NULL)
{
break;
}
}
}
}
else
#endif // X86モードでは、アドレスは問題にならない
{
pAlloc = VirtualAlloc(NULL, BlockSize, MEM_RESERVE, protect);
}
if (pAlloc != NULL)
{
MEMORY_BLOCK block = { 0 };
block.pAddress = pAlloc;
block.protect = protect;
#if defined _M_X64
mb_iter i = std::lower_bound(gMemoryBlocks.begin(), gMemoryBlocks.end(), pAlloc);
#elif defined _M_IX86
mb_iter i = gMemoryBlocks.end();
#endif
i = gMemoryBlocks.insert(i, block);
return &(*i);
}
return NULL;
}
template <typename T>
bool operator <(const MEMORY_BLOCK& lhs, const T& rhs)
{
return lhs.pAddress < reinterpret_cast<void*>(rhs);
}
template <typename T>
bool operator <(const T& lhs, const MEMORY_BLOCK& rhs)
{
return reinterpret_cast<void*>(lhs) < rhs.pAddress;
}
bool operator <(const MEMORY_BLOCK& lhs, const MEMORY_BLOCK& rhs)
{
return lhs.pAddress < rhs.pAddress;
}
}}

40
minhook/src/buffer.h Normal file
View File

@ -0,0 +1,40 @@
/*
* MinHook - Minimalistic API Hook Library
* Copyright (C) 2009 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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
namespace MinHook
{
void InitializeBuffer();
void UninitializeBuffer();
void* AllocateCodeBuffer(void* const pOrigin, size_t size);
void* AllocateDataBuffer(void* const pOrigin, size_t size);
void FreeBuffer(void* const pBuffer);
void RollbackBuffer();
void CommitBuffer();
}

78
minhook/src/export.cpp Normal file
View File

@ -0,0 +1,78 @@
/*
* MinHook - Minimalistic API Hook Library
* Copyright (C) 2009 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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.
*/
#include <Windows.h>
#include "MinHook.h"
#include "hook.h"
using namespace MinHook;
MH_STATUS WINAPI MH_Initialize()
{
return Initialize();
}
MH_STATUS WINAPI MH_Uninitialize()
{
return Uninitialize();
}
MH_STATUS WINAPI MH_CreateHook(void* pTarget, void* const pDetour, void** ppOriginal)
{
return CreateHook(pTarget, pDetour, ppOriginal);
}
MH_STATUS WINAPI MH_RemoveHook(void* pTarget)
{
return RemoveHook(pTarget);
}
MH_STATUS WINAPI MH_EnableHook(void* pTarget)
{
return EnableHook(pTarget);
}
MH_STATUS WINAPI MH_DisableHook(void* pTarget)
{
return DisableHook(pTarget);
}
MH_STATUS WINAPI MH_QueueEnableHook(void* pTarget)
{
return QueueEnableHook(pTarget);
}
MH_STATUS WINAPI MH_QueueDisableHook(void* pTarget)
{
return QueueDisableHook(pTarget);
}
MH_STATUS WINAPI MH_ApplyQueued()
{
return ApplyQueued();
}

730
minhook/src/hook.cpp Normal file
View File

@ -0,0 +1,730 @@
/*
* MinHook - Minimalistic API Hook Library
* Copyright (C) 2009 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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.
*/
#include <cassert>
#include <vector>
#include <algorithm>
#include <functional>
#include <Windows.h>
#include "pstdint.h"
#include "MinHook.h"
#include "hook.h"
#include "buffer.h"
#include "trampoline.h"
#include "thread.h"
namespace MinHook { namespace
{
struct HOOK_ENTRY
{
void* pTarget;
void* pDetour;
#if defined _M_X64
void* pTable;
void* pRelay;
#endif
void* pTrampoline;
void* pBackup;
bool patchAbove;
bool isEnabled;
bool queueEnable;
std::vector<uintptr_t> oldIPs;
std::vector<uintptr_t> newIPs;
};
// 命令書き込み用構造体
#pragma pack(push, 1)
struct JMP_REL_SHORT
{
uint8_t opcode;
uint8_t operand;
};
struct JMP_REL
{
uint8_t opcode;
uint32_t operand;
};
struct JMP_ABS
{
uint16_t opcode;
uint32_t operand;
};
#pragma pack(pop)
MH_STATUS EnableHookLL(HOOK_ENTRY *pHook);
MH_STATUS DisableHookLL(HOOK_ENTRY *pHook);
MH_STATUS EnableAllHooksLL();
MH_STATUS DisableAllHooksLL();
HOOK_ENTRY* FindHook(void* const pTarget);
bool IsExecutableAddress(void* pAddress);
void WriteRelativeJump(void* pFrom, void* const pTo);
void WriteAbsoluteJump(void* pFrom, void* const pTo, void* pTable);
template <typename T>
bool operator <(const HOOK_ENTRY& lhs, const T& rhs) ;
template <typename T>
bool operator <(const T& lhs, const HOOK_ENTRY& rhs) ;
bool operator <(const HOOK_ENTRY& lhs, const HOOK_ENTRY& rhs);
std::vector<HOOK_ENTRY> gHooks;
bool gIsInitialized = false;
}}
static MinHook::CriticalSection* gCS = NULL;
namespace MinHook
{
MH_STATUS Initialize()
{
if (!gCS) gCS = new CriticalSection();
CriticalSection::ScopedLock lock(*gCS);
if (gIsInitialized)
{
return MH_ERROR_ALREADY_INITIALIZED;
}
// 内部関数バッファの初期化
InitializeBuffer();
gIsInitialized = true;
return MH_OK;
}
MH_STATUS Uninitialize()
{
CriticalSection::ScopedLock lock(*gCS);
if (!gIsInitialized)
{
return MH_ERROR_NOT_INITIALIZED;
}
// すべてのフックを解除
MH_STATUS status = DisableAllHooksLL();
if (status != MH_OK)
{
return status;
}
std::vector<HOOK_ENTRY> v;
gHooks.swap(v);
// 内部関数バッファの開放
UninitializeBuffer();
gIsInitialized = false;
return MH_OK;
}
struct RollbackIfNotCommitted
{
bool* committed_;
RollbackIfNotCommitted(bool* committed)
: committed_(committed)
{
}
~RollbackIfNotCommitted()
{
if (!*committed_)
{
RollbackBuffer();
}
}
};
MH_STATUS CreateHook(void* pTarget, void* const pDetour, void** ppOriginal)
{
CriticalSection::ScopedLock lock(*gCS);
if (!gIsInitialized)
{
return MH_ERROR_NOT_INITIALIZED;
}
HOOK_ENTRY *pHook = FindHook(pTarget);
if (pHook != NULL)
{
return MH_ERROR_ALREADY_CREATED;
}
if (!IsExecutableAddress(pTarget) || !IsExecutableAddress(pDetour))
{
return MH_ERROR_NOT_EXECUTABLE;
}
{
bool committed = false;
RollbackIfNotCommitted scopedRollback(&committed);
// トランポリン関数を作成する
CREATE_TREMPOLINE_T ct = { 0 };
ct.pTarget = pTarget;
if (!CreateTrampolineFunction(ct))
{
return MH_ERROR_UNSUPPORTED_FUNCTION;
}
void* pJmpPtr = pTarget;
if (ct.patchAbove)
{
pJmpPtr = reinterpret_cast<char*>(pJmpPtr) - sizeof(JMP_REL);
}
void* pTrampoline = AllocateCodeBuffer(pJmpPtr, ct.trampoline.size());
if (pTrampoline == NULL)
{
return MH_ERROR_MEMORY_ALLOC;
}
#if defined _M_X64
void* pTable = AllocateDataBuffer(pTrampoline, (ct.table.size() + 1) * sizeof(uintptr_t));
if (pTable == NULL)
{
return MH_ERROR_MEMORY_ALLOC;
}
#endif
ct.pTrampoline = pTrampoline;
#if defined _M_X64
ct.pTable = pTable;
#endif
if (!ResolveTemporaryAddresses(ct))
{
return MH_ERROR_UNSUPPORTED_FUNCTION;
}
memcpy(pTrampoline, &ct.trampoline[ 0 ], ct.trampoline.size());
#if defined _M_X64
if (ct.table.size() != 0)
{
memcpy(pTable, &ct.table[ 0 ], ct.table.size() * sizeof(uintptr_t));
}
#endif
// ターゲット関数のバックアップをとる
size_t backupSize = sizeof(JMP_REL);
if (ct.patchAbove)
{
backupSize += sizeof(JMP_REL_SHORT);
}
void* pBackup = AllocateDataBuffer(NULL, backupSize);
if (pBackup == NULL)
{
return MH_ERROR_MEMORY_ALLOC;
}
memcpy(pBackup, pJmpPtr, backupSize);
// 中継関数を作成する
#if defined _M_X64
void* pRelay = AllocateCodeBuffer(pJmpPtr, sizeof(JMP_ABS));
if (pRelay == NULL)
{
return MH_ERROR_MEMORY_ALLOC;
}
WriteAbsoluteJump(pRelay, pDetour, reinterpret_cast<uintptr_t*>(pTable) + ct.table.size());
#endif
CommitBuffer();
committed = true;
// フック情報の登録
HOOK_ENTRY hook = { 0 };
hook.pTarget = pTarget;
hook.pDetour = pDetour;
#if defined _M_X64
hook.pTable = pTable;
hook.pRelay = pRelay;
#endif
hook.pTrampoline = pTrampoline;
hook.pBackup = pBackup;
hook.patchAbove = ct.patchAbove;
hook.isEnabled = false;
hook.queueEnable = false;
hook.oldIPs = ct.oldIPs;
hook.newIPs = ct.newIPs;
std::vector<HOOK_ENTRY>::iterator i = std::lower_bound(gHooks.begin(), gHooks.end(), hook);
i = gHooks.insert(i, hook);
pHook = &(*i);
}
// OUT引数の処理
*ppOriginal = pHook->pTrampoline;
return MH_OK;
}
MH_STATUS RemoveHook(void* pTarget)
{
CriticalSection::ScopedLock lock(*gCS);
if (!gIsInitialized)
{
return MH_ERROR_NOT_INITIALIZED;
}
std::vector<HOOK_ENTRY>::iterator i
= std::lower_bound(gHooks.begin(), gHooks.end(), pTarget);
if (i == gHooks.end() || i->pTarget != pTarget)
return MH_ERROR_NOT_CREATED;
HOOK_ENTRY *pHook = &(*i);
if (pHook->isEnabled)
{
ScopedThreadExclusive tex(pHook->newIPs, pHook->oldIPs);
MH_STATUS status = DisableHookLL(pHook);
if (status != MH_OK)
{
return status;
}
}
FreeBuffer(pHook->pTrampoline);
#if defined _M_X64
FreeBuffer(pHook->pTable);
#endif
FreeBuffer(pHook->pBackup);
#if defined _M_X64
FreeBuffer(pHook->pRelay);
#endif
gHooks.erase(i);
return MH_OK;
}
MH_STATUS EnableHook(void* pTarget)
{
CriticalSection::ScopedLock lock(*gCS);
if (!gIsInitialized)
{
return MH_ERROR_NOT_INITIALIZED;
}
if (pTarget == MH_ALL_HOOKS)
{
return EnableAllHooksLL();
}
HOOK_ENTRY *pHook = FindHook(pTarget);
if (pHook == NULL)
{
return MH_ERROR_NOT_CREATED;
}
if (pHook->isEnabled)
{
return MH_ERROR_ENABLED;
}
// ターゲット関数の冒頭に、中継関数またはフック関数へのジャンプを書き込む
{
ScopedThreadExclusive tex(pHook->oldIPs, pHook->newIPs);
MH_STATUS status = EnableHookLL(pHook);
if (status != MH_OK)
{
return status;
}
}
return MH_OK;
}
MH_STATUS DisableHook(void* pTarget)
{
CriticalSection::ScopedLock lock(*gCS);
if (!gIsInitialized)
{
return MH_ERROR_NOT_INITIALIZED;
}
if (pTarget == MH_ALL_HOOKS)
{
return DisableAllHooksLL();
}
HOOK_ENTRY *pHook = FindHook(pTarget);
if (pHook == NULL)
{
return MH_ERROR_NOT_CREATED;
}
if (!pHook->isEnabled)
{
return MH_ERROR_DISABLED;
}
// ターゲット関数の冒頭を書き戻すだけ。他は再利用のため残しておく
{
ScopedThreadExclusive tex(pHook->newIPs, pHook->oldIPs);
MH_STATUS status = DisableHookLL(pHook);
if (status != MH_OK)
{
return status;
}
}
return MH_OK;
}
MH_STATUS QueueEnableHook(void* pTarget)
{
CriticalSection::ScopedLock lock(*gCS);
if (!gIsInitialized)
{
return MH_ERROR_NOT_INITIALIZED;
}
if (pTarget == MH_ALL_HOOKS)
{
for (size_t i = 0, count = gHooks.size(); i < count; ++i)
{
HOOK_ENTRY& hook = gHooks[i];
hook.queueEnable = true;
}
return MH_OK;
}
HOOK_ENTRY *pHook = FindHook(pTarget);
if (pHook == NULL)
{
return MH_ERROR_NOT_CREATED;
}
pHook->queueEnable = true;
return MH_OK;
}
MH_STATUS QueueDisableHook(void* pTarget)
{
CriticalSection::ScopedLock lock(*gCS);
if (!gIsInitialized)
{
return MH_ERROR_NOT_INITIALIZED;
}
if (pTarget == MH_ALL_HOOKS)
{
for (size_t i = 0, count = gHooks.size(); i < count; ++i)
{
HOOK_ENTRY& hook = gHooks[i];
hook.queueEnable = false;
}
return MH_OK;
}
HOOK_ENTRY *pHook = FindHook(pTarget);
if (pHook == NULL)
{
return MH_ERROR_NOT_CREATED;
}
pHook->queueEnable = false;
return MH_OK;
}
MH_STATUS ApplyQueued()
{
CriticalSection::ScopedLock lock(*gCS);
if (!gIsInitialized)
{
return MH_ERROR_NOT_INITIALIZED;
}
std::vector<uintptr_t> oldIPs;
std::vector<uintptr_t> newIPs;
for (size_t i = 0, count = gHooks.size(); i < count; ++i)
{
HOOK_ENTRY& hook = gHooks[i];
if (hook.isEnabled != hook.queueEnable)
{
if (hook.queueEnable)
{
oldIPs.insert(oldIPs.end(), hook.oldIPs.begin(), hook.oldIPs.end());
newIPs.insert(newIPs.end(), hook.newIPs.begin(), hook.newIPs.end());
}
else
{
oldIPs.insert(oldIPs.end(), hook.newIPs.begin(), hook.newIPs.end());
newIPs.insert(newIPs.end(), hook.oldIPs.begin(), hook.oldIPs.end());
}
}
}
if (oldIPs.size() > 0)
{
ScopedThreadExclusive tex(oldIPs, newIPs);
for (size_t i = 0, count = gHooks.size(); i < count; ++i)
{
HOOK_ENTRY& hook = gHooks[i];
if (hook.isEnabled != hook.queueEnable)
{
MH_STATUS status;
if (hook.queueEnable)
{
status = EnableHookLL(&hook);
}
else
{
status = DisableHookLL(&hook);
}
if (status != MH_OK)
{
return status;
}
}
}
}
return MH_OK;
}
}
namespace MinHook { namespace
{
MH_STATUS EnableHookLL(HOOK_ENTRY *pHook)
{
void* pPatchTarget = pHook->pTarget;
size_t patchSize = sizeof(JMP_REL);
if (pHook->patchAbove)
{
pPatchTarget = reinterpret_cast<char*>(pPatchTarget) - sizeof(JMP_REL);
patchSize += sizeof(JMP_REL_SHORT);
}
DWORD oldProtect;
if (!VirtualProtect(pPatchTarget, patchSize, PAGE_EXECUTE_READWRITE, &oldProtect))
{
return MH_ERROR_MEMORY_PROTECT;
}
#if defined _M_X64
WriteRelativeJump(pPatchTarget, pHook->pRelay);
#elif defined _M_IX86
WriteRelativeJump(pPatchTarget, pHook->pDetour);
#endif
if (pHook->patchAbove)
{
JMP_REL_SHORT jmpAbove;
jmpAbove.opcode = 0xEB;
jmpAbove.operand = 0 - static_cast<uint8_t>(sizeof(JMP_REL_SHORT) + sizeof(JMP_REL));
memcpy(pHook->pTarget, &jmpAbove, sizeof(jmpAbove));
}
VirtualProtect(pPatchTarget, patchSize, oldProtect, &oldProtect);
pHook->isEnabled = true;
pHook->queueEnable = true;
return MH_OK;
}
MH_STATUS DisableHookLL(HOOK_ENTRY *pHook)
{
void* pPatchTarget = pHook->pTarget;
size_t patchSize = sizeof(JMP_REL);
if (pHook->patchAbove)
{
pPatchTarget = reinterpret_cast<char*>(pPatchTarget) - sizeof(JMP_REL);
patchSize += sizeof(JMP_REL_SHORT);
}
DWORD oldProtect;
if (!VirtualProtect(pPatchTarget, patchSize, PAGE_EXECUTE_READWRITE, &oldProtect))
{
return MH_ERROR_MEMORY_PROTECT;
}
memcpy(pPatchTarget, pHook->pBackup, patchSize);
VirtualProtect(pPatchTarget, patchSize, oldProtect, &oldProtect);
pHook->isEnabled = false;
pHook->queueEnable = false;
return MH_OK;
}
MH_STATUS EnableAllHooksLL()
{
std::vector<uintptr_t> oldIPs;
std::vector<uintptr_t> newIPs;
for (size_t i = 0, count = gHooks.size(); i < count; ++i)
{
HOOK_ENTRY& hook = gHooks[i];
if (!hook.isEnabled)
{
oldIPs.insert(oldIPs.end(), hook.oldIPs.begin(), hook.oldIPs.end());
newIPs.insert(newIPs.end(), hook.newIPs.begin(), hook.newIPs.end());
}
}
if (oldIPs.size() > 0)
{
ScopedThreadExclusive tex(oldIPs, newIPs);
for (size_t i = 0, count = gHooks.size(); i < count; ++i)
{
HOOK_ENTRY& hook = gHooks[i];
if (!hook.isEnabled)
{
MH_STATUS status = EnableHookLL(&hook);
if (status != MH_OK)
{
return status;
}
}
}
}
return MH_OK;
}
MH_STATUS DisableAllHooksLL()
{
std::vector<uintptr_t> oldIPs;
std::vector<uintptr_t> newIPs;
for (size_t i = 0, count = gHooks.size(); i < count; ++i)
{
HOOK_ENTRY& hook = gHooks[i];
if (hook.isEnabled)
{
oldIPs.insert(oldIPs.end(), hook.oldIPs.begin(), hook.oldIPs.end());
newIPs.insert(newIPs.end(), hook.newIPs.begin(), hook.newIPs.end());
}
}
if (oldIPs.size() > 0)
{
ScopedThreadExclusive tex(newIPs, oldIPs);
for (size_t i = 0, count = gHooks.size(); i < count; ++i)
{
HOOK_ENTRY& hook = gHooks[i];
if (hook.isEnabled)
{
MH_STATUS status = DisableHookLL(&hook);
if (status != MH_OK)
{
return status;
}
}
}
}
return MH_OK;
}
HOOK_ENTRY* FindHook(void* const pTarget)
{
std::vector<HOOK_ENTRY>::iterator i
= std::lower_bound(gHooks.begin(), gHooks.end(), pTarget);
if (i != gHooks.end() && i->pTarget == pTarget)
{
return &(*i);
}
return NULL;
}
bool IsExecutableAddress(void* pAddress)
{
static const DWORD PageExecuteMask
= (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY);
// 未割り当てや実行不可能な領域をチェック
MEMORY_BASIC_INFORMATION mi = { 0 };
VirtualQuery(pAddress, &mi, sizeof(mi));
return ((mi.Protect & PageExecuteMask) != 0);
}
void WriteRelativeJump(void* pFrom, void* const pTo)
{
JMP_REL jmp;
jmp.opcode = 0xE9;
jmp.operand = static_cast<uint32_t>(reinterpret_cast<char*>(pTo) - (reinterpret_cast<char*>(pFrom) + sizeof(jmp)));
memcpy(pFrom, &jmp, sizeof(jmp));
}
void WriteAbsoluteJump(void* pFrom, void* const pTo, void* pTable)
{
JMP_ABS jmp;
jmp.opcode = 0x25FF;
jmp.operand = static_cast<uint32_t>(reinterpret_cast<char*>(pTable) - (reinterpret_cast<char*>(pFrom) + sizeof(jmp)));
memcpy(pFrom, &jmp, sizeof(jmp));
memcpy(pTable, &pTo, sizeof(pTo));
}
template <typename T>
bool operator <(const HOOK_ENTRY& lhs, const T& rhs)
{
return lhs.pTarget < reinterpret_cast<void*>(rhs);
}
template <typename T>
bool operator <(const T& lhs, const HOOK_ENTRY& rhs)
{
return reinterpret_cast<void*>(lhs) < rhs.pTarget;
}
bool operator <(const HOOK_ENTRY& lhs, const HOOK_ENTRY& rhs)
{
return lhs.pTarget < rhs.pTarget;
}
}}

44
minhook/src/hook.h Normal file
View File

@ -0,0 +1,44 @@
/*
* MinHook - Minimalistic API Hook Library
* Copyright (C) 2009 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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 "MinHook.h"
namespace MinHook
{
MH_STATUS Initialize();
MH_STATUS Uninitialize();
MH_STATUS CreateHook(void* pTarget, void* const pDetour, void** ppOriginal);
MH_STATUS RemoveHook(void* pTarget);
MH_STATUS EnableHook(void* pTarget);
MH_STATUS DisableHook(void* pTarget);
MH_STATUS QueueEnableHook(void* pTarget);
MH_STATUS QueueDisableHook(void* pTarget);
MH_STATUS ApplyQueued();
}

799
minhook/src/pstdint.h Normal file
View File

@ -0,0 +1,799 @@
/* A portable stdint.h
****************************************************************************
* BSD License:
****************************************************************************
*
* Copyright (c) 2005-2007 Paul Hsieh
* 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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.
*
****************************************************************************
*
* Version 0.1.11
*
* The ANSI C standard committee, for the C99 standard, specified the
* inclusion of a new standard include file called stdint.h. This is
* a very useful and long desired include file which contains several
* very precise definitions for integer scalar types that is
* critically important for making portable several classes of
* applications including cryptography, hashing, variable length
* integer libraries and so on. But for most developers its likely
* useful just for programming sanity.
*
* The problem is that most compiler vendors have decided not to
* implement the C99 standard, and the next C++ language standard
* (which has a lot more mindshare these days) will be a long time in
* coming and its unknown whether or not it will include stdint.h or
* how much adoption it will have. Either way, it will be a long time
* before all compilers come with a stdint.h and it also does nothing
* for the extremely large number of compilers available today which
* do not include this file, or anything comparable to it.
*
* So that's what this file is all about. Its an attempt to build a
* single universal include file that works on as many platforms as
* possible to deliver what stdint.h is supposed to. A few things
* that should be noted about this file:
*
* 1) It is not guaranteed to be portable and/or present an identical
* interface on all platforms. The extreme variability of the
* ANSI C standard makes this an impossibility right from the
* very get go. Its really only meant to be useful for the vast
* majority of platforms that possess the capability of
* implementing usefully and precisely defined, standard sized
* integer scalars. Systems which are not intrinsically 2s
* complement may produce invalid constants.
*
* 2) There is an unavoidable use of non-reserved symbols.
*
* 3) Other standard include files are invoked.
*
* 4) This file may come in conflict with future platforms that do
* include stdint.h. The hope is that one or the other can be
* used with no real difference.
*
* 5) In the current verison, if your platform can't represent
* int32_t, int16_t and int8_t, it just dumps out with a compiler
* error.
*
* 6) 64 bit integers may or may not be defined. Test for their
* presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX.
* Note that this is different from the C99 specification which
* requires the existence of 64 bit support in the compiler. If
* this is not defined for your platform, yet it is capable of
* dealing with 64 bits then it is because this file has not yet
* been extended to cover all of your system's capabilities.
*
* 7) (u)intptr_t may or may not be defined. Test for its presence
* with the test: #ifdef PTRDIFF_MAX. If this is not defined
* for your platform, then it is because this file has not yet
* been extended to cover all of your system's capabilities, not
* because its optional.
*
* 8) The following might not been defined even if your platform is
* capable of defining it:
*
* WCHAR_MIN
* WCHAR_MAX
* (u)int64_t
* PTRDIFF_MIN
* PTRDIFF_MAX
* (u)intptr_t
*
* 9) The following have not been defined:
*
* WINT_MIN
* WINT_MAX
*
* 10) The criteria for defining (u)int_least(*)_t isn't clear,
* except for systems which don't have a type that precisely
* defined 8, 16, or 32 bit types (which this include file does
* not support anyways). Default definitions have been given.
*
* 11) The criteria for defining (u)int_fast(*)_t isn't something I
* would trust to any particular compiler vendor or the ANSI C
* committee. It is well known that "compatible systems" are
* commonly created that have very different performance
* characteristics from the systems they are compatible with,
* especially those whose vendors make both the compiler and the
* system. Default definitions have been given, but its strongly
* recommended that users never use these definitions for any
* reason (they do *NOT* deliver any serious guarantee of
* improved performance -- not in this file, nor any vendor's
* stdint.h).
*
* 12) The following macros:
*
* PRINTF_INTMAX_MODIFIER
* PRINTF_INT64_MODIFIER
* PRINTF_INT32_MODIFIER
* PRINTF_INT16_MODIFIER
* PRINTF_LEAST64_MODIFIER
* PRINTF_LEAST32_MODIFIER
* PRINTF_LEAST16_MODIFIER
* PRINTF_INTPTR_MODIFIER
*
* are strings which have been defined as the modifiers required
* for the "d", "u" and "x" printf formats to correctly output
* (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t,
* (u)least32_t, (u)least16_t and (u)intptr_t types respectively.
* PRINTF_INTPTR_MODIFIER is not defined for some systems which
* provide their own stdint.h. PRINTF_INT64_MODIFIER is not
* defined if INT64_MAX is not defined. These are an extension
* beyond what C99 specifies must be in stdint.h.
*
* In addition, the following macros are defined:
*
* PRINTF_INTMAX_HEX_WIDTH
* PRINTF_INT64_HEX_WIDTH
* PRINTF_INT32_HEX_WIDTH
* PRINTF_INT16_HEX_WIDTH
* PRINTF_INT8_HEX_WIDTH
* PRINTF_INTMAX_DEC_WIDTH
* PRINTF_INT64_DEC_WIDTH
* PRINTF_INT32_DEC_WIDTH
* PRINTF_INT16_DEC_WIDTH
* PRINTF_INT8_DEC_WIDTH
*
* Which specifies the maximum number of characters required to
* print the number of that type in either hexadecimal or decimal.
* These are an extension beyond what C99 specifies must be in
* stdint.h.
*
* Compilers tested (all with 0 warnings at their highest respective
* settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32
* bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio
* .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3
*
* This file should be considered a work in progress. Suggestions for
* improvements, especially those which increase coverage are strongly
* encouraged.
*
* Acknowledgements
*
* The following people have made significant contributions to the
* development and testing of this file:
*
* Chris Howie
* John Steele Scott
* Dave Thorup
*
*/
#include <stddef.h>
#include <limits.h>
#include <signal.h>
/*
* For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and
* do nothing else. On the Mac OS X version of gcc this is _STDINT_H_.
*/
#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) )) && !defined (_PSTDINT_H_INCLUDED)
#include <stdint.h>
#define _PSTDINT_H_INCLUDED
# ifndef PRINTF_INT64_MODIFIER
# define PRINTF_INT64_MODIFIER "ll"
# endif
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER "l"
# endif
# ifndef PRINTF_INT16_MODIFIER
# define PRINTF_INT16_MODIFIER "h"
# endif
# ifndef PRINTF_INTMAX_MODIFIER
# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
# endif
# ifndef PRINTF_INT64_HEX_WIDTH
# define PRINTF_INT64_HEX_WIDTH "16"
# endif
# ifndef PRINTF_INT32_HEX_WIDTH
# define PRINTF_INT32_HEX_WIDTH "8"
# endif
# ifndef PRINTF_INT16_HEX_WIDTH
# define PRINTF_INT16_HEX_WIDTH "4"
# endif
# ifndef PRINTF_INT8_HEX_WIDTH
# define PRINTF_INT8_HEX_WIDTH "2"
# endif
# ifndef PRINTF_INT64_DEC_WIDTH
# define PRINTF_INT64_DEC_WIDTH "20"
# endif
# ifndef PRINTF_INT32_DEC_WIDTH
# define PRINTF_INT32_DEC_WIDTH "10"
# endif
# ifndef PRINTF_INT16_DEC_WIDTH
# define PRINTF_INT16_DEC_WIDTH "5"
# endif
# ifndef PRINTF_INT8_DEC_WIDTH
# define PRINTF_INT8_DEC_WIDTH "3"
# endif
# ifndef PRINTF_INTMAX_HEX_WIDTH
# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
# endif
# ifndef PRINTF_INTMAX_DEC_WIDTH
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
# endif
/*
* Something really weird is going on with Open Watcom. Just pull some of
* these duplicated definitions from Open Watcom's stdint.h file for now.
*/
# if defined (__WATCOMC__) && __WATCOMC__ >= 1250
# if !defined (INT64_C)
# define INT64_C(x) (x + (INT64_MAX - INT64_MAX))
# endif
# if !defined (UINT64_C)
# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX))
# endif
# if !defined (INT32_C)
# define INT32_C(x) (x + (INT32_MAX - INT32_MAX))
# endif
# if !defined (UINT32_C)
# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX))
# endif
# if !defined (INT16_C)
# define INT16_C(x) (x)
# endif
# if !defined (UINT16_C)
# define UINT16_C(x) (x)
# endif
# if !defined (INT8_C)
# define INT8_C(x) (x)
# endif
# if !defined (UINT8_C)
# define UINT8_C(x) (x)
# endif
# if !defined (UINT64_MAX)
# define UINT64_MAX 18446744073709551615ULL
# endif
# if !defined (INT64_MAX)
# define INT64_MAX 9223372036854775807LL
# endif
# if !defined (UINT32_MAX)
# define UINT32_MAX 4294967295UL
# endif
# if !defined (INT32_MAX)
# define INT32_MAX 2147483647L
# endif
# if !defined (INTMAX_MAX)
# define INTMAX_MAX INT64_MAX
# endif
# if !defined (INTMAX_MIN)
# define INTMAX_MIN INT64_MIN
# endif
# endif
#endif
#ifndef _PSTDINT_H_INCLUDED
#define _PSTDINT_H_INCLUDED
#ifndef SIZE_MAX
# define SIZE_MAX (~(size_t)0)
#endif
/*
* Deduce the type assignments from limits.h under the assumption that
* integer sizes in bits are powers of 2, and follow the ANSI
* definitions.
*/
#ifndef UINT8_MAX
# define UINT8_MAX 0xff
#endif
#ifndef uint8_t
# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S)
typedef unsigned char uint8_t;
# define UINT8_C(v) ((uint8_t) v)
# else
# error "Platform not supported"
# endif
#endif
#ifndef INT8_MAX
# define INT8_MAX 0x7f
#endif
#ifndef INT8_MIN
# define INT8_MIN INT8_C(0x80)
#endif
#ifndef int8_t
# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S)
typedef signed char int8_t;
# define INT8_C(v) ((int8_t) v)
# else
# error "Platform not supported"
# endif
#endif
#ifndef UINT16_MAX
# define UINT16_MAX 0xffff
#endif
#ifndef uint16_t
#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S)
typedef unsigned int uint16_t;
# ifndef PRINTF_INT16_MODIFIER
# define PRINTF_INT16_MODIFIER ""
# endif
# define UINT16_C(v) ((uint16_t) (v))
#elif (USHRT_MAX == UINT16_MAX)
typedef unsigned short uint16_t;
# define UINT16_C(v) ((uint16_t) (v))
# ifndef PRINTF_INT16_MODIFIER
# define PRINTF_INT16_MODIFIER "h"
# endif
#else
#error "Platform not supported"
#endif
#endif
#ifndef INT16_MAX
# define INT16_MAX 0x7fff
#endif
#ifndef INT16_MIN
# define INT16_MIN INT16_C(0x8000)
#endif
#ifndef int16_t
#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S)
typedef signed int int16_t;
# define INT16_C(v) ((int16_t) (v))
# ifndef PRINTF_INT16_MODIFIER
# define PRINTF_INT16_MODIFIER ""
# endif
#elif (SHRT_MAX == INT16_MAX)
typedef signed short int16_t;
# define INT16_C(v) ((int16_t) (v))
# ifndef PRINTF_INT16_MODIFIER
# define PRINTF_INT16_MODIFIER "h"
# endif
#else
#error "Platform not supported"
#endif
#endif
#ifndef UINT32_MAX
# define UINT32_MAX (0xffffffffUL)
#endif
#ifndef uint32_t
#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S)
typedef unsigned long uint32_t;
# define UINT32_C(v) v ## UL
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER "l"
# endif
#elif (UINT_MAX == UINT32_MAX)
typedef unsigned int uint32_t;
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER ""
# endif
# define UINT32_C(v) v ## U
#elif (USHRT_MAX == UINT32_MAX)
typedef unsigned short uint32_t;
# define UINT32_C(v) ((unsigned short) (v))
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER ""
# endif
#else
#error "Platform not supported"
#endif
#endif
#ifndef INT32_MAX
# define INT32_MAX (0x7fffffffL)
#endif
#ifndef INT32_MIN
# define INT32_MIN INT32_C(0x80000000)
#endif
#ifndef int32_t
#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S)
typedef signed long int32_t;
# define INT32_C(v) v ## L
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER "l"
# endif
#elif (INT_MAX == INT32_MAX)
typedef signed int int32_t;
# define INT32_C(v) v
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER ""
# endif
#elif (SHRT_MAX == INT32_MAX)
typedef signed short int32_t;
# define INT32_C(v) ((short) (v))
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER ""
# endif
#else
#error "Platform not supported"
#endif
#endif
/*
* The macro stdint_int64_defined is temporarily used to record
* whether or not 64 integer support is available. It must be
* defined for any 64 integer extensions for new platforms that are
* added.
*/
#undef stdint_int64_defined
#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S)
# if (__STDC__ && __STDC_VERSION >= 199901L) || defined (S_SPLINT_S)
# define stdint_int64_defined
typedef long long int64_t;
typedef unsigned long long uint64_t;
# define UINT64_C(v) v ## ULL
# define INT64_C(v) v ## LL
# ifndef PRINTF_INT64_MODIFIER
# define PRINTF_INT64_MODIFIER "ll"
# endif
# endif
#endif
#if !defined (stdint_int64_defined)
# if defined(__GNUC__)
# define stdint_int64_defined
__extension__ typedef long long int64_t;
__extension__ typedef unsigned long long uint64_t;
# define UINT64_C(v) v ## ULL
# define INT64_C(v) v ## LL
# ifndef PRINTF_INT64_MODIFIER
# define PRINTF_INT64_MODIFIER "ll"
# endif
# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S)
# define stdint_int64_defined
typedef long long int64_t;
typedef unsigned long long uint64_t;
# define UINT64_C(v) v ## ULL
# define INT64_C(v) v ## LL
# ifndef PRINTF_INT64_MODIFIER
# define PRINTF_INT64_MODIFIER "ll"
# endif
# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC)
# define stdint_int64_defined
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
# define UINT64_C(v) v ## UI64
# define INT64_C(v) v ## I64
# ifndef PRINTF_INT64_MODIFIER
# define PRINTF_INT64_MODIFIER "I64"
# endif
# endif
#endif
#if !defined (LONG_LONG_MAX) && defined (INT64_C)
# define LONG_LONG_MAX INT64_C (9223372036854775807)
#endif
#ifndef ULONG_LONG_MAX
# define ULONG_LONG_MAX UINT64_C (18446744073709551615)
#endif
#if !defined (INT64_MAX) && defined (INT64_C)
# define INT64_MAX INT64_C (9223372036854775807)
#endif
#if !defined (INT64_MIN) && defined (INT64_C)
# define INT64_MIN INT64_C (-9223372036854775808)
#endif
#if !defined (UINT64_MAX) && defined (INT64_C)
# define UINT64_MAX UINT64_C (18446744073709551615)
#endif
/*
* Width of hexadecimal for number field.
*/
#ifndef PRINTF_INT64_HEX_WIDTH
# define PRINTF_INT64_HEX_WIDTH "16"
#endif
#ifndef PRINTF_INT32_HEX_WIDTH
# define PRINTF_INT32_HEX_WIDTH "8"
#endif
#ifndef PRINTF_INT16_HEX_WIDTH
# define PRINTF_INT16_HEX_WIDTH "4"
#endif
#ifndef PRINTF_INT8_HEX_WIDTH
# define PRINTF_INT8_HEX_WIDTH "2"
#endif
#ifndef PRINTF_INT64_DEC_WIDTH
# define PRINTF_INT64_DEC_WIDTH "20"
#endif
#ifndef PRINTF_INT32_DEC_WIDTH
# define PRINTF_INT32_DEC_WIDTH "10"
#endif
#ifndef PRINTF_INT16_DEC_WIDTH
# define PRINTF_INT16_DEC_WIDTH "5"
#endif
#ifndef PRINTF_INT8_DEC_WIDTH
# define PRINTF_INT8_DEC_WIDTH "3"
#endif
/*
* Ok, lets not worry about 128 bit integers for now. Moore's law says
* we don't need to worry about that until about 2040 at which point
* we'll have bigger things to worry about.
*/
#ifdef stdint_int64_defined
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
# define INTMAX_MAX INT64_MAX
# define INTMAX_MIN INT64_MIN
# define UINTMAX_MAX UINT64_MAX
# define UINTMAX_C(v) UINT64_C(v)
# define INTMAX_C(v) INT64_C(v)
# ifndef PRINTF_INTMAX_MODIFIER
# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
# endif
# ifndef PRINTF_INTMAX_HEX_WIDTH
# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
# endif
# ifndef PRINTF_INTMAX_DEC_WIDTH
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
# endif
#else
typedef int32_t intmax_t;
typedef uint32_t uintmax_t;
# define INTMAX_MAX INT32_MAX
# define UINTMAX_MAX UINT32_MAX
# define UINTMAX_C(v) UINT32_C(v)
# define INTMAX_C(v) INT32_C(v)
# ifndef PRINTF_INTMAX_MODIFIER
# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER
# endif
# ifndef PRINTF_INTMAX_HEX_WIDTH
# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH
# endif
# ifndef PRINTF_INTMAX_DEC_WIDTH
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH
# endif
#endif
/*
* Because this file currently only supports platforms which have
* precise powers of 2 as bit sizes for the default integers, the
* least definitions are all trivial. Its possible that a future
* version of this file could have different definitions.
*/
#ifndef stdint_least_defined
typedef int8_t int_least8_t;
typedef uint8_t uint_least8_t;
typedef int16_t int_least16_t;
typedef uint16_t uint_least16_t;
typedef int32_t int_least32_t;
typedef uint32_t uint_least32_t;
# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER
# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER
# define UINT_LEAST8_MAX UINT8_MAX
# define INT_LEAST8_MAX INT8_MAX
# define UINT_LEAST16_MAX UINT16_MAX
# define INT_LEAST16_MAX INT16_MAX
# define UINT_LEAST32_MAX UINT32_MAX
# define INT_LEAST32_MAX INT32_MAX
# define INT_LEAST8_MIN INT8_MIN
# define INT_LEAST16_MIN INT16_MIN
# define INT_LEAST32_MIN INT32_MIN
# ifdef stdint_int64_defined
typedef int64_t int_least64_t;
typedef uint64_t uint_least64_t;
# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER
# define UINT_LEAST64_MAX UINT64_MAX
# define INT_LEAST64_MAX INT64_MAX
# define INT_LEAST64_MIN INT64_MIN
# endif
#endif
#undef stdint_least_defined
/*
* The ANSI C committee pretending to know or specify anything about
* performance is the epitome of misguided arrogance. The mandate of
* this file is to *ONLY* ever support that absolute minimum
* definition of the fast integer types, for compatibility purposes.
* No extensions, and no attempt to suggest what may or may not be a
* faster integer type will ever be made in this file. Developers are
* warned to stay away from these types when using this or any other
* stdint.h.
*/
typedef int_least8_t int_fast8_t;
typedef uint_least8_t uint_fast8_t;
typedef int_least16_t int_fast16_t;
typedef uint_least16_t uint_fast16_t;
typedef int_least32_t int_fast32_t;
typedef uint_least32_t uint_fast32_t;
#define UINT_FAST8_MAX UINT_LEAST8_MAX
#define INT_FAST8_MAX INT_LEAST8_MAX
#define UINT_FAST16_MAX UINT_LEAST16_MAX
#define INT_FAST16_MAX INT_LEAST16_MAX
#define UINT_FAST32_MAX UINT_LEAST32_MAX
#define INT_FAST32_MAX INT_LEAST32_MAX
#define INT_FAST8_MIN INT_LEAST8_MIN
#define INT_FAST16_MIN INT_LEAST16_MIN
#define INT_FAST32_MIN INT_LEAST32_MIN
#ifdef stdint_int64_defined
typedef int_least64_t int_fast64_t;
typedef uint_least64_t uint_fast64_t;
# define UINT_FAST64_MAX UINT_LEAST64_MAX
# define INT_FAST64_MAX INT_LEAST64_MAX
# define INT_FAST64_MIN INT_LEAST64_MIN
#endif
#undef stdint_int64_defined
/*
* Whatever piecemeal, per compiler thing we can do about the wchar_t
* type limits.
*/
#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__)
# include <wchar.h>
# ifndef WCHAR_MIN
# define WCHAR_MIN 0
# endif
# ifndef WCHAR_MAX
# define WCHAR_MAX ((wchar_t)-1)
# endif
#endif
/*
* Whatever piecemeal, per compiler/platform thing we can do about the
* (u)intptr_t types and limits.
*/
#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED)
# define STDINT_H_UINTPTR_T_DEFINED
#endif
#ifndef STDINT_H_UINTPTR_T_DEFINED
# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64)
# define stdint_intptr_bits 64
# elif defined (__WATCOMC__) || defined (__TURBOC__)
# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)
# define stdint_intptr_bits 16
# else
# define stdint_intptr_bits 32
# endif
# elif defined (__i386__) || defined (_WIN32) || defined (WIN32)
# define stdint_intptr_bits 32
# elif defined (__INTEL_COMPILER)
/* TODO -- what will Intel do about x86-64? */
# endif
# ifdef stdint_intptr_bits
# define stdint_intptr_glue3_i(a,b,c) a##b##c
# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c)
# ifndef PRINTF_INTPTR_MODIFIER
# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER)
# endif
# ifndef PTRDIFF_MAX
# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
# endif
# ifndef PTRDIFF_MIN
# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
# endif
# ifndef UINTPTR_MAX
# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX)
# endif
# ifndef INTPTR_MAX
# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
# endif
# ifndef INTPTR_MIN
# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
# endif
# ifndef INTPTR_C
# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x)
# endif
# ifndef UINTPTR_C
# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x)
# endif
typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t;
typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t;
# else
/* TODO -- This following is likely wrong for some platforms, and does
nothing for the definition of uintptr_t. */
typedef ptrdiff_t intptr_t;
# endif
# define STDINT_H_UINTPTR_T_DEFINED
#endif
/*
* Assumes sig_atomic_t is signed and we have a 2s complement machine.
*/
#ifndef SIG_ATOMIC_MAX
# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1)
#endif
#endif
#if defined (__TEST_PSTDINT_FOR_CORRECTNESS)
/*
* Please compile with the maximum warning settings to make sure macros are not
* defined more than once.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define glue3_aux(x,y,z) x ## y ## z
#define glue3(x,y,z) glue3_aux(x,y,z)
#define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,=) glue3(UINT,bits,_C) (0);
#define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,=) glue3(INT,bits,_C) (0);
#define DECL(us,bits) glue3(DECL,us,) (bits)
#define TESTUMAX(bits) glue3(u,bits,=) glue3(~,u,bits); if (glue3(UINT,bits,_MAX) glue3(!=,u,bits)) printf ("Something wrong with UINT%d_MAX\n", bits)
int main () {
DECL(I,8)
DECL(U,8)
DECL(I,16)
DECL(U,16)
DECL(I,32)
DECL(U,32)
#ifdef INT64_MAX
DECL(I,64)
DECL(U,64)
#endif
intmax_t imax = INTMAX_C(0);
uintmax_t umax = UINTMAX_C(0);
char str0[256], str1[256];
sprintf (str0, "%d %x\n", 0, ~0);
sprintf (str1, "%d %x\n", i8, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with i8 : %s\n", str1);
sprintf (str1, "%u %x\n", u8, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with u8 : %s\n", str1);
sprintf (str1, "%d %x\n", i16, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with i16 : %s\n", str1);
sprintf (str1, "%u %x\n", u16, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with u16 : %s\n", str1);
sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with i32 : %s\n", str1);
sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with u32 : %s\n", str1);
#ifdef INT64_MAX
sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with i64 : %s\n", str1);
#endif
sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with imax : %s\n", str1);
sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with umax : %s\n", str1);
TESTUMAX(8);
TESTUMAX(16);
TESTUMAX(32);
#ifdef INT64_MAX
TESTUMAX(64);
#endif
return EXIT_SUCCESS;
}
#endif

188
minhook/src/thread.cpp Normal file
View File

@ -0,0 +1,188 @@
/*
* MinHook - Minimalistic API Hook Library
* Copyright (C) 2009 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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.
*/
#include <cassert>
#include <vector>
#include <algorithm>
#include <windows.h>
#include <TlHelp32.h>
#include "thread.h"
namespace MinHook { namespace
{
// 自動的にCloseHandleされるWindowsハンドル
class ScopedHandle
{
ScopedHandle(const ScopedHandle&);
void operator=(const ScopedHandle&);
private:
HANDLE handle_;
public:
ScopedHandle(HANDLE handle)
: handle_(handle)
{
}
~ScopedHandle()
{
CloseHandle(handle_);
}
operator HANDLE() const
{
return handle_;
}
};
}}
// CriticalSection, CriticalSection::ScopedLock の実装
namespace MinHook
{
CriticalSection::CriticalSection()
{
InitializeCriticalSection(&cs_);
}
CriticalSection::~CriticalSection()
{
DeleteCriticalSection(&cs_);
}
void CriticalSection::enter()
{
EnterCriticalSection(&cs_);
}
void CriticalSection::leave()
{
LeaveCriticalSection(&cs_);
}
CriticalSection::ScopedLock::ScopedLock(CriticalSection& cs)
: cs_(cs)
{
cs_.enter();
}
CriticalSection::ScopedLock::~ScopedLock()
{
cs_.leave();
}
}
// ScopedThreadExclusive の実装
namespace MinHook
{
ScopedThreadExclusive::ScopedThreadExclusive(const std::vector<uintptr_t>& oldIPs, const std::vector<uintptr_t>& newIPs)
{
assert(("ScopedThreadExclusive::ctor", (oldIPs.size() == newIPs.size())));
GetThreads(threads_);
Freeze(threads_, oldIPs, newIPs);
}
ScopedThreadExclusive::~ScopedThreadExclusive()
{
Unfreeze(threads_);
}
void ScopedThreadExclusive::GetThreads(std::vector<DWORD>& threads)
{
ScopedHandle hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
{
return;
}
THREADENTRY32 te = { sizeof(te) };
if (Thread32First(hSnapshot, &te))
{
do
{
if (te.th32OwnerProcessID == GetCurrentProcessId()
&& te.th32ThreadID != GetCurrentThreadId())
{
threads.push_back(te.th32ThreadID);
}
}
while (Thread32Next(hSnapshot, &te));
}
}
void ScopedThreadExclusive::Freeze(
const std::vector<DWORD>& threads, const std::vector<uintptr_t>& oldIPs, const std::vector<uintptr_t>& newIPs)
{
assert(("ScopedThreadExclusive::freeze", (oldIPs.size() == newIPs.size())));
static const DWORD ThreadAccess
= THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION | THREAD_SET_CONTEXT;
for (size_t i = 0, count = threads.size(); i < count; ++i)
{
DWORD tid = threads[i];
ScopedHandle hThread = OpenThread(ThreadAccess, FALSE, tid);
SuspendThread(hThread);
// 書き換え範囲内でスレッドが停止した場合は、トランポリン関数に制御を移す
CONTEXT c = { 0 };
c.ContextFlags = CONTEXT_CONTROL;
if (!GetThreadContext(hThread, &c))
{
return;
}
#if defined _M_X64
DWORD64& ip = c.Rip;
#elif defined _M_IX86
DWORD& ip = c.Eip;
#endif
for (size_t i = 0; i < oldIPs.size(); ++i)
{
if (ip == oldIPs[ i ])
{
ip = newIPs[ i ];
SetThreadContext(hThread, &c);
break;
}
}
}
}
void ScopedThreadExclusive::Unfreeze(const std::vector<DWORD>& threads)
{
for (size_t i = 0, count = threads.size(); i < count; ++i)
{
DWORD tid = threads[i];
ScopedHandle hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, tid);
ResumeThread(hThread);
}
}
}

79
minhook/src/thread.h Normal file
View File

@ -0,0 +1,79 @@
/*
* MinHook - Minimalistic API Hook Library
* Copyright (C) 2009 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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 <vector>
#include <windows.h>
#include "trampoline.h"
namespace MinHook
{
// ScopedLock 付きクリティカルセクション
class CriticalSection
{
CriticalSection(const CriticalSection&);
void operator=(const CriticalSection&);
public:
class ScopedLock
{
ScopedLock(const ScopedLock&);
void operator=(const ScopedLock&);
private:
CriticalSection& cs_;
public:
ScopedLock(CriticalSection& cs);
~ScopedLock();
};
private:
CRITICAL_SECTION cs_;
public:
CriticalSection();
~CriticalSection();
void enter();
void leave();
};
// 同一プロセス内の他のスレッドをすべて停止
class ScopedThreadExclusive
{
private:
std::vector<DWORD> threads_;
public:
ScopedThreadExclusive(const std::vector<uintptr_t>& oldIPs, const std::vector<uintptr_t>& newIPs);
~ScopedThreadExclusive();
private:
static void GetThreads(std::vector<DWORD>& threads);
static void Freeze(
const std::vector<DWORD>& threads, const std::vector<uintptr_t>& oldIPs, const std::vector<uintptr_t>& newIPs);
static void Unfreeze(const std::vector<DWORD>& threads);
};
}

393
minhook/src/trampoline.cpp Normal file
View File

@ -0,0 +1,393 @@
/*
* MinHook - Minimalistic API Hook Library
* Copyright (C) 2009 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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.
*/
#include <cassert>
#include <vector>
#include <algorithm>
#include <Windows.h>
#include "pstdint.h"
#if defined _M_X64
#include "hde64/include/hde64.h"
#elif defined _M_IX86
#include "hde32/hde32.h"
#endif
#include "trampoline.h"
namespace MinHook { namespace
{
#if defined _M_X64
typedef hde64s hde_t;
inline unsigned int hde_disasm(const void* code, hde_t* hs) { return hde64_disasm(code, hs); }
#elif defined _M_IX86
typedef hde32s hde_t;
inline unsigned int hde_disasm(const void* code, hde_t* hs) { return hde32_disasm(code, hs); }
#endif
// 命令書き込み用構造体
#pragma pack(push, 1)
struct JMP_REL_SHORT
{
uint8_t opcode;
uint8_t operand;
};
struct JMP_REL
{
uint8_t opcode;
uint32_t operand;
};
typedef JMP_REL CALL_REL;
struct JMP_ABS
{
uint16_t opcode;
uint32_t operand;
};
typedef JMP_ABS CALL_ABS, JCC_REL;
// 間接絶対NEAR Jccに相当するロジック
struct JCC_ABS
{
uint8_t opcode; // 7* 02 J** +4
uint8_t dummy0;
uint8_t dummy1; // EB 06 JMP +8
uint8_t dummy2;
uint16_t dummy3; // FF25 xxxxxxxx JMP [RIP+xxxxxxxx]
uint32_t operand;
};
#pragma pack(pop)
uintptr_t GetRelativeBranchDestination(uint8_t* pInst, const hde_t& hs, bool isShort);
inline bool IsInternalJump(void* pTarget, uintptr_t dest);
template <typename T>
void AppendTempAddress(uintptr_t address, size_t pos, const T& inst, CREATE_TREMPOLINE_T& ct);
#if defined _M_X64
void AppendRipRelativeAddress(uint8_t* pInst, size_t pos, const hde_t& hs, CREATE_TREMPOLINE_T& ct);
#endif
inline void SetJccOpcode(const hde_t& hs, JCC_REL& inst);
inline void SetJccOpcode(const hde_t& hs, JCC_ABS& inst);
bool IsCodePadding(uint8_t* pInst, size_t size);
bool IsExecutableAddress(void* pAddress);
}}
namespace MinHook
{
bool CreateTrampolineFunction(CREATE_TREMPOLINE_T& ct)
{
assert(("CreateTrampolineFunction", ct.pTarget != NULL));
#if defined _M_X64
CALL_ABS call = { 0x15FF, 0x00000000 };
JMP_ABS jmp = { 0x25FF, 0x00000000 };
JCC_ABS jcc = { 0x70, 0x02, 0xEB, 0x06, 0x25FF, 0x00000000 };
#elif defined _M_IX86
CALL_REL call = { 0xE8, 0x00000000 };
JMP_REL jmp = { 0xE9, 0x00000000 };
JCC_REL jcc = { 0x800F, 0x00000000 };
#endif
size_t oldPos = 0;
size_t newPos = 0;
uintptr_t jmpDest = 0; // 関数内ジャンプの飛び先アドレス(分岐中判定に使用)
bool finished = false; // 関数終了フラグ
while (!finished)
{
uint8_t *pInst = reinterpret_cast<uint8_t*>(ct.pTarget) + oldPos;
hde_t hs;
hde_disasm(pInst, &hs);
if ((hs.flags & F_ERROR) == F_ERROR)
{
return false;
}
void* pCopySrc = pInst;
size_t copySize = hs.len;
if (pInst - reinterpret_cast<uint8_t*>(ct.pTarget) >= sizeof(JMP_REL))
{
// ターゲット関数へのジャンプを書き込み、関数を終了
AppendTempAddress(reinterpret_cast<uintptr_t>(pInst), newPos, jmp, ct);
pCopySrc = &jmp;
copySize = sizeof(jmp);
finished = true;
}
#if defined _M_X64
// RIP相対アドレッシングを使用している命令 (ModR/M = 00???101B)
else if ((hs.modrm & 0xC7) == 0x05)
{
// RIP相対アドレスのみ書き換え
AppendRipRelativeAddress(pInst, newPos, hs, ct);
// JMP (FF /4)なら関数を終了
if (hs.opcode == 0xFF && hs.modrm_reg == 4)
{
finished = true;
}
}
#endif
// 相対直接CALL
else if (hs.opcode == 0xE8)
{
AppendTempAddress(GetRelativeBranchDestination(pInst, hs, false), newPos, call, ct);
pCopySrc = &call;
copySize = sizeof(call);
}
// 相対直接JMP (EB or E9)
else if ((hs.opcode & 0xFD) == 0xE9)
{
uintptr_t dest = GetRelativeBranchDestination(pInst, hs, hs.opcode == 0xEB);
// 関数内へのジャンプはそのままコピー(ジャンプ中は命令長が変わるような操作は不可)
if (IsInternalJump(ct.pTarget, dest))
{
jmpDest = std::max<uintptr_t>(jmpDest, dest);
}
else
{
AppendTempAddress(dest, newPos, jmp, ct);
pCopySrc = &jmp;
copySize = sizeof(jmp);
// 分岐中でなければ関数を終了
finished = (reinterpret_cast<uintptr_t>(pInst) >= jmpDest);
}
}
// 相対直接Jcc
else if ((hs.opcode & 0xF0) == 0x70 || (hs.opcode & 0xFC) == 0xE0 || (hs.opcode2 & 0xF0) == 0x80)
{
uintptr_t dest = GetRelativeBranchDestination(pInst, hs, (hs.opcode & 0xF0) == 0x70 || (hs.opcode & 0xFC) == 0xE0);
// 関数内へのジャンプはそのままコピー(分岐中は命令長が変わるような操作は不可)
if (IsInternalJump(ct.pTarget, dest))
{
jmpDest = std::max<uintptr_t>(jmpDest, dest);
}
else if ((hs.opcode & 0xFC) == 0xE0) // 関数外へのJCXZ, JECXZ には対応しない
{
return false;
}
else
{
AppendTempAddress(dest, newPos, jcc, ct);
SetJccOpcode(hs, jcc);
pCopySrc = &jcc;
copySize = sizeof(jcc);
}
}
// RET (C2 or C3)
else if ((hs.opcode & 0xFE) == 0xC2)
{
// 分岐中でなければトランポリン関数を終了
finished = (reinterpret_cast<uintptr_t>(pInst) >= jmpDest);
}
// 分岐中は命令長が変わるような操作は不可
if (reinterpret_cast<uintptr_t>(pInst) < jmpDest && copySize != hs.len)
{
return false;
}
ct.trampoline.resize(newPos + copySize);
memcpy(&ct.trampoline[ newPos ], pCopySrc, copySize);
ct.oldIPs.push_back(oldPos);
oldPos += hs.len;
ct.newIPs.push_back(newPos);
newPos += copySize;
}
// Is there enough place for a long jump?
if (oldPos < sizeof(JMP_REL) && !IsCodePadding(reinterpret_cast<uint8_t*>(ct.pTarget) + oldPos, sizeof(JMP_REL) - oldPos))
{
// Is there enough place for a short jump?
if (oldPos < sizeof(JMP_REL_SHORT) && !IsCodePadding(reinterpret_cast<uint8_t*>(ct.pTarget) + oldPos, sizeof(JMP_REL_SHORT) - oldPos))
{
return false;
}
// Can we place the long jump above the function?
if (!IsExecutableAddress(reinterpret_cast<uint8_t*>(ct.pTarget) - sizeof(JMP_REL)))
{
return false;
}
if (!IsCodePadding(reinterpret_cast<uint8_t*>(ct.pTarget) - sizeof(JMP_REL), sizeof(JMP_REL)))
{
return false;
}
ct.patchAbove = true;
}
return true;
}
bool ResolveTemporaryAddresses(CREATE_TREMPOLINE_T& ct)
{
assert(("ResolveTemporaryAddresses", ct.pTrampoline != NULL));
#if defined _M_X64
assert(("ResolveTemporaryAddresses", (ct.table.empty() || ct.pTable != NULL)));
#endif
#if defined _M_X64
uintptr_t* pt = reinterpret_cast<uintptr_t*>(ct.pTable);
#endif
for (size_t i = 0, count = ct.tempAddr.size(); i < count; ++i)
{
const TEMP_ADDR& ta = ct.tempAddr[i];
if (ta.position > ct.trampoline.size() - sizeof(uint32_t))
{
return false;
}
uintptr_t addr;
#if defined _M_X64
if (ta.address < 0x10000) // 0x10000未満はテーブルのインデックス、0x10000以上はRIP相対アドレス
{
addr = reinterpret_cast<uintptr_t>(pt++);
}
else
#endif
{
addr = ta.address;
}
*reinterpret_cast<uint32_t*>(&ct.trampoline[ ta.position ])
= static_cast<uint32_t>(addr - (reinterpret_cast<uintptr_t>(ct.pTrampoline) + ta.pc));
}
for (size_t i = 0; i < ct.oldIPs.size(); ++i)
{
ct.oldIPs[ i ] += reinterpret_cast<uintptr_t>(ct.pTarget);
ct.newIPs[ i ] += reinterpret_cast<uintptr_t>(ct.pTrampoline);
}
if (ct.patchAbove)
{
ct.oldIPs.push_back(reinterpret_cast<uintptr_t>(ct.pTarget));
ct.newIPs.push_back(reinterpret_cast<uintptr_t>(ct.pTarget) - sizeof(JMP_REL));
}
return true;
}
}
namespace MinHook { namespace
{
inline uintptr_t GetRelativeBranchDestination(uint8_t* pInst, const hde_t& hs, bool isShort)
{
int32_t imm = isShort ? static_cast<int8_t>(hs.imm.imm8) : static_cast<int32_t>(hs.imm.imm32);
return reinterpret_cast<uintptr_t>(pInst) + hs.len + imm;
}
inline bool IsInternalJump(void* pTarget, uintptr_t dest)
{
uintptr_t pt = reinterpret_cast<uintptr_t>(pTarget);
return (pt <= dest && dest <= pt + sizeof(JMP_REL));
}
template <typename T>
void AppendTempAddress(uintptr_t address, size_t pos, const T& inst, CREATE_TREMPOLINE_T& ct)
{
TEMP_ADDR ta;
#if defined _M_X64
ta.address = ct.table.size();
ct.table.push_back(address);
#elif defined _M_IX86
ta.address = address;
#endif
ta.position = pos + (reinterpret_cast<uintptr_t>(&inst.operand) - reinterpret_cast<uintptr_t>(&inst));
ta.pc = pos + sizeof(inst);
ct.tempAddr.push_back(ta);
}
#if defined _M_X64
void AppendRipRelativeAddress(uint8_t* pInst, size_t pos, const hde_t& hs, CREATE_TREMPOLINE_T& ct)
{
TEMP_ADDR ta;
ta.address = reinterpret_cast<uintptr_t>(pInst) + hs.len + static_cast<int32_t>(hs.disp.disp32);
ta.position = pos + hs.len - ((hs.flags & 0x3C) >> 2) - 4; // pos + 命令長 - 即値サイズ - 4
ta.pc = pos + hs.len;
ct.tempAddr.push_back(ta);
}
#endif
inline void SetJccOpcode(const hde_t& hs, JCC_REL& inst)
{
uint8_t n = ((hs.opcode != 0x0F ? hs.opcode : hs.opcode2) & 0x0F);
inst.opcode = 0x800F | (n << 8);
}
inline void SetJccOpcode(const hde_t& hs, JCC_ABS& inst)
{
uint8_t n = ((hs.opcode != 0x0F ? hs.opcode : hs.opcode2) & 0x0F);
inst.opcode = 0x70 | n;
}
bool IsCodePadding(uint8_t* pInst, size_t size)
{
uint8_t paddingByte = pInst[0];
switch (paddingByte)
{
case 0x00:
case 0x90: // NOP
case 0xCC: // INT3
for (size_t i = 1; i < size; ++i)
{
if (pInst[i] != paddingByte)
{
return false;
}
}
return true;
default:
return false;
}
}
bool IsExecutableAddress(void* pAddress)
{
static const DWORD PageExecuteMask
= (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY);
// 未割り当てや実行不可能な領域をチェック
MEMORY_BASIC_INFORMATION mi = { 0 };
VirtualQuery(pAddress, &mi, sizeof(mi));
return ((mi.Protect & PageExecuteMask) != 0);
}
}}

59
minhook/src/trampoline.h Normal file
View File

@ -0,0 +1,59 @@
/*
* MinHook - Minimalistic API Hook Library
* Copyright (C) 2009 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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 <vector>
namespace MinHook
{
struct TEMP_ADDR
{
uintptr_t address;
size_t position;
size_t pc;
};
struct CREATE_TREMPOLINE_T
{
void* pTarget;
void* pTrampoline;
bool patchAbove;
std::vector<char> trampoline;
std::vector<TEMP_ADDR> tempAddr;
#if defined _M_X64
void* pTable;
std::vector<uintptr_t> table;
#endif
std::vector<uintptr_t> oldIPs;
std::vector<uintptr_t> newIPs;
};
bool CreateTrampolineFunction(CREATE_TREMPOLINE_T& ct);
bool ResolveTemporaryAddresses(CREATE_TREMPOLINE_T& ct);
}