xiaoguozi's Blog
Pay it forword - 我并不觉的自豪,我所尝试的事情都失败了······习惯原本生活的人不容易改变,就算现状很糟,他们也很难改变,在过程中,他们还是放弃了······他们一放弃,大家就都是输家······让爱传出去,很困难,也无法预料,人们需要更细心的观察别人,要随时注意才能保护别人,因为他们未必知道自己要什么·····
这两天主要看了flex的cairngorm框架,顺便写了个用flex获取flickr网站的图片,其中不乏艰难的过程,第一个就是flickr库api和实际编译出来的有出入,其中Photo.as缺少farm就是一个明显,所以只能自己手工修改源码重新编译,网上讨论这个问题的比较少,不知道为什么,我找了好久才找到一篇关于这个的。还有一个问题就是大墙,其中网上有段这么描述:
最 近打开Flickr发现有些图片总是显示小红叉,开始以为是网速问题没有在意,昨天有个朋友说他存在Flickr上的图片都不能显示了,发觉情况不对劲 了。
今天看到了这篇帖子:
http://www.flickr.com/help/forum/zh-hk/117995/
原来又是伟大的墙在作怪,这次的症状是所有的网通线路都无法 访问farm3.static.flickr.com和farm5.static.flickr.com这两个服务器,由于这次只是让域名无法解析,所以 最简单的解决办法是修改host文件,方法如下:
用记事本打开C:\Windows\System32\drivers\etc\hosts 这个文件,然后在文件最后追加两行:

然 后重启一下浏览器,我们亲爱的Flickr又复活了  : )

由于自己是网通的,图片是farm5服务器的,所以图片也显示不了,不过修改下host表就OK了

写这个的主要目的还是学习下cairgorm框架,学习他的MVC思想,目的算基本达到,flickr的问题实在有点烦,不过还是走过来了,下面是运行效果:


有用的几个网址:
http://code.google.com/p/as3flickrlib/issues/detail?id=14#makechanges
http://www.flickr.com/services/api/
http://naramiki.blogbus.com/logs/57133710.html

最后附上flickr自己编译的库
http://www.cppblog.com/Files/guojingjia2006/flickr087.swc.rar

posted @ 2010-07-20 22:10 小果子 阅读(524) | 评论 (0)编辑 收藏

 

左通过栈传递,被调用的函数在返回前清理传送参数的内存栈,但不同的 是函数名的修饰部分(关于函数名的修饰部分在后面将详细说明)。

_stdcall
Pascal程序的缺省调用方式,通常用于Win32 Api中,函数采用从右到左 的压栈方式,自己在退出时清空堆栈。VC将函数编译后会在函数名前面加上下划线前缀,在函数名后加上"@"和参数的字节数。


2
C调 用约定(即用__cdecl关键字说明)按从右至左的顺序压参数入栈,由调用者把参数弹出栈。对于传送参数的内存栈是由调用者来维护的(正因为如此,实现可变参数的函数只 能使用该调用约定)。另外,在函数名修饰约定方面也有所不同。


_cdecl
CC++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所 以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。VC将函数编译后会在函数名前面加上下划线前缀。是MFC缺省调用约定。


3
__fastcall调用约定是“人”如其名,它的主要特点就是快,因为它是通过寄存器来传送参数的(实际上,它用ECXEDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送,被调用的函数在返 回前清理传送参数的内存栈),在函数名修饰约定方面,它和前两者均不同。


_fastcall
方式的函数采用寄存器传递参数,VC将函数编译后会在函数名前面加上"@"前缀,在函数名后加上"@"和参数的字节数。


4
thiscall仅仅应用于“C++”成员函数。this指针存放于CX寄存器,参数从右到左压。thiscall不是关键词,因此不能被程序员指定。


5
naked call采用1-4的调用约定时,如果必要的话,进入函数时编译器会产生代码来保存ESIEDIEBXEBP寄存器,退出函数时则产生代码恢复这些寄存器的内容。naked call不产生这样的代码。naked call不是类型修饰符,故 必须和_declspec共同使用。


关键字 __stdcall__cdecl__fastcall可以直接加在要输出的函数前,也可以在编译环境的Setting...\C/C++ \Code Generation项选择。当加在输出函数前的关键字与编译环境中的选择不同时,直接加在输出函数前的关键字有效。它们对应的命令行参数分别为/Gz/Gd/Gr。缺省状态为/Gd,即__cdecl


要完全模仿PASCAL调用约定首先必须使用__stdcall调用约定,至于函数名修饰约定,可以通过其它方法模仿。还有一个值得 一提的是WINAPI宏,Windows.h支持该宏,它可以将出函数翻译成适当的调用约定,在WIN32中,它被定义为__stdcall。使用WINAPI宏可以创建自己的APIs


2)
名字修饰约定


1
、修饰名
(Decoration name)

C”或者“C++”函数在内部(编译和链接)通过修饰名识别。修饰名是编译器在编译函 数定义或者原型时生成的字符串。有些情况下使用函数的修饰名是必要的,如在模块定义文件里头指定输出“C++”重载函数、构造函数、析构函数,又如在汇编代码里调用“C””或“C++”函数等。


修饰名由函数名、类名、调用约定、返回类型、参数等共同决定。


2
、名字修饰约定随调用约定和编译种类(CC++)的不同而变化。函数名修饰约定随编译种类和调用约定的不同而不同,下 面分别说明。


a
C编译时函数名修饰约定规则:


__stdcall
调用约定在输出函数名前加上一个下划线前缀,后面加上一个“@”符号和其参数的字节数,格式为_functionname@number


