Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1293 lines
40 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
process.c
Abstract:
WinDbg Extension Api
Author:
Wesley Witt (wesw) 15-Aug-1993
Environment:
User Mode.
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
extern ULONG STeip, STebp, STesp;
static PHANDLE_TABLE PspCidTable;
static HANDLE_TABLE CapturedPspCidTable;
PEPROCESS ProcessLastDump;
ULONG ThreadLastDump;
ULONG TotalProcessCommit;
#ifdef TARGET_i386
VOID GetStackTraceRegs(ULONG,PULONG,PULONG,PULONG);
#endif
BOOLEAN
GetTheSystemTime (
OUT PLARGE_INTEGER Time
);
DECLARE_API( process )
/*++
Routine Description:
Dumps the active process list.
Arguments:
None.
Return Value:
None.
--*/
{
ULONG ProcessToDump;
ULONG Flags;
ULONG Result;
LIST_ENTRY List;
PLIST_ENTRY Next;
ULONG ProcessHead;
PEPROCESS Process;
EPROCESS ProcessContents;
PETHREAD Thread;
ETHREAD ThreadContents;
ProcessToDump = 0xFFFFFFFF;
Flags = 0xFFFFFFFF;
sscanf(args,"%lx %lx",&ProcessToDump,&Flags);
if (ProcessToDump == 0xFFFFFFFF) {
ProcessToDump = (ULONG)GetCurrentProcessAddress( dwProcessor, hCurrentThread, NULL );
if (ProcessToDump == 0) {
dprintf("Unable to get current process pointer.\n");
return;
}
if (Flags == 0xFFFFFFFF) {
Flags = 3;
}
}
if (ProcessToDump == 0) {
dprintf("**** NT ACTIVE PROCESS DUMP ****\n");
if (Flags == 0xFFFFFFFF) {
Flags = 3;
}
}
if (ProcessToDump < MM_USER_PROBE_ADDRESS) {
ProcessHead = GetExpression( "PsActiveProcessHead" );
if (!ProcessHead) {
dprintf("Unable to get value of PsActiveProcessHead\n");
return;
}
if (!ReadMemory( ProcessHead, &List, sizeof(LIST_ENTRY), &Result )) {
dprintf("Unable to get value of PsActiveProcessHead\n");
return;
}
if (ProcessToDump != 0) {
dprintf("Searching for Process with Cid == %lx\n", ProcessToDump);
}
Next = List.Flink;
if (Next == NULL) {
dprintf("PsActiveProcessHead is NULL!\n");
return;
}
}
else {
Next = NULL;
ProcessHead = 1;
}
while((ULONG)Next != ProcessHead) {
if (Next != NULL) {
Process = CONTAINING_RECORD(Next,EPROCESS,ActiveProcessLinks);
}
else {
Process = (PEPROCESS)ProcessToDump;
}
if (!ReadMemory( (DWORD)Process, &ProcessContents, sizeof(EPROCESS), &Result )) {
dprintf("Unable to read _EPROCESS at %lx\n",Process);
return;
}
if (ProcessToDump == 0 ||
ProcessToDump < MM_USER_PROBE_ADDRESS && ProcessToDump == (ULONG)ProcessContents.UniqueProcessId ||
ProcessToDump > MM_USER_PROBE_ADDRESS && ProcessToDump == (ULONG)Process
) {
if (DumpProcess (&ProcessContents, Process, Flags) && (Flags & 6)) {
Next = ProcessContents.Pcb.ThreadListHead.Flink;
while ( Next != &Process->Pcb.ThreadListHead) {
Thread = (PETHREAD)(CONTAINING_RECORD(Next,KTHREAD,ThreadListEntry));
if (!ReadMemory((DWORD)Thread,
&ThreadContents,
sizeof(ETHREAD),
&Result)) {
dprintf("Unable to read _ETHREAD at %lx\n",Thread);
break;
}
if (!DumpThread(dwProcessor," ", &ThreadContents, Thread, Flags)) {
break;
}
Next = ((PKTHREAD)&ThreadContents)->ThreadListEntry.Flink;
if (CheckControlC()) {
return;
}
}
EXPRLastDump = (ULONG)Process;
ProcessLastDump = Process;
dprintf("\n");
}
if (ProcessToDump != 0) {
return;
}
}
if (Next == NULL) {
return;
}
Next = ProcessContents.ActiveProcessLinks.Flink;
if (CheckControlC()) {
return;
}
}
return;
}
DECLARE_API( thread )
/*++
Routine Description:
Dumps the specified thread.
Arguments:
None.
Return Value:
None.
--*/
{
ULONG Address;
ULONG Flags;
ULONG result;
PETHREAD Thread;
ETHREAD ThreadContents;
Address = 0xFFFFFFFF;
Flags = 6;
sscanf(args,"%lx %lx",&Address,&Flags);
if (Address == 0xFFFFFFFF) {
Address = (ULONG)GetCurrentThreadAddress( (USHORT)dwProcessor, hCurrentThread);
}
Thread = (PETHREAD)(PVOID)Address;
if ( !ReadMemory( (DWORD)Thread,
&ThreadContents,
sizeof(ETHREAD),
&result) ) {
dprintf("%08lx: Unable to get thread contents\n", Thread );
return;
}
DumpThread (dwProcessor,"", &ThreadContents, Thread, Flags);
EXPRLastDump = (ULONG)Thread;
ThreadLastDump = (ULONG)Thread;
return;
}
BOOL
DumpProcess (
IN PEPROCESS ProcessContents,
IN PEPROCESS RealProcessBase,
IN ULONG Flags
)
{
HANDLE_TABLE HandleTable;
ULONG NumberOfHandles;
WCHAR Buf[256];
ULONG Result;
LARGE_INTEGER RunTime;
TIME_FIELDS Times;
ULONG KeTimeIncrement;
ULONG TimeIncrement;
if (ProcessContents->Pcb.Header.Type != ProcessObject) {
dprintf("TYPE mismatch for process object at %lx\n",RealProcessBase);
return FALSE;
}
NumberOfHandles = 0;
if (ProcessContents->ObjectTable) {
if (ReadMemory((DWORD)ProcessContents->ObjectTable,
&HandleTable,
sizeof(HandleTable),
&Result)) {
NumberOfHandles = (HandleTable.TableBound - HandleTable.TableEntries) - 1;
}
}
dprintf("PROCESS %08lx Cid: %04lx Peb: %08x ParentCid: %04lx\n",
RealProcessBase,
ProcessContents->UniqueProcessId,
ProcessContents->Peb,
ProcessContents->InheritedFromUniqueProcessId
);
dprintf(" DirBase: %08lx ObjectTable: %08lx TableSize: %3u.\n",
ProcessContents->Pcb.DirectoryTableBase[ 0 ],
ProcessContents->ObjectTable,
NumberOfHandles
);
if (ProcessContents->ImageFileName[0] != '\0' ) {
strcpy((char *)Buf,ProcessContents->ImageFileName);
} else {
strcpy((char *)Buf,"System Process");
}
dprintf(" Image: %s\n",Buf);
if (!(Flags & 1)) {
dprintf("\n");
return TRUE;
}
dprintf(" VadRoot %lx Clone %lx Private %ld. Modified %ld. Locked %ld.\n",ProcessContents->VadRoot,
ProcessContents->CloneRoot,
ProcessContents->NumberOfPrivatePages,
ProcessContents->ModifiedPageCount,
ProcessContents->NumberOfLockedPages);
dprintf(" %X MutantState %s OwningThread %lx\n",
&RealProcessBase->ProcessMutant,
ProcessContents->ProcessMutant.Header.SignalState ? "Signalled" : "Locked",
ProcessContents->ProcessMutant.OwnerThread);
if (ProcessContents->LockCount != 1) {
dprintf(" Process Lock Owned by Thread %lx\n",
ProcessContents->LockOwner);
}
//
// Primary token
//
dprintf(" Token %lx\n", ProcessContents->Token );
//
// Get the time increment value which is used to compute runtime.
//
KeTimeIncrement = GetExpression( "KeTimeIncrement" );
if (KeTimeIncrement) {
ReadMemory( KeTimeIncrement, &TimeIncrement, sizeof(ULONG), &Result );
}
GetTheSystemTime (&RunTime);
RunTime.QuadPart -= ProcessContents->CreateTime.QuadPart;
RtlTimeToElapsedTimeFields ( &RunTime, &Times);
dprintf(" ElapsedTime %3ld:%02ld:%02ld.%04ld\n",
Times.Hour,
Times.Minute,
Times.Second,
Times.Milliseconds);
RunTime.QuadPart = UInt32x32To64(ProcessContents->Pcb.UserTime, TimeIncrement);
RtlTimeToElapsedTimeFields ( &RunTime, &Times);
dprintf(" UserTime %3ld:%02ld:%02ld.%04ld\n",
Times.Hour,
Times.Minute,
Times.Second,
Times.Milliseconds);
RunTime.QuadPart = UInt32x32To64(ProcessContents->Pcb.KernelTime, TimeIncrement);
RtlTimeToElapsedTimeFields ( &RunTime, &Times);
dprintf(" KernelTime %3ld:%02ld:%02ld.%04ld\n",
Times.Hour,
Times.Minute,
Times.Second,
Times.Milliseconds);
dprintf(" QuotaPoolUsage[PagedPool] %ld\n",ProcessContents->QuotaPoolUsage[PagedPool] );
dprintf(" QuotaPoolUsage[NonPagedPool] %ld\n",ProcessContents->QuotaPoolUsage[NonPagedPool] );
dprintf(" Working Set Sizes (now,min,max) (%ld, %ld, %ld) (%ldKB, %ldKB, %ldKB)\n",
ProcessContents->Vm.WorkingSetSize,
ProcessContents->Vm.MinimumWorkingSetSize,
ProcessContents->Vm.MaximumWorkingSetSize,
_KB*ProcessContents->Vm.WorkingSetSize,
_KB*ProcessContents->Vm.MinimumWorkingSetSize,
_KB*ProcessContents->Vm.MaximumWorkingSetSize
);
dprintf(" PeakWorkingSetSize %ld\n",ProcessContents->Vm.PeakWorkingSetSize );
dprintf(" VirtualSize %ld Mb\n",ProcessContents->VirtualSize /(1024*1024) );
dprintf(" PeakVirtualSize %ld Mb\n",ProcessContents->PeakVirtualSize/(1024*1024) );
dprintf(" PageFaultCount %ld\n",ProcessContents->Vm.PageFaultCount );
dprintf(" MemoryPriority %s\n",ProcessContents->Vm.MemoryPriority ? "FOREGROUND" : "BACKGROUND" );
dprintf(" BasePriority %ld\n",ProcessContents->Pcb.BasePriority);
dprintf(" CommitCharge %ld\n",ProcessContents->CommitCharge );
dprintf("\n");
return TRUE;
}
UCHAR *WaitReasonList[] = {
"Executive",
"FreePage",
"PageIn",
"PoolAllocation",
"DelayExecution",
"Suspended",
"UserRequest",
"WrExecutive",
"WrFreePage",
"WrPageIn",
"WrPoolAllocation",
"WrDelayExecution",
"WrSuspended",
"WrUserRequest",
"WrEventPairHigh",
"WrEventPairLow",
"WrLpcReceive",
"WrLpcReply",
"WrVirtualMemory",
"WrPageOut",
"Spare1",
"Spare2",
"Spare3",
"Spare4",
"Spare5",
"Spare6",
"Spare7"};
BOOL
DumpThread (
IN ULONG Processor,
IN char *Pad,
IN PETHREAD Thread,
IN PETHREAD RealThreadBase,
IN ULONG Flags
)
{
#define MAX_STACK_FRAMES 40
TIME_FIELDS Times;
LARGE_INTEGER RunTime;
ULONG Address;
ULONG Result;
KMUTANT WaitObject;
PVOID PointerWaitObject = &WaitObject;
PKWAIT_BLOCK WaitBlock;
KWAIT_BLOCK OutsideBlock;
ULONG WaitOffset;
PEPROCESS Process;
CHAR Buffer[80];
ULONG KeTimeIncrement;
ULONG TimeIncrement;
ULONG frames = 0;
ULONG i;
ULONG displacement;
EXTSTACKTRACE stk[MAX_STACK_FRAMES];
#ifdef TARGET_i386
struct {
KSWITCHFRAME Frame;
DWORD SavedEbp;
} SwitchFrame;
#endif
if (Thread->Tcb.Header.Type != ThreadObject) {
dprintf("TYPE mismatch for thread object at %lx\n",RealThreadBase);
return FALSE;
}
dprintf("%sTHREAD %lx Cid %lx.%lx Teb: %08x Win32Thread: %08x ",
Pad,
RealThreadBase,
Thread->Cid.UniqueProcess,
Thread->Cid.UniqueThread,
Thread->Tcb.Teb,
Thread->Tcb.Win32Thread
);
switch (Thread->Tcb.State) {
case Initialized:
dprintf("%s\n","INITIALIZED");break;
case Ready:
dprintf("%s\n","READY");break;
case Running:
dprintf("%s\n","RUNNING");break;
case Standby:
dprintf("%s\n","STANDBY");break;
case Terminated:
dprintf("%s\n","TERMINATED");break;
case Waiting:
dprintf("%s","WAIT:");break;
case Transition:
dprintf("%s","TRANSITION");break;
}
if (!(Flags & 2)) {
dprintf("\n");
return TRUE;
}
if (Thread->Tcb.State == Waiting) {
dprintf(" (%s) %s %s\n",
WaitReasonList[Thread->Tcb.WaitReason],
(Thread->Tcb.WaitMode==KernelMode) ? "KernelMode" : "UserMode",Thread->Tcb.Alertable ? "Alertable" : "Non-Alertable");
if ( Thread->Tcb.SuspendCount ) {
dprintf("SuspendCount %lx\n",Thread->Tcb.SuspendCount);
}
if ( Thread->Tcb.FreezeCount ) {
dprintf("FreezeCount %lx\n",Thread->Tcb.FreezeCount);
}
WaitOffset =
(ULONG)Thread->Tcb.WaitBlockList - (ULONG)RealThreadBase;
if (WaitOffset > (ULONG)sizeof(ETHREAD)) {
if (!ReadMemory((DWORD)Thread->Tcb.WaitBlockList,
&OutsideBlock,
sizeof(KWAIT_BLOCK),
&Result)) {
dprintf("%sunable to get Wait object\n",Pad);
goto BadWaitBlock;
}
WaitBlock = &OutsideBlock;
} else {
WaitBlock = (PKWAIT_BLOCK)((ULONG)Thread + WaitOffset);
}
do {
dprintf("%s %lx ",Pad,WaitBlock->Object);
if (!ReadMemory((DWORD)WaitBlock->Object,
&WaitObject,
sizeof(KMUTANT),
&Result)) {
dprintf("%sunable to get Wait object\n",Pad);
break;
}
switch (WaitObject.Header.Type) {
case EventNotificationObject:
dprintf("NotificationEvent\n");
break;
case EventSynchronizationObject:
dprintf("SynchronizationEvent\n");
break;
case SemaphoreObject:
dprintf("Semaphore Limit 0x%lx\n",
((PKSEMAPHORE)PointerWaitObject)->Limit);
break;
case ThreadObject:
dprintf("Thread\n");
break;
case TimerNotificationObject:
dprintf("NotificationTimer\n");
break;
case TimerSynchronizationObject:
dprintf("SynchronizationTimer\n");
break;
case EventPairObject:
dprintf("EventPair\n");
break;
case ProcessObject:
dprintf("ProcessObject\n");
break;
case MutantObject:
dprintf("Mutant - owning thread %lx\n",
((PKMUTANT)PointerWaitObject)->OwnerThread);
break;
default:
dprintf("Unknown\n");
break;
}
if (WaitBlock->NextWaitBlock == Thread->Tcb.WaitBlockList) {
break;
}
WaitOffset =
(ULONG)WaitBlock->NextWaitBlock - (ULONG)RealThreadBase;
if (WaitOffset > (ULONG)sizeof(ETHREAD)) {
if (!ReadMemory((DWORD)WaitBlock->NextWaitBlock,
&OutsideBlock,
sizeof(KWAIT_BLOCK),
&Result)) {
dprintf("%sunable to get Wait object\n",Pad);
break;
}
WaitBlock = &OutsideBlock;
} else {
WaitBlock = (PKWAIT_BLOCK)((ULONG)Thread + WaitOffset);
}
} while ( TRUE );
}
BadWaitBlock:
if (!(Flags & 4)) {
dprintf("\n");
return TRUE;
}
if (Thread->LpcReplyMessageId != 0) {
dprintf("%sWaiting for reply to LPC MessageId %08x:\n",Pad,Thread->LpcReplyMessageId);
}
if (Thread->LpcReplyMessage != NULL) {
LPCP_MESSAGE MsgContents, *p;
dprintf("%sPending LPC Reply Message:\n",Pad);
Address = (ULONG)Thread->LpcReplyMessage;
if (!ReadMemory((DWORD)Address,
&MsgContents,
sizeof(MsgContents),
&Result)) {
dprintf("unable to get LPC msg\n");
} else {
p = &MsgContents;
dprintf("%s %08lx: [%08lx,%08lx]\n",
Pad, Address, p->Entry.Blink, p->Entry.Flink
);
}
}
if (Thread->IrpList.Flink != Thread->IrpList.Blink ||
Thread->IrpList.Flink != &RealThreadBase->IrpList
) {
ULONG IrpListHead = (ULONG)&RealThreadBase->IrpList;
PLIST_ENTRY Next;
IRP IrpContents;
PIRP p;
ULONG Counter = 0;
Next = Thread->IrpList.Flink;
dprintf("%sIRP List:\n",Pad);
while (((ULONG)Next != IrpListHead) && (Counter < 17)) {
Counter += 1;
Address = (ULONG)CONTAINING_RECORD(Next,IRP,ThreadListEntry);
if (!ReadMemory((DWORD)Address,
&IrpContents,
sizeof(IRP),
&Result)) {
dprintf( "%sunable to get IRP object\n", Pad );
break;
}
p = &IrpContents;
dprintf("%s %08lx: (%04x,%04x) Flags: %08lx Mdl: %08lx\n",
Pad,Address,p->Type,p->Size,p->Flags,p->MdlAddress);
Next = p->ThreadListEntry.Flink;
}
}
//
// Impersonation information
//
if (Thread->ActiveImpersonationInfo) {
dprintf("%sImpersonation token: %lx\n", Pad, Thread->ImpersonationInfo);
} else {
dprintf("%sNot impersonating\n", Pad);
}
Process = CONTAINING_RECORD(Thread->Tcb.ApcState.Process,EPROCESS,Pcb);
dprintf("%sOwning Process %lx\n", Pad, Process);
GetTheSystemTime (&RunTime);
dprintf("%sWaitTime (seconds) %ld\n",
Pad,
Thread->Tcb.WaitTime);
dprintf("%sContext Switch Count %ld",
Pad,
Thread->Tcb.ContextSwitches);
if (!Thread->Tcb.EnableStackSwap) {
dprintf(" NoStackSwap");
} else {
dprintf(" ");
}
if (Thread->Tcb.LargeStack) {
dprintf(" LargeStack");
}
dprintf ("\n");
//
// Get the time increment value which is used to compute runtime.
//
KeTimeIncrement = GetExpression( "KeTimeIncrement" );
if (KeTimeIncrement) {
ReadMemory( KeTimeIncrement, &TimeIncrement, sizeof(ULONG), &Result );
}
RunTime.QuadPart = UInt32x32To64(Thread->Tcb.UserTime, TimeIncrement);
RtlTimeToElapsedTimeFields ( &RunTime, &Times);
dprintf("%sUserTime %3ld:%02ld:%02ld.%04ld\n",
Pad,
Times.Hour,
Times.Minute,
Times.Second,
Times.Milliseconds);
RunTime.QuadPart = UInt32x32To64(Thread->Tcb.KernelTime, TimeIncrement);
RtlTimeToElapsedTimeFields ( &RunTime, &Times);
dprintf("%sKernelTime %3ld:%02ld:%02ld.%04ld\n",
Pad,
Times.Hour,
Times.Minute,
Times.Second,
Times.Milliseconds);
if (Thread->PerformanceCountHigh != 0) {
dprintf("%sPerfCounterHigh 0x%lx %08lx\n",
Pad,
Thread->PerformanceCountHigh,
Thread->PerformanceCountHigh);
} else if (Thread->PerformanceCountLow != 0) {
dprintf("%sPerfCounter %lu\n",Pad,Thread->PerformanceCountLow);
}
dumpSymbolicAddress((ULONG)Thread->StartAddress, Buffer, TRUE);
dprintf("%sStart Address %s\n",
Pad,
Buffer
);
if (Thread->Win32StartAddress)
if (Thread->LpcReceivedMsgIdValid)
{
dprintf("%sLPC Server thread working on message Id %x\n",
Pad,
Thread->LpcReceivedMessageId
);
}
else
{
dumpSymbolicAddress((ULONG)Thread->Win32StartAddress, Buffer, TRUE);
dprintf("%sWin32 Start Address %s\n",
Pad,
Buffer
);
}
dprintf("%sStack Init %lx Current %lx Base %lx Limit %lx Call %lx\n",
Pad,
Thread->Tcb.InitialStack,
Thread->Tcb.KernelStack,
Thread->Tcb.StackBase,
Thread->Tcb.StackLimit,
Thread->Tcb.CallbackStack
);
dprintf("%sPriority %ld BasePriority %ld PriorityDecrement %ld DecrementCount %ld\n",
Pad,
Thread->Tcb.Priority,
Thread->Tcb.BasePriority,
Thread->Tcb.PriorityDecrement,
Thread->Tcb.DecrementCount
);
if (!Thread->Tcb.KernelStackResident) {
dprintf("Kernel stack not resident.\n");
}
#ifdef TARGET_i386
if (Thread->Tcb.State == Running) {
GetStackTraceRegs( Thread->Tcb.NextProcessor, &STeip, &STebp, &STesp );
SetThreadForOperation( (PULONG)&RealThreadBase );
frames = StackTrace( STebp, STesp, STeip, stk, MAX_STACK_FRAMES );
} else {
//
// Get SwitchFrame and perform backtrace providing EBP,ESP,EIP
// (full FPO backtrace context)
//
// N.B. The dword immediately preceding the switch frame contains
// the saved EBP.
//
ZeroMemory( &SwitchFrame, sizeof(SwitchFrame) );
ReadMemory(
(DWORD)Thread->Tcb.KernelStack,
(PVOID)&SwitchFrame,
sizeof(SwitchFrame),
&Result
);
if (Result == sizeof(SwitchFrame)) {
STeip = SwitchFrame.Frame.RetAddr;
STebp = SwitchFrame.SavedEbp;
STesp = (ULONG) Thread->Tcb.KernelStack + sizeof(KSWITCHFRAME);
SetThreadForOperation( (PULONG)&RealThreadBase );
frames = StackTrace( STebp, STesp, STeip, stk, MAX_STACK_FRAMES );
}
}
#elif defined(TARGET_MIPS) || defined(TARGET_ALPHA) || defined(TARGET_PPC)
if (Thread->Tcb.State != Running) {
SetThreadForOperation( (PULONG)&RealThreadBase );
frames = StackTrace( (DWORD)Thread->Tcb.KernelStack,
(DWORD)Thread->Tcb.KernelStack,
0,
stk,
MAX_STACK_FRAMES
);
}
#endif
for (i=0; i<frames; i++) {
if (i==0) {
#ifdef TARGET_PPC
dprintf( "\n%sChildEBP RetAddr\n", Pad );
#else
dprintf( "\n%sChildEBP RetAddr Args to Child\n", Pad );
#endif
}
Buffer[0] = '!';
GetSymbol((LPVOID)stk[i].ProgramCounter, Buffer, &displacement);
#ifdef TARGET_PPC
dprintf( "%s%08x %08x %s",
Pad,
stk[i].FramePointer,
stk[i].ReturnAddress,
Buffer
);
#else
dprintf( "%s%08x %08x %08x %08x %08x %s",
Pad,
stk[i].FramePointer,
stk[i].ReturnAddress,
stk[i].Args[0],
stk[i].Args[1],
stk[i].Args[2],
Buffer
);
#endif
if (displacement) {
dprintf( "+0x%x", displacement );
}
dprintf( "\n" );
}
dprintf("\n");
return TRUE;
}
DECLARE_API( processfields )
/*++
Routine Description:
Displays the field offsets for EPROCESS type.
Arguments:
None.
Return Value:
None.
--*/
{
dprintf(" EPROCESS structure offsets:\n\n");
dprintf(" Pcb: 0x%lx\n", FIELD_OFFSET(EPROCESS, Pcb) );
dprintf(" ExitStatus: 0x%lx\n", FIELD_OFFSET(EPROCESS, ExitStatus) );
dprintf(" LockEvent: 0x%lx\n", FIELD_OFFSET(EPROCESS, LockEvent) );
dprintf(" LockCount: 0x%lx\n", FIELD_OFFSET(EPROCESS, LockCount) );
dprintf(" CreateTime: 0x%lx\n", FIELD_OFFSET(EPROCESS, CreateTime) );
dprintf(" ExitTime: 0x%lx\n", FIELD_OFFSET(EPROCESS, ExitTime) );
dprintf(" LockOwner: 0x%lx\n", FIELD_OFFSET(EPROCESS, LockOwner) );
dprintf(" UniqueProcessId: 0x%lx\n", FIELD_OFFSET(EPROCESS, UniqueProcessId) );
dprintf(" ActiveProcessLinks: 0x%lx\n", FIELD_OFFSET(EPROCESS, ActiveProcessLinks) );
dprintf(" QuotaPeakPoolUsage[0]: 0x%lx\n", FIELD_OFFSET(EPROCESS, QuotaPeakPoolUsage) );
dprintf(" QuotaPoolUsage[0]: 0x%lx\n", FIELD_OFFSET(EPROCESS, QuotaPoolUsage) );
dprintf(" PagefileUsage: 0x%lx\n", FIELD_OFFSET(EPROCESS, PagefileUsage) );
dprintf(" CommitCharge: 0x%lx\n", FIELD_OFFSET(EPROCESS, CommitCharge) );
dprintf(" PeakPagefileUsage: 0x%lx\n", FIELD_OFFSET(EPROCESS, PeakPagefileUsage) );
dprintf(" PeakVirtualSize: 0x%lx\n", FIELD_OFFSET(EPROCESS, PeakVirtualSize) );
dprintf(" VirtualSize: 0x%lx\n", FIELD_OFFSET(EPROCESS, VirtualSize) );
dprintf(" Vm: 0x%lx\n", FIELD_OFFSET(EPROCESS, Vm) );
dprintf(" LastProtoPteFault: 0x%lx\n", FIELD_OFFSET(EPROCESS, LastProtoPteFault) );
dprintf(" DebugPort: 0x%lx\n", FIELD_OFFSET(EPROCESS, DebugPort) );
dprintf(" ExceptionPort: 0x%lx\n", FIELD_OFFSET(EPROCESS, ExceptionPort) );
dprintf(" ObjectTable: 0x%lx\n", FIELD_OFFSET(EPROCESS, ObjectTable) );
dprintf(" Token: 0x%lx\n", FIELD_OFFSET(EPROCESS, Token) );
dprintf(" WorkingSetLock: 0x%lx\n", FIELD_OFFSET(EPROCESS, WorkingSetLock) );
dprintf(" WorkingSetPage: 0x%lx\n", FIELD_OFFSET(EPROCESS, WorkingSetPage) );
dprintf(" ProcessOutswapEnabled: 0x%lx\n", FIELD_OFFSET(EPROCESS, ProcessOutswapEnabled) );
dprintf(" ProcessOutswapped: 0x%lx\n", FIELD_OFFSET(EPROCESS, ProcessOutswapped) );
dprintf(" AddressSpaceInitialized: 0x%lx\n", FIELD_OFFSET(EPROCESS, AddressSpaceInitialized) );
dprintf(" AddressSpaceDeleted: 0x%lx\n", FIELD_OFFSET(EPROCESS, AddressSpaceDeleted) );
dprintf(" AddressCreationLock: 0x%lx\n", FIELD_OFFSET(EPROCESS, AddressCreationLock) );
dprintf(" ForkInProgress: 0x%lx\n", FIELD_OFFSET(EPROCESS, ForkInProgress) );
dprintf(" VmOperation: 0x%lx\n", FIELD_OFFSET(EPROCESS, VmOperation) );
dprintf(" VmOperationEvent: 0x%lx\n", FIELD_OFFSET(EPROCESS, VmOperationEvent) );
dprintf(" PageDirectoryPte: 0x%lx\n", FIELD_OFFSET(EPROCESS, PageDirectoryPte) );
dprintf(" LastFaultCount: 0x%lx\n", FIELD_OFFSET(EPROCESS, LastFaultCount) );
dprintf(" VadRoot: 0x%lx\n", FIELD_OFFSET(EPROCESS, VadRoot) );
dprintf(" VadHint: 0x%lx\n", FIELD_OFFSET(EPROCESS, VadHint) );
dprintf(" CloneRoot: 0x%lx\n", FIELD_OFFSET(EPROCESS, CloneRoot) );
dprintf(" NumberOfPrivatePages: 0x%lx\n", FIELD_OFFSET(EPROCESS, NumberOfPrivatePages) );
dprintf(" NumberOfLockedPages: 0x%lx\n", FIELD_OFFSET(EPROCESS, NumberOfLockedPages) );
dprintf(" ForkWasSuccessful: 0x%lx\n", FIELD_OFFSET(EPROCESS, ForkWasSuccessful) );
dprintf(" ExitProcessCalled: 0x%lx\n", FIELD_OFFSET(EPROCESS, ExitProcessCalled) );
dprintf(" CreateProcessReported: 0x%lx\n", FIELD_OFFSET(EPROCESS, CreateProcessReported) );
dprintf(" SectionHandle: 0x%lx\n", FIELD_OFFSET(EPROCESS, SectionHandle) );
dprintf(" Peb: 0x%lx\n", FIELD_OFFSET(EPROCESS, Peb) );
dprintf(" SectionBaseAddress: 0x%lx\n", FIELD_OFFSET(EPROCESS, SectionBaseAddress) );
dprintf(" QuotaBlock: 0x%lx\n", FIELD_OFFSET(EPROCESS, QuotaBlock) );
dprintf(" LastThreadExitStatus: 0x%lx\n", FIELD_OFFSET(EPROCESS, LastThreadExitStatus) );
dprintf(" WorkingSetWatch: 0x%lx\n", FIELD_OFFSET(EPROCESS, WorkingSetWatch) );
dprintf(" InheritedFromUniqueProcessId: 0x%lx\n", FIELD_OFFSET(EPROCESS, InheritedFromUniqueProcessId) );
dprintf(" GrantedAccess: 0x%lx\n", FIELD_OFFSET(EPROCESS, GrantedAccess) );
dprintf(" DefaultHardErrorProcessing 0x%lx\n", FIELD_OFFSET(EPROCESS, DefaultHardErrorProcessing) );
dprintf(" LdtInformation: 0x%lx\n", FIELD_OFFSET(EPROCESS, LdtInformation) );
dprintf(" VadFreeHint: 0x%lx\n", FIELD_OFFSET(EPROCESS, VadFreeHint) );
dprintf(" VdmObjects: 0x%lx\n", FIELD_OFFSET(EPROCESS, VdmObjects) );
dprintf(" ProcessMutant: 0x%lx\n", FIELD_OFFSET(EPROCESS, ProcessMutant) );
dprintf(" ImageFileName[0]: 0x%lx\n", FIELD_OFFSET(EPROCESS, ImageFileName) );
dprintf(" VmTrimFaultValue: 0x%lx\n", FIELD_OFFSET(EPROCESS, VmTrimFaultValue) );
dprintf(" Win32Process: 0x%lx\n", FIELD_OFFSET(EPROCESS, Win32Process) );
dprintf(" Win32WindowStation: 0x%lx\n", FIELD_OFFSET(EPROCESS, Win32WindowStation) );
return;
}
DECLARE_API( threadfields )
/*++
Routine Description:
Displays the field offsets for ETHREAD type.
Arguments:
None.
Return Value:
None.
--*/
{
dprintf(" ETHREAD structure offsets:\n\n");
dprintf(" Tcb: 0x%lx\n", FIELD_OFFSET(ETHREAD, Tcb) );
dprintf(" CreateTime: 0x%lx\n", FIELD_OFFSET(ETHREAD, CreateTime) );
dprintf(" ExitTime: 0x%lx\n", FIELD_OFFSET(ETHREAD, ExitTime) );
dprintf(" ExitStatus: 0x%lx\n", FIELD_OFFSET(ETHREAD, ExitStatus) );
dprintf(" PostBlockList: 0x%lx\n", FIELD_OFFSET(ETHREAD, PostBlockList) );
dprintf(" TerminationPortList: 0x%lx\n", FIELD_OFFSET(ETHREAD, TerminationPortList) );
dprintf(" ActiveTimerListLock: 0x%lx\n", FIELD_OFFSET(ETHREAD, ActiveTimerListLock) );
dprintf(" ActiveTimerListHead: 0x%lx\n", FIELD_OFFSET(ETHREAD, ActiveTimerListHead) );
dprintf(" Cid: 0x%lx\n", FIELD_OFFSET(ETHREAD, Cid) );
dprintf(" LpcReplySemaphore: 0x%lx\n", FIELD_OFFSET(ETHREAD, LpcReplySemaphore) );
dprintf(" LpcReplyMessage: 0x%lx\n", FIELD_OFFSET(ETHREAD, LpcReplyMessage) );
dprintf(" LpcReplyMessageId: 0x%lx\n", FIELD_OFFSET(ETHREAD, LpcReplyMessageId) );
dprintf(" ImpersonationInfo: 0x%lx\n", FIELD_OFFSET(ETHREAD, ImpersonationInfo) );
dprintf(" IrpList: 0x%lx\n", FIELD_OFFSET(ETHREAD, IrpList) );
dprintf(" TopLevelIrp: 0x%lx\n", FIELD_OFFSET(ETHREAD, TopLevelIrp) );
dprintf(" ReadClusterSize: 0x%lx\n", FIELD_OFFSET(ETHREAD, ReadClusterSize) );
dprintf(" ForwardClusterOnly: 0x%lx\n", FIELD_OFFSET(ETHREAD, ForwardClusterOnly) );
dprintf(" DisablePageFaultClustering: 0x%lx\n", FIELD_OFFSET(ETHREAD, DisablePageFaultClustering) );
dprintf(" DeadThread: 0x%lx\n", FIELD_OFFSET(ETHREAD, DeadThread) );
dprintf(" HasTerminated: 0x%lx\n", FIELD_OFFSET(ETHREAD, HasTerminated) );
dprintf(" EventPair: 0x%lx\n", FIELD_OFFSET(ETHREAD, EventPair) );
dprintf(" GrantedAccess: 0x%lx\n", FIELD_OFFSET(ETHREAD, GrantedAccess) );
dprintf(" ThreadsProcess: 0x%lx\n", FIELD_OFFSET(ETHREAD, ThreadsProcess) );
dprintf(" StartAddress: 0x%lx\n", FIELD_OFFSET(ETHREAD, StartAddress) );
dprintf(" Win32StartAddress: 0x%lx\n", FIELD_OFFSET(ETHREAD, Win32StartAddress) );
dprintf(" LpcExitThreadCalled: 0x%lx\n", FIELD_OFFSET(ETHREAD, LpcExitThreadCalled) );
dprintf(" HardErrorsAreDisabled: 0x%lx\n", FIELD_OFFSET(ETHREAD, HardErrorsAreDisabled) );
return;
}
PVOID
GetCurrentProcessAddress(
DWORD Processor,
HANDLE hCurrentThread,
PETHREAD CurrentThread
)
{
ULONG Result;
ETHREAD Thread;
if (CurrentThread == NULL) {
CurrentThread = (PETHREAD)GetCurrentThreadAddress( (USHORT)Processor, hCurrentThread );
if (CurrentThread == NULL) {
return NULL;
}
}
if (!ReadMemory((DWORD)CurrentThread, &Thread, sizeof(Thread), &Result)) {
return NULL;
}
return CONTAINING_RECORD(Thread.Tcb.ApcState.Process,EPROCESS,Pcb);
}
PVOID
GetCurrentThreadAddress(
USHORT Processor,
HANDLE hCurrentThread
)
{
ULONG Address;
#ifdef TARGET_ALPHA
ReadControlSpace( (USHORT)Processor,
DEBUG_CONTROL_SPACE_THREAD,
(PVOID)&Address,
sizeof(PKTHREAD)
);
return CONTAINING_RECORD(Address, ETHREAD, Tcb);
#elif defined(TARGET_MIPS)
KPRCB Prcb;
if (!ReadPcr(Processor, &Prcb, &Address, hCurrentThread)) {
dprintf("Unable to read PCR for Processor %u\n",Processor);
return NULL;
}
return CONTAINING_RECORD(Prcb.CurrentThread,ETHREAD,Tcb);
#elif defined(TARGET_PPC)
KPCR Pcr;
PKPCR pp;
KPRCB Prcb;
ULONG Result;
Processor = 0;
pp = &Pcr;
if (!ReadPcr(Processor, pp, &Address, hCurrentThread)) {
dprintf("Unable to read PCR for Processor %u\n",Processor);
return NULL;
}
//
// Address -> base of the pcr, read the PCR in.
//
if (!ReadMemory((DWORD)pp->Prcb, &Prcb, sizeof(KPRCB), &Result)) {
return NULL;
}
return CONTAINING_RECORD(Prcb.CurrentThread,ETHREAD,Tcb);
#elif defined(TARGET_i386)
KPCR Pcr;
PKPCR pp;
pp = &Pcr;
if (!ReadPcr(Processor, pp, &Address, hCurrentThread)) {
dprintf("Unable to read PCR for Processor %u\n",Processor);
return NULL;
}
return CONTAINING_RECORD(pp->PrcbData.CurrentThread,ETHREAD,Tcb);
#else
#error( "unknown processor type" )
#endif
}
#if defined(TARGET_i386)
#define SYSTEM_TIME_ADDRESS KI_USER_SHARED_DATA
#elif defined(TARGET_MIPS)
#define SYSTEM_TIME_ADDRESS KIPCR2
#elif defined(TARGET_ALPHA)
#define SYSTEM_TIME_ADDRESS KI_USER_SHARED_DATA
#elif defined(TARGET_PPC)
#define SYSTEM_TIME_ADDRESS KI_USER_SHARED_DATA
#else
#error( "unknown target machine" );
#endif
BOOLEAN
GetTheSystemTime (
OUT PLARGE_INTEGER Time
)
{
KUSER_SHARED_DATA sud;
ULONG Result;
ZeroMemory( Time, sizeof(*Time) );
if (!ReadMemory(SYSTEM_TIME_ADDRESS,
&sud,
sizeof(KUSER_SHARED_DATA),
&Result)) {
dprintf( "unable to read memory @ SharedUserData\n");
return FALSE;
}
*Time = *(LARGE_INTEGER UNALIGNED *)&sud.SystemTime;
return TRUE;
}
VOID
dumpSymbolicAddress(
ULONG Address,
PUCHAR Buffer,
BOOL AlwaysShowHex
)
{
ULONG displacement;
PUCHAR s;
Buffer[0] = '!';
GetSymbol((LPVOID)Address, Buffer, &displacement);
s = Buffer + strlen( Buffer );
if (s == Buffer) {
sprintf( s, "0x%08x", Address );
}
else {
if (displacement != 0) {
sprintf( s, "+0x%x", displacement );
}
if (AlwaysShowHex) {
sprintf( s, " (0x%08x)", Address );
}
}
return;
}
BOOLEAN
FetchProcessStructureVariables(
VOID
)
{
ULONG Result;
static BOOLEAN HavePspVariables = FALSE;
if (HavePspVariables) {
return TRUE;
}
PspCidTable = (PHANDLE_TABLE)GetExpression( "PspCidTable" );
if ( !PspCidTable ||
!ReadMemory((DWORD)PspCidTable,
&PspCidTable,
sizeof(PspCidTable),
&Result) ) {
dprintf("%08lx: Unable to get value of PspCidTable\n",PspCidTable);
return FALSE;
}
HavePspVariables = TRUE;
return TRUE;
}
PVOID
LookupUniqueId(
HANDLE UniqueId
)
{
HANDLE_ENTRY Entry;
static BOOLEAN HavePspCidTable = FALSE;
ULONG Result;
PHANDLE_ENTRY TableBound;
PHANDLE_ENTRY TableEntries;
ULONG TableIndex;
if (!HavePspCidTable) {
if (!ReadMemory((DWORD)PspCidTable,
&CapturedPspCidTable,
sizeof(HANDLE_TABLE),
&Result)) {
return NULL;
}
HavePspCidTable = TRUE;
}
TableBound = CapturedPspCidTable.TableBound;
TableEntries = CapturedPspCidTable.TableEntries;
TableIndex = (ULONG)UniqueId;
if (TableIndex < (ULONG)(TableBound - TableEntries)) {
if (!ReadMemory((DWORD)(&TableEntries[TableIndex]),
&Entry,
sizeof(HANDLE_ENTRY),
&Result)) {
Entry.Object = NULL;
} else if (ExIsEntryFree(TableEntries, TableBound, &Entry)) {
Entry.Object = NULL;
}
} else {
Entry.Object = NULL;
}
return Entry.Object;
}
int
__cdecl
CmpFunc(
const void *pszElem1,
const void *pszElem2
)
{
PPROCESS_COMMIT_USAGE p1, p2;
p1 = (PPROCESS_COMMIT_USAGE)pszElem1;
p2 = (PPROCESS_COMMIT_USAGE)pszElem2;
return p2->CommitCharge - p1->CommitCharge;
}
PPROCESS_COMMIT_USAGE
GetProcessCommit (
PULONG TotalCommitCharge,
PULONG NumberOfProcesses
)
{
PPROCESS_COMMIT_USAGE p;
ULONG n;
LIST_ENTRY List;
PLIST_ENTRY Next;
ULONG ProcessHead;
PEPROCESS Process;
EPROCESS ProcessContents;
ULONG Total;
ULONG Result;
Total = 0;
n = 0;
p = HeapAlloc( GetProcessHeap(), 0, 1 );
ProcessHead = GetExpression( "PsActiveProcessHead" );
if (!ProcessHead) {
dprintf("Unable to get value of PsActiveProcessHead\n");
return 0;
}
if (!ReadMemory( ProcessHead, &List, sizeof(LIST_ENTRY), &Result )) {
dprintf("Unable to get value of PsActiveProcessHead\n");
return 0;
}
Next = List.Flink;
while((ULONG)Next != ProcessHead) {
Process = CONTAINING_RECORD(Next,EPROCESS,ActiveProcessLinks);
if (!ReadMemory( (DWORD)Process, &ProcessContents, sizeof(EPROCESS), &Result )) {
dprintf("Unable to read _EPROCESS at %lx\n",Process);
return 0;
}
Total += ProcessContents.CommitCharge;
n += 1;
p = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, p, n * sizeof( *p ) );
if (p != NULL) {
strcpy( p[ n-1 ].ImageFileName, ProcessContents.ImageFileName );
p[ n-1 ].CommitCharge = ProcessContents.CommitCharge;
p[ n-1 ].NumberOfPrivatePages = ProcessContents.NumberOfPrivatePages;
p[ n-1 ].NumberOfLockedPages = ProcessContents.NumberOfLockedPages;
}
Next = ProcessContents.ActiveProcessLinks.Flink;
if (CheckControlC()) {
return 0;
}
}
qsort( p, n, sizeof( *p ), CmpFunc );
*TotalCommitCharge = Total;
*NumberOfProcesses = n;
return p;
}