Aah ;-) The closest I've come to programming a stack backtrace is through the use of the WINDBG_EXTENSION_APIS lpStackTraceRoutine function, implemented as a Softice KDExtension. This essentially gives you the same info as the STACK command.
There are 2 definitions for a stack trace in Windbg, one defined in wdbgext.h, a more extensive one in dbgeng.h.
Code:
// wdbgext.h
(WDBGAPI*PWINDBG_STACKTRACE_ROUTINE)(
ULONG FramePointer, // stack frame EBP (or 0)
ULONG StackPointer, // stack frame ESP (or 0)
ULONG ProgramCounter, // Instruction offset (or 0)
PEXTSTACKTRACE StackFrames, // return structure
ULONG Frames // number of frames to return (based
// on number of EXTSTACKTRACE structures)
);
The FramePointer and StackPointer are the ClientEBP and ClientESP which you can get from Windbg lpGetThreadContextRoutine. This function returns a pointer to a CONTEXT_FULL Context structure for the thread Id specified. In kernel mode you specify the processor number instead of the TID.
So, this is the way to do it using Windbg api's. It sounds like you want to program a fully manual stack backtracing routine. That's cool. An interesting programming challenge. You might be able to pick up some tricks from tracing an implemented Windbg stack trace routine, if you haven't already got something developed.
Where then is the starting point? You can get the StackBase and StackLimit from the TEB. "Walking" the stack manually can begin there then, or must you get at least one valid EBP value from a context structure? I don't know what problems one might encounter in doing a stack backtrace manually, how far could you go before you "lose" it? And then there's the context switch problem you mentioned.
Softice does do context switches in both the STACK command and the internal lpStackTraceRoutine function it exports for KDExtension use. In Softice, "context" is defined as a pointer to the KPROCESS structure and a "context switch" is based on it, I mentioned this in a previous post.
Back to your original question on how to get the ring3 context of the parent process, I'd actually have to reserve judgement to see what is *necessary* at the time, in terms of a stack backtrace implementation. For example, where and in what context are you starting the backtrace from and how far can you get? If indeed you would need to "jump over" an INT2E ZwCreateProcess to tap into the previous stack tracings to get at the parent, I'm really not sure the best approach at this time.
I'm not sure how much of this applies to your problem or question. It's an interesting topic though so if anyone has any further insights it would be useful. Perhaps you already have some procedures developed and might be willing to share in terms of implementing a stack backtrace. Maybe you can mention exactly where you saw this stack trace picture you spoke of.
Regards,
Kayaker