PROCESS.C
/*++ 
 
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; 
}