__cdecl
调用约定仅在输出函数名前加上一个下划线前缀,格式为_functionname


__fastcall
调用约定在输出函数名前加上一个“@”符号,后面也是一个“@”符号和其参数的字节数,格式为@functionname@number


它们均不改变输出函数名中的字符大小写,这和PASCAL调用约定不同,PASCAL约定输出的函数名无任何修饰且全部大写。


b
C++编 译时函数名修饰约定规则:


__stdcall
调用约定:

1
、 以“?”标识函数 名的开始,后跟函数名;

2
、函数名后面以“@@YG”标识参数表的开始,后跟参数表;

3
、 参数表以代号表示:

X--void

D--char

E--unsigned char

F--short

H--int

I--unsigned int

J--long

K--unsigned long

M--float

N--double

_N--bool

....
PA--
表示指 针,后面的代号表明指针类型,如果相同类型的指针连续出现,以“0”代替,一个“0”代表一次重复;

4
、 参数表的第一项为该函数的返回值类型,其后依次为参数的数据类型,指针标识在其所指数据类型前;

5
、 参数表后以“@Z” 标识整个名字的结束,如果该函数无参数,则以“Z”标识结束。


其格式为“?functionname@@YG*****@Z”或“?functionname@@YG*XZ”,例如

int Test1
char *var1,unsigned long-----?Test1@@YGHPADK@Z

void Test2
() -----?Test2@@YGXXZ


__cdecl
调用约定:

规 则同上面的_stdcall调用约定,只是参数表的开始标识由上面的“@@YG”变为“@@YA”。


__fastcall
调用约定:

规 则同上面的_stdcall调用约定,只是参数表的开始标识由上面的“@@YG”变为“@@YI”。


VC++
对函数的省缺声明是"__cedcl",将只能被C/C++调用
.

CB
在输出函数声明时使用4种修饰符号

//__cdecl
cb
的默认值,它会在输出函数名前加_,并保留此函数名不变,参数按照从右到左的顺序依次传递给栈,也可以写 成_cdeclcdecl形式。

//__fastcall
她修饰的函数的参 数将尽肯呢感地使用寄存器来处理,其函数名前加@,参数按照从左到右的顺序压栈;

//__pascal
它说明的函数名使 用Pascal格 式的命名约定。这时函数名全部大写。参数按照从左到右的顺序压栈;

//__stdcall
使用标准约定的函 数名。函数名不会改变。使用__stdcall修饰时。参数按照由右到左的顺序压栈,也可以是_stdcall


TITLE  : __stdcall与__cdecl的区别
AUTHOR : lionel@nkbbs.org
DATE   : 
01/10/2005

CONTENT:

    Visual C
++ Compiler Options可以指定的Calling Convention有 3种:
   
    
/Gd /Gr /Gz
   
    这三个参数决定了:
   
    
1.函数参数以何种顺序入栈,右到左还是左到右。
    
2.在函数运行完后,是调用函数还是被调用函数清理入栈的参数。
    
3.在编译时函数名字是如何转换的。
   
    下面我们分别详细介绍:
   
    
1./Gd
        这是编译器默认的转换模式,对一般函数使用 C的函数调用转换方式__cdecl,
        但是对于C
++ 成员函数和前面修饰了__stdcall __fastcall的函数除外。
       
    
2./Gr
        对于一般函数使用__fastcall函数调用转换方式,所有使用__fastcall的函数
        必须要有函数原形。但对于C
++ 成员函数和前面修饰了__cdecl __stdcall 的
        函数除外。
       
    
3./Gz
        对于所有 C函数使用__stdcall函数调用转换方式,但对于可变参数的 C函数以
        及用__cdecl __fastcall修饰过的函数和C
++ 成员函数除外。所有用__stdcall
        修饰的函数必须有函数原形。
       
        事实上,对于x86系统,C
++ 成员函数的调用方式有点特别,将成员函数的this
        指针放入ECX,所有函数参数从右向左入栈,被调用的成员函数负责清理入栈的
        参数。对于可变参数的成员函数,始终使用__cdecl的转换方式。
       
    下面该进入主题,分别讲一下这三种函数调用转换方式有什么区别:
   
    
1.__cdecl
        这是编译器默认的函数调用转换方式,它可以处理可变参数的函数调用。参数
        的入栈顺序是从右向左。在函数运行结束后,由调用函数负责清理入栈的参数。
        在编译时,在每个函数前面加上下划线(_),没有函数名大小写的转换。即
       
          _functionname
       
    
2.__fastcall
        有一些函数调用的参数被放入ECX,EDX中,而其它参数从右向左入栈。被调用
        函数在它将要返回时负责清理入栈的参数。在内嵌汇编语言的时候,需要注意
        寄存器的使用,以免与编译器使用的产生冲突。函数名字的转换是:
       
          @functionname@number
       
        没有函数名大小写的转换,number表示函数参数的字节数。由于有一些参数不
        需要入栈,所以这种转换方式会在一定程度上提高函数调用的速度。
       
    
3.__stdcall
      函数参数从右向左入栈,被调用函数负责入栈参数的清理工作。函数名转换格
      式如下:
   
        _functionname@number
   
    下面我们亲自写一个程序,看看各种不同的调用在编译后有什么区别,我们的被调
    用函数如下:
   
    
int function(int a, int b)
    {
        
return a + b;
    }
   
    
void main()
    {
        function(
1020);
    }
   
    
1.__cdecl
       
        _function

                 push    ebp
                 mov     ebp, esp
                 mov     eax, [ebp
+8]       ;参数1
                 add     eax, [ebp
+C]       ;加上参数2
                 pop     ebp
                 retn

        _main
                 push    ebp
                 mov     ebp, esp
                 push    14h                ;参数 2入栈
                 push    0Ah                ;参数 1入栈
                 call    _function          ;调用函数
                 add     esp, 
