-/* $Id$
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/ps/process.c
+ * PURPOSE: Process managment
*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/ps/process.c
- * PURPOSE: Process managment
- * PROGRAMMER: David Welch (welch@cwcom.net)
- * REVISION HISTORY:
- * 21/07/98: Created
+ * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
+ * David Welch (welch@cwcom.net)
*/
/* INCLUDES ******************************************************************/
/* GLOBALS ******************************************************************/
PEPROCESS EXPORTED PsInitialSystemProcess = NULL;
-
+PEPROCESS PsIdleProcess = NULL;
POBJECT_TYPE EXPORTED PsProcessType = NULL;
+extern PHANDLE_TABLE PspCidTable;
-LIST_ENTRY PsProcessListHead;
-static KSPIN_LOCK PsProcessListLock;
-static ULONG PiNextProcessUniqueId = 0; /* TODO */
-static LARGE_INTEGER ShortPsLockDelay, PsLockTimeout;
+EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock;
-static GENERIC_MAPPING PiProcessMapping = {STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
- STANDARD_RIGHTS_WRITE | PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD |
- PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE |
- PROCESS_TERMINATE | PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION | PROCESS_SET_PORT,
- STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
- PROCESS_ALL_ACCESS};
+LIST_ENTRY PsActiveProcessHead;
+FAST_MUTEX PspActiveProcessMutex;
+LARGE_INTEGER ShortPsLockDelay, PsLockTimeout;
-#define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8
-#define MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT 8
+/* INTERNAL FUNCTIONS *****************************************************************/
-static PCREATE_PROCESS_NOTIFY_ROUTINE
-PiProcessNotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT];
-static PLOAD_IMAGE_NOTIFY_ROUTINE
-PiLoadImageNotifyRoutine[MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT];
+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();
-typedef struct
-{
- WORK_QUEUE_ITEM WorkQueueItem;
- KEVENT Event;
- PEPROCESS Process;
- BOOLEAN IsWorkerQueue;
-} DEL_CONTEXT, *PDEL_CONTEXT;
+ KeEnterCriticalRegion();
-/* FUNCTIONS *****************************************************************/
+ 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);
+ }
-VOID
-STDCALL
-PsExitSpecialApc(PKAPC Apc,
- PKNORMAL_ROUTINE *NormalRoutine,
- PVOID *NormalContext,
- PVOID *SystemArgument1,
- PVOID *SystemArgument2)
-{
+ 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;
}
-PEPROCESS
-PsGetNextProcess(PEPROCESS OldProcess)
+VOID
+NTAPI
+PsUnlockProcess(PEPROCESS Process)
{
- KIRQL oldIrql;
- PEPROCESS NextProcess;
- NTSTATUS Status;
-
- if (OldProcess == NULL)
- {
- Status = ObReferenceObjectByPointer(PsInitialSystemProcess,
- PROCESS_ALL_ACCESS,
- PsProcessType,
- KernelMode);
- if (!NT_SUCCESS(Status))
- {
- CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed for PsInitialSystemProcess\n");
- KEBUGCHECK(0);
- }
- return PsInitialSystemProcess;
- }
-
- KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
- NextProcess = OldProcess;
- while (1)
- {
- if (NextProcess->ProcessListEntry.Blink == &PsProcessListHead)
- {
- NextProcess = CONTAINING_RECORD(PsProcessListHead.Blink,
- EPROCESS,
- ProcessListEntry);
- }
- else
- {
- NextProcess = CONTAINING_RECORD(NextProcess->ProcessListEntry.Blink,
- EPROCESS,
- ProcessListEntry);
- }
- Status = ObReferenceObjectByPointer(NextProcess,
- PROCESS_ALL_ACCESS,
- PsProcessType,
- KernelMode);
- if (NT_SUCCESS(Status))
- {
- break;
- }
- else if (Status == STATUS_PROCESS_IS_TERMINATING)
- {
- continue;
- }
- else if (!NT_SUCCESS(Status))
- {
- CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed\n");
- KEBUGCHECK(0);
- }
- }
-
- KeReleaseSpinLock(&PsProcessListLock, oldIrql);
- ObDereferenceObject(OldProcess);
-
- return(NextProcess);
-}
+ PAGED_CODE();
+ ASSERT(Process->LockOwner == KeGetCurrentThread());
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-NtOpenProcessToken(IN HANDLE ProcessHandle,
- IN ACCESS_MASK DesiredAccess,
- OUT PHANDLE TokenHandle)
-{
- PACCESS_TOKEN Token;
- HANDLE hToken;
- NTSTATUS Status;
+ if(InterlockedDecrementUL(&Process->LockCount) == 0)
+ {
+ InterlockedExchangePointer(&Process->LockOwner, NULL);
+ KeSetEvent(&Process->LockEvent, IO_NO_INCREMENT, FALSE);
+ }
- Status = PsOpenTokenOfProcess(ProcessHandle,
- &Token);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- Status = ObCreateHandle(PsGetCurrentProcess(),
- Token,
- DesiredAccess,
- FALSE,
- &hToken);
- ObDereferenceObject(Token);
-
- if(NT_SUCCESS(Status))
- {
- Status = MmCopyToCaller(TokenHandle, &hToken, sizeof(HANDLE));
- }
- return(Status);
+ KeLeaveCriticalRegion();
}
-
-/*
- * @unimplemented
- */
-NTSTATUS
+PEPROCESS
STDCALL
-NtOpenProcessTokenEx(
- IN HANDLE ProcessHandle,
- IN ACCESS_MASK DesiredAccess,
- IN ULONG HandleAttributes,
- OUT PHANDLE TokenHandle
- )
+PsGetNextProcess(PEPROCESS OldProcess)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
+ 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);
+ }
-/*
- * @implemented
- */
-PACCESS_TOKEN STDCALL
-PsReferencePrimaryToken(PEPROCESS Process)
-{
- ObReferenceObjectByPointer(Process->Token,
- TOKEN_ALL_ACCESS,
- SepTokenObjectType,
- UserMode);
- return(Process->Token);
-}
+ return PsIdleProcess;
+ }
+ /* Acquire the Active Process Lock */
+ ExAcquireFastMutex(&PspActiveProcessMutex);
-NTSTATUS
-PsOpenTokenOfProcess(HANDLE ProcessHandle,
- PACCESS_TOKEN* Token)
-{
- PEPROCESS Process;
- NTSTATUS Status;
-
- Status = ObReferenceObjectByHandle(ProcessHandle,
- PROCESS_QUERY_INFORMATION,
- PsProcessType,
- UserMode,
- (PVOID*)&Process,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- *Token = PsReferencePrimaryToken(Process);
- ObDereferenceObject(Process);
- return(STATUS_SUCCESS);
-}
+ /* 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);
-VOID
-PiKillMostProcesses(VOID)
-{
- KIRQL oldIrql;
- PLIST_ENTRY current_entry;
- PEPROCESS current;
-
- KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
-
- current_entry = PsProcessListHead.Flink;
- while (current_entry != &PsProcessListHead)
- {
- current = CONTAINING_RECORD(current_entry, EPROCESS,
- ProcessListEntry);
- current_entry = current_entry->Flink;
-
- if (current->UniqueProcessId != PsInitialSystemProcess->UniqueProcessId &&
- current->UniqueProcessId != (ULONG)PsGetCurrentProcessId())
- {
- PiTerminateProcessThreads(current, STATUS_SUCCESS);
- }
- }
-
- KeReleaseSpinLock(&PsProcessListLock, oldIrql);
-}
+ /* 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);
-VOID INIT_FUNCTION
-PsInitProcessManagment(VOID)
-{
- PKPROCESS KProcess;
- KIRQL oldIrql;
- NTSTATUS Status;
-
- ShortPsLockDelay.QuadPart = -100LL;
- PsLockTimeout.QuadPart = -10000000LL; /* one second */
- /*
- * Register the process object type
- */
-
- PsProcessType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
-
- PsProcessType->Tag = TAG('P', 'R', 'O', 'C');
- PsProcessType->TotalObjects = 0;
- PsProcessType->TotalHandles = 0;
- PsProcessType->PeakObjects = 0;
- PsProcessType->PeakHandles = 0;
- PsProcessType->PagedPoolCharge = 0;
- PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS);
- PsProcessType->Mapping = &PiProcessMapping;
- PsProcessType->Dump = NULL;
- PsProcessType->Open = NULL;
- PsProcessType->Close = NULL;
- PsProcessType->Delete = PiDeleteProcess;
- PsProcessType->Parse = NULL;
- PsProcessType->Security = NULL;
- PsProcessType->QueryName = NULL;
- PsProcessType->OkayToClose = NULL;
- PsProcessType->Create = NULL;
- PsProcessType->DuplicationNotify = NULL;
-
- RtlRosInitUnicodeStringFromLiteral(&PsProcessType->TypeName, L"Process");
-
- ObpCreateTypeObject(PsProcessType);
-
- InitializeListHead(&PsProcessListHead);
- KeInitializeSpinLock(&PsProcessListLock);
-
- RtlZeroMemory(PiProcessNotifyRoutine, sizeof(PiProcessNotifyRoutine));
- RtlZeroMemory(PiLoadImageNotifyRoutine, sizeof(PiLoadImageNotifyRoutine));
-
- /*
- * Initialize the system process
- */
- Status = ObCreateObject(KernelMode,
- PsProcessType,
- NULL,
- KernelMode,
- NULL,
- sizeof(EPROCESS),
- 0,
- 0,
- (PVOID*)&PsInitialSystemProcess);
- if (!NT_SUCCESS(Status))
- {
- return;
- }
-
- /* System threads may run on any processor. */
- PsInitialSystemProcess->Pcb.Affinity = 0xFFFFFFFF;
- PsInitialSystemProcess->Pcb.IopmOffset = 0xffff;
- PsInitialSystemProcess->Pcb.LdtDescriptor[0] = 0;
- PsInitialSystemProcess->Pcb.LdtDescriptor[1] = 0;
- PsInitialSystemProcess->Pcb.BasePriority = PROCESS_PRIO_NORMAL;
- PsInitialSystemProcess->Pcb.ThreadQuantum = 6;
- InitializeListHead(&PsInitialSystemProcess->Pcb.ThreadListHead);
- KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
- InternalProcessType,
- sizeof(EPROCESS),
- FALSE);
- KProcess = &PsInitialSystemProcess->Pcb;
-
- MmInitializeAddressSpace(PsInitialSystemProcess,
- &PsInitialSystemProcess->AddressSpace);
- ObCreateHandleTable(NULL,FALSE,PsInitialSystemProcess);
-
- KeInitializeEvent(&PsInitialSystemProcess->LockEvent, SynchronizationEvent, FALSE);
- PsInitialSystemProcess->LockCount = 0;
- PsInitialSystemProcess->LockOwner = NULL;
-
-#if defined(__GNUC__)
- KProcess->DirectoryTableBase =
- (LARGE_INTEGER)(LONGLONG)(ULONG)MmGetPageDirectory();
-#else
- {
- LARGE_INTEGER dummy;
- dummy.QuadPart = (LONGLONG)(ULONG)MmGetPageDirectory();
- KProcess->DirectoryTableBase = dummy;
- }
-#endif
+ /* Exit the loop if the reference worked, keep going if there's an error */
+ if (NT_SUCCESS(Status)) break;
+ }
- PsInitialSystemProcess->UniqueProcessId =
- InterlockedIncrementUL(&PiNextProcessUniqueId); /* TODO */
- PsInitialSystemProcess->Win32WindowStation = (HANDLE)0;
-
- KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
- InsertHeadList(&PsProcessListHead,
- &PsInitialSystemProcess->ProcessListEntry);
- InitializeListHead(&PsInitialSystemProcess->ThreadListHead);
- KeReleaseSpinLock(&PsProcessListLock, oldIrql);
-
- strcpy(PsInitialSystemProcess->ImageFileName, "SYSTEM");
-
- SepCreateSystemProcessToken(PsInitialSystemProcess);
+ /* Release the lock */
+ ExReleaseFastMutex(&PspActiveProcessMutex);
+
+ /* Reference the Process we had referenced earlier */
+ ObDereferenceObject(OldProcess);
+ return(NextProcess);
}
-VOID STDCALL
-PiDeleteProcessWorker(PVOID pContext)
+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)
{
- KIRQL oldIrql;
- PDEL_CONTEXT Context;
- PEPROCESS CurrentProcess;
- PEPROCESS Process;
+ 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;
+ DirectoryTableBase.QuadPart = (ULONGLONG)0;
+ BOOLEAN ProcessCreated = FALSE;
+
+ 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);
- Context = (PDEL_CONTEXT)pContext;
- Process = Context->Process;
- CurrentProcess = PsGetCurrentProcess();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to reference the parent process: Status: 0x%x\n", Status);
+ goto Cleanup;
+ }
- DPRINT("PiDeleteProcess(ObjectBody %x)\n",Process);
+ /* Inherit Parent process's Affinity. */
+ Affinity = pParentProcess->Pcb.Affinity;
- if (CurrentProcess != Process)
+ }
+ else
{
- KeAttachProcess(&Process->Pcb);
+ pParentProcess = NULL;
+#ifdef CONFIG_SMP
+ /* FIXME:
+ * Only the boot cpu is initialized in the early boot phase.
+ */
+ Affinity = 0xffffffff;
+#else
+ Affinity = KeActiveProcessors;
+#endif
}
- KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
- RemoveEntryList(&Process->ProcessListEntry);
- KeReleaseSpinLock(&PsProcessListLock, oldIrql);
+ /* 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;
+ }
+ }
- /* KDB hook */
- KDB_DELETEPROCESS_HOOK(Process);
+ /* Add the exception port */
+ if (ExceptionPort != NULL)
+ {
+ Status = ObReferenceObjectByHandle(ExceptionPort,
+ PORT_ALL_ACCESS,
+ LpcPortObjectType,
+ PreviousMode,
+ (PVOID*)&pExceptionPort,
+ NULL);
- ObDereferenceObject(Process->Token);
- ObDeleteHandleTable(Process);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to reference the exception port: Status: 0x%x\n", Status);
+ goto Cleanup;
+ }
+ }
- if (CurrentProcess != Process)
+ /* Add the Section */
+ if (SectionHandle != NULL)
{
- KeDetachProcess();
+ 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;
+ }
}
- MmReleaseMmInfo(Process);
- if (Context->IsWorkerQueue)
+ /* 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))
{
- KeSetEvent(&Context->Event, IO_NO_INCREMENT, FALSE);
+ DPRINT1("Failed to create process object, Status: 0x%x\n", Status);
+ goto Cleanup;
}
-}
-
-VOID STDCALL
-PiDeleteProcess(PVOID ObjectBody)
-{
- DEL_CONTEXT Context;
- Context.Process = (PEPROCESS)ObjectBody;
+ /* Clean up the Object */
+ DPRINT("Cleaning Process Object\n");
+ RtlZeroMemory(Process, sizeof(EPROCESS));
- if (PsGetCurrentProcess() == Context.Process ||
- PsGetCurrentThread()->ThreadsProcess == Context.Process)
+ /* Inherit stuff from the Parent since we now have the object created */
+ if (pParentProcess)
{
- KEBUGCHECK(0);
+ Process->InheritedFromUniqueProcessId = pParentProcess->UniqueProcessId;
+ Process->Session = pParentProcess->Session;
}
- if (PsGetCurrentThread()->ThreadsProcess == PsGetCurrentProcess())
+ /* 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))
{
- Context.IsWorkerQueue = FALSE;
- PiDeleteProcessWorker(&Context);
+ DbgPrint("PspInitializeProcessSecurity failed (Status %x)\n", Status);
+ goto Cleanup;
}
- else
- {
- Context.IsWorkerQueue = TRUE;
- KeInitializeEvent(&Context.Event, NotificationEvent, FALSE);
- ExInitializeWorkItem (&Context.WorkQueueItem, PiDeleteProcessWorker, &Context);
- ExQueueWorkItem(&Context.WorkQueueItem, HyperCriticalWorkQueue);
- if (KeReadStateEvent(&Context.Event) == 0)
- {
- KeWaitForSingleObject(&Context.Event, Executive, KernelMode, FALSE, NULL);
- }
- }
-
- if(((PEPROCESS)ObjectBody)->Win32Process != NULL)
- {
- /* delete the W32PROCESS structure if there's one associated */
- ExFreePool (((PEPROCESS)ObjectBody)->Win32Process);
- }
-}
-static NTSTATUS
-PsCreatePeb(HANDLE ProcessHandle,
- PEPROCESS Process,
- PVOID ImageBase)
-{
- ULONG AllocSize;
- ULONG PebSize;
- PPEB Peb;
- LARGE_INTEGER SectionOffset;
- ULONG ViewSize;
- PVOID TableBase;
- NTSTATUS Status;
-
- /* Allocate the Process Environment Block (PEB) */
- Process->TebBlock = (PVOID) MM_ROUND_DOWN(PEB_BASE, MM_VIRTMEM_GRANULARITY);
- AllocSize = MM_VIRTMEM_GRANULARITY;
- Status = NtAllocateVirtualMemory(ProcessHandle,
- &Process->TebBlock,
- 0,
- &AllocSize,
- MEM_RESERVE,
- PAGE_READWRITE);
- if (!NT_SUCCESS(Status))
+ /* Create the Process' Address Space */
+ DPRINT("Initialzing Process Address Space\n");
+ Status = MmCreateProcessAddressSpace(Process, SectionObject);
+ if (!NT_SUCCESS(Status))
{
- DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
- return(Status);
+ DPRINT1("Failed to create Address Space\n");
+ goto Cleanup;
}
- ASSERT((ULONG_PTR) Process->TebBlock <= PEB_BASE &&
- PEB_BASE + PAGE_SIZE <= (ULONG_PTR) Process->TebBlock + AllocSize);
- Peb = (PPEB)PEB_BASE;
- PebSize = PAGE_SIZE;
- Status = NtAllocateVirtualMemory(ProcessHandle,
- (PVOID*)&Peb,
- 0,
- &PebSize,
- MEM_COMMIT,
- PAGE_READWRITE);
- if (!NT_SUCCESS(Status))
+
+ if (SectionObject)
{
- DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
- return(Status);
+ /* Map the System Dll */
+ DPRINT("Mapping System DLL\n");
+ PspMapSystemDll(Process, NULL);
}
- DPRINT("Peb %p PebSize %lu\n", Peb, PebSize);
- ASSERT((PPEB) PEB_BASE == Peb && PAGE_SIZE <= PebSize);
- Process->TebLastAllocated = (PVOID) Peb;
-
- ViewSize = 0;
- SectionOffset.QuadPart = (ULONGLONG)0;
- TableBase = NULL;
- Status = MmMapViewOfSection(NlsSectionObject,
- Process,
- &TableBase,
- 0,
- 0,
- &SectionOffset,
- &ViewSize,
- ViewShare,
- MEM_TOP_DOWN,
- PAGE_READONLY);
- if (!NT_SUCCESS(Status))
+
+ /* 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("MmMapViewOfSection() failed (Status %lx)\n", Status);
- return(Status);
+ DPRINT1("Failed to create CID handle\n");
+ Status = STATUS_UNSUCCESSFUL; /* FIXME - what error should we return? */
+ goto Cleanup;
}
- DPRINT("TableBase %p ViewSize %lx\n", TableBase, ViewSize);
-
- KeAttachProcess(&Process->Pcb);
-
- /* Initialize the PEB */
- RtlZeroMemory(Peb, sizeof(PEB));
- Peb->ImageBaseAddress = ImageBase;
-
- Peb->OSMajorVersion = 4;
- Peb->OSMinorVersion = 0;
- Peb->OSBuildNumber = 1381;
- Peb->OSPlatformId = 2; //VER_PLATFORM_WIN32_NT;
- Peb->SPMajorVersion = 6;
-
- Peb->AnsiCodePageData = (char*)TableBase + NlsAnsiTableOffset;
- Peb->OemCodePageData = (char*)TableBase + NlsOemTableOffset;
- Peb->UnicodeCaseTableData = (char*)TableBase + NlsUnicodeTableOffset;
-
- Process->Peb = Peb;
- KeDetachProcess();
-
- DPRINT("PsCreatePeb: Peb created at %p\n", Peb);
-
- return(STATUS_SUCCESS);
-}
-
-
-PKPROCESS
-KeGetCurrentProcess(VOID)
-/*
- * FUNCTION: Returns a pointer to the current process
- */
-{
- return(&(PsGetCurrentProcess()->Pcb));
-}
-
-/*
- * Warning: Even though it returns HANDLE, it's not a real HANDLE but really a
- * ULONG ProcessId! (Skywing)
- */
-/*
- * @implemented
- */
-HANDLE STDCALL
-PsGetCurrentProcessId(VOID)
-{
- return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
-}
-
-/*
- * @unimplemented
- */
-ULONG
-STDCALL
-PsGetCurrentProcessSessionId (
- VOID
- )
-{
- return PsGetCurrentProcess()->SessionId;
-}
-
-/*
- * 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
- */
-NTSTATUS STDCALL
-PsCreateSystemProcess(PHANDLE ProcessHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ObjectAttributes)
-{
- HANDLE SystemProcessHandle;
- NTSTATUS Status;
-
- /* FIXME - what about security? should there be any privilege checks or something
- security related? */
-
- Status = ObCreateHandle(PsGetCurrentProcess(),
- PsInitialSystemProcess,
- PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION,
- FALSE,
- &SystemProcessHandle);
- if(!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to create a handle for the system process!\n");
- return Status;
- }
-
- Status = NtCreateProcess(ProcessHandle,
- DesiredAccess,
- ObjectAttributes,
- SystemProcessHandle,
- FALSE,
- NULL,
- NULL,
- NULL);
-
- NtClose(SystemProcessHandle);
-
- return Status;
-}
-
-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)
-/*
- * 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
- */
-{
- PEPROCESS Process;
- PEPROCESS pParentProcess;
- PKPROCESS KProcess;
- NTSTATUS Status;
- KIRQL oldIrql;
- PVOID LdrStartupAddr;
- PVOID ImageBase;
- PEPORT pDebugPort;
- PEPORT pExceptionPort;
- PVOID BaseAddress;
- PMEMORY_AREA MemoryArea;
- PHYSICAL_ADDRESS BoundaryAddressMultiple;
-
- DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes);
-
- BoundaryAddressMultiple.QuadPart = 0;
-
- Status = ObReferenceObjectByHandle(ParentProcess,
- PROCESS_CREATE_PROCESS,
- PsProcessType,
- ExGetPreviousMode(),
- (PVOID*)&pParentProcess,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("NtCreateProcess() = %x\n",Status);
- return(Status);
- }
- Status = ObCreateObject(ExGetPreviousMode(),
- PsProcessType,
- ObjectAttributes,
- ExGetPreviousMode(),
- NULL,
- sizeof(EPROCESS),
- 0,
- 0,
- (PVOID*)&Process);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(pParentProcess);
- DPRINT("ObCreateObject() = %x\n",Status);
- return(Status);
- }
+ /* FIXME: Insert into Job Object */
- Status = ObInsertObject ((PVOID)Process,
- NULL,
- DesiredAccess,
- 0,
- NULL,
- ProcessHandle);
- if (!NT_SUCCESS(Status))
+ /* Create PEB only for User-Mode Processes */
+ if (pParentProcess)
{
- ObDereferenceObject (Process);
- ObDereferenceObject (pParentProcess);
- DPRINT("ObInsertObject() = %x\n",Status);
- return Status;
+ DPRINT("Creating PEB\n");
+ Status = MmCreatePeb(Process);
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
+ goto Cleanup;
+ }
}
- KeInitializeDispatcherHeader(&Process->Pcb.DispatcherHeader,
- InternalProcessType,
- sizeof(EPROCESS),
- FALSE);
- KProcess = &Process->Pcb;
- /* Inherit parent process's affinity. */
- KProcess->Affinity = pParentProcess->Pcb.Affinity;
- KProcess->BasePriority = PROCESS_PRIO_NORMAL;
- KProcess->IopmOffset = 0xffff;
- KProcess->LdtDescriptor[0] = 0;
- KProcess->LdtDescriptor[1] = 0;
- InitializeListHead(&KProcess->ThreadListHead);
- KProcess->ThreadQuantum = 6;
- KProcess->AutoAlignment = 0;
- MmInitializeAddressSpace(Process,
- &Process->AddressSpace);
- Process->UniqueProcessId = InterlockedIncrementUL(&PiNextProcessUniqueId); /* TODO */
- Process->InheritedFromUniqueProcessId =
- (HANDLE)pParentProcess->UniqueProcessId;
- ObCreateHandleTable(pParentProcess,
- InheritObjectTable,
- Process);
- MmCopyMmInfo(ParentProcess, Process);
-
- KeInitializeEvent(&Process->LockEvent, SynchronizationEvent, FALSE);
- Process->LockCount = 0;
- Process->LockOwner = NULL;
-
- Process->Win32WindowStation = (HANDLE)0;
-
- KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
- InsertHeadList(&PsProcessListHead, &Process->ProcessListEntry);
- InitializeListHead(&Process->ThreadListHead);
- KeReleaseSpinLock(&PsProcessListLock, oldIrql);
-
- ExInitializeFastMutex(&Process->TebLock);
- Process->Pcb.State = PROCESS_STATE_ACTIVE;
-
- /*
- * Add the debug port
- */
- if (DebugPort != NULL)
- {
- Status = ObReferenceObjectByHandle(DebugPort,
- PORT_ALL_ACCESS,
- LpcPortObjectType,
- UserMode,
- (PVOID*)&pDebugPort,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(Process);
- ObDereferenceObject(pParentProcess);
- ZwClose(*ProcessHandle);
- *ProcessHandle = NULL;
- return(Status);
- }
- Process->DebugPort = pDebugPort;
- }
-
- /*
- * Add the exception port
- */
- if (ExceptionPort != NULL)
- {
- Status = ObReferenceObjectByHandle(ExceptionPort,
- PORT_ALL_ACCESS,
- LpcPortObjectType,
- UserMode,
- (PVOID*)&pExceptionPort,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(Process);
- ObDereferenceObject(pParentProcess);
- ZwClose(*ProcessHandle);
- *ProcessHandle = NULL;
- return(Status);
- }
- Process->ExceptionPort = pExceptionPort;
- }
-
- /*
- * Now we have created the process proper
- */
-
- MmLockAddressSpace(&Process->AddressSpace);
-
- /* Protect the highest 64KB of the process address space */
- BaseAddress = (PVOID)MmUserProbeAddress;
- Status = MmCreateMemoryArea(Process,
- &Process->AddressSpace,
- MEMORY_AREA_NO_ACCESS,
- &BaseAddress,
- 0x10000,
- PAGE_NOACCESS,
- &MemoryArea,
- FALSE,
- FALSE,
- BoundaryAddressMultiple);
- if (!NT_SUCCESS(Status))
- {
- MmUnlockAddressSpace(&Process->AddressSpace);
- DPRINT1("Failed to protect the highest 64KB of the process address space\n");
- KEBUGCHECK(0);
- }
-
- /* Protect the lowest 64KB of the process address space */
-#if 0
- BaseAddress = (PVOID)0x00000000;
- Status = MmCreateMemoryArea(Process,
- &Process->AddressSpace,
- MEMORY_AREA_NO_ACCESS,
- &BaseAddress,
- 0x10000,
- PAGE_NOACCESS,
- &MemoryArea,
- FALSE,
- FALSE,
- BoundaryAddressMultiple);
- if (!NT_SUCCESS(Status))
- {
- MmUnlockAddressSpace(&Process->AddressSpace);
- DPRINT1("Failed to protect the lowest 64KB of the process address space\n");
- KEBUGCHECK(0);
- }
-#endif
-
- /* Protect the 60KB above the shared user page */
- BaseAddress = (char*)USER_SHARED_DATA + PAGE_SIZE;
- Status = MmCreateMemoryArea(Process,
- &Process->AddressSpace,
- MEMORY_AREA_NO_ACCESS,
- &BaseAddress,
- 0x10000 - PAGE_SIZE,
- PAGE_NOACCESS,
- &MemoryArea,
- FALSE,
- FALSE,
- BoundaryAddressMultiple);
- if (!NT_SUCCESS(Status))
- {
- MmUnlockAddressSpace(&Process->AddressSpace);
- DPRINT1("Failed to protect the memory above the shared user page\n");
- KEBUGCHECK(0);
- }
-
- /* Create the shared data page */
- BaseAddress = (PVOID)USER_SHARED_DATA;
- Status = MmCreateMemoryArea(Process,
- &Process->AddressSpace,
- MEMORY_AREA_SHARED_DATA,
- &BaseAddress,
- PAGE_SIZE,
- PAGE_READONLY,
- &MemoryArea,
- FALSE,
- FALSE,
- BoundaryAddressMultiple);
- MmUnlockAddressSpace(&Process->AddressSpace);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to create shared data page\n");
- KEBUGCHECK(0);
- }
+ /* 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);
- if (SectionHandle != NULL)
- {
- PSECTION_OBJECT SectionObject;
- UNICODE_STRING FileName;
- PWCHAR szSrc;
- PCHAR szDest;
- USHORT lnFName = 0;
-
- /*
- * Determine the image file name and save it to the EPROCESS structure
- */
- Status = ObReferenceObjectByHandle(SectionHandle,
- 0,
- MmSectionObjectType,
- UserMode,
- (PVOID*)&SectionObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DbgPrint("Failed to reference section object\n", Status);
- ObDereferenceObject(Process);
- ObDereferenceObject(pParentProcess);
- return(Status);
- }
-
- FileName = SectionObject->FileObject->FileName;
- szSrc = (PWCHAR)(FileName.Buffer + (FileName.Length / sizeof(WCHAR)) - 1);
- while(szSrc >= FileName.Buffer)
+ DPRINT("Done. Returning handle: %x\n", hProcess);
+ _SEH_TRY
{
- if(*szSrc == L'\\')
- {
- szSrc++;
- break;
- }
- else
- {
- szSrc--;
- lnFName++;
- }
+ *ProcessHandle = hProcess;
}
-
- /* copy the image file name to the process and truncate it to 15 characters
- if necessary */
- szDest = Process->ImageFileName;
- lnFName = min(lnFName, sizeof(Process->ImageFileName) - 1);
- while(lnFName-- > 0)
+ _SEH_HANDLE
{
- *(szDest++) = (UCHAR)*(szSrc++);
- }
- *szDest = '\0';
-
-
- ObDereferenceObject(SectionObject);
- }
- else
- {
- Process->ImageFileName[0] = '\0';
- }
+ Status = _SEH_GetExceptionCode();
+ } _SEH_END;
+ /* FIXME: ObGetObjectSecurity(Process, &SecurityDescriptor)
+ SeAccessCheck
+ */
+ }
- /*
- * Map ntdll
- */
- Status = LdrpMapSystemDll(*ProcessHandle,
- &LdrStartupAddr);
- if (!NT_SUCCESS(Status))
- {
- DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status);
- ObDereferenceObject(Process);
- ObDereferenceObject(pParentProcess);
- return(Status);
- }
-
- /*
- * Map the process image
- */
- if (SectionHandle != NULL)
- {
- DPRINT("Mapping process image\n");
- Status = LdrpMapImage(*ProcessHandle,
- SectionHandle,
- &ImageBase);
- if (!NT_SUCCESS(Status))
- {
- DbgPrint("LdrpMapImage failed (Status %x)\n", Status);
- ObDereferenceObject(Process);
- ObDereferenceObject(pParentProcess);
- return(Status);
- }
- }
- else
- {
- ImageBase = NULL;
- }
-
- /*
- * Duplicate the token
- */
- Status = SepInitializeNewProcess(Process, pParentProcess);
- if (!NT_SUCCESS(Status))
+Cleanup:
+ if(pParentProcess != NULL) ObDereferenceObject(pParentProcess);
+ if(SectionObject != NULL) ObDereferenceObject(SectionObject);
+ if (!ProcessCreated)
{
- DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status);
- ObDereferenceObject(Process);
- ObDereferenceObject(pParentProcess);
- return(Status);
+ if(pExceptionPort != NULL) ObDereferenceObject(pExceptionPort);
+ if(pDebugPort != NULL) ObDereferenceObject(pDebugPort);
+ if(Process != NULL) ObDereferenceObject(Process);
}
- /*
- *
- */
- DPRINT("Creating PEB\n");
- Status = PsCreatePeb(*ProcessHandle,
- Process,
- ImageBase);
- if (!NT_SUCCESS(Status))
- {
- DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
- ObDereferenceObject(Process);
- ObDereferenceObject(pParentProcess);
- ZwClose(*ProcessHandle);
- *ProcessHandle = NULL;
- return(Status);
- }
-
- /*
- * Maybe send a message to the creator process's debugger
- */
-#if 0
- if (pParentProcess->DebugPort != NULL)
- {
- LPC_DBG_MESSAGE Message;
- HANDLE FileHandle;
-
- ObCreateHandle(NULL, // Debugger Process
- NULL, // SectionHandle
- FILE_ALL_ACCESS,
- FALSE,
- &FileHandle);
-
- Message.Header.MessageSize = sizeof(LPC_DBG_MESSAGE);
- Message.Header.DataSize = sizeof(LPC_DBG_MESSAGE) -
- sizeof(LPC_MESSAGE);
- Message.Type = DBG_EVENT_CREATE_PROCESS;
- Message.Data.CreateProcess.FileHandle = FileHandle;
- Message.Data.CreateProcess.Base = ImageBase;
- Message.Data.CreateProcess.EntryPoint = NULL; //
-
- Status = LpcSendDebugMessagePort(pParentProcess->DebugPort,
- &Message);
- }
-#endif
-
- PspRunCreateProcessNotifyRoutines(Process, TRUE);
-
- ObDereferenceObject(Process);
- ObDereferenceObject(pParentProcess);
- return(STATUS_SUCCESS);
+ return Status;
}
+/* PUBLIC FUNCTIONS *****************************************************************/
/*
- * @unimplemented
+ * @implemented
*/
-NTSTATUS STDCALL
-NtOpenProcess(OUT PHANDLE ProcessHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes,
- IN PCLIENT_ID ClientId)
+NTSTATUS
+STDCALL
+PsCreateSystemProcess(PHANDLE ProcessHandle,
+ ACCESS_MASK DesiredAccess,
+ POBJECT_ATTRIBUTES ObjectAttributes)
{
- DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
- "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
- ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
- ClientId->UniqueProcess, ClientId->UniqueThread);
-
-
- /*
- * Not sure of the exact semantics
- */
- if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL &&
- ObjectAttributes->ObjectName->Buffer != NULL)
- {
- NTSTATUS Status;
- PEPROCESS Process;
-
- Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
- ObjectAttributes->Attributes,
- NULL,
- DesiredAccess,
- PsProcessType,
- UserMode,
- NULL,
- (PVOID*)&Process);
- if (Status != STATUS_SUCCESS)
- {
- return(Status);
- }
-
- Status = ObCreateHandle(PsGetCurrentProcess(),
- Process,
- DesiredAccess,
- FALSE,
- ProcessHandle);
- ObDereferenceObject(Process);
-
- return(Status);
- }
- else
- {
- KIRQL oldIrql;
- PLIST_ENTRY current_entry;
- PEPROCESS current;
- NTSTATUS Status;
-
- KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
- current_entry = PsProcessListHead.Flink;
- while (current_entry != &PsProcessListHead)
- {
- current = CONTAINING_RECORD(current_entry, EPROCESS,
- ProcessListEntry);
- if (current->UniqueProcessId == (ULONG)ClientId->UniqueProcess)
- {
- if (current->Pcb.State == PROCESS_STATE_TERMINATED)
- {
- Status = STATUS_PROCESS_IS_TERMINATING;
- }
- else
- {
- Status = ObReferenceObjectByPointer(current,
- DesiredAccess,
- PsProcessType,
- UserMode);
- }
- KeReleaseSpinLock(&PsProcessListLock, oldIrql);
- if (NT_SUCCESS(Status))
- {
- Status = ObCreateHandle(PsGetCurrentProcess(),
- current,
- DesiredAccess,
- FALSE,
- ProcessHandle);
- ObDereferenceObject(current);
- DPRINT("*ProcessHandle %x\n", ProcessHandle);
- DPRINT("NtOpenProcess() = %x\n", Status);
- }
- return(Status);
- }
- current_entry = current_entry->Flink;
- }
- KeReleaseSpinLock(&PsProcessListLock, oldIrql);
- DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
- return(STATUS_UNSUCCESSFUL);
- }
- return(STATUS_UNSUCCESSFUL);
+ return PspCreateProcess(ProcessHandle,
+ DesiredAccess,
+ ObjectAttributes,
+ NULL, /* no parent process */
+ FALSE,
+ NULL,
+ NULL,
+ NULL);
}
-
/*
- * @unimplemented
+ * @implemented
*/
-NTSTATUS STDCALL
-NtQueryInformationProcess(IN HANDLE ProcessHandle,
- IN PROCESSINFOCLASS ProcessInformationClass,
- OUT PVOID ProcessInformation,
- IN ULONG ProcessInformationLength,
- OUT PULONG ReturnLength OPTIONAL)
+NTSTATUS
+STDCALL
+PsLookupProcessByProcessId(IN HANDLE ProcessId,
+ OUT PEPROCESS *Process)
{
- PEPROCESS Process;
- NTSTATUS Status;
-
- /*
- * TODO: Here we should probably check that ProcessInformationLength
- * bytes indeed are writable at address ProcessInformation.
- */
-
- Status = ObReferenceObjectByHandle(ProcessHandle,
- PROCESS_SET_INFORMATION,
- PsProcessType,
- UserMode,
- (PVOID*)&Process,
- NULL);
- if (Status != STATUS_SUCCESS)
- {
- return(Status);
- }
+ 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;
- switch (ProcessInformationClass)
- {
- case ProcessBasicInformation:
- if (ProcessInformationLength != sizeof(PROCESS_BASIC_INFORMATION))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
- {
- PPROCESS_BASIC_INFORMATION ProcessBasicInformationP =
- (PPROCESS_BASIC_INFORMATION)ProcessInformation;
- ProcessBasicInformationP->ExitStatus = Process->ExitStatus;
- ProcessBasicInformationP->PebBaseAddress = Process->Peb;
- ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity;
- ProcessBasicInformationP->UniqueProcessId =
- Process->UniqueProcessId;
- ProcessBasicInformationP->InheritedFromUniqueProcessId =
- (ULONG)Process->InheritedFromUniqueProcessId;
- ProcessBasicInformationP->BasePriority =
- Process->Pcb.BasePriority;
-
- if (ReturnLength)
- {
- *ReturnLength = sizeof(PROCESS_BASIC_INFORMATION);
- }
- }
- break;
-
- case ProcessQuotaLimits:
- case ProcessIoCounters:
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
- case ProcessTimes:
- if (ProcessInformationLength != sizeof(KERNEL_USER_TIMES))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
- {
- PKERNEL_USER_TIMES ProcessTimeP =
- (PKERNEL_USER_TIMES)ProcessInformation;
-
- ProcessTimeP->CreateTime = Process->CreateTime;
- ProcessTimeP->UserTime.QuadPart = Process->Pcb.UserTime * 100000LL;
- ProcessTimeP->KernelTime.QuadPart = Process->Pcb.KernelTime * 100000LL;
- ProcessTimeP->ExitTime = Process->ExitTime;
-
- if (ReturnLength)
- {
- *ReturnLength = sizeof(KERNEL_USER_TIMES);
- }
- }
- break;
-
- case ProcessDebugPort:
- case ProcessLdtInformation:
- case ProcessWorkingSetWatch:
- case ProcessWx86Information:
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
- case ProcessHandleCount:
- if (ProcessInformationLength != sizeof(ULONG))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
- {
- PULONG HandleCount = (PULONG)ProcessInformation;
- *HandleCount = ObpGetHandleCountByHandleTable(&Process->HandleTable);
- if (ReturnLength)
- {
- *ReturnLength = sizeof(ULONG);
- }
- }
- break;
-
- case ProcessSessionInformation:
- case ProcessWow64Information:
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
- case ProcessVmCounters:
- if (ProcessInformationLength != sizeof(VM_COUNTERS))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
- {
- PVM_COUNTERS pOut = (PVM_COUNTERS)ProcessInformation;
- pOut->PeakVirtualSize = Process->PeakVirtualSize;
- /*
- * Here we should probably use VirtualSize.LowPart, but due to
- * incompatibilities in current headers (no unnamed union),
- * I opted for cast.
- */
- pOut->VirtualSize = (ULONG)Process->VirtualSize.QuadPart;
- pOut->PageFaultCount = Process->Vm.PageFaultCount;
- pOut->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize;
- pOut->WorkingSetSize = Process->Vm.WorkingSetSize;
- pOut->QuotaPeakPagedPoolUsage = Process->QuotaPeakPoolUsage[0]; // TODO: Verify!
- pOut->QuotaPagedPoolUsage = Process->QuotaPoolUsage[0]; // TODO: Verify!
- pOut->QuotaPeakNonPagedPoolUsage = Process->QuotaPeakPoolUsage[1]; // TODO: Verify!
- pOut->QuotaNonPagedPoolUsage = Process->QuotaPoolUsage[1]; // TODO: Verify!
- pOut->PagefileUsage = Process->PagefileUsage;
- pOut->PeakPagefileUsage = Process->PeakPagefileUsage;
-
- if (ReturnLength)
- {
- *ReturnLength = sizeof(VM_COUNTERS);
- }
- }
- break;
-
- case ProcessDefaultHardErrorMode:
- if (ProcessInformationLength != sizeof(ULONG))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
- {
- PULONG HardErrMode = (PULONG)ProcessInformation;
- *HardErrMode = Process->DefaultHardErrorProcessing;
-
- if (ReturnLength)
- {
- *ReturnLength = sizeof(ULONG);
- }
- }
- break;
-
- case ProcessPriorityBoost:
- if (ProcessInformationLength != sizeof(ULONG))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
- {
- PULONG BoostEnabled = (PULONG)ProcessInformation;
- *BoostEnabled = Process->Pcb.DisableBoost ? FALSE : TRUE;
-
- if (ReturnLength)
- {
- *ReturnLength = sizeof(ULONG);
- }
- }
- break;
-
- case ProcessDeviceMap:
- if (ProcessInformationLength != sizeof(PROCESS_DEVICEMAP_INFORMATION))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
- {
- ObQueryDeviceMapInformation(Process, (PPROCESS_DEVICEMAP_INFORMATION)ProcessInformation);
- if (ReturnLength)
- {
- *ReturnLength = sizeof(PROCESS_DEVICEMAP_INFORMATION);
- }
- }
- break;
-
- case ProcessPriorityClass:
- if (ProcessInformationLength != sizeof(USHORT))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
- {
- PUSHORT Priority = (PUSHORT)ProcessInformation;
- *Priority = Process->PriorityClass;
-
- if (ReturnLength)
- {
- *ReturnLength = sizeof(USHORT);
- }
- }
- break;
-
- case ProcessImageFileName:
- {
- /*
- * We DO NOT return the file name stored in the EPROCESS structure.
- * Propably if we can't find a PEB or ProcessParameters structure for the
- * process!
- */
- PRTL_USER_PROCESS_PARAMETERS ProcParams;
- ASSERT(Process->Peb);
- ASSERT(Process->Peb->ProcessParameters);
- ProcParams = Process->Peb->ProcessParameters;
- if(ProcessInformationLength < sizeof(UNICODE_STRING) + ProcParams->ImagePathName.Length + sizeof(WCHAR))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
+ /* Make sure it's really a process */
+ if (FoundProcess->Pcb.Header.Type == ProcessObject)
{
- PUNICODE_STRING DstPath = (PUNICODE_STRING)ProcessInformation;
- DstPath->Length = ProcParams->ImagePathName.Length;
- DstPath->MaximumLength = DstPath->Length + sizeof(WCHAR);
- DstPath->Buffer = (PWSTR)(DstPath + 1);
-
- RtlCopyMemory(DstPath->Buffer, ProcParams->ImagePathName.Buffer, ProcParams->ImagePathName.Length);
- DstPath->Buffer[DstPath->Length / sizeof(WCHAR)] = L'\0';
+ /* Reference and return it */
+ ObReferenceObject(FoundProcess);
+ *Process = FoundProcess;
+ Status = STATUS_SUCCESS;
}
- break;
- }
- /*
- * Note: The following 10 information classes are verified to not be
- * implemented on NT, and do indeed return STATUS_INVALID_INFO_CLASS;
- */
- case ProcessBasePriority:
- case ProcessRaisePriority:
- case ProcessExceptionPort:
- case ProcessAccessToken:
- case ProcessLdtSize:
- case ProcessIoPortHandlers:
- case ProcessUserModeIOPL:
- case ProcessEnableAlignmentFaultFixup:
- case ProcessAffinityMask:
- case ProcessForegroundInformation:
- default:
- Status = STATUS_INVALID_INFO_CLASS;
- }
- ObDereferenceObject(Process);
- return(Status);
-}
+ /* Unlock the Entry */
+ ExUnlockHandleTableEntry(PspCidTable, CidEntry);
+ }
+
+ KeLeaveCriticalRegion();
+ /* Return to caller */
+ return Status;
+}
+/*
+ * @implemented
+ */
NTSTATUS
-PspAssignPrimaryToken(PEPROCESS Process,
- HANDLE TokenHandle)
+STDCALL
+PsLookupProcessThreadByCid(IN PCLIENT_ID Cid,
+ OUT PEPROCESS *Process OPTIONAL,
+ OUT PETHREAD *Thread)
{
- PACCESS_TOKEN Token;
- PACCESS_TOKEN OldToken;
- NTSTATUS Status;
-
- Status = ObReferenceObjectByHandle(TokenHandle,
- 0,
- SepTokenObjectType,
- UserMode,
- (PVOID*)&Token,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- Status = SeExchangePrimaryToken(Process, Token, &OldToken);
- if (NT_SUCCESS(Status))
- {
- ObDereferenceObject(OldToken);
- }
- ObDereferenceObject(Token);
- return(Status);
+ 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;
}
/*
- * @unimplemented
+ * FUNCTION: Returns a pointer to the current process
+ *
+ * @implemented
*/
-NTSTATUS STDCALL
-NtSetInformationProcess(IN HANDLE ProcessHandle,
- IN PROCESSINFOCLASS ProcessInformationClass,
- IN PVOID ProcessInformation,
- IN ULONG ProcessInformationLength)
+PEPROCESS STDCALL
+IoGetCurrentProcess(VOID)
{
- PEPROCESS Process;
- NTSTATUS Status;
- PHANDLE ProcessAccessTokenP;
-
- Status = ObReferenceObjectByHandle(ProcessHandle,
- PROCESS_SET_INFORMATION,
- PsProcessType,
- UserMode,
- (PVOID*)&Process,
- NULL);
- if (!NT_SUCCESS(Status))
+ if (PsGetCurrentThread() == NULL ||
+ PsGetCurrentThread()->Tcb.ApcState.Process == NULL)
{
- return(Status);
+ return(PsInitialSystemProcess);
}
-
- switch (ProcessInformationClass)
+ else
{
- case ProcessQuotaLimits:
- case ProcessBasePriority:
- case ProcessRaisePriority:
- case ProcessDebugPort:
- case ProcessExceptionPort:
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
- case ProcessAccessToken:
- ProcessAccessTokenP = (PHANDLE)ProcessInformation;
- Status = PspAssignPrimaryToken(Process, *ProcessAccessTokenP);
- break;
-
- case ProcessLdtInformation:
- case ProcessLdtSize:
- case ProcessDefaultHardErrorMode:
- case ProcessIoPortHandlers:
- case ProcessWorkingSetWatch:
- case ProcessUserModeIOPL:
- case ProcessEnableAlignmentFaultFixup:
- case ProcessPriorityClass:
- case ProcessAffinityMask:
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
- case ProcessBasicInformation:
- case ProcessIoCounters:
- case ProcessTimes:
- case ProcessPooledUsageAndLimits:
- case ProcessWx86Information:
- case ProcessHandleCount:
- case ProcessWow64Information:
- default:
- Status = STATUS_INVALID_INFO_CLASS;
+ return(PEPROCESS)(PsGetCurrentThread()->Tcb.ApcState.Process);
}
- ObDereferenceObject(Process);
- return(Status);
-}
-
-
-/**********************************************************************
- * NAME INTERNAL
- * PiQuerySystemProcessInformation
- *
- * DESCRIPTION
- * Compute the size of a process+thread snapshot as
- * expected by NtQuerySystemInformation.
- *
- * RETURN VALUE
- * 0 on error; otherwise the size, in bytes of the buffer
- * required to write a full snapshot.
- *
- * NOTE
- * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
- */
-NTSTATUS
-PiQuerySystemProcessInformation(PVOID Buffer,
- ULONG Size,
- PULONG ReqSize)
-{
- return STATUS_NOT_IMPLEMENTED;
-
-#if 0
- KIRQL OldIrql;
- PLIST_ENTRY CurrentEntryP;
- PEPROCESS CurrentP;
- PLIST_ENTRY CurrentEntryT;
- PETHREAD CurrentT;
-
- ULONG RequiredSize = 0L;
- BOOLEAN SizeOnly = FALSE;
-
- ULONG SpiSize = 0L;
-
- PSYSTEM_PROCESS_INFORMATION pInfoP = (PSYSTEM_PROCESS_INFORMATION) SnapshotBuffer;
- PSYSTEM_PROCESS_INFORMATION pInfoPLast = NULL;
- PSYSTEM_THREAD_INFO pInfoT = NULL;
-
-
- /* Lock the process list. */
- KeAcquireSpinLock(&PsProcessListLock,
- &OldIrql);
-
- /*
- * Scan the process list. Since the
- * list is circular, the guard is false
- * after the last process.
- */
- for ( CurrentEntryP = PsProcessListHead.Flink;
- (CurrentEntryP != & PsProcessListHead);
- CurrentEntryP = CurrentEntryP->Flink
- )
- {
- /*
- * Compute how much space is
- * occupied in the snapshot
- * by adding this process info.
- * (at least one thread).
- */
- SpiSizeCurrent = sizeof (SYSTEM_PROCESS_INFORMATION);
- RequiredSize += SpiSizeCurrent;
- /*
- * Do not write process data in the
- * buffer if it is too small.
- */
- if (TRUE == SizeOnly) continue;
- /*
- * Check if the buffer can contain
- * the full snapshot.
- */
- if (Size < RequiredSize)
- {
- SizeOnly = TRUE;
- continue;
- }
- /*
- * Get a reference to the
- * process descriptor we are
- * handling.
- */
- CurrentP = CONTAINING_RECORD(
- CurrentEntryP,
- EPROCESS,
- ProcessListEntry
- );
- /*
- * Write process data in the buffer.
- */
- RtlZeroMemory (pInfoP, sizeof (SYSTEM_PROCESS_INFORMATION));
- /* PROCESS */
- pInfoP->ThreadCount = 0L;
- pInfoP->ProcessId = CurrentP->UniqueProcessId;
- RtlInitUnicodeString (
- & pInfoP->Name,
- CurrentP->ImageFileName
- );
- /* THREAD */
- for ( pInfoT = & CurrentP->ThreadSysInfo [0],
- CurrentEntryT = CurrentP->ThreadListHead.Flink;
-
- (CurrentEntryT != & CurrentP->ThreadListHead);
-
- pInfoT = & CurrentP->ThreadSysInfo [pInfoP->ThreadCount],
- CurrentEntryT = CurrentEntryT->Flink
- )
- {
- /*
- * Recalculate the size of the
- * information block.
- */
- if (0 < pInfoP->ThreadCount)
- {
- RequiredSize += sizeof (SYSTEM_THREAD_INFORMATION);
- }
- /*
- * Do not write thread data in the
- * buffer if it is too small.
- */
- if (TRUE == SizeOnly) continue;
- /*
- * Check if the buffer can contain
- * the full snapshot.
- */
- if (Size < RequiredSize)
- {
- SizeOnly = TRUE;
- continue;
- }
- /*
- * Get a reference to the
- * thread descriptor we are
- * handling.
- */
- CurrentT = CONTAINING_RECORD(
- CurrentEntryT,
- KTHREAD,
- ThreadListEntry
- );
- /*
- * Write thread data.
- */
- RtlZeroMemory (
- pInfoT,
- sizeof (SYSTEM_THREAD_INFORMATION)
- );
- pInfoT->KernelTime = CurrentT-> ; /* TIME */
- pInfoT->UserTime = CurrentT-> ; /* TIME */
- pInfoT->CreateTime = CurrentT-> ; /* TIME */
- pInfoT->TickCount = CurrentT-> ; /* ULONG */
- pInfoT->StartEIP = CurrentT-> ; /* ULONG */
- pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
- pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
- pInfoT->DynamicPriority = CurrentT-> ; /* ULONG */
- pInfoT->BasePriority = CurrentT-> ; /* ULONG */
- pInfoT->nSwitches = CurrentT-> ; /* ULONG */
- pInfoT->State = CurrentT-> ; /* DWORD */
- pInfoT->WaitReason = CurrentT-> ; /* KWAIT_REASON */
- /*
- * Count the number of threads
- * this process has.
- */
- ++ pInfoP->ThreadCount;
- }
- /*
- * Save the size of information
- * stored in the buffer for the
- * current process.
- */
- pInfoP->RelativeOffset = SpiSize;
- /*
- * Save a reference to the last
- * valid information block.
- */
- pInfoPLast = pInfoP;
- /*
- * Compute the offset of the
- * SYSTEM_PROCESS_INFORMATION
- * descriptor in the snapshot
- * buffer for the next process.
- */
- (ULONG) pInfoP += SpiSize;
- }
- /*
- * Unlock the process list.
- */
- KeReleaseSpinLock (
- & PsProcessListLock,
- OldIrql
- );
- /*
- * Return the proper error status code,
- * if the buffer was too small.
- */
- if (TRUE == SizeOnly)
- {
- if (NULL != RequiredSize)
- {
- *pRequiredSize = RequiredSize;
- }
- return STATUS_INFO_LENGTH_MISMATCH;
- }
- /*
- * Mark the end of the snapshot.
- */
- pInfoP->RelativeOffset = 0L;
- /* OK */
- return STATUS_SUCCESS;
-#endif
}
/*
*/
LONGLONG
STDCALL
-PsGetProcessCreateTimeQuadPart(
- PEPROCESS Process
- )
+PsGetProcessCreateTimeQuadPart(PEPROCESS Process)
{
- return Process->CreateTime.QuadPart;
+ return Process->CreateTime.QuadPart;
}
/*
*/
PVOID
STDCALL
-PsGetProcessDebugPort(
- PEPROCESS Process
- )
+PsGetProcessDebugPort(PEPROCESS Process)
{
- return Process->DebugPort;
+ return Process->DebugPort;
}
/*
*/
BOOLEAN
STDCALL
-PsGetProcessExitProcessCalled(
- PEPROCESS Process
- )
+PsGetProcessExitProcessCalled(PEPROCESS Process)
{
- return Process->ExitProcessCalled;
+ return Process->ProcessExiting;
}
/*
*/
NTSTATUS
STDCALL
-PsGetProcessExitStatus(
- PEPROCESS Process
- )
+PsGetProcessExitStatus(PEPROCESS Process)
{
- return Process->ExitStatus;
+ return Process->ExitStatus;
}
/*
*/
HANDLE
STDCALL
-PsGetProcessId(
- PEPROCESS Process
- )
+PsGetProcessId(PEPROCESS Process)
{
- return (HANDLE)Process->UniqueProcessId;
+ return (HANDLE)Process->UniqueProcessId;
}
/*
*/
LPSTR
STDCALL
-PsGetProcessImageFileName(
- PEPROCESS Process
- )
+PsGetProcessImageFileName(PEPROCESS Process)
{
- return (LPSTR)Process->ImageFileName;
+ return (LPSTR)Process->ImageFileName;
}
/*
*/
HANDLE
STDCALL
-PsGetProcessInheritedFromUniqueProcessId(
- PEPROCESS Process
- )
+PsGetProcessInheritedFromUniqueProcessId(PEPROCESS Process)
{
- return Process->InheritedFromUniqueProcessId;
+ return Process->InheritedFromUniqueProcessId;
}
/*
*/
PEJOB
STDCALL
-PsGetProcessJob(
- PEPROCESS Process
- )
+PsGetProcessJob(PEPROCESS Process)
{
- return Process->Job;
+ return Process->Job;
}
/*
*/
PPEB
STDCALL
-PsGetProcessPeb(
- PEPROCESS Process
- )
+PsGetProcessPeb(PEPROCESS Process)
{
- return Process->Peb;
+ return Process->Peb;
}
/*
*/
ULONG
STDCALL
-PsGetProcessPriorityClass(
- PEPROCESS Process
- )
-{
- return Process->PriorityClass;
-}
-
-/*
- * @implemented
- */
-PVOID
-STDCALL
-PsGetProcessSectionBaseAddress(
- PEPROCESS Process
- )
+PsGetProcessPriorityClass(PEPROCESS Process)
{
- return Process->SectionBaseAddress;
+ return Process->PriorityClass;
}
/*
* @implemented
*/
-PVOID
-STDCALL
-PsGetProcessSecurityPort(
- PEPROCESS Process
- )
+HANDLE STDCALL
+PsGetCurrentProcessId(VOID)
{
- return Process->SecurityPort;
+ return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
}
/*
* @implemented
*/
-HANDLE
+ULONG
STDCALL
-PsGetProcessSessionId(
- PEPROCESS Process
- )
+PsGetCurrentProcessSessionId(VOID)
{
- return (HANDLE)Process->SessionId;
+ return PsGetCurrentProcess()->Session;
}
/*
*/
PVOID
STDCALL
-PsGetProcessWin32Process(
- PEPROCESS Process
- )
+PsGetProcessSectionBaseAddress(PEPROCESS Process)
{
- return Process->Win32Process;
+ return Process->SectionBaseAddress;
}
/*
*/
PVOID
STDCALL
-PsGetProcessWin32WindowStation(
- PEPROCESS Process
- )
+PsGetProcessSecurityPort(PEPROCESS Process)
{
- return Process->Win32WindowStation;
+ return Process->SecurityPort;
}
/*
* @implemented
*/
-BOOLEAN
+HANDLE
STDCALL
-PsIsProcessBeingDebugged(
- PEPROCESS Process
- )
+PsGetProcessSessionId(PEPROCESS Process)
{
- return FALSE/*Process->IsProcessBeingDebugged*/;
+ return (HANDLE)Process->Session;
}
-
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-PsLookupProcessByProcessId(IN PVOID ProcessId,
- OUT PEPROCESS *Process)
+struct _W32THREAD*
+STDCALL
+PsGetWin32Thread(VOID)
{
- KIRQL oldIrql;
- PLIST_ENTRY current_entry;
- PEPROCESS current;
-
- KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
-
- current_entry = PsProcessListHead.Flink;
- while (current_entry != &PsProcessListHead)
- {
- current = CONTAINING_RECORD(current_entry,
- EPROCESS,
- ProcessListEntry);
- if (current->UniqueProcessId == (ULONG)ProcessId)
- {
- *Process = current;
- ObReferenceObject(current);
- KeReleaseSpinLock(&PsProcessListLock, oldIrql);
- return(STATUS_SUCCESS);
- }
- current_entry = current_entry->Flink;
- }
-
- KeReleaseSpinLock(&PsProcessListLock, oldIrql);
-
- return(STATUS_INVALID_PARAMETER);
+ return(PsGetCurrentThread()->Tcb.Win32Thread);
}
-VOID
+struct _W32PROCESS*
STDCALL
-PspRunCreateProcessNotifyRoutines
-(
- PEPROCESS CurrentProcess,
- BOOLEAN Create
-)
+PsGetWin32Process(VOID)
{
- ULONG i;
- HANDLE ProcessId = (HANDLE)CurrentProcess->UniqueProcessId;
- HANDLE ParentId = CurrentProcess->InheritedFromUniqueProcessId;
-
- for(i = 0; i < MAX_PROCESS_NOTIFY_ROUTINE_COUNT; ++ i)
- if(PiProcessNotifyRoutine[i])
- PiProcessNotifyRoutine[i](ParentId, ProcessId, Create);
+ return (struct _W32PROCESS*)PsGetCurrentProcess()->Win32Process;
}
/*
* @implemented
*/
-NTSTATUS STDCALL
-PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
- IN BOOLEAN Remove)
-{
- ULONG i;
-
- if (Remove)
- {
- for(i=0;i<MAX_PROCESS_NOTIFY_ROUTINE_COUNT;i++)
- {
- if ((PVOID)PiProcessNotifyRoutine[i] == (PVOID)NotifyRoutine)
- {
- PiProcessNotifyRoutine[i] = NULL;
- break;
- }
- }
-
- return(STATUS_SUCCESS);
- }
-
- /*insert*/
- for(i=0;i<MAX_PROCESS_NOTIFY_ROUTINE_COUNT;i++)
- {
- if (PiProcessNotifyRoutine[i] == NULL)
- {
- PiProcessNotifyRoutine[i] = NotifyRoutine;
- break;
- }
- }
-
- if (i == MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- return STATUS_SUCCESS;
-}
-
-VOID STDCALL
-PspRunLoadImageNotifyRoutines(
- PUNICODE_STRING FullImageName,
- HANDLE ProcessId,
- PIMAGE_INFO ImageInfo)
-{
- ULONG i;
-
- for (i = 0; i < MAX_PROCESS_NOTIFY_ROUTINE_COUNT; ++ i)
- if (PiLoadImageNotifyRoutine[i])
- PiLoadImageNotifyRoutine[i](FullImageName, ProcessId, ImageInfo);
-}
-
-/*
- * @unimplemented
- */
-NTSTATUS
+PVOID
STDCALL
-PsRemoveLoadImageNotifyRoutine(
- IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
- )
+PsGetProcessWin32Process(PEPROCESS Process)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ return Process->Win32Process;
}
/*
* @implemented
*/
-NTSTATUS STDCALL
-PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine)
-{
- ULONG i;
-
- for (i = 0; i < MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT; i++)
- {
- if (PiLoadImageNotifyRoutine[i] == NULL)
- {
- PiLoadImageNotifyRoutine[i] = NotifyRoutine;
- break;
- }
- }
-
- if (i == MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- return STATUS_SUCCESS;
-}
-
-/*
- * @implemented
- */
-VOID
+PVOID
STDCALL
-PsSetProcessPriorityClass(
- PEPROCESS Process,
- ULONG PriorityClass
- )
+PsGetProcessWin32WindowStation(PEPROCESS Process)
{
- Process->PriorityClass = PriorityClass;
+ return Process->Win32WindowStation;
}
/*
* @implemented
- */
-VOID
+ */
+BOOLEAN
STDCALL
-PsSetProcessSecurityPort(
- PEPROCESS Process,
- PVOID SecurityPort
- )
+PsIsProcessBeingDebugged(PEPROCESS Process)
{
- Process->SecurityPort = SecurityPort;
+ return FALSE; //Process->IsProcessBeingDebugged;
}
/*
*/
VOID
STDCALL
-PsSetProcessWin32Process(
- PEPROCESS Process,
- PVOID Win32Process
- )
+PsSetProcessPriorityClass(PEPROCESS Process,
+ ULONG PriorityClass)
{
- Process->Win32Process = Win32Process;
+ Process->PriorityClass = PriorityClass;
}
/*
*/
VOID
STDCALL
-PsSetProcessWin32WindowStation(
- PEPROCESS Process,
- PVOID WindowStation
- )
+PsSetProcessSecurityPort(PEPROCESS Process,
+ PVOID SecurityPort)
{
- Process->Win32WindowStation = WindowStation;
+ Process->SecurityPort = SecurityPort;
}
-/* Pool Quotas */
/*
* @implemented
*/
VOID
STDCALL
-PsChargePoolQuota(
- IN PEPROCESS Process,
- IN POOL_TYPE PoolType,
- IN ULONG_PTR Amount
- )
+PsSetProcessWin32Process(PEPROCESS Process,
+ PVOID Win32Process)
{
- NTSTATUS Status;
-
- /* Charge the usage */
- Status = PsChargeProcessPoolQuota(Process, PoolType, Amount);
-
- /* Raise Exception */
- if (!NT_SUCCESS(Status)) {
- ExRaiseStatus(Status);
- }
+ Process->Win32Process = Win32Process;
}
/*
* @implemented
*/
-NTSTATUS
+VOID
STDCALL
-PsChargeProcessNonPagedPoolQuota (
- IN PEPROCESS Process,
- IN ULONG_PTR Amount
- )
+PsSetProcessWindowStation(PEPROCESS Process,
+ PVOID WindowStation)
{
- /* Call the general function */
- return PsChargeProcessPoolQuota(Process, NonPagedPool, Amount);
+ Process->Win32WindowStation = WindowStation;
}
/*
- * @implemented
+ * @unimplemented
*/
NTSTATUS
STDCALL
-PsChargeProcessPagedPoolQuota (
- IN PEPROCESS Process,
- IN ULONG_PTR Amount
- )
+PsSetProcessPriorityByClass(IN PEPROCESS Process,
+ IN ULONG Type)
{
- /* Call the general function */
- return PsChargeProcessPoolQuota(Process, PagedPool, Amount);
+ 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
-PsChargeProcessPoolQuota(
- IN PEPROCESS Process,
- IN POOL_TYPE PoolType,
- IN ULONG_PTR Amount
- )
+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)
{
- PEPROCESS_QUOTA_BLOCK QuotaBlock;
- ULONG NewUsageSize;
- ULONG NewMaxQuota;
-
- /* Get current Quota Block */
- QuotaBlock = Process->QuotaBlock;
-
- /* Quota Operations are not to be done on the SYSTEM Process */
- if (Process == PsInitialSystemProcess) return STATUS_SUCCESS;
-
- /* New Size in use */
- NewUsageSize = QuotaBlock->QuotaEntry[PoolType].Usage + Amount;
-
- /* Does this size respect the quota? */
- if (NewUsageSize > QuotaBlock->QuotaEntry[PoolType].Limit) {
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
- /* It doesn't, so keep raising the Quota */
- while (MiRaisePoolQuota(PoolType, QuotaBlock->QuotaEntry[PoolType].Limit, &NewMaxQuota)) {
- /* Save new Maximum Quota */
- QuotaBlock->QuotaEntry[PoolType].Limit = NewMaxQuota;
+ PAGED_CODE();
- /* See if the new Maximum Quota fulfills our need */
- if (NewUsageSize <= NewMaxQuota) goto QuotaChanged;
+ /* Check parameters */
+ if(PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWriteHandle(ProcessHandle);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
}
+ _SEH_END;
- return STATUS_QUOTA_EXCEEDED;
+ if(!NT_SUCCESS(Status)) return Status;
}
-QuotaChanged:
- /* Save new Usage */
- QuotaBlock->QuotaEntry[PoolType].Usage = NewUsageSize;
-
- /* Is this a new peak? */
- if (NewUsageSize > QuotaBlock->QuotaEntry[PoolType].Peak) {
- QuotaBlock->QuotaEntry[PoolType].Peak = NewUsageSize;
+ /* 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);
}
- /* All went well */
- return STATUS_SUCCESS;
+ /* Return Status */
+ return Status;
}
/*
- * @unimplemented
- */
-VOID
+ * @implemented
+ */
+NTSTATUS
STDCALL
-PsReturnPoolQuota(
- IN PEPROCESS Process,
- IN POOL_TYPE PoolType,
- IN ULONG_PTR Amount
- )
+NtOpenProcess(OUT PHANDLE ProcessHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN PCLIENT_ID ClientId)
{
- UNIMPLEMENTED;
-}
+ KPROCESSOR_MODE PreviousMode;
+ CLIENT_ID SafeClientId;
+ ULONG Attributes = 0;
+ HANDLE hProcess;
+ BOOLEAN HasObjectName = FALSE;
+ PETHREAD Thread = NULL;
+ PEPROCESS Process = NULL;
+ NTSTATUS Status = STATUS_SUCCESS;
-/*
- * @unimplemented
- */
-VOID
-STDCALL
-PsReturnProcessNonPagedPoolQuota(
- IN PEPROCESS Process,
- IN ULONG_PTR Amount
- )
-{
- UNIMPLEMENTED;
-}
+ PAGED_CODE();
-/*
- * @unimplemented
- */
-VOID
-STDCALL
-PsReturnProcessPagedPoolQuota(
- IN PEPROCESS Process,
- IN ULONG_PTR Amount
- )
-{
- UNIMPLEMENTED;
-}
+ PreviousMode = KeGetPreviousMode();
-NTSTATUS
-PsLockProcess(PEPROCESS Process, BOOL Timeout)
-{
- ULONG Attempts = 0;
- PKTHREAD PrevLockOwner;
- NTSTATUS Status = STATUS_UNSUCCESSFUL;
- PLARGE_INTEGER Delay = (Timeout ? &PsLockTimeout : NULL);
- PKTHREAD CallingThread = KeGetCurrentThread();
-
- KeEnterCriticalRegion();
-
- for(;;)
- {
- if(Process->Pcb.State == PROCESS_STATE_TERMINATED)
+ /* 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
{
- KeLeaveCriticalRegion();
- return STATUS_PROCESS_IS_TERMINATING;
+ HasObjectName = (ObjectAttributes->ObjectName != NULL);
+ Attributes = ObjectAttributes->Attributes;
}
- PrevLockOwner = (PKTHREAD)InterlockedCompareExchangePointer(
- &Process->LockOwner, CallingThread, NULL);
- if(PrevLockOwner == NULL || PrevLockOwner == CallingThread)
+ if (HasObjectName && ClientId != NULL)
{
- /* we got the lock or already locked it */
- if(InterlockedIncrementUL(&Process->LockCount) == 1)
- {
- KeClearEvent(&Process->LockEvent);
- }
+ /* can't pass both, n object name and a client id */
+ return STATUS_INVALID_PARAMETER_MIX;
+ }
- return STATUS_SUCCESS;
+ /* 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
{
- if(++Attempts > 2)
- {
- Status = KeWaitForSingleObject(&Process->LockEvent,
- Executive,
- KernelMode,
- FALSE,
- Delay);
- if(Status == STATUS_TIMEOUT)
+ /* 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
{
- KeLeaveCriticalRegion();
- break;
+ *ProcessHandle = hProcess;
}
- }
- else
- {
- KeDelayExecutionThread(KernelMode, FALSE, &ShortPsLockDelay);
- }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
}
- }
-
- return Status;
-}
-VOID
-PsUnlockProcess(PEPROCESS Process)
-{
- ASSERT(Process->LockOwner == KeGetCurrentThread());
-
- if(InterlockedDecrementUL(&Process->LockCount) == 0)
- {
- InterlockedExchangePointer(&Process->LockOwner, NULL);
- KeSetEvent(&Process->LockEvent, IO_NO_INCREMENT, FALSE);
- }
-
- KeLeaveCriticalRegion();
+ return Status;
}
-
/* EOF */