/* INCLUDES ******************************************************************/
#include <limits.h>
-#include <ddk/ntddk.h>
+#define NTOS_MODE_KERNEL
+#include <ntos.h>
#include <internal/ob.h>
#include <internal/mm.h>
#include <internal/ke.h>
#include <roscfg.h>
#include <internal/se.h>
#include <internal/kd.h>
+#include <internal/nls.h>
#define NDEBUG
#include <internal/debug.h>
+
/* GLOBALS ******************************************************************/
PEPROCESS EXPORTED PsInitialSystemProcess = NULL;
#define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8
-static ULONG PiProcessNotifyRoutineCount = 0;
static PCREATE_PROCESS_NOTIFY_ROUTINE
PiProcessNotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT];
-/* FUNCTIONS *****************************************************************/
+typedef struct
+{
+ WORK_QUEUE_ITEM WorkQueueItem;
+ KEVENT Event;
+ PEPROCESS Process;
+ BOOLEAN IsWorkerQueue;
+} DEL_CONTEXT, *PDEL_CONTEXT;
+/* FUNCTIONS *****************************************************************/
-PEPROCESS
+PEPROCESS
PsGetNextProcess(PEPROCESS OldProcess)
{
KIRQL oldIrql;
EPROCESS,
ProcessListEntry);
}
- KeReleaseSpinLock(&PsProcessListLock, oldIrql);
Status = ObReferenceObjectByPointer(NextProcess,
PROCESS_ALL_ACCESS,
PsProcessType,
KernelMode);
+ KeReleaseSpinLock(&PsProcessListLock, oldIrql);
if (!NT_SUCCESS(Status))
{
CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
ObDereferenceObject(OldProcess);
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
NtOpenProcessToken(IN HANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
}
+/*
+ * @implemented
+ */
PACCESS_TOKEN STDCALL
PsReferencePrimaryToken(PEPROCESS Process)
{
/*
* Initialize the system process
*/
- Status = ObCreateObject(NULL,
+ Status = ObRosCreateObject(NULL,
PROCESS_ALL_ACCESS,
NULL,
PsProcessType,
/* 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;
KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
InternalProcessType,
}
VOID STDCALL
-PiDeleteProcess(PVOID ObjectBody)
+PiDeleteProcessWorker(PVOID pContext)
{
KIRQL oldIrql;
- PEPROCESS Process;
ULONG i;
+ PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT];
+ ULONG NotifyRoutineCount;
+ PDEL_CONTEXT Context;
+ PEPROCESS CurrentProcess;
+ PEPROCESS Process;
+
+ Context = (PDEL_CONTEXT)pContext;
+ Process = Context->Process;
+ CurrentProcess = PsGetCurrentProcess();
- DPRINT("PiDeleteProcess(ObjectBody %x)\n",ObjectBody);
+ DPRINT("PiDeleteProcess(ObjectBody %x)\n",Process);
+
+ if (CurrentProcess != Process)
+ {
+ KeAttachProcess(Process);
+ }
+
+ /* Terminate Win32 Process */
+ PsTerminateWin32Process (Process);
- Process = (PEPROCESS)ObjectBody;
KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
- for (i = 0; i < PiProcessNotifyRoutineCount; i++)
+ NotifyRoutineCount = 0;
+ for (i = 0; i < MAX_PROCESS_NOTIFY_ROUTINE_COUNT; i++)
{
- PiProcessNotifyRoutine[i](Process->InheritedFromUniqueProcessId,
- (HANDLE)Process->UniqueProcessId,
- FALSE);
+ if (PiProcessNotifyRoutine[i])
+ {
+ NotifyRoutine[NotifyRoutineCount++] = PiProcessNotifyRoutine[i];
+ }
+ }
+ RemoveEntryList(&Process->ProcessListEntry);
+ KeReleaseSpinLock(&PsProcessListLock, oldIrql);
+
+ for (i = 0;i < NotifyRoutineCount; i++)
+ {
+ /* must be called below DISPATCH_LVL */
+ NotifyRoutine[i](Process->InheritedFromUniqueProcessId,
+ (HANDLE)Process->UniqueProcessId,
+ FALSE);
}
- RemoveEntryList(&Process->ProcessListEntry);
- KeReleaseSpinLock(&PsProcessListLock, oldIrql);
- /* KDB hook */
- KDB_DELETEPROCESS_HOOK(Process);
+ /* KDB hook */
+ KDB_DELETEPROCESS_HOOK(Process);
- ObDereferenceObject(Process->Token);
- ObDeleteHandleTable(Process);
+ ObDereferenceObject(Process->Token);
+ ObDeleteHandleTable(Process);
- (VOID)MmReleaseMmInfo(Process);
+ if (CurrentProcess != Process)
+ {
+ KeDetachProcess();
+ }
+
+ MmReleaseMmInfo(Process);
+ if (Context->IsWorkerQueue)
+ {
+ KeSetEvent(&Context->Event, IO_NO_INCREMENT, FALSE);
+ }
}
+VOID STDCALL
+PiDeleteProcess(PVOID ObjectBody)
+{
+ DEL_CONTEXT Context;
+
+ Context.Process = (PEPROCESS)ObjectBody;
+
+ if (PsGetCurrentProcess() == Context.Process || PsGetCurrentThread()->OldProcess == NULL)
+ {
+ 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)
+ {
+ KeWaitForSingleObject(&Context.Event, Executive, KernelMode, FALSE, NULL);
+ }
+ }
+}
static NTSTATUS
PsCreatePeb(HANDLE ProcessHandle,
- PVOID ImageBase,
- PVOID* RPeb)
+ PEPROCESS Process,
+ PVOID ImageBase)
{
- NTSTATUS Status;
- PVOID PebBase;
- ULONG PebSize;
- PEB Peb;
- ULONG BytesWritten;
-
- memset(&Peb, 0, sizeof(Peb));
- Peb.ImageBaseAddress = ImageBase;
-
- PebBase = (PVOID)PEB_BASE;
- PebSize = 0x1000;
- Status = NtAllocateVirtualMemory(ProcessHandle,
- &PebBase,
- 0,
- &PebSize,
- MEM_RESERVE | MEM_COMMIT,
- PAGE_READWRITE);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- NtWriteVirtualMemory(ProcessHandle,
- (PVOID)PEB_BASE,
- &Peb,
- sizeof(Peb),
- &BytesWritten);
+ ULONG PebSize;
+ PPEB Peb;
+ LARGE_INTEGER SectionOffset;
+ ULONG ViewSize;
+ PVOID TableBase;
+ NTSTATUS Status;
+
+ /* Allocate the Process Environment Block (PEB) */
+ Peb = (PPEB)PEB_BASE;
+ PebSize = PAGE_SIZE;
+ Status = NtAllocateVirtualMemory(ProcessHandle,
+ (PVOID*)&Peb,
+ 0,
+ &PebSize,
+ MEM_RESERVE | 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);
+
+ ViewSize = 0;
+ SectionOffset.QuadPart = 0LL;
+ 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);
+ }
+ DPRINT("TableBase %p ViewSize %lx\n", TableBase, ViewSize);
- DPRINT("PsCreatePeb: Peb created at %x\n", PebBase);
-
- *RPeb = PebBase;
-
- return(STATUS_SUCCESS);
+ KeAttachProcess(Process);
+
+ /* Initialize the PEB */
+ RtlZeroMemory(Peb, sizeof(PEB));
+ Peb->ImageBaseAddress = ImageBase;
+
+ Peb->OSMajorVersion = 4;
+ Peb->OSMinorVersion = 0;
+ Peb->OSBuildNumber = 0;
+ Peb->OSPlatformId = 2; //VER_PLATFORM_WIN32_NT;
+
+ Peb->AnsiCodePageData = TableBase + NlsAnsiTableOffset;
+ Peb->OemCodePageData = TableBase + NlsOemTableOffset;
+ Peb->UnicodeCaseTableData = TableBase + NlsUnicodeTableOffset;
+
+ Process->Peb = Peb;
+ KeDetachProcess();
+
+ DPRINT("PsCreatePeb: Peb created at %p\n", Peb);
+
+ return(STATUS_SUCCESS);
}
* FUNCTION: Returns a pointer to the current process
*/
{
- return(&(PsGetCurrentProcess()->Pcb));
+ return(&(PsGetCurrentProcess()->Pcb));
}
+/*
+ * @implemented
+ */
HANDLE STDCALL
PsGetCurrentProcessId(VOID)
{
- return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
+ return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
}
/*
* FUNCTION: Returns a pointer to the current process
+ *
+ * @implemented
*/
PEPROCESS STDCALL
IoGetCurrentProcess(VOID)
}
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
PsCreateSystemProcess(PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
KIRQL oldIrql;
PVOID LdrStartupAddr;
PVOID ImageBase;
- PVOID Peb;
PEPORT DebugPort;
PEPORT ExceptionPort;
PVOID BaseAddress;
PMEMORY_AREA MemoryArea;
ULONG i;
-
+ PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT];
+ ULONG NotifyRoutineCount;
+
DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes);
Status = ObReferenceObjectByHandle(ParentProcessHandle,
return(Status);
}
- Status = ObCreateObject(ProcessHandle,
+ Status = ObRosCreateObject(ProcessHandle,
DesiredAccess,
ObjectAttributes,
PsProcessType,
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(ParentProcess);
- DPRINT("ObCreateObject() = %x\n",Status);
+ DPRINT("ObRosCreateObject() = %x\n",Status);
return(Status);
}
/* Inherit parent process's affinity. */
KProcess->Affinity = ParentProcess->Pcb.Affinity;
KProcess->BasePriority = PROCESS_PRIO_NORMAL;
+ KProcess->IopmOffset = 0xffff;
+ KProcess->LdtDescriptor[0] = 0;
+ KProcess->LdtDescriptor[1] = 0;
MmInitializeAddressSpace(Process,
&Process->AddressSpace);
Process->UniqueProcessId = InterlockedIncrement((LONG *)&PiNextProcessUniqueId);
DUPLICATE_SAME_ACCESS);
if (!NT_SUCCESS(Status))
{
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
}
else
DUPLICATE_SAME_ACCESS);
if (!NT_SUCCESS(Status))
{
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
}
else
}
KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
- for (i = 0; i < PiProcessNotifyRoutineCount; i++)
- {
- PiProcessNotifyRoutine[i](Process->InheritedFromUniqueProcessId,
- (HANDLE)Process->UniqueProcessId,
- TRUE);
- }
+ NotifyRoutineCount = 0;
+ for (i = 0; i < MAX_PROCESS_NOTIFY_ROUTINE_COUNT; i++)
+ {
+ if (PiProcessNotifyRoutine[i])
+ {
+ NotifyRoutine[NotifyRoutineCount++] = PiProcessNotifyRoutine[i];
+ }
+ }
InsertHeadList(&PsProcessListHead, &Process->ProcessListEntry);
InitializeListHead(&Process->ThreadListHead);
KeReleaseSpinLock(&PsProcessListLock, oldIrql);
-
+
+ for (i = 0;i < NotifyRoutineCount; i++)
+ {
+ //must be called below DISPATCH_LVL
+ NotifyRoutine[i](Process->InheritedFromUniqueProcessId,
+ (HANDLE)Process->UniqueProcessId,
+ TRUE);
+ }
+
Process->Pcb.State = PROCESS_STATE_ACTIVE;
/*
/*
* Now we have created the process proper
*/
-
- /*
- * Create the shared data page
- */
+
MmLockAddressSpace(&Process->AddressSpace);
+
+ /* Protect the highest 64KB of the process address space */
+ BaseAddress = MmUserProbeAddress;
+ Status = MmCreateMemoryArea(Process,
+ &Process->AddressSpace,
+ MEMORY_AREA_NO_ACCESS,
+ &BaseAddress,
+ 0x10000,
+ PAGE_NOACCESS,
+ &MemoryArea,
+ FALSE,
+ FALSE);
+ 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);
+ 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 = (PVOID)USER_SHARED_DATA + PAGE_SIZE;
+ Status = MmCreateMemoryArea(Process,
+ &Process->AddressSpace,
+ MEMORY_AREA_NO_ACCESS,
+ &BaseAddress,
+ 0x10000 - PAGE_SIZE,
+ PAGE_NOACCESS,
+ &MemoryArea,
+ FALSE,
+ FALSE);
+ 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,
PAGE_SIZE,
PAGE_READONLY,
&MemoryArea,
+ FALSE,
FALSE);
MmUnlockAddressSpace(&Process->AddressSpace);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create shared data page\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
-
+
/*
* Map ntdll
*/
*/
DPRINT("Creating PEB\n");
Status = PsCreatePeb(*ProcessHandle,
- ImageBase,
- &Peb);
+ Process,
+ ImageBase);
if (!NT_SUCCESS(Status))
{
DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
*ProcessHandle = NULL;
return(Status);
}
- Process->Peb = Peb;
/*
* Maybe send a message to the creator process's debugger
}
+/*
+ * @unimplemented
+ */
NTSTATUS STDCALL
NtOpenProcess(OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
}
+/*
+ * @unimplemented
+ */
NTSTATUS STDCALL
NtQueryInformationProcess(IN HANDLE ProcessHandle,
IN CINT ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
- OUT PULONG ReturnLength)
+ OUT PULONG ReturnLength OPTIONAL)
{
PEPROCESS Process;
NTSTATUS Status;
- PPROCESS_BASIC_INFORMATION ProcessBasicInformationP;
-
+
+ /*
+ * TODO: Here we should probably check that ProcessInformationLength
+ * bytes indeed are writable at address ProcessInformation.
+ */
+
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_SET_INFORMATION,
PsProcessType,
{
return(Status);
}
-
+
switch (ProcessInformationClass)
{
case ProcessBasicInformation:
- 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;
- Status = STATUS_SUCCESS;
+ 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;
+
+ if (ReturnLength)
+ {
+ *ReturnLength = sizeof(PROCESS_BASIC_INFORMATION);
+ }
+ }
break;
-
+
case ProcessQuotaLimits:
case ProcessIoCounters:
- case ProcessVmCounters:
case ProcessTimes:
case ProcessDebugPort:
case ProcessLdtInformation:
+ case ProcessWorkingSetWatch:
+ case ProcessWx86Information:
+ case ProcessHandleCount:
+ case ProcessSessionInformation:
+ case ProcessWow64Information:
Status = STATUS_NOT_IMPLEMENTED;
break;
-
- case ProcessDefaultHardErrorMode:
- *((PULONG)ProcessInformation) = Process->DefaultHardErrorProcessing;
+
+ 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 ProcessWorkingSetWatch:
- Status = STATUS_NOT_IMPLEMENTED;
+
+ 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 ProcessWx86Information:
- case ProcessHandleCount:
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:
- case ProcessSessionInformation:
- case ProcessWow64Information:
Status = STATUS_NOT_IMPLEMENTED;
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;
+
+ /*
+ * 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 ProcessIoPortHandlers:
case ProcessUserModeIOPL:
case ProcessEnableAlignmentFaultFixup:
- case ProcessPriorityClass:
case ProcessAffinityMask:
case ProcessForegroundInformation:
default:
return(Status);
}
+
NTSTATUS
PspAssignPrimaryToken(PEPROCESS Process,
HANDLE TokenHandle)
return(Status);
}
+/*
+ * @unimplemented
+ */
NTSTATUS STDCALL
NtSetInformationProcess(IN HANDLE ProcessHandle,
IN CINT ProcessInformationClass,
case ProcessBasicInformation:
case ProcessIoCounters:
- case ProcessVmCounters:
case ProcessTimes:
case ProcessPooledUsageAndLimits:
case ProcessWx86Information:
#endif
}
+/*
+ * @implemented
+ */
LARGE_INTEGER STDCALL
PsGetProcessExitTime(VOID)
{
return Li;
}
+/*
+ * @implemented
+ */
BOOLEAN STDCALL
PsIsThreadTerminating(IN PETHREAD Thread)
{
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
PsLookupProcessByProcessId(IN PVOID ProcessId,
OUT PEPROCESS *Process)
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
IN BOOLEAN Remove)
{
- if (PiProcessNotifyRoutineCount >= MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
- return(STATUS_INSUFFICIENT_RESOURCES);
+ KIRQL oldIrql;
+ ULONG i;
- PiProcessNotifyRoutine[PiProcessNotifyRoutineCount] = NotifyRoutine;
- PiProcessNotifyRoutineCount++;
+ KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
- return(STATUS_SUCCESS);
+ if (Remove)
+ {
+ for(i=0;i<MAX_PROCESS_NOTIFY_ROUTINE_COUNT;i++)
+ {
+ if ((PVOID)PiProcessNotifyRoutine[i] == (PVOID)NotifyRoutine)
+ {
+ PiProcessNotifyRoutine[i] = NULL;
+ break;
+ }
+ }
+
+ KeReleaseSpinLock(&PsProcessListLock, oldIrql);
+ return(STATUS_SUCCESS);
+ }
+
+ /*insert*/
+ for(i=0;i<MAX_PROCESS_NOTIFY_ROUTINE_COUNT;i++)
+ {
+ if (PiProcessNotifyRoutine[i] == NULL)
+ {
+ PiProcessNotifyRoutine[i] = NotifyRoutine;
+ break;
+ }
+ }
+
+ KeReleaseSpinLock(&PsProcessListLock, oldIrql);
+
+ if (i == MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ return STATUS_SUCCESS;
}
/* EOF */