8             ;修正栈
                 xor     eax, eax
                 pop     ebp
                 retn
                
    
2.__fastcall
   
        @function@
8
                 push    ebp
                 mov     ebp, esp           ;保存栈指针
                 sub     esp, 
8             ;多了两个局部变量
                 mov     [ebp
-8], edx       ;保存参数 2
                 mov     [ebp
-4], ecx       ;保存参数 1
                 mov     eax, [ebp
-4]       ;参数 1
                 add     eax, [ebp
-8]       ;加上参数 2
                 mov     esp, ebp           ;修正栈
                 pop     ebp
                 retn

        _main
                 push    ebp
                 mov     ebp, esp
                 mov     edx, 14h           ;参数 2给EDX
                 mov     ecx, 0Ah           ;参数 1给ECX
                 call    @function@
8        ;调用函数
                 xor     eax, eax
                 pop     ebp
                 retn
 
    
3.__stdcall
   
        _function@
8

                 push    ebp
                 mov     ebp, esp
                 mov     eax, [ebp]         ;参数 
1
                 add     eax, [ebp
+C]       ;加上参数 2
                 pop     ebp
                 retn    
8                  ;修复栈

        _main
                 push    ebp
                 mov     ebp, esp
                 push    14h                ;参数 2入栈
                 push    0Ah                ;参数 1入栈 
                 call    _function@
8    ;函数调用
                 xor     eax, eax
                 pop     ebp
                 retn

    可见上述三种方法各有各的特点,而且_main必须是__cdecl,一般WIN32的函数都是
    __stdcall。而且在Windef.h中有如下的定义:
   
    
#define CALLBACK __stdcall
    
#define WINAPI  __stdcall

posted @ 2010-07-01 09:27 小果子 阅读(262) | 评论 (0)编辑 收藏
当调用(call)一个函数时,主调函数将声明中的参数表以逆序压栈,然后将当前的代码执行指针(eip)压栈,跳转到被调函数的入口点。
        进入被调函数时,函数将esp减去相应字节数获取局部变量存储空间。被调函数返回(ret)时,将esp加上相应字节数,归还栈空间,弹出主调函数 压在栈中的代码执行指针(eip),跳回主调函数。再由主调函数恢复到调用前的栈。
      
为了访问函数局部变量,必须有方法定位每一个变量。变量相对于栈顶esp的位置在进入函数体时就已确定,但是由于esp会在函数执行期变动,所以将esp
的值保存在ebp中,并事先将原ebp的值压栈保存,以声明中的顺序(即压栈的相反顺序)来确定偏移量。
访问函数的局部变量和访问函数参数的区别:
局部变量总是通过将ebp减去偏移量来访问,函数参数总是通过将ebp加上偏移量来访问。对于32位 变量而言,第一个局部变量位于ebp-4,第二个位于ebp-8,以此类推,32位局部变量在栈中形成一个逆序数组;第一个函数参数位于ebp+8,第二 个位于ebp+12,以此类推,32位函数参数在栈中形成一个正序数组。

      
函数的返回值不同于函数参数,可以通过寄存器传递。如果返回值类型可以放入32位变量,比如int、short、char、指针等类型,将通过eax寄存
器传递。如果返回值类型是64位变量,如_int64,则通过edx+eax传递,edx存储高32位,eax存储低32位。如果返回值是浮点类型,如
float和double,通过专用的浮点数寄存器栈的栈顶返回。如果返回值类型是struct或class类型,编译器将通过隐式修改函数的签名,以引
用型参数的形式传回。由于函数返回值通过寄存器返回,不需要空间分配等操作,所以返回值的代价很低。基于这个原因,C89规范中约定,不写明返回值类型的
函数,返回值类型默认为int。这一规则与现行的C++语法相违背,因为C++中,不写明返回值类型的函数返回值类型为void,表示不返回值。这种语法
不兼容性是为了加强C++的类型安全,但同时也带来了一些代码兼容性问题。
代码示例
VarType Func (Arg1, Arg2, Arg3, ... ArgN)
{
    VarType Var1, Var2, Var3, ...VarN;
    //...
    return VarN;
}
假设sizeof(VarType) = 4(DWORD), 则一次函数调用汇编代码示例为:
调用方代码:

push ArgN ; 依次逆序压入调用参数
push ...
push Arg1
call Func_Address ; 压入当前EIP后跳转
跳转至被调方代码:
push ebp ; 备份调用方EBP指针
mov ebp, esp ; 建立被调方栈底
sub esp, N * 4; 为局部变量分配空间
mov dword ptr[esp- 4 * 1 ], 0 ; 初始化各个局部变量 = 0 这里假定VarType不是类
mov dword ptr[esp - 4 * ... ], 0
mov dword ptr[esp - 4 * N ], 0
. . . . . . ; 这里执行一些函数功能语句(比如将第N个参数[ebp + N * 4]存入局部变量), 功能完成后将函数返回值存至eax
add esp, N * 4 ; 销毁局部变量
mov esp, ebp ; 恢复主调方栈顶
pop ebp ; 恢复主调方栈底
ret ; 弹出EIP 返回主调方代码
接上面调用方代码:
add esp, N * 4 ; 释放参数空间, 恢复调用前的栈
mov dword ptr[ebp - 4], eax ; 将返回值保存进调用方的某个VarType型局部变量
进入函数时堆栈分配示意图
内存低地址 | ESP - - - - - - - - - - - - - - - - EBP - - - - - - - - - - - - - - - - - - - - - >| 内存高地址
Stack State: VarN . . . Var3 Var2 Var1 SFP EIP Arg1 Arg2 Arg3 . . . ArgN
//资料
区...............................................................................................................................
SFP 解释:      
除了堆栈指针(ESP指向堆栈顶部的的低地址)之外,
为了使用方便还有指向帧内固定地址的指针叫做帧指针(FP)。有些文章把它叫做局部基指针(LB-local base
pointer)。从理论上来说, 局部变量可以用SP加偏移量来引用。 然而, 当有字被压栈和出栈后, 这些偏移量就变了。
尽管在某些情况下编译器能够跟踪栈中的字操作, 由此可以修正偏移量, 但是在某些情况下不能。而且在所有情况下, 要引入可观的管理开销。
而且在有些机器上, 比如Intel处理器, 由SP加偏移量访问一个变量需要多条指令才能实现。
        因此,
