00126 :
00127
00128 This function calls a
procedure in another thread/process, by
using
00129 NtGetContext and NtSetContext. Parameters are passed to
the target
00130
procedure via
the nonvolatile registers (s0 - s7).
00131
00132 Arguments:
00133
00134 Process - Supplies an open handle to
the target process.
00135
00136 Thread - Supplies an open handle to
the target thread within
the target
00137 process.
00138
00139 CallSize - Supplies
the address of
the procedure to call in
the target
00140 process.
00141
00142 ArgumentCount - Supplies
the number of 32 bit parameters to pass to
the
00143 target
procedure.
00144
00145 Arguments - Supplies a pointer to
the array of 32 bit parameters to pass.
00146
00147 PassContext - Supplies a
boolean value that determines whether a parameter
00148
is to be passed that points to a context record. This parameter
is
00149 ignored on MIPS hosts.
00150
00151 AlreadySuspended - Supplies a
boolean value that determines whether
the
00152 target thread
is already in a suspended or waiting state.
00153
00154 Return Value:
00155
00156
Status -
Status value
00157
00158 --*/
00159
00160 {
00161
00162
NTSTATUS Status;
00163 CONTEXT Context;
00164 ULONG NewSp;
00165
00166
if (ArgumentCount > 8) {
00167
return(STATUS_INVALID_PARAMETER);
00168 }
00169
00170
00171
00172
00173
00174
00175
if (AlreadySuspended ==
FALSE) {
00176
Status =
NtSuspendThread(Thread, NULL);
00177
if (
NT_SUCCESS(Status) ==
FALSE) {
00178
return(
Status);
00179 }
00180 }
00181
00182
00183
00184
00185
00186 Context.ContextFlags =
CONTEXT_FULL;
00187
Status =
NtGetContextThread(Thread, &Context);
00188
if (
NT_SUCCESS(Status) ==
FALSE) {
00189
if (AlreadySuspended ==
FALSE) {
00190
NtResumeThread(Thread, NULL);
00191 }
00192
return(
Status);
00193 }
00194
00195
if (AlreadySuspended ) {
00196
00197 Context.Gpr3 = STATUS_ALERTED;
00198 }
00199
00200
00201
00202
00203
00204
00205 NewSp = Context.Gpr1 -
sizeof(CONTEXT) -
STK_MIN_FRAME;
00206
Status =
NtWriteVirtualMemory(Process, (PVOID)(NewSp + STK_MIN_FRAME), &Context,
00207
sizeof(CONTEXT), NULL);
00208
Status =
NtWriteVirtualMemory(Process, (PVOID)NewSp, &Context.Gpr1,
00209
sizeof(ULONG), NULL);
00210
if (
NT_SUCCESS(Status) ==
FALSE) {
00211
if (AlreadySuspended ==
FALSE) {
00212
NtResumeThread(Thread, NULL);
00213 }
00214
return(
Status);
00215 }
00216
00217 Context.Gpr1 = NewSp;
00218
00219
if (PassContext) {
00220 Context.Gpr14 = NewSp +
STK_MIN_FRAME;
00221 RtlMoveMemory(&Context.Gpr15, Arguments, ArgumentCount *
sizeof(ULONG));
00222
00223 }
else {
00224
00225 RtlMoveMemory(&Context.Gpr14, Arguments, ArgumentCount *
sizeof(ULONG));
00226 }
00227
00228
00229
00230
00231
00232
00233 Context.Iar = (ULONG)CallSite;
00234 Context.Gpr2 = 0;
00235
Status =
NtSetContextThread(Thread, &Context);
00236
if (AlreadySuspended ==
FALSE) {
00237
NtResumeThread(Thread, NULL);
00238 }
00239
return(
Status);
00240 }
}