最近在改这样一个代码,但是有些地方不解,求教!代码名称:Call API functions by Name
下载地址:http://www.freevbcode.com/ShowCode.asp?ID=18631、下面这个函数,将CALL &h12345678 添加到汇编代码数组,为什么要在地址上- VarPtr(m_abCode(m_lCP)) - 4?
Private Sub AddCallToCode(ByVal dwAddress As Long)
AddByteToCode &HE8
AddLongToCode dwAddress - VarPtr(m_abCode(m_lCP)) - 4
End Sub
2、下面这个函数中m_lParameters(i) = CLng(FuncParams(i - 1))一句,是如何运行的?明显的FuncParams的每一个元素都是变体,那么对变体执行CLNG函数的效果……难道说是引用类型时,VB6的CLNG函数会返回这个引用类型的内存首地址,而非引用类型时才是我们熟悉的CLNG?头疼!
3、下面函数中, ReDim m_abCode()时,为什么是18 + 32 + 6 * UBound(m_lParameters)?依据是什么啊?
Public Function CallFunction(ParamArray FuncParams()) As Long
Dim i As Long
If m_lpFn = 0 Then
MsgBox "Function not defined!", vbCritical, "Call function error"
Exit Function
End If
ReDim m_abCode(0)
ReDim m_lParameters(UBound(FuncParams) + 1)
ReDim m_abCode(18 + 32 + 6 * UBound(m_lParameters))
For i = 1 To UBound(m_lParameters)
m_lParameters(i) = CLng(FuncParams(i - 1))
Next i
CallFunction = CallWindowProc(PrepareCode, 0, 0, 0, 0)
m_lpFn = 0
End Function
以上……………………
下载地址:http://www.freevbcode.com/ShowCode.asp?ID=18631、下面这个函数,将CALL &h12345678 添加到汇编代码数组,为什么要在地址上- VarPtr(m_abCode(m_lCP)) - 4?
Private Sub AddCallToCode(ByVal dwAddress As Long)
AddByteToCode &HE8
AddLongToCode dwAddress - VarPtr(m_abCode(m_lCP)) - 4
End Sub
2、下面这个函数中m_lParameters(i) = CLng(FuncParams(i - 1))一句,是如何运行的?明显的FuncParams的每一个元素都是变体,那么对变体执行CLNG函数的效果……难道说是引用类型时,VB6的CLNG函数会返回这个引用类型的内存首地址,而非引用类型时才是我们熟悉的CLNG?头疼!
3、下面函数中, ReDim m_abCode()时,为什么是18 + 32 + 6 * UBound(m_lParameters)?依据是什么啊?
Public Function CallFunction(ParamArray FuncParams()) As Long
Dim i As Long
If m_lpFn = 0 Then
MsgBox "Function not defined!", vbCritical, "Call function error"
Exit Function
End If
ReDim m_abCode(0)
ReDim m_lParameters(UBound(FuncParams) + 1)
ReDim m_abCode(18 + 32 + 6 * UBound(m_lParameters))
For i = 1 To UBound(m_lParameters)
m_lParameters(i) = CLng(FuncParams(i - 1))
Next i
CallFunction = CallWindowProc(PrepareCode, 0, 0, 0, 0)
m_lpFn = 0
End Function
以上……………………
解决方案 »
- 请问:VB6.0下水晶报表如何动态连接数据源?
- 救命啊 为什么我在form_load里面向picturebox画图无效
- 求一个SQL语句
- 如何让DBGrid控件显示指定的数据
- 寻求一个代码!!
- Webbrowser 缺失对象,确定后无法继续执行代码
- 关于程序打包的问题
- 谁用过lotus screencam做过演示盘?或者什么工具作演示盘比较好
- 谁有最新的邮件巡捕的注册版,我这里有600分,全部赠送!!
- 50分大放送!!http://www.csdn.net/expert/Topic/476/476550.shtm!!(这20分照给)。急!!
- List1列表的保存和读取
- 这样子来判断目录和文件,能不能办到???很复杂!
这个回答我还需要详细问一下,嘿嘿,我比较愚昧……BYTES里面放的就是汇编代码了吧,传入的第一个参数就是这个数组,数组里面的CALL 不是直接调用函数地址吗?为什么还会偏移啊……例如说,要调用SetWindowTextA那么
Dim s() As Byte, x As Long, y As Long
s = StrConv("Hello !", vbFromUnicode)
b = 15
x = CallApiByName("user32", "SetWindowTextA", hwnd, VarPtr(s(0)))
它的入口是:
77D2F56B
而我输出汇编代码数组,得到的却是CC
CC
CC
CC
CC
CC
CC
CC
58
59
59
59
59
50
68
90
72
15
0
68
42
B
9
0
E8
A6
7C
BD
77
0前面的CC不用管了,给调试器用的吧。
58
59
59
59
59
50
就是清栈并设置运行位置,对CallWindowProc作用的。后面的才是真正的调用SetWindowTextA的代码
68
90
72
15
0
68
42
B
9
0
68是对齐代码为4字节指令,忽略。。第二个参数在前,也就是说Hello !这个字符串所在内存地址了吧。第一个参数就是窗口句柄。
接下来的代码就是我不明白的了
E8
A6
7C
BD
77
E8是CALL这应该没问题后面的呢?就是地址吧。77BD7CA6这个地址就是第一个问题那个函数得到的。用这样一段代码输出他们:
Form1.Text1.Text = Hex(lngAddress)
Form1.Text2.Text = Hex(VarPtr(mbytCode(mlngCP)))
Form1.Text3.Text = Hex(lngAddress - VarPtr(mbytCode(mlngCP)) - 4)
得到的分别是77D2F56B
1578C5
77BD7CA2第一行那是函数地址,直接调用不行吗。。那么怎么转换的啊依据是啥啊。。头都大了。
E8
A6
7C
BD
77
E8是CALL这应该没问题后面的呢?就是地址吧。
为什么是77BD7CA6
而不是77D2F56B呢?俺想应该是
E8
6B
F5
D2
77
才是CALL SetWindowTextA吧。
比如我用w32dasm反编译了c:\windows\hh.exe,在导入wsprintfA那里看见有这样的一段代码:01001241 E8 41 02 00 00 call 01001487
:01001487 3B 0D 42 00 01 cmp ecx, dword ptr [01002004]而0x01001487 - 0x01001241 - 5 = 0x241
所以被调用函数地址计算公式就是"call语句所在地址(上面是0x01001241) + 32位偏移地址(上面是0x241) + 5",就是说如果要求"32位偏移地址",那么就要这样来求:被调用函数地址-call语句所在地址-5而代码里面在执行AddByteToCode &HE8之前VarPtr(mbytCode(mlngCP))就正好是"call语句所在地址",但是加了E8这个字节之后地址指针被向后移动了一个字节,所以后面应该是-4不是-5,于是"lngAddress - VarPtr(mbytCode(mlngCP)) - 4"就应该是要call的"32位偏移地址"了......
昨天晚上睡不着,想了想,今天又翻出来一些CE,OLG什么的搞了一下,说明楼上的说法确实是对的,之所以用相对地址是因为前面是E8,参考INTER 的80X86汇编手册看了一下,还有F2,9A,FF什么什么的,那些是用绝对地址。
其实啊,我是用VB.NET写代码,参考人家的VB6代码,这会儿算基本竣工了测试了SetWindowTextA、FlashWindow、GetWindowTextA、LoadLibraryA这几个函数。就是说只有返回值、传入返回值、返回返回值什么什么的类型都正常运行了。第三个问题不问了估摸就是按代码可能最大长度计算的,由于.NET调用时封装的一些问题,所以直接固定了这个长度为1024字节。不考虑了。。
最后还发现一个怪事,在VISTA环境下,VB6的代码能运行,但是我写的.NET代码不行,会出现非法写入内存的问题。可能需要权限提升吧,模块在笔记本上放着,懒得测试了也很可能是别的问题,以后有时间在深究吧。在XP下两个代码就都行了。
结贴了