Author: fireball
Date: Tue Feb 24 17:02:39 2009
New Revision: 39738
URL:
http://svn.reactos.org/svn/reactos?rev=39738&view=rev
Log:
- Make SystemProcessInformation return required size if buffer is too small. Matches
Windows XP behavior.
See issue #4087 for more details.
Modified:
trunk/reactos/ntoskrnl/ex/sysinfo.c
Modified: trunk/reactos/ntoskrnl/ex/sysinfo.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/sysinfo.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ex/sysinfo.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ex/sysinfo.c [iso-8859-1] Tue Feb 24 17:02:39 2009
@@ -716,6 +716,7 @@
NTSTATUS Status = STATUS_SUCCESS;
PUNICODE_STRING ProcessImageName;
PWCHAR szSrc;
+ BOOLEAN Overflow = FALSE;
_SEH2_TRY
{
@@ -726,11 +727,12 @@
*ReqSize = sizeof(SYSTEM_PROCESS_INFORMATION);
+ /* Check for overflow */
if (Size < sizeof(SYSTEM_PROCESS_INFORMATION))
- {
- _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH); // in case buffer size is
too small
- }
- RtlZeroMemory(Spi, Size);
+ Overflow = TRUE;
+
+ /* Zero user's buffer */
+ if (!Overflow) RtlZeroMemory(Spi, Size);
SystemProcess = PsIdleProcess;
Process = SystemProcess;
@@ -784,90 +786,86 @@
TotalSize += CurrentSize + ImageNameMaximumLength;
+ /* Check for overflow */
if (TotalSize > Size)
+ Overflow = TRUE;
+
+ /* Fill system information */
+ if (!Overflow)
{
- *ReqSize = TotalSize;
- ObDereferenceObject(Process);
-
- /* Release the memory allocated by SeLocateProcessImageName */
- if (NT_SUCCESS(Status)) ExFreePool(ProcessImageName);
-
- _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH); // in case buffer size
is too small
+ SpiCurrent->NextEntryOffset = CurrentSize + ImageNameMaximumLength; //
relative offset to the beginnnig of the next structure
+ SpiCurrent->NumberOfThreads = ThreadsCount;
+ SpiCurrent->CreateTime = Process->CreateTime;
+ SpiCurrent->ImageName.Length = ImageNameLength;
+ SpiCurrent->ImageName.MaximumLength = ImageNameMaximumLength;
+ SpiCurrent->ImageName.Buffer = (void*)(Current + CurrentSize);
+
+ /* Copy name to the end of the struct */
+ if(Process != PsIdleProcess)
+ {
+ if (szSrc)
+ {
+ RtlCopyMemory(SpiCurrent->ImageName.Buffer, szSrc,
SpiCurrent->ImageName.Length);
+
+ /* Release the memory allocated by SeLocateProcessImageName */
+ ExFreePool(ProcessImageName);
+ }
+ else if (Process->ImageFileName)
+ {
+ RtlInitAnsiString(&ImageName, Process->ImageFileName);
+ RtlAnsiStringToUnicodeString(&SpiCurrent->ImageName,
&ImageName, FALSE);
+ }
+ }
+ else
+ {
+ RtlInitUnicodeString(&SpiCurrent->ImageName, NULL);
+ }
+
+ SpiCurrent->BasePriority = Process->Pcb.BasePriority;
+ SpiCurrent->UniqueProcessId = Process->UniqueProcessId;
+ SpiCurrent->InheritedFromUniqueProcessId =
Process->InheritedFromUniqueProcessId;
+ SpiCurrent->HandleCount = ObGetProcessHandleCount(Process);
+ SpiCurrent->PeakVirtualSize = Process->PeakVirtualSize;
+ SpiCurrent->VirtualSize = Process->VirtualSize;
+ SpiCurrent->PageFaultCount = Process->Vm.PageFaultCount;
+ SpiCurrent->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize;
+ SpiCurrent->WorkingSetSize = Process->Vm.WorkingSetSize;
+ SpiCurrent->QuotaPeakPagedPoolUsage = Process->QuotaPeak[0];
+ SpiCurrent->QuotaPagedPoolUsage = Process->QuotaUsage[0];
+ SpiCurrent->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[1];
+ SpiCurrent->QuotaNonPagedPoolUsage = Process->QuotaUsage[1];
+ SpiCurrent->PagefileUsage = Process->QuotaUsage[2];
+ SpiCurrent->PeakPagefileUsage = Process->QuotaPeak[2];
+ SpiCurrent->PrivatePageCount = Process->CommitCharge;
+ ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(SpiCurrent + 1);
+
+ CurrentEntry = Process->ThreadListHead.Flink;
+ while (CurrentEntry != &Process->ThreadListHead)
+ {
+ CurrentThread = CONTAINING_RECORD(CurrentEntry, ETHREAD,
+ ThreadListEntry);
+
+ ThreadInfo->KernelTime.QuadPart =
UInt32x32To64(CurrentThread->Tcb.KernelTime, KeMaximumIncrement);
+ ThreadInfo->UserTime.QuadPart =
UInt32x32To64(CurrentThread->Tcb.UserTime, KeMaximumIncrement);
+ ThreadInfo->CreateTime.QuadPart =
CurrentThread->CreateTime.QuadPart;
+ ThreadInfo->WaitTime = CurrentThread->Tcb.WaitTime;
+ ThreadInfo->StartAddress = (PVOID)
CurrentThread->StartAddress;
+ ThreadInfo->ClientId = CurrentThread->Cid;
+ ThreadInfo->Priority = CurrentThread->Tcb.Priority;
+ ThreadInfo->BasePriority = CurrentThread->Tcb.BasePriority;
+ ThreadInfo->ContextSwitches =
CurrentThread->Tcb.ContextSwitches;
+ ThreadInfo->ThreadState = CurrentThread->Tcb.State;
+ ThreadInfo->WaitReason = CurrentThread->Tcb.WaitReason;
+
+ ThreadInfo++;
+ CurrentEntry = CurrentEntry->Flink;
+ }
+
+ /* Query total user/kernel times of a process */
+ TotalKernel = KeQueryRuntimeProcess(&Process->Pcb,
&TotalUser);
+ SpiCurrent->UserTime.QuadPart = UInt32x32To64(TotalUser,
KeMaximumIncrement);
+ SpiCurrent->KernelTime.QuadPart = UInt32x32To64(TotalKernel,
KeMaximumIncrement);
}
-
- /* Fill system information */
- SpiCurrent->NextEntryOffset = CurrentSize + ImageNameMaximumLength; //
relative offset to the beginnnig of the next structure
- SpiCurrent->NumberOfThreads = ThreadsCount;
- SpiCurrent->CreateTime = Process->CreateTime;
- SpiCurrent->ImageName.Length = ImageNameLength;
- SpiCurrent->ImageName.MaximumLength = ImageNameMaximumLength;
- SpiCurrent->ImageName.Buffer = (void*)(Current + CurrentSize);
-
- /* Copy name to the end of the struct */
- if(Process != PsIdleProcess)
- {
- if (szSrc)
- {
- RtlCopyMemory(SpiCurrent->ImageName.Buffer, szSrc,
SpiCurrent->ImageName.Length);
-
- /* Release the memory allocated by SeLocateProcessImageName */
- ExFreePool(ProcessImageName);
- }
- else if (Process->ImageFileName)
- {
- RtlInitAnsiString(&ImageName, Process->ImageFileName);
- RtlAnsiStringToUnicodeString(&SpiCurrent->ImageName,
&ImageName, FALSE);
- }
- }
- else
- {
- RtlInitUnicodeString(&SpiCurrent->ImageName, NULL);
- }
-
- SpiCurrent->BasePriority = Process->Pcb.BasePriority;
- SpiCurrent->UniqueProcessId = Process->UniqueProcessId;
- SpiCurrent->InheritedFromUniqueProcessId =
Process->InheritedFromUniqueProcessId;
- SpiCurrent->HandleCount = ObGetProcessHandleCount(Process);
- SpiCurrent->PeakVirtualSize = Process->PeakVirtualSize;
- SpiCurrent->VirtualSize = Process->VirtualSize;
- SpiCurrent->PageFaultCount = Process->Vm.PageFaultCount;
- SpiCurrent->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize;
- SpiCurrent->WorkingSetSize = Process->Vm.WorkingSetSize;
- SpiCurrent->QuotaPeakPagedPoolUsage = Process->QuotaPeak[0];
- SpiCurrent->QuotaPagedPoolUsage = Process->QuotaUsage[0];
- SpiCurrent->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[1];
- SpiCurrent->QuotaNonPagedPoolUsage = Process->QuotaUsage[1];
- SpiCurrent->PagefileUsage = Process->QuotaUsage[2];
- SpiCurrent->PeakPagefileUsage = Process->QuotaPeak[2];
- SpiCurrent->PrivatePageCount = Process->CommitCharge;
- ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(SpiCurrent + 1);
-
- CurrentEntry = Process->ThreadListHead.Flink;
- while (CurrentEntry != &Process->ThreadListHead)
- {
- CurrentThread = CONTAINING_RECORD(CurrentEntry, ETHREAD,
- ThreadListEntry);
-
- ThreadInfo->KernelTime.QuadPart =
UInt32x32To64(CurrentThread->Tcb.KernelTime, KeMaximumIncrement);
- ThreadInfo->UserTime.QuadPart =
UInt32x32To64(CurrentThread->Tcb.UserTime, KeMaximumIncrement);
- ThreadInfo->CreateTime.QuadPart =
CurrentThread->CreateTime.QuadPart;
- ThreadInfo->WaitTime = CurrentThread->Tcb.WaitTime;
- ThreadInfo->StartAddress = (PVOID) CurrentThread->StartAddress;
- ThreadInfo->ClientId = CurrentThread->Cid;
- ThreadInfo->Priority = CurrentThread->Tcb.Priority;
- ThreadInfo->BasePriority = CurrentThread->Tcb.BasePriority;
- ThreadInfo->ContextSwitches = CurrentThread->Tcb.ContextSwitches;
- ThreadInfo->ThreadState = CurrentThread->Tcb.State;
- ThreadInfo->WaitReason = CurrentThread->Tcb.WaitReason;
-
- ThreadInfo++;
- CurrentEntry = CurrentEntry->Flink;
- }
-
- /* Query total user/kernel times of a process */
- TotalKernel = KeQueryRuntimeProcess(&Process->Pcb, &TotalUser);
- SpiCurrent->UserTime.QuadPart = UInt32x32To64(TotalUser,
KeMaximumIncrement);
- SpiCurrent->KernelTime.QuadPart = UInt32x32To64(TotalKernel,
KeMaximumIncrement);
/* Handle idle process entry */
if (Process == PsIdleProcess) Process = NULL;
@@ -876,7 +874,8 @@
ThreadsCount = 0;
if ((Process == SystemProcess) || (Process == NULL))
{
- SpiCurrent->NextEntryOffset = 0;
+ if (!Overflow)
+ SpiCurrent->NextEntryOffset = 0;
break;
}
else
@@ -894,6 +893,9 @@
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
+
+ if (Overflow)
+ Status = STATUS_INFO_LENGTH_MISMATCH;
*ReqSize = TotalSize;
return Status;