许多编译器使用第二个寄存器, FP, 对于局部变量和函数参数都可以引用, 因为它们到FP的距离不会受到PUSH和POP操作的影响。
在Intel CPU中, BP(EBP)用于这个目的。 在Motorola CPU中,
除了A7(堆栈指针SP)之外的任何地址寄存器都可以做FP。考虑到我们堆栈的增长方向, 从FP的位置开始计算, 函数参数的偏移量是正值,
而局部变量的偏移量是负值。
      
当一个例程被调用时所必须做的第一件事是保存前一个FP(这样当例程退出时就可以恢复这个被保存的FP称为SFP)。 然后它把SP复制到FP,
创建新的FP, 把SP向前移动为局部变量保留空间。 这称为例程的序幕(prolog)工作。当例程退出时, 堆栈必须被清除干净,
这称为例程的收尾(epilog)工作。 Intel的ENTER和LEAVE指令, Motorola的LINK和UNLINK指令,
都可以用于有效地序幕和收尾工作。
         所有局部变量都在栈中由函数统一分配,形成了类似逆序数组的结构,可以通过指针逐一访问。这一特点具有很多有趣性质,比如,考虑如下函数,找出其中的错 误及其造成的结果:
void f()
{
int i,a[10];
for(i=0;i}
        这个函数中包含的错误,即使是C++新手也很容易发现,这是老生常谈的越界访问问
题。但是这个错误造成的结果,是很多人没有想到的。这次的越界访问,并不会像很多新手预料的那样造成一个“非法操作”消息,也不会像很多老手估计的那样会
默不作声,而是导致一个死循环。
        错误的本质显而易见,我们访问了a[10],但是a[10]并不存在。C++标准对于越界访问只是说“未定义操作”。我们知道,a[10]是数组a 所在位置之后的一个位置,但问题是,是谁在这个位置上。是i!
      
根据前面的讨论,i在数组a之前被声明,所以在a之前分配在栈上。但是,I386上栈是向下增长的,所以,a的地址低于i的地址。其结果是在循环的最后,


---------------------------------------------
原文的红色esp感觉应该是ebp..
posted @ 2010-07-01 09:07 小果子 阅读(419) | 评论 (0)编辑 收藏
这几天对汇编来了兴趣~,同时对setWindowsHook感兴趣,所以研究了下扫雷程序用OD,参考了网上的分析和自己的实践,写了个扫雷辅助~,用setWindowsHook ,附上学习成果~
dll.cpp

#include 
"saoleiDll.h"

#pragma   data_seg("Shared")
HINSTANCE g_hInstance = NULL;
HHOOK       g_hHook = NULL;
HWND         g_hWnd = NULL;
#pragma   data_seg()
#pragma   comment(linker,"/SECTION:Shared,RWS")   

LRESULT WINAPI MouseProc(
int nCode,WPARAM wParam,LPARAM lParam){
    
//MessageBox(g_hWnd,L"DD",L"DD",MB_OK);
    DWORD x = 0x10056A8;
    DWORD y = 0x10056AC;
    DWORD addr = 0x1005361;

    wchar_t d[100];
    
int ny=*((wchar_t*)x);
    
int nx=*((wchar_t*)y);

    DWORD pFunc = 0x01003512 ; 

    
for(int i=0;i<ny;i++){
        
for(int j=0;j<nx;j++){
            
int tmp=*((char*)(addr+32*i+j));
            
if(tmp==0x8E){
            }
else if(tmp==0x0F){
                {
                    
int xi=i+1;
                    
int yi=j+1;
                    __asm{
                        push xi
                        push yi
                        call pFunc
                    }
                }
            }
        }
    }

    
//wsprintf(d,L"%d %d",ny,nx);
    //MessageBox(g_hWnd,d,L"DD",MB_OK);
    return  CallNextHookEx(g_hHook,nCode,wParam,lParam);
};
HHOOK InstallHook (HWND hWnd,DWORD dwThreadId)
{
    
if(dwThreadId!=0){
        g_hWnd = hWnd;
        g_hHook = SetWindowsHookEx(WH_KEYBOARD,MouseProc,g_hInstance,dwThreadId);
        
return g_hHook;
    }
else{
        
return NULL;
    }
}
void UninstallHook()
{
    UnhookWindowsHookEx(g_hHook);
}
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    
switch (ul_reason_for_call)
    {
    
case DLL_PROCESS_ATTACH:
        g_hInstance=(HINSTANCE)hModule;
        
break;
    
case DLL_THREAD_ATTACH:
    
case DLL_THREAD_DETACH:
    
case DLL_PROCESS_DETACH:
        
break;
    }
    
return TRUE;
}

