热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

类里面强制调用回调函数

OptionExplicit-CallbackdeclarationsforPaulCatonthunkingmagic------------------------------
Option Explicit


'-Callback declarations for Paul Caton thunking magic----------------------------------------------
Private z_CbMem As Long 'Callback allocated memory address
Private z_Cb() As Long 'Callback thunk array
Private Declare Function GetModuleHandleA Lib "kernel32" (ByVal lpModuleName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function IsBadCodePtr Lib "kernel32" (ByVal lpfn As Long) As Long
Private Declare Function VirtualAlloc Lib "kernel32" (ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Declare Function VirtualFree Lib "kernel32" (ByVal lpAddress As Long, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
Private Declare Sub RtlMoveMemory Lib "kernel32" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Long)
'-------------------------------------------------------------------------------------------------
Private s$, I&
Property Let Name(ByVal nm As String)
s
= Trim(nm)
End Property
Property Get Name() As String
Name
= s
End Property
Property Let id(ByVal aa As Long)
I
= aa
End Property
Property Get id() As Long
id
= I
End Property

'-Callback code-----------------------------------------------------------------------------------
Public Function zb_AddressOf(ByVal nOrdinal As Long, _
ByVal nParamCount As Long, _
Optional ByVal nThunkNo As Long = 0, _
Optional ByVal oCallback As Object = Nothing, _
Optional ByVal bIdeSafety As Boolean = True) As Long 'Return the address of the specified callback thunk
'
*************************************************************************************************
'
* nOrdinal - Callback ordinal number, the final private method is ordinal 1, the second last is ordinal 2, etc...
'
* nParamCount - The number of parameters that will callback
'
* nThunkNo - Optional, allows multiple simultaneous callbacks by referencing different thunks... adjust the MAX_THUNKS Const if you need to use more than two thunks simultaneously
'
* oCallback - Optional, the object that will receive the callback. If undefined, callbacks are sent to this object's instance
'
* bIdeSafety - Optional, set to false to disable IDE protection.
'
*************************************************************************************************
Const MAX_FUNKS As Long = 1 'Number of simultaneous thunks, adjust to taste
Const FUNK_LONGS As Long = 22 'Number of Longs in the thunk
Const FUNK_LEN As Long = FUNK_LONGS * 4 'Bytes in a thunk
Const MEM_LEN As Long = MAX_FUNKS * FUNK_LEN 'Memory bytes required for the callback thunk
Const PAGE_RWX As Long = &H40& 'Allocate executable memory
Const MEM_COMMIT As Long = &H1000& 'Commit allocated memory
Dim nAddr As Long

If nThunkNo <0 Or nThunkNo > (MAX_FUNKS - 1) Then
MsgBox "nThunkNo doesn't exist.", vbCritical + vbApplicationModal, "Error in " & TypeName(Me) & ".cb_Callback"
Exit Function
End If

If oCallback Is Nothing Then 'If the user hasn't specified the callback owner
Set oCallback = Me 'Then it is me
End If

nAddr
= zAddressOf(oCallback, nOrdinal) 'Get the callback address of the specified ordinal
If nAddr = 0 Then
MsgBox "Callback address not found.", vbCritical + vbApplicationModal, "Error in " & TypeName(Me) & ".cb_Callback"
Exit Function
End If

If z_CbMem = 0 Then 'If memory hasn't been allocated
ReDim z_Cb(0 To FUNK_LONGS - 1, 0 To MAX_FUNKS - 1) As Long 'Create the machine-code array
z_CbMem = VirtualAlloc(z_CbMem, MEM_LEN, MEM_COMMIT, PAGE_RWX) 'Allocate executable memory
End If

If z_Cb(0, nThunkNo) = 0 Then 'If this ThunkNo hasn't been initialized...
z_Cb(3, nThunkNo) = _
GetProcAddress(GetModuleHandleA(
"kernel32"), "IsBadCodePtr")
z_Cb(
4, nThunkNo) = &HBB60E089
z_Cb(
5, nThunkNo) = VarPtr(z_Cb(0, nThunkNo)) 'Set the data address
z_Cb(6, nThunkNo) = &H73FFC589: z_Cb(7, nThunkNo) = &HC53FF04: z_Cb(8, nThunkNo) = &H7B831F75: z_Cb(9, nThunkNo) = &H20750008: z_Cb(10, nThunkNo) = &HE883E889: z_Cb(11, nThunkNo) = &HB9905004: z_Cb(13, nThunkNo) = &H74FF06E3: z_Cb(14, nThunkNo) = &HFAE2008D: z_Cb(15, nThunkNo) = &H53FF33FF: z_Cb(16, nThunkNo) = &HC2906104: z_Cb(18, nThunkNo) = &H830853FF: z_Cb(19, nThunkNo) = &HD87401F8: z_Cb(20, nThunkNo) = &H4589C031: z_Cb(21, nThunkNo) = &HEAEBFC
End If

z_Cb(
0, nThunkNo) = ObjPtr(oCallback) 'Set the Owner
z_Cb(1, nThunkNo) = nAddr 'Set the callback address

If bIdeSafety Then 'If the user wants IDE protection
z_Cb(2, nThunkNo) = GetProcAddress(GetModuleHandleA("vba6"), "EbMode") 'EbMode Address
End If

z_Cb(
12, nThunkNo) = nParamCount 'Set the parameter count
z_Cb(17, nThunkNo) = nParamCount * 4 'Set the number of stck bytes to release on thunk return

nAddr
= z_CbMem + (nThunkNo * FUNK_LEN) 'Calculate where in the allocated memory to copy the thunk
RtlMoveMemory nAddr, VarPtr(z_Cb(0, nThunkNo)), FUNK_LEN 'Copy thunk code to executable memory
zb_AddressOf = nAddr + 16 'Thunk code start address
End Function

'Return the address of the specified ordinal method on the oCallback object, 1 = last private method, 2 = second last private method, etc
Private Function zAddressOf(ByVal oCallback As Object, ByVal nOrdinal As Long) As Long
Dim bSub As Byte 'Value we expect to find pointed at by a vTable method entry
Dim bVal As Byte
Dim nAddr As Long 'Address of the vTable
Dim I As Long 'Loop index
Dim J As Long 'Loop limit

RtlMoveMemory VarPtr(nAddr), ObjPtr(oCallback),
4 'Get the address of the callback object's instance
If Not zProbe(nAddr + &H1C, I, bSub) Then 'Probe for a Class method
If Not zProbe(nAddr + &H6F8, I, bSub) Then 'Probe for a Form method
If Not zProbe(nAddr + &H7A4, I, bSub) Then 'Probe for a UserControl method
Exit Function 'Bail...
End If
End If
End If

I
= I + 4 'Bump to the next entry
J = I + 1024 'Set a reasonable limit, scan 256 vTable entries
Do While I < J
RtlMoveMemory VarPtr(nAddr), I,
4 'Get the address stored in this vTable entry

If IsBadCodePtr(nAddr) Then 'Is the entry an invalid code address?
RtlMoveMemory VarPtr(zAddressOf), I - (nOrdinal * 4), 4 'Return the specified vTable entry address
Exit Do 'Bad method signature, quit loop
End If

RtlMoveMemory VarPtr(bVal), nAddr,
1 'Get the byte pointed to by the vTable entry
If bVal <> bSub Then 'If the byte doesn't match the expected value...
RtlMoveMemory VarPtr(zAddressOf), I - (nOrdinal * 4), 4 'Return the specified vTable entry address
Exit Do 'Bad method signature, quit loop
End If

I
= I + 4 'Next vTable entry
Loop
End Function

'Probe at the specified start address for a method signature
Private Function zProbe(ByVal nStart As Long, ByRef nMethod As Long, ByRef bSub As Byte) As Boolean
Dim bVal As Byte
Dim nAddr As Long
Dim nLimit As Long
Dim nEntry As Long

nAddr
= nStart 'Start address
nLimit = nAddr + 32 'Probe eight entries
Do While nAddr 'While we've not reached our probe depth
RtlMoveMemory VarPtr(nEntry), nAddr, 4 'Get the vTable entry

If nEntry <> 0 Then 'If not an implemented interface
RtlMoveMemory VarPtr(bVal), nEntry, 1 'Get the value pointed at by the vTable entry
If bVal = &H33 Or bVal = &HE9 Then 'Check for a native or pcode method signature
nMethod = nAddr 'Store the vTable entry
bSub = bVal 'Store the found method signature
zProbe = True 'Indicate success
Exit Function 'Return
End If
End If

nAddr
= nAddr + 4 'Next vTable entry
Loop
End Function
Private Function TimerProc3(Elem1 As student, _
Elem2
As student, _
unused1
As Long, _
unused2
As Long) As Integer
Debug.Print
"TimerProc3"
End Function
Private Function TimerProc2(Elem1 As student, _
Elem2
As student, _
unused1
As Long, _
unused2
As Long) As Integer
Debug.Print
"TimerProc2"
End Function
Private Function TimerProc(Elem1 As student, _
Elem2
As student, _
unused1
As Long, _
unused2
As Long) As Integer
Debug.Print
"TimerProc"
End Function
Option Explicit

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Declare Function Compare Lib "user32" Alias _
"CallWindowProcA" (ByVal pfnCompare As Long, ByVal pElem1 As Long, _
ByVal pElem2 As Long, ByVal unused1 As Long, _
ByVal unused2 As Long) As Integer

Sub e1()
Dim arr(2) As student
Set arr(0) = New student
Set arr(1) = New student
Set arr(2) = New student
arr(
0).id = 3
arr(
1).id = 2
'Call SwapStrPtr2(VarPtr(arr(0)), VarPtr(arr(1)))
arr(2).id = 1

Call qsort(VarPtr(arr(0)), UBound(arr) + 1, 4, arr(0).zb_AddressOf(3, 4))
End Sub

Sub e3()
Dim arr(2) As Long
arr(
0) = 3
arr(
1) = 2
Call SwapStrPtr2(VarPtr(arr(0)), VarPtr(arr(1)))
End Sub

Sub e4()
Dim s As New student

End Sub
Sub qsort(ByVal ArrayPtr As Long, ByVal nCount As Long, ByVal nElemSize As Integer, ByVal pfnCompare As Long)
Dim I As Long, J As Long

For I = 1 To nCount
For J = I + 1 To nCount
'这里省略快速排序算法的具体实现,仅给出比较两个元素的方法。
If Compare(pfnCompare, ArrayPtr + (I - 1) * nElemSize, _
ArrayPtr
+ (J - 1) * nElemSize, 0, 0) > 0 Then
'如果第i个元素比第j个元素大则用CopyMemory来交换这两个元素。
Call SwapStrPtr2(ArrayPtr + (I - 1) * nElemSize, ArrayPtr + (J - 1) * nElemSize)
End If
Next
Next
End Sub

Sub SwapStrPtr3(sA As student, sB As student)
Dim temp As Object
CopyMemory temp,
ByVal VarPtr(sA), 4
CopyMemory
ByVal VarPtr(sA), ByVal VarPtr(sB), 4
CopyMemory
ByVal VarPtr(sB), temp, 4
End Sub
Sub SwapStrPtr2(sA As Long, sB As Long)
Dim lTmp As Variant
Dim pTmp As Long
pTmp
= VarPtr(lTmp)
CopyMemory pTmp,
ByVal sA, 4
CopyMemory
ByVal sA, ByVal sB, 4
CopyMemory
ByVal sB, pTmp, 4
End Sub

 


推荐阅读
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • IB 物理真题解析:比潜热、理想气体的应用
    本文是对2017年IB物理试卷paper 2中一道涉及比潜热、理想气体和功率的大题进行解析。题目涉及液氧蒸发成氧气的过程,讲解了液氧和氧气分子的结构以及蒸发后分子之间的作用力变化。同时,文章也给出了解题技巧,建议根据得分点的数量来合理分配答题时间。最后,文章提供了答案解析,标注了每个得分点的位置。 ... [详细]
  • 怀疑是每次都在新建文件,具体代码如下 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 展开全部下面的代码是创建一个立方体Thisexamplescreatesanddisplaysasimplebox.#Thefirstlineloadstheinit_disp ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文讨论了如何在codeigniter中识别来自angularjs的请求,并提供了两种方法的代码示例。作者尝试了$this->input->is_ajax_request()和自定义函数is_ajax(),但都没有成功。最后,作者展示了一个ajax请求的示例代码。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 怎么在PHP项目中实现一个HTTP断点续传功能发布时间:2021-01-1916:26:06来源:亿速云阅读:96作者:Le ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
author-avatar
雙子座的魚love
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有