ICI_SQ_SAME( 0, 1, 0 ), /* ProcessUnknown33 */
ICI_SQ_SAME( 0, 1, 0 ), /* ProcessUnknown34 */
ICI_SQ_SAME( 0, 1, 0 ), /* ProcessUnknown35 */
-
+
ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY), /* ProcessCookie */
};
{
BOOLEAN Implemented;
ULONG Size;
-} QueryInformationData[MaxThreadInfoClass + 1] =
+} QueryInformationData[MaxThreadInfoClass + 1] =
{
{TRUE, sizeof(THREAD_BASIC_INFORMATION)}, // ThreadBasicInformation
{TRUE, sizeof(KERNEL_USER_TIMES)}, // ThreadTimes
{
BOOLEAN Implemented;
ULONG Size;
-} SetInformationData[MaxThreadInfoClass + 1] =
+} SetInformationData[MaxThreadInfoClass + 1] =
{
{TRUE, 0}, // ThreadBasicInformation
{TRUE, 0}, // ThreadTimes
PEPROCESS Process;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
-
+
PAGED_CODE();
-
+
PreviousMode = ExGetPreviousMode();
-
- DefaultQueryInfoBufferCheck(ProcessInformationClass,
- PsProcessInfoClass,
- ProcessInformation,
- ProcessInformationLength,
- ReturnLength,
- PreviousMode,
- &Status);
+
+ Status = DefaultQueryInfoBufferCheck(ProcessInformationClass,
+ PsProcessInfoClass,
+ sizeof(PsProcessInfoClass) / sizeof(PsProcessInfoClass[0]),
+ ProcessInformation,
+ ProcessInformationLength,
+ ReturnLength,
+ PreviousMode);
if(!NT_SUCCESS(Status))
{
DPRINT1("NtQueryInformationProcess() failed, Status: 0x%x\n", Status);
return Status;
}
-
+
if(ProcessInformationClass != ProcessCookie)
{
Status = ObReferenceObjectByHandle(ProcessHandle,
real handle actually represents the current process. */
return STATUS_INVALID_PARAMETER;
}
-
+
switch (ProcessInformationClass)
{
case ProcessBasicInformation:
ProcessBasicInformationP->PebBaseAddress = Process->Peb;
ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity;
ProcessBasicInformationP->UniqueProcessId =
- Process->UniqueProcessId;
+ (ULONG)Process->UniqueProcessId;
ProcessBasicInformationP->InheritedFromUniqueProcessId =
- Process->InheritedFromUniqueProcessId;
+ (ULONG)Process->InheritedFromUniqueProcessId;
ProcessBasicInformationP->BasePriority =
Process->Pcb.BasePriority;
_SEH_END;
break;
}
-
+
case ProcessLdtInformation:
case ProcessWorkingSetWatch:
case ProcessWx86Information:
case ProcessHandleCount:
{
ULONG HandleCount = ObpGetHandleCountByHandleTable(Process->ObjectTable);
-
+
_SEH_TRY
{
*(PULONG)ProcessInformation = HandleCount;
_SEH_TRY
{
- SessionInfo->SessionId = Process->SessionId;
+ SessionInfo->SessionId = Process->Session;
if (ReturnLength)
{
*ReturnLength = sizeof(PROCESS_SESSION_INFORMATION);
_SEH_END;
break;
}
-
+
case ProcessWow64Information:
DPRINT1("We currently don't support the ProcessWow64Information information class!\n");
Status = STATUS_NOT_IMPLEMENTED;
case ProcessVmCounters:
{
PVM_COUNTERS pOut = (PVM_COUNTERS)ProcessInformation;
-
+
_SEH_TRY
{
pOut->PeakVirtualSize = Process->PeakVirtualSize;
* incompatibilities in current headers (no unnamed union),
* I opted for cast.
*/
- pOut->VirtualSize = (ULONG)Process->VirtualSize.QuadPart;
+ pOut->VirtualSize = (ULONG)Process->VirtualSize;
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;
+ pOut->QuotaPeakPagedPoolUsage = Process->QuotaPeak[0]; // TODO: Verify!
+ pOut->QuotaPagedPoolUsage = Process->QuotaUsage[0]; // TODO: Verify!
+ pOut->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[1]; // TODO: Verify!
+ pOut->QuotaNonPagedPoolUsage = Process->QuotaUsage[1]; // TODO: Verify!
+ pOut->PagefileUsage = Process->QuotaUsage[2];
+ pOut->PeakPagefileUsage = Process->QuotaPeak[2];
if (ReturnLength)
{
case ProcessPriorityBoost:
{
PULONG BoostEnabled = (PULONG)ProcessInformation;
-
+
_SEH_TRY
{
*BoostEnabled = Process->Pcb.DisableBoost ? FALSE : TRUE;
case ProcessDeviceMap:
{
PROCESS_DEVICEMAP_INFORMATION DeviceMap;
-
+
ObQueryDeviceMapInformation(Process, &DeviceMap);
_SEH_TRY
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;
- BOOLEAN Attached;
ULONG ImagePathLen = 0;
+ PROS_SECTION_OBJECT Section;
PUNICODE_STRING DstPath = (PUNICODE_STRING)ProcessInformation;
+ PWSTR SrcBuffer = NULL, DstBuffer = (PWSTR)(DstPath + 1);
- /* we need to attach to the process to make sure we're in the right context! */
- Attached = Process != PsGetCurrentProcess();
+ Section = (PROS_SECTION_OBJECT)Process->SectionObject;
- if(Attached)
- KeAttachProcess(&Process->Pcb);
-
- _SEH_TRY
+ if (Section != NULL && Section->FileObject != NULL)
{
- ProcParams = Process->Peb->ProcessParameters;
- ImagePathLen = ProcParams->ImagePathName.Length;
+ /* FIXME - check for SEC_IMAGE and/or SEC_FILE instead
+ of relying on FileObject being != NULL? */
+ SrcBuffer = Section->FileObject->FileName.Buffer;
+ if (SrcBuffer != NULL)
+ {
+ ImagePathLen = Section->FileObject->FileName.Length;
+ }
}
- _SEH_HANDLE
+
+ if(ProcessInformationLength < sizeof(UNICODE_STRING) + ImagePathLen + sizeof(WCHAR))
{
- Status = _SEH_GetExceptionCode();
+ Status = STATUS_INFO_LENGTH_MISMATCH;
}
- _SEH_END;
-
- if(NT_SUCCESS(Status))
+ else
{
- if(ProcessInformationLength < sizeof(UNICODE_STRING) + ImagePathLen + sizeof(WCHAR))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
- {
- PWSTR StrSource = NULL;
-
- RtlZeroMemory(&LocalDest, sizeof(LocalDest));
-
- /* 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;
+ /* copy the string manually, don't use RtlCopyUnicodeString with DstPath! */
+ DstPath->Length = ImagePathLen;
+ DstPath->MaximumLength = ImagePathLen + sizeof(WCHAR);
+ DstPath->Buffer = DstBuffer;
+ if (ImagePathLen != 0)
+ {
+ RtlCopyMemory(DstBuffer,
+ SrcBuffer,
+ ImagePathLen);
+ }
+ DstBuffer[ImagePathLen / sizeof(WCHAR)] = L'\0';
+
+ Status = STATUS_SUCCESS;
}
_SEH_HANDLE
{
- Status = _SEH_GetExceptionCode();
+ 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 */
- if(Attached)
- 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!!! */
- if(Attached)
- KeDetachProcess();
- }
- else
- {
- /* FIXME - what to do here? */
- Status = STATUS_UNSUCCESSFUL;
- }
- break;
+ break;
}
-
+
case ProcessCookie:
{
ULONG Cookie;
-
+
/* receive the process cookie, this is only allowed for the current
process! */
LARGE_INTEGER SystemTime;
ULONG NewCookie;
PKPRCB Prcb;
-
+
/* generate a new cookie */
-
+
KeQuerySystemTime(&SystemTime);
-
+
Prcb = KeGetCurrentPrcb();
NewCookie = Prcb->KeSystemCalls ^ Prcb->InterruptTime ^
SystemTime.u.LowPart ^ SystemTime.u.HighPart;
-
+
/* try to set the new cookie, return the current one if another thread
set it in the meanwhile */
Cookie = InterlockedCompareExchange((LONG*)&Process->Cookie,
Cookie = NewCookie;
}
}
-
+
_SEH_TRY
{
*(PULONG)ProcessInformation = Cookie;
Status = _SEH_GetExceptionCode();
}
_SEH_END;
-
+
break;
}
{
ObDereferenceObject(Process);
}
-
+
return Status;
}
KPROCESSOR_MODE PreviousMode;
ACCESS_MASK Access;
NTSTATUS Status = STATUS_SUCCESS;
-
+
PAGED_CODE();
-
+
PreviousMode = ExGetPreviousMode();
- DefaultSetInfoBufferCheck(ProcessInformationClass,
- PsProcessInfoClass,
- ProcessInformation,
- ProcessInformationLength,
- PreviousMode,
- &Status);
+ Status = DefaultSetInfoBufferCheck(ProcessInformationClass,
+ PsProcessInfoClass,
+ sizeof(PsProcessInfoClass) / sizeof(PsProcessInfoClass[0]),
+ ProcessInformation,
+ ProcessInformationLength,
+ PreviousMode);
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;
break;
}
-
+
Status = ObReferenceObjectByHandle(ProcessHandle,
Access,
PsProcessType,
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
*/
if(NT_SUCCESS(Status))
{
/* lock the process to be thread-safe! */
-
- Status = PsLockProcess(Process, FALSE);
+
+ Status = PsLockProcess((PROS_EPROCESS)Process, FALSE);
if(NT_SUCCESS(Status))
{
/*
ObDereferenceObject(ExceptionPort);
Status = STATUS_PORT_ALREADY_SET;
}
- PsUnlockProcess(Process);
+ PsUnlockProcess((PROS_EPROCESS)Process);
}
else
{
_SEH_END;
break;
}
-
+
case ProcessSessionInformation:
{
PROCESS_SESSION_INFORMATION SessionInfo;
Status = STATUS_SUCCESS;
-
+
RtlZeroMemory(&SessionInfo, sizeof(SessionInfo));
-
+
_SEH_TRY
{
/* copy the structure to the stack */
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!
*/
Status = STATUS_PRIVILEGE_NOT_HELD;
break;
}
-
+
/* FIXME - update the session id for the process token */
- Status = PsLockProcess(Process, FALSE);
+ Status = PsLockProcess((PROS_EPROCESS)Process, FALSE);
if(NT_SUCCESS(Status))
{
- Process->SessionId = SessionInfo.SessionId;
+ Process->Session = SessionInfo.SessionId;
/* Update the session id in the PEB structure */
if(Process->Peb != NULL)
KeDetachProcess();
}
- PsUnlockProcess(Process);
+ PsUnlockProcess((PROS_EPROCESS)Process);
}
}
break;
}
-
+
case ProcessPriorityClass:
{
PROCESS_PRIORITY_CLASS ppc;
Status = _SEH_GetExceptionCode();
}
_SEH_END;
-
+
if(NT_SUCCESS(Status))
{
}
-
+
break;
}
-
+
case ProcessLdtInformation:
case ProcessLdtSize:
case ProcessIoPortHandlers:
* PiQuerySystemProcessInformation
*
* DESCRIPTION
- * Compute the size of a process+thread snapshot as
+ * Compute the size of a process+thread snapshot as
* expected by NtQuerySystemInformation.
*
* RETURN VALUE
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. */
ExAcquireFastMutex(&PspActiveProcessMutex);
SizeOnly = TRUE;
continue;
}
- /*
- * Get a reference to the
+ /*
+ * Get a reference to the
* process descriptor we are
* handling.
*/
CurrentP = CONTAINING_RECORD(
CurrentEntryP,
- EPROCESS,
+ EPROCESS,
ProcessListEntry
);
/*
/* THREAD */
for ( pInfoT = & CurrentP->ThreadSysInfo [0],
CurrentEntryT = CurrentP->ThreadListHead.Flink;
-
+
(CurrentEntryT != & CurrentP->ThreadListHead);
-
+
pInfoT = & CurrentP->ThreadSysInfo [pInfoP->ThreadCount],
CurrentEntryT = CurrentEntryT->Flink
)
SizeOnly = TRUE;
continue;
}
- /*
- * Get a reference to the
+ /*
+ * Get a reference to the
* thread descriptor we are
* handling.
*/
CurrentT = CONTAINING_RECORD(
CurrentEntryT,
- KTHREAD,
+ KTHREAD,
ThreadListEntry
);
/*
pInfoT->State = CurrentT-> ; /* DWORD */
pInfoT->WaitReason = CurrentT-> ; /* KWAIT_REASON */
/*
- * Count the number of threads
+ * Count the number of threads
* this process has.
*/
++ pInfoP->ThreadCount;
*/
pInfoPLast = pInfoP;
/*
- * Compute the offset of the
+ * Compute the offset of the
* SYSTEM_PROCESS_INFORMATION
- * descriptor in the snapshot
+ * descriptor in the snapshot
* buffer for the next process.
*/
(ULONG) pInfoP += SpiSize;
* Mark the end of the snapshot.
*/
pInfoP->RelativeOffset = 0L;
- /* OK */
+ /* OK */
return STATUS_SUCCESS;
#endif
}
IN ULONG ThreadInformationLength)
{
PETHREAD Thread;
- NTSTATUS Status;
union
{
KPRIORITY Priority;
HANDLE Handle;
PVOID Address;
}u;
-
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
+
PAGED_CODE();
+
+ PreviousMode = ExGetPreviousMode();
if (ThreadInformationClass <= MaxThreadInfoClass &&
!SetInformationData[ThreadInformationClass].Implemented)
return STATUS_INFO_LENGTH_MISMATCH;
}
+ if (PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForRead(ThreadInformation,
+ SetInformationData[ThreadInformationClass].Size,
+ 1);
+ RtlCopyMemory(&u.Priority,
+ ThreadInformation,
+ SetInformationData[ThreadInformationClass].Size);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+ else
+ {
+ RtlCopyMemory(&u.Priority,
+ ThreadInformation,
+ SetInformationData[ThreadInformationClass].Size);
+ }
+
+ /* 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 */
Status = ObReferenceObjectByHandle (ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
ExGetPreviousMode (),
(PVOID*)&Thread,
NULL);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- Status = MmCopyFromCaller(&u.Priority,
- ThreadInformation,
- SetInformationData[ThreadInformationClass].Size);
if (NT_SUCCESS(Status))
{
switch (ThreadInformationClass)
}
KeSetPriorityThread(&Thread->Tcb, u.Priority);
break;
-
+
case ThreadBasePriority:
KeSetBasePriorityThread (&Thread->Tcb, u.Increment);
break;
-
+
case ThreadAffinityMask:
- Status = KeSetAffinityThread(&Thread->Tcb, u.Affinity);
+
+ /* Check if this is valid */
+ DPRINT1("%lx, %lx\n", Thread->ThreadsProcess->Pcb.Affinity, u.Affinity);
+ if ((Thread->ThreadsProcess->Pcb.Affinity & u.Affinity) !=
+ u.Affinity)
+ {
+ DPRINT1("Wrong affinity given\n");
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ else
+ {
+ Status = KeSetAffinityThread(&Thread->Tcb, u.Affinity);
+ }
break;
-
+
case ThreadImpersonationToken:
Status = PsAssignImpersonationToken (Thread, u.Handle);
break;
-
+
case ThreadQuerySetWin32StartAddress:
Thread->Win32StartAddress = u.Address;
break;
/* Shoult never occure if the data table is correct */
KEBUGCHECK(0);
}
+ ObDereferenceObject (Thread);
}
- ObDereferenceObject (Thread);
-
+
return Status;
}
OUT PULONG ReturnLength OPTIONAL)
{
PETHREAD Thread;
- NTSTATUS Status;
union
{
THREAD_BASIC_INFORMATION TBI;
LARGE_INTEGER Count;
BOOLEAN Last;
}u;
-
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
+
PAGED_CODE();
+
+ PreviousMode = ExGetPreviousMode();
if (ThreadInformationClass <= MaxThreadInfoClass &&
!QueryInformationData[ThreadInformationClass].Implemented)
return STATUS_INFO_LENGTH_MISMATCH;
}
+ if (PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWrite(ThreadInformation,
+ QueryInformationData[ThreadInformationClass].Size,
+ 1);
+ if (ReturnLength != NULL)
+ {
+ ProbeForWriteUlong(ReturnLength);
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
Status = ObReferenceObjectByHandle(ThreadHandle,
THREAD_QUERY_INFORMATION,
PsThreadType,
{
case ThreadBasicInformation:
/* A test on W2K agains ntdll shows NtQueryInformationThread return STATUS_PENDING
- * as ExitStatus for current/running thread, while KETHREAD's ExitStatus is
+ * 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 = Thread->Tcb.Teb;
+ 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 = Thread->Tcb.BasePriority;
+ u.TBI.BasePriority = KeQueryBasePriorityThread(&Thread->Tcb);
break;
-
+
case ThreadTimes:
u.TTI.KernelTime.QuadPart = Thread->Tcb.KernelTime * 100000LL;
u.TTI.UserTime.QuadPart = Thread->Tcb.UserTime * 100000LL;
/* Shoult never occure if the data table is correct */
KEBUGCHECK(0);
}
- if (QueryInformationData[ThreadInformationClass].Size)
+
+ if (PreviousMode != KernelMode)
{
- Status = MmCopyToCaller(ThreadInformation,
- &u.TBI,
- QueryInformationData[ThreadInformationClass].Size);
+ _SEH_TRY
+ {
+ if (QueryInformationData[ThreadInformationClass].Size)
+ {
+ RtlCopyMemory(ThreadInformation,
+ &u.TBI,
+ QueryInformationData[ThreadInformationClass].Size);
+ }
+ if (ReturnLength != NULL)
+ {
+ *ReturnLength = QueryInformationData[ThreadInformationClass].Size;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
}
- if (ReturnLength)
+ else
{
- NTSTATUS Status2;
- static ULONG Null = 0;
- Status2 = MmCopyToCaller(ReturnLength,
- NT_SUCCESS(Status) ? &QueryInformationData[ThreadInformationClass].Size : &Null,
- sizeof(ULONG));
- if (NT_SUCCESS(Status))
+ if (QueryInformationData[ThreadInformationClass].Size)
{
- Status = Status2;
- }
+ RtlCopyMemory(ThreadInformation,
+ &u.TBI,
+ QueryInformationData[ThreadInformationClass].Size);
+ }
+
+ if (ReturnLength != NULL)
+ {
+ *ReturnLength = QueryInformationData[ThreadInformationClass].Size;
+ }
}
ObDereferenceObject(Thread);