test: psctxppc.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# psctxppc.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1990  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     psctxmip.c
    00008
    00009 Abstract:
    00010
    00011     This module implements function to get and set the context of a thread.
    00012
    00013 Author:
    00014
    00015     David N. Cutler (davec) 1-Oct-1990
    00016
    00017 Revision History:
    00018
    00019     Tom Wood (twood) 19-Aug-1994
    00020     Update to use RtlVirtualUnwind even when there isn't a function table
    00021     entry.  Add stack limit parameters to RtlVirtualUnwind.
    00022
    00023 --*/
    00024
    00025 #include "psp.h"
    00026 #pragma hdrstop
    00027 #define         STK_MIN_FRAME   56
    00028 extern  ULONG   KiBreakPoints;
    00029
    00030 VOID
    00031 PspGetContext (
    00032     IN PKTRAP_FRAME TrapFrame,
    00033     IN PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
    00034     IN OUT PCONTEXT ContextRecord
    00035     )
    00036
    00037 /*++
    00038
    00039 Routine Description:
    00040
    00041     This function selectively moves the contents of the specified trap frame
    00042     and nonvolatile context to the specified context record.
    00043
    00044 Arguments:
    00045
    00046     TrapFrame - Supplies a pointer to a trap frame.
    00047
    00048     ContextPointers - Supplies the address of context pointers record.
    00049
    00050     ContextRecord - Supplies the address of a context record.
    00051
    00052 Return Value:
    00053
    00054     None.
    00055
    00056 --*/
    00057
    00058 {
    00059
    00060     if ((ContextRecord->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
    00061
    00062         //
    00063         // Get machine state, instr address, link, count registers
    00064         //
    00065
    00066         ContextRecord->Msr = TrapFrame->Msr;
    00067         ContextRecord->Iar = TrapFrame->Iar;
    00068         ContextRecord->Lr  = TrapFrame->Lr;
    00069         ContextRecord->Ctr = TrapFrame->Ctr;
    00070     }
    00071
    00072     if ((ContextRecord->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
    00073
    00074         //
    00075         // Get volatile integer regs in trap frame are 0..12
    00076         //
    00077
    00078         RtlMoveMemory (&ContextRecord->Gpr0, &TrapFrame->Gpr0,
    00079                        sizeof (ULONG) * 13);
    00080
    00081         //
    00082         // Get non-volatile integer regs in exception frame are 13..31
    00083         //
    00084
    00085         ContextRecord->Gpr13 = *ContextPointers->IntegerContext[13];
    00086         ContextRecord->Gpr14 = *ContextPointers->IntegerContext[14];
    00087         ContextRecord->Gpr15 = *ContextPointers->IntegerContext[15];
    00088         ContextRecord->Gpr16 = *ContextPointers->IntegerContext[16];
    00089         ContextRecord->Gpr17 = *ContextPointers->IntegerContext[17];
    00090         ContextRecord->Gpr18 = *ContextPointers->IntegerContext[18];
    00091         ContextRecord->Gpr19 = *ContextPointers->IntegerContext[19];
    00092         ContextRecord->Gpr20 = *ContextPointers->IntegerContext[20];
    00093         ContextRecord->Gpr21 = *ContextPointers->IntegerContext[21];
    00094         ContextRecord->Gpr22 = *ContextPointers->IntegerContext[22];
    00095         ContextRecord->Gpr23 = *ContextPointers->IntegerContext[23];
    00096         ContextRecord->Gpr24 = *ContextPointers->IntegerContext[24];
    00097         ContextRecord->Gpr25 = *ContextPointers->IntegerContext[25];
    00098         ContextRecord->Gpr26 = *ContextPointers->IntegerContext[26];
    00099         ContextRecord->Gpr27 = *ContextPointers->IntegerContext[27];
    00100         ContextRecord->Gpr28 = *ContextPointers->IntegerContext[28];
    00101         ContextRecord->Gpr29 = *ContextPointers->IntegerContext[29];
    00102         ContextRecord->Gpr30 = *ContextPointers->IntegerContext[30];
    00103         ContextRecord->Gpr31 = *ContextPointers->IntegerContext[31];
    00104
    00105         //
    00106         // The CR is made up of volatile and non-volatile fields,
    00107         // but the entire CR is saved in the trap frame
    00108         //
    00109
    00110         ContextRecord->Cr = TrapFrame->Cr;
    00111
    00112         //
    00113         // Fixed Point Exception Register (XER) is part of the
    00114         // integer state
    00115         //
    00116
    00117         ContextRecord->Xer = TrapFrame->Xer;
    00118     }
    00119
    00120     if ((ContextRecord->ContextFlags & CONTEXT_FLOATING_POINT) ==
    00121          CONTEXT_FLOATING_POINT) {
    00122
    00123         //
    00124         // Get volatile floating point regs in trap frame are 0..13
    00125         //
    00126
    00127         RtlMoveMemory(&ContextRecord->Fpr0, &TrapFrame->Fpr0,
    00128                      sizeof(DOUBLE) * (14));
    00129
    00130         //
    00131         // Get non-volatile floating point regs 14..31
    00132         //
    00133
    00134         ContextRecord->Fpr14 = *ContextPointers->FloatingContext[14];
    00135         ContextRecord->Fpr15 = *ContextPointers->FloatingContext[15];
    00136         ContextRecord->Fpr16 = *ContextPointers->FloatingContext[16];
    00137         ContextRecord->Fpr17 = *ContextPointers->FloatingContext[17];
    00138         ContextRecord->Fpr18 = *ContextPointers->FloatingContext[18];
    00139         ContextRecord->Fpr19 = *ContextPointers->FloatingContext[19];
    00140         ContextRecord->Fpr20 = *ContextPointers->FloatingContext[20];
    00141         ContextRecord->Fpr21 = *ContextPointers->FloatingContext[21];
    00142         ContextRecord->Fpr22 = *ContextPointers->FloatingContext[22];
    00143         ContextRecord->Fpr23 = *ContextPointers->FloatingContext[23];
    00144         ContextRecord->Fpr24 = *ContextPointers->FloatingContext[24];
    00145         ContextRecord->Fpr25 = *ContextPointers->FloatingContext[25];
    00146         ContextRecord->Fpr26 = *ContextPointers->FloatingContext[26];
    00147         ContextRecord->Fpr27 = *ContextPointers->FloatingContext[27];
    00148         ContextRecord->Fpr28 = *ContextPointers->FloatingContext[28];
    00149         ContextRecord->Fpr29 = *ContextPointers->FloatingContext[29];
    00150         ContextRecord->Fpr30 = *ContextPointers->FloatingContext[30];
    00151         ContextRecord->Fpr31 = *ContextPointers->FloatingContext[31];
    00152
    00153         //
    00154         // Get floating point status and control register.
    00155         //
    00156
    00157         ContextRecord->Fpscr = TrapFrame->Fpscr;
    00158     }
    00159
    00160     //
    00161     // Fetch Dr register contents if requested.  Values may be trash.
    00162     //
    00163
    00164     if ((ContextRecord->ContextFlags & CONTEXT_DEBUG_REGISTERS) ==
    00165         CONTEXT_DEBUG_REGISTERS) {
    00166
    00167
    00168         ContextRecord->Dr0 = TrapFrame->Dr0;
    00169         ContextRecord->Dr1 = TrapFrame->Dr1;
    00170         ContextRecord->Dr2 = TrapFrame->Dr2;
    00171         ContextRecord->Dr3 = TrapFrame->Dr3;
    00172         ContextRecord->Dr6 = TrapFrame->Dr6;
    00173         ContextRecord->Dr5 = 0;           // Zero initialize unused regs
    00174         ContextRecord->Dr4 = 0;
    00175
    00176         //
    00177         // If it's a user mode frame, and the thread doesn't have DRs set,
    00178         // and we just return the trash in the frame, we risk accidentally
    00179         // making the thread active with trash values on a set.  Therefore,
    00180         // Dr7 must be set to the number of available data address breakpoint
    00181         // registers if we get a non-active user mode frame.
    00182         //
    00183         if (((TrapFrame->PreviousMode) != KernelMode) &&
    00184             (KeGetCurrentThread()->DebugActive)) {
    00185
    00186             ContextRecord->Dr7 = TrapFrame->Dr7;
    00187             ContextRecord->Dr6 |= KiBreakPoints;
    00188         } else {
    00189
    00190             ContextRecord->Dr7 = 0;
    00191             ContextRecord->Dr6 = KiBreakPoints;
    00192         }
    00193     }
    00194
    00195     return;
    00196 }
    00197
    00198 VOID
    00199 PspSetContext (
    00200     IN OUT PKTRAP_FRAME TrapFrame,
    00201     IN PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
    00202     IN PCONTEXT ContextRecord,
    00203     IN KPROCESSOR_MODE ProcessorMode
    00204     )
    00205
    00206 /*++
    00207
    00208 Routine Description:
    00209
    00210     This function selectively moves the contents of the specified context
    00211     record to the specified trap frame and nonvolatile context.
    00212
    00213 Arguments:
    00214
    00215     TrapFrame - Supplies the address of a trap frame.
    00216
    00217     ContextPointers - Supplies the address of a context pointers record.
    00218
    00219     ContextRecord - Supplies the address of a context record.
    00220
    00221     ProcessorMode - Supplies the processor mode to use when sanitizing
    00222         the PSR and FSR.
    00223
    00224 Return Value:
    00225
    00226     None.
    00227
    00228 --*/
    00229
    00230 {
    00231
    00232     if ((ContextRecord->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
    00233
    00234         //
    00235         // Set instruction address, link, count, and machine state registers
    00236         //
    00237
    00238         TrapFrame->Lr  = ContextRecord->Lr;
    00239         TrapFrame->Ctr = ContextRecord->Ctr;
    00240         TrapFrame->Msr = SANITIZE_MSR(ContextRecord->Msr, ProcessorMode);
    00241
    00242         //
    00243         // If this is a remote call dereference the function descritor in
    00244         // the remote threads context.
    00245         //
    00246         if (((ContextRecord->ContextFlags & CONTEXT_INTEGER) ==
    00247               CONTEXT_INTEGER) &&
    00248             (ContextRecord->Gpr2 == 0)) {
    00249            try {
    00250
    00251                //
    00252                // Make sure we have read access to the function descriptor.
    00253                //
    00254                ProbeForRead(ContextRecord->Iar,
    00255                             (sizeof(ULONG) * 2), sizeof(ULONG));
    00256                TrapFrame->Iar = *((PULONG)(ContextRecord->Iar))++;
    00257                ContextRecord->Gpr2 = *(PULONG)(ContextRecord->Iar);
    00258
    00259            } except(EXCEPTION_EXECUTE_HANDLER) {
    00260
    00261                //
    00262                // Remote thread doesn't have access to the function
    00263                // descriptor. Just set the IAR and let the thread take
    00264                // the exception.
    00265                //
    00266                TrapFrame->Iar = ContextRecord->Iar;
    00267                return;
    00268            }
    00269         } else {
    00270            TrapFrame->Iar = ContextRecord->Iar;
    00271         }
    00272     }
    00273
    00274     if ((ContextRecord->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
    00275
    00276         //
    00277         // Volatile integer regs are 0..12
    00278         //
    00279
    00280         RtlMoveMemory(&TrapFrame->Gpr0, &ContextRecord->Gpr0,
    00281                      sizeof(ULONG) * (13));
    00282
    00283         //
    00284         // Non-volatile integer regs are 13..31
    00285         //
    00286
    00287         *ContextPointers->IntegerContext[13] = ContextRecord->Gpr13;
    00288         *ContextPointers->IntegerContext[14] = ContextRecord->Gpr14;
    00289         *ContextPointers->IntegerContext[15] = ContextRecord->Gpr15;
    00290         *ContextPointers->IntegerContext[16] = ContextRecord->Gpr16;
    00291         *ContextPointers->IntegerContext[17] = ContextRecord->Gpr17;
    00292         *ContextPointers->IntegerContext[18] = ContextRecord->Gpr18;
    00293         *ContextPointers->IntegerContext[19] = ContextRecord->Gpr19;
    00294         *ContextPointers->IntegerContext[20] = ContextRecord->Gpr20;
    00295         *ContextPointers->IntegerContext[21] = ContextRecord->Gpr21;
    00296         *ContextPointers->IntegerContext[22] = ContextRecord->Gpr22;
    00297         *ContextPointers->IntegerContext[23] = ContextRecord->Gpr23;
    00298         *ContextPointers->IntegerContext[24] = ContextRecord->Gpr24;
    00299         *ContextPointers->IntegerContext[25] = ContextRecord->Gpr25;
    00300         *ContextPointers->IntegerContext[26] = ContextRecord->Gpr26;
    00301         *ContextPointers->IntegerContext[27] = ContextRecord->Gpr27;
    00302         *ContextPointers->IntegerContext[28] = ContextRecord->Gpr28;
    00303         *ContextPointers->IntegerContext[29] = ContextRecord->Gpr29;
    00304         *ContextPointers->IntegerContext[30] = ContextRecord->Gpr30;
    00305         *ContextPointers->IntegerContext[31] = ContextRecord->Gpr31;
    00306
    00307         //
    00308         // Copy the Condition Reg and Fixed Point Exception Reg
    00309         //
    00310
    00311         TrapFrame->Cr = ContextRecord->Cr;
    00312         TrapFrame->Xer = ContextRecord->Xer;
    00313     }
    00314
    00315     if ((ContextRecord->ContextFlags & CONTEXT_FLOATING_POINT) ==
    00316          CONTEXT_FLOATING_POINT) {
    00317
    00318         //
    00319         // Volatile floating point regs are 0..13
    00320         //
    00321
    00322         RtlMoveMemory(&TrapFrame->Fpr0, &ContextRecord->Fpr0,
    00323                      sizeof(DOUBLE) * (14));
    00324
    00325         //
    00326         // Non-volatile floating point regs are 14..31
    00327         //
    00328
    00329         *ContextPointers->FloatingContext[14] = ContextRecord->Fpr14;
    00330         *ContextPointers->FloatingContext[15] = ContextRecord->Fpr15;
    00331         *ContextPointers->FloatingContext[16] = ContextRecord->Fpr16;
    00332         *ContextPointers->FloatingContext[17] = ContextRecord->Fpr17;
    00333         *ContextPointers->FloatingContext[18] = ContextRecord->Fpr18;
    00334         *ContextPointers->FloatingContext[19] = ContextRecord->Fpr19;
    00335         *ContextPointers->FloatingContext[20] = ContextRecord->Fpr20;
    00336         *ContextPointers->FloatingContext[21] = ContextRecord->Fpr21;
    00337         *ContextPointers->FloatingContext[22] = ContextRecord->Fpr22;
    00338         *ContextPointers->FloatingContext[23] = ContextRecord->Fpr23;
    00339         *ContextPointers->FloatingContext[24] = ContextRecord->Fpr24;
    00340         *ContextPointers->FloatingContext[25] = ContextRecord->Fpr25;
    00341         *ContextPointers->FloatingContext[26] = ContextRecord->Fpr26;
    00342         *ContextPointers->FloatingContext[27] = ContextRecord->Fpr27;
    00343         *ContextPointers->FloatingContext[28] = ContextRecord->Fpr28;
    00344         *ContextPointers->FloatingContext[29] = ContextRecord->Fpr29;
    00345         *ContextPointers->FloatingContext[30] = ContextRecord->Fpr30;
    00346         *ContextPointers->FloatingContext[31] = ContextRecord->Fpr31;
    00347
    00348         //
    00349         // Set floating point status and control register.
    00350         //
    00351
    00352         TrapFrame->Fpscr = SANITIZE_FPSCR(ContextRecord->Fpscr, ProcessorMode);
    00353     }
    00354
    00355     //
    00356     // Set debug register state if specified.  If previous mode is user
    00357     // mode (i.e. it's a user frame we're setting) and if effect will be to
    00358     // cause at least one of the debug register enable bits in Dr7
    00359     // to be set then set DebugActive to the enable bit mask.
    00360     //
    00361
    00362     if ((ContextRecord->ContextFlags & CONTEXT_DEBUG_REGISTERS) ==
    00363          CONTEXT_DEBUG_REGISTERS) {
    00364
    00365         //
    00366         // Set the debug control register for the 601 and 604
    00367         // indicating the number of address breakpoints supported.
    00368         //
    00369         TrapFrame->Dr0 = SANITIZE_DRADDR(ContextRecord->Dr0, ProcessorMode);
    00370         TrapFrame->Dr1 = SANITIZE_DRADDR(ContextRecord->Dr1, ProcessorMode);
    00371         TrapFrame->Dr2 = SANITIZE_DRADDR(ContextRecord->Dr2, ProcessorMode);
    00372         TrapFrame->Dr3 = SANITIZE_DRADDR(ContextRecord->Dr3, ProcessorMode);
    00373         TrapFrame->Dr6 = SANITIZE_DR6(ContextRecord->Dr6, ProcessorMode);
    00374         TrapFrame->Dr7 = SANITIZE_DR7(ContextRecord->Dr7, ProcessorMode);
    00375
    00376         if (ProcessorMode != KernelMode) {
    00377               KeGetPcr()->DebugActive = KeGetCurrentThread()->DebugActive =
    00378                                         (UCHAR)(TrapFrame->Dr7 & DR7_ACTIVE);
    00379         }
    00380     }
    00381
    00382     return;
    00383 }
    00384
    00385 VOID
    00386 PspGetSetContextApc (
    00387     IN PKAPC Apc,
    00388     IN PKNORMAL_ROUTINE *NormalRoutine,
    00389     IN PVOID *NormalContext,
    00390     IN PVOID *SystemArgument1,
    00391     IN PVOID *SystemArgument2
    00392     )
    00393
    00394 /*++
    00395
    00396 Routine Description:
    00397
    00398     This function either captures the user mode state of the current
    00399     thread, or sets the user mode state of the current thread. The
    00400     operation type is determined by the value of SystemArgument1. A
    00401     zero value is used for get context, and a nonzero value is used
    00402     for set context.
    00403
    00404 Arguments:
    00405
    00406     Apc - Supplies a pointer to the APC control object that caused entry
    00407           into this routine.
    00408
    00409     NormalRoutine - Supplies a pointer to the normal routine function that
    00410         was specified when the APC was initialized. This parameter is not
    00411         used.
    00412
    00413     NormalContext - Supplies a pointer to an arbitrary data structure that
    00414         was specified when the APC was initialized. This parameter is not
    00415         used.
    00416
    00417     SystemArgument1, SystemArgument2 - Supplies a set of two pointer to two
    00418         arguments that contain untyped data. These parameters are not used.
    00419
    00420 Return Value:
    00421
    00422     None.
    00423
    00424 --*/
    00425
    00426 {
    00427
    00428     PGETSETCONTEXT ContextBlock;
    00429     KNONVOLATILE_CONTEXT_POINTERS ContextPointers;
    00430     CONTEXT ContextRecord;
    00431     ULONG ControlPc;
    00432     ULONG EstablisherFrame;
    00433     PRUNTIME_FUNCTION FunctionEntry;
    00434     BOOLEAN InFunction;
    00435     PETHREAD Thread;
    00436     ULONG TrapFrame1;
    00437     ULONG TrapFrame2;
    00438
    00439     //
    00440     // Get the address of the context block and compute the address of the
    00441     // system entry trap frame.
    00442     //
    00443
    00444     ContextBlock = CONTAINING_RECORD(Apc, GETSETCONTEXT, Apc);
    00445     Thread = PsGetCurrentThread();
    00446     TrapFrame1 = (ULONG)Thread->Tcb.InitialStack - (KTRAP_FRAME_LENGTH +
    00447                  sizeof(KEXCEPTION_FRAME) + (2 * sizeof(ULONG)));
    00448     TrapFrame2 = (ULONG)Thread->Tcb.InitialStack - (KTRAP_FRAME_LENGTH +
    00449                  sizeof(KEXCEPTION_FRAME) + STK_MIN_FRAME +
    00450                  (10 * sizeof(ULONG)));
    00451
    00452     //
    00453     // Capture the current thread context and set the initial control PC
    00454     // value.
    00455     //
    00456
    00457     RtlCaptureContext(&ContextRecord);
    00458     ControlPc = ContextRecord.Lr;
    00459
    00460     //
    00461     // Initialize context pointers for the nonvolatile integer and floating
    00462     // registers.
    00463     //
    00464
    00465     ContextPointers.IntegerContext[13] = &ContextRecord.Gpr13;
    00466     ContextPointers.IntegerContext[14] = &ContextRecord.Gpr14;
    00467     ContextPointers.IntegerContext[15] = &ContextRecord.Gpr15;
    00468     ContextPointers.IntegerContext[16] = &ContextRecord.Gpr16;
    00469     ContextPointers.IntegerContext[17] = &ContextRecord.Gpr17;
    00470     ContextPointers.IntegerContext[18] = &ContextRecord.Gpr18;
    00471     ContextPointers.IntegerContext[19] = &ContextRecord.Gpr19;
    00472     ContextPointers.IntegerContext[20] = &ContextRecord.Gpr20;
    00473     ContextPointers.IntegerContext[21] = &ContextRecord.Gpr21;
    00474     ContextPointers.IntegerContext[22] = &ContextRecord.Gpr22;
    00475     ContextPointers.IntegerContext[23] = &ContextRecord.Gpr23;
    00476     ContextPointers.IntegerContext[24] = &ContextRecord.Gpr24;
    00477     ContextPointers.IntegerContext[25] = &ContextRecord.Gpr25;
    00478     ContextPointers.IntegerContext[26] = &ContextRecord.Gpr26;
    00479     ContextPointers.IntegerContext[27] = &ContextRecord.Gpr27;
    00480     ContextPointers.IntegerContext[28] = &ContextRecord.Gpr28;
    00481     ContextPointers.IntegerContext[29] = &ContextRecord.Gpr29;
    00482     ContextPointers.IntegerContext[30] = &ContextRecord.Gpr30;
    00483     ContextPointers.IntegerContext[31] = &ContextRecord.Gpr31;
    00484
    00485     ContextPointers.FloatingContext[14] = &ContextRecord.Fpr14;
    00486     ContextPointers.FloatingContext[15] = &ContextRecord.Fpr15;
    00487     ContextPointers.FloatingContext[16] = &ContextRecord.Fpr16;
    00488     ContextPointers.FloatingContext[17] = &ContextRecord.Fpr17;
    00489     ContextPointers.FloatingContext[18] = &ContextRecord.Fpr18;
    00490     ContextPointers.FloatingContext[19] = &ContextRecord.Fpr19;
    00491     ContextPointers.FloatingContext[20] = &ContextRecord.Fpr20;
    00492     ContextPointers.FloatingContext[21] = &ContextRecord.Fpr21;
    00493     ContextPointers.FloatingContext[22] = &ContextRecord.Fpr22;
    00494     ContextPointers.FloatingContext[23] = &ContextRecord.Fpr23;
    00495     ContextPointers.FloatingContext[24] = &ContextRecord.Fpr24;
    00496     ContextPointers.FloatingContext[25] = &ContextRecord.Fpr25;
    00497     ContextPointers.FloatingContext[26] = &ContextRecord.Fpr26;
    00498     ContextPointers.FloatingContext[27] = &ContextRecord.Fpr27;
    00499     ContextPointers.FloatingContext[28] = &ContextRecord.Fpr28;
    00500     ContextPointers.FloatingContext[29] = &ContextRecord.Fpr29;
    00501     ContextPointers.FloatingContext[30] = &ContextRecord.Fpr30;
    00502     ContextPointers.FloatingContext[31] = &ContextRecord.Fpr31;
    00503
    00504     //
    00505     // Start with the frame specified by the context record and virtually
    00506     // unwind call frames until the system entry trap frame is encountered.
    00507     //
    00508
    00509     do {
    00510
    00511         //
    00512         // Lookup the function table entry using the point at which control
    00513         // left the procedure.
    00514         //
    00515
    00516         FunctionEntry = RtlLookupFunctionEntry(ControlPc);
    00517
    00518         //
    00519         // Virtually unwind to the caller of the current routine to
    00520         // obtain the address where control left the caller.
    00521         //
    00522
    00523         ControlPc = RtlVirtualUnwind(ControlPc,
    00524                                      FunctionEntry,
    00525                                      &ContextRecord,
    00526                                      &InFunction,
    00527                                      &EstablisherFrame,
    00528                                      &ContextPointers,
    00529                                      (ULONG)Thread->Tcb.StackLimit,
    00530                                      (ULONG)Thread->Tcb.InitialStack);
    00531
    00532     } while ((ContextRecord.Gpr1 >= (ULONG)Thread->Tcb.StackLimit) &&
    00533              (ContextRecord.Gpr1 < (ULONG)Thread->Tcb.InitialStack));
    00534
    00535     //
    00536     // If system argument one is nonzero, then set the context of the current
    00537     // thread. Otherwise, get the context of the current thread.
    00538     //
    00539
    00540     if (Apc->SystemArgument1 != 0) {
    00541
    00542         //
    00543         // Set context of current thread.
    00544         //
    00545
    00546         PspSetContext((PKTRAP_FRAME)TrapFrame1,
    00547                       &ContextPointers,
    00548                       &ContextBlock->Context,
    00549                       ContextBlock->Mode);
    00550
    00551     } else {
    00552
    00553         //
    00554         // Get context of current thread.
    00555         //
    00556
    00557         PspGetContext((PKTRAP_FRAME)TrapFrame1,
    00558                       &ContextPointers,
    00559                       &ContextBlock->Context);
    00560     }
    00561
    00562     KeSetEvent(&ContextBlock->OperationComplete, 0, FALSE);
    00563     return;
    00564 }