00485                    :
00486 
00487     This function either captures 
the user mode state of 
the current
00488     thread, or sets 
the user mode state of 
the current thread. The
00489     operation 
type is determined by 
the value of SystemArgument1. 
A
00490     zero value 
is used 
for get context, and a nonzero value 
is used
00491     
for set context.
00492 
00493 Arguments:
00494 
00495     Apc - Supplies a pointer to 
the APC 
control object that caused entry
00496           into 
this routine.
00497 
00498     NormalRoutine - Supplies a pointer to 
the normal routine function that
00499         was specified when 
the APC was initialized. This parameter 
is not
00500         used.
00501 
00502     NormalContext - Supplies a pointer to an arbitrary data structure that
00503         was specified when 
the APC was initialized. This parameter 
is not
00504         used.
00505 
00506     SystemArgument1, SystemArgument2 - Supplies a set of two pointer to two
00507         arguments that contain untyped data. These parameters are not used.
00508 
00509 Return Value:
00510 
00511     None.
00512 
00513 --*/
00514 
00515 {
00516 
00517     
PGETSETCONTEXT ContextBlock;
00518     KNONVOLATILE_CONTEXT_POINTERS ContextPointers;
00519     CONTEXT ContextRecord;
00520     ULONG ControlPc;
00521     ULONG EstablisherFrame;
00522     PRUNTIME_FUNCTION FunctionEntry;
00523     BOOLEAN InFunction;
00524     
PETHREAD Thread;
00525     ULONG TrapFrame1;
00526     ULONG TrapFrame2;
00527 
00528     
00529     
00530     
00531     
00532 
00533     ContextBlock = CONTAINING_RECORD(Apc, 
GETSETCONTEXT, Apc);
00534     Thread = 
PsGetCurrentThread();
00535     TrapFrame1 = (ULONG)Thread->
Tcb.
InitialStack - KTRAP_FRAME_LENGTH;
00536     TrapFrame2 = (ULONG)Thread->
Tcb.
InitialStack - KTRAP_FRAME_LENGTH - KTRAP_FRAME_ARGUMENTS;
00537 
00538     
00539     
00540     
00541     
00542 
00543     RtlCaptureContext(&ContextRecord);
00544     ControlPc = (ULONG)ContextRecord.XIntRa;
00545 
00546     
00547     
00548     
00549     
00550 
00551     ContextPointers.XIntS0 = &ContextRecord.XIntS0;
00552     ContextPointers.XIntS1 = &ContextRecord.XIntS1;
00553     ContextPointers.XIntS2 = &ContextRecord.XIntS2;
00554     ContextPointers.XIntS3 = &ContextRecord.XIntS3;
00555     ContextPointers.XIntS4 = &ContextRecord.XIntS4;
00556     ContextPointers.XIntS5 = &ContextRecord.XIntS5;
00557     ContextPointers.XIntS6 = &ContextRecord.XIntS6;
00558     ContextPointers.XIntS7 = &ContextRecord.XIntS7;
00559 
00560     ContextPointers.FltF20 = &ContextRecord.FltF20;
00561     ContextPointers.FltF21 = &ContextRecord.FltF21;
00562     ContextPointers.FltF22 = &ContextRecord.FltF22;
00563     ContextPointers.FltF23 = &ContextRecord.FltF23;
00564     ContextPointers.FltF24 = &ContextRecord.FltF24;
00565     ContextPointers.FltF25 = &ContextRecord.FltF25;
00566     ContextPointers.FltF26 = &ContextRecord.FltF26;
00567     ContextPointers.FltF27 = &ContextRecord.FltF27;
00568     ContextPointers.FltF28 = &ContextRecord.FltF28;
00569     ContextPointers.FltF29 = &ContextRecord.FltF29;
00570     ContextPointers.FltF30 = &ContextRecord.FltF30;
00571     ContextPointers.FltF31 = &ContextRecord.FltF31;
00572 
00573     
00574     
00575     
00576     
00577 
00578     
do {
00579 
00580         
00581         
00582         
00583         
00584 
00585         FunctionEntry = 
RtlLookupFunctionEntry(ControlPc);
00586 
00587         
00588         
00589         
00590         
00591         
00592         
00593         
00594 
00595         
if (FunctionEntry != 
NULL) {
00596             ControlPc = 
RtlVirtualUnwind(ControlPc | 1,
00597                                          FunctionEntry,
00598                                          &ContextRecord,
00599                                          &InFunction,
00600                                          &EstablisherFrame,
00601                                          &ContextPointers);
00602 
00603         } 
else {
00604             ControlPc = (ULONG)ContextRecord.XIntRa;
00605         }
00606 
00607     } 
while (((ULONG)ContextRecord.XIntSp != TrapFrame1) &&
00608              (((ULONG)ContextRecord.XIntSp != TrapFrame2) ||
00609              (ControlPc < PCR->SystemServiceDispatchStart) ||
00610              (ControlPc >= PCR->SystemServiceDispatchEnd)));
00611 
00612     
00613     
00614     
00615     
00616 
00617     
if (Apc->SystemArgument1 != 0) {
00618 
00619         
00620         
00621         
00622 
00623         
PspSetContext((PKTRAP_FRAME)TrapFrame1,
00624                       &ContextPointers,
00625                       &ContextBlock->
Context,
00626                       ContextBlock->
Mode);
00627 
00628     } 
else {
00629 
00630         
00631         
00632         
00633 
00634         
PspGetContext((PKTRAP_FRAME)TrapFrame1,
00635                       &ContextPointers,
00636                       &ContextBlock->
Context);
00637     }
00638 
00639     
KeSetEvent(&ContextBlock->
OperationComplete, 0, FALSE);
00640     
return;
00641 }
}