engine.h

#ifndef __engine_h__
#define __engine_h__
#include "..\saoleiDll\saoleiDll.h"

#pragma comment(lib,"..\\Debug\\saoleiDll.lib")
DWORD dwThreadId;
HWND hhWnd;
extern HWND hWnd;
void process(){
    DWORD x = 0x10056A8;
    DWORD y = 0x10056AC;
    DWORD addr = 0x1005361;

    hhWnd=FindWindow(NULL,L"扫雷");
    DWORD hProcessId;
    dwThreadId=GetWindowThreadProcessId(hhWnd, &hProcessId);
    HANDLE Process = OpenProcess(PROCESS_VM_OPERATION| PROCESS_VM_WRITE|PROCESS_VM_READ, 
false, hProcessId);

    
if(Process==NULL){
    
//MessageBox(-1,GetLastError(),"D",MB_OK);
        DWORD sd=GetLastError();
    }


    unsigned 
short int nx=0,ny=0;
    ReadProcessMemory(Process,(LPCVOID)x,&ny,2,NULL);
    ReadProcessMemory(Process,(LPCVOID)y,&nx,2,NULL);

    unsigned 
short int s=0,b=0;
    
int test=0;
    
int cnt=0;
    
for(int i = 0; i < ny; i ++){
        
for(int j = 0; j < nx; j++){
            ::ReadProcessMemory(Process, (LPCVOID)(addr + 32*i+j), &b, 1, NULL);
            
if (b == 0x8F) 
            {
                cnt++;
                s = 0x8E; 
                ::WriteProcessMemory(Process, (LPVOID)(addr + (nx+2)*i+j), &s, 1, NULL);
                ReadProcessMemory(Process, (LPCVOID)(addr + (nx+2)*i+j), &test, 1, NULL);
            }
        }
    }
    ::InvalidateRect(hhWnd, NULL, 
true);
    ::CloseHandle(Process);
}

#endif


posted @ 2010-06-30 20:42 小果子 阅读(147) | 评论 (0)编辑 收藏
方法14 :MessageProc Function

The MessageProc hook procedure 
is an application-defined or library-defined callback function used with the SetWindowsHookEx function. The system calls this function after an input event occurs in a dialog box, message box, menu, or scroll bar, but before the message generated by the input event is processed. The hook procedure can monitor messages for a dialog box, message box, menu, or scroll bar created by a particular application or all applications. MessageProc钩子子程是同SetWindowsHookEx方法一起使用的、应用程序或者库定义的回调方法。在对话框,消息框,菜单,滚动条的输入事件发生后、在这些输入事件生成的消息被处理之前,系统调用该方法。钩子子程可以监视特定的程序或者所有程序生成的对话框,消息框,菜单或者滚动条的消息。

The HOOKPROC type defines a pointer to 
this callback function. MessageProc is a placeholder for the application-defined or library-defined function name. HOOKPROC类型定义了指向该回调函数的指针。MessageProc是程序定义的或者库定义的方法名字。

Syntax语法

LRESULT CALLBACK MessageProc(      

        
int code,

    WPARAM wParam,

    LPARAM lParam

);

Parameters参数

code :[
in] Specifies the type of input event that generated the message. If code is less than zero, the hook procedure must pass the message to the CallNextHookEx function without further processing and return the value returned by CallNextHookEx. This parameter can be one of the following values. 指定生成消息的输入事件的类型。如果code小于0,钩子子程必须将消息传递给CallNextHookEx方法,自己不进行任何进一步处理,并且要返回由方法CallNextHookEx返回的返回值。该参数可以时下列方法之一。

1.MSGF_DDEMGR :The input event occurred while the Dynamic Data Exchange Management Library (DDEML) was waiting for a synchronous transaction to finish. 当DDEML正在等待同步传输结束时,该输入事件发生。

2.MSGF_DIALOGBOX :The input event occurred in a message box or dialog box. 输入事件在消息框或者对话框中发生。

3.MSGF_MENU :The input event occurred in a menu. 输入事件在菜单中发生。

4.MSGF_SCROLLBAR :The input event occurred in a scroll bar.输入事件在滚动条中发生。

wParam :This parameter 
is not used. 该参数未被使用。

lParam :[
in] Pointer to an MSG structure. 指向MSG结构的指针。

Return Value返回值

If code 
is less than zero, the hook procedure must return the value returned by CallNextHookEx.

If code 
is greater than or equal to zero, and the hook procedure did not process the message, it is highly recommended that you call CallNextHookEx and return the value it returns; otherwise, other applications that have installed WH_MSGFILTER hooks will not receive hook notifications and may behave incorrectly as a result. If the hook procedure processed the message, it may return a nonzero value to prevent the system from passing the message to the rest of the hook chain or the target window procedure.

如果code小于0,钩子子程必须返回由方法CallNextHookEx返回的返回值。如果code大于等于0,而且钩子子程还没有处理该消息,强烈要求调用CallNextHookEx方法并返回由它返回的返回值;否则,其它已经安装了WH_MSGFILTER钩子的应用程序将收不到钩子通知,可能导致行为的错误。如果钩子子程已经处理了该消息,应该返回非0值,以组织系统将消息传递给钩子链表中剩下的钩子或者目标窗口子程。

Remarks备注

An application installs the hook procedure by specifying the WH_MSGFILTER hook type and a pointer to the hook procedure 
in a call to the SetWindowsHookEx function.

If an application that uses the DDEML and performs synchronous transactions must process messages before they are dispatched, it must use the WH_MSGFILTER hook.

应用程序通过下面方法来安装钩子:指定WH_MSGFILTER钩子类型;指定在调用SetWindowsHookEx的方法中指向钩子子程的指针。

