00134 :
00135
00136 This function calls a
procedure in another thread/process,
using
00137 NtGetContext and NtSetContext. Parameters are passed to
the
00138 target
procedure via its stack.
00139
00140 Arguments:
00141
00142 Process -
Handle of
the target process
00143
00144 Thread -
Handle of
the target thread within that process
00145
00146 CallSite - Address of
the procedure to call in
the target process.
00147
00148 ArgumentCount - Number of 32 bit parameters to pass to
the target
00149
procedure.
00150
00151 Arguments - Pointer to
the array of 32 bit parameters to pass.
00152
00153 PassContext -
TRUE if an additional parameter
is to be passed that
00154 points to a context record.
00155
00156 AlreadySuspended -
TRUE if the target thread
is already in a suspended
00157 or waiting state.
00158
00159 Return Value:
00160
00161
Status -
Status value
00162
00163 --*/
00164
00165 {
00166
NTSTATUS Status;
00167 CONTEXT Context;
00168 ULONG NewSp;
00169 ULONG ArgumentsCopy[5];
00170
00171
RTL_PAGED_CODE();
00172
00173
if (ArgumentCount > 4)
00174
return STATUS_INVALID_PARAMETER;
00175
00176
00177
00178
00179
if (!AlreadySuspended) {
00180
Status =
NtSuspendThread( Thread, NULL );
00181
if (!
NT_SUCCESS( Status )) {
00182
return(
Status );
00183 }
00184 }
00185
00186
00187
00188
00189
00190
00191 Context.ContextFlags =
CONTEXT_FULL;
00192
Status =
NtGetContextThread( Thread, &Context );
00193
if (!
NT_SUCCESS( Status )) {
00194
if (!AlreadySuspended) {
00195
NtResumeThread( Thread, NULL );
00196 }
00197
return(
Status );
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 NewSp = Context.Esp;
00210
if (PassContext) {
00211 NewSp -=
sizeof( CONTEXT );
00212
Status =
NtWriteVirtualMemory( Process,
00213 (PVOID)NewSp,
00214 &Context,
00215
sizeof( CONTEXT ),
00216 NULL
00217 );
00218
if (!
NT_SUCCESS( Status )) {
00219
if (!AlreadySuspended) {
00220
NtResumeThread( Thread, NULL );
00221 }
00222
return(
Status );
00223 }
00224 ArgumentsCopy[0] = NewSp;
00225 RtlMoveMemory(&(ArgumentsCopy[1]),Arguments,ArgumentCount*
sizeof( ULONG ));
00226 ArgumentCount++;
00227 }
00228
else {
00229 RtlMoveMemory(ArgumentsCopy,Arguments,ArgumentCount*
sizeof( ULONG ));
00230 }
00231
00232
00233
00234
00235
if (ArgumentCount) {
00236 NewSp -= ArgumentCount *
sizeof( ULONG );
00237
Status =
NtWriteVirtualMemory( Process,
00238 (PVOID)NewSp,
00239 ArgumentsCopy,
00240 ArgumentCount *
sizeof( ULONG ),
00241 NULL
00242 );
00243
if (!
NT_SUCCESS( Status )) {
00244
if (!AlreadySuspended) {
00245
NtResumeThread( Thread, NULL );
00246 }
00247
return(
Status );
00248 }
00249 }
00250
00251
00252
00253
00254
00255 Context.Esp = NewSp;
00256 Context.Eip = (ULONG)CallSite;
00257
Status =
NtSetContextThread( Thread, &Context );
00258
if (!AlreadySuspended) {
00259
NtResumeThread( Thread, NULL );
00260 }
00261
00262
return(
Status );
00263 }
}