00205                    :
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     
00253     
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     
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     
00282     
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     
00297     
00298     
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     
00317     
00318     
00319     
00320     
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 }
}