当我正在调查我只能在Windows 8上重现的奇怪崩溃时,我发现EBX
寄存器未从RmShutdown
或RmRestart
的调用中恢复。我在Windows 8上运行时发现的第一个区别是它使用ECX
,而这些函数的win7版本使用(从而恢复)EBX
。 (我没有仔细研究过其他Windows版本,只是注意到这个bug并没有在Vista上重现。)
当我进一步挖掘时,我注意到对RM_WRITE_STATUS_CALLBACK
的调用并没有通过弹出其中的参数来恢复堆栈,因为调用者似乎没有做到这一点。它要么。因此,当RstrtMgr!CRestartManager::ShutdownApplications
调用RstrtMgr!_EH_epilog3
时,会从堆栈中弹出错误的寄存器值。但至少,ESP
已正确恢复,RmShutdown
的结尾正确重置了所使用的寄存器,包括EBP
,它在调用{{1}之间不会使用和...结束......
所以在Windows 7上,一切都很好......但是Windows 8版本,使用CRestartManager::ShutdownApplications
代替ECX
,EBX
未恢复,如果调用代码依赖在它... BOOM !!!
要解决此问题,我只是将回调函数更改为使用EBX
(这意味着我无法使用真正的__stdcall
类型,并且需要将其类型转换为API所期望的内容,或使用RM_WRITE_STATUS_CALLBACK
技术,无论如何都需要在XP上运行相同的代码。)
我是否遗漏了某些内容,或者这确实是API的问题? GetProcAddress
和EDI
怎么样?即使在Windows 7上,它们也无法正常恢复。在我的情况下,它们没有被使用,所以没关系,但我不能相信这些函数的调用者都不需要这些寄存器才能正常恢复......对吗?
我想我会向微软提交一个错误信息......除非有人能提出更好的解释......