使用DDEML、执行同步传递的应用程序应该在消息被分发前进行处理,必须使用WH_MSGFILTER钩子。

 

方法15 :MouseProc Function

The MouseProc hook procedure 
is an application-defined or library-defined callback function used with the SetWindowsHookEx function. The system calls this function whenever an application calls the GetMessage or PeekMessage function and there is a mouse message to be processed. MouseProc钩子子程是同SetWindowsHookEx方法一起使用的、应用程序定义的或者库定义的回调函数。无论什么时候,当应用程序一调用GetMessage 或者 PeekMessage方法,有鼠标消息即将被处理时,系统调用该方法。

The HOOKPROC type defines a pointer to 
this callback function. MouseProc is a placeholder for the application-defined or library-defined function name.  HOOKPROC类型定义了指向回调函数的指针。MouseProc是应用程序定义的或者库定义的方法名称。

Syntax:语法

LRESULT CALLBACK MouseProc(      

         
int nCode,

    WPARAM wParam,

    LPARAM lParam

);

Parameters 参数

nCode :[
in] Specifies a code the hook procedure uses to determine how to process the message. If nCode is less than zero, the hook procedure must pass the message to the CallNextHookEx function without further processing and should return the value returned by CallNextHookEx. This parameter can be one of the following values. 指定钩子子程使用的用来决定如何处理消息的码值。如果nCode小于0,钩子子程必须将消息传递给CallNextHookEx方法,自己不进行进一步的处理,并且要返回由CallNextHookEx方法返回的返回值。该参数可以是下列值之一:

1.HC_ACTION :The wParam and lParam parameters contain information about a mouse message. 参数wParam 和 lParam包含和鼠标消息相关的信息。

2.HC_NOREMOVE :The wParam and lParam parameters contain information about a mouse message, and the mouse message has not been removed from the message queue. (An application called the PeekMessage function, specifying the PM_NOREMOVE flag.)

参数wParam 和 lParam包含和鼠标消息相关的信息,鼠标消息还没有从消息队列中移除。

wParam :[
in] Specifies the identifier of the mouse message. 指定鼠标消息的标识符。

lParam:[
in] Pointer to a MOUSEHOOKSTRUCT structure. 指向MOUSEHOOKSTRUCT结构的指针。

Return Value 返回值

If nCode 
is less than zero, the hook procedure must return the value returned by CallNextHookEx. If nCode is greater than or equal to zero, and the hook procedure did not process the message, it is highly recommended that you call CallNextHookEx and return the value it returns; otherwise, other applications that have installed WH_MOUSE hooks will not receive hook notifications and may behave incorrectly as a result. If the hook procedure processed the message, it may return a nonzero value to prevent the system from passing the message to the target window procedure.

如果code小于0,钩子子程必须返回由CallNextHookEx方法返回的返回值。如果code大于等于0,钩子子程还没有处理该消息,强烈要求调用CallNextHookEx方法并返回由它返回的返回值;否则,其它已经安装了WH_MOUSE钩子的应用程序将收不到钩子通知,可能导致行为的错误。如果钩子子程已经处理了该消息,应该返回非0值,以阻止系统将消息传递给钩子链表中剩余的钩子或者目标窗体程序。

Remarks备注

An application installs the hook procedure by specifying the WH_MOUSE hook type and a pointer to the hook procedure 
in a call to the SetWindowsHookEx function. The hook procedure must not install a WH_JOURNALPLAYBACK Hook callback function.

应用程序通过下面方法来安装钩子:指定WH_MOUSE钩子类型;指定在调用SetWindowsHookEx的方法中指向钩子子程的指针。该钩子子程不应安装WH_JOURNALPLAYBACK钩子的回调函数。

 

方法15 :MouseProc Function

The MouseProc hook procedure 
is an application-defined or library-defined callback function used with the SetWindowsHookEx function. The system calls this function whenever an application calls the GetMessage or PeekMessage function and there is a mouse message to be processed. MouseProc钩子子程是同SetWindowsHookEx方法一起使用的、应用程序定义的或者库定义的回调函数。无论什么时候,当应用程序一调用GetMessage 或者 PeekMessage方法,有鼠标消息即将被处理时,系统调用该方法。

The HOOKPROC type defines a pointer to 
this callback function. MouseProc is a placeholder for the application-defined or library-defined function name.  HOOKPROC类型定义了指向回调函数的指针。MouseProc是应用程序定义的或者库定义的方法名称。

Syntax:语法

LRESULT CALLBACK MouseProc(      

         
int nCode,

    WPARAM wParam,

    LPARAM lParam

);

Parameters 参数

nCode :[
in] Specifies a code the hook procedure uses to determine how to process the message. If nCode is less than zero, the hook procedure must pass the message to the CallNextHookEx function without further processing and should return the value returned by CallNextHookEx. This parameter can be one of the following values. 指定钩子子程使用的用来决定如何处理消息的码值。如果nCode小于0,钩子子程必须将消息传递给CallNextHookEx方法,自己不进行进一步的处理,并且要返回由CallNextHookEx方法返回的返回值。该参数可以是下列值之一:

1.HC_ACTION :The wParam and lParam parameters contain information about a mouse message. 参数wParam 和 lParam包含和鼠标消息相关的信息。

2.HC_NOREMOVE :The wParam and lParam parameters contain information about a mouse message, and the mouse message has not been removed from the message queue. (An application called the PeekMessage function, specifying the PM_NOREMOVE flag.)

参数wParam 和 lParam包含和鼠标消息相关的信息,鼠标消息还没有从消息队列中移除。

