Wednesday, April 22, 2009

SetWindowsHookEx return error 87

最近要用 SetWindowsHookEx 函数改变下 VMware 的一个功能。于是开始先写一个单独的,简单的测试程序。弄了半天,发现在 HOOK VMware 的时候总是失败,给的错误代码是87,也就是无效参数。但是我已经确认过那4个参数都是对的啊。头疼。

没办法,又自己写个超小的WINDOWS程序来代替VMWARE, 一切正常。可是为啥VMWARE 不行呢?还是想不通,于是又换个程序HOOK. 不过换成CALC.EXE(计算器)之后,出现同样的87错误。可是同样的程序HOOK我自己的小程序就没那个错误。苦恼。

又想了下,那4个传给 SetWindowsHookEx 参数绝对都是对的,因为我都检查过。那么我的小程序和其他CALC.EXE, VMWARE有啥不同呢?GOOLE了N个文章,没答案。又想了半天,忽然想到,我是在CREATEPROCESS之后马上用 SetWindowsHookEx进行HOOK的。我的小程序启动肯定很快,但是另外2个也许比较慢。难道要多等一段时间才能HOOK? 马上在SetWindowsHookEx 之前加个SLEEP 3秒钟。再试,搞定!

我现在觉得,原因在于CREATEPROCESS是异步调用的。虽然它已经返回了,但是新的PROCESS也许还没真正准备好 (创建一个新进程比生个小孩还麻烦)。所以这时马上调用 SetWindowsHookEx 的话,就会出错。不过错误信息太雷人了。

另外 MSDN 上应该好好说明一下。

A few days ago, I tried to use SetWindowsHookEx function to modify the behavior of a program -- VMware. In my program, I first  call CreateProcess to create vmware process then I call SetWindowsHookEx. But SetWindowsHookEx  always return an error -- 87. It means invalid parameter. However, I was sure all the parameters passed to SetWindowsHookEx are correct. So what's wrong? After a lot of googling and thinking, I finally found out that you have to put a Sleep(100) or sth. similar between the CreateProcess and SetWindowsHookEx. I guess the reason is that CreateProcess is an asynchronous function. When it returns, the process may not actually ready and call SetWindowsHookEx immediately may then fail. Unfortunately, the error code is misleading and make it hard to find out the true reason.

No comments: