_stdcallthunk
// c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.14.26428\atlmfc\include\atlstdthunk.h
// This is a part of the Active Template Library.
// Copyright (C) Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Active Template Library Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Active Template Library product.
#ifndef __ATLSTDTHUNK_H__
#define __ATLSTDTHUNK_H__
#pragma once
#pragma push_macro("new")
#undef new
#include <atldef.h>
#if !defined(_ATL_USE_WINAPI_FAMILY_DESKTOP_APP)
#error This file is not compatible with the current WINAPI_FAMILY
#endif
#if !defined(USE_ATL_THUNK2) && (defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64))
#define USE_ATL_THUNK2
#endif
#include <atlthunk.h>
namespace ATL
{
/////////////////////////////////////////////////////////////////////////////
// Thunks for __stdcall member functions
#if defined(_M_IX86)
PVOID __stdcall __AllocStdCallThunk(VOID);
VOID  __stdcall __FreeStdCallThunk(_In_opt_ PVOID);
#pragma pack(push,1)
struct _stdcallthunk
{
	DWORD   m_mov;          // mov dword ptr [esp+0x4], pThis (esp+0x4 is hWnd)
	DWORD   m_this;         //
	BYTE    m_jmp;          // jmp WndProc
	DWORD   m_relproc;      // relative jmp
	BOOL Init(
		_In_ DWORD_PTR proc,
		_In_opt_ void* pThis)
	{
		m_mov = 0x042444C7;  //C7 44 24 0C
		m_this = PtrToUlong(pThis);
		m_jmp = 0xe9;
		m_relproc = DWORD((INT_PTR)proc - ((INT_PTR)this+sizeof(_stdcallthunk)));
		// write block from data cache and
		//  flush from instruction cache
		FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk));
		return TRUE;
	}
	//some thunks will dynamically allocate the memory for the code
	void* GetCodeAddress()
	{
		return this;
	}
	_Ret_maybenull_ _Post_writable_byte_size_(sizeof(_stdcallthunk)) void* operator new(_In_ size_t)
	{
        return __AllocStdCallThunk();
    }
    void operator delete(_In_opt_ void* pThunk)
    {
        __FreeStdCallThunk(pThunk);
    }
};
#pragma pack(pop)
#elif defined(_M_X64)
PVOID __stdcall __AllocStdCallThunk(VOID);
VOID  __stdcall __FreeStdCallThunk(PVOID);
#pragma pack(push,2)
struct _stdcallthunk
{
    USHORT  RcxMov;         // mov rcx, pThis
    ULONG64 RcxImm;         //
    USHORT  RaxMov;         // mov rax, target
    ULONG64 RaxImm;         //
    USHORT  RaxJmp;         // jmp target
    BOOL Init(
		_In_ DWORD_PTR proc,
		_In_opt_ void *pThis)
    {
        RcxMov = 0xb948;          // mov rcx, pThis
        RcxImm = (ULONG64)pThis;  //
        RaxMov = 0xb848;          // mov rax, target
        RaxImm = (ULONG64)proc;   //
        RaxJmp = 0xe0ff;          // jmp rax
        FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk));
		return TRUE;
    }
	//some thunks will dynamically allocate the memory for the code
	void* GetCodeAddress()
	{
		return this;
	}
	_Ret_maybenull_ _Post_writable_byte_size_(sizeof(_stdcallthunk)) void* operator new(_In_ size_t)
	{
        return __AllocStdCallThunk();
    }
    void operator delete(_In_opt_ void* pThunk)
    {
        __FreeStdCallThunk(pThunk);
    }
};
#pragma pack(pop)
#elif defined (_M_THUMB)
// note this case must be before _M_ARM because _M_ARM is also defined
PVOID __stdcall __AllocStdCallThunk(VOID);
VOID  __stdcall __FreeStdCallThunk(PVOID);
#pragma pack(push,2)
struct _stdcallthunk
{
	USHORT	m_mov_r0[2];	// mov	r0, pThis
	USHORT	m_mov_pc[2];	// mov	pc, pFunc
	DWORD	m_pThis;
	DWORD	m_pFunc;
	BOOL Init(DWORD_PTR proc, void* pThis)
	{
		m_mov_r0[0] = 0xF8DF;
		m_mov_r0[1] = 0x0004;
 		m_mov_pc[0] = 0xF8DF;
		m_mov_pc[1] = 0xF004;
		m_pThis = (DWORD)pThis;
		m_pFunc = (DWORD)proc;
		// write block from data cache and
		//  flush from instruction cache
		FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk));
		return TRUE;
	}
	void* GetCodeAddress()
	{
		return (void *)((ULONG_PTR)this | 1);
	}
	void* operator new(size_t)
	{
		return __AllocStdCallThunk();
    }
	void operator delete(void* pThunk)
	{
		__FreeStdCallThunk(pThunk);
	}
};
#pragma pack(pop)
#elif defined(_M_ARM64)
PVOID __stdcall __AllocStdCallThunk(VOID);
VOID  __stdcall __FreeStdCallThunk(PVOID);
#pragma pack(push,4)
struct _stdcallthunk {
    ULONG   m_ldr_r16;      // ldr  x16, [pc, #24]
    ULONG   m_ldr_r0;       // ldr  x0, [pc, #12]
    ULONG   m_br;           // br   x16
    ULONG   m_pad;
    ULONG64	m_pThis;
    ULONG64	m_pFunc;
    BOOL Init(DWORD_PTR proc, void* pThis) {
        m_ldr_r16 = 0x580000D0;
        m_ldr_r0 = 0x58000060;
        m_br = 0xd61f0200;
        m_pThis = (ULONG64)pThis;
        m_pFunc = (ULONG64)proc;
        // write block from data cache and
        //  flush from instruction cache
        FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk));
        return TRUE;
    }
    void* GetCodeAddress() {
        return (void *)((ULONG_PTR)this | 1);
    }
    void* operator new(size_t)
    {
        return __AllocStdCallThunk();
    }
    void operator delete(void* pThunk) {
        __FreeStdCallThunk(pThunk);
    }
};
#pragma pack(pop)
#elif defined(_ARM_)
#pragma pack(push,4)
struct _stdcallthunk // this should come out to 16 bytes
{
	DWORD	m_mov_r0;		// mov	r0, pThis
	DWORD	m_mov_pc;		// mov	pc, pFunc
	DWORD	m_pThis;
	DWORD	m_pFunc;
	BOOL Init(
		_In_ DWORD_PTR proc,
		_In_opt_ void* pThis)
	{
		m_mov_r0 = 0xE59F0000;
		m_mov_pc = 0xE59FF000;
		m_pThis = (DWORD)pThis;
		m_pFunc = (DWORD)proc;
		// write block from data cache and
		//  flush from instruction cache
		FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk));
		return TRUE;
	}
	void* GetCodeAddress()
	{
		return this;
	}
};
#pragma pack(pop)
#else
#error Only X86, X64, ARM, and ARM64 supported
#endif
#if defined(_M_IX86) || defined (_M_X64) || defined(_M_ARM)
#pragma pack(push,8)
// avoid ODR violations
#ifdef USE_ATL_THUNK2
typedef class CDynamicStdCallThunk2 CDynamicStdCallThunk; class CDynamicStdCallThunk2
#else
class CDynamicStdCallThunk
#endif
{
public:
#ifdef USE_ATL_THUNK2
	AtlThunkData_t* pThunk;
#else
	_stdcallthunk *pThunk;
#endif
#ifdef USE_ATL_THUNK2
	CDynamicStdCallThunk2()
#else
	CDynamicStdCallThunk()
#endif
	{
		pThunk = NULL;
	}
#ifdef USE_ATL_THUNK2
	~CDynamicStdCallThunk2()
#else
	~CDynamicStdCallThunk()
#endif
	{
		if (pThunk)
		{
#ifdef USE_ATL_THUNK2
			AtlThunk_FreeData(pThunk);
#else
			delete pThunk;
#endif
		}
	}
	BOOL Init(
		_In_ DWORD_PTR proc,
		_In_opt_ void *pThis)
	{
		if (pThunk == NULL)
		{
#ifdef USE_ATL_THUNK2
			pThunk = AtlThunk_AllocateData();
#else
			pThunk = new _stdcallthunk;
#endif
			if (pThunk == NULL)
			{
				return FALSE;
			}
		}
#ifdef USE_ATL_THUNK2
		AtlThunk_InitData(pThunk, (void*)proc, (size_t)pThis);
		return TRUE;
#else
		return pThunk->Init(proc, pThis);
#endif
	}
	void* GetCodeAddress()
	{
#ifdef USE_ATL_THUNK2
		return AtlThunk_DataToCode(pThunk);
#else
		return pThunk->GetCodeAddress();
#endif
	}
};
#pragma pack(pop)
typedef CDynamicStdCallThunk CStdCallThunk;
#else
typedef _stdcallthunk CStdCallThunk;
#endif  // _M_IX86 || _M_X64 || _M_ARM
}   // namespace ATL
#pragma pop_macro("new")
#endif // __ATLSTDTHUNK_H__
												
											_stdcallthunk的更多相关文章
