00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include <ntos.h>
00022
#include "ldrp.h"
00023
#include <stktrace.h>
00024
#include <heap.h>
00025
#include <stdio.h>
00026
00027 #define AdjustPointer( t, p, d ) (p); if ((p) != NULL) (p) = (t)((ULONG_PTR)(p) + (d))
00028
00029 NTSYSAPI
00030
NTSTATUS
00031 NTAPI
00032 RtlpQueryProcessDebugInformationRemote(
00033 IN OUT PRTL_DEBUG_INFORMATION Buffer
00034 )
00035 {
00036
NTSTATUS Status;
00037 ULONG i;
00038 ULONG_PTR Delta;
00039 PRTL_PROCESS_HEAPS Heaps;
00040 PRTL_HEAP_INFORMATION HeapInfo;
00041
00042
if (
Buffer->EventPairTarget !=
NULL) {
00043
Status =
NtWaitLowEventPair(
Buffer->EventPairTarget );
00044 }
00045
else {
00046
Status = STATUS_SUCCESS;
00047 }
00048
00049
while (
NT_SUCCESS(
Status )) {
00050
Status =
RtlQueryProcessDebugInformation( NtCurrentTeb()->ClientId.UniqueProcess,
00051
Buffer->Flags,
00052
Buffer
00053 );
00054
if (
NT_SUCCESS(
Status )) {
00055
if (Delta =
Buffer->ViewBaseDelta) {
00056
00057
00058
00059
AdjustPointer( PRTL_PROCESS_MODULES,
Buffer->Modules, Delta );
00060
AdjustPointer( PRTL_PROCESS_BACKTRACES,
Buffer->BackTraces, Delta );
00061 Heaps =
AdjustPointer( PRTL_PROCESS_HEAPS,
Buffer->Heaps, Delta );
00062
if (Heaps !=
NULL) {
00063
for (i=0; i<Heaps->NumberOfHeaps; i++) {
00064 HeapInfo = &Heaps->Heaps[ i ];
00065
AdjustPointer( PRTL_HEAP_TAG, HeapInfo->Tags, Delta );
00066
AdjustPointer( PRTL_HEAP_ENTRY, HeapInfo->Entries, Delta );
00067 }
00068 }
00069
00070
AdjustPointer( PRTL_PROCESS_LOCKS,
Buffer->Locks, Delta );
00071 }
00072 }
00073
00074
if (
Buffer->EventPairTarget ==
NULL) {
00075
00076
00077
00078
break;
00079 }
00080
00081
Status =
NtSetHighWaitLowEventPair(
Buffer->EventPairTarget );
00082
if (
Buffer->EventPairTarget ==
NULL) {
00083
break;
00084 }
00085 }
00086
00087
00088
00089
00090
00091
00092
NtUnmapViewOfSection( NtCurrentProcess(),
Buffer );
00093
NtTerminateThread( NtCurrentThread(),
Status );
00094
return Status;
00095 }
00096
00097
00098
NTSTATUS
00099 RtlpChangeQueryDebugBufferTarget(
00100 IN PRTL_DEBUG_INFORMATION Buffer,
00101 IN HANDLE TargetProcessId,
00102 OUT PHANDLE ReturnedTargetProcessHandle
00103 )
00104 {
00105
NTSTATUS Status;
00106 CLIENT_ID OldTargetClientId, NewTargetClientId;
00107 OBJECT_ATTRIBUTES
ObjectAttributes;
00108 HANDLE OldTargetProcess, NewTargetProcess, NewHandle;
00109 PHANDLE pOldHandle;
00110 ULONG DuplicateHandleFlags;
00111
00112
if (
Buffer->EventPairClient !=
NULL &&
00113
Buffer->TargetProcessId == TargetProcessId
00114 ) {
00115
return STATUS_SUCCESS;
00116 }
00117
00118 InitializeObjectAttributes( &
ObjectAttributes,
00119
NULL,
00120 0,
00121
NULL,
00122
NULL
00123 );
00124
00125 DuplicateHandleFlags = DUPLICATE_CLOSE_SOURCE |
00126 DUPLICATE_SAME_ACCESS |
00127 DUPLICATE_SAME_ATTRIBUTES;
00128
00129
if (
Buffer->EventPairClient !=
NULL) {
00130 pOldHandle = &
Buffer->EventPairTarget;
00131 }
00132
else {
00133 pOldHandle =
NULL;
00134 }
00135
00136
if (
Buffer->TargetProcessId !=
NULL) {
00137 OldTargetClientId.UniqueProcess =
Buffer->TargetProcessId;
00138 OldTargetClientId.UniqueThread = 0;
00139
Status =
NtOpenProcess( &OldTargetProcess,
00140 PROCESS_ALL_ACCESS,
00141 &
ObjectAttributes,
00142 &OldTargetClientId
00143 );
00144
if (!
NT_SUCCESS(
Status )) {
00145
return Status;
00146 }
00147 }
00148
else {
00149 OldTargetProcess = NtCurrentProcess();
00150 DuplicateHandleFlags &= ~DUPLICATE_CLOSE_SOURCE;
00151
if (pOldHandle !=
NULL) {
00152 pOldHandle = &
Buffer->EventPairClient;
00153 }
00154 }
00155
00156
if (ARGUMENT_PRESENT( TargetProcessId )) {
00157 NewTargetClientId.UniqueProcess = TargetProcessId;
00158 NewTargetClientId.UniqueThread = 0;
00159
Status =
NtOpenProcess( &NewTargetProcess,
00160 PROCESS_ALL_ACCESS,
00161 &
ObjectAttributes,
00162 &NewTargetClientId
00163 );
00164
if (!
NT_SUCCESS(
Status )) {
00165
if (OldTargetProcess != NtCurrentProcess()) {
00166
NtClose( OldTargetProcess );
00167 }
00168
return Status;
00169 }
00170 }
00171
else {
00172 NewTargetProcess =
NULL;
00173 }
00174
00175 NewHandle =
NULL;
00176
if (pOldHandle !=
NULL) {
00177
Status =
NtDuplicateObject( OldTargetProcess,
00178 *pOldHandle,
00179 NewTargetProcess,
00180 &NewHandle,
00181 0,
00182 0,
00183 DuplicateHandleFlags
00184 );
00185
if (!
NT_SUCCESS(
Status )) {
00186
if (OldTargetProcess != NtCurrentProcess()) {
00187
NtClose( OldTargetProcess );
00188 }
00189
if (NewTargetProcess !=
NULL) {
00190
NtClose( NewTargetProcess );
00191 }
00192
return Status;
00193 }
00194 }
00195
00196
if (OldTargetProcess != NtCurrentProcess()) {
00197
NtUnmapViewOfSection( OldTargetProcess,
Buffer->ViewBaseTarget );
00198 }
00199
else {
00200
Buffer->ViewBaseTarget =
Buffer->ViewBaseClient;
00201 }
00202
00203
if (NewTargetProcess !=
NULL) {
00204
Status =
NtMapViewOfSection(
Buffer->SectionHandleClient,
00205 NewTargetProcess,
00206 &
Buffer->ViewBaseTarget,
00207 0,
00208 0,
00209
NULL,
00210 &
Buffer->ViewSize,
00211 ViewUnmap,
00212 0,
00213 PAGE_READWRITE
00214 );
00215
if (
Status == STATUS_CONFLICTING_ADDRESSES) {
00216
Buffer->ViewBaseTarget =
NULL;
00217
Status =
NtMapViewOfSection(
Buffer->SectionHandleClient,
00218 NewTargetProcess,
00219 &
Buffer->ViewBaseTarget,
00220 0,
00221 0,
00222
NULL,
00223 &
Buffer->ViewSize,
00224 ViewUnmap,
00225 0,
00226 PAGE_READWRITE
00227 );
00228 }
00229
00230
if (!
NT_SUCCESS(
Status )) {
00231
if (NewHandle !=
NULL) {
00232
NtDuplicateObject( NewTargetProcess,
00233 &NewHandle,
00234
NULL,
00235
NULL,
00236 0,
00237 0,
00238 DUPLICATE_CLOSE_SOURCE
00239 );
00240 }
00241
00242
return Status;
00243 }
00244
00245
if (ARGUMENT_PRESENT( ReturnedTargetProcessHandle )) {
00246 *ReturnedTargetProcessHandle = NewTargetProcess;
00247 }
00248
else {
00249
NtClose( NewTargetProcess );
00250 }
00251 }
00252
00253
Buffer->EventPairTarget = NewHandle;
00254
Buffer->ViewBaseDelta = (ULONG_PTR)
Buffer->ViewBaseClient - (ULONG_PTR)
Buffer->ViewBaseTarget;
00255
return STATUS_SUCCESS;
00256 }
00257
00258
00259 PVOID
00260 RtlpCommitQueryDebugInfo(
00261 IN PRTL_DEBUG_INFORMATION Buffer,
00262 IN ULONG Size
00263 )
00264 {
00265
NTSTATUS Status;
00266 PVOID Result;
00267 PVOID CommitBase;
00268 SIZE_T CommitSize;
00269 SIZE_T NeededSize;
00270
00271
Size = (
Size + 3) & ~3;
00272 NeededSize =
Buffer->OffsetFree +
Size;
00273
if (NeededSize >
Buffer->CommitSize) {
00274
if (NeededSize >=
Buffer->ViewSize) {
00275
return NULL;
00276 }
00277
00278 CommitBase = (PCHAR)
Buffer +
Buffer->CommitSize;
00279 CommitSize = NeededSize -
Buffer->CommitSize;
00280
Status =
NtAllocateVirtualMemory( NtCurrentProcess(),
00281 &CommitBase,
00282 0,
00283 &CommitSize,
00284 MEM_COMMIT,
00285 PAGE_READWRITE
00286 );
00287
if (!
NT_SUCCESS(
Status )) {
00288
return NULL;
00289 }
00290
00291
00292
Buffer->CommitSize += CommitSize;
00293 }
00294
00295 Result = (PCHAR)
Buffer +
Buffer->OffsetFree;
00296
Buffer->OffsetFree = NeededSize;
00297
return Result;
00298 }
00299
00300
VOID
00301 RtlpDeCommitQueryDebugInfo(
00302 IN PRTL_DEBUG_INFORMATION Buffer,
00303 IN PVOID p,
00304 IN ULONG Size
00305 )
00306 {
00307
Size = (
Size + 3) & ~3;
00308
if (p == (PVOID)(
Buffer->OffsetFree -
Size)) {
00309
Buffer->OffsetFree -=
Size;
00310 }
00311 }
00312
00313 NTSYSAPI
00314 PRTL_DEBUG_INFORMATION
00315 NTAPI
00316 RtlCreateQueryDebugBuffer(
00317 IN ULONG MaximumCommit OPTIONAL,
00318 IN BOOLEAN UseEventPair
00319 )
00320 {
00321
NTSTATUS Status;
00322 HANDLE Section;
00323 PRTL_DEBUG_INFORMATION
Buffer;
00324 LARGE_INTEGER MaximumSize;
00325 ULONG_PTR ViewSize, CommitSize;
00326
00327
if (!ARGUMENT_PRESENT( (PVOID)(ULONG_PTR)MaximumCommit )) {
00328 MaximumCommit = 4 * 1024 * 1024;
00329 }
00330 MaximumSize.QuadPart = MaximumCommit;
00331
Status =
NtCreateSection( &Section,
00332 SECTION_ALL_ACCESS,
00333
NULL,
00334 &MaximumSize,
00335 PAGE_READWRITE,
00336 SEC_RESERVE,
00337
NULL
00338 );
00339
if (!
NT_SUCCESS(
Status )) {
00340
return NULL;
00341 }
00342
00343
Buffer =
NULL;
00344 ViewSize = MaximumCommit;
00345
Status =
NtMapViewOfSection( Section,
00346 NtCurrentProcess(),
00347 &
Buffer,
00348 0,
00349 0,
00350
NULL,
00351 &ViewSize,
00352 ViewUnmap,
00353 0,
00354 PAGE_READWRITE
00355 );
00356
if (!
NT_SUCCESS(
Status )) {
00357
NtClose( Section );
00358
return NULL;
00359 }
00360
00361 CommitSize = 1;
00362
Status =
NtAllocateVirtualMemory( NtCurrentProcess(),
00363 &
Buffer,
00364 0,
00365 &CommitSize,
00366 MEM_COMMIT,
00367 PAGE_READWRITE
00368 );
00369
if (!
NT_SUCCESS(
Status )) {
00370
NtUnmapViewOfSection( NtCurrentProcess(),
Buffer );
00371
NtClose( Section );
00372
return NULL;
00373 }
00374
00375
if (UseEventPair) {
00376
Status =
NtCreateEventPair( &
Buffer->EventPairClient,
00377 EVENT_PAIR_ALL_ACCESS,
00378
NULL
00379 );
00380
if (!
NT_SUCCESS(
Status )) {
00381
NtUnmapViewOfSection( NtCurrentProcess(),
Buffer );
00382
NtClose( Section );
00383
return NULL;
00384 }
00385 }
00386
00387
Buffer->SectionHandleClient = Section;
00388
Buffer->ViewBaseClient =
Buffer;
00389
Buffer->OffsetFree = 0;
00390
Buffer->CommitSize = CommitSize;
00391
Buffer->ViewSize = ViewSize;
00392
return Buffer;
00393 }
00394
00395
00396 NTSYSAPI
00397
NTSTATUS
00398 NTAPI
00399 RtlDestroyQueryDebugBuffer(
00400 IN PRTL_DEBUG_INFORMATION Buffer
00401 )
00402 {
00403
NTSTATUS Status;
00404 HANDLE ProcessHandle,
ThreadHandle;
00405 THREAD_BASIC_INFORMATION BasicInformation;
00406 PTEB Teb;
00407 PVOID StackDeallocationBase;
00408 ULONG
Size;
00409 SIZE_T BigSize;
00410
00411
RtlpChangeQueryDebugBufferTarget(
Buffer,
NULL,
NULL );
00412
00413
Status = STATUS_SUCCESS;
00414
if (
Buffer->TargetThreadHandle !=
NULL) {
00415 StackDeallocationBase =
NULL;
00416
Status =
NtQueryInformationThread(
Buffer->TargetThreadHandle,
00417 ThreadBasicInformation,
00418 &BasicInformation,
00419
sizeof( BasicInformation ),
00420
NULL
00421 );
00422
if (
NT_SUCCESS(
Status )) {
00423
if (Teb = BasicInformation.TebBaseAddress) {
00424
NtReadVirtualMemory(
Buffer->TargetProcessHandle,
00425 &Teb->DeallocationStack,
00426 &StackDeallocationBase,
00427
sizeof( StackDeallocationBase ),
00428 &
Size
00429 );
00430 }
00431 }
00432
00433
Buffer->EventPairTarget =
NULL;
00434
NtSetLowEventPair(
Buffer->EventPairClient );
00435
NtClose(
Buffer->EventPairClient );
00436
Status =
NtWaitForSingleObject(
Buffer->TargetThreadHandle,
00437
TRUE,
00438
NULL
00439 );
00440
if (
NT_SUCCESS(
Status )) {
00441
Status =
NtQueryInformationThread(
Buffer->TargetThreadHandle,
00442 ThreadBasicInformation,
00443 &BasicInformation,
00444
sizeof( BasicInformation ),
00445
NULL
00446 );
00447
if (
NT_SUCCESS(
Status )) {
00448
Status = BasicInformation.ExitStatus;
00449 }
00450 }
00451
00452 BigSize = 0;
00453
NtFreeVirtualMemory(
Buffer->TargetProcessHandle,
00454 &StackDeallocationBase,
00455 &BigSize,
00456 MEM_RELEASE
00457 );
00458 }
00459
00460
NtClose(
Buffer->SectionHandleClient );
00461
NtUnmapViewOfSection( NtCurrentProcess(),
Buffer );
00462
return Status;
00463 }
00464
00465
00466 NTSYSAPI
00467
NTSTATUS
00468 NTAPI
00469 RtlQueryProcessDebugInformation(
00470 IN HANDLE UniqueProcessId,
00471 IN ULONG Flags,
00472 IN OUT PRTL_DEBUG_INFORMATION Buffer
00473 )
00474 {
00475
NTSTATUS Status;
00476 HANDLE ProcessHandle,
ThreadHandle;
00477 THREAD_BASIC_INFORMATION BasicInformation;
00478 PTEB Teb;
00479 PVOID StackDeallocationBase;
00480 ULONG
Size;
00481 SIZE_T BigSize;
00482
00483
Buffer->Flags = Flags;
00484
if (
Buffer->OffsetFree != 0) {
00485 RtlZeroMemory( (
Buffer+1),
Buffer->OffsetFree - (SIZE_T)
sizeof(*
Buffer) );
00486 }
00487
Buffer->OffsetFree =
sizeof( *Buffer );
00488
00489
if (NtCurrentTeb()->ClientId.UniqueProcess != UniqueProcessId) {
00490
00491
00492
00493 ProcessHandle =
NULL;
00494
Status =
RtlpChangeQueryDebugBufferTarget(
Buffer, UniqueProcessId, &ProcessHandle );
00495
if (!
NT_SUCCESS(
Status )) {
00496
return Status;
00497 }
00498
00499
if (ProcessHandle ==
NULL) {
00500 waitForDump:
00501
Status =
NtSetLowWaitHighEventPair(
Buffer->EventPairClient );
00502 }
00503
else {
00504
00505
00506
00507
00508
00509
00510
00511
Status =
RtlCreateUserThread( ProcessHandle,
00512
NULL,
00513
TRUE,
00514 0,
00515 0,
00516 0,
00517
RtlpQueryProcessDebugInformationRemote,
00518
Buffer->ViewBaseTarget,
00519 &
ThreadHandle,
00520
NULL
00521 );
00522
if (
NT_SUCCESS(
Status )) {
00523
00524
Status =
NtSetInformationThread(
ThreadHandle,
00525 ThreadHideFromDebugger,
00526
NULL,
00527 0
00528 );
00529
00530
if ( !
NT_SUCCESS(
Status) ) {
00531
NtTerminateThread(
ThreadHandle,
Status);
00532
NtClose(
ThreadHandle);
00533
NtClose(ProcessHandle);
00534
return Status;
00535 }
00536
00537
NtResumeThread(
ThreadHandle,
NULL);
00538
00539
if (
Buffer->EventPairClient !=
NULL) {
00540
Buffer->TargetThreadHandle =
ThreadHandle;
00541
Buffer->TargetProcessHandle = ProcessHandle;
00542
goto waitForDump;
00543 }
00544
00545 StackDeallocationBase =
NULL;
00546
Status =
NtQueryInformationThread(
ThreadHandle,
00547 ThreadBasicInformation,
00548 &BasicInformation,
00549
sizeof( BasicInformation ),
00550
NULL
00551 );
00552
if (
NT_SUCCESS(
Status )) {
00553
if (Teb = BasicInformation.TebBaseAddress) {
00554
NtReadVirtualMemory( ProcessHandle,
00555 &Teb->DeallocationStack,
00556 &StackDeallocationBase,
00557
sizeof( StackDeallocationBase ),
00558 &
Size
00559 );
00560 }
00561 }
00562
00563
Status =
NtWaitForSingleObject(
ThreadHandle,
00564
TRUE,
00565
NULL
00566 );
00567
00568
if (
NT_SUCCESS(
Status )) {
00569
Status =
NtQueryInformationThread(
ThreadHandle,
00570 ThreadBasicInformation,
00571 &BasicInformation,
00572
sizeof( BasicInformation ),
00573
NULL
00574 );
00575
if (
NT_SUCCESS(
Status )) {
00576
Status = BasicInformation.ExitStatus;
00577 }
00578 }
00579
00580 BigSize = 0;
00581
NtFreeVirtualMemory( ProcessHandle, &StackDeallocationBase, &BigSize, MEM_RELEASE );
00582
NtClose(
ThreadHandle );
00583
00584 }
00585
00586
00587
NtClose( ProcessHandle );
00588 }
00589 }
00590
else {
00591
if (Flags & RTL_QUERY_PROCESS_MODULES) {
00592
Status =
RtlQueryProcessModuleInformation(
Buffer );
00593
if (
Status != STATUS_SUCCESS) {
00594
return Status;
00595 }
00596 }
00597
00598
if (Flags & RTL_QUERY_PROCESS_BACKTRACES) {
00599
Status =
RtlQueryProcessBackTraceInformation(
Buffer );
00600
if (
Status != STATUS_SUCCESS) {
00601
return Status;
00602 }
00603 }
00604
00605
if (Flags & RTL_QUERY_PROCESS_LOCKS) {
00606
Status =
RtlQueryProcessLockInformation(
Buffer );
00607
if (
Status != STATUS_SUCCESS) {
00608
return Status;
00609 }
00610 }
00611
00612
if (Flags & (RTL_QUERY_PROCESS_HEAP_SUMMARY |
00613 RTL_QUERY_PROCESS_HEAP_TAGS |
00614 RTL_QUERY_PROCESS_HEAP_ENTRIES
00615 )
00616 ) {
00617
Status =
RtlQueryProcessHeapInformation(
Buffer );
00618
if (
Status != STATUS_SUCCESS) {
00619
return Status;
00620 }
00621 }
00622 }
00623
00624
return Status;
00625 }
00626
00627
00628
NTSTATUS
00629 NTAPI
00630 RtlQueryProcessModuleInformation(
00631 IN OUT PRTL_DEBUG_INFORMATION Buffer
00632 )
00633 {
00634
NTSTATUS Status;
00635 ULONG RequiredLength;
00636 PRTL_PROCESS_MODULES Modules;
00637
00638
Status =
LdrQueryProcessModuleInformation(
NULL,
00639 0,
00640 &RequiredLength
00641 );
00642
if (
Status == STATUS_INFO_LENGTH_MISMATCH) {
00643 Modules =
RtlpCommitQueryDebugInfo(
Buffer, RequiredLength );
00644
if (Modules !=
NULL) {
00645
Status =
LdrQueryProcessModuleInformation( Modules,
00646 RequiredLength,
00647 &RequiredLength
00648 );
00649
if (
NT_SUCCESS(
Status )) {
00650
Buffer->Modules = Modules;
00651
return STATUS_SUCCESS;
00652 }
00653 }
00654 }
00655
00656
return STATUS_NO_MEMORY;
00657 }
00658
00659
NTSTATUS
00660 RtlQueryProcessBackTraceInformation(
00661 IN OUT PRTL_DEBUG_INFORMATION Buffer
00662 )
00663 {
00664
#if i386
00665
NTSTATUS Status;
00666 OUT PRTL_PROCESS_BACKTRACES BackTraces;
00667 PRTL_PROCESS_BACKTRACE_INFORMATION BackTraceInfo;
00668
PSTACK_TRACE_DATABASE DataBase;
00669
PRTL_STACK_TRACE_ENTRY p, *pp;
00670 ULONG
n;
00671
00672 DataBase =
RtlpAcquireStackTraceDataBase();
00673
if (DataBase ==
NULL) {
00674
return STATUS_SUCCESS;
00675 }
00676
00677 BackTraces =
RtlpCommitQueryDebugInfo(
Buffer, FIELD_OFFSET( RTL_PROCESS_BACKTRACES, BackTraces ) );
00678
if (BackTraces ==
NULL) {
00679
return STATUS_NO_MEMORY;
00680 }
00681
00682 DataBase->
DumpInProgress =
TRUE;
00683
RtlpReleaseStackTraceDataBase();
00684
try {
00685 BackTraces->CommittedMemory = (ULONG)DataBase->
CurrentUpperCommitLimit -
00686 (ULONG)DataBase->
CommitBase;
00687 BackTraces->ReservedMemory = (ULONG)DataBase->
EntryIndexArray -
00688 (ULONG)DataBase->
CommitBase;
00689 BackTraces->NumberOfBackTraceLookups = DataBase->
NumberOfEntriesLookedUp;
00690 BackTraces->NumberOfBackTraces = DataBase->
NumberOfEntriesAdded;
00691 BackTraceInfo =
RtlpCommitQueryDebugInfo(
Buffer, (
sizeof( *BackTraceInfo ) * BackTraces->NumberOfBackTraces) );
00692
if (BackTraceInfo ==
NULL) {
00693
Status = STATUS_NO_MEMORY;
00694 }
00695
else {
00696
Status = STATUS_SUCCESS;
00697
n = DataBase->
NumberOfEntriesAdded;
00698 pp = DataBase->
EntryIndexArray;
00699
while (
n--) {
00700 p = *--pp;
00701 BackTraceInfo->SymbolicBackTrace =
NULL;
00702 BackTraceInfo->TraceCount = p->
TraceCount;
00703 BackTraceInfo->Index = p->
Index;
00704 BackTraceInfo->Depth = p->
Depth;
00705 RtlMoveMemory( BackTraceInfo->BackTrace,
00706 p->
BackTrace,
00707 p->
Depth *
sizeof( PVOID )
00708 );
00709 BackTraceInfo++;
00710 }
00711 }
00712 }
00713 finally {
00714 DataBase->
DumpInProgress =
FALSE;
00715 }
00716
00717
if (
NT_SUCCESS(
Status )) {
00718
Buffer->BackTraces = BackTraces;
00719 }
00720
00721
return Status;
00722
#else
00723
return STATUS_SUCCESS;
00724
#endif // i386
00725
}
00726
00727
00728
NTSTATUS
00729 RtlpQueryProcessEnumHeapsRoutine(
00730 PVOID HeapHandle,
00731 PVOID Parameter
00732 )
00733 {
00734 PRTL_DEBUG_INFORMATION
Buffer = (PRTL_DEBUG_INFORMATION)Parameter;
00735 PRTL_PROCESS_HEAPS Heaps =
Buffer->Heaps;
00736
PHEAP Heap = (
PHEAP)
HeapHandle;
00737 PRTL_HEAP_INFORMATION HeapInfo;
00738
PHEAP_SEGMENT Segment;
00739 UCHAR SegmentIndex;
00740
00741 HeapInfo =
RtlpCommitQueryDebugInfo(
Buffer,
sizeof( *HeapInfo ) );
00742
if (HeapInfo ==
NULL) {
00743
return STATUS_NO_MEMORY;
00744 }
00745
00746 HeapInfo->BaseAddress = Heap;
00747 HeapInfo->
Flags = Heap->
Flags;
00748 HeapInfo->EntryOverhead =
sizeof(
HEAP_ENTRY );
00749 HeapInfo->CreatorBackTraceIndex = Heap->
AllocatorBackTraceIndex;
00750 SegmentIndex =
HEAP_MAXIMUM_SEGMENTS;
00751
while (SegmentIndex--) {
00752 Segment = Heap->
Segments[ SegmentIndex ];
00753
if (Segment) {
00754 HeapInfo->BytesCommitted += (Segment->
NumberOfPages -
00755 Segment->
NumberOfUnCommittedPages
00756 ) *
PAGE_SIZE;
00757
00758 }
00759 }
00760 HeapInfo->BytesAllocated = HeapInfo->BytesCommitted -
00761 (Heap->
TotalFreeSize <<
HEAP_GRANULARITY_SHIFT);
00762 Heaps->NumberOfHeaps += 1;
00763
return STATUS_SUCCESS;
00764 }
00765
00766 NTSYSAPI
00767
NTSTATUS
00768 NTAPI
00769 RtlQueryProcessHeapInformation(
00770 IN OUT PRTL_DEBUG_INFORMATION Buffer
00771 )
00772 {
00773
NTSTATUS Status;
00774
PHEAP Heap;
00775 BOOLEAN LockAcquired;
00776 PRTL_PROCESS_HEAPS Heaps;
00777 PRTL_HEAP_INFORMATION HeapInfo;
00778 ULONG NumberOfHeaps;
00779 PVOID *ProcessHeaps;
00780 UCHAR SegmentIndex;
00781 ULONG i,
n, TagIndex;
00782
PHEAP_SEGMENT Segment;
00783 PRTL_HEAP_TAG Tags;
00784
PHEAP_PSEUDO_TAG_ENTRY PseudoTags;
00785 PRTL_HEAP_ENTRY Entries;
00786
PHEAP_ENTRY CurrentBlock;
00787
PHEAP_ENTRY_EXTRA ExtraStuff;
00788 PRTL_HEAP_ENTRY p;
00789 PLIST_ENTRY Head, Next;
00790
PHEAP_VIRTUAL_ALLOC_ENTRY VirtualAllocBlock;
00791 ULONG
Size;
00792
PHEAP_UNCOMMMTTED_RANGE UnCommittedRange;
00793
00794 Heaps =
RtlpCommitQueryDebugInfo(
Buffer, FIELD_OFFSET( RTL_PROCESS_HEAPS, Heaps ) );
00795
if (Heaps ==
NULL) {
00796
return STATUS_NO_MEMORY;
00797 }
00798
00799
Buffer->Heaps = Heaps;
00800
Status =
RtlEnumProcessHeaps(
RtlpQueryProcessEnumHeapsRoutine,
Buffer );
00801
if (
NT_SUCCESS(
Status )) {
00802
if (
Buffer->Flags & RTL_QUERY_PROCESS_HEAP_TAGS) {
00803 Heap =
RtlpGlobalTagHeap;
00804
if (Heap->
TagEntries !=
NULL) {
00805 HeapInfo =
RtlpCommitQueryDebugInfo(
Buffer,
sizeof( *HeapInfo ) );
00806
if (HeapInfo ==
NULL) {
00807
return STATUS_NO_MEMORY;
00808 }
00809
00810 HeapInfo->BaseAddress = Heap;
00811 HeapInfo->
Flags = Heap->
Flags;
00812 HeapInfo->EntryOverhead =
sizeof(
HEAP_ENTRY );
00813 Heaps->NumberOfHeaps += 1;
00814 }
00815
00816
for (i=0; i<Heaps->NumberOfHeaps; i++) {
00817 HeapInfo = &Heaps->Heaps[ i ];
00818
if (
Buffer->SpecificHeap ==
NULL ||
00819
Buffer->SpecificHeap == HeapInfo->BaseAddress
00820 ) {
00821 Heap = HeapInfo->BaseAddress;
00822 HeapInfo->NumberOfTags = Heap->
NextAvailableTagIndex;
00823
n = HeapInfo->NumberOfTags *
sizeof( RTL_HEAP_TAG );
00824
if (Heap->
PseudoTagEntries !=
NULL) {
00825 HeapInfo->NumberOfTags +=
HEAP_MAXIMUM_FREELISTS + 1;
00826
n += (
HEAP_MAXIMUM_FREELISTS + 1) *
sizeof( RTL_HEAP_TAG );
00827 }
00828 Tags =
RtlpCommitQueryDebugInfo(
Buffer,
n );
00829
if (Tags ==
NULL) {
00830
Status = STATUS_NO_MEMORY;
00831
break;
00832 }
00833 HeapInfo->Tags = Tags;
00834
if ((PseudoTags = Heap->
PseudoTagEntries) !=
NULL) {
00835 HeapInfo->NumberOfPseudoTags =
HEAP_NUMBER_OF_PSEUDO_TAG;
00836 HeapInfo->PseudoTagGranularity =
HEAP_GRANULARITY;
00837
for (TagIndex=0; TagIndex<=
HEAP_MAXIMUM_FREELISTS; TagIndex++) {
00838 Tags->NumberOfAllocations = PseudoTags->
Allocs;
00839 Tags->NumberOfFrees = PseudoTags->
Frees;
00840 Tags->BytesAllocated = PseudoTags->
Size <<
HEAP_GRANULARITY_SHIFT;
00841 Tags->TagIndex = (
USHORT)(TagIndex | HEAP_PSEUDO_TAG_FLAG);
00842
if (TagIndex == 0) {
00843 swprintf( Tags->TagName,
L"Objects>%4u",
00844
HEAP_MAXIMUM_FREELISTS <<
HEAP_GRANULARITY_SHIFT
00845 );
00846 }
00847
else
00848
if (TagIndex <
HEAP_MAXIMUM_FREELISTS) {
00849 swprintf( Tags->TagName,
L"Objects=%4u",
00850 TagIndex <<
HEAP_GRANULARITY_SHIFT
00851 );
00852 }
00853
else {
00854 swprintf( Tags->TagName,
L"VirtualAlloc",
00855 TagIndex <<
HEAP_GRANULARITY_SHIFT
00856 );
00857 }
00858
00859 Tags += 1;
00860 PseudoTags += 1;
00861 }
00862 }
00863
00864 RtlMoveMemory( Tags,
00865 Heap->
TagEntries,
00866 Heap->
NextAvailableTagIndex *
sizeof( RTL_HEAP_TAG )
00867 );
00868
for (TagIndex=0; TagIndex<Heap->
NextAvailableTagIndex; TagIndex++) {
00869 Tags->BytesAllocated <<=
HEAP_GRANULARITY_SHIFT;
00870 Tags += 1;
00871 }
00872 }
00873 }
00874 }
00875 }
00876
else {
00877
Buffer->Heaps =
NULL;
00878 }
00879
if (
NT_SUCCESS(
Status )) {
00880
if (
Buffer->Flags & RTL_QUERY_PROCESS_HEAP_ENTRIES) {
00881
for (i=0; i<Heaps->NumberOfHeaps; i++) {
00882 HeapInfo = &Heaps->Heaps[ i ];
00883 Heap = HeapInfo->BaseAddress;
00884
if (
Buffer->SpecificHeap ==
NULL ||
00885
Buffer->SpecificHeap == Heap
00886 ) {
00887
if (!(Heap->
Flags & HEAP_NO_SERIALIZE)) {
00888 RtlEnterCriticalSection( (PRTL_CRITICAL_SECTION)Heap->
LockVariable );
00889 LockAcquired =
TRUE;
00890 }
00891
else {
00892 LockAcquired =
FALSE;
00893 }
00894
00895
try {
00896
for (SegmentIndex=0; SegmentIndex<
HEAP_MAXIMUM_SEGMENTS; SegmentIndex++) {
00897 Segment = Heap->
Segments[ SegmentIndex ];
00898
if (!Segment) {
00899
continue;
00900 }
00901
00902 Entries =
RtlpCommitQueryDebugInfo(
Buffer,
sizeof( *Entries ) );
00903
if (Entries ==
NULL) {
00904
Status = STATUS_NO_MEMORY;
00905
break;
00906 }
00907
else
00908
if (HeapInfo->Entries ==
NULL) {
00909 HeapInfo->Entries = Entries;
00910 }
00911
00912 Entries->Flags = RTL_HEAP_SEGMENT;
00913 Entries->AllocatorBackTraceIndex = Segment->
AllocatorBackTraceIndex;
00914 Entries->Size = Segment->
NumberOfPages *
PAGE_SIZE;
00915 Entries->u.s2.CommittedSize = (Segment->
NumberOfPages -
00916 Segment->
NumberOfUnCommittedPages
00917 ) *
PAGE_SIZE;
00918 Entries->u.s2.FirstBlock = Segment->
FirstEntry;
00919 HeapInfo->NumberOfEntries++;
00920
00921 UnCommittedRange = Segment->
UnCommittedRanges;
00922 CurrentBlock = Segment->
FirstEntry;
00923
while (CurrentBlock < Segment->
LastValidEntry) {
00924 Entries =
RtlpCommitQueryDebugInfo(
Buffer,
sizeof( *Entries ) );
00925
if (Entries ==
NULL) {
00926
Status = STATUS_NO_MEMORY;
00927
break;
00928 }
00929
00930
Size = CurrentBlock->
Size <<
HEAP_GRANULARITY_SHIFT;
00931 Entries->Size =
Size;
00932 HeapInfo->NumberOfEntries++;
00933
if (CurrentBlock->
Flags &
HEAP_ENTRY_BUSY) {
00934
if (CurrentBlock->
Flags &
HEAP_ENTRY_EXTRA_PRESENT) {
00935 ExtraStuff = (
PHEAP_ENTRY_EXTRA)(CurrentBlock + CurrentBlock->
Size - 1);
00936
#if i386
00937
Entries->
AllocatorBackTraceIndex = ExtraStuff->
AllocatorBackTraceIndex;
00938
#endif // i386
00939
Entries->Flags |= RTL_HEAP_SETTABLE_VALUE;
00940 Entries->u.s1.Settable = ExtraStuff->
Settable;
00941 Entries->u.s1.Tag = ExtraStuff->
TagIndex;
00942 }
00943
else {
00944 Entries->u.s1.Tag = CurrentBlock->
SmallTagIndex;
00945 }
00946
00947 Entries->Flags |= RTL_HEAP_BUSY | (CurrentBlock->
Flags &
HEAP_ENTRY_SETTABLE_FLAGS);
00948 }
00949
else
00950
if (CurrentBlock->
Flags &
HEAP_ENTRY_EXTRA_PRESENT) {
00951
PHEAP_FREE_ENTRY_EXTRA FreeExtra;
00952
00953 FreeExtra = (
PHEAP_FREE_ENTRY_EXTRA)(CurrentBlock + CurrentBlock->
Size) - 1;
00954 Entries->u.s1.Tag = FreeExtra->
TagIndex;
00955 Entries->AllocatorBackTraceIndex = FreeExtra->
FreeBackTraceIndex;
00956 }
00957
00958
if (CurrentBlock->
Flags &
HEAP_ENTRY_LAST_ENTRY) {
00959 CurrentBlock += CurrentBlock->
Size;
00960
if (UnCommittedRange ==
NULL) {
00961 CurrentBlock = Segment->
LastValidEntry;
00962 }
00963
else {
00964 Entries =
RtlpCommitQueryDebugInfo(
Buffer,
sizeof( *Entries ) );
00965
if (Entries ==
NULL) {
00966
Status = STATUS_NO_MEMORY;
00967
break;
00968 }
00969
00970 Entries->Flags = RTL_HEAP_UNCOMMITTED_RANGE;
00971 Entries->Size = UnCommittedRange->
Size;
00972 HeapInfo->NumberOfEntries++;
00973
00974 CurrentBlock = (
PHEAP_ENTRY)
00975 ((PCHAR)UnCommittedRange->
Address + UnCommittedRange->
Size);
00976 UnCommittedRange = UnCommittedRange->
Next;
00977 }
00978 }
00979
else {
00980 CurrentBlock += CurrentBlock->
Size;
00981 }
00982 }
00983 }
00984
00985 Head = &Heap->
VirtualAllocdBlocks;
00986 Next = Head->Flink;
00987
while (Head != Next) {
00988 VirtualAllocBlock = CONTAINING_RECORD( Next,
HEAP_VIRTUAL_ALLOC_ENTRY, Entry );
00989 CurrentBlock = &VirtualAllocBlock->
BusyBlock;
00990 Entries =
RtlpCommitQueryDebugInfo(
Buffer,
sizeof( *Entries ) );
00991
if (Entries ==
NULL) {
00992
Status = STATUS_NO_MEMORY;
00993
break;
00994 }
00995
else
00996
if (HeapInfo->Entries ==
NULL) {
00997 HeapInfo->Entries = Entries;
00998 }
00999
01000 Entries->Flags = RTL_HEAP_SEGMENT;
01001 Entries->Size = VirtualAllocBlock->
ReserveSize;
01002 Entries->u.s2.CommittedSize = VirtualAllocBlock->
CommitSize;
01003 Entries->u.s2.FirstBlock = CurrentBlock;
01004 HeapInfo->NumberOfEntries++;
01005 Entries =
RtlpCommitQueryDebugInfo(
Buffer,
sizeof( *Entries ) );
01006
if (Entries ==
NULL) {
01007
Status = STATUS_NO_MEMORY;
01008
break;
01009 }
01010
01011 Entries->Size = VirtualAllocBlock->
CommitSize;
01012 Entries->Flags = RTL_HEAP_BUSY | (CurrentBlock->
Flags &
HEAP_ENTRY_SETTABLE_FLAGS);
01013
#if i386
01014
Entries->AllocatorBackTraceIndex = VirtualAllocBlock->
ExtraStuff.
AllocatorBackTraceIndex;
01015
#endif // i386
01016
Entries->Flags |= RTL_HEAP_SETTABLE_VALUE;
01017 Entries->u.s1.Settable = VirtualAllocBlock->
ExtraStuff.
Settable;
01018 Entries->u.s1.Tag = VirtualAllocBlock->
ExtraStuff.
TagIndex;
01019 HeapInfo->NumberOfEntries++;
01020
01021 Next = Next->Flink;
01022 }
01023 }
01024 finally {
01025
01026
01027
01028
01029
if (LockAcquired) {
01030 RtlLeaveCriticalSection( (PRTL_CRITICAL_SECTION)Heap->
LockVariable );
01031 }
01032 }
01033 }
01034
01035
if (!
NT_SUCCESS(
Status )) {
01036
break;
01037 }
01038 }
01039 }
01040 }
01041
01042
return Status;
01043 }
01044
01045
01046 NTSYSAPI
01047
NTSTATUS
01048 NTAPI
01049 RtlQueryProcessLockInformation(
01050 IN OUT PRTL_DEBUG_INFORMATION Buffer
01051 )
01052 {
01053
NTSTATUS Status;
01054 PLIST_ENTRY Head, Next;
01055 PRTL_PROCESS_LOCKS Locks;
01056 PRTL_PROCESS_LOCK_INFORMATION LockInfo;
01057 PRTL_CRITICAL_SECTION CriticalSection;
01058 PRTL_CRITICAL_SECTION_DEBUG DebugInfo;
01059 PRTL_RESOURCE
Resource;
01060 PRTL_RESOURCE_DEBUG ResourceDebugInfo;
01061
01062 Locks =
RtlpCommitQueryDebugInfo(
Buffer, FIELD_OFFSET( RTL_PROCESS_LOCKS, Locks ) );
01063
if (Locks ==
NULL) {
01064
return STATUS_NO_MEMORY;
01065 }
01066
01067 RtlEnterCriticalSection( &
RtlCriticalSectionLock );
01068 Head = &
RtlCriticalSectionList;
01069 Next = Head->Flink;
01070
Status = STATUS_SUCCESS;
01071
while (Next != Head) {
01072 DebugInfo = CONTAINING_RECORD( Next,
01073 RTL_CRITICAL_SECTION_DEBUG,
01074 ProcessLocksList
01075 );
01076 LockInfo =
RtlpCommitQueryDebugInfo(
Buffer,
sizeof( RTL_PROCESS_LOCK_INFORMATION ) );
01077
if (LockInfo ==
NULL) {
01078
Status = STATUS_NO_MEMORY;
01079
break;
01080 }
01081
01082 CriticalSection = DebugInfo->CriticalSection;
01083
try {
01084 LockInfo->Address = CriticalSection;
01085 LockInfo->Type = DebugInfo->Type;
01086 LockInfo->CreatorBackTraceIndex = DebugInfo->CreatorBackTraceIndex;
01087
if (LockInfo->Type == RTL_CRITSECT_TYPE) {
01088 LockInfo->OwningThread = CriticalSection->OwningThread;
01089 LockInfo->LockCount = CriticalSection->LockCount;
01090 LockInfo->RecursionCount = CriticalSection->RecursionCount;
01091 LockInfo->ContentionCount = DebugInfo->ContentionCount;
01092 LockInfo->EntryCount = DebugInfo->EntryCount;
01093 }
01094
else {
01095
Resource = (PRTL_RESOURCE)CriticalSection;
01096 ResourceDebugInfo =
Resource->DebugInfo;
01097 LockInfo->
ContentionCount = ResourceDebugInfo->ContentionCount;
01098 LockInfo->OwningThread =
Resource->ExclusiveOwnerThread;
01099 LockInfo->LockCount =
Resource->NumberOfActive;
01100 LockInfo->NumberOfWaitingShared =
Resource->NumberOfWaitingShared;
01101 LockInfo->NumberOfWaitingExclusive =
Resource->NumberOfWaitingExclusive;
01102 }
01103
01104 Locks->NumberOfLocks++;
01105 }
01106 except (
EXCEPTION_EXECUTE_HANDLER) {
01107
DbgPrint(
"NTDLL: Lost critical section %08lX\n", CriticalSection);
01108
RtlpDeCommitQueryDebugInfo(
Buffer, LockInfo,
sizeof( RTL_PROCESS_LOCK_INFORMATION ) );
01109 }
01110
01111
if (Next == Next->Flink) {
01112
01113
01114
01115
break;
01116 }
01117
else {
01118 Next = Next->Flink;
01119 }
01120 }
01121
01122 RtlLeaveCriticalSection( &
RtlCriticalSectionLock );
01123
01124
if (
NT_SUCCESS(
Status )) {
01125
Buffer->Locks = Locks;
01126 }
01127
01128
return Status;
01129 }