|
马上加入TC
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
本帖最后由 rainshine 于 2014-8-17 11:56 编辑
这次的源码是限制鼠标在一个矩形范围内移动,参数是一个结构体指针。http://www.c2014.cc,www.rblog.cc,欢迎。
那么tc怎么搞定这个结构体呢?其实只要懂得结构体内存对齐之后 其他的就是分配内存和写内存就行了、
我尽量说得像人话哈。------建议你有点c/c++基础再看。
一个结构体狭义地说就是几个变量凑在一块,比如呢个RECT structure,在msdn的解释是这样滴,http://msdn.microsoft.com/en-us/library/dd162897(VS.85).aspx。可以看到他的原型是
typedef struct _RECT { LONG left; LONG top; LONG right; LONG bottom;} RECT, *PRECT;
那么这个结构体在内存中就体现为4个4字节(long算4bytes)变量,连着的哦。也就是说,我们调用api的时候让你传进去一个结构体的指针,那么这个指针指向的内存区域应该有4*4一共16个字节,首四字节存放的是left成员变量的值,第二个四字节存放的就是top的值,第三个四字节存放的就是right,最后四个字节存放的是bottom(中文:底)。这是个比较简单的结构体,成员类型都一样,无需考虑对齐的问题,那么复杂点的结构体默认如何对齐呢,可以参考如下三个原则(ps:sizeof(结构体类型)函数可以直接得到其总大小):
•原则1、数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。
•原则2、结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储。)
•原则3、收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。
==so,那么我们只需要在内存里模拟出来这个结构体就完事了。分配16字节的内存,然后分别偏移0,4,8,12,写4字节整型变量即可。这就需要用到分配内存、写内存的函数,分配先不说了,globalalloc(0,dwsize),globalfree(hMem)可以很方便地分配内存(ps:对于巨大量的数据不推荐使用此函数分配【固定】内存)。
那么写内存怎么办呢。tcapi木有,难道要用插件么!不,这不是rain的风格0.0。那么找到写内存的winapi,WriteProcessMemory,msdn:http://msdn.microsoft.com/en-us/library/aa909195.aspx。
我们可以看到他的函数原型,我一个一个解释参数。
hProcess,int,进程句柄,自己的进程写-1。
lpBaseAddress,int,要写入的内存区域首地址,globalalloc(0,size)返回值。
lpBuffer,int,待写入的数据【指针】,nSize,int,要写入多长。
lpNumberOfBytesWritten,int,指针,返回实际写入的字节数,可NULL忽略。
现在问题来了,待写入的数据要传进去指针,但是tc不支持传整型的地址。肿么办呢,解决方案总是有的。不支持整型,支持字符串吧!那咱们就用字符串实现。先解释一下,不管什么类型,在内存里都是一位一位,一个字节一个字节地存储。所以咱们只需要自己制造一个神奇的字符串,让它在内存中存储的每个字节跟我们需要的整型数是一样的不就得了!然后dllcall writeprocessmem,lpBuffer类型写char *或者wchar *,这样就能让lpBuffer传进去字符串的首地址(指针)!那么函数就会把字符串写进去,实际上写的是我们需要的整型数。
这里还有一点需要注意的是,tc的dllcall在传字符串指针的时候,支持把字符串转成ANSI或UNICODE两种编码方式。ANSI在内存中,每个字符占一个字节,而UNICODE每个字符占2个字节。所以unicode写一个字符实际上是占两个字节的。一个字符就能顶两个字节,so,我选择用unicode,比ansi用更少的代码实现同样的操作。好了,现在就剩下一个问题,如何拼凑这个神奇的字符串,我结合源码解释。
function write4byte2(lpBuffer,iData)
hiword=type.int(iData/65536)
loword=iData%65536
temp.WriteProcessMemoryW(-1,lpBuffer,str.format("%c%c",loword,hiword),4)
endfunction
这里我把一个int看作dword型,然后把它的hiword(高16位),loword(低16位)取出来。因为每个word在内存中就是占2个字节的大小,正好符合unicode一个字符的大小。所以我们分别把hiword和loword格式化成一个unicode字符,然后拼成一个字符串,这就ok啦。这个字符串在内存中就体现为4个字节的一块小区域,以int方式都出来就是我们刚写入的整型数。
接着,调用writeprocessmem函数,lpBuffer类型为:wchar *,数据就是那个格式化完的字符串。
终于差不多讲完了0.0,我感觉我的世界观要崩溃了,这些概念乱七八糟的都很难理解,特别是很难表达出来,而且还要表达的让地球人能看懂。。。
==
那么,知道了如何写到内存一个整型数据,现在把四个整型数据连着写,做成一个结构体的样子。然后传给windowsapi函数,参数就写上这四个整形数据的首地址……搞定。。
说了这么多理论神马的,我觉得还是看看源码、结合源码学习比较容易理解。好的那么源码时间到!!!啦啦啦。另外。。我再插句话,这里边还有个方法写int,一个字节一个字节地填充,有兴趣的可以研究一下。我就不解释了。获取其他【本源码】信息请移步:http://rblog.cc/archives/987。
小广告:http://www.c2014.cc,www.rblog.cc,期待您的访问。
看在我花了一上午的时间弄这个源码,和纯手打这么些字,,神(da)啊(jia)给我点回复吧,神(da)啊(jia)给我点金币威望吧!
链接: http://pan.baidu.com/s/1i3vGrYX 密码:
|
评分
-
查看全部评分
|