Когда я расследовал странный сбой, который я мог воспроизвести только в 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
не восстанавливается и если от него зависит вызывающий код … БУМ !!!
Чтобы это исправить, я просто изменил функцию обратного вызова, чтобы использовать __stdcall
(это означает, что я не мог использовать реальный RM_WRITE_STATUS_CALLBACK
введите, и необходимо указать его в соответствии с ожиданиями API или использовать GetProcAddress
техника, которая необходима для запуска того же кода на XP в любом случае).
Я что-то упустил или это действительно проблема с API? А как насчет EDI
а также ESI
? Они также НЕ восстанавливаются должным образом, даже в Windows 7. В моем случае они не использовались, так что это нормально, но я не могу поверить, что ни одному из вызывающих этих функций не потребовалось бы правильного восстановления этих регистров … Верно?
Я думаю, что напишу ошибку в Microsoft для этого … Если кто-то не может придумать лучшего объяснения …
Задача ещё не решена.