- ATL中窗口句柄与窗口过程的关联方法
		
ATL中采用了一种动态生成机器指令的方式进行窗口句柄与窗口对象进行关联,以是详细分析: CWindowImpl会在第一次调用Create时注册窗口类,该窗口类是的信息是在CWindowImpl的子类中 ...
 - [IE编程] 多页面基于IE内核浏览器的代码示例
		
有不少人发信问这个问题,我把答案贴在这里: 建议参考 WTL (Windows Template Library) 的代码示例工程TabBrowser (在WTL目录/Samples/TabBrow ...
 - ATL Thunk机制深入分析
		
如果你有SDK的编程经验,就一定应该知道在创建窗口时需要指定窗口类,窗口类中的一种重要的参数就是窗口过程.任何窗口接收到的消息,都是由该窗口过程来处理. 在面向对象编程中,如果还需要开发人员来使用原始 ...
 - wtl学习总结
		
在windows平台,相比MFC,我更喜欢WTL,因其简洁漂亮.所以陆续花了一年的时间学习之,这里总结一下(在学习Wtl/Atl之前,最好是对WinApi编程有一定的了解). 安装 Wtl主页 htt ...
 - ATL7窗口类详细剖析
		
前言: ATL是微软继MFC之后提供的一套C++模板类库,小巧.精妙.效率极高.它的主要作用是为我们编写COM/DOM/COM+程序提供了丰富的支持.但是ATL只能写COM么?我以前只是MFC程序员的 ...
 - 深入解析Windows窗体创建和消息分发
		
Windows GUI採用基于事件驱动的编程模型,其实差点儿全部的界面库都是这样做的.在纯粹的Window32 SDK编程时代.人们还能够搞懂整个Windows窗口创建和消息的流通过程.可是在如今各种 ...
 - 深入解析Windows窗口创建和消息分发(三个核心问题:怎么将不同的窗口过程勾到一起,将不同的hwnd消息分发给对应的CWnd类去处理,CWnd如何简单有效的去处理消息,由浅入深,非常清楚) good
		
笔记:争取不用看下面的内容,只看自己的笔记,就能记住这个流程,就算明白了: _tWinMain-->AfxWinMain,它调用四个函数: -->AfxWinInit用于做一些框架的初始化 ...
 
随机推荐
- 【函数】wm_concat包的订制
			
[函数]wm_concat包的订制 1 BLOG文档结构图 2 前言部分 2.1 导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道 ...
 - vue v-show无法动态更新的问题
			
本人之前学过angularJS,记得v-for绑定的数组,只要切换v-if = ''item.show'' 只要改变相关的值,就可以对应的值,视图就会重新渲染,但是在vue中却不灵了,找到答案了,需要 ...
 - idea上maven打包
			
首先要实现maven打包,pom需要引入依赖 pom.xml <project> <dependencies> …… </dependencies> <bui ...
 - yum仓库的部署
			
https://segmentfault.com/a/1190000013968371 私有yum仓库在企业中的应用还是比较广泛,有方便.快捷.灵活等优势.如某公司安全部门不允许大批量的主机连接互联网 ...
 - js 变量以及函数传参
			
一.变量: 基本类型是变量对象重新创建一个新值给变量对象空间,虽然是同一个值但是互不影响. 引用类型是也是将一个值重新赋值给新的变量空间,但是这个值是堆中对象的一个指针,新的变量和旧的变量指向是同一个 ...
 - Linux——配置maven
			
前言 Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(De ...
 - HBase应用
			
太多column family的影响 每个 MemoryStore分配到的内存较少,进而导致过多的合并,影响性能 几个column family比较合适呢 推荐是:1-3个 划分column fa ...
 - WebService(一)
			
最近一段时间研究webservice,一般来说,开发java的Webservice经常使用axis2和cxf这两个比较流行的框架 先使用cxf,开发一个完整示例,方便对webservice有一个整体的 ...
 - shell脚本 基础应用
			
变量分为普通变量可只读变量 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ...
 - 洛谷 P2512 [HAOI2008]糖果传递 题解
			
每日一题 day47 打卡 Analysis 首先,最终每个小朋友的糖果数量可以计算出来,等于糖果总数除以n,用ave表示. 假设标号为i的小朋友开始有Ai颗糖果,Xi表示第i个小朋友给了第i-1个小 ...