wParam :[
in] Specifies the identifier of the mouse message. 指定鼠标消息的标识符。

lParam:[
in] Pointer to a MOUSEHOOKSTRUCT structure. 指向MOUSEHOOKSTRUCT结构的指针。

Return Value 返回值

If nCode 
is less than zero, the hook procedure must return the value returned by CallNextHookEx. If nCode is greater than or equal to zero, and the hook procedure did not process the message, it is highly recommended that you call CallNextHookEx and return the value it returns; otherwise, other applications that have installed WH_MOUSE hooks will not receive hook notifications and may behave incorrectly as a result. If the hook procedure processed the message, it may return a nonzero value to prevent the system from passing the message to the target window procedure.

如果code小于0,钩子子程必须返回由CallNextHookEx方法返回的返回值。如果code大于等于0,钩子子程还没有处理该消息,强烈要求调用CallNextHookEx方法并返回由它返回的返回值;否则,其它已经安装了WH_MOUSE钩子的应用程序将收不到钩子通知,可能导致行为的错误。如果钩子子程已经处理了该消息,应该返回非0值,以阻止系统将消息传递给钩子链表中剩余的钩子或者目标窗体程序。

Remarks备注

An application installs the hook procedure by specifying the WH_MOUSE hook type and a pointer to the hook procedure 
in a call to the SetWindowsHookEx function. The hook procedure must not install a WH_JOURNALPLAYBACK Hook callback function.

应用程序通过下面方法来安装钩子:指定WH_MOUSE钩子类型;指定在调用SetWindowsHookEx的方法中指向钩子子程的指针。该钩子子程不应安装WH_JOURNALPLAYBACK钩子的回调函数。

 

 

方法16 :SetWindowsHookEx Function

The SetWindowsHookEx function installs an application
-defined hook procedure into a hook chain. You would install a hook procedure to monitor the system for certain types of events. These events are associated either with a specific thread or with all threads in the same desktop as the calling thread.

SetWindowsHookEx方法安装一个应用程序定义的钩子子程到钩子链表中。你可能安装钩子子程来监视系统的一些类型的事件。这些事件可以同下面的线程一起使用:指定的线程或者同一桌面下做为调用线程的所有线程。

Syntax 语法

HHOOK SetWindowsHookEx(      

    
int idHook,

    HOOKPROC lpfn,

    HINSTANCE hMod,

    DWORD dwThreadId

);

Parameters参数

idHook :[
in] Specifies the type of hook procedure to be installed. This parameter can be one of the following values. 指定即将被安装的钩子子程的类型。该参数可以是下列值之一:

1.WH_CALLWNDPROC :Installs a hook procedure that monitors messages before the system sends them to the destination window procedure. 安装一个钩子子程,用来在系统将消息发送给目的窗体程序之前监视消息。

2. WH_CALLWNDPROCRET :Installs a hook procedure that monitors messages after they have been processed by the destination window procedure. 安装一个钩子子程,用来在消息被目标窗体程序处理之后来监视消息。

3.WH_CBT :Installs a hook procedure that receives notifications useful to a computer-based training (CBT) application.安装一个钩子子程,用来接收对CBT程序有用的通知。

4.WH_DEBUG :Installs a hook procedure useful for debugging other hook procedures.安装一个对调试其它钩子子程有用的钩子子程。

5.WH_FOREGROUNDIDLE :Installs a hook procedure that will be called when the application's foreground thread is about to become idle. This hook is useful for performing low priority tasks during idle time.安装一个钩子子程,当应用程序的前台线程即将空闲时,该子程被调用。该钩子在空闲时间里来执行低权限任务时很有用。

5.WH_GETMESSAGE :Installs a hook procedure that monitors messages posted to a message queue.安装一个钩子子程用来监视传递给消息队列的消息。

6.WH_JOURNALPLAYBACK :Installs a hook procedure that posts messages previously recorded by a WH_JOURNALRECORD hook procedure.安装一个钩子子程用来传递前期由WH_JOURNALRECORD钩子子程记录的消息。

7.WH_JOURNALRECORD :Installs a hook procedure that records input messages posted to the system message queue. This hook is useful for recording macros. 安装一个钩子子程来记录传递给系统消息队列的输入消息。该钩子对记录宏很有用。

8.WH_KEYBOARD :Installs a hook procedure that monitors keystroke messages.安装一个钩子子程用来监视键盘消息。

9.WH_KEYBOARD_LL  :Windows NT/2000/XP: Installs a hook procedure that monitors low-level keyboard input events.在Windows NT/2000/XP环境下:安装一个钩子子程用来监视低层键盘输入事件。

10.WH_MOUSE :Installs a hook procedure that monitors mouse messages.安装一个钩子子程用来监视鼠标消息。

11.WH_MOUSE_LL :: Installs a hook procedure that monitors low-level mouse input events. 在 Windows NT/2000/XP环境下,安装一个钩子子程用来监视低层鼠标输入事件。

12.WH_MSGFILTER :Installs a hook procedure that monitors messages generated as a result of an input event in a dialog box, message box, menu, or scroll bar.安装一个钩子子程用来监视下列对象的输入事件产生的消息:对话框、消息框、菜单、滚动条。

13.WH_SHELL :Installs a hook procedure that receives notifications useful to shell applications.安装一个钩子子程用来接收对加壳程序有用的通知。

14.WH_SYSMSGFILTER :Installs a hook procedure that monitors messages generated as a result of an input event in a dialog box, message box, menu, or scroll bar. The hook procedure monitors these messages for all applications in the same desktop as the calling thread.安装一个钩子子程用来监视下列对象的输入事件产生的消息:对话框、消息框、菜单、滚动条。钩子子程为同一桌面下做为调用线程的所有线程监视这些消息。

