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 00021 Revise for MIPS environment. 00022 00023 --*/ 00024 00025 #include <ntos.h> 00026 00027 VOID 00028 RtlInitializeContext( 00029 IN HANDLE Process, 00030 OUT PCONTEXT Context, 00031 IN PVOID Parameter OPTIONAL, 00032 IN PVOID InitialPc OPTIONAL, 00033 IN PVOID InitialSp OPTIONAL 00034 ) 00035 00036 /*++ 00037 00038 Routine Description: 00039 00040 This function initializes a context structure so that it can be used in 00041 a subsequent call to NtCreateThread. 00042 00043 Arguments: 00044 00045 Context - Supplies a pointer to a context record that is to be initialized. 00046 00047 InitialPc - Supplies an initial program counter value. 00048 00049 InitialSp - Supplies an initial stack pointer value. 00050 00051 Return Value: 00052 00053 Raises STATUS_BAD_INITIAL_STACK if the value of InitialSp is not properly 00054 aligned. 00055 00056 Raises STATUS_BAD_INITIAL_PC if the value of InitialPc is not properly 00057 aligned. 00058 00059 --*/ 00060 00061 { 00062 00063 // 00064 // Check for proper initial stack and PC alignment. 00065 // 00066 00067 if (((ULONG)InitialSp & 0x7) != 0) { 00068 RtlRaiseStatus(STATUS_BAD_INITIAL_STACK); 00069 } 00070 if (((ULONG)InitialPc & 0x3) != 0) { 00071 RtlRaiseStatus(STATUS_BAD_INITIAL_PC); 00072 } 00073 00074 // 00075 // Initialize the integer registers to contain their register number. 00076 // 00077 00078 Context->XIntZero = 0; 00079 Context->XIntAt = 1; 00080 Context->XIntV0 = 2; 00081 Context->XIntV1 = 3; 00082 Context->XIntA0 = 4; 00083 Context->XIntA1 = 5; 00084 Context->XIntA2 = 6; 00085 Context->XIntA3 = 7; 00086 Context->XIntT0 = 8; 00087 Context->XIntT1 = 9; 00088 Context->XIntT2 = 10; 00089 Context->XIntT3 = 11; 00090 Context->XIntT4 = 12; 00091 Context->XIntT5 = 13; 00092 Context->XIntT6 = 14; 00093 Context->XIntT7 = 15; 00094 Context->XIntS0 = 16; 00095 Context->XIntS1 = 17; 00096 Context->XIntS2 = 18; 00097 Context->XIntS3 = 19; 00098 Context->XIntS4 = 20; 00099 Context->XIntS5 = 21; 00100 Context->XIntS6 = 22; 00101 Context->XIntS7 = 23; 00102 Context->XIntT8 = 24; 00103 Context->XIntT9 = 25; 00104 Context->XIntS8 = 30; 00105 Context->XIntLo = 0; 00106 Context->XIntHi = 0; 00107 00108 // 00109 // Initialize the floating point registers to contain zero in their upper 00110 // half and the integer value of their register number in the lower half. 00111 // 00112 00113 Context->FltF0 = 0; 00114 Context->FltF1 = 0; 00115 Context->FltF2 = 2; 00116 Context->FltF3 = 0; 00117 Context->FltF4 = 4; 00118 Context->FltF5 = 0; 00119 Context->FltF6 = 6; 00120 Context->FltF7 = 0; 00121 Context->FltF8 = 8; 00122 Context->FltF9 = 0; 00123 Context->FltF10 = 10; 00124 Context->FltF11 = 0; 00125 Context->FltF12 = 12; 00126 Context->FltF13 = 0; 00127 Context->FltF14 = 14; 00128 Context->FltF15 = 0; 00129 Context->FltF16 = 16; 00130 Context->FltF17 = 0; 00131 Context->FltF18 = 18; 00132 Context->FltF19 = 0; 00133 Context->FltF20 = 20; 00134 Context->FltF21 = 0; 00135 Context->FltF22 = 22; 00136 Context->FltF23 = 0; 00137 Context->FltF24 = 24; 00138 Context->FltF25 = 0; 00139 Context->FltF26 = 26; 00140 Context->FltF27 = 0; 00141 Context->FltF28 = 28; 00142 Context->FltF29 = 0; 00143 Context->FltF30 = 30; 00144 Context->FltF31 = 0; 00145 Context->Fsr = 0; 00146 00147 // 00148 // Initialize the control registers. 00149 // 00150 // N.B. The register gp is estabished at thread startup by the loader. 00151 // 00152 00153 Context->XIntGp = 0; 00154 Context->XIntSp = (LONG)InitialSp; 00155 Context->XIntRa = 1; 00156 Context->Fir = (ULONG)InitialPc; 00157 Context->Psr = 0; 00158 Context->ContextFlags = CONTEXT_FULL; 00159 00160 // 00161 // Set the initial context of the thread in a machine specific way. 00162 // 00163 00164 Context->XIntA0 = (LONG)Parameter; 00165 Context->XIntSp -= KTRAP_FRAME_ARGUMENTS; 00166 } 00167 00168 NTSTATUS 00169 RtlRemoteCall( 00170 HANDLE Process, 00171 HANDLE Thread, 00172 PVOID CallSite, 00173 ULONG ArgumentCount, 00174 PULONG Arguments, 00175 BOOLEAN PassContext, 00176 BOOLEAN AlreadySuspended 00177 ) 00178 00179 /*++ 00180 00181 Routine Description: 00182 00183 This function calls a procedure in another thread/process, by using 00184 NtGetContext and NtSetContext. Parameters are passed to the target 00185 procedure via the nonvolatile registers (s0 - s7). 00186 00187 Arguments: 00188 00189 Process - Supplies an open handle to the target process. 00190 00191 Thread - Supplies an open handle to the target thread within the target 00192 process. 00193 00194 CallSize - Supplies the address of the procedure to call in the target 00195 process. 00196 00197 ArgumentCount - Supplies the number of 32 bit parameters to pass to the 00198 target procedure. 00199 00200 Arguments - Supplies a pointer to the array of 32 bit parameters to pass. 00201 00202 PassContext - Supplies a boolean value that determines whether a parameter 00203 is to be passed that points to a context record. This parameter is 00204 ignored on MIPS hosts. 00205 00206 AlreadySuspended - Supplies a boolean value that determines whether the 00207 target thread is already in a suspended or waiting state. 00208 00209 Return Value: 00210 00211 Status - Status value 00212 00213 --*/ 00214 00215 { 00216 00217 NTSTATUS Status; 00218 CONTEXT Context; 00219 ULONG NewSp; 00220 00221 if (ArgumentCount > 8) { 00222 return(STATUS_INVALID_PARAMETER); 00223 } 00224 00225 // 00226 // If necessary, suspend the target thread before getting the thread's 00227 // current state. 00228 // 00229 00230 if (AlreadySuspended == FALSE) { 00231 Status = NtSuspendThread(Thread, NULL); 00232 if (NT_SUCCESS(Status) == FALSE) { 00233 return(Status); 00234 } 00235 } 00236 00237 // 00238 // Get the cuurent state of the target thread. 00239 // 00240 00241 Context.ContextFlags = CONTEXT_FULL; 00242 Status = NtGetContextThread(Thread, &Context); 00243 if (NT_SUCCESS(Status) == FALSE) { 00244 if (AlreadySuspended == FALSE) { 00245 NtResumeThread(Thread, NULL); 00246 } 00247 00248 return Status; 00249 } 00250 00251 if (AlreadySuspended) { 00252 Context.XIntV0 = (LONG)STATUS_ALERTED; 00253 } 00254 00255 // 00256 // Pass the parameters to the other thread via the non-volatile registers 00257 // s0 - s7. The context record is passed on the stack of the target thread. 00258 // 00259 00260 NewSp = (ULONG)(Context.XIntSp - sizeof(CONTEXT)); 00261 Status = NtWriteVirtualMemory(Process, 00262 (PVOID)NewSp, 00263 &Context, 00264 sizeof(CONTEXT), 00265 NULL); 00266 00267 if (NT_SUCCESS(Status) == FALSE) { 00268 if (AlreadySuspended == FALSE) { 00269 NtResumeThread(Thread, NULL); 00270 } 00271 00272 return Status; 00273 } 00274 00275 Context.XIntSp = (LONG)NewSp; 00276 if (PassContext) { 00277 Context.XIntS0 = (LONG)NewSp; 00278 RtlMoveMemory(&Context.XIntS1, Arguments, ArgumentCount * sizeof(ULONG)); 00279 00280 } else { 00281 RtlMoveMemory(&Context.XIntS0, Arguments, ArgumentCount * sizeof(ULONG)); 00282 } 00283 00284 // 00285 // Set the address of the target code into FIR and set the thread context 00286 // to cause the target procedure to be executed. 00287 // 00288 00289 Context.Fir = (ULONG)CallSite;; 00290 Status = NtSetContextThread(Thread, &Context); 00291 if (AlreadySuspended == FALSE) { 00292 NtResumeThread(Thread, NULL); 00293 } 00294 00295 return Status; 00296 }

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