RtlRaiseStatus(Status);
}
+static
+VOID
+RtlpCaptureNonVolatileContextPointers(
+ _Out_ PKNONVOLATILE_CONTEXT_POINTERS NonvolatileContextPointers,
+ _In_ ULONG64 TargetFrame)
+{
+ CONTEXT Context;
+ PRUNTIME_FUNCTION FunctionEntry;
+ ULONG64 ImageBase;
+ PVOID HandlerData;
+ ULONG64 EstablisherFrame;
+
+ /* Zero out the nonvolatile context pointers */
+ RtlZeroMemory(NonvolatileContextPointers, sizeof(*NonvolatileContextPointers));
+
+ /* Capture the current context */
+ RtlCaptureContext(&Context);
+
+ do
+ {
+ /* Look up the function entry */
+ FunctionEntry = RtlLookupFunctionEntry(Context.Rip, &ImageBase, NULL);
+ ASSERT(FunctionEntry != NULL);
+
+ /* Do a virtual unwind to the caller and capture saved non-volatiles */
+ RtlVirtualUnwind(UNW_FLAG_EHANDLER,
+ ImageBase,
+ Context.Rip,
+ FunctionEntry,
+ &Context,
+ &HandlerData,
+ &EstablisherFrame,
+ NonvolatileContextPointers);
+
+ /* Make sure nothing fishy is going on. Currently this is for kernel mode only. */
+ ASSERT(EstablisherFrame != 0);
+ ASSERT((LONG64)Context.Rip < 0);
+
+ /* Continue until we reached the target frame or user mode */
+ } while (EstablisherFrame < TargetFrame);
+
+ /* If the caller did the right thing, we should get exactly the target frame */
+ ASSERT(EstablisherFrame == TargetFrame);
+}
+
+VOID
+RtlSetUnwindContext(
+ _In_ PCONTEXT Context,
+ _In_ DWORD64 TargetFrame)
+{
+ KNONVOLATILE_CONTEXT_POINTERS ContextPointers;
+
+ /* Capture pointers to the non-volatiles up to the target frame */
+ RtlpCaptureNonVolatileContextPointers(&ContextPointers, TargetFrame);
+
+ /* Copy the nonvolatiles to the captured locations */
+ *ContextPointers.R12 = Context->R12;
+ *ContextPointers.R13 = Context->R13;
+ *ContextPointers.R14 = Context->R14;
+ *ContextPointers.R15 = Context->R15;
+ *ContextPointers.Xmm6 = Context->Xmm6;
+ *ContextPointers.Xmm7 = Context->Xmm7;
+ *ContextPointers.Xmm8 = Context->Xmm8;
+ *ContextPointers.Xmm9 = Context->Xmm9;
+ *ContextPointers.Xmm10 = Context->Xmm10;
+ *ContextPointers.Xmm11 = Context->Xmm11;
+ *ContextPointers.Xmm12 = Context->Xmm12;
+ *ContextPointers.Xmm13 = Context->Xmm13;
+ *ContextPointers.Xmm14 = Context->Xmm14;
+ *ContextPointers.Xmm15 = Context->Xmm15;
+}