-/* $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;
-
-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};
-
-static const INFORMATION_CLASS_INFO PsProcessInfoClass[] =
-{
- ICI_SQ_SAME( sizeof(PROCESS_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* ProcessBasicInformation */
- ICI_SQ_SAME( sizeof(QUOTA_LIMITS), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessQuotaLimits */
- ICI_SQ_SAME( sizeof(IO_COUNTERS), sizeof(ULONG), ICIF_QUERY ), /* ProcessIoCounters */
- ICI_SQ_SAME( sizeof(VM_COUNTERS), sizeof(ULONG), ICIF_QUERY ), /* ProcessVmCounters */
- ICI_SQ_SAME( sizeof(KERNEL_USER_TIMES), sizeof(ULONG), ICIF_QUERY ), /* ProcessTimes */
- ICI_SQ_SAME( sizeof(KPRIORITY), sizeof(USHORT), ICIF_SET ), /* ProcessBasePriority */
- ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_SET ), /* ProcessRaisePriority */
- ICI_SQ_SAME( sizeof(HANDLE), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessDebugPort */
- ICI_SQ_SAME( sizeof(HANDLE), sizeof(ULONG), ICIF_SET ), /* ProcessExceptionPort */
- ICI_SQ_SAME( sizeof(PROCESS_ACCESS_TOKEN), sizeof(USHORT), ICIF_SET ), /* ProcessAccessToken */
- ICI_SQ_SAME( 0 /* FIXME */, sizeof(USHORT), ICIF_QUERY | ICIF_SET ), /* ProcessLdtInformation */
- ICI_SQ_SAME( 0 /* FIXME */, sizeof(USHORT), ICIF_SET ), /* ProcessLdtSize */
- ICI_SQ_SAME( sizeof(ULONG), sizeof(USHORT), ICIF_QUERY | ICIF_SET ), /* ProcessDefaultHardErrorMode */
- ICI_SQ_SAME( 0 /* FIXME */, sizeof(USHORT), ICIF_SET ), /* ProcessIoPortHandlers */
- ICI_SQ_SAME( sizeof(POOLED_USAGE_AND_LIMITS), sizeof(ULONG), ICIF_QUERY ), /* ProcessPooledUsageAndLimits */
- ICI_SQ_SAME( sizeof(PROCESS_WS_WATCH_INFORMATION), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessWorkingSetWatch */
- ICI_SQ_SAME( 0 /* FIXME */, sizeof(USHORT), ICIF_SET ), /* ProcessUserModeIOPL */
- ICI_SQ_SAME( sizeof(BOOLEAN), sizeof(USHORT), ICIF_SET ), /* ProcessEnableAlignmentFaultFixup */
- ICI_SQ_SAME( sizeof(PROCESS_PRIORITY_CLASS), sizeof(USHORT), ICIF_SET ), /* ProcessPriorityClass */
- ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY ), /* ProcessWx86Information */
- ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY ), /* ProcessHandleCount */
- ICI_SQ_SAME( sizeof(KAFFINITY), sizeof(USHORT), ICIF_SET ), /* ProcessAffinityMask */
- ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessPriorityBoost */
-
- ICI_SQ(/*Q*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION)0x0)->Query), /* ProcessDeviceMap */
- /*S*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION)0x0)->Set),
- /*Q*/ sizeof(USHORT),
- /*S*/ sizeof(USHORT),
- ICIF_QUERY | ICIF_SET ),
-
- ICI_SQ_SAME( sizeof(PROCESS_SESSION_INFORMATION), sizeof(USHORT), ICIF_QUERY | ICIF_SET ), /* ProcessSessionInformation */
- ICI_SQ_SAME( sizeof(BOOLEAN), sizeof(USHORT), ICIF_SET ), /* ProcessForegroundInformation */
- ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY ), /* ProcessWow64Information */
- ICI_SQ_SAME( sizeof(UNICODE_STRING), sizeof(ULONG), ICIF_QUERY | ICIF_SIZE_VARIABLE), /* ProcessImageFileName */
-};
-
-#define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8
-#define MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT 8
-
-static PCREATE_PROCESS_NOTIFY_ROUTINE
-PiProcessNotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT];
-static PLOAD_IMAGE_NOTIFY_ROUTINE
-PiLoadImageNotifyRoutine[MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT];
-
-
-typedef struct
-{
- WORK_QUEUE_ITEM WorkQueueItem;
- KEVENT Event;
- PEPROCESS Process;
- BOOLEAN IsWorkerQueue;
-} DEL_CONTEXT, *PDEL_CONTEXT;
-
-/* FUNCTIONS *****************************************************************/
-
-VOID
-STDCALL
-PsExitSpecialApc(PKAPC Apc,
- PKNORMAL_ROUTINE *NormalRoutine,
- PVOID *NormalContext,
- PVOID *SystemArgument1,
- PVOID *SystemArgument2)
-{
-}
-
-PEPROCESS
-PsGetNextProcess(PEPROCESS OldProcess)
-{
- 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);
-}
-
+EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock;
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-NtOpenProcessToken(IN HANDLE ProcessHandle,
- IN ACCESS_MASK DesiredAccess,
- OUT PHANDLE TokenHandle)
-{
- return NtOpenProcessTokenEx(ProcessHandle,
- DesiredAccess,
- 0,
- TokenHandle);
-}
+LIST_ENTRY PsActiveProcessHead;
+FAST_MUTEX PspActiveProcessMutex;
+LARGE_INTEGER ShortPsLockDelay, PsLockTimeout;
+/* INTERNAL FUNCTIONS *****************************************************************/
-/*
- * @unimplemented
- */
NTSTATUS
-STDCALL
-NtOpenProcessTokenEx(
- IN HANDLE ProcessHandle,
- IN ACCESS_MASK DesiredAccess,
- IN ULONG HandleAttributes,
- OUT PHANDLE TokenHandle
- )
+NTAPI
+PsLockProcess(PEPROCESS Process, BOOLEAN Timeout)
{
- PACCESS_TOKEN Token;
- HANDLE hToken;
- NTSTATUS Status;
+ ULONG Attempts = 0;
+ PKTHREAD PrevLockOwner;
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+ PLARGE_INTEGER Delay = (Timeout ? &PsLockTimeout : NULL);
+ PKTHREAD CallingThread = KeGetCurrentThread();
- 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);
-}
+ PAGED_CODE();
+ KeEnterCriticalRegion();
-/*
- * @implemented
- */
-PACCESS_TOKEN STDCALL
-PsReferencePrimaryToken(PEPROCESS Process)
-{
- ObReferenceObjectByPointer(Process->Token,
- TOKEN_ALL_ACCESS,
- SepTokenObjectType,
- UserMode);
- return(Process->Token);
-}
+ 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);
+ }
+ }
+ }
-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);
+ return Status;
}
-
-VOID
-PiKillMostProcesses(VOID)
+VOID
+NTAPI
+PsUnlockProcess(PEPROCESS Process)
{
- 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);
-}
+ PAGED_CODE();
+ ASSERT(Process->LockOwner == KeGetCurrentThread());
-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
+ if(InterlockedDecrementUL(&Process->LockCount) == 0)
+ {
+ InterlockedExchangePointer(&Process->LockOwner, NULL);
+ KeSetEvent(&Process->LockEvent, IO_NO_INCREMENT, FALSE);
+ }
- 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);
+ KeLeaveCriticalRegion();
}
-VOID STDCALL
-PiDeleteProcessWorker(PVOID pContext)
+PEPROCESS
+STDCALL
+PsGetNextProcess(PEPROCESS OldProcess)
{
- KIRQL oldIrql;
- PDEL_CONTEXT Context;
- PEPROCESS CurrentProcess;
- PEPROCESS Process;
-
- Context = (PDEL_CONTEXT)pContext;
- Process = Context->Process;
- CurrentProcess = PsGetCurrentProcess();
-
- DPRINT("PiDeleteProcess(ObjectBody %x)\n",Process);
+ PEPROCESS NextProcess;
+ NTSTATUS Status;
- if (CurrentProcess != Process)
+ /* Check if we have a previous process */
+ if (OldProcess == NULL)
{
- KeAttachProcess(&Process->Pcb);
- }
-
- KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
- RemoveEntryList(&Process->ProcessListEntry);
- KeReleaseSpinLock(&PsProcessListLock, oldIrql);
-
- /* KDB hook */
- KDB_DELETEPROCESS_HOOK(Process);
-
- ObDereferenceObject(Process->Token);
- ObDeleteHandleTable(Process);
+ /* 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);
+ }
- if (CurrentProcess != Process)
- {
- KeDetachProcess();
+ return PsIdleProcess;
}
- MmReleaseMmInfo(Process);
- if (Context->IsWorkerQueue)
- {
- KeSetEvent(&Context->Event, IO_NO_INCREMENT, FALSE);
- }
-}
+ /* Acquire the Active Process Lock */
+ ExAcquireFastMutex(&PspActiveProcessMutex);
-VOID STDCALL
-PiDeleteProcess(PVOID ObjectBody)
-{
- DEL_CONTEXT Context;
-
- Context.Process = (PEPROCESS)ObjectBody;
+ /* Start at the previous process */
+ NextProcess = OldProcess;
- if (PsGetCurrentProcess() == Context.Process ||
- PsGetCurrentThread()->ThreadsProcess == Context.Process)
+ /* Loop until we fail */
+ while (1)
{
- KEBUGCHECK(0);
- }
+ /* Get the Process Link */
+ PLIST_ENTRY Flink = (NextProcess == PsIdleProcess ? PsActiveProcessHead.Flink :
+ NextProcess->ActiveProcessLinks.Flink);
- if (PsGetCurrentThread()->ThreadsProcess == PsGetCurrentProcess())
- {
- Context.IsWorkerQueue = FALSE;
- PiDeleteProcessWorker(&Context);
- }
- else
- {
- Context.IsWorkerQueue = TRUE;
- KeInitializeEvent(&Context.Event, NotificationEvent, FALSE);
- ExInitializeWorkItem (&Context.WorkQueueItem, PiDeleteProcessWorker, &Context);
- ExQueueWorkItem(&Context.WorkQueueItem, HyperCriticalWorkQueue);
- if (KeReadStateEvent(&Context.Event) == 0)
+ /* Move to the next Process if we're not back at the beginning */
+ if (Flink != &PsActiveProcessHead)
{
- KeWaitForSingleObject(&Context.Event, Executive, KernelMode, FALSE, NULL);
- }
- }
+ NextProcess = CONTAINING_RECORD(Flink, EPROCESS, ActiveProcessLinks);
+ }
+ else
+ {
+ NextProcess = NULL;
+ break;
+ }
- if(((PEPROCESS)ObjectBody)->Win32Process != NULL)
- {
- /* delete the W32PROCESS structure if there's one associated */
- ExFreePool (((PEPROCESS)ObjectBody)->Win32Process);
- }
-}
+ /* Reference the Process */
+ Status = ObReferenceObjectByPointer(NextProcess,
+ PROCESS_ALL_ACCESS,
+ PsProcessType,
+ KernelMode);
-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))
- {
- DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
- return(Status);
- }
- 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))
- {
- DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
- return(Status);
- }
- 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))
- {
- DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status);
- return(Status);
+ /* Exit the loop if the reference worked, keep going if there's an error */
+ if (NT_SUCCESS(Status)) break;
}
- 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;
+ /* Release the lock */
+ ExReleaseFastMutex(&PspActiveProcessMutex);
- Process->Peb = Peb;
- KeDetachProcess();
-
- DPRINT("PsCreatePeb: Peb created at %p\n", Peb);
-
- return(STATUS_SUCCESS);
+ /* Reference the Process we had referenced earlier */
+ ObDereferenceObject(OldProcess);
+ return(NextProcess);
}
-
-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
+NTSTATUS
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)
+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 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;
-}
+ 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);
-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);
- }
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to reference the parent process: Status: 0x%x\n", Status);
+ goto Cleanup;
+ }
- 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);
- }
+ /* Inherit Parent process's Affinity. */
+ Affinity = pParentProcess->Pcb.Affinity;
- Status = ObInsertObject ((PVOID)Process,
- NULL,
- DesiredAccess,
- 0,
- NULL,
- ProcessHandle);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject (Process);
- ObDereferenceObject (pParentProcess);
- DPRINT("ObInsertObject() = %x\n",Status);
- return Status;
}
-
- 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
+ else
+ {
+ pParentProcess = NULL;
+#ifdef CONFIG_SMP
+ /* FIXME:
+ * Only the boot cpu is initialized in the early boot phase.
*/
-
- 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);
- }
+ Affinity = 0xffffffff;
+#else
+ Affinity = KeActiveProcessors;
#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);
- }
+ /* 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;
+ }
+ }
- /* 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);
- }
+ /* Add the exception port */
+ if (ExceptionPort != NULL)
+ {
+ Status = ObReferenceObjectByHandle(ExceptionPort,
+ PORT_ALL_ACCESS,
+ LpcPortObjectType,
+ PreviousMode,
+ (PVOID*)&pExceptionPort,
+ NULL);
- 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
- */
+ 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,
- 0,
+ SECTION_MAP_EXECUTE,
MmSectionObjectType,
- UserMode,
+ PreviousMode,
(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)
- {
- if(*szSrc == L'\\')
- {
- szSrc++;
- break;
- }
- else
- {
- szSrc--;
- lnFName++;
- }
- }
-
- /* 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)
+ if (!NT_SUCCESS(Status))
{
- *(szDest++) = (UCHAR)*(szSrc++);
+ DPRINT1("Failed to reference process image section: Status: 0x%x\n", Status);
+ goto Cleanup;
}
- *szDest = '\0';
-
-
- ObDereferenceObject(SectionObject);
- }
- else
- {
- Process->ImageFileName[0] = '\0';
- }
+ }
- /*
- * 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))
+ /* 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))
{
- DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status);
- ObDereferenceObject(Process);
- ObDereferenceObject(pParentProcess);
- return(Status);
+ DPRINT1("Failed to create process object, Status: 0x%x\n", Status);
+ goto Cleanup;
}
- /*
- *
- */
- 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);
-}
-
-
-/*
- * @unimplemented
- */
-NTSTATUS STDCALL
-NtOpenProcess(OUT PHANDLE ProcessHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes,
- IN PCLIENT_ID ClientId)
-{
- 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);
-}
-
-
-/*
- * @unimplemented
- */
-NTSTATUS STDCALL
-NtQueryInformationProcess(IN HANDLE ProcessHandle,
- IN PROCESSINFOCLASS ProcessInformationClass,
- OUT PVOID ProcessInformation,
- IN ULONG ProcessInformationLength,
- OUT PULONG ReturnLength OPTIONAL)
-{
- PEPROCESS Process;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status = STATUS_SUCCESS;
-
- PreviousMode = ExGetPreviousMode();
-
- DefaultQueryInfoBufferCheck(ProcessInformationClass,
- PsProcessInfoClass,
- ProcessInformation,
- ProcessInformationLength,
- ReturnLength,
- PreviousMode,
- &Status);
- if(!NT_SUCCESS(Status))
- {
- DPRINT1("NtQueryInformationProcess() failed, Status: 0x%x\n", Status);
- return Status;
- }
-
- /*
- * TODO: Here we should probably check that ProcessInformationLength
- * bytes indeed are writable at address ProcessInformation.
- */
-
- Status = ObReferenceObjectByHandle(ProcessHandle,
- PROCESS_QUERY_INFORMATION,
- PsProcessType,
- PreviousMode,
- (PVOID*)&Process,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- switch (ProcessInformationClass)
- {
- case ProcessBasicInformation:
- {
- PPROCESS_BASIC_INFORMATION ProcessBasicInformationP =
- (PPROCESS_BASIC_INFORMATION)ProcessInformation;
+ /* Clean up the Object */
+ DPRINT("Cleaning Process Object\n");
+ RtlZeroMemory(Process, sizeof(EPROCESS));
- _SEH_TRY
- {
- 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);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
-
- case ProcessQuotaLimits:
- case ProcessIoCounters:
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
- case ProcessTimes:
- {
- PKERNEL_USER_TIMES ProcessTimeP = (PKERNEL_USER_TIMES)ProcessInformation;
- _SEH_TRY
- {
- 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);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
+ /* Inherit stuff from the Parent since we now have the object created */
+ if (pParentProcess)
+ {
+ Process->InheritedFromUniqueProcessId = pParentProcess->UniqueProcessId;
+ Process->Session = pParentProcess->Session;
+ }
- case ProcessDebugPort:
- {
- _SEH_TRY
- {
- *(PHANDLE)ProcessInformation = (Process->DebugPort != NULL ? (HANDLE)-1 : NULL);
- if (ReturnLength)
- {
- *ReturnLength = sizeof(HANDLE);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
-
- case ProcessLdtInformation:
- case ProcessWorkingSetWatch:
- case ProcessWx86Information:
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
- case ProcessHandleCount:
- {
- ULONG HandleCount = ObpGetHandleCountByHandleTable(&Process->HandleTable);
-
- _SEH_TRY
- {
- *(PULONG)ProcessInformation = HandleCount;
- if (ReturnLength)
- {
- *ReturnLength = sizeof(ULONG);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
+ /* 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;
+ }
- case ProcessSessionInformation:
- {
- PPROCESS_SESSION_INFORMATION SessionInfo = (PPROCESS_SESSION_INFORMATION)ProcessInformation;
+ /* 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;
+ }
- _SEH_TRY
- {
- SessionInfo->SessionId = Process->SessionId;
- if (ReturnLength)
- {
- *ReturnLength = sizeof(PROCESS_SESSION_INFORMATION);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
-
- case ProcessWow64Information:
- DPRINT1("We currently don't support the ProcessWow64Information information class!\n");
- Status = STATUS_NOT_IMPLEMENTED;
- break;
+ if (SectionObject)
+ {
+ /* Map the System Dll */
+ DPRINT("Mapping System DLL\n");
+ PspMapSystemDll(Process, NULL);
+ }
- case ProcessVmCounters:
- {
- PVM_COUNTERS pOut = (PVM_COUNTERS)ProcessInformation;
-
- _SEH_TRY
- {
- 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);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
+ /* 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;
+ }
- case ProcessDefaultHardErrorMode:
- {
- PULONG HardErrMode = (PULONG)ProcessInformation;
- _SEH_TRY
- {
- *HardErrMode = Process->DefaultHardErrorProcessing;
- if (ReturnLength)
- {
- *ReturnLength = sizeof(ULONG);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
+ /* FIXME: Insert into Job Object */
- case ProcessPriorityBoost:
- {
- PULONG BoostEnabled = (PULONG)ProcessInformation;
-
- _SEH_TRY
- {
- *BoostEnabled = Process->Pcb.DisableBoost ? FALSE : TRUE;
-
- if (ReturnLength)
- {
- *ReturnLength = sizeof(ULONG);
- }
- }
- _SEH_HANDLE
+ /* Create PEB only for User-Mode Processes */
+ if (pParentProcess)
+ {
+ DPRINT("Creating PEB\n");
+ Status = MmCreatePeb(Process);
+ if (!NT_SUCCESS(Status))
{
- Status = _SEH_GetExceptionCode();
+ DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
+ goto Cleanup;
}
- _SEH_END;
- break;
- }
+ }
- case ProcessDeviceMap:
- {
- PROCESS_DEVICEMAP_INFORMATION DeviceMap;
-
- ObQueryDeviceMapInformation(Process, &DeviceMap);
+ /* 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
{
- *(PPROCESS_DEVICEMAP_INFORMATION)ProcessInformation = DeviceMap;
- if (ReturnLength)
- {
- *ReturnLength = sizeof(PROCESS_DEVICEMAP_INFORMATION);
- }
+ *ProcessHandle = hProcess;
}
_SEH_HANDLE
{
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
-
- case ProcessPriorityClass:
- {
- PUSHORT Priority = (PUSHORT)ProcessInformation;
-
- _SEH_TRY
- {
- *Priority = Process->PriorityClass;
-
- if (ReturnLength)
- {
- *ReturnLength = sizeof(USHORT);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- 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!
- */
- if(Process->Peb != NULL)
- {
- PRTL_USER_PROCESS_PARAMETERS ProcParams = NULL;
- UNICODE_STRING LocalDest;
- ULONG ImagePathLen = 0;
- PUNICODE_STRING DstPath = (PUNICODE_STRING)ProcessInformation;
-
- /* we need to attach to the process to make sure we're in the right context! */
- KeAttachProcess(&Process->Pcb);
-
- _SEH_TRY
- {
- ProcParams = Process->Peb->ProcessParameters;
- ImagePathLen = ProcParams->ImagePathName.Length;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if(NT_SUCCESS(Status))
- {
- if(ProcessInformationLength < sizeof(UNICODE_STRING) + ImagePathLen + sizeof(WCHAR))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
- {
- PWSTR StrSource = NULL;
-
- /* create a DstPath structure on the stack */
- _SEH_TRY
- {
- LocalDest.Length = ImagePathLen;
- LocalDest.MaximumLength = ImagePathLen + sizeof(WCHAR);
- LocalDest.Buffer = (PWSTR)(DstPath + 1);
-
- /* save a copy of the pointer to the source buffer */
- StrSource = ProcParams->ImagePathName.Buffer;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if(NT_SUCCESS(Status))
- {
- /* now, let's allocate some anonymous memory to copy the string to.
- we can't just copy it to the buffer the caller pointed as it might
- be user memory in another context */
- PWSTR PathCopy = ExAllocatePool(PagedPool, LocalDest.Length + sizeof(WCHAR));
- if(PathCopy != NULL)
- {
- /* make a copy of the buffer to the temporary buffer */
- _SEH_TRY
- {
- RtlCopyMemory(PathCopy, StrSource, LocalDest.Length);
- PathCopy[LocalDest.Length / sizeof(WCHAR)] = L'\0';
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- /* detach from the process */
- KeDetachProcess();
-
- /* only copy the string back to the caller if we were able to
- copy it into the temporary buffer! */
- if(NT_SUCCESS(Status))
- {
- /* now let's copy the buffer back to the caller */
- _SEH_TRY
- {
- *DstPath = LocalDest;
- RtlCopyMemory(LocalDest.Buffer, PathCopy, LocalDest.Length + sizeof(WCHAR));
- if (ReturnLength)
- {
- *ReturnLength = sizeof(UNICODE_STRING) + LocalDest.Length + sizeof(WCHAR);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- }
-
- /* we're done with the copy operation, free the temporary kernel buffer */
- ExFreePool(PathCopy);
-
- /* we need to bail because we're already detached from the process */
- break;
- }
- else
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
- }
- }
- }
-
- /* don't forget to detach from the process!!! */
- KeDetachProcess();
- }
- else
- {
- /* FIXME - what to do here? */
- Status = STATUS_UNSUCCESSFUL;
- }
- break;
- }
+ Status = _SEH_GetExceptionCode();
+ } _SEH_END;
+ /* FIXME: ObGetObjectSecurity(Process, &SecurityDescriptor)
+ SeAccessCheck
+ */
+ }
- /*
- * 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;
- }
+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);
+ }
- ObDereferenceObject(Process);
- return Status;
+ return Status;
}
+/* PUBLIC FUNCTIONS *****************************************************************/
+/*
+ * @implemented
+ */
NTSTATUS
-PspAssignPrimaryToken(PEPROCESS Process,
- HANDLE TokenHandle)
+STDCALL
+PsCreateSystemProcess(PHANDLE ProcessHandle,
+ ACCESS_MASK DesiredAccess,
+ POBJECT_ATTRIBUTES ObjectAttributes)
{
- 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);
+ return PspCreateProcess(ProcessHandle,
+ DesiredAccess,
+ ObjectAttributes,
+ NULL, /* no parent process */
+ FALSE,
+ NULL,
+ NULL,
+ NULL);
}
/*
- * @unimplemented
+ * @implemented
*/
-NTSTATUS STDCALL
-NtSetInformationProcess(IN HANDLE ProcessHandle,
- IN PROCESSINFOCLASS ProcessInformationClass,
- IN PVOID ProcessInformation,
- IN ULONG ProcessInformationLength)
+NTSTATUS
+STDCALL
+PsLookupProcessByProcessId(IN HANDLE ProcessId,
+ OUT PEPROCESS *Process)
{
- PEPROCESS Process;
- KPROCESSOR_MODE PreviousMode;
- ACCESS_MASK Access;
- NTSTATUS Status = STATUS_SUCCESS;
-
- PreviousMode = ExGetPreviousMode();
-
- DefaultSetInfoBufferCheck(ProcessInformationClass,
- PsProcessInfoClass,
- ProcessInformation,
- ProcessInformationLength,
- PreviousMode,
- &Status);
- if(!NT_SUCCESS(Status))
- {
- DPRINT1("NtSetInformationProcess() %d %x %x called\n", ProcessInformationClass, ProcessInformation, ProcessInformationLength);
- DPRINT1("NtSetInformationProcess() %x failed, Status: 0x%x\n", Status);
- return Status;
- }
-
- switch(ProcessInformationClass)
- {
- case ProcessSessionInformation:
- Access = PROCESS_SET_INFORMATION | PROCESS_SET_SESSIONID;
- break;
- case ProcessExceptionPort:
- case ProcessDebugPort:
- Access = PROCESS_SET_INFORMATION | PROCESS_SET_PORT;
- break;
-
- default:
- Access = PROCESS_SET_INFORMATION;
- break;
- }
-
- Status = ObReferenceObjectByHandle(ProcessHandle,
- Access,
- PsProcessType,
- PreviousMode,
- (PVOID*)&Process,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- switch (ProcessInformationClass)
- {
- case ProcessQuotaLimits:
- case ProcessBasePriority:
- case ProcessRaisePriority:
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
- case ProcessDebugPort:
- {
- if(ProcessInformationLength != sizeof(HANDLE))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
- {
- HANDLE PortHandle = NULL;
-
- /* make a safe copy of the buffer on the stack */
- _SEH_TRY
- {
- PortHandle = *(PHANDLE)ProcessInformation;
- Status = (PortHandle != NULL ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER);
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if(NT_SUCCESS(Status))
- {
- PEPORT DebugPort;
-
- /* in case we had success reading from the buffer, verify the provided
- * LPC port handle
- */
- Status = ObReferenceObjectByHandle(PortHandle,
- 0,
- LpcPortObjectType,
- PreviousMode,
- (PVOID)&DebugPort,
- NULL);
- if(NT_SUCCESS(Status))
- {
- /* lock the process to be thread-safe! */
-
- Status = PsLockProcess(Process, FALSE);
- if(NT_SUCCESS(Status))
- {
- /*
- * according to "NT Native API" documentation, setting the debug
- * port is only permitted once!
- */
- if(Process->DebugPort == NULL)
- {
- /* keep the reference to the handle! */
- Process->DebugPort = DebugPort;
-
- if(Process->Peb)
- {
- /* we're now debugging the process, so set the flag in the PEB
- structure. However, to access it we need to attach to the
- process so we're sure we're in the right context! */
-
- KeAttachProcess(&Process->Pcb);
- _SEH_TRY
- {
- Process->Peb->BeingDebugged = TRUE;
- }
- _SEH_HANDLE
- {
- DPRINT1("Trying to set the Peb->BeingDebugged field of process 0x%x failed, exception: 0x%x\n", Process, _SEH_GetExceptionCode());
- }
- _SEH_END;
- KeDetachProcess();
- }
- Status = STATUS_SUCCESS;
- }
- else
- {
- ObDereferenceObject(DebugPort);
- Status = STATUS_PORT_ALREADY_SET;
- }
- PsUnlockProcess(Process);
- }
- else
- {
- ObDereferenceObject(DebugPort);
- }
- }
- }
- }
- break;
- }
+ 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;
- case ProcessExceptionPort:
- {
- if(ProcessInformationLength != sizeof(HANDLE))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
+ /* Make sure it's really a process */
+ if (FoundProcess->Pcb.Header.Type == ProcessObject)
{
- HANDLE PortHandle = NULL;
-
- /* make a safe copy of the buffer on the stack */
- _SEH_TRY
- {
- PortHandle = *(PHANDLE)ProcessInformation;
+ /* Reference and return it */
+ ObReferenceObject(FoundProcess);
+ *Process = FoundProcess;
Status = STATUS_SUCCESS;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if(NT_SUCCESS(Status))
- {
- PEPORT ExceptionPort;
-
- /* in case we had success reading from the buffer, verify the provided
- * LPC port handle
- */
- Status = ObReferenceObjectByHandle(PortHandle,
- 0,
- LpcPortObjectType,
- PreviousMode,
- (PVOID)&ExceptionPort,
- NULL);
- if(NT_SUCCESS(Status))
- {
- /* lock the process to be thread-safe! */
-
- Status = PsLockProcess(Process, FALSE);
- if(NT_SUCCESS(Status))
- {
- /*
- * according to "NT Native API" documentation, setting the exception
- * port is only permitted once!
- */
- if(Process->ExceptionPort == NULL)
- {
- /* keep the reference to the handle! */
- Process->ExceptionPort = ExceptionPort;
- Status = STATUS_SUCCESS;
- }
- else
- {
- ObDereferenceObject(ExceptionPort);
- Status = STATUS_PORT_ALREADY_SET;
- }
- PsUnlockProcess(Process);
- }
- else
- {
- ObDereferenceObject(ExceptionPort);
- }
- }
- }
}
- break;
- }
-
- case ProcessAccessToken:
- {
- if(ProcessInformationLength != sizeof(PROCESS_ACCESS_TOKEN))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
- {
- HANDLE TokenHandle = NULL;
- /* make a safe copy of the buffer on the stack */
- _SEH_TRY
- {
- TokenHandle = ((PPROCESS_ACCESS_TOKEN)ProcessInformation)->Token;
- Status = STATUS_SUCCESS;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
+ /* Unlock the Entry */
+ ExUnlockHandleTableEntry(PspCidTable, CidEntry);
+ }
+
+ KeLeaveCriticalRegion();
- if(NT_SUCCESS(Status))
- {
- /* in case we had success reading from the buffer, perform the actual task */
- Status = PspAssignPrimaryToken(Process, TokenHandle);
- }
- }
- break;
- }
+ /* Return to caller */
+ return Status;
+}
- case ProcessDefaultHardErrorMode:
- {
- if(ProcessInformationLength != sizeof(UINT))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
- {
- _SEH_TRY
- {
- InterlockedExchange((LONG*)&Process->DefaultHardErrorProcessing,
- *(PLONG)ProcessInformation);
- Status = STATUS_SUCCESS;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- }
- break;
- }
-
- case ProcessSessionInformation:
- {
- if(ProcessInformationLength != sizeof(UINT))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
+/*
+ * @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))
{
- PROCESS_SESSION_INFORMATION SessionInfo;
- Status = STATUS_SUCCESS;
-
- _SEH_TRY
- {
- /* copy the structure to the stack */
- SessionInfo = *(PPROCESS_SESSION_INFORMATION)ProcessInformation;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if(NT_SUCCESS(Status))
- {
- /* we successfully copied the structure to the stack, continue processing */
-
- /*
- * setting the session id requires the SeTcbPrivilege!
- */
- if(!SeSinglePrivilegeCheck(SeTcbPrivilege,
- PreviousMode))
- {
- /* can't set the session id, bail! */
- Status = STATUS_PRIVILEGE_NOT_HELD;
- break;
- }
-
- /* FIXME - update the session id for the process token */
+ /* Reference and return it */
+ ObReferenceObject(FoundThread);
+ *Thread = FoundThread;
+ Status = STATUS_SUCCESS;
- Status = PsLockProcess(Process, FALSE);
- if(NT_SUCCESS(Status))
+ /* Check if we should return the Process too */
+ if (Process)
{
- Process->SessionId = SessionInfo.SessionId;
-
- /* Update the session id in the PEB structure */
- if(Process->Peb != NULL)
- {
- /* we need to attach to the process to make sure we're in the right
- context to access the PEB structure */
- KeAttachProcess(&Process->Pcb);
-
- _SEH_TRY
- {
- /* FIXME: Process->Peb->SessionId = SessionInfo.SessionId; */
-
- Status = STATUS_SUCCESS;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- KeDetachProcess();
- }
-
- PsUnlockProcess(Process);
+ /* Return it and reference it */
+ *Process = FoundThread->ThreadsProcess;
+ ObReferenceObject(*Process);
}
- }
}
- break;
- }
-
- case ProcessLdtInformation:
- case ProcessLdtSize:
- 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;
- }
- ObDereferenceObject(Process);
- return(Status);
-}
+ /* Unlock the Entry */
+ ExUnlockHandleTableEntry(PspCidTable, CidEntry);
+ }
+
+ KeLeaveCriticalRegion();
-/**********************************************************************
- * 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.
+ /* Return to caller */
+ return Status;
+}
+
+/*
+ * FUNCTION: Returns a pointer to the current process
*
- * NOTE
- * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
+ * @implemented
*/
-NTSTATUS
-PiQuerySystemProcessInformation(PVOID Buffer,
- ULONG Size,
- PULONG ReqSize)
+PEPROCESS STDCALL
+IoGetCurrentProcess(VOID)
{
- 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
+ if (PsGetCurrentThread() == NULL ||
+ PsGetCurrentThread()->Tcb.ApcState.Process == NULL)
+ {
+ return(PsInitialSystemProcess);
+ }
+ else
+ {
+ return(PEPROCESS)(PsGetCurrentThread()->Tcb.ApcState.Process);
+ }
}
/*
*/
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)
+PVOID
+STDCALL
+PsGetProcessWin32WindowStation(PEPROCESS Process)
{
- 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;
+ return Process->Win32WindowStation;
}
/*
* @implemented
- */
-VOID
+ */
+BOOLEAN
STDCALL
-PsSetProcessPriorityClass(
- PEPROCESS Process,
- ULONG PriorityClass
- )
+PsIsProcessBeingDebugged(PEPROCESS Process)
{
- Process->PriorityClass = PriorityClass;
+ return FALSE; //Process->IsProcessBeingDebugged;
}
/*
* @implemented
- */
+ */
VOID
STDCALL
-PsSetProcessSecurityPort(
- PEPROCESS Process,
- PVOID SecurityPort
- )
+PsSetProcessPriorityClass(PEPROCESS Process,
+ ULONG PriorityClass)
{
- Process->SecurityPort = SecurityPort;
+ Process->PriorityClass = PriorityClass;
}
/*
*/
VOID
STDCALL
-PsSetProcessWin32Process(
- PEPROCESS Process,
- PVOID Win32Process
- )
+PsSetProcessSecurityPort(PEPROCESS Process,
+ PVOID SecurityPort)
{
- Process->Win32Process = Win32Process;
+ Process->SecurityPort = SecurityPort;
}
/*
*/
VOID
STDCALL
-PsSetProcessWin32WindowStation(
- PEPROCESS Process,
- PVOID WindowStation
- )
+PsSetProcessWin32Process(PEPROCESS Process,
+ PVOID Win32Process)
{
- Process->Win32WindowStation = WindowStation;
+ Process->Win32Process = Win32Process;
}
-/* Pool Quotas */
/*
* @implemented
*/
VOID
STDCALL
-PsChargePoolQuota(
- IN PEPROCESS Process,
- IN POOL_TYPE PoolType,
- IN ULONG_PTR Amount
- )
+PsSetProcessWindowStation(PEPROCESS Process,
+ PVOID WindowStation)
{
- NTSTATUS Status;
-
- /* Charge the usage */
- Status = PsChargeProcessPoolQuota(Process, PoolType, Amount);
-
- /* Raise Exception */
- if (!NT_SUCCESS(Status)) {
- ExRaiseStatus(Status);
- }
+ Process->Win32WindowStation = WindowStation;
}
/*
- * @implemented
+ * @unimplemented
*/
NTSTATUS
STDCALL
-PsChargeProcessNonPagedPoolQuota (
- IN PEPROCESS Process,
- IN ULONG_PTR Amount
- )
+PsSetProcessPriorityByClass(IN PEPROCESS Process,
+ IN ULONG Type)
{
- /* Call the general function */
- return PsChargeProcessPoolQuota(Process, NonPagedPool, 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
-PsChargeProcessPagedPoolQuota (
- IN PEPROCESS Process,
- 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)
{
- /* Call the general function */
- return PsChargeProcessPoolQuota(Process, PagedPool, Amount);
+ 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;
}
/*
*/
NTSTATUS
STDCALL
-PsChargeProcessPoolQuota(
- 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)
{
- PEPROCESS_QUOTA_BLOCK QuotaBlock;
- ULONG NewUsageSize;
- ULONG NewMaxQuota;
+ KPROCESSOR_MODE PreviousMode;
+ CLIENT_ID SafeClientId;
+ ULONG Attributes = 0;
+ HANDLE hProcess;
+ BOOLEAN HasObjectName = FALSE;
+ PETHREAD Thread = NULL;
+ PEPROCESS Process = NULL;
+ NTSTATUS Status = STATUS_SUCCESS;
- /* Get current Quota Block */
- QuotaBlock = Process->QuotaBlock;
+ PAGED_CODE();
- /* Quota Operations are not to be done on the SYSTEM Process */
- if (Process == PsInitialSystemProcess) return STATUS_SUCCESS;
+ PreviousMode = KeGetPreviousMode();
- /* New Size in use */
- NewUsageSize = QuotaBlock->QuotaEntry[PoolType].Usage + Amount;
+ /* Probe the paraemeters */
+ if(PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWriteHandle(ProcessHandle);
- /* Does this size respect the quota? */
- if (NewUsageSize > QuotaBlock->QuotaEntry[PoolType].Limit) {
+ if(ClientId != NULL)
+ {
+ ProbeForRead(ClientId,
+ sizeof(CLIENT_ID),
+ sizeof(ULONG));
- /* 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;
+ SafeClientId = *ClientId;
+ ClientId = &SafeClientId;
+ }
- /* See if the new Maximum Quota fulfills our need */
- if (NewUsageSize <= NewMaxQuota) goto QuotaChanged;
+ /* 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;
- return STATUS_QUOTA_EXCEEDED;
+ if(!NT_SUCCESS(Status)) return Status;
+ }
+ else
+ {
+ HasObjectName = (ObjectAttributes->ObjectName != NULL);
+ Attributes = ObjectAttributes->Attributes;
}
-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;
+ if (HasObjectName && ClientId != NULL)
+ {
+ /* can't pass both, n object name and a client id */
+ return STATUS_INVALID_PARAMETER_MIX;
}
- /* All went well */
- 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);
+ }
-/*
- * @unimplemented
- */
-VOID
-STDCALL
-PsReturnPoolQuota(
- IN PEPROCESS Process,
- IN POOL_TYPE PoolType,
- IN ULONG_PTR Amount
- )
-{
- UNIMPLEMENTED;
-}
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failure to find process\n");
+ return Status;
+ }
-/*
- * @unimplemented
- */
-VOID
-STDCALL
-PsReturnProcessNonPagedPoolQuota(
- IN PEPROCESS Process,
- IN ULONG_PTR Amount
- )
-{
- UNIMPLEMENTED;
-}
+ /* Open the Process Object */
+ Status = ObOpenObjectByPointer(Process,
+ Attributes,
+ NULL,
+ DesiredAccess,
+ PsProcessType,
+ PreviousMode,
+ &hProcess);
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failure to open process\n");
+ }
-/*
- * @unimplemented
- */
-VOID
-STDCALL
-PsReturnProcessPagedPoolQuota(
- IN PEPROCESS Process,
- IN ULONG_PTR Amount
- )
-{
- UNIMPLEMENTED;
-}
+ /* Dereference the thread if we used it */
+ if (Thread) ObDereferenceObject(Thread);
-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)
- {
- KeLeaveCriticalRegion();
- return STATUS_PROCESS_IS_TERMINATING;
+ /* Dereference the Process */
+ ObDereferenceObject(Process);
}
-
- PrevLockOwner = (PKTHREAD)InterlockedCompareExchangePointer(
- &Process->LockOwner, CallingThread, NULL);
- if(PrevLockOwner == NULL || PrevLockOwner == CallingThread)
+ else
{
- /* we got the lock or already locked it */
- if(InterlockedIncrementUL(&Process->LockCount) == 1)
- {
- KeClearEvent(&Process->LockEvent);
- }
-
- return STATUS_SUCCESS;
+ /* neither an object name nor a client id was passed */
+ return STATUS_INVALID_PARAMETER_MIX;
}
- else
+
+ /* Write back the handle */
+ if(NT_SUCCESS(Status))
{
- if(++Attempts > 2)
- {
- Status = KeWaitForSingleObject(&Process->LockEvent,
- Executive,
- KernelMode,
- FALSE,
- Delay);
- if(!NT_SUCCESS(Status))
+ _SEH_TRY
{
-#ifndef NDEBUG
- if(Status == STATUS_TIMEOUT)
- {
- DPRINT1("PsLockProcess(0x%x) timed out!\n", Process);
- }
-#endif
- KeLeaveCriticalRegion();
-
+ *ProcessHandle = hProcess;
}
- break;
- }
- 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 */