I'm trying to get one of my currently XP or later applications running on Windows 2000/x86. Currently I'm having trouble getting some stack walking functionality working without the use of RtlCaptureContext(), which doesn't appear on Windows 2000 boxes. I'm currently using C++ with MSVC 7.1.
So far I've tried throwing a dummy exception and capturing the context in the __except handler:
EXCEPTION_POINTERS * eps = 0;
__try {
RaiseException(0, 0, 0, 0);
} __except((eps = GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER) {
}
CONTEXT ctx = *(eps->ContextRecord);
This is both with RaiseException() and various variations of throw, different exception codes, assigning the CONTEXT in the exception handler and outside the exception handler, and so on. This generates a CONTEXT, but the stack walk is funny: it only shows two entries on the stack, no matter where it's called, when both the debugger stack view and the RtlCaptureContext() version show significantly deeper stack frames. (RaiseException() is shown as the top most frame when the RaiseException() version is used, so I assume that the stack walk is to some degree valid, but it remains unhelpful.)
I've also tried use inline assembly to get at the EIP, ESP and EBP registers. ESP and EBP are trivial, but getting the EIP seems problematic. So far I've tried:
__asm call x
__asm x: pop eax
__asm mov ctx.Eip, eax
But this generates a runtime error, and my assembly skills are sufficiently poor to be unable to see how to improve this (the EIP register being something I usually don't have any need to mess with).
I'd also rather avoid multiple threads so GetThreadContext() is out. Also, the application uses a commercial library, which has a license that conflicts with the GPL, so many free library solutions are out. Any ideas? No rush on this, as getting this to run on 2000 is a low priority.