当我正在调查一个只能在 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
使用而不是EBX
,EBX
没有恢复,如果调用代码依赖它...... BOOM !!!
为了解决这个问题,我只是将回调函数更改为使用__stdcall
(这意味着我不能使用真实RM_WRITE_STATUS_CALLBACK
类型,需要将其类型转换为 API 期望的类型,或者使用GetProcAddress
在 XP 上运行相同代码所需的技术反正)。
我是否遗漏了什么,或者这真的是 API 的问题吗?EDI
和怎么样ESI
?即使在 Windows 7 上,它们也没有正确恢复。在我的情况下,它们没有被使用,所以没关系,但我不敢相信这些函数的调用者都不需要正确恢复这些寄存器......对吗?
我想我会为此向微软提交一个错误......除非有人能提出更好的解释......