00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "psp.h"
00022
00023
VOID
00024
PspQueueApcSpecialApc(
00025 IN
PKAPC Apc,
00026 IN PKNORMAL_ROUTINE *NormalRoutine,
00027 IN PVOID *NormalContext,
00028 IN PVOID *SystemArgument1,
00029 IN PVOID *SystemArgument2
00030 );
00031
00032
#ifdef ALLOC_PRAGMA
00033
#pragma alloc_text(PAGE, NtGetContextThread)
00034
#pragma alloc_text(PAGE, NtSetContextThread)
00035
#pragma alloc_text(PAGE, NtQueueApcThread)
00036
#pragma alloc_text(PAGE, PspQueueApcSpecialApc )
00037
#endif
00038
00039
VOID
00040 PspQueueApcSpecialApc(
00041 IN
PKAPC Apc,
00042 IN PKNORMAL_ROUTINE *NormalRoutine,
00043 IN PVOID *NormalContext,
00044 IN PVOID *SystemArgument1,
00045 IN PVOID *SystemArgument2
00046 )
00047 {
00048
PAGED_CODE();
00049
00050
ExFreePool(Apc);
00051 }
00052
00053 NTSYSAPI
00054
NTSTATUS
00055 NTAPI
00056 NtQueueApcThread(
00057 IN HANDLE ThreadHandle,
00058 IN PPS_APC_ROUTINE ApcRoutine,
00059 IN PVOID ApcArgument1,
00060 IN PVOID ApcArgument2,
00061 IN PVOID ApcArgument3
00062 )
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 {
00092
PETHREAD Thread;
00093
NTSTATUS st;
00094
KPROCESSOR_MODE Mode;
00095 KIRQL Irql;
00096
PKAPC Apc;
00097
00098
PAGED_CODE();
00099
00100 Mode = KeGetPreviousMode();
00101
00102 st =
ObReferenceObjectByHandle(
00103
ThreadHandle,
00104 THREAD_SET_CONTEXT,
00105
PsThreadType,
00106 Mode,
00107 (PVOID *)&Thread,
00108
NULL
00109 );
00110
00111
if (
NT_SUCCESS(st) ) {
00112 st = STATUS_SUCCESS;
00113
if (
IS_SYSTEM_THREAD(Thread) ) {
00114 st = STATUS_INVALID_HANDLE;
00115 }
00116
else {
00117 Apc =
ExAllocatePoolWithQuotaTag(
00118 (
NonPagedPool |
POOL_QUOTA_FAIL_INSTEAD_OF_RAISE),
00119
sizeof(*Apc),
00120 'pasP'
00121 );
00122
00123
if ( !Apc ) {
00124 st = STATUS_NO_MEMORY;
00125 }
00126
else {
00127
KeInitializeApc(
00128 Apc,
00129 &Thread->Tcb,
00130
OriginalApcEnvironment,
00131
PspQueueApcSpecialApc,
00132
NULL,
00133 (
PKNORMAL_ROUTINE)ApcRoutine,
00134
UserMode,
00135 ApcArgument1
00136 );
00137
00138
if ( !
KeInsertQueueApc(Apc,ApcArgument2,ApcArgument3,0) ) {
00139
ExFreePool(Apc);
00140 st = STATUS_UNSUCCESSFUL;
00141 }
00142 }
00143 }
00144
ObDereferenceObject(Thread);
00145 }
00146
00147
return st;
00148 }
00149
00150
NTSTATUS
00151 NtGetContextThread(
00152 IN HANDLE ThreadHandle,
00153 IN OUT PCONTEXT ThreadContext
00154 )
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 {
00181
00182 ULONG Alignment;
00183 ULONG ContextFlags;
00184
GETSETCONTEXT ContextFrame;
00185 ULONG ContextLength;
00186 KIRQL Irql;
00187
KPROCESSOR_MODE Mode;
00188
NTSTATUS Status;
00189
PETHREAD Thread;
00190
00191
PAGED_CODE();
00192
00193
00194
00195
00196
00197 Mode = KeGetPreviousMode();
00198
Status =
ObReferenceObjectByHandle(
ThreadHandle,
00199 THREAD_GET_CONTEXT,
00200
PsThreadType,
00201 Mode,
00202 (PVOID *)&Thread,
00203
NULL);
00204
00205
00206
00207
00208
00209
00210
if (
NT_SUCCESS(
Status)) {
00211
00212
00213
00214
00215
00216
00217
if (
IS_SYSTEM_THREAD(Thread) ==
FALSE) {
00218
00219
00220
00221
00222
00223
try {
00224
00225
00226
00227
00228
00229
00230 Alignment = CONTEXT_ALIGN;
00231 ContextFlags =
ProbeAndReadUlong(&
ThreadContext->ContextFlags);
00232 ContextLength =
sizeof(CONTEXT);
00233
00234
#if defined(_X86_)
00235
00236
00237
00238
00239
if ((ContextFlags & CONTEXT_EXTENDED_REGISTERS) != CONTEXT_EXTENDED_REGISTERS) {
00240 ContextLength = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
00241 }
00242
#endif
00243
00244
#if defined(_MIPS_)
00245
00246
00247
00248
00249
00250
00251
00252
if ((ContextFlags &
CONTEXT_EXTENDED_INTEGER) !=
CONTEXT_EXTENDED_INTEGER) {
00253 Alignment =
sizeof(ULONG);
00254 ContextLength = FIELD_OFFSET(CONTEXT, ContextFlags) + 4;
00255 }
00256
00257
#endif
00258
00259
if (Mode !=
KernelMode) {
00260
ProbeForWrite(
ThreadContext, ContextLength, Alignment);
00261 }
00262
00263 } except(
EXCEPTION_EXECUTE_HANDLER) {
00264
Status = GetExceptionCode();
00265 }
00266
00267
00268
00269
00270
00271
00272
if (
NT_SUCCESS(
Status)) {
00273
KeInitializeEvent(&ContextFrame.
OperationComplete,
00274 NotificationEvent,
00275
FALSE);
00276
00277 ContextFrame.
Context.ContextFlags = ContextFlags;
00278
00279 ContextFrame.
Mode = Mode;
00280
if (Thread ==
PsGetCurrentThread()) {
00281 ContextFrame.
Apc.
SystemArgument1 =
NULL;
00282 ContextFrame.
Apc.
SystemArgument2 = Thread;
00283
KeRaiseIrql(
APC_LEVEL, &Irql);
00284
PspGetSetContextSpecialApc(&ContextFrame.
Apc,
00285
NULL,
00286
NULL,
00287 &ContextFrame.
Apc.
SystemArgument1,
00288 &ContextFrame.
Apc.
SystemArgument2);
00289
00290
KeLowerIrql(Irql);
00291
00292
00293
00294
00295
00296
00297
try {
00298 RtlMoveMemory(
ThreadContext,
00299 &ContextFrame.
Context,
00300 ContextLength);
00301
00302 } except(
EXCEPTION_EXECUTE_HANDLER) {
00303 }
00304
00305 }
else {
00306
KeInitializeApc(&ContextFrame.
Apc,
00307 &Thread->Tcb,
00308
OriginalApcEnvironment,
00309
PspGetSetContextSpecialApc,
00310
NULL,
00311
NULL,
00312
KernelMode,
00313
NULL);
00314
00315
if (!
KeInsertQueueApc(&ContextFrame.
Apc,
NULL, Thread, 2)) {
00316
Status = STATUS_UNSUCCESSFUL;
00317
00318 }
else {
00319
KeWaitForSingleObject(&ContextFrame.
OperationComplete,
00320
Executive,
00321
KernelMode,
00322
FALSE,
00323
NULL);
00324
00325
00326
00327
00328
00329
00330
try {
00331 RtlMoveMemory(
ThreadContext,
00332 &ContextFrame.
Context,
00333 ContextLength);
00334
00335 } except(
EXCEPTION_EXECUTE_HANDLER) {
00336 }
00337 }
00338 }
00339 }
00340
00341 }
else {
00342
Status = STATUS_INVALID_HANDLE;
00343 }
00344
00345
ObDereferenceObject(Thread);
00346 }
00347
00348
return Status;
00349 }
00350
00351
NTSTATUS
00352 NtSetContextThread(
00353 IN HANDLE ThreadHandle,
00354 IN PCONTEXT ThreadContext
00355 )
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 {
00382
00383 ULONG Alignment;
00384 ULONG ContextFlags;
00385
GETSETCONTEXT ContextFrame;
00386 ULONG ContextLength;
00387 KIRQL Irql;
00388
KPROCESSOR_MODE Mode;
00389
NTSTATUS Status;
00390
PETHREAD Thread;
00391
00392
PAGED_CODE();
00393
00394
00395
00396
00397
00398 Mode = KeGetPreviousMode();
00399
Status =
ObReferenceObjectByHandle(
ThreadHandle,
00400 THREAD_SET_CONTEXT,
00401
PsThreadType,
00402 Mode,
00403 (PVOID *)&Thread,
00404
NULL);
00405
00406
00407
00408
00409
00410
00411
if (
NT_SUCCESS(
Status)) {
00412
00413
00414
00415
00416
00417
00418
if (
IS_SYSTEM_THREAD(Thread) ==
FALSE) {
00419
00420
00421
00422
00423
00424
try {
00425
00426
00427
00428
00429
00430
00431 Alignment = CONTEXT_ALIGN;
00432 ContextFlags =
ProbeAndReadUlong(&
ThreadContext->ContextFlags);
00433 ContextLength =
sizeof(CONTEXT);
00434
00435
#if defined(_X86_)
00436
00437
00438
00439
00440
if ((ContextFlags & CONTEXT_EXTENDED_REGISTERS) != CONTEXT_EXTENDED_REGISTERS) {
00441 ContextLength = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
00442 }
00443
#endif
00444
00445
#if defined(_MIPS_)
00446
00447
00448
00449
00450
00451
00452
00453
if ((ContextFlags &
CONTEXT_EXTENDED_INTEGER) !=
CONTEXT_EXTENDED_INTEGER) {
00454 Alignment =
sizeof(ULONG);
00455 ContextLength = FIELD_OFFSET(CONTEXT, ContextFlags) + 4;
00456 }
00457
00458
#endif
00459
00460
if (Mode !=
KernelMode) {
00461
ProbeForRead(
ThreadContext, ContextLength, Alignment);
00462 }
00463
00464 RtlMoveMemory(&ContextFrame.
Context,
ThreadContext, ContextLength);
00465
00466 } except(
EXCEPTION_EXECUTE_HANDLER) {
00467
Status = GetExceptionCode();
00468 }
00469
00470
00471
00472
00473
00474
00475
if (
NT_SUCCESS(
Status)) {
00476
KeInitializeEvent(&ContextFrame.
OperationComplete,
00477 NotificationEvent,
00478
FALSE);
00479
00480 ContextFrame.
Context.ContextFlags = ContextFlags;
00481
00482 ContextFrame.
Mode = Mode;
00483
if (Thread ==
PsGetCurrentThread()) {
00484 ContextFrame.
Apc.
SystemArgument1 = (PVOID)1;
00485 ContextFrame.
Apc.
SystemArgument2 = Thread;
00486
KeRaiseIrql(
APC_LEVEL, &Irql);
00487
PspGetSetContextSpecialApc(&ContextFrame.
Apc,
00488
NULL,
00489
NULL,
00490 &ContextFrame.
Apc.
SystemArgument1,
00491 &ContextFrame.
Apc.
SystemArgument2);
00492
00493
KeLowerIrql(Irql);
00494
00495 }
else {
00496
KeInitializeApc(&ContextFrame.
Apc,
00497 &Thread->Tcb,
00498
OriginalApcEnvironment,
00499
PspGetSetContextSpecialApc,
00500
NULL,
00501
NULL,
00502
KernelMode,
00503
NULL);
00504
00505
if (!
KeInsertQueueApc(&ContextFrame.
Apc, (PVOID)1, Thread, 2)) {
00506
Status = STATUS_UNSUCCESSFUL;
00507
00508 }
else {
00509
KeWaitForSingleObject(&ContextFrame.
OperationComplete,
00510
Executive,
00511
KernelMode,
00512
FALSE,
00513
NULL);
00514 }
00515 }
00516 }
00517
00518 }
else {
00519
Status = STATUS_INVALID_HANDLE;
00520 }
00521
00522
ObDereferenceObject(Thread);
00523 }
00524
00525
return Status;
00526 }