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

context.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1990 Microsoft Corporation 00004 00005 Module Name: 00006 00007 context.c 00008 00009 Abstract: 00010 00011 This module implements user-mode callable context manipulation routines. 00012 00013 Author: 00014 00015 Mark Lucovsky (markl) 20-Jun-1989 00016 00017 Revision History: 00018 00019 David N. Cutler (davec) 18-Apr-1990 00020 Rick Simpson, Peter Johnston Conversion to PowerPC 11/5/93 00021 00022 Revise for MIPS environment. 00023 00024 --*/ 00025 00026 #include <ntos.h> 00027 #define _KXPPC_C_HEADER_ 00028 #include <kxppc.h> 00029 00030 VOID 00031 RtlInitializeContext( 00032 IN HANDLE Process, 00033 OUT PCONTEXT Context, 00034 IN PVOID Parameter OPTIONAL, 00035 IN PVOID InitialPc OPTIONAL, 00036 IN PVOID InitialSp OPTIONAL 00037 ) 00038 00039 /*++ 00040 00041 Routine Description: 00042 00043 This function initializes a context structure so that it can be used in 00044 a subsequent call to NtCreateThread. 00045 00046 Arguments: 00047 00048 Context - Supplies a pointer to a context record that is to be initialized. 00049 00050 InitialPc - Supplies an initial program counter value. 00051 00052 InitialSp - Supplies an initial stack pointer value. 00053 00054 Return Value: 00055 00056 Raises STATUS_BAD_INITIAL_STACK if the value of InitialSp is not properly 00057 aligned. 00058 00059 Raises STATUS_BAD_INITIAL_PC if the value of InitialPc is not properly 00060 aligned. 00061 00062 --*/ 00063 00064 { 00065 00066 // 00067 // Check for proper initial stack and PC alignment. 00068 // 00069 00070 if (((ULONG)InitialSp & 0x7) != 0) { 00071 RtlRaiseStatus(STATUS_BAD_INITIAL_STACK); 00072 } 00073 if (((ULONG)InitialPc & 0x3) != 0) { 00074 RtlRaiseStatus(STATUS_BAD_INITIAL_PC); 00075 } 00076 00077 // 00078 // Initialize the integer and floating registers to contain zeroes. 00079 // 00080 00081 RtlZeroMemory(Context, sizeof(CONTEXT)); 00082 00083 // 00084 // Initialize the control registers. 00085 // 00086 00087 if ( ARGUMENT_PRESENT(InitialPc) ) { 00088 Context->Iar = (ULONG)InitialPc; 00089 } 00090 if ( ARGUMENT_PRESENT(InitialSp) ) { 00091 Context->Gpr1 = (ULONG)InitialSp - STK_MIN_FRAME; 00092 } 00093 00094 Context->Msr = 00095 MASK_SPR(MSR_ILE,1)| 00096 MASK_SPR(MSR_FP,1) | 00097 MASK_SPR(MSR_FE0,1)| 00098 MASK_SPR(MSR_FE1,1)| 00099 MASK_SPR(MSR_ME,1) | 00100 MASK_SPR(MSR_IR,1) | 00101 MASK_SPR(MSR_DR,1) | 00102 MASK_SPR(MSR_PR,1) | 00103 MASK_SPR(MSR_LE,1); 00104 Context->ContextFlags = CONTEXT_FULL; 00105 00106 // 00107 // Set the initial context of the thread in a machine specific way. 00108 // 00109 00110 Context->Gpr3 = (ULONG)Parameter; 00111 } 00112 00113 NTSTATUS 00114 RtlRemoteCall( 00115 HANDLE Process, 00116 HANDLE Thread, 00117 PVOID CallSite, 00118 ULONG ArgumentCount, 00119 PULONG Arguments, 00120 BOOLEAN PassContext, 00121 BOOLEAN AlreadySuspended 00122 ) 00123 00124 /*++ 00125 00126 Routine Description: 00127 00128 This function calls a procedure in another thread/process, by using 00129 NtGetContext and NtSetContext. Parameters are passed to the target 00130 procedure via the nonvolatile registers (s0 - s7). 00131 00132 Arguments: 00133 00134 Process - Supplies an open handle to the target process. 00135 00136 Thread - Supplies an open handle to the target thread within the target 00137 process. 00138 00139 CallSize - Supplies the address of the procedure to call in the target 00140 process. 00141 00142 ArgumentCount - Supplies the number of 32 bit parameters to pass to the 00143 target procedure. 00144 00145 Arguments - Supplies a pointer to the array of 32 bit parameters to pass. 00146 00147 PassContext - Supplies a boolean value that determines whether a parameter 00148 is to be passed that points to a context record. This parameter is 00149 ignored on MIPS hosts. 00150 00151 AlreadySuspended - Supplies a boolean value that determines whether the 00152 target thread is already in a suspended or waiting state. 00153 00154 Return Value: 00155 00156 Status - Status value 00157 00158 --*/ 00159 00160 { 00161 00162 NTSTATUS Status; 00163 CONTEXT Context; 00164 ULONG NewSp; 00165 00166 if (ArgumentCount > 8) { 00167 return(STATUS_INVALID_PARAMETER); 00168 } 00169 00170 // 00171 // If necessary, suspend the target thread before getting the thread's 00172 // current state. 00173 // 00174 00175 if (AlreadySuspended == FALSE) { 00176 Status = NtSuspendThread(Thread, NULL); 00177 if (NT_SUCCESS(Status) == FALSE) { 00178 return(Status); 00179 } 00180 } 00181 00182 // 00183 // Get the current state of the target thread. 00184 // 00185 00186 Context.ContextFlags = CONTEXT_FULL; 00187 Status = NtGetContextThread(Thread, &Context); 00188 if (NT_SUCCESS(Status) == FALSE) { 00189 if (AlreadySuspended == FALSE) { 00190 NtResumeThread(Thread, NULL); 00191 } 00192 return(Status); 00193 } 00194 00195 if (AlreadySuspended ) { 00196 00197 Context.Gpr3 = STATUS_ALERTED; 00198 } 00199 00200 // 00201 // Pass the parameters to the other thread via the non-volatile registers 00202 // s0 - s7. The context record is passed on the stack of the target thread. 00203 // 00204 00205 NewSp = Context.Gpr1 - sizeof(CONTEXT) - STK_MIN_FRAME; 00206 Status = NtWriteVirtualMemory(Process, (PVOID)(NewSp + STK_MIN_FRAME), &Context, 00207 sizeof(CONTEXT), NULL); 00208 Status = NtWriteVirtualMemory(Process, (PVOID)NewSp, &Context.Gpr1, 00209 sizeof(ULONG), NULL); 00210 if (NT_SUCCESS(Status) == FALSE) { 00211 if (AlreadySuspended == FALSE) { 00212 NtResumeThread(Thread, NULL); 00213 } 00214 return(Status); 00215 } 00216 00217 Context.Gpr1 = NewSp; 00218 00219 if (PassContext) { 00220 Context.Gpr14 = NewSp + STK_MIN_FRAME; 00221 RtlMoveMemory(&Context.Gpr15, Arguments, ArgumentCount * sizeof(ULONG)); 00222 00223 } else { 00224 00225 RtlMoveMemory(&Context.Gpr14, Arguments, ArgumentCount * sizeof(ULONG)); 00226 } 00227 00228 // 00229 // Set the address of the target code into FIR and set the thread context 00230 // to cause the target procedure to be executed. 00231 // 00232 00233 Context.Iar = (ULONG)CallSite; // Set context will dereference the 00234 Context.Gpr2 = 0; // FNDESC in the remote threads context 00235 Status = NtSetContextThread(Thread, &Context); 00236 if (AlreadySuspended == FALSE) { 00237 NtResumeThread(Thread, NULL); 00238 } 00239 return(Status); 00240 }

Generated on Sat May 15 19:39:33 2004 for test by doxygen 1.3.7