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) 1989 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 The interfaces exported from this module are portable, but they must 00013 be re-implemented for each architecture. 00014 00015 Author: 00016 00017 Mark Lucovsky (markl) 20-Jun-1989 00018 00019 Revision History: 00020 00021 Bryan Willman (bryanwi) 8-Mar-90 00022 00023 Ported to the 80386 00024 00025 --*/ 00026 00027 #include "ntrtlp.h" 00028 00029 #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME) 00030 #pragma alloc_text(PAGE,RtlInitializeContext) 00031 #pragma alloc_text(PAGE,RtlRemoteCall) 00032 #endif 00033 00034 00035 VOID 00036 RtlInitializeContext( 00037 IN HANDLE Process, 00038 OUT PCONTEXT Context, 00039 IN PVOID Parameter OPTIONAL, 00040 IN PVOID InitialPc OPTIONAL, 00041 IN PVOID InitialSp OPTIONAL 00042 ) 00043 00044 /*++ 00045 00046 Routine Description: 00047 00048 This function initializes a context structure so that it can 00049 be used in a subsequent call to NtCreateThread. 00050 00051 Arguments: 00052 00053 Context - Supplies a context buffer to be initialized by this routine. 00054 00055 InitialPc - Supplies an initial program counter value. 00056 00057 InitialSp - Supplies an initial stack pointer value. 00058 00059 Return Value: 00060 00061 Raises STATUS_BAD_INITIAL_STACK if the value of InitialSp is not properly 00062 aligned. 00063 00064 Raises STATUS_BAD_INITIAL_PC if the value of InitialPc is not properly 00065 aligned. 00066 00067 --*/ 00068 00069 { 00070 RTL_PAGED_CODE(); 00071 00072 Context->Eax = 0L; 00073 Context->Ebx = 1L; 00074 Context->Ecx = 2L; 00075 Context->Edx = 3L; 00076 Context->Esi = 4L; 00077 Context->Edi = 5L; 00078 Context->Ebp = 0L; 00079 00080 Context->SegGs = 0; 00081 Context->SegFs = KGDT_R3_TEB; 00082 Context->SegEs = KGDT_R3_DATA; 00083 Context->SegDs = KGDT_R3_DATA; 00084 Context->SegSs = KGDT_R3_DATA; 00085 Context->SegCs = KGDT_R3_CODE; 00086 00087 Context->EFlags = 0x200L; // force interrupts on, clear all else. 00088 00089 // 00090 // Even though these are optional, they are used as is, since NULL 00091 // is what these would have been initialized to anyway 00092 // 00093 00094 Context->Esp = (ULONG) InitialSp; 00095 Context->Eip = (ULONG) InitialPc; 00096 00097 // 00098 // add code to check alignment and raise exception... 00099 // 00100 00101 Context->ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_SEGMENTS; 00102 00103 // 00104 // Set the initial context of the thread in a machine specific way. 00105 // ie, pass the initial parameter to the start address 00106 // 00107 00108 Context->Esp -= sizeof(Parameter); 00109 ZwWriteVirtualMemory(Process, 00110 (PVOID)Context->Esp, 00111 (PVOID)&Parameter, 00112 sizeof(Parameter), 00113 NULL); 00114 Context->Esp -= sizeof(Parameter); // Reserve room for ret address 00115 00116 00117 } 00118 00119 00120 00121 NTSTATUS 00122 RtlRemoteCall( 00123 HANDLE Process, 00124 HANDLE Thread, 00125 PVOID CallSite, 00126 ULONG ArgumentCount, 00127 PULONG Arguments, 00128 BOOLEAN PassContext, 00129 BOOLEAN AlreadySuspended 00130 ) 00131 00132 /*++ 00133 00134 Routine Description: 00135 00136 This function calls a procedure in another thread/process, using 00137 NtGetContext and NtSetContext. Parameters are passed to the 00138 target procedure via its stack. 00139 00140 Arguments: 00141 00142 Process - Handle of the target process 00143 00144 Thread - Handle of the target thread within that process 00145 00146 CallSite - Address of the procedure to call in the target process. 00147 00148 ArgumentCount - Number of 32 bit parameters to pass to the target 00149 procedure. 00150 00151 Arguments - Pointer to the array of 32 bit parameters to pass. 00152 00153 PassContext - TRUE if an additional parameter is to be passed that 00154 points to a context record. 00155 00156 AlreadySuspended - TRUE if the target thread is already in a suspended 00157 or waiting state. 00158 00159 Return Value: 00160 00161 Status - Status value 00162 00163 --*/ 00164 00165 { 00166 NTSTATUS Status; 00167 CONTEXT Context; 00168 ULONG NewSp; 00169 ULONG ArgumentsCopy[5]; 00170 00171 RTL_PAGED_CODE(); 00172 00173 if (ArgumentCount > 4) 00174 return STATUS_INVALID_PARAMETER; 00175 00176 // 00177 // If necessary, suspend the guy before with we mess with his stack. 00178 // 00179 if (!AlreadySuspended) { 00180 Status = NtSuspendThread( Thread, NULL ); 00181 if (!NT_SUCCESS( Status )) { 00182 return( Status ); 00183 } 00184 } 00185 00186 00187 // 00188 // Get the context record for the target thread. 00189 // 00190 00191 Context.ContextFlags = CONTEXT_FULL; 00192 Status = NtGetContextThread( Thread, &Context ); 00193 if (!NT_SUCCESS( Status )) { 00194 if (!AlreadySuspended) { 00195 NtResumeThread( Thread, NULL ); 00196 } 00197 return( Status ); 00198 } 00199 00200 00201 // 00202 // Pass all parameters on the stack, regardless of whether a 00203 // a context record is passed. 00204 // 00205 00206 // 00207 // Put Context Record on stack first, so it is above other args. 00208 // 00209 NewSp = Context.Esp; 00210 if (PassContext) { 00211 NewSp -= sizeof( CONTEXT ); 00212 Status = NtWriteVirtualMemory( Process, 00213 (PVOID)NewSp, 00214 &Context, 00215 sizeof( CONTEXT ), 00216 NULL 00217 ); 00218 if (!NT_SUCCESS( Status )) { 00219 if (!AlreadySuspended) { 00220 NtResumeThread( Thread, NULL ); 00221 } 00222 return( Status ); 00223 } 00224 ArgumentsCopy[0] = NewSp; // pass pointer to context 00225 RtlMoveMemory(&(ArgumentsCopy[1]),Arguments,ArgumentCount*sizeof( ULONG )); 00226 ArgumentCount++; 00227 } 00228 else { 00229 RtlMoveMemory(ArgumentsCopy,Arguments,ArgumentCount*sizeof( ULONG )); 00230 } 00231 00232 // 00233 // Copy the arguments onto the target stack 00234 // 00235 if (ArgumentCount) { 00236 NewSp -= ArgumentCount * sizeof( ULONG ); 00237 Status = NtWriteVirtualMemory( Process, 00238 (PVOID)NewSp, 00239 ArgumentsCopy, 00240 ArgumentCount * sizeof( ULONG ), 00241 NULL 00242 ); 00243 if (!NT_SUCCESS( Status )) { 00244 if (!AlreadySuspended) { 00245 NtResumeThread( Thread, NULL ); 00246 } 00247 return( Status ); 00248 } 00249 } 00250 00251 // 00252 // Set the address of the target code into Eip, the new target stack 00253 // into Esp, and reload context to make it happen. 00254 // 00255 Context.Esp = NewSp; 00256 Context.Eip = (ULONG)CallSite; 00257 Status = NtSetContextThread( Thread, &Context ); 00258 if (!AlreadySuspended) { 00259 NtResumeThread( Thread, NULL ); 00260 } 00261 00262 return( Status ); 00263 }

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