00181                    :
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     
00227     
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     
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     
00257     
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     
00286     
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 }
}