/*++
Copyright 1995 - 1998 Microsoft Corporation
Module Name:
process.c
Abstract:
This module maintains state about each process/thread created by the application
pfmon program.
Author:
Mark Lucovsky (markl) 26-Jan-1995
Revision History:
--*/
#include "pfmonp.h"
BOOL
AddProcess(
LPDEBUG_EVENT DebugEvent,
PPROCESS_INFO *ReturnedProcess
)
{
PPROCESS_INFO Process;
Process = LocalAlloc(LMEM_ZEROINIT, sizeof( *Process ) );
if (Process == NULL) {
return FALSE;
}
Process->Id = DebugEvent->dwProcessId;
Process->Handle = DebugEvent->u.CreateProcessInfo.hProcess;
InitializeListHead( &Process->ThreadListHead );
InsertTailList( &ProcessListHead, &Process->Entry );
*ReturnedProcess = Process;
return TRUE;
}
BOOL
DeleteProcess(
PPROCESS_INFO Process
)
{
PLIST_ENTRY Next, Head;
PTHREAD_INFO Thread;
PMODULE_INFO Module;
CHAR Line[256];
RemoveEntryList( &Process->Entry );
Head = &Process->ThreadListHead;
Next = Head->Flink;
while (Next != Head) {
Thread = CONTAINING_RECORD( Next, THREAD_INFO, Entry );
Next = Next->Flink;
DeleteThread( Process, Thread );
}
LocalFree( Process );
fprintf(stdout,"\n");
Next = ModuleListHead.Flink;
while ( Next != &ModuleListHead ) {
Module = CONTAINING_RECORD(Next,MODULE_INFO,Entry);
sprintf(Line,"%16s Caused %6d faults had %6d Soft %6d Hard faulted VA's\n",
Module->DebugInfo->ImageFileName,
Module->NumberCausedFaults,
Module->NumberFaultedSoftVas,
Module->NumberFaultedHardVas
);
if ( !fLogOnly ) {
fprintf(stdout,"%s",Line);
}
if ( LogFile ) {
fprintf(LogFile,"%s",Line);
}
Next = Next->Flink;
}
return TRUE;
}
BOOL
AddThread(
LPDEBUG_EVENT DebugEvent,
PPROCESS_INFO Process,
PTHREAD_INFO *ReturnedThread
)
{
PTHREAD_INFO Thread;
Thread = LocalAlloc(LMEM_ZEROINIT, sizeof( *Thread ) );
if (Thread == NULL) {
return FALSE;
}
Thread->Id = DebugEvent->dwThreadId;
if (DebugEvent->dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) {
Thread->Handle = DebugEvent->u.CreateProcessInfo.hThread;
Thread->StartAddress = DebugEvent->u.CreateProcessInfo.lpStartAddress;
}
else {
Thread->Handle = DebugEvent->u.CreateThread.hThread;
Thread->StartAddress = DebugEvent->u.CreateThread.lpStartAddress;
}
InsertTailList( &Process->ThreadListHead, &Thread->Entry );
*ReturnedThread = Thread;
return TRUE;
}
BOOL
DeleteThread(
PPROCESS_INFO Process,
PTHREAD_INFO Thread
)
{
RemoveEntryList( &Thread->Entry );
LocalFree( Thread );
return TRUE;
}
PPROCESS_INFO
FindProcessById(
ULONG Id
)
{
PLIST_ENTRY Next, Head;
PPROCESS_INFO Process;
Head = &ProcessListHead;
Next = Head->Flink;
while (Next != Head) {
Process = CONTAINING_RECORD( Next, PROCESS_INFO, Entry );
if (Process->Id == Id) {
return Process;
}
Next = Next->Flink;
}
return NULL;
}
BOOL
FindProcessAndThreadForEvent(
LPDEBUG_EVENT DebugEvent,
PPROCESS_INFO *ReturnedProcess,
PTHREAD_INFO *ReturnedThread
)
{
PLIST_ENTRY Next, Head;
PPROCESS_INFO Process;
PTHREAD_INFO Thread;
Head = &ProcessListHead;
Next = Head->Flink;
Process = NULL;
Thread = NULL;
while (Next != Head) {
Process = CONTAINING_RECORD( Next, PROCESS_INFO, Entry );
if (Process->Id == DebugEvent->dwProcessId) {
Head = &Process->ThreadListHead;
Next = Head->Flink;
while (Next != Head) {
Thread = CONTAINING_RECORD( Next, THREAD_INFO, Entry );
if (Thread->Id == DebugEvent->dwThreadId) {
break;
}
Thread = NULL;
Next = Next->Flink;
}
break;
}
Process = NULL;
Next = Next->Flink;
}
*ReturnedProcess = Process;
*ReturnedThread = Thread;
if (DebugEvent->dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) {
if (Process != NULL) {
DeclareError( PFMON_DUPLICATE_PROCESS_ID, 0, DebugEvent->dwProcessId );
return FALSE;
}
}
else
if (DebugEvent->dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT) {
if (Thread != NULL) {
DeclareError( PFMON_DUPLICATE_THREAD_ID, 0, DebugEvent->dwThreadId, DebugEvent->dwProcessId );
return FALSE;
}
if (Process == NULL) {
DeclareError( PFMON_MISSING_PROCESS_ID, 0, DebugEvent->dwProcessId );
return FALSE;
}
}
else
if (Process == NULL) {
DeclareError( PFMON_MISSING_PROCESS_ID, 0, DebugEvent->dwProcessId );
return FALSE;
}
else
if (Thread == NULL) {
DeclareError( PFMON_MISSING_THREAD_ID, 0, DebugEvent->dwThreadId, DebugEvent->dwProcessId );
return FALSE;
}
return TRUE;
}