Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

610 lines
15 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
process.c
Abstract:
This module maintains state about each process/thread created by the application
setup/install program.
Author:
Steve Wood (stevewo) 09-Aug-1994
Revision History:
--*/
#include "instaler.h"
BOOLEAN
AddProcess(
LPDEBUG_EVENT DebugEvent,
PPROCESS_INFO *ReturnedProcess
)
{
NTSTATUS Status;
PPROCESS_INFO Process;
RTL_USER_PROCESS_PARAMETERS ProcessParameters;
PEB Peb;
PWSTR FreeBuffer, s;
Process = AllocMem( sizeof( *Process ) );
if (Process == NULL) {
return FALSE;
}
Process->Id = DebugEvent->dwProcessId;
Process->Handle = DebugEvent->u.CreateProcessInfo.hProcess;
InitializeListHead( &Process->ThreadListHead );
InitializeListHead( &Process->BreakpointListHead );
InitializeListHead( &Process->OpenHandleListHead );
InsertTailList( &ProcessListHead, &Process->Entry );
*ReturnedProcess = Process;
Status = NtQueryInformationProcess( Process->Handle,
ProcessBasicInformation,
&Process->ProcessInformation,
sizeof( Process->ProcessInformation ),
NULL
);
FreeBuffer = NULL;
if (ReadMemory( Process,
Process->ProcessInformation.PebBaseAddress,
&Peb,
sizeof( Peb ),
"PEB"
) &&
Peb.ProcessParameters != NULL &&
ReadMemory( Process,
Peb.ProcessParameters,
&ProcessParameters,
sizeof( ProcessParameters ),
"ProcessParameters"
) &&
ProcessParameters.ImagePathName.Length != 0 &&
(FreeBuffer = AllocMem( ProcessParameters.ImagePathName.Length + sizeof( UNICODE_NULL ) )) != NULL &&
ReadMemory( Process,
ProcessParameters.Flags & RTL_USER_PROC_PARAMS_NORMALIZED ?
ProcessParameters.ImagePathName.Buffer :
(PWSTR)((ULONG)(ProcessParameters.ImagePathName.Buffer) + (PCHAR)(Peb.ProcessParameters)),
FreeBuffer,
ProcessParameters.ImagePathName.Length,
"Image File Name"
)
) {
s = (PWSTR)((PCHAR)FreeBuffer + ProcessParameters.ImagePathName.Length);
while (s > FreeBuffer && s[ -1 ] != OBJ_NAME_PATH_SEPARATOR) {
s--;
}
wcsncpy( Process->ImageFileName,
s,
(sizeof( Process->ImageFileName ) - sizeof( UNICODE_NULL )) / sizeof( WCHAR )
);
}
FreeMem( &FreeBuffer );
return TRUE;
}
BOOLEAN
DeleteProcess(
PPROCESS_INFO Process
)
{
PLIST_ENTRY Next, Head;
PTHREAD_INFO Thread;
PBREAKPOINT_INFO Breakpoint;
POPENHANDLE_INFO p;
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 );
}
Head = &Process->BreakpointListHead;
Next = Head->Flink;
while (Next != Head) {
Breakpoint = CONTAINING_RECORD( Next, BREAKPOINT_INFO, Entry );
Next = Next->Flink;
DestroyBreakpoint( Breakpoint->Address, Process, NULL );
}
Head = &Process->OpenHandleListHead;
Next = Head->Flink;
while (Next != Head) {
p = CONTAINING_RECORD( Next, OPENHANDLE_INFO, Entry );
Next = Next->Flink;
DeleteOpenHandle( Process, p->Handle, p->Type );
}
FreeMem( &Process );
return TRUE;
}
BOOLEAN
AddThread(
LPDEBUG_EVENT DebugEvent,
PPROCESS_INFO Process,
PTHREAD_INFO *ReturnedThread
)
{
PTHREAD_INFO Thread;
Thread = AllocMem( 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;
}
Thread->SingleStepExpected = FALSE;
InitializeListHead( &Thread->BreakpointListHead );
InsertTailList( &Process->ThreadListHead, &Thread->Entry );
*ReturnedThread = Thread;
return TRUE;
}
BOOLEAN
DeleteThread(
PPROCESS_INFO Process,
PTHREAD_INFO Thread
)
{
PLIST_ENTRY Next, Head;
PBREAKPOINT_INFO Breakpoint;
RemoveEntryList( &Thread->Entry );
Head = &Thread->BreakpointListHead;
Next = Head->Flink;
while (Next != Head) {
Breakpoint = CONTAINING_RECORD( Next, BREAKPOINT_INFO, Entry );
Next = Next->Flink;
DestroyBreakpoint( Breakpoint->Address, Process, Thread );
}
FreeMem( &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;
}
BOOLEAN
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( INSTALER_DUPLICATE_PROCESS_ID, 0, DebugEvent->dwProcessId );
return FALSE;
}
}
else
if (DebugEvent->dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT) {
if (Thread != NULL) {
DeclareError( INSTALER_DUPLICATE_THREAD_ID, 0, DebugEvent->dwThreadId, DebugEvent->dwProcessId );
return FALSE;
}
if (Process == NULL) {
DeclareError( INSTALER_MISSING_PROCESS_ID, 0, DebugEvent->dwProcessId );
return FALSE;
}
}
else
if (Process == NULL) {
DeclareError( INSTALER_MISSING_PROCESS_ID, 0, DebugEvent->dwProcessId );
return FALSE;
}
else
if (Thread == NULL) {
DeclareError( INSTALER_MISSING_THREAD_ID, 0, DebugEvent->dwThreadId, DebugEvent->dwProcessId );
return FALSE;
}
return TRUE;
}
VOID
SuspendAllButThisThread(
PPROCESS_INFO Process,
PTHREAD_INFO Thread
)
{
PTHREAD_INFO Thread1;
PLIST_ENTRY Next, Head;
if (Thread != NULL) {
Head = &Process->ThreadListHead;
Next = Head->Flink;
while (Next != Head) {
Thread1 = CONTAINING_RECORD( Next, THREAD_INFO, Entry );
if (Thread1 != Thread) {
NtSuspendThread( Thread1->Handle, NULL );
}
Next = Next->Flink;
}
}
return;
}
VOID
ResumeAllButThisThread(
PPROCESS_INFO Process,
PTHREAD_INFO Thread
)
{
PTHREAD_INFO Thread1;
PLIST_ENTRY Next, Head;
if (Thread != NULL) {
Head = &Process->ThreadListHead;
Next = Head->Flink;
while (Next != Head) {
Thread1 = CONTAINING_RECORD( Next, THREAD_INFO, Entry );
if (Thread1 != Thread) {
NtResumeThread( Thread1->Handle, NULL );
}
Next = Next->Flink;
}
}
return;
}
PBREAKPOINT_INFO
FindBreakpoint(
LPVOID Address,
PPROCESS_INFO Process,
PTHREAD_INFO Thread
)
{
PBREAKPOINT_INFO Breakpoint;
PLIST_ENTRY Next, Head;
if (Thread != NULL) {
Head = &Thread->BreakpointListHead;
Next = Head->Flink;
while (Next != Head) {
Breakpoint = CONTAINING_RECORD( Next, BREAKPOINT_INFO, Entry );
if (Breakpoint->Address == Address) {
return Breakpoint;
}
Next = Next->Flink;
}
}
Head = &Process->BreakpointListHead;
Next = Head->Flink;
while (Next != Head) {
Breakpoint = CONTAINING_RECORD( Next, BREAKPOINT_INFO, Entry );
if (Breakpoint->Address == Address) {
return Breakpoint;
}
Next = Next->Flink;
}
return NULL;
}
BOOLEAN
CreateBreakpoint(
LPVOID Address,
PPROCESS_INFO Process,
PTHREAD_INFO Thread,
UCHAR ApiIndex,
PAPI_SAVED_PARAMETERS SavedParameters,
PBREAKPOINT_INFO *ReturnedBreakpoint
)
{
PBREAKPOINT_INFO Breakpoint;
Breakpoint = FindBreakpoint( Address, Process, Thread );
if (ARGUMENT_PRESENT( ReturnedBreakpoint )) {
*ReturnedBreakpoint = Breakpoint;
}
if (Breakpoint != NULL) {
return (Breakpoint->ApiIndex == ApiIndex);
}
Breakpoint = AllocMem( sizeof( *Breakpoint ) );
if (Breakpoint == NULL) {
return FALSE;
}
Breakpoint->Address = Address;
Breakpoint->ApiIndex = ApiIndex;
if (ARGUMENT_PRESENT( SavedParameters )) {
Breakpoint->SavedParameters = *SavedParameters;
Breakpoint->SavedParametersValid = TRUE;
}
else {
Breakpoint->SavedParametersValid = FALSE;
}
if (Thread != NULL) {
InsertTailList( &Thread->BreakpointListHead, &Breakpoint->Entry );
}
else {
InsertTailList( &Process->BreakpointListHead, &Breakpoint->Entry );
}
InstallBreakpoint( Process, Breakpoint );
if (ARGUMENT_PRESENT( ReturnedBreakpoint )) {
*ReturnedBreakpoint = Breakpoint;
}
return TRUE;
}
BOOLEAN
DestroyBreakpoint(
LPVOID Address,
PPROCESS_INFO Process,
PTHREAD_INFO Thread
)
{
PBREAKPOINT_INFO Breakpoint;
Breakpoint = FindBreakpoint( Address, Process, Thread );
if (Breakpoint == NULL) {
return FALSE;
}
RemoveBreakpoint( Process, Breakpoint );
RemoveEntryList( &Breakpoint->Entry );
FreeMem( &Breakpoint );
return TRUE;
}
BOOLEAN
HandleThreadsForSingleStep(
PPROCESS_INFO Process,
PTHREAD_INFO ThreadToSingleStep,
BOOLEAN SuspendThreads
)
{
PLIST_ENTRY Next, Head;
PTHREAD_INFO Thread;
Head = &Process->ThreadListHead;
Next = Head->Flink;
while (Next != Head) {
Thread = CONTAINING_RECORD( Next, THREAD_INFO, Entry );
if (Thread != ThreadToSingleStep) {
if (SuspendThreads) {
if (Thread->BreakpointToStepOver == NULL) {
SuspendThread( Thread->Handle );
}
}
else {
ResumeThread( Thread->Handle );
}
break;
}
Next = Next->Flink;
}
return TRUE;
}
BOOLEAN
ReadMemory(
PPROCESS_INFO Process,
PVOID Address,
PVOID DataRead,
ULONG BytesToRead,
PCHAR Reason
)
{
ULONG BytesRead;
if (!ReadProcessMemory( Process->Handle,
Address,
DataRead,
BytesToRead,
&BytesRead
) ||
BytesRead != BytesToRead
) {
DbgEvent( MEMORYERROR, ( "Read memory from %x for %x bytes failed (%u) - '%s'\n",
Address,
BytesToRead,
GetLastError(),
Reason
)
);
return FALSE;
}
else {
return TRUE;
}
}
BOOLEAN
WriteMemory(
PPROCESS_INFO Process,
PVOID Address,
PVOID DataToWrite,
ULONG BytesToWrite,
PCHAR Reason
)
{
ULONG BytesWritten;
ULONG OldProtection;
BOOLEAN Result;
if (WriteProcessMemory( Process->Handle,
Address,
DataToWrite,
BytesToWrite,
&BytesWritten
) &&
BytesWritten == BytesToWrite
) {
return TRUE;
}
Result = FALSE;
if (GetLastError() == ERROR_NOACCESS &&
VirtualProtectEx( Process->Handle,
Address,
BytesToWrite,
PAGE_READWRITE,
&OldProtection
)
) {
if (WriteProcessMemory( Process->Handle,
Address,
DataToWrite,
BytesToWrite,
&BytesWritten
) &&
BytesWritten == BytesToWrite
) {
Result = TRUE;
}
VirtualProtectEx( Process->Handle,
Address,
BytesToWrite,
OldProtection,
&OldProtection
);
if (Result) {
return TRUE;
}
}
DbgEvent( MEMORYERROR, ( "Write memory to %x for %x bytes failed (%u) - '%s'\n",
Address,
BytesToWrite,
GetLastError(),
Reason
)
);
return FALSE;
}
PVOID
AllocMem(
ULONG Size
)
{
PVOID p;
p = HeapAlloc( AppHeap, HEAP_ZERO_MEMORY, Size );
if (p == NULL) {
DbgEvent( INTERNALERROR, ( "HeapAlloc( %0x8 ) failed\n", Size ) );
}
return p;
}
VOID
FreeMem(
PVOID *p
)
{
if (*p != NULL) {
HeapFree( AppHeap, 0, *p );
*p = NULL;
}
return;
}