00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#include "psp.h"
00023
00024
#ifdef ALLOC_PRAGMA
00025
#pragma alloc_text(PAGE, PspTerminateThreadByPointer)
00026
#pragma alloc_text(PAGE, PspTerminateProcess)
00027
#pragma alloc_text(PAGE, NtTerminateProcess)
00028
#pragma alloc_text(PAGE, NtTerminateThread)
00029
#pragma alloc_text(PAGE, PspNullSpecialApc)
00030
#pragma alloc_text(PAGE, PspExitNormalApc)
00031
#pragma alloc_text(PAGE, PspExitProcess)
00032
#pragma alloc_text(PAGE, PspProcessDelete)
00033
#pragma alloc_text(PAGE, PspThreadDelete)
00034
#pragma alloc_text(PAGE, NtRegisterThreadTerminatePort)
00035
#pragma alloc_text(PAGE, PspExitThread)
00036
#pragma alloc_text(PAGE, PsExitSpecialApc)
00037
#pragma alloc_text(PAGE, PsGetProcessExitTime)
00038
#pragma alloc_text(PAGE, PsSetLegoNotifyRoutine)
00039
#endif
00040
00041
00042 PLEGO_NOTIFY_ROUTINE PspLegoNotifyRoutine;
00043
00044 ULONG
00045 PsSetLegoNotifyRoutine(
00046 PLEGO_NOTIFY_ROUTINE LegoNotifyRoutine
00047 )
00048 {
00049
PAGED_CODE();
00050
00051
PspLegoNotifyRoutine = LegoNotifyRoutine;
00052
00053
return FIELD_OFFSET(
KTHREAD,LegoData);
00054 }
00055
00056
VOID
00057 PspReaper(
00058 IN PVOID Context
00059 )
00060
00061
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 PLIST_ENTRY NextEntry;
00089 KIRQL OldIrql, OldIrql2;
00090
PETHREAD Thread;
00091
PEPROCESS Process;
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
KiLockDispatcherDatabase(&OldIrql);
00104 NextEntry =
PsReaperListHead.Flink;
00105
while (NextEntry != &
PsReaperListHead) {
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 RemoveEntryList(NextEntry);
00119 Thread = CONTAINING_RECORD(NextEntry,
ETHREAD, TerminationPortList);
00120
00121
KiLockContextSwap(&OldIrql2);
00122
KiUnlockContextSwap(OldIrql2);
00123
00124
KiUnlockDispatcherDatabase(OldIrql);
00125
00126
00127
00128
00129
00130
00131
00132 Process =
THREAD_TO_PROCESS(Thread);
00133
00134
00135
00136
00137
MmDeleteKernelStack(Thread->
Tcb.
StackBase,(BOOLEAN)Thread->
Tcb.
LargeStack);
00138 Thread->
Tcb.
InitialStack =
NULL;
00139
ObDereferenceObject(Thread);
00140
00141
00142
00143
00144
00145
00146
KiLockDispatcherDatabase(&OldIrql);
00147 NextEntry =
PsReaperListHead.Flink;
00148 }
00149
00150
00151
00152
00153
00154
PsReaperActive =
FALSE;
00155
KiUnlockDispatcherDatabase(OldIrql);
00156
return;
00157 }
00158
00159
NTSTATUS
00160 PspTerminateThreadByPointer(
00161 IN
PETHREAD Thread,
00162 IN NTSTATUS ExitStatus
00163 )
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 {
00184
00185
PKAPC ExitApc;
00186
00187
PAGED_CODE();
00188
00189
if ( Thread ==
PsGetCurrentThread() ) {
00190
ObDereferenceObject(Thread);
00191
PspExitThread(ExitStatus);
00192
00193
00194
00195
00196
00197 }
else {
00198 ExitApc =
ExAllocatePool(
NonPagedPool,(ULONG)
sizeof(
KAPC));
00199
00200
if ( !ExitApc ) {
00201
return STATUS_INSUFFICIENT_RESOURCES;
00202 }
00203
00204
KeInitializeApc(
00205 ExitApc,
00206 &Thread->Tcb,
00207
OriginalApcEnvironment,
00208
PsExitSpecialApc,
00209
NULL,
00210
PspExitNormalApc,
00211
KernelMode,
00212 ULongToPtr(ExitStatus)
00213 );
00214
00215
00216
if ( !
KeInsertQueueApc(ExitApc,ExitApc,
NULL, 2) ) {
00217
ExFreePool(ExitApc);
00218
00219
return STATUS_UNSUCCESSFUL;
00220 }
00221 }
00222
00223
return STATUS_SUCCESS;
00224 }
00225
00226
NTSTATUS
00227 NtTerminateProcess(
00228 IN HANDLE ProcessHandle OPTIONAL,
00229 IN NTSTATUS ExitStatus
00230 )
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 {
00252
00253
PETHREAD Thread,Self;
00254
PEPROCESS Process;
00255 PLIST_ENTRY Next;
00256
NTSTATUS st,xst;
00257 BOOLEAN ProcessHandleSpecified;
00258
PAGED_CODE();
00259
00260 Self =
PsGetCurrentThread();
00261
00262
if ( ARGUMENT_PRESENT(ProcessHandle) ) {
00263 ProcessHandleSpecified =
TRUE;
00264 }
else {
00265 ProcessHandleSpecified =
FALSE;
00266 ProcessHandle = NtCurrentProcess();
00267 }
00268
00269 st =
ObReferenceObjectByHandle(
00270 ProcessHandle,
00271 PROCESS_TERMINATE,
00272
PsProcessType,
00273 KeGetPreviousMode(),
00274 (PVOID *)&Process,
00275
NULL
00276 );
00277
00278
if ( !
NT_SUCCESS(st) ) {
00279
return(st);
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
if ( ExitStatus == DBG_TERMINATE_PROCESS && Process !=
PsGetCurrentProcess() ) {
00289
if ( Process->DebugPort ) {
00290
ObDereferenceObject( Process );
00291
return STATUS_ACCESS_DENIED;
00292 }
00293
else {
00294 ExitStatus = STATUS_SUCCESS;
00295 }
00296 }
00297
00298 st = STATUS_SUCCESS;
00299
00300
00301
00302
00303
00304
00305
00306
00307 xst =
PsLockProcess(Process,
KernelMode,
PsLockPollOnTimeout);
00308
00309
if ( xst != STATUS_SUCCESS ) {
00310
ObDereferenceObject( Process );
00311
return STATUS_PROCESS_IS_TERMINATING;
00312 }
00313
00314 Next = Process->ThreadListHead.Flink;
00315
00316
while ( Next != &Process->ThreadListHead) {
00317
00318 Thread = (
PETHREAD)(CONTAINING_RECORD(Next,
ETHREAD,ThreadListEntry));
00319
00320
if ( Thread != Self ) {
00321
00322
if (
IS_SYSTEM_THREAD(Thread) ) {
00323
ObDereferenceObject(Process);
00324
PsUnlockProcess(Process);
00325
return STATUS_INVALID_PARAMETER;
00326 }
00327
00328
if ( !Thread->
HasTerminated ) {
00329 Thread->
HasTerminated =
TRUE;
00330
00331
PspTerminateThreadByPointer(Thread, ExitStatus);
00332
KeForceResumeThread(&Thread->
Tcb);
00333 }
00334 }
00335 Next = Next->Flink;
00336 }
00337
00338
00339
00340
if ( Process ==
PsGetCurrentProcess() && ProcessHandleSpecified ) {
00341
00342 Self->
HasTerminated =
TRUE;
00343
00344
00345
00346
00347
00348
00349
00350
KeQuerySystemTime(&Process->ExitTime);
00351
00352
PsUnlockProcess(Process);
00353
00354
ObDereferenceObject(Process);
00355
00356
PspExitThread(ExitStatus);
00357
00358
00359
00360
00361
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
if ( ProcessHandleSpecified ) {
00371
00372
KeQuerySystemTime(&Process->ExitTime);
00373
00374 }
00375
00376
PsUnlockProcess(Process);
00377
00378
ObDereferenceObject(Process);
00379
00380
return st;
00381 }
00382
00383
NTSTATUS
00384 PspTerminateProcess(
00385
PEPROCESS Process,
00386 NTSTATUS Status,
00387 PSLOCKPROCESSMODE LockMode
00388 )
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 {
00410
00411
PETHREAD Thread;
00412 PLIST_ENTRY Next;
00413
NTSTATUS st;
00414
00415
PAGED_CODE();
00416
00417
if ( Process ==
PsGetCurrentProcess() ) {
00418
return STATUS_INVALID_PARAMETER;
00419 }
00420
00421
00422
00423
00424
00425
00426
00427
00428 st =
PsLockProcess(Process,
KernelMode,LockMode);
00429
00430
if ( st != STATUS_SUCCESS ) {
00431
return st;
00432 }
00433
00434 Next = Process->
ThreadListHead.Flink;
00435
00436
while ( Next != &Process->
ThreadListHead) {
00437
00438 Thread = (
PETHREAD)(CONTAINING_RECORD(Next,
ETHREAD,ThreadListEntry));
00439
00440
if (
IS_SYSTEM_THREAD(Thread) ) {
00441
ObDereferenceObject(Process);
00442
PsUnlockProcess(Process);
00443
return STATUS_INVALID_PARAMETER;
00444 }
00445
00446
if ( !Thread->
HasTerminated ) {
00447 Thread->
HasTerminated =
TRUE;
00448
PspTerminateThreadByPointer(Thread,
Status);
00449
KeForceResumeThread(&Thread->
Tcb);
00450 }
00451 Next = Next->Flink;
00452 }
00453
00454
PsUnlockProcess(Process);
00455
00456
return STATUS_SUCCESS;
00457 }
00458
00459
00460
NTSTATUS
00461 NtTerminateThread(
00462 IN HANDLE ThreadHandle OPTIONAL,
00463 IN NTSTATUS ExitStatus
00464 )
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 {
00485
00486
PETHREAD Thread;
00487
NTSTATUS st;
00488
00489
PAGED_CODE();
00490
00491
if ( !ARGUMENT_PRESENT(
ThreadHandle) ) {
00492
if ( (
PsGetCurrentProcess()->ThreadListHead.Flink ==
00493
PsGetCurrentProcess()->ThreadListHead.Blink
00494 )
00495 &&
00496 (
PsGetCurrentProcess()->ThreadListHead.Flink ==
00497 &
PsGetCurrentThread()->ThreadListEntry
00498 )
00499 ) {
00500
return( STATUS_CANT_TERMINATE_SELF );
00501 }
else {
00502
ThreadHandle = NtCurrentThread();
00503 }
00504 }
00505
00506 st =
ObReferenceObjectByHandle(
00507
ThreadHandle,
00508 THREAD_TERMINATE,
00509
PsThreadType,
00510 KeGetPreviousMode(),
00511 (PVOID *)&Thread,
00512
NULL
00513 );
00514
00515
if ( !
NT_SUCCESS(st) ) {
00516
return(st);
00517 }
00518
00519
if (
IS_SYSTEM_THREAD(Thread) ) {
00520
ObDereferenceObject(Thread);
00521
return STATUS_INVALID_PARAMETER;
00522 }
00523
00524
if ( Thread !=
PsGetCurrentThread() ) {
00525
00526
if (!Thread->HasTerminated) {
00527
PsLockProcess(
THREAD_TO_PROCESS(Thread),
KernelMode,
PsLockWaitForever);
00528
00529 Thread->HasTerminated =
TRUE;
00530 st =
PspTerminateThreadByPointer(Thread,ExitStatus);
00531
if (
NT_SUCCESS(st) ) {
00532
KeForceResumeThread(&Thread->Tcb);
00533 }
00534
PsUnlockProcess(
THREAD_TO_PROCESS(Thread));
00535 }
00536 }
else {
00537 Thread->HasTerminated =
TRUE;
00538
PspTerminateThreadByPointer(Thread,ExitStatus);
00539 }
00540
ObDereferenceObject(Thread);
00541
00542
return st;
00543 }
00544
00545
NTSTATUS
00546 PsTerminateSystemThread(
00547 IN NTSTATUS ExitStatus
00548 )
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 {
00568
PETHREAD Thread =
PsGetCurrentThread();
00569
00570
if ( !
IS_SYSTEM_THREAD(Thread) ) {
00571
return STATUS_INVALID_PARAMETER;
00572 }
00573
00574 Thread->
HasTerminated =
TRUE;
00575
PspExitThread(ExitStatus);
00576 }
00577
00578
00579
VOID
00580 PspNullSpecialApc(
00581 IN
PKAPC Apc,
00582 IN PKNORMAL_ROUTINE *NormalRoutine,
00583 IN PVOID *NormalContext,
00584 IN PVOID *SystemArgument1,
00585 IN PVOID *SystemArgument2
00586 )
00587
00588 {
00589
00590
PAGED_CODE();
00591
00592 UNREFERENCED_PARAMETER(NormalContext);
00593 UNREFERENCED_PARAMETER(SystemArgument1);
00594 UNREFERENCED_PARAMETER(SystemArgument2);
00595
00596
if (
PsGetCurrentThread()->HasTerminated ) {
00597 *NormalRoutine =
NULL;
00598 }
00599
ExFreePool(Apc);
00600 }
00601
00602
VOID
00603 PsExitSpecialApc(
00604 IN
PKAPC Apc,
00605 IN PKNORMAL_ROUTINE *NormalRoutine,
00606 IN PVOID *NormalContext,
00607 IN PVOID *SystemArgument1,
00608 IN PVOID *SystemArgument2
00609 )
00610
00611 {
00612
NTSTATUS ExitStatus;
00613
00614
PAGED_CODE();
00615
00616 UNREFERENCED_PARAMETER(NormalRoutine);
00617 UNREFERENCED_PARAMETER(NormalContext);
00618 UNREFERENCED_PARAMETER(SystemArgument1);
00619 UNREFERENCED_PARAMETER(SystemArgument2);
00620
00621
if ( Apc->SystemArgument2 ) {
00622 ExitStatus = (
NTSTATUS)((LONG_PTR)Apc->NormalContext);
00623
ExFreePool(Apc);
00624
PspExitThread(ExitStatus);
00625 }
00626
00627 }
00628
00629
00630
VOID
00631 PspExitNormalApc(
00632 IN PVOID NormalContext,
00633 IN PVOID SystemArgument1,
00634 IN PVOID SystemArgument2
00635 )
00636
00637 {
00638
PETHREAD Thread;
00639
PKAPC ExitApc;
00640
NTSTATUS ExitStatus;
00641
00642
PAGED_CODE();
00643
00644 Thread =
PsGetCurrentThread();
00645
00646
if ( SystemArgument2 ) {
00647
KeBugCheck(0x12345678);
00648 }
00649
00650 ExitApc = (
PKAPC) SystemArgument1;
00651
00652
if (
IS_SYSTEM_THREAD(Thread) ) {
00653 ExitStatus = (
NTSTATUS)((LONG_PTR)ExitApc->
NormalContext);
00654
ExFreePool(ExitApc);
00655
PspExitThread(ExitStatus);
00656 }
else {
00657
00658
KeInitializeApc(
00659 ExitApc,
00660 &Thread->
Tcb,
00661
OriginalApcEnvironment,
00662
PsExitSpecialApc,
00663
NULL,
00664
PspExitNormalApc,
00665
UserMode,
00666 NormalContext
00667 );
00668
00669
if ( !
KeInsertQueueApc(ExitApc,ExitApc,(PVOID) 1, 2) ) {
00670
ExFreePool(ExitApc);
00671 }
00672
00673
KeForceResumeThread(&Thread->
Tcb);
00674 }
00675 }
00676
00677
00678 BOOLEAN
00679 PspMarkCidInvalid(
00680 IN
PHANDLE_TABLE_ENTRY HandleEntry,
00681 IN ULONG_PTR Parameter
00682 )
00683 {
00684 HandleEntry->Object = (PVOID)Parameter;
00685
return TRUE;
00686 }
00687
00688 DECLSPEC_NORETURN
00689
VOID
00690 PspExitThread(
00691 IN NTSTATUS ExitStatus
00692 )
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 {
00715
00716
PETHREAD Thread;
00717
PEPROCESS Process;
00718
PKAPC Apc;
00719 PLIST_ENTRY FirstEntry;
00720 PLIST_ENTRY NextEntry;
00721
PTERMINATION_PORT TerminationPort;
00722 LPC_CLIENT_DIED_MSG CdMsg;
00723 BOOLEAN LastThread;
00724
00725
PAGED_CODE();
00726
00727 Thread =
PsGetCurrentThread();
00728 Process =
THREAD_TO_PROCESS(Thread);
00729
00730
if (
KeIsAttachedProcess() ) {
00731
KeBugCheckEx(
00732 INVALID_PROCESS_ATTACH_ATTEMPT,
00733 (ULONG_PTR)Process,
00734 (ULONG_PTR)Thread->
Tcb.
ApcState.
Process,
00735 (ULONG)Thread->
Tcb.
ApcStateIndex,
00736 (ULONG_PTR)Thread
00737 );
00738 }
00739
00740
KeLowerIrql(
PASSIVE_LEVEL);
00741
00742
if (Thread->
Tcb.
Priority < LOW_REALTIME_PRIORITY) {
00743
KeSetPriorityThread (&Thread->
Tcb, LOW_REALTIME_PRIORITY);
00744 }
00745
00746
00747
00748
00749
00750
PoRundownThread(Thread);
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
PsLockProcess(Process,
UserMode,
PsLockIAmExiting);
00764
KeForceResumeThread (&Thread->
Tcb);
00765
00766
00767
00768
00769
00770
if (
PspCreateThreadNotifyRoutineCount != 0) {
00771 ULONG i;
00772
00773
for (i=0; i<
PSP_MAX_CREATE_THREAD_NOTIFY; i++) {
00774
if (
PspCreateThreadNotifyRoutine[i] !=
NULL) {
00775 (*
PspCreateThreadNotifyRoutine[i])(Process->
UniqueProcessId,
00776 Thread->
Cid.UniqueThread,
00777
FALSE
00778 );
00779 }
00780 }
00781 }
00782
00783 LastThread =
FALSE;
00784
00785
if ( (Process->
ThreadListHead.Flink == Process->
ThreadListHead.Blink)
00786 && (Process->
ThreadListHead.Flink == &Thread->
ThreadListEntry) ) {
00787 LastThread =
TRUE;
00788
if ( ExitStatus == STATUS_THREAD_IS_TERMINATING ) {
00789
if ( Process->
ExitStatus == STATUS_PENDING ) {
00790 Process->
ExitStatus = Process->
LastThreadExitStatus;
00791 }
00792 }
else {
00793 Process->
ExitStatus = ExitStatus;
00794 }
00795
00796
DbgkExitProcess(ExitStatus);
00797
00798 }
else {
00799
if ( ExitStatus != STATUS_THREAD_IS_TERMINATING ) {
00800 Process->
LastThreadExitStatus = ExitStatus;
00801 }
00802
00803
DbgkExitThread(ExitStatus);
00804 }
00805
00806
KeLeaveCriticalRegion();
00807
ASSERT(Thread->
Tcb.
KernelApcDisable == 0);
00808
00809 Thread->
Tcb.
KernelApcDisable = 0;
00810
00811
00812
00813
00814
if ( !IsListEmpty(&Thread->
TerminationPortList) ) {
00815
00816 CdMsg.PortMsg.u1.s1.DataLength =
sizeof(LARGE_INTEGER);
00817 CdMsg.PortMsg.u1.s1.TotalLength =
sizeof(LPC_CLIENT_DIED_MSG);
00818 CdMsg.PortMsg.u2.s2.Type = LPC_CLIENT_DIED;
00819 CdMsg.PortMsg.u2.s2.DataInfoOffset = 0;
00820
00821
while ( !IsListEmpty(&Thread->
TerminationPortList) ) {
00822
00823 NextEntry = RemoveHeadList(&Thread->
TerminationPortList);
00824 TerminationPort = CONTAINING_RECORD(NextEntry,
TERMINATION_PORT,Links);
00825 CdMsg.CreateTime.QuadPart =
PS_GET_THREAD_CREATE_TIME(Thread);
00826
LpcRequestPort(TerminationPort->
Port, (PPORT_MESSAGE)&CdMsg);
00827
ObDereferenceObject(TerminationPort->
Port);
00828
ExFreePool(TerminationPort);
00829 }
00830 }
else {
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
if ( (ExitStatus == STATUS_THREAD_IS_TERMINATING && Thread->
DeadThread) ||
00850 !Thread->
DeadThread ) {
00851
00852 CdMsg.PortMsg.u1.s1.DataLength =
sizeof(LARGE_INTEGER);
00853 CdMsg.PortMsg.u1.s1.TotalLength =
sizeof(LPC_CLIENT_DIED_MSG);
00854 CdMsg.PortMsg.u2.s2.Type = LPC_CLIENT_DIED;
00855 CdMsg.PortMsg.u2.s2.DataInfoOffset = 0;
00856
if (
PsGetCurrentProcess()->ExceptionPort ) {
00857 CdMsg.CreateTime.QuadPart =
PS_GET_THREAD_CREATE_TIME(Thread);
00858
LpcRequestPort(
PsGetCurrentProcess()->ExceptionPort, (PPORT_MESSAGE)&CdMsg);
00859 }
00860 }
00861 }
00862
00863
00864
00865
00866
00867
if ( Thread->
Tcb.
Win32Thread ) {
00868 (
PspW32ThreadCallout)(Thread,
PsW32ThreadCalloutExit);
00869 }
00870
00871
if ( LastThread && Process->
Win32Process ) {
00872 (
PspW32ProcessCallout)(Process,
FALSE);
00873 }
00874
00875
00876
00877
00878
00879
00880
00881
if ( !Thread->
Tcb.
EnableStackSwap ) {
00882
KeBugCheckEx(KERNEL_STACK_LOCKED_AT_EXIT,0,0,0,0);
00883 }
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
if (Thread->
Tcb.
Teb) {
00894
if (
IS_SYSTEM_THREAD(Thread) ) {
00895
ExFreePool( Thread->
Tcb.
Teb );
00896 }
else {
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
try {
00909 PTEB Teb;
00910 PPEB Peb;
00911 PRTL_CRITICAL_SECTION Cs;
00912
int DecrementCount;
00913
00914 Teb = Thread->
Tcb.
Teb;
00915 Peb = Process->
Peb;
00916
00917 Cs = Peb->LoaderLock;
00918
if ( Cs ) {
00919
ProbeForRead(Cs,
sizeof(*Cs),4);
00920
if ( Cs->OwningThread == Thread->
Cid.UniqueThread ) {
00921
00922
00923
00924
00925
00926
#if defined(_X86_)
00927
DecrementCount = Cs->RecursionCount;
00928
#else
00929
DecrementCount = Cs->RecursionCount + 1;
00930
#endif
00931
Cs->RecursionCount = 0;
00932 Cs->OwningThread = 0;
00933
00934
00935
00936
00937
00938
while(DecrementCount > 1){
00939 InterlockedDecrement(&Cs->LockCount);
00940 DecrementCount--;
00941 }
00942
00943
00944
00945
00946
00947
if ( InterlockedDecrement(&Cs->LockCount) >= 0 ){
00948
NtSetEvent(Cs->LockSemaphore,
NULL);
00949 }
00950 }
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
else if ( Teb->WaitingOnLoaderLock ) {
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991 InterlockedDecrement(&Cs->LockCount);
00992 }
00993 }
00994
#if defined(_WIN64)
00995
if (Process->
Wow64Process) {
00996
00997 PRTL_CRITICAL_SECTION32 Cs32;
00998 PPEB32 Peb32;
00999
01000 Peb32 = Process->
Wow64Process->
Wow64;
01001 Cs32 = (PRTL_CRITICAL_SECTION32)ULongToPtr(Peb32->LoaderLock);
01002
if (Cs32) {
01003
ProbeForRead(Cs32,
sizeof(*Cs32),4);
01004
if ( Cs32->OwningThread == PtrToUlong(Thread->
Cid.UniqueThread) ) {
01005
01006
01007
01008
01009
01010
01011 DecrementCount = Cs32->RecursionCount;
01012 Cs32->RecursionCount = 0;
01013 Cs32->OwningThread = 0;
01014
01015
01016
01017
01018
while(DecrementCount > 1) {
01019 InterlockedDecrement(&Cs32->LockCount);
01020 DecrementCount--;
01021 }
01022
01023
01024
01025
01026
if ( InterlockedDecrement(&Cs32->LockCount) >= 0 ){
01027
NtSetEvent(LongToHandle(Cs32->LockSemaphore),
NULL);
01028 }
01029 }
else {
01030 PTEB32 Teb32 = WOW64_GET_TEB32(Teb);
01031
01032
ProbeForRead(Teb32,
sizeof(*Teb32),4);
01033
if ( Teb32->WaitingOnLoaderLock ) {
01034 InterlockedDecrement(&Cs32->LockCount);
01035 }
01036 }
01037 }
01038 }
01039
#endif
01040
}
01041 except (
EXCEPTION_EXECUTE_HANDLER) {
01042 ;
01043 }
01044
01045
#if defined(_WIN64)
01046
if (Process->
Wow64Process) {
01047
01048
01049
01050
try {
01051 PVOID BaseAddress;
01052 SIZE_T RegionSize;
01053
01054
01055 BaseAddress = *(PVOID *)WOW64_TEB32_POINTER_ADDRESS(((PTEB)Thread->
Tcb.
Teb));
01056
01057
01058
01059 RegionSize =
PAGE_SIZE;
01060 ZwFreeVirtualMemory( NtCurrentProcess(),
01061 &BaseAddress,
01062 &RegionSize,
01063 MEM_RELEASE
01064 );
01065
01066 }
01067 except (
EXCEPTION_EXECUTE_HANDLER) {
01068 ;
01069 }
01070 }
01071
#endif
01072
01073
MmDeleteTeb(Process, Thread->
Tcb.
Teb);
01074 Thread->
Tcb.
Teb =
NULL;
01075 }
01076 }
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
IoCancelThreadIo(Thread);
01088
ExTimerRundown();
01089
CmNotifyRunDown(Thread);
01090
KeRundownThread();
01091
01092
01093
01094
01095
01096
if (!(
ExChangeHandle(
PspCidTable, Thread->
Cid.UniqueThread,
PspMarkCidInvalid,
PSP_INVALID_ID))) {
01097
KeBugCheck(CID_HANDLE_DELETION);
01098 }
01099
ObDereferenceObject(Thread);
01100
01101
01102
01103
01104
01105
01106
LpcExitThread(Thread);
01107
01108
01109
01110
01111
01112
if ( LastThread ) {
01113
if (!(
ExChangeHandle(
PspCidTable,Process->
UniqueProcessId,
PspMarkCidInvalid,
PSP_INVALID_ID))) {
01114
KeBugCheck(CID_HANDLE_DELETION);
01115 }
01116
KeQuerySystemTime(&Process->
ExitTime);
01117
PspExitProcess(
TRUE,Process);
01118 }
01119
01120
01121 Thread->
ExitStatus = ExitStatus;
01122
KeQuerySystemTime(&Thread->
ExitTime);
01123
01124
01125 RemoveEntryList(&Thread->
ThreadListEntry);
01126
KeEnterCriticalRegion();
01127
01128 Thread->
ThreadListEntry.Flink =
NULL;
01129 Thread->
ThreadListEntry.Blink =
NULL;
01130
01131
PsUnlockProcess(Process);
01132
ASSERT(Thread->
Tcb.
KernelApcDisable == 0);
01133
01134
if ( LastThread ) {
01135
01136
01137
01138
01139
01140
01141
01142
ObKillProcess(
TRUE, Process);
01143
01144
if ( Process->
Job) {
01145
01146
01147
01148
01149
01150
01151
PspExitProcessFromJob(Process->
Job,Process);
01152
01153 }
01154
01155
KeSetProcess(&Process->
Pcb,0,
FALSE);
01156
01157 }
01158
01159
01160
01161
01162
01163 (
VOID)
KeDisableApcQueuingThread(&Thread->
Tcb);
01164
01165
01166
01167
01168
01169 FirstEntry =
KeFlushQueueApc(&Thread->
Tcb,
UserMode);
01170
01171
if ( FirstEntry ) {
01172
01173 NextEntry = FirstEntry;
01174
do {
01175 Apc = CONTAINING_RECORD(NextEntry,
KAPC, ApcListEntry);
01176 NextEntry = NextEntry->Flink;
01177
01178
01179
01180
01181
01182
01183
if ( Apc->
RundownRoutine ) {
01184 (Apc->
RundownRoutine)(Apc);
01185 }
else {
01186
ExFreePool(Apc);
01187 }
01188
01189 }
while (NextEntry != FirstEntry);
01190 }
01191
01192
if ( LastThread ) {
01193
MmCleanProcessAddressSpace();
01194 }
01195
01196
if ( Thread->
Tcb.
LegoData &&
PspLegoNotifyRoutine ) {
01197 (
PspLegoNotifyRoutine)(&Thread->
Tcb);
01198 }
01199
01200
01201
01202
01203
01204
01205
01206
01207 FirstEntry =
KeFlushQueueApc(&Thread->
Tcb,
KernelMode);
01208
01209
if ( FirstEntry ) {
01210
KeBugCheckEx(
01211 KERNEL_APC_PENDING_DURING_EXIT,
01212 (ULONG_PTR)FirstEntry,
01213 (ULONG_PTR)Thread->
Tcb.
KernelApcDisable,
01214 (ULONG_PTR)KeGetCurrentIrql(),
01215 0
01216 );
01217 }
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
KeTerminateThread(0
L);
01229 }
01230
01231
VOID
01232 PspExitProcess(
01233 IN BOOLEAN TrimAddressSpace,
01234 IN
PEPROCESS Process
01235 )
01236 {
01237
01238 ULONG ActualTime;
01239
01240
PAGED_CODE();
01241
01242
if (!Process->ExitProcessCalled &&
PspCreateProcessNotifyRoutineCount != 0) {
01243 ULONG i;
01244
01245
for (i=0; i<
PSP_MAX_CREATE_PROCESS_NOTIFY; i++) {
01246
if (
PspCreateProcessNotifyRoutine[i] !=
NULL) {
01247 (*
PspCreateProcessNotifyRoutine[i])( Process->InheritedFromUniqueProcessId,
01248 Process->UniqueProcessId,
01249
FALSE
01250 );
01251 }
01252 }
01253 }
01254
01255 Process->ExitProcessCalled =
TRUE;
01256
01257
PoRundownProcess(Process);
01258
01259
01260
01261
01262
01263
01264
if ( Process->ActiveProcessLinks.Flink !=
NULL &&
01265 Process->ActiveProcessLinks.Blink !=
NULL ) {
01266
01267 ExAcquireFastMutex(&
PspActiveProcessMutex);
01268 RemoveEntryList(&Process->ActiveProcessLinks);
01269 Process->ActiveProcessLinks.Flink =
NULL;
01270 Process->ActiveProcessLinks.Blink =
NULL;
01271 ExReleaseFastMutex(&
PspActiveProcessMutex);
01272
01273 }
01274
01275
if (Process->SecurityPort) {
01276
01277
ObDereferenceObject(Process->SecurityPort);
01278
01279 Process->SecurityPort =
NULL ;
01280 }
01281
01282
01283
if ( TrimAddressSpace ) {
01284
01285
01286
01287
01288
01289
01290
01291
if (Process->SetTimerResolution !=
FALSE) {
01292 ZwSetTimerResolution(
KeMaximumIncrement,
FALSE, &ActualTime);
01293 }
01294
01295
if ( Process->Job
01296 && Process->Job->CompletionPort
01297 && !(Process->JobStatus &
PS_JOB_STATUS_NOT_REALLY_ACTIVE)
01298 && !(Process->JobStatus &
PS_JOB_STATUS_EXIT_PROCESS_REPORTED)) {
01299
01300 ULONG_PTR ExitMessageId;
01301
01302
switch (Process->ExitStatus) {
01303
case STATUS_GUARD_PAGE_VIOLATION :
01304
case STATUS_DATATYPE_MISALIGNMENT :
01305
case STATUS_BREAKPOINT :
01306
case STATUS_SINGLE_STEP :
01307
case STATUS_ACCESS_VIOLATION :
01308
case STATUS_IN_PAGE_ERROR :
01309
case STATUS_ILLEGAL_INSTRUCTION :
01310
case STATUS_NONCONTINUABLE_EXCEPTION :
01311
case STATUS_INVALID_DISPOSITION :
01312
case STATUS_ARRAY_BOUNDS_EXCEEDED :
01313
case STATUS_FLOAT_DENORMAL_OPERAND :
01314
case STATUS_FLOAT_DIVIDE_BY_ZERO :
01315
case STATUS_FLOAT_INEXACT_RESULT :
01316
case STATUS_FLOAT_INVALID_OPERATION :
01317
case STATUS_FLOAT_OVERFLOW :
01318
case STATUS_FLOAT_STACK_CHECK :
01319
case STATUS_FLOAT_UNDERFLOW :
01320
case STATUS_INTEGER_DIVIDE_BY_ZERO :
01321
case STATUS_INTEGER_OVERFLOW :
01322
case STATUS_PRIVILEGED_INSTRUCTION :
01323
case STATUS_STACK_OVERFLOW :
01324
case STATUS_CONTROL_C_EXIT :
01325
case STATUS_FLOAT_MULTIPLE_FAULTS :
01326
case STATUS_FLOAT_MULTIPLE_TRAPS :
01327
case STATUS_REG_NAT_CONSUMPTION :
01328 ExitMessageId = JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS;
01329
break;
01330
default:
01331 ExitMessageId = JOB_OBJECT_MSG_EXIT_PROCESS;
01332
break;
01333 }
01334
01335
PS_SET_CLEAR_BITS (&Process->JobStatus,
01336
PS_JOB_STATUS_EXIT_PROCESS_REPORTED,
01337
PS_JOB_STATUS_LAST_REPORT_MEMORY);
01338
01339 ExAcquireFastMutex(&Process->Job->MemoryLimitsLock);
01340
01341
if (Process->Job->CompletionPort !=
NULL) {
01342
IoSetIoCompletion(
01343 Process->Job->CompletionPort,
01344 Process->Job->CompletionKey,
01345 (PVOID)Process->UniqueProcessId,
01346 STATUS_SUCCESS,
01347 ExitMessageId,
01348
FALSE
01349 );
01350 }
01351 ExReleaseFastMutex(&Process->Job->MemoryLimitsLock);
01352 }
01353
01354 }
else {
01355
KeSetProcess(&Process->Pcb,0,
FALSE);
01356
ObKillProcess(
FALSE, Process);
01357
MmCleanProcessAddressSpace();
01358 }
01359
01360 }
01361
01362
VOID
01363 PspProcessDelete(
01364 IN PVOID Object
01365 )
01366 {
01367
PEPROCESS Process;
01368 ULONG AddressSpace;
01369
KAPC_STATE ApcState;
01370
01371
PAGED_CODE();
01372
01373 Process = (
PEPROCESS)Object;
01374
01375
if (
SeDetailedAuditing && Process->
Token !=
NULL ) {
01376
SeAuditProcessExit(
01377 Process
01378 );
01379 }
01380
01381
if ( Process->
Job ) {
01382
PspRemoveProcessFromJob(Process->
Job,Process);
01383
ObDereferenceObject(Process->
Job);
01384 }
01385
01386
KeTerminateProcess((
PKPROCESS)Process);
01387 AddressSpace = (ULONG)
01388 ((PHARDWARE_PTE)(&(Process->Pcb.
DirectoryTableBase[0])))->PageFrameNumber;
01389
01390
01391
if (Process->DebugPort) {
01392
ObDereferenceObject(Process->DebugPort);
01393 }
01394
if (Process->ExceptionPort) {
01395
ObDereferenceObject(Process->ExceptionPort);
01396 }
01397
if ( Process->UniqueProcessId ) {
01398
if ( !(
ExDestroyHandle(
PspCidTable,Process->UniqueProcessId,
NULL))) {
01399
KeBugCheck(CID_HANDLE_DELETION);
01400 }
01401 }
01402
01403
PspDeleteLdt( Process );
01404
PspDeleteVdmObjects( Process );
01405
01406
if ( AddressSpace ) {
01407
01408
01409
01410
01411
01412
KeStackAttachProcess(&Process->Pcb, &ApcState);
01413
01414
PspExitProcess(
FALSE,Process);
01415
01416
KeUnstackDetachProcess(&ApcState);
01417 }
01418
01419
PspDeleteProcessSecurity( Process );
01420
01421
if (AddressSpace) {
01422
MmDeleteProcessAddressSpace(Process);
01423 }
01424
01425
#if DEVL
01426
if ( Process->WorkingSetWatch ) {
01427
ExFreePool(Process->WorkingSetWatch);
01428 }
01429
#endif // DEVL
01430
01431
PERFINFO_PROCESS_DELETE(Process);
01432
01433
ObDereferenceDeviceMap(Process);
01434
PspDereferenceQuota(Process);
01435 }
01436
01437
VOID
01438 PspThreadDelete(
01439 IN PVOID Object
01440 )
01441 {
01442
PETHREAD Thread;
01443
PEPROCESS Process;
01444
01445
PAGED_CODE();
01446
01447 Thread = (
PETHREAD) Object;
01448
01449
PERFINFO_THREAD_DELETE(Thread);
01450
01451
ASSERT(Thread->
Tcb.
Win32Thread ==
NULL);
01452
01453
if ( Thread->
Tcb.
InitialStack ) {
01454
MmDeleteKernelStack(Thread->
Tcb.
InitialStack,(BOOLEAN)Thread->
Tcb.
LargeStack);
01455 }
01456
01457
if ( Thread->
Cid.UniqueThread ) {
01458
if (!(
ExDestroyHandle(
PspCidTable,Thread->
Cid.UniqueThread,
NULL))) {
01459
KeBugCheck(CID_HANDLE_DELETION);
01460 }
01461 }
01462
01463
PspDeleteThreadSecurity( Thread );
01464
01465 Process =
THREAD_TO_PROCESS(Thread);
01466
if (Process) {
01467
ObDereferenceObject(Process);
01468 }
01469 }
01470
01471
NTSTATUS
01472 NtRegisterThreadTerminatePort(
01473 IN HANDLE PortHandle
01474 )
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494 {
01495
01496 PVOID Port;
01497
PTERMINATION_PORT TerminationPort;
01498
NTSTATUS st;
01499
01500
PAGED_CODE();
01501
01502 st =
ObReferenceObjectByHandle (
01503
PortHandle,
01504 0,
01505
LpcPortObjectType,
01506 KeGetPreviousMode(),
01507 (PVOID *)&Port,
01508
NULL
01509 );
01510
01511
if ( !
NT_SUCCESS(st) ) {
01512
return st;
01513
01514 }
01515
01516
01517
01518
01519
01520
try {
01521
01522 TerminationPort =
NULL;
01523 TerminationPort =
ExAllocatePoolWithQuota(
PagedPool,
sizeof(
TERMINATION_PORT));
01524
01525 TerminationPort->
Port = Port;
01526 InsertTailList(&
PsGetCurrentThread()->TerminationPortList,&TerminationPort->
Links);
01527
01528 } except(
EXCEPTION_EXECUTE_HANDLER) {
01529
01530
ObDereferenceObject(Port);
01531
01532
return GetExceptionCode();
01533 }
01534
01535
return STATUS_SUCCESS;
01536 }
01537
01538 LARGE_INTEGER
01539 PsGetProcessExitTime(
01540 VOID
01541 )
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564 {
01565
PAGED_CODE();
01566
01567
01568
01569
01570
01571
return PsGetCurrentProcess()->ExitTime;
01572 }
01573
01574
01575
#undef PsIsThreadTerminating
01576
01577 BOOLEAN
01578 PsIsThreadTerminating(
01579 IN
PETHREAD Thread
01580 )
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599 {
01600
01601
01602
01603
01604
if ( Thread->HasTerminated ) {
01605
return TRUE;
01606 }
01607
else {
01608
return FALSE;
01609 }
01610 }