* PURPOSE: Process Manager: Thread/Process Query/Set Information
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Thomas Weidenmueller (w3seek@reactos.org)
+ * Eric Kohl
*/
/* INCLUDES ******************************************************************/
{
PEPROCESS Process;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS Status;
ULONG Length = 0;
PPROCESS_BASIC_INFORMATION ProcessBasicInfo =
(PPROCESS_BASIC_INFORMATION)ProcessInformation;
/* Prepare to probe parameters */
_SEH2_TRY
{
+ /* Probe the buffer */
ProbeForWrite(ProcessInformation,
ProcessInformationLength,
sizeof(ULONG));
+
+ /* Probe the return length if required */
if (ReturnLength) ProbeForWriteUlong(ReturnLength);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- /* Get the error code */
- Status = _SEH2_GetExceptionCode();
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
- if(!NT_SUCCESS(Status)) return Status;
}
if((ProcessInformationClass == ProcessCookie) &&
Process->Vm.MinimumWorkingSetSize << PAGE_SHIFT;
/* Set default time limits */
- QuotaLimits->TimeLimit.LowPart = (ULONG)-1;
- QuotaLimits->TimeLimit.HighPart = (ULONG)-1;
+ QuotaLimits->TimeLimit.LowPart = MAXULONG;
+ QuotaLimits->TimeLimit.HighPart = MAXULONG;
/* Is quota block a default one? */
if (Process->QuotaBlock == &PspDefaultQuotaBlock)
ObDereferenceObject(Process);
break;
+ case ProcessBreakOnTermination:
+
+ /* Set the return length*/
+ Length = sizeof(ULONG);
+ if (ProcessInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Reference the process */
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_QUERY_INFORMATION,
+ PsProcessType,
+ PreviousMode,
+ (PVOID*)&Process,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ break;
+
+ /* Enter SEH for writing back data */
+ _SEH2_TRY
+ {
+ /* Return the BreakOnTermination state */
+ *(PULONG)ProcessInformation = Process->BreakOnTermination;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
+ break;
+
/* Per-process security cookie */
case ProcessCookie:
Length = sizeof(ULONG);
}
+ /* Indicate success */
+ Status = STATUS_SUCCESS;
+
/* Enter SEH to protect write */
_SEH2_TRY
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
if (!NT_SUCCESS(Status)) break;
/* Get the LPC Port */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
if (!NT_SUCCESS(Status)) break;
/* Assign the actual token */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
if (!NT_SUCCESS(Status)) break;
/* Setting the session id requires the SeTcbPrivilege */
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- /* Get the exception code */
+ /* Return the exception code */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
if (!NT_SUCCESS(Status)) break;
/* Check for invalid PriorityClass value */
Status = STATUS_NOT_IMPLEMENTED;
break;
+ case ProcessBreakOnTermination:
+
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(ULONG))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Setting 'break on termination' requires the SeDebugPrivilege */
+ if (!SeSinglePrivilegeCheck(SeDebugPrivilege, PreviousMode))
+ {
+ Status = STATUS_PRIVILEGE_NOT_HELD;
+ break;
+ }
+
+ /* Enter SEH for direct buffer read */
+ _SEH2_TRY
+ {
+ Process->BreakOnTermination = *(PULONG)ProcessInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ break;
+
/* We currently don't implement any of these */
case ProcessLdtInformation:
case ProcessLdtSize:
Access = THREAD_SET_THREAD_TOKEN;
}
- /* Reference the process */
+ /* Reference the thread */
Status = ObReferenceObjectByHandle(ThreadHandle,
Access,
PsThreadType,
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
if (!NT_SUCCESS(Status)) break;
/* Validate it */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
if (!NT_SUCCESS(Status)) break;
/* Validate it */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
- if (!NT_SUCCESS(Status)) break;
/* Validate it */
if (!Affinity)
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
if (!NT_SUCCESS(Status)) break;
/* Assign the actual token */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
if (!NT_SUCCESS(Status)) break;
/* Set the address */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
if (!NT_SUCCESS(Status)) break;
/* Validate it */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
if (!NT_SUCCESS(Status)) break;
/* Call the kernel */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
if (!NT_SUCCESS(Status)) break;
/* This is only valid for the current thread */
{
PETHREAD Thread;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS Status;
ULONG Access;
ULONG Length = 0;
PTHREAD_BASIC_INFORMATION ThreadBasicInfo =
KIRQL OldIrql;
PAGED_CODE();
+ /* Check if we were called from user mode */
if (PreviousMode != KernelMode)
{
+ /* Enter SEH */
_SEH2_TRY
{
+ /* Probe the buffer */
ProbeForWrite(ThreadInformation,
ThreadInformationLength,
sizeof(ULONG));
- if (ReturnLength)
- {
- ProbeForWriteUlong(ReturnLength);
- }
+ /* Probe the return length if required */
+ if (ReturnLength) ProbeForWriteUlong(ReturnLength);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- Status = _SEH2_GetExceptionCode();
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
-
- if (!NT_SUCCESS(Status)) return Status;
}
/* Check what class this is */
KeLowerIrql(OldIrql);
break;
+ /* LDT and GDT information */
case ThreadDescriptorTableEntry:
- DPRINT1("NtQueryInformationThread(): case ThreadDescriptorTableEntry not implemented!\n");
+
+#if defined(_X86_)
+ /* Call the worker routine */
+ Status = PspQueryDescriptorThread(Thread,
+ ThreadInformation,
+ ThreadInformationLength,
+ ReturnLength);
+#else
+ /* Only implemented on x86 */
Status = STATUS_NOT_IMPLEMENTED;
+#endif
break;
case ThreadPriorityBoost: