00165                    :
00166 
00167     This function calls a 
procedure in another thread/process, 
using
00168     NtGetContext and NtSetContext.  Parameters are passed to 
the
00169     target 
procedure via its stack.
00170 
00171 Arguments:
00172 
00173     Process - 
Handle of 
the target process
00174 
00175     Thread - 
Handle of 
the target thread within that process
00176 
00177     CallSite - Address of 
the procedure to call in 
the target process.
00178 
00179     ArgumentCount - Number of parameters to pass to 
the target
00180                     
procedure.
00181 
00182     Arguments - Pointer to 
the array of parameters to pass.
00183 
00184     PassContext - 
TRUE if an additional parameter 
is to be passed that
00185         points to a context record.
00186 
00187     AlreadySuspended - 
TRUE if the target thread 
is already in a suspended
00188                        or waiting state.
00189 
00190 Return Value:
00191 
00192     
Status - 
Status value
00193 
00194 --*/
00195 
00196 {
00197     
NTSTATUS Status;
00198     CONTEXT Context;
00199     ULONG_PTR ContextAddress;
00200     ULONG_PTR NewSp;
00201     ULONG_PTR NewBspStore;
00202     ULONGLONG ArgumentsCopy[10];
00203     PVOID ptr;
00204     ULONG 
Count = 0;
00205     ULONG ShiftCount;
00206     BOOLEAN RnatSaved = 
FALSE;
00207 
00208 
00209     
RTL_PAGED_CODE();
00210 
00211     
if (ArgumentCount > 8)
00212         
return STATUS_INVALID_PARAMETER;
00213 
00214     
00215     
00216     
00217 
00218     
if (AlreadySuspended == 
FALSE) {
00219         
Status = 
NtSuspendThread(Thread, NULL);
00220         
if (
NT_SUCCESS(Status) == 
FALSE) {
00221             
return(
Status);
00222         }
00223     }
00224 
00225     
00226     
00227     
00228 
00229     Context.ContextFlags = 
CONTEXT_FULL;
00230     
Status = 
NtGetContextThread(Thread, &Context);
00231     
if (
NT_SUCCESS(Status) == 
FALSE) {
00232         
if (AlreadySuspended == 
FALSE) {
00233             
NtResumeThread(Thread, NULL);
00234         }
00235         
return(
Status);
00236     }
00237 
00238     
if (AlreadySuspended) {
00239         Context.IntV0 = STATUS_ALERTED;
00240     }
00241 
00242     
00243     
00244     
00245     
00246     
00247     
00248 
00249     ContextAddress = (((ULONG_PTR)Context.IntSp + 0xf) & 0xf) - 
sizeof(CONTEXT);
00250     NewSp = ContextAddress - STACK_SCRATCH_AREA;
00251     
Status = 
NtWriteVirtualMemory(Process, (PVOID)ContextAddress, &Context,
00252                   
sizeof(CONTEXT), NULL);
00253 
00254     
if (
NT_SUCCESS(Status) == 
FALSE) {
00255         
if (AlreadySuspended == 
FALSE) {
00256             
NtResumeThread(Thread, NULL);
00257         }
00258         
return(
Status);
00259     }
00260 
00261     RtlZeroMemory((PVOID)ArgumentsCopy, 
sizeof(ArgumentsCopy));
00262     NewBspStore = (ULONG_PTR) Context.RsBSPSTORE;
00263 
00264     
if (PassContext) {
00265         
if ( (NewBspStore & 0x1F8) == 0x1F8 ) {
00266             ArgumentsCopy[
Count++] = Context.RsRNAT;
00267             NewBspStore += 
sizeof(ULONGLONG);
00268             RnatSaved = 
TRUE;
00269         }
00270         ShiftCount = (ULONG) (NewBspStore & 0x1F8) >> 3;
00271         Context.RsRNAT &= ~(0x1 << ShiftCount);
00272         ArgumentsCopy[
Count++] = ContextAddress;
00273         NewBspStore += 
sizeof(ULONGLONG);
00274     }
00275 
00276     
for (; ArgumentCount != 0 ; ArgumentCount--) {
00277         
if ( (RnatSaved == 
FALSE) && ((NewBspStore & 0x1F8) == 0x1F8) ) {
00278             ArgumentsCopy[
Count++] = Context.RsRNAT;
00279             NewBspStore += 
sizeof(ULONGLONG);
00280             RnatSaved = 
TRUE;
00281         }
00282         ShiftCount = (ULONG)(NewBspStore & 0x1F8) >> 3;
00283         Context.RsRNAT &= ~(0x1 << ShiftCount);
00284         ArgumentsCopy[
Count++] = (ULONGLONG)(*Arguments++);
00285         NewBspStore += 
sizeof(ULONGLONG);
00286     }
00287 
00288     
if ( (RnatSaved == 
FALSE) && ((NewBspStore & 0x1F8) == 0x1F8) ) {
00289         ArgumentsCopy[
Count++] = Context.RsRNAT;
00290         NewBspStore += 
sizeof(ULONGLONG);
00291     }
00292 
00293     
00294     
00295     
00296 
00297     
if (
Count) {
00298         
Status = 
NtWriteVirtualMemory(Process,
00299                                       (PVOID)Context.RsBSPSTORE,
00300                                       ArgumentsCopy,
00301                                       Count * 
sizeof(ULONGLONG),
00302                                       NULL
00303                                       );
00304 
00305         
if (
NT_SUCCESS(Status) == 
FALSE) {
00306             
if (AlreadySuspended == 
FALSE) {
00307                 
NtResumeThread(Thread, NULL);
00308             }
00309             
return(
Status);
00310         }
00311     }
00312 
00313     
00314     
00315     
00316 
00317     Context.RsRSC = (RSC_MODE_LY<<RSC_MODE)
00318                    | (RSC_BE_LITTLE<<RSC_BE)
00319                    | (0x3<<RSC_PL);
00320 
00321     
00322     
00323     
00324 
00325     Context.StIFS = (ULONGLONG)
Count;       
00326     Context.RsBSP = Context.RsBSPSTORE;
00327 
00328     
00329     
00330     
00331     
00332 
00333     Context.IntSp = (ULONG_PTR)NewSp;
00334 
00335     
00336     
00337     
00338 
00339     Context.StIIP = (ULONG_PTR)CallSite;
00340 
00341     
00342     
00343     
00344 
00345     SANITIZE_FSR(Context.StFPSR, UserMode);
00346 
00347     
Status = 
NtSetContextThread(Thread, &Context);
00348     
if (!AlreadySuspended) {
00349         
NtResumeThread(Thread, NULL);
00350     }
00351 
00352     
return( 
Status );
00353 }