3

当我正在调查一个只能在 Windows 8 上重现的奇怪崩溃时,我发现EBX寄存器没有从对RmShutdown或的调用中恢复RmRestart。我发现在 Windows 8 上运行的第一个区别是,它ECX在这些功能的 win7 版本使用时使用(并因此恢复)EBX。(我没有仔细调查其他 Windows 版本,只是注意到该错误不会在 Vista 上重现。)

当我进一步挖掘时,我注意到对 的调用RM_WRITE_STATUS_CALLBACK并没有通过从中弹出参数来恢复堆栈,因为调用者似乎也没有这样做。因此,当RstrtMgr!CRestartManager::ShutdownApplications调用RstrtMgr!_EH_epilog3错误的寄存器值时,会从堆栈中弹出。但至少,ESP正确恢复并且RmShutdown正确重置它使用的寄存器的结束,包括EBP在调用和结束之间不使用的寄存器CRestartManager::ShutdownApplications......

所以在 Windows 7 上,一切都很好......但是 Windows 8 版本,因为ECX使用而不是EBXEBX没有恢复,如果调用代码依赖它...... BOOM !!!

为了解决这个问题,我只是将回调函数更改为使用__stdcall(这意味着我不能使用真实RM_WRITE_STATUS_CALLBACK类型,需要将其类型转换为 API 期望的类型,或者使用GetProcAddress在 XP 上运行相同代码所需的技术反正)。

我是否遗漏了什么,或者这真的是 API 的问题吗?EDI和怎么样ESI?即使在 Windows 7 上,它们也没有正确恢复。在我的情况下,它们没有被使用,所以没关系,但我不敢相信这些函数的调用者都不需要正确恢复这些寄存器......对吗?

我想我会为此向微软提交一个错误......除非有人能提出更好的解释......

4

0 回答 0