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 }
}