lpfn :[
in] Pointer to the hook procedure. If the dwThreadId parameter is zero or specifies the identifier of a thread created by a different process, the lpfn parameter must point to a hook procedure in a dynamic-link library (DLL). Otherwise, lpfn can point to a hook procedure in the code associated with the current process.

钩子子程的指针。如果参数dwThreadId为0或者指定由不同进程创建的线程的标识符,lpfn参数必须指向动态链接库里的钩子子程。否则,lpfn可以指向与当前进程相关的代码中的钩子子程。

hMod :[
in] Handle to the DLL containing the hook procedure pointed to by the lpfn parameter. The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process.

由lpfn参数指向的含有钩子子程的DLL的句柄。如果参数dwThreadId指定了由当前进程创建的线程,或者如果钩子子程处在与当前进程相关的代码中,hMod参数必须设置为Null。

dwThreadId :[
in] Specifies the identifier of the thread with which the hook procedure is to be associated. If this parameter is zero, the hook procedure is associated with all existing threads running in the same desktop as the calling thread. 指定钩子子程即将关联的线程的标识符。如果该参数是0,钩子子程与在同一桌面环境下运行的做为调用线程的所有存在的线程相关联。

Return Value返回值

If the function succeeds, the 
return value is the handle to the hook procedure. If the function fails, the return value is NULL.

如果方法执行成功,返回钩子子程的句柄。如果失败,返回空。

Remarks备注

SetWindowsHookEx can be used to inject a DLL into another process. A 
32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL cannot be injected into a 32-bit process. If an application requires the use of hooks in other processes, it is required that a 32-bit application call SetWindowsHookEx to inject a 32-bit DLL into 32-bit processes, and a 64-bit application call SetWindowsHookEx to inject a 64-bit DLL into 64-bit processes. The 32-bit and 64-bit DLLs must have different names.

SetWindowsHookEx可以被注入到DLL中,进而被映射到另外进程中。32位的DLL不能被注入到64位的进程中,同样,64位的DLL也不能被注入到32位的进程中。如果应用程序请求在其它的进程中使用钩子,要求,32位的应用程序调用SetWindowsHookEx将32位的DLL注入到32位的进程中,64位的应用程序调用SetWindowsHookEx将64位的DLL注入到64位的进程中。32位的DLL和64位的DLL必须具有不同的名称。

An error may occur 
if the hMod parameter is NULL and the dwThreadId parameter is zero or specifies the identifier of a thread created by another process. 如果参数hMod为空,参数dwThreadId为0,或者指定了由另外进程创建的线程的标识符,会产生错误。

Calling the CallNextHookEx function to chain to the next hook procedure 
is optional, but it is highly recommended; otherwise, other applications that have installed hooks will not receive hook notifications and may behave incorrectly as a result. You should call CallNextHookEx unless you absolutely need to prevent the notification from being seen by other applications. 虽然调用CallNextHookEx方法链接到下一个钩子子程是可选的,但是强烈建议使用;否则,其它已经安装了钩子的应用程序将不接收钩子通知,可能导致行为错误。除非绝对需要阻止通知被其它应用程序看见,其他时候都应该调用CallNextHookEx方法。

Before terminating, an application must call the UnhookWindowsHookEx function to free system resources associated with the hook. 在结束前,应用程序必须调用UnhookWindowsHookEx方法来释放与该钩子相关的系统资源。

The scope of a hook depends on the hook type. Some hooks can be 
set only with global scope; others can also be set for only a specific thread, as shown in the following table. 钩子的作用域取决于钩子的类型。一些钩子只能在全局范围使用,其它一些仅仅能在指定的线程中使用。如下表所示:

Hook
    

Scope

WH_CALLWNDPROC
    

Thread or global线程
/全局

WH_CALLWNDPROCRET
    

Thread or global线程
/全局

WH_CBT
    

Thread or global线程
/全局

WH_DEBUG
    

Thread or global线程
/全局

WH_FOREGROUNDIDLE
    

Thread or global线程
/全局

WH_GETMESSAGE
    

Thread or global线程
/全局

WH_JOURNALPLAYBACK
    

Global only全局

WH_JOURNALRECORD
    

Global only全局

WH_KEYBOARD
    

Thread or global线程
/全局

WH_KEYBOARD_LL
    

Global only全局

WH_MOUSE
    

Thread or global线程
/全局

WH_MOUSE_LL
    

Global only全局

WH_MSGFILTER
    

Thread or global线程
/全局

WH_SHELL
    

Thread or global线程
/全局

WH_SYSMSGFILTER
    

Global only全局

For a specified hook type, thread hooks are called first, then global hooks.

对于指定的钩子类型,线程钩子先被调用,然后是全局钩子。

The global hooks are a shared resource, and installing one affects all applications 
in the same desktop as the calling thread. All global hook functions must be in libraries. Global hooks should be restricted to special-purpose applications or to use as a development aid during application debugging. Libraries that no longer need a hook should remove its hook procedure.

 全局钩子是共享资源,安装一个钩子会影响同一桌面环境下做为调用线程的所有应用程序。所有的全局钩子函数都应该在库中。全局钩子应该被分发到特定目的的应用程序中,或者在程序调试中间,来辅助开发。不再需要钩子的库应该移除钩子子程。

posted @ 2010-06-26 20:38 小果子 阅读(442) | 评论 (0)编辑 收藏
仅列出标题
共58页: First 35 36 37 38 39 40 41 42 43 Last