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 }