首页

为什么 SetWindowsHookEx 采用 HINSTANCE 参数?  

有开发者问了这样一个问题:既然 SetWindowsHookEx 的第一个参数总是会被转换为一个文件名,那为什么它的传参类型是 HINSTANCE 呢?这岂不是多此一举? 原因是这样的:在 16 位 Windows 系统上,它不是这样工作的。16 位 Windows 上根本就没有 “钩子注入” 的概念。 所有 16 位 Windows 应用程序都是运行在同一个地址空间,所以...

浅谈 DLL 导出函数中的转发器函数  

在之前的一篇文章中,我们了解到 32 位 DLL 的函数导出方式和 16 位是类似的,只是 32 位 DLL 更倾向于使用基于名称的导出,而不是基于函数序号的导出。 这种倾向性不会在文件格式中表达出来: 16 位和 32 位 DLL 都可以按名称或序号(或两者)导出,但 Win32 的设计者在设计理念上更偏向于仅使用名称导出。 但是 Win32 中有一种新型的导出函数,我们叫它们转发器。 转发器看...

在32位Windows中,DLL是如何导出的?  

32 位 Windows 的设计者不必担心将所有内容压缩到 256KB 的内存中。由于 Win32 中的模块基于需求分页,因此你所要做的就是将整个映像映射到内存中,然后运行访问所需的部分。 DLL中的常驻名(resident name)和非常驻名(non-resident name)之间没有区别,导出函数的名称仅存储在 DLL 文件中,并带有指向导出表中存储的名称的指针(即相对虚拟地址)。 与 1...

调试心得:通过观察正常的程序行为来识别Bug  

有时候,当我调试一个问题的时候,我会特意忽略掉某些线程。 这个时候,有人就问了:”这些线程是干什么的?你为什么知道要忽略它们?” 我的回答是:我也不清楚这些线程是干啥的,但是无论它的内部工作是什么,这都是正常的。” 博主 Tess Ferrandez 一直在编写关于 CLR 调试的系列文章,这些文章十分有用,但最为重要的一条是在调试 ASP.NET 死锁问题时该...

安全编程:初始化那些你忽略掉的东西  

对于黑客来说,特权提升漏洞是令他感到非常兴奋的事情,而有时候这种漏洞的来源仅仅是因为开发者忘记将内存缓冲区中的垃圾数据进行初始化。此话怎讲? 我想,现在每个人都应该熟悉 SecureZeroMemory 函数的使用,它用来擦除包含敏感信息的缓冲区,但是在将缓冲区的内容写入另一个位置之前,你还必须将其清零。例如,请考虑以下二进制格式: 下面是一段想文件中写入数据的例子: 在上面的代码中,你有没有...

在工具提示中使用自绘修改字体  

在上一篇文章中,我们学习了如何在应用程序中添加工具提示。在之前的例子代码中,我们通过简单地为创建的工具提示设置了目标字体,这种方法很简单,因为自始至终,我们都只创建了一个工具提示。 但是,如果在应用程序中,我们创建了多个不同字体的工具提示,则这种方法就不会奏效了。这个时候,我们需要一种新的方法,是的,你想的和我一样:自绘。 让我们还是回到之前的例子代码,但是这次,我们将会通过自绘来设置字体,而不是...

软件的可用性改善:善用帮助信息  

当我们吭哧吭哧的开发功能性模块的时候,也需要回头思考一下软件的可用性。今天的主题就是使用帮助信息来改善软件的可用性,让软件不仅”能用”,也更”好用”。 帮助信息,也叫工具提示(Tooltip)。当用户的鼠标悬停在一段文字或者控件上时,会自动显示相关的帮助信息。例如,如果一个控件上的字符串没有足够的控件显示,当鼠标悬停在控件上时,可以通过工具提示来显示...

自动重置事件只是一个愚蠢的信号量  

当我们调用 CreateEvent 函数创建一个事件对象的时候,我们可以通过参数来指定这个事件对象是自动重置的,还是手动重置的。 对于一个手动重置的事件对象,它很容易理解:当事件未激发时,在此事件上的等待将一直挂起,而当事件被激发时,在此事件对象上的等待将会立即返回。 上面的工作原则和有多少个线程正在等待此对象没有任何关系。所有线程对此对象的等待操作都是一致的,并且事件对象的状态也不会受到等待它的...

思维调试:理解 DDE 的初始化过程  

最近有人问我下面这个问题,我们依然可以使用之前我提到的 “思维调试” 来研究研究。 我们碰到了一个技术问题。当在资源管理器中双击打开文档时,资源管理器不会启动我们的应用程序。 更加奇怪的是,如果我们将一个调试器挂接到资源管理器进程,并在 kernel32 模块的 CreateProcessW 处下断点,然后等待 CreateProcess 返回,并在调试器中继续执行,则文档...

修改窗口类的属性将影响所有该类的窗口  

正如标题所指出的:窗口类的属性将影响所有由该窗口类创建的窗口。这就是它为什么称之为窗口类的原因。 我用这么多话来强调这一点,似乎是一件显而易见的事情,但我看到许多”解决方案”忽视了这个简单的事实。 在 WNDCLASS(或 WNDCLASSEX)中设置的所有属性都是窗口类属性,可以通过 Get/SetClassWord/Long/LongPtr 访问的属性也是如此。这意味着...