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 Thomas Van Baak (tvb) 11-May-1992 00024 00025 Adapted for Alpha AXP. 00026 00027 --*/ 00028 00029 #include <nt.h> 00030 #include <ntrtl.h> 00031 #include <alphaops.h> 00032 00033 VOID 00034 RtlInitializeContext( 00035 IN HANDLE Process, 00036 OUT PCONTEXT Context, 00037 IN PVOID Parameter OPTIONAL, 00038 IN PVOID InitialPc OPTIONAL, 00039 IN PVOID InitialSp OPTIONAL 00040 ) 00041 00042 /*++ 00043 00044 Routine Description: 00045 00046 This function initializes a context structure so that it can be used in 00047 a subsequent call to NtCreateThread. 00048 00049 Arguments: 00050 00051 Process - Supplies an open handle to the target process. This argument 00052 is ignored by this function. 00053 00054 Context - Supplies a pointer to a context record that is to be initialized. 00055 00056 Parameter - Supplies an initial value for register A0. 00057 00058 InitialPc - Supplies an initial program counter value. 00059 00060 InitialSp - Supplies an initial stack pointer value. 00061 00062 Return Value: 00063 00064 Raises STATUS_BAD_INITIAL_STACK if the value of InitialSp is not properly 00065 aligned. 00066 00067 Raises STATUS_BAD_INITIAL_PC if the value of InitialPc is not properly 00068 aligned. 00069 00070 --*/ 00071 00072 { 00073 00074 // 00075 // Check for proper initial stack and PC alignment. 00076 // 00077 00078 if (((ULONG_PTR)InitialSp & 0xF) != 0) { 00079 RtlRaiseStatus(STATUS_BAD_INITIAL_STACK); 00080 } 00081 if (((ULONG_PTR)InitialPc & 0x3) != 0) { 00082 RtlRaiseStatus(STATUS_BAD_INITIAL_PC); 00083 } 00084 00085 // 00086 // Initialize the integer registers to contain their register number 00087 // (they must be initialized and using register numbers instead of 0 00088 // can be useful for debugging). Integer registers a0, ra, gp, and sp 00089 // are set later. 00090 // 00091 00092 Context->IntV0 = 0; 00093 Context->IntT0 = 1; 00094 Context->IntT1 = 2; 00095 Context->IntT2 = 3; 00096 Context->IntT3 = 4; 00097 Context->IntT4 = 5; 00098 Context->IntT5 = 6; 00099 Context->IntT6 = 7; 00100 Context->IntT7 = 8; 00101 Context->IntS0 = 9; 00102 Context->IntS1 = 10; 00103 Context->IntS2 = 11; 00104 Context->IntS3 = 12; 00105 Context->IntS4 = 13; 00106 Context->IntS5 = 14; 00107 Context->IntFp = 15; 00108 Context->IntA1 = 17; 00109 Context->IntA2 = 18; 00110 Context->IntA3 = 19; 00111 Context->IntA4 = 20; 00112 Context->IntA5 = 21; 00113 Context->IntT8 = 22; 00114 Context->IntT9 = 23; 00115 Context->IntT10 = 24; 00116 Context->IntT11 = 25; 00117 Context->IntT12 = 27; 00118 Context->IntAt = 28; 00119 00120 // 00121 // Initialize the floating point registers to contain the integer value 00122 // of their register number (they must be initialized and using register 00123 // numbers instead of 0 can be useful for debugging). 00124 // 00125 00126 Context->FltF0 = 0; 00127 Context->FltF1 = 1; 00128 Context->FltF2 = 2; 00129 Context->FltF3 = 3; 00130 Context->FltF4 = 4; 00131 Context->FltF5 = 5; 00132 Context->FltF6 = 6; 00133 Context->FltF7 = 7; 00134 Context->FltF8 = 8; 00135 Context->FltF9 = 9; 00136 Context->FltF10 = 10; 00137 Context->FltF11 = 11; 00138 Context->FltF12 = 12; 00139 Context->FltF13 = 13; 00140 Context->FltF14 = 14; 00141 Context->FltF15 = 15; 00142 Context->FltF16 = 16; 00143 Context->FltF17 = 17; 00144 Context->FltF18 = 18; 00145 Context->FltF19 = 19; 00146 Context->FltF20 = 20; 00147 Context->FltF21 = 21; 00148 Context->FltF22 = 22; 00149 Context->FltF23 = 23; 00150 Context->FltF24 = 24; 00151 Context->FltF25 = 25; 00152 Context->FltF26 = 26; 00153 Context->FltF27 = 27; 00154 Context->FltF28 = 28; 00155 Context->FltF29 = 29; 00156 Context->FltF30 = 30; 00157 Context->FltF31 = 0; 00158 00159 // 00160 // Initialize the control registers. 00161 // 00162 // Gp: will be set in LdrpInitialize at thread startup. 00163 // Ra: some debuggers compare for 1 as a top-of-stack indication. 00164 // 00165 // N.B. On 32-bit systems, ULONG becomes canonical longword with the 00166 // (ULONGLONG)(LONG) cast. 00167 // 00168 00169 Context->IntGp = 0; 00170 Context->IntSp = (ULONGLONG)(LONG_PTR)InitialSp; 00171 Context->IntRa = 1; 00172 Context->Fir = (ULONGLONG)(LONG_PTR)InitialPc; 00173 00174 // 00175 // Set default Alpha floating point control register values. 00176 // 00177 00178 Context->Fpcr = (ULONGLONG)0; 00179 ((PFPCR)(&Context->Fpcr))->DynamicRoundingMode = ROUND_TO_NEAREST; 00180 Context->SoftFpcr = (ULONGLONG)0; 00181 00182 Context->Psr = 0; 00183 Context->ContextFlags = CONTEXT_FULL; 00184 00185 // 00186 // Set the initial context of the thread in a machine specific way. 00187 // 00188 00189 Context->IntA0 = (ULONGLONG)(LONG_PTR)Parameter; 00190 } 00191 00192 NTSTATUS 00193 RtlRemoteCall( 00194 HANDLE Process, 00195 HANDLE Thread, 00196 PVOID CallSite, 00197 ULONG ArgumentCount, 00198 PULONG_PTR Arguments, 00199 BOOLEAN PassContext, 00200 BOOLEAN AlreadySuspended 00201 ) 00202 00203 /*++ 00204 00205 Routine Description: 00206 00207 This function calls a procedure in another thread/process by using 00208 NtGetContext and NtSetContext. Parameters are passed to the target 00209 procedure via the nonvolatile registers (s0 - s5). 00210 00211 Arguments: 00212 00213 Process - Supplies an open handle to the target process. 00214 00215 Thread - Supplies an open handle to the target thread within the target 00216 process. 00217 00218 CallSite - Supplies the address of the procedure to call in the target 00219 process. 00220 00221 ArgumentCount - Supplies the number of parameters to pass to the 00222 target procedure. 00223 00224 Arguments - Supplies a pointer to the array of parameters to pass. 00225 00226 PassContext - Supplies a boolean value that determines whether a parameter 00227 is to be passed that points to a context record. This parameter is 00228 ignored on MIPS and Alpha hosts. 00229 00230 AlreadySuspended - Supplies a boolean value that determines whether the 00231 target thread is already in a suspended or waiting state. 00232 00233 Return Value: 00234 00235 Status - Status value. 00236 00237 --*/ 00238 00239 { 00240 00241 NTSTATUS Status; 00242 CONTEXT Context; 00243 ULONG Index; 00244 ULONGLONG NewSp; 00245 00246 if ((ArgumentCount > 6) || 00247 (PassContext && (ArgumentCount > 5))) { 00248 return(STATUS_INVALID_PARAMETER); 00249 } 00250 00251 // 00252 // If necessary, suspend the target thread before getting the thread's 00253 // current state. 00254 // 00255 00256 if (AlreadySuspended == FALSE) { 00257 Status = NtSuspendThread(Thread, NULL); 00258 if (NT_SUCCESS(Status) == FALSE) { 00259 return(Status); 00260 } 00261 } 00262 00263 // 00264 // Get the current state of the target thread. 00265 // 00266 00267 Context.ContextFlags = CONTEXT_FULL; 00268 Status = NtGetContextThread(Thread, &Context); 00269 if (NT_SUCCESS(Status) == FALSE) { 00270 if (AlreadySuspended == FALSE) { 00271 NtResumeThread(Thread, NULL); 00272 } 00273 return(Status); 00274 } 00275 00276 if (AlreadySuspended) { 00277 Context.IntV0 = STATUS_ALERTED; 00278 } 00279 00280 // 00281 // Pass the parameters to the other thread via the non-volatile registers 00282 // s0 - s5. The context record is passed on the stack of the target thread. 00283 // 00284 00285 NewSp = Context.IntSp - sizeof(CONTEXT); 00286 Status = NtWriteVirtualMemory(Process, (PVOID)NewSp, &Context, 00287 sizeof(CONTEXT), NULL); 00288 if (NT_SUCCESS(Status) == FALSE) { 00289 if (AlreadySuspended == FALSE) { 00290 NtResumeThread(Thread, NULL); 00291 } 00292 return(Status); 00293 } 00294 00295 // 00296 // N.B. On 32-bit system each ULONG argument is converted to canonical 00297 // form with the (ULONGLONG)(LONG) cast as required by the calling 00298 // standard. 00299 // 00300 00301 Context.IntSp = NewSp; 00302 00303 if (PassContext) { 00304 Context.IntS0 = NewSp; 00305 for (Index = 0; Index < ArgumentCount; Index += 1) { 00306 (&Context.IntS1)[Index] = (ULONGLONG)(LONG_PTR)Arguments[Index]; 00307 } 00308 00309 } else { 00310 for (Index = 0; Index < ArgumentCount; Index += 1) { 00311 (&Context.IntS0)[Index] = (ULONGLONG)(LONG_PTR)Arguments[Index]; 00312 } 00313 } 00314 00315 // 00316 // Set the address of the target code into FIR and set the thread context 00317 // to cause the target procedure to be executed. 00318 // 00319 // N.B. The PVOID CallSite is stored as a canonical longword in order 00320 // for Fir to be a valid 64-bit address. 00321 // 00322 00323 Context.Fir = (ULONGLONG)(LONG_PTR)CallSite; 00324 Status = NtSetContextThread(Thread, &Context); 00325 if (AlreadySuspended == FALSE) { 00326 NtResumeThread(Thread, NULL); 00327 } 00328 return(Status); 00329 }

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