#include <ntoskrnl.h>
#define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
/* Include Information Class Tables */
#include "internal/ps_i.h"
/* Debugging Level */
-ULONG PspTraceLevel = 0; //PS_KILL_DEBUG | PS_SECURITY_DEBUG;
+ULONG PspTraceLevel = 0;
/* PRIVATE FUNCTIONS *********************************************************/
-/* FIXME:
- * This entire API is messed up because:
- * 1) Directly pokes SECTION_OBJECT/FILE_OBJECT without special reffing.
- * 2) Ignores SeAuditProcessImageFileName stuff added in XP (and ROS).
- * 3) Doesn't use ObQueryNameString.
- */
NTSTATUS
NTAPI
-PspGetImagePath(IN PEPROCESS Process,
- OUT PUNICODE_STRING DstPath,
- IN ULONG ProcessInformationLength)
+PsReferenceProcessFilePointer(IN PEPROCESS Process,
+ OUT PFILE_OBJECT *FileObject)
{
- NTSTATUS Status;
- ULONG ImagePathLen = 0;
- PROS_SECTION_OBJECT Section;
- PWSTR SrcBuffer = NULL, DstBuffer = (PWSTR)(DstPath + 1);
+ PSECTION Section;
+ PAGED_CODE();
- Section = (PROS_SECTION_OBJECT)Process->SectionObject;
- if ((Section)&& (Section->FileObject))
- {
- /* FIXME - check for SEC_IMAGE and/or SEC_FILE instead
- of relying on FileObject being != NULL? */
- SrcBuffer = Section->FileObject->FileName.Buffer;
- if (SrcBuffer) ImagePathLen = Section->FileObject->FileName.Length;
- }
+ /* Lock the process */
+ ExAcquireRundownProtection(&Process->RundownProtect);
- if (ProcessInformationLength < (sizeof(UNICODE_STRING) +
- ImagePathLen +
- sizeof(WCHAR)))
+ /* Get the section */
+ Section = Process->SectionObject;
+ if (Section)
{
- return STATUS_INFO_LENGTH_MISMATCH;
+ /* Get the file object and reference it */
+ *FileObject = MmGetFileObjectForSection((PVOID)Section);
+ ObReferenceObject(*FileObject);
}
- Status = STATUS_SUCCESS;
- _SEH_TRY
- {
- /* copy the string manually, don't use RtlCopyUnicodeString with DstPath! */
- DstPath->Length = ImagePathLen;
- DstPath->MaximumLength = ImagePathLen + sizeof(WCHAR);
- DstPath->Buffer = DstBuffer;
- if (ImagePathLen) RtlCopyMemory(DstBuffer, SrcBuffer, ImagePathLen);
- DstBuffer[ImagePathLen / sizeof(WCHAR)] = L'\0';
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
+ /* Release the protection */
+ ExReleaseRundownProtection(&Process->RundownProtect);
/* Return status */
- return Status;
+ return Section ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}
/* PUBLIC FUNCTIONS **********************************************************/
PPROCESS_BASIC_INFORMATION ProcessBasicInfo =
(PPROCESS_BASIC_INFORMATION)ProcessInformation;
PKERNEL_USER_TIMES ProcessTime = (PKERNEL_USER_TIMES)ProcessInformation;
+ PPROCESS_PRIORITY_CLASS PsPriorityClass = (PPROCESS_PRIORITY_CLASS)ProcessInformation;
ULONG HandleCount;
PPROCESS_SESSION_INFORMATION SessionInfo =
(PPROCESS_SESSION_INFORMATION)ProcessInformation;
PVM_COUNTERS VmCounters = (PVM_COUNTERS)ProcessInformation;
+ PIO_COUNTERS IoCounters = (PIO_COUNTERS)ProcessInformation;
+ PQUOTA_LIMITS QuotaLimits = (PQUOTA_LIMITS)ProcessInformation;
PROCESS_DEVICEMAP_INFORMATION DeviceMap;
+ PUNICODE_STRING ImageName;
ULONG Cookie;
PAGED_CODE();
/* Check validity of Information Class */
+#if 0
Status = DefaultQueryInfoBufferCheck(ProcessInformationClass,
PsProcessInfoClass,
RTL_NUMBER_OF(PsProcessInfoClass),
ReturnLength,
PreviousMode);
if (!NT_SUCCESS(Status)) return Status;
+#endif
- /* Check if this isn't the cookie class */
- if(ProcessInformationClass != ProcessCookie)
- {
- /* Reference the process */
- Status = ObReferenceObjectByHandle(ProcessHandle,
- PROCESS_QUERY_INFORMATION,
- PsProcessType,
- PreviousMode,
- (PVOID*)&Process,
- NULL);
- if (!NT_SUCCESS(Status)) return Status;
- }
- else if(ProcessHandle != NtCurrentProcess())
+ if((ProcessInformationClass == ProcessCookie) &&
+ (ProcessHandle != NtCurrentProcess()))
{
/*
* Retreiving the process cookie is only allowed for the calling process
/* Basic process information */
case ProcessBasicInformation:
+ /* Set return length */
+ Length = sizeof(PROCESS_BASIC_INFORMATION);
+
+ 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;
+
/* Protect writes with SEH */
- _SEH_TRY
+ _SEH2_TRY
{
/* Write all the information from the EPROCESS/KPROCESS */
ProcessBasicInfo->ExitStatus = Process->ExitStatus;
ProcessBasicInfo->PebBaseAddress = Process->Peb;
ProcessBasicInfo->AffinityMask = Process->Pcb.Affinity;
- ProcessBasicInfo->UniqueProcessId = (ULONG)Process->
+ ProcessBasicInfo->UniqueProcessId = (ULONG_PTR)Process->
UniqueProcessId;
ProcessBasicInfo->InheritedFromUniqueProcessId =
(ULONG)Process->InheritedFromUniqueProcessId;
ProcessBasicInfo->BasePriority = Process->Pcb.BasePriority;
- /* Set return length */
- Length = sizeof(PROCESS_BASIC_INFORMATION);
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get exception code */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
- /* Quote limits and I/O Counters: not implemented */
+ /* Process quota limits */
case ProcessQuotaLimits:
+
+ Length = sizeof(QUOTA_LIMITS);
+ 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;
+
+ /* Indicate success */
+ Status = STATUS_SUCCESS;
+
+ _SEH2_TRY
+ {
+ /* Set max/min working set sizes */
+ QuotaLimits->MaximumWorkingSetSize =
+ Process->Vm.MaximumWorkingSetSize << PAGE_SHIFT;
+ QuotaLimits->MinimumWorkingSetSize =
+ Process->Vm.MinimumWorkingSetSize << PAGE_SHIFT;
+
+ /* Set default time limits */
+ QuotaLimits->TimeLimit.LowPart = (ULONG)-1;
+ QuotaLimits->TimeLimit.HighPart = (ULONG)-1;
+
+ /* Is quota block a default one? */
+ if (Process->QuotaBlock == &PspDefaultQuotaBlock)
+ {
+ /* Set default pools and pagefile limits */
+ QuotaLimits->PagedPoolLimit = (SIZE_T)-1;
+ QuotaLimits->NonPagedPoolLimit = (SIZE_T)-1;
+ QuotaLimits->PagefileLimit = (SIZE_T)-1;
+ }
+ else
+ {
+ /* Get limits from non-default quota block */
+ QuotaLimits->PagedPoolLimit =
+ Process->QuotaBlock->QuotaEntry[PagedPool].Limit;
+ QuotaLimits->NonPagedPoolLimit =
+ Process->QuotaBlock->QuotaEntry[NonPagedPool].Limit;
+ QuotaLimits->PagefileLimit =
+ Process->QuotaBlock->QuotaEntry[2].Limit;
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
+ break;
+
case ProcessIoCounters:
- Status = STATUS_NOT_IMPLEMENTED;
+
+ Length = sizeof(IO_COUNTERS);
+ 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;
+
+ _SEH2_TRY
+ {
+ IoCounters->ReadOperationCount = Process->ReadOperationCount.QuadPart;
+ IoCounters->ReadTransferCount = Process->ReadTransferCount.QuadPart;
+ IoCounters->WriteOperationCount = Process->WriteOperationCount.QuadPart;
+ IoCounters->WriteTransferCount = Process->WriteTransferCount.QuadPart;
+ IoCounters->OtherOperationCount = Process->OtherOperationCount.QuadPart;
+ IoCounters->OtherTransferCount = Process->OtherTransferCount.QuadPart;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Ignore exception */
+ }
+ _SEH2_END;
+
+ /* Set status to success in any case */
+ Status = STATUS_SUCCESS;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
/* Timing */
case ProcessTimes:
+ /* Set the return length */
+ Length = sizeof(KERNEL_USER_TIMES);
+
+ 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;
+
/* Protect writes with SEH */
- _SEH_TRY
+ _SEH2_TRY
{
/* Copy time information from EPROCESS/KPROCESS */
ProcessTime->CreateTime = Process->CreateTime;
ProcessTime->KernelTime.QuadPart = Process->Pcb.KernelTime *
100000LL;
ProcessTime->ExitTime = Process->ExitTime;
-
- /* Set the return length */
- Length = sizeof(KERNEL_USER_TIMES);
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get exception code */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
/* Process Debug Port */
case ProcessDebugPort:
+ /* Set return length */
+ Length = sizeof(HANDLE);
+
+ 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;
+
/* Protect write with SEH */
- _SEH_TRY
+ _SEH2_TRY
{
/* Return whether or not we have a debug port */
*(PHANDLE)ProcessInformation = (Process->DebugPort ?
(HANDLE)-1 : NULL);
-
- /* Set the return length*/
- Length = sizeof(HANDLE);
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get exception code */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
/* LDT, WS and VDM Information: not implemented */
case ProcessLdtInformation:
case ProcessWorkingSetWatch:
case ProcessWx86Information:
+
+ /* Reference the process */
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_QUERY_INFORMATION,
+ PsProcessType,
+ PreviousMode,
+ (PVOID*)&Process,
+ NULL);
+ if (!NT_SUCCESS(Status)) break;
+
+ DPRINT1("Not implemented: %lx\n", ProcessInformationClass);
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
Status = STATUS_NOT_IMPLEMENTED;
break;
case ProcessHandleCount:
+ /* 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;
+
/* Count the number of handles this process has */
- HandleCount = ObpGetHandleCountByHandleTable(Process->ObjectTable);
+ HandleCount = ObGetProcessHandleCount(Process);
/* Protect write in SEH */
- _SEH_TRY
+ _SEH2_TRY
{
/* Return the count of handles */
*(PULONG)ProcessInformation = HandleCount;
-
- /* Set the return length*/
- Length = sizeof(ULONG);
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get the exception code */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
/* Session ID for the process */
case ProcessSessionInformation:
+ /* Set the return length*/
+ Length = sizeof(PROCESS_SESSION_INFORMATION);
+
+ 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 write safety */
- _SEH_TRY
+ _SEH2_TRY
{
/* Write back the Session ID */
SessionInfo->SessionId = Process->Session;
-
- /* Set the return length */
- Length = sizeof(PROCESS_SESSION_INFORMATION);
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get the exception code */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
/* WOW64: Not implemented */
/* Virtual Memory Statistics */
case ProcessVmCounters:
+ /* Set the return length */
+ Length = sizeof(VM_COUNTERS);
+
+ 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 write safety */
- _SEH_TRY
+ _SEH2_TRY
{
/* Return data from EPROCESS */
VmCounters->PeakVirtualSize = Process->PeakVirtualSize;
VmCounters->PagefileUsage = Process->QuotaUsage[2];
VmCounters->PeakPagefileUsage = Process->QuotaPeak[2];
- /* Set the return length */
- *ReturnLength = sizeof(VM_COUNTERS);
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get the exception code */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
/* Hard Error Processing Mode */
case ProcessDefaultHardErrorMode:
+ /* 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 */
- _SEH_TRY
+ _SEH2_TRY
{
/* Write the current processing mode */
*(PULONG)ProcessInformation = Process->
DefaultHardErrorProcessing;
-
- /* Set the return length */
- Length = sizeof(ULONG);
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get the exception code */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
/* Priority Boosting status */
case ProcessPriorityBoost:
+ /* 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 */
- _SEH_TRY
+ _SEH2_TRY
{
/* Return boost status */
*(PULONG)ProcessInformation = Process->Pcb.DisableBoost ?
- FALSE : TRUE;
-
- /* Set the return length */
- Length = sizeof(ULONG);
+ TRUE : FALSE;
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get the exception code */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
/* DOS Device Map */
case ProcessDeviceMap:
+ /* Set the return length*/
+ Length = sizeof(PROCESS_DEVICEMAP_INFORMATION);
+
+ 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;
+
/* Query the device map information */
ObQueryDeviceMapInformation(Process, &DeviceMap);
/* Enter SEH for writing back data */
- _SEH_TRY
+ _SEH2_TRY
{
*(PPROCESS_DEVICEMAP_INFORMATION)ProcessInformation = DeviceMap;
-
- /* Set the return length */
- Length = sizeof(PROCESS_DEVICEMAP_INFORMATION);
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get the exception code */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
/* Priority class */
case ProcessPriorityClass:
+ /* Set the return length*/
+ Length = sizeof(PROCESS_PRIORITY_CLASS);
+
+ 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 */
- _SEH_TRY
+ _SEH2_TRY
{
/* Return current priority class */
- *(PUSHORT)ProcessInformation = Process->PriorityClass;
-
- /* Set the return length */
- Length = sizeof(USHORT);
+ PsPriorityClass->PriorityClass = Process->PriorityClass;
+ PsPriorityClass->Foreground = FALSE;
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get the exception code */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
case ProcessImageFileName:
+ /* Reference the process */
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_QUERY_INFORMATION,
+ PsProcessType,
+ PreviousMode,
+ (PVOID*)&Process,
+ NULL);
+ if (!NT_SUCCESS(Status)) break;
+
/* Get the image path */
- Status = PspGetImagePath(Process,
- (PUNICODE_STRING)ProcessInformation,
- ProcessInformationLength);
+ Status = SeLocateProcessImageName(Process, &ImageName);
+ if (NT_SUCCESS(Status))
+ {
+ /* Set return length */
+ Length = ImageName->MaximumLength +
+ sizeof(OBJECT_NAME_INFORMATION);
+
+ /* Make sure it's large enough */
+ if (Length <= ProcessInformationLength)
+ {
+ /* Enter SEH to protect write */
+ _SEH2_TRY
+ {
+ /* Copy it */
+ RtlCopyMemory(ProcessInformation,
+ ImageName,
+ Length);
+
+ /* Update pointer */
+ ((PUNICODE_STRING)ProcessInformation)->Buffer =
+ (PWSTR)((PUNICODE_STRING)ProcessInformation + 1);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ }
+ else
+ {
+ /* Buffer too small */
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+
+ /* Free the image path */
+ ExFreePool(ImageName);
+ }
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
/* Per-process security cookie */
/* Get the current process and cookie */
Process = PsGetCurrentProcess();
Cookie = Process->Cookie;
- if(!Cookie)
+ if (!Cookie)
{
LARGE_INTEGER SystemTime;
ULONG NewCookie;
Cookie = InterlockedCompareExchange((LONG*)&Process->Cookie,
NewCookie,
Cookie);
- if(!Cookie) Cookie = NewCookie;
+ if (!Cookie) Cookie = NewCookie;
/* Set return length */
Length = sizeof(ULONG);
}
/* Enter SEH to protect write */
- _SEH_TRY
+ _SEH2_TRY
{
/* Write back the cookie */
*(PULONG)ProcessInformation = Cookie;
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get the exception code */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
break;
/* Not yet implemented, or unknown */
case ProcessAffinityMask:
case ProcessForegroundInformation:
default:
+ DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass);
Status = STATUS_INVALID_INFO_CLASS;
}
/* Protect write with SEH */
- _SEH_TRY
+ _SEH2_TRY
{
/* Check if caller wanted return length */
if (ReturnLength) *ReturnLength = Length;
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get exception code */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
- /* If we referenced the process, dereference it */
- if(ProcessInformationClass != ProcessCookie) ObDereferenceObject(Process);
return Status;
}
NTSTATUS Status;
HANDLE PortHandle = NULL;
HANDLE TokenHandle = NULL;
- PROCESS_SESSION_INFORMATION SessionInfo;
- PEPORT ExceptionPort;
+ PROCESS_SESSION_INFORMATION SessionInfo = {0};
+ PROCESS_PRIORITY_CLASS PriorityClass = {0};
+ PVOID ExceptionPort;
PAGED_CODE();
/* Verify Information Class validity */
+#if 0
Status = DefaultSetInfoBufferCheck(ProcessInformationClass,
PsProcessInfoClass,
RTL_NUMBER_OF(PsProcessInfoClass),
ProcessInformationLength,
PreviousMode);
if (!NT_SUCCESS(Status)) return Status;
+#endif
/* Check what class this is */
Access = PROCESS_SET_INFORMATION;
/* Check what kind of information class this is */
switch (ProcessInformationClass)
{
- /* Quotas and priorities: not implemented */
- case ProcessQuotaLimits:
- case ProcessBasePriority:
- case ProcessRaisePriority:
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
/* Error/Exception Port */
case ProcessExceptionPort:
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(HANDLE))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
/* Use SEH for capture */
- _SEH_TRY
+ _SEH2_TRY
{
/* Capture the handle */
PortHandle = *(PHANDLE)ProcessInformation;
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get the exception code */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
if (!NT_SUCCESS(Status)) break;
/* Get the LPC Port */
/* Security Token */
case ProcessAccessToken:
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(PROCESS_ACCESS_TOKEN))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
/* Use SEH for capture */
- _SEH_TRY
+ _SEH2_TRY
{
/* Save the token handle */
TokenHandle = ((PPROCESS_ACCESS_TOKEN)ProcessInformation)->
Token;
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get the exception code */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
if (!NT_SUCCESS(Status)) break;
/* Assign the actual token */
/* Hard error processing */
case ProcessDefaultHardErrorMode:
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(ULONG))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
/* Enter SEH for direct buffer read */
- _SEH_TRY
+ _SEH2_TRY
{
/* Update the current mode abd return the previous one */
InterlockedExchange((LONG*)&Process->DefaultHardErrorProcessing,
*(PLONG)ProcessInformation);
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get exception code */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
break;
/* Session ID */
case ProcessSessionInformation:
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(PROCESS_SESSION_INFORMATION))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
/* Enter SEH for capture */
- _SEH_TRY
+ _SEH2_TRY
{
/* Capture the caller's buffer */
SessionInfo = *(PPROCESS_SESSION_INFORMATION)ProcessInformation;
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get the exception code */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
if (!NT_SUCCESS(Status)) break;
/* Setting the session id requires the SeTcbPrivilege */
KeAttachProcess(&Process->Pcb);
/* Enter SEH for write to user-mode PEB */
- _SEH_TRY
+ _SEH2_TRY
{
/* Write the session ID */
Process->Peb->SessionId = SessionInfo.SessionId;
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get exception code */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
/* Detach from the process */
KeDetachProcess();
//PsUnlockProcess(Process);
break;
- /* Priority class: HACK! */
case ProcessPriorityClass:
+
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(PROCESS_PRIORITY_CLASS))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Enter SEH for capture */
+ _SEH2_TRY
+ {
+ /* Capture the caller's buffer */
+ PriorityClass = *(PPROCESS_PRIORITY_CLASS)ProcessInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ if (!NT_SUCCESS(Status)) break;
+
+ /* Check for invalid PriorityClass value */
+ if (PriorityClass.PriorityClass > PROCESS_PRIORITY_CLASS_ABOVE_NORMAL)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ /* TODO: Check privileges */
+
+ /* Check if we have a job */
+ if (Process->Job)
+ {
+ DPRINT1("Jobs not yet supported\n");
+ }
+
+ /* Set process priority class */
+ Process->PriorityClass = PriorityClass.PriorityClass;
+
+ /* Set process priority mode (foreground or background) */
+ PsSetProcessPriorityByClass(Process,
+ !PriorityClass.Foreground ? PsProcessPriorityBackground :
+ PsProcessPriorityForeground);
+
+ Status = STATUS_SUCCESS;
break;
/* We currently don't implement any of these */
+ case ProcessQuotaLimits:
+ case ProcessBasePriority:
+ case ProcessRaisePriority:
case ProcessLdtInformation:
case ProcessLdtSize:
case ProcessIoPortHandlers:
case ProcessUserModeIOPL:
case ProcessEnableAlignmentFaultFixup:
case ProcessAffinityMask:
+ DPRINT1("Not implemented: %lx\n", ProcessInformationClass);
Status = STATUS_NOT_IMPLEMENTED;
break;
case ProcessWow64Information:
case ProcessDebugPort:
default:
+ DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass);
Status = STATUS_INVALID_INFO_CLASS;
}
}
/*
- * @unimplemented
+ * @implemented
*/
NTSTATUS
NTAPI
IN ULONG ThreadInformationLength)
{
PETHREAD Thread;
+ ULONG Access;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS Status;
+ HANDLE TokenHandle = NULL;
+ KPRIORITY Priority = 0;
+ KAFFINITY Affinity = 0, CombinedAffinity;
+ PVOID Address = NULL;
+ PEPROCESS Process;
+ ULONG DisableBoost = 0;
+ ULONG IdealProcessor = 0;
+ PTEB Teb;
+ ULONG TlsIndex = 0;
+ PVOID *ExpansionSlots;
+ PETHREAD ProcThread;
PAGED_CODE();
- DPRINT1("%s called for: %d\n", __FUNCTION__, ThreadInformationClass);
- /* FIXME: This is REALLY wrong. Some types don't need THREAD_SET_INFORMATION */
- /* FIXME: We should also check for certain things before doing the reference */
+ /* Verify Information Class validity */
+#if 0
+ Status = DefaultSetInfoBufferCheck(ThreadInformationClass,
+ PsThreadInfoClass,
+ RTL_NUMBER_OF(PsThreadInfoClass),
+ ThreadInformation,
+ ThreadInformationLength,
+ PreviousMode);
+ if (!NT_SUCCESS(Status)) return Status;
+#endif
+
+ /* Check what class this is */
+ Access = THREAD_SET_INFORMATION;
+ if (ThreadInformationClass == ThreadImpersonationToken)
+ {
+ /* Setting the impersonation token needs a special mask */
+ Access = THREAD_SET_THREAD_TOKEN;
+ }
+
+ /* Reference the process */
Status = ObReferenceObjectByHandle(ThreadHandle,
- THREAD_SET_INFORMATION,
+ Access,
PsThreadType,
PreviousMode,
(PVOID*)&Thread,
NULL);
- if (NT_SUCCESS(Status))
- {
-#if 0
- switch (ThreadInformationClass)
- {
- case ThreadPriority:
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Check what kind of information class this is */
+ switch (ThreadInformationClass)
+ {
+ /* Thread priority */
+ case ThreadPriority:
+
+ /* Check buffer length */
+ if (ThreadInformationLength != sizeof(KPRIORITY))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Use SEH for capture */
+ _SEH2_TRY
+ {
+ /* Get the priority */
+ Priority = *(PLONG)ThreadInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ if (!NT_SUCCESS(Status)) break;
- if (u.Priority < LOW_PRIORITY || u.Priority >= MAXIMUM_PRIORITY)
+ /* Validate it */
+ if ((Priority > HIGH_PRIORITY) ||
+ (Priority <= LOW_PRIORITY))
+ {
+ /* Fail */
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ /* Set the priority */
+ KeSetPriorityThread(&Thread->Tcb, Priority);
+ break;
+
+ case ThreadBasePriority:
+
+ /* Check buffer length */
+ if (ThreadInformationLength != sizeof(LONG))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Use SEH for capture */
+ _SEH2_TRY
+ {
+ /* Get the priority */
+ Priority = *(PLONG)ThreadInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ if (!NT_SUCCESS(Status)) break;
+
+ /* Validate it */
+ if ((Priority > THREAD_BASE_PRIORITY_MAX) ||
+ (Priority < THREAD_BASE_PRIORITY_MIN))
+ {
+ /* These ones are OK */
+ if ((Priority != THREAD_BASE_PRIORITY_LOWRT + 1) &&
+ (Priority != THREAD_BASE_PRIORITY_IDLE - 1))
{
- Status = STATUS_INVALID_PARAMETER;
- break;
+ /* Check if the process is real time */
+ if (PsGetCurrentProcess()->PriorityClass !=
+ PROCESS_PRIORITY_CLASS_REALTIME)
+ {
+ /* It isn't, fail */
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
}
- KeSetPriorityThread(&Thread->Tcb, u.Priority);
+ }
+
+ /* Set the base priority */
+ KeSetBasePriorityThread(&Thread->Tcb, Priority);
+ break;
+
+ case ThreadAffinityMask:
+
+ /* Check buffer length */
+ if (ThreadInformationLength != sizeof(ULONG_PTR))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
break;
+ }
+
+ /* Use SEH for capture */
+ _SEH2_TRY
+ {
+ /* Get the priority */
+ Affinity = *(PULONG_PTR)ThreadInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ if (!NT_SUCCESS(Status)) break;
- case ThreadBasePriority:
- KeSetBasePriorityThread (&Thread->Tcb, u.Increment);
+ /* Validate it */
+ if (!Affinity)
+ {
+ /* Fail */
+ Status = STATUS_INVALID_PARAMETER;
break;
+ }
- case ThreadAffinityMask:
+ /* Get the process */
+ Process = Thread->ThreadsProcess;
- /* Check if this is valid */
- DPRINT1("%lx, %lx\n", Thread->ThreadsProcess->Pcb.Affinity, u.Affinity);
- if ((Thread->ThreadsProcess->Pcb.Affinity & u.Affinity) !=
- u.Affinity)
+ /* Try to acquire rundown */
+ if (ExAcquireRundownProtection(&Process->RundownProtect))
+ {
+ /* Lock it */
+ KeEnterCriticalRegion();
+ ExAcquirePushLockShared(&Process->ProcessLock);
+
+ /* Combine masks */
+ CombinedAffinity = Affinity & Process->Pcb.Affinity;
+ if (CombinedAffinity != Affinity)
{
- DPRINT1("Wrong affinity given\n");
+ /* Fail */
Status = STATUS_INVALID_PARAMETER;
}
else
{
- Status = KeSetAffinityThread(&Thread->Tcb, u.Affinity);
+ /* Set the affinity */
+ KeSetAffinityThread(&Thread->Tcb, CombinedAffinity);
}
+
+ /* Release the lock and rundown */
+ ExReleasePushLockShared(&Process->ProcessLock);
+ KeLeaveCriticalRegion();
+ ExReleaseRundownProtection(&Process->RundownProtect);
+ }
+ else
+ {
+ /* Too late */
+ Status = STATUS_PROCESS_IS_TERMINATING;
+ }
+
+ /* Return status */
+ break;
+
+ case ThreadImpersonationToken:
+
+ /* Check buffer length */
+ if (ThreadInformationLength != sizeof(HANDLE))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Use SEH for capture */
+ _SEH2_TRY
+ {
+ /* Save the token handle */
+ TokenHandle = *(PHANDLE)ThreadInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ if (!NT_SUCCESS(Status)) break;
+
+ /* Assign the actual token */
+ Status = PsAssignImpersonationToken(Thread, TokenHandle);
+ break;
+
+ case ThreadQuerySetWin32StartAddress:
+
+ /* Check buffer length */
+ if (ThreadInformationLength != sizeof(ULONG_PTR))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
break;
+ }
- case ThreadImpersonationToken:
- Status = PsAssignImpersonationToken (Thread, u.Handle);
+ /* Use SEH for capture */
+ _SEH2_TRY
+ {
+ /* Get the priority */
+ Address = *(PVOID*)ThreadInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ if (!NT_SUCCESS(Status)) break;
+
+ /* Set the address */
+ Thread->Win32StartAddress = Address;
+ break;
+
+ case ThreadIdealProcessor:
+
+ /* Check buffer length */
+ if (ThreadInformationLength != sizeof(ULONG_PTR))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
break;
+ }
- case ThreadQuerySetWin32StartAddress:
- Thread->Win32StartAddress = u.Address;
+ /* Use SEH for capture */
+ _SEH2_TRY
+ {
+ /* Get the priority */
+ IdealProcessor = *(PULONG_PTR)ThreadInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ if (!NT_SUCCESS(Status)) break;
+
+ /* Validate it */
+ if (IdealProcessor > MAXIMUM_PROCESSORS)
+ {
+ /* Fail */
+ Status = STATUS_INVALID_PARAMETER;
break;
+ }
- default:
- /* Shoult never occure if the data table is correct */
- KEBUGCHECK(0);
- }
-#endif
- ObDereferenceObject (Thread);
+ /* Set the ideal */
+ Status = KeSetIdealProcessorThread(&Thread->Tcb,
+ (CCHAR)IdealProcessor);
+
+ /* Get the TEB and protect the thread */
+ Teb = Thread->Tcb.Teb;
+ if ((Teb) && (ExAcquireRundownProtection(&Thread->RundownProtect)))
+ {
+ /* Save the ideal processor */
+ Teb->IdealProcessor = Thread->Tcb.IdealProcessor;
+
+ /* Release rundown protection */
+ ExReleaseRundownProtection(&Thread->RundownProtect);
+ }
+
+ break;
+
+ case ThreadPriorityBoost:
+
+ /* Check buffer length */
+ if (ThreadInformationLength != sizeof(ULONG_PTR))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Use SEH for capture */
+ _SEH2_TRY
+ {
+ /* Get the priority */
+ DisableBoost = *(PULONG_PTR)ThreadInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ if (!NT_SUCCESS(Status)) break;
+
+ /* Call the kernel */
+ KeSetDisableBoostThread(&Thread->Tcb, (BOOLEAN)DisableBoost);
+ break;
+
+ case ThreadZeroTlsCell:
+
+ /* Check buffer length */
+ if (ThreadInformationLength != sizeof(ULONG_PTR))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Use SEH for capture */
+ _SEH2_TRY
+ {
+ /* Get the priority */
+ TlsIndex = *(PULONG_PTR)ThreadInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ if (!NT_SUCCESS(Status)) break;
+
+ /* This is only valid for the current thread */
+ if (Thread != PsGetCurrentThread())
+ {
+ /* Fail */
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ /* Get the process */
+ Process = Thread->ThreadsProcess;
+
+ /* Loop the threads */
+ ProcThread = PsGetNextProcessThread(Process, NULL);
+ while (ProcThread)
+ {
+ /* Acquire rundown */
+ if (ExAcquireRundownProtection(&ProcThread->RundownProtect))
+ {
+ /* Get the TEB */
+ Teb = ProcThread->Tcb.Teb;
+ if (Teb)
+ {
+ /* Check if we're in the expansion range */
+ if (TlsIndex > TLS_MINIMUM_AVAILABLE - 1)
+ {
+ if (TlsIndex < (TLS_MINIMUM_AVAILABLE +
+ TLS_EXPANSION_SLOTS) - 1)
+ {
+ /* Check if we have expansion slots */
+ ExpansionSlots = Teb->TlsExpansionSlots;
+ if (ExpansionSlots)
+ {
+ /* Clear the index */
+ ExpansionSlots[TlsIndex - TLS_MINIMUM_AVAILABLE] = 0;
+ }
+ }
+ }
+ else
+ {
+ /* Clear the index */
+ Teb->TlsSlots[TlsIndex] = NULL;
+ }
+ }
+
+ /* Release rundown */
+ ExReleaseRundownProtection(&ProcThread->RundownProtect);
+ }
+
+ /* Go to the next thread */
+ ProcThread = PsGetNextProcessThread(Process, ProcThread);
+ }
+
+ /* All done */
+ break;
+
+ default:
+ /* We don't implement it yet */
+ DPRINT1("Not implemented: %lx\n", ThreadInformationClass);
+ Status = STATUS_NOT_IMPLEMENTED;
}
+ /* Dereference and return status */
+ ObDereferenceObject(Thread);
return Status;
}
PETHREAD Thread;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
+ ULONG Access;
+ ULONG Length = 0;
+ PTHREAD_BASIC_INFORMATION ThreadBasicInfo =
+ (PTHREAD_BASIC_INFORMATION)ThreadInformation;
+ PKERNEL_USER_TIMES ThreadTime = (PKERNEL_USER_TIMES)ThreadInformation;
+ KIRQL OldIrql;
PAGED_CODE();
- DPRINT1("%s called for: %d\n", __FUNCTION__, ThreadInformationClass);
+ if (PreviousMode != KernelMode)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWrite(ThreadInformation,
+ ThreadInformationLength,
+ sizeof(ULONG));
+
+ if (ReturnLength)
+ {
+ ProbeForWriteUlong(ReturnLength);
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ if (!NT_SUCCESS(Status)) return Status;
+ }
+
+ /* Check what class this is */
+ Access = THREAD_QUERY_INFORMATION;
+
+ /* Reference the process */
Status = ObReferenceObjectByHandle(ThreadHandle,
- THREAD_QUERY_INFORMATION,
+ Access,
PsThreadType,
PreviousMode,
(PVOID*)&Thread,
NULL);
if (!NT_SUCCESS(Status)) return Status;
-#if 0
+ /* Check what kind of information class this is */
switch (ThreadInformationClass)
{
+ /* Basic thread information */
case ThreadBasicInformation:
- /* A test on W2K agains ntdll shows NtQueryInformationThread return STATUS_PENDING
- * as ExitStatus for current/running thread, while KETHREAD's ExitStatus is
- * 0. So do the conversion here:
- * -Gunnar */
- u.TBI.ExitStatus = (Thread->ExitStatus == 0) ? STATUS_PENDING : Thread->ExitStatus;
- u.TBI.TebBaseAddress = (PVOID)Thread->Tcb.Teb;
- u.TBI.ClientId = Thread->Cid;
- u.TBI.AffinityMask = Thread->Tcb.Affinity;
- u.TBI.Priority = Thread->Tcb.Priority;
- u.TBI.BasePriority = KeQueryBasePriorityThread(&Thread->Tcb);
+
+ /* Set return length */
+ Length = sizeof(THREAD_BASIC_INFORMATION);
+
+ if (ThreadInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+ /* Protect writes with SEH */
+ _SEH2_TRY
+ {
+ /* Write all the information from the ETHREAD/KTHREAD */
+ ThreadBasicInfo->ExitStatus = Thread->ExitStatus;
+ ThreadBasicInfo->TebBaseAddress = (PVOID)Thread->Tcb.Teb;
+ ThreadBasicInfo->ClientId = Thread->Cid;
+ ThreadBasicInfo->AffinityMask = Thread->Tcb.Affinity;
+ ThreadBasicInfo->Priority = Thread->Tcb.Priority;
+ ThreadBasicInfo->BasePriority = KeQueryBasePriorityThread(&Thread->Tcb);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
break;
+ /* Thread time information */
case ThreadTimes:
- u.TTI.KernelTime.QuadPart = Thread->Tcb.KernelTime * 100000LL;
- u.TTI.UserTime.QuadPart = Thread->Tcb.UserTime * 100000LL;
- u.TTI.CreateTime = Thread->CreateTime;
- /*This works*/
- u.TTI.ExitTime = Thread->ExitTime;
+
+ /* Set the return length */
+ Length = sizeof(KERNEL_USER_TIMES);
+
+ if (ThreadInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+ /* Protect writes with SEH */
+ _SEH2_TRY
+ {
+ /* Copy time information from ETHREAD/KTHREAD */
+ ThreadTime->KernelTime.QuadPart = Thread->Tcb.KernelTime *
+ 100000LL;
+ ThreadTime->UserTime.QuadPart = Thread->Tcb.UserTime *
+ 100000LL;
+ ThreadTime->CreateTime = Thread->CreateTime;
+ ThreadTime->ExitTime = Thread->ExitTime;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
break;
case ThreadQuerySetWin32StartAddress:
- u.Address = Thread->Win32StartAddress;
+
+ /* Set the return length*/
+ Length = sizeof(PVOID);
+
+ if (ThreadInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+ /* Protect write with SEH */
+ _SEH2_TRY
+ {
+ /* Return the Win32 Start Address */
+ *(PVOID*)ThreadInformation = Thread->Win32StartAddress;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
break;
case ThreadPerformanceCount:
- /* Nebbett says this class is always zero */
- u.Count.QuadPart = 0;
+
+ /* Set the return length*/
+ Length = sizeof(LARGE_INTEGER);
+
+ if (ThreadInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+ /* Protect write with SEH */
+ _SEH2_TRY
+ {
+ /* FIXME */
+ (*(PLARGE_INTEGER)ThreadInformation).QuadPart = 0;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
break;
case ThreadAmILastThread:
- if (Thread->ThreadsProcess->ThreadListHead.Flink->Flink ==
- &Thread->ThreadsProcess->ThreadListHead)
+
+ /* Set the return length*/
+ Length = sizeof(ULONG);
+
+ if (ThreadInformationLength != Length)
{
- u.Last = TRUE;
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
}
- else
+ /* Protect write with SEH */
+ _SEH2_TRY
{
- u.Last = FALSE;
+ /* Return whether or not we are the last thread */
+ *(PULONG)ThreadInformation = ((Thread->ThreadsProcess->
+ ThreadListHead.Flink->Flink ==
+ &Thread->ThreadsProcess->
+ ThreadListHead) ?
+ TRUE : FALSE);
}
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
break;
case ThreadIsIoPending:
+
+ /* Set the return length*/
+ Length = sizeof(ULONG);
+
+ if (ThreadInformationLength != Length)
{
- KIRQL OldIrql;
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+ /* Raise the IRQL to protect the IRP list */
+ KeRaiseIrql(APC_LEVEL, &OldIrql);
- /* Raise the IRQL to protect the IRP list */
- KeRaiseIrql(APC_LEVEL, &OldIrql);
- u.IsIoPending = !IsListEmpty(&Thread->IrpList);
- KeLowerIrql(OldIrql);
+ /* Protect write with SEH */
+ _SEH2_TRY
+ {
+ /* Check if the IRP list is empty or not */
+ *(PULONG)ThreadInformation = !IsListEmpty(&Thread->IrpList);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ /* Lower IRQL back */
+ KeLowerIrql(OldIrql);
+ break;
+
+ case ThreadDescriptorTableEntry:
+ DPRINT1("NtQueryInformationThread(): case ThreadDescriptorTableEntry not implemented!\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case ThreadPriorityBoost:
+
+ /* Set the return length*/
+ Length = sizeof(ULONG);
+
+ if (ThreadInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
+ _SEH2_TRY
+ {
+ *(PULONG)ThreadInformation = Thread->Tcb.DisableBoost ? 1 : 0;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ break;
+
+ /* Anything else */
default:
- /* Shoult never occure if the data table is correct */
- KEBUGCHECK(0);
+
+ /* Not yet implemented */
+ DPRINT1("Not implemented: %lx\n", ThreadInformationClass);
+ Status = STATUS_NOT_IMPLEMENTED;
}
-#endif
+
+ /* Protect write with SEH */
+ _SEH2_TRY
+ {
+ /* Check if caller wanted return length */
+ if (ReturnLength) *ReturnLength = Length;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ /* Dereference the thread, and return */
ObDereferenceObject(Thread);
- return(Status);
+ return Status;
}
/* EOF */