reactos/reactos/ntoskrnl/ps/process.c
Alex Ionescu caaa37c1ac - Support INIT section pragmas for msvc. Patch by Brezenbak.
svn path=/trunk/; revision=19732
2005-11-28 23:25:31 +00:00

1074 lines
27 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ps/process.c
* PURPOSE: Process managment
*
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
* David Welch (welch@cwcom.net)
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* GLOBALS ******************************************************************/
PEPROCESS PsInitialSystemProcess = NULL;
PEPROCESS PsIdleProcess = NULL;
POBJECT_TYPE PsProcessType = NULL;
extern PHANDLE_TABLE PspCidTable;
EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock;
LIST_ENTRY PsActiveProcessHead;
FAST_MUTEX PspActiveProcessMutex;
LARGE_INTEGER ShortPsLockDelay, PsLockTimeout;
/* INTERNAL FUNCTIONS *****************************************************************/
NTSTATUS
NTAPI
PsLockProcess(PEPROCESS Process, BOOLEAN Timeout)
{
ULONG Attempts = 0;
PKTHREAD PrevLockOwner;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PLARGE_INTEGER Delay = (Timeout ? &PsLockTimeout : NULL);
PKTHREAD CallingThread = KeGetCurrentThread();
PAGED_CODE();
KeEnterCriticalRegion();
for(;;)
{
PrevLockOwner = (PKTHREAD)InterlockedCompareExchangePointer(
&Process->LockOwner, CallingThread, NULL);
if(PrevLockOwner == NULL || PrevLockOwner == CallingThread)
{
/* we got the lock or already locked it */
if(InterlockedIncrementUL(&Process->LockCount) == 1)
{
KeClearEvent(&Process->LockEvent);
}
return STATUS_SUCCESS;
}
else
{
if(++Attempts > 2)
{
Status = KeWaitForSingleObject(&Process->LockEvent,
Executive,
KernelMode,
FALSE,
Delay);
if(!NT_SUCCESS(Status) || Status == STATUS_TIMEOUT)
{
#ifndef NDEBUG
if(Status == STATUS_TIMEOUT)
{
DPRINT1("PsLockProcess(0x%x) timed out!\n", Process);
}
#endif
KeLeaveCriticalRegion();
break;
}
}
else
{
KeDelayExecutionThread(KernelMode, FALSE, &ShortPsLockDelay);
}
}
}
return Status;
}
VOID
NTAPI
PsUnlockProcess(PEPROCESS Process)
{
PAGED_CODE();
ASSERT(Process->LockOwner == KeGetCurrentThread());
if(InterlockedDecrementUL(&Process->LockCount) == 0)
{
InterlockedExchangePointer(&Process->LockOwner, NULL);
KeSetEvent(&Process->LockEvent, IO_NO_INCREMENT, FALSE);
}
KeLeaveCriticalRegion();
}
PEPROCESS
STDCALL
PsGetNextProcess(PEPROCESS OldProcess)
{
PEPROCESS NextProcess;
NTSTATUS Status;
/* Check if we have a previous process */
if (OldProcess == NULL)
{
/* We don't, start with the Idle Process */
Status = ObReferenceObjectByPointer(PsIdleProcess,
PROCESS_ALL_ACCESS,
PsProcessType,
KernelMode);
if (!NT_SUCCESS(Status))
{
DPRINT1("PsGetNextProcess(): ObReferenceObjectByPointer failed for PsIdleProcess\n");
KEBUGCHECK(0);
}
return PsIdleProcess;
}
/* Acquire the Active Process Lock */
ExAcquireFastMutex(&PspActiveProcessMutex);
/* Start at the previous process */
NextProcess = OldProcess;
/* Loop until we fail */
while (1)
{
/* Get the Process Link */
PLIST_ENTRY Flink = (NextProcess == PsIdleProcess ? PsActiveProcessHead.Flink :
NextProcess->ActiveProcessLinks.Flink);
/* Move to the next Process if we're not back at the beginning */
if (Flink != &PsActiveProcessHead)
{
NextProcess = CONTAINING_RECORD(Flink, EPROCESS, ActiveProcessLinks);
}
else
{
NextProcess = NULL;
break;
}
/* Reference the Process */
Status = ObReferenceObjectByPointer(NextProcess,
PROCESS_ALL_ACCESS,
PsProcessType,
KernelMode);
/* Exit the loop if the reference worked, keep going if there's an error */
if (NT_SUCCESS(Status)) break;
}
/* Release the lock */
ExReleaseFastMutex(&PspActiveProcessMutex);
/* Reference the Process we had referenced earlier */
ObDereferenceObject(OldProcess);
return(NextProcess);
}
NTSTATUS
STDCALL
PspCreateProcess(OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ParentProcess OPTIONAL,
IN BOOLEAN InheritObjectTable,
IN HANDLE SectionHandle OPTIONAL,
IN HANDLE DebugPort OPTIONAL,
IN HANDLE ExceptionPort OPTIONAL)
{
HANDLE hProcess;
PEPROCESS Process = NULL;
PEPROCESS pParentProcess = NULL;
PEPORT pDebugPort = NULL;
PEPORT pExceptionPort = NULL;
PSECTION_OBJECT SectionObject = NULL;
NTSTATUS Status = STATUS_SUCCESS;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
PHYSICAL_ADDRESS DirectoryTableBase;
KAFFINITY Affinity;
HANDLE_TABLE_ENTRY CidEntry;
BOOLEAN ProcessCreated = FALSE;
DirectoryTableBase.QuadPart = (ULONGLONG)0;
DPRINT("PspCreateProcess(ObjectAttributes %x)\n", ObjectAttributes);
/* Reference the Parent if there is one */
if(ParentProcess != NULL)
{
Status = ObReferenceObjectByHandle(ParentProcess,
PROCESS_CREATE_PROCESS,
PsProcessType,
PreviousMode,
(PVOID*)&pParentProcess,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to reference the parent process: Status: 0x%x\n", Status);
goto Cleanup;
}
/* Inherit Parent process's Affinity. */
Affinity = pParentProcess->Pcb.Affinity;
}
else
{
pParentProcess = NULL;
#ifdef CONFIG_SMP
/* FIXME:
* Only the boot cpu is initialized in the early boot phase.
*/
Affinity = 0xffffffff;
#else
Affinity = KeActiveProcessors;
#endif
}
/* Add the debug port */
if (DebugPort != NULL)
{
Status = ObReferenceObjectByHandle(DebugPort,
PORT_ALL_ACCESS,
LpcPortObjectType,
PreviousMode,
(PVOID*)&pDebugPort,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to reference the debug port: Status: 0x%x\n", Status);
goto Cleanup;
}
}
/* Add the exception port */
if (ExceptionPort != NULL)
{
Status = ObReferenceObjectByHandle(ExceptionPort,
PORT_ALL_ACCESS,
LpcPortObjectType,
PreviousMode,
(PVOID*)&pExceptionPort,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to reference the exception port: Status: 0x%x\n", Status);
goto Cleanup;
}
}
/* Add the Section */
if (SectionHandle != NULL)
{
Status = ObReferenceObjectByHandle(SectionHandle,
SECTION_MAP_EXECUTE,
MmSectionObjectType,
PreviousMode,
(PVOID*)&SectionObject,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to reference process image section: Status: 0x%x\n", Status);
goto Cleanup;
}
}
/* Create the Object */
DPRINT("Creating Process Object\n");
Status = ObCreateObject(PreviousMode,
PsProcessType,
ObjectAttributes,
PreviousMode,
NULL,
sizeof(EPROCESS),
0,
0,
(PVOID*)&Process);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create process object, Status: 0x%x\n", Status);
goto Cleanup;
}
/* Clean up the Object */
DPRINT("Cleaning Process Object\n");
RtlZeroMemory(Process, sizeof(EPROCESS));
/* Inherit stuff from the Parent since we now have the object created */
if (pParentProcess)
{
Process->InheritedFromUniqueProcessId = pParentProcess->UniqueProcessId;
Process->Session = pParentProcess->Session;
}
/* Set up the Quota Block from the Parent */
PspInheritQuota(Process, pParentProcess);
/* FIXME: Set up Dos Device Map from the Parent
ObInheritDeviceMap(Parent, Process) */
/* Set the Process' LPC Ports */
Process->DebugPort = pDebugPort;
Process->ExceptionPort = pExceptionPort;
/* Setup the Lock Event */
DPRINT("Initialzing Process Lock\n");
KeInitializeEvent(&Process->LockEvent, SynchronizationEvent, FALSE);
/* Setup the Thread List Head */
DPRINT("Initialzing Process ThreadListHead\n");
InitializeListHead(&Process->ThreadListHead);
/* Create or Clone the Handle Table */
DPRINT("Initialzing Process Handle Table\n");
ObCreateHandleTable(pParentProcess, InheritObjectTable, Process);
DPRINT("Handle Table: %x\n", Process->ObjectTable);
/* Set Process's Directory Base */
DPRINT("Initialzing Process Directory Base\n");
MmCopyMmInfo(pParentProcess ? pParentProcess : PsInitialSystemProcess,
Process,
&DirectoryTableBase);
/* Now initialize the Kernel Process */
DPRINT("Initialzing Kernel Process\n");
KeInitializeProcess(&Process->Pcb,
PROCESS_PRIORITY_NORMAL,
Affinity,
DirectoryTableBase);
/* Duplicate Parent Token */
DPRINT("Initialzing Process Token\n");
Status = PspInitializeProcessSecurity(Process, pParentProcess);
if (!NT_SUCCESS(Status))
{
DbgPrint("PspInitializeProcessSecurity failed (Status %x)\n", Status);
goto Cleanup;
}
/* Create the Process' Address Space */
DPRINT("Initialzing Process Address Space\n");
Status = MmCreateProcessAddressSpace(Process, SectionObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create Address Space\n");
goto Cleanup;
}
if (SectionObject)
{
/* Map the System Dll */
DPRINT("Mapping System DLL\n");
PspMapSystemDll(Process, NULL);
}
/* Create a handle for the Process */
DPRINT("Initialzing Process CID Handle\n");
CidEntry.u1.Object = Process;
CidEntry.u2.GrantedAccess = 0;
Process->UniqueProcessId = ExCreateHandle(PspCidTable, &CidEntry);
DPRINT("Created CID: %d\n", Process->UniqueProcessId);
if(!Process->UniqueProcessId)
{
DPRINT1("Failed to create CID handle\n");
Status = STATUS_UNSUCCESSFUL; /* FIXME - what error should we return? */
goto Cleanup;
}
/* FIXME: Insert into Job Object */
/* Create PEB only for User-Mode Processes */
if (pParentProcess)
{
DPRINT("Creating PEB\n");
Status = MmCreatePeb(Process);
if (!NT_SUCCESS(Status))
{
DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
goto Cleanup;
}
}
/* W00T! The process can now be activated */
DPRINT("Inserting into Active Process List\n");
ExAcquireFastMutex(&PspActiveProcessMutex);
InsertTailList(&PsActiveProcessHead, &Process->ActiveProcessLinks);
ExReleaseFastMutex(&PspActiveProcessMutex);
ProcessCreated = TRUE;
/* FIXME: SeCreateAccessStateEx */
/* Insert the Process into the Object Directory */
DPRINT("Inserting Process Object\n");
Status = ObInsertObject(Process,
NULL,
DesiredAccess,
0,
NULL,
&hProcess);
if (NT_SUCCESS(Status))
{
/* Set the Creation Time */
KeQuerySystemTime(&Process->CreateTime);
DPRINT("Done. Returning handle: %x\n", hProcess);
_SEH_TRY
{
*ProcessHandle = hProcess;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
} _SEH_END;
/* FIXME: ObGetObjectSecurity(Process, &SecurityDescriptor)
SeAccessCheck
*/
}
Cleanup:
if(pParentProcess != NULL) ObDereferenceObject(pParentProcess);
if(SectionObject != NULL) ObDereferenceObject(SectionObject);
if (!ProcessCreated)
{
if(pExceptionPort != NULL) ObDereferenceObject(pExceptionPort);
if(pDebugPort != NULL) ObDereferenceObject(pDebugPort);
if(Process != NULL) ObDereferenceObject(Process);
}
return Status;
}
/* PUBLIC FUNCTIONS *****************************************************************/
/*
* @implemented
*/
NTSTATUS
STDCALL
PsCreateSystemProcess(PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes)
{
return PspCreateProcess(ProcessHandle,
DesiredAccess,
ObjectAttributes,
NULL, /* no parent process */
FALSE,
NULL,
NULL,
NULL);
}
/*
* @implemented
*/
NTSTATUS
STDCALL
PsLookupProcessByProcessId(IN HANDLE ProcessId,
OUT PEPROCESS *Process)
{
PHANDLE_TABLE_ENTRY CidEntry;
PEPROCESS FoundProcess;
NTSTATUS Status = STATUS_INVALID_PARAMETER;
PAGED_CODE();
KeEnterCriticalRegion();
/* Get the CID Handle Entry */
if ((CidEntry = ExMapHandleToPointer(PspCidTable,
ProcessId)))
{
/* Get the Process */
FoundProcess = CidEntry->u1.Object;
/* Make sure it's really a process */
if (FoundProcess->Pcb.Header.Type == ProcessObject)
{
/* Reference and return it */
ObReferenceObject(FoundProcess);
*Process = FoundProcess;
Status = STATUS_SUCCESS;
}
/* Unlock the Entry */
ExUnlockHandleTableEntry(PspCidTable, CidEntry);
}
KeLeaveCriticalRegion();
/* Return to caller */
return Status;
}
/*
* @implemented
*/
NTSTATUS
STDCALL
PsLookupProcessThreadByCid(IN PCLIENT_ID Cid,
OUT PEPROCESS *Process OPTIONAL,
OUT PETHREAD *Thread)
{
PHANDLE_TABLE_ENTRY CidEntry;
PETHREAD FoundThread;
NTSTATUS Status = STATUS_INVALID_CID;
PAGED_CODE();
KeEnterCriticalRegion();
/* Get the CID Handle Entry */
if ((CidEntry = ExMapHandleToPointer(PspCidTable,
Cid->UniqueThread)))
{
/* Get the Process */
FoundThread = CidEntry->u1.Object;
/* Make sure it's really a thread and this process' */
if ((FoundThread->Tcb.DispatcherHeader.Type == ThreadObject) &&
(FoundThread->Cid.UniqueProcess == Cid->UniqueProcess))
{
/* Reference and return it */
ObReferenceObject(FoundThread);
*Thread = FoundThread;
Status = STATUS_SUCCESS;
/* Check if we should return the Process too */
if (Process)
{
/* Return it and reference it */
*Process = FoundThread->ThreadsProcess;
ObReferenceObject(*Process);
}
}
/* Unlock the Entry */
ExUnlockHandleTableEntry(PspCidTable, CidEntry);
}
KeLeaveCriticalRegion();
/* Return to caller */
return Status;
}
/*
* FUNCTION: Returns a pointer to the current process
*
* @implemented
*/
PEPROCESS STDCALL
IoGetCurrentProcess(VOID)
{
if (PsGetCurrentThread() == NULL ||
PsGetCurrentThread()->Tcb.ApcState.Process == NULL)
{
return(PsInitialSystemProcess);
}
else
{
return(PEPROCESS)(PsGetCurrentThread()->Tcb.ApcState.Process);
}
}
/*
* @implemented
*/
LARGE_INTEGER STDCALL
PsGetProcessExitTime(VOID)
{
LARGE_INTEGER Li;
Li.QuadPart = PsGetCurrentProcess()->ExitTime.QuadPart;
return Li;
}
/*
* @implemented
*/
LONGLONG
STDCALL
PsGetProcessCreateTimeQuadPart(PEPROCESS Process)
{
return Process->CreateTime.QuadPart;
}
/*
* @implemented
*/
PVOID
STDCALL
PsGetProcessDebugPort(PEPROCESS Process)
{
return Process->DebugPort;
}
/*
* @implemented
*/
BOOLEAN
STDCALL
PsGetProcessExitProcessCalled(PEPROCESS Process)
{
return Process->ProcessExiting;
}
/*
* @implemented
*/
NTSTATUS
STDCALL
PsGetProcessExitStatus(PEPROCESS Process)
{
return Process->ExitStatus;
}
/*
* @implemented
*/
HANDLE
STDCALL
PsGetProcessId(PEPROCESS Process)
{
return (HANDLE)Process->UniqueProcessId;
}
/*
* @implemented
*/
LPSTR
STDCALL
PsGetProcessImageFileName(PEPROCESS Process)
{
return (LPSTR)Process->ImageFileName;
}
/*
* @implemented
*/
HANDLE
STDCALL
PsGetProcessInheritedFromUniqueProcessId(PEPROCESS Process)
{
return Process->InheritedFromUniqueProcessId;
}
/*
* @implemented
*/
PEJOB
STDCALL
PsGetProcessJob(PEPROCESS Process)
{
return Process->Job;
}
/*
* @implemented
*/
PPEB
STDCALL
PsGetProcessPeb(PEPROCESS Process)
{
return Process->Peb;
}
/*
* @implemented
*/
ULONG
STDCALL
PsGetProcessPriorityClass(PEPROCESS Process)
{
return Process->PriorityClass;
}
/*
* @implemented
*/
HANDLE STDCALL
PsGetCurrentProcessId(VOID)
{
return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
}
/*
* @implemented
*/
ULONG
STDCALL
PsGetCurrentProcessSessionId(VOID)
{
return PsGetCurrentProcess()->Session;
}
/*
* @implemented
*/
PVOID
STDCALL
PsGetProcessSectionBaseAddress(PEPROCESS Process)
{
return Process->SectionBaseAddress;
}
/*
* @implemented
*/
PVOID
STDCALL
PsGetProcessSecurityPort(PEPROCESS Process)
{
return Process->SecurityPort;
}
/*
* @implemented
*/
HANDLE
STDCALL
PsGetProcessSessionId(PEPROCESS Process)
{
return (HANDLE)Process->Session;
}
struct _W32THREAD*
STDCALL
PsGetWin32Thread(VOID)
{
return(PsGetCurrentThread()->Tcb.Win32Thread);
}
struct _W32PROCESS*
STDCALL
PsGetWin32Process(VOID)
{
return (struct _W32PROCESS*)PsGetCurrentProcess()->Win32Process;
}
/*
* @implemented
*/
PVOID
STDCALL
PsGetProcessWin32Process(PEPROCESS Process)
{
return Process->Win32Process;
}
/*
* @implemented
*/
PVOID
STDCALL
PsGetProcessWin32WindowStation(PEPROCESS Process)
{
return Process->Win32WindowStation;
}
/*
* @implemented
*/
BOOLEAN
STDCALL
PsIsProcessBeingDebugged(PEPROCESS Process)
{
return FALSE; //Process->IsProcessBeingDebugged;
}
/*
* @implemented
*/
VOID
STDCALL
PsSetProcessPriorityClass(PEPROCESS Process,
ULONG PriorityClass)
{
Process->PriorityClass = PriorityClass;
}
/*
* @implemented
*/
VOID
STDCALL
PsSetProcessSecurityPort(PEPROCESS Process,
PVOID SecurityPort)
{
Process->SecurityPort = SecurityPort;
}
/*
* @implemented
*/
VOID
STDCALL
PsSetProcessWin32Process(PEPROCESS Process,
PVOID Win32Process)
{
Process->Win32Process = Win32Process;
}
/*
* @implemented
*/
VOID
STDCALL
PsSetProcessWindowStation(PEPROCESS Process,
PVOID WindowStation)
{
Process->Win32WindowStation = WindowStation;
}
/*
* @unimplemented
*/
NTSTATUS
STDCALL
PsSetProcessPriorityByClass(IN PEPROCESS Process,
IN ULONG Type)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/*
* FUNCTION: Creates a process.
* ARGUMENTS:
* ProcessHandle (OUT) = Caller supplied storage for the resulting
* handle
* DesiredAccess = Specifies the allowed or desired access to the
* process can be a combination of
* STANDARD_RIGHTS_REQUIRED| ..
* ObjectAttribute = Initialized attributes for the object, contains
* the rootdirectory and the filename
* ParentProcess = Handle to the parent process.
* InheritObjectTable = Specifies to inherit the objects of the parent
* process if true.
* SectionHandle = Handle to a section object to back the image file
* DebugPort = Handle to a DebugPort if NULL the system default debug
* port will be used.
* ExceptionPort = Handle to a exception port.
* REMARKS:
* This function maps to the win32 CreateProcess.
* RETURNS: Status
*
* @implemented
*/
NTSTATUS
STDCALL
NtCreateProcess(OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ParentProcess,
IN BOOLEAN InheritObjectTable,
IN HANDLE SectionHandle OPTIONAL,
IN HANDLE DebugPort OPTIONAL,
IN HANDLE ExceptionPort OPTIONAL)
{
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
/* Check parameters */
if(PreviousMode != KernelMode)
{
_SEH_TRY
{
ProbeForWriteHandle(ProcessHandle);
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status)) return Status;
}
/* Make sure there's a parent process */
if(ParentProcess == NULL)
{
/* Can't create System Processes like this */
Status = STATUS_INVALID_PARAMETER;
}
else
{
/* Create a user Process */
Status = PspCreateProcess(ProcessHandle,
DesiredAccess,
ObjectAttributes,
ParentProcess,
InheritObjectTable,
SectionHandle,
DebugPort,
ExceptionPort);
}
/* Return Status */
return Status;
}
/*
* @implemented
*/
NTSTATUS
STDCALL
NtOpenProcess(OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId)
{
KPROCESSOR_MODE PreviousMode;
CLIENT_ID SafeClientId;
ULONG Attributes = 0;
HANDLE hProcess;
BOOLEAN HasObjectName = FALSE;
PETHREAD Thread = NULL;
PEPROCESS Process = NULL;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
PreviousMode = KeGetPreviousMode();
/* Probe the paraemeters */
if(PreviousMode != KernelMode)
{
_SEH_TRY
{
ProbeForWriteHandle(ProcessHandle);
if(ClientId != NULL)
{
ProbeForRead(ClientId,
sizeof(CLIENT_ID),
sizeof(ULONG));
SafeClientId = *ClientId;
ClientId = &SafeClientId;
}
/* just probe the object attributes structure, don't capture it
completely. This is done later if necessary */
ProbeForRead(ObjectAttributes,
sizeof(OBJECT_ATTRIBUTES),
sizeof(ULONG));
HasObjectName = (ObjectAttributes->ObjectName != NULL);
Attributes = ObjectAttributes->Attributes;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status)) return Status;
}
else
{
HasObjectName = (ObjectAttributes->ObjectName != NULL);
Attributes = ObjectAttributes->Attributes;
}
if (HasObjectName && ClientId != NULL)
{
/* can't pass both, n object name and a client id */
return STATUS_INVALID_PARAMETER_MIX;
}
/* Open by name if one was given */
DPRINT("Checking type\n");
if (HasObjectName)
{
/* Open it */
DPRINT("Opening by name\n");
Status = ObOpenObjectByName(ObjectAttributes,
PsProcessType,
NULL,
PreviousMode,
DesiredAccess,
NULL,
&hProcess);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not open object by name\n");
}
}
else if (ClientId != NULL)
{
/* Open by Thread ID */
if (ClientId->UniqueThread)
{
/* Get the Process */
DPRINT("Opening by Thread ID: %x\n", ClientId->UniqueThread);
Status = PsLookupProcessThreadByCid(ClientId,
&Process,
&Thread);
}
else
{
/* Get the Process */
DPRINT("Opening by Process ID: %x\n", ClientId->UniqueProcess);
Status = PsLookupProcessByProcessId(ClientId->UniqueProcess,
&Process);
}
if(!NT_SUCCESS(Status))
{
DPRINT1("Failure to find process\n");
return Status;
}
/* Open the Process Object */
Status = ObOpenObjectByPointer(Process,
Attributes,
NULL,
DesiredAccess,
PsProcessType,
PreviousMode,
&hProcess);
if(!NT_SUCCESS(Status))
{
DPRINT1("Failure to open process\n");
}
/* Dereference the thread if we used it */
if (Thread) ObDereferenceObject(Thread);
/* Dereference the Process */
ObDereferenceObject(Process);
}
else
{
/* neither an object name nor a client id was passed */
return STATUS_INVALID_PARAMETER_MIX;
}
/* Write back the handle */
if(NT_SUCCESS(Status))
{
_SEH_TRY
{
*ProcessHandle = hProcess;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
return Status;
}
/* EOF */