From 0ef3ed3fb17d7b92bac1173c7805962cd007bdd2 Mon Sep 17 00:00:00 2001 From: Matthias Kupfer Date: Sat, 21 Feb 2009 22:41:14 +0000 Subject: [PATCH] Evgeniy Boltik Jan Roeloffzen - Fixes task manager process list names and kernel sysinfo. - See issue #4087 for details. svn path=/trunk/; revision=39704 --- reactos/base/applications/taskmgr/perfdata.c | 17 +- reactos/ntoskrnl/ex/sysinfo.c | 320 +++++++++++-------- 2 files changed, 189 insertions(+), 148 deletions(-) diff --git a/reactos/base/applications/taskmgr/perfdata.c b/reactos/base/applications/taskmgr/perfdata.c index 5978639371a..c8176a4ee5c 100644 --- a/reactos/base/applications/taskmgr/perfdata.c +++ b/reactos/base/applications/taskmgr/perfdata.c @@ -241,7 +241,8 @@ void PerfDataRefresh(void) HeapFree(GetProcessHeap(), 0, pPerfDataOld); } pPerfDataOld = pPerfData; - pPerfData = (PPERFDATA)HeapAlloc(GetProcessHeap(), 0, sizeof(PERFDATA) * ProcessCount); + /* Clear out process perf data structures with HEAP_ZERO_MEMORY flag: */ + pPerfData = (PPERFDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PERFDATA) * ProcessCount); pSPI = (PSYSTEM_PROCESS_INFORMATION)pBuffer; for (Idx=0; IdxImageName.Buffer) - wcscpy(pPerfData[Idx].ImageName, pSPI->ImageName.Buffer); - else + if (pSPI->ImageName.Buffer) { + /* Don't assume a UNICODE_STRING Buffer is zero terminated: */ + int len = pSPI->ImageName.Length / 2; + /* Check against max size and allow for terminating zero (already zeroed): */ + if(len >= MAX_PATH)len=MAX_PATH - 1; + wcsncpy(pPerfData[Idx].ImageName, pSPI->ImageName.Buffer, len); + } else { LoadStringW(hInst, IDS_IDLE_PROCESS, pPerfData[Idx].ImageName, sizeof(pPerfData[Idx].ImageName) / sizeof(pPerfData[Idx].ImageName[0])); + } pPerfData[Idx].ProcessId = pSPI->UniqueProcessId; diff --git a/reactos/ntoskrnl/ex/sysinfo.c b/reactos/ntoskrnl/ex/sysinfo.c index 0db5e0520fc..e4b5ab4a664 100644 --- a/reactos/ntoskrnl/ex/sysinfo.c +++ b/reactos/ntoskrnl/ex/sysinfo.c @@ -701,7 +701,7 @@ QSI_DEF(SystemPathInformation) /* Class 5 - Process Information */ QSI_DEF(SystemProcessInformation) { - PSYSTEM_PROCESS_INFORMATION SpiCurrent; + PSYSTEM_PROCESS_INFORMATION SpiCurrent = NULL; PSYSTEM_THREAD_INFORMATION ThreadInfo; PEPROCESS Process = NULL, SystemProcess; PETHREAD CurrentThread; @@ -712,176 +712,213 @@ QSI_DEF(SystemProcessInformation) PLIST_ENTRY CurrentEntry; ULONG TotalSize = 0, ThreadsCount; ULONG TotalUser, TotalKernel; - PUCHAR Current; + PUCHAR Current = NULL; NTSTATUS Status = STATUS_SUCCESS; PUNICODE_STRING ProcessImageName; PWCHAR szSrc; + //1 Write in to bufer + //2 Calc size buffer + //4 Vista compatible + //Flags always start write and calculate size + //For Vista compatible add "| 4" + USHORT OSMode = 1 | 2; + _SEH2_TRY { /* scan the process list */ PSYSTEM_PROCESS_INFORMATION Spi - = (PSYSTEM_PROCESS_INFORMATION) Buffer; + = (PSYSTEM_PROCESS_INFORMATION) Buffer; - *ReqSize = sizeof(SYSTEM_PROCESS_INFORMATION); - - if (Size < sizeof(SYSTEM_PROCESS_INFORMATION)) + while ((OSMode & 1) || (OSMode & 2)) { - _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH); // in case buffer size is too small - } - RtlZeroMemory(Spi, Size); + //Vista first cycle only calc size and readonly + if (OSMode & 4 && OSMode & 1) + OSMode ^= 1; + //not exists byffer or size protect write, only calc size + if (OSMode & 1 && ((Size == 0) || (!Buffer))) + OSMode ^= 1; - SystemProcess = PsIdleProcess; - Process = SystemProcess; - Current = (PUCHAR) Spi; + if (OSMode & 1) + { + //Only in second cycle and vista compatible + if (TotalSize > 0 && TotalSize > Size) + { + *ReqSize = TotalSize; + _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH); // in case buffer size is too small + } + if (Size > 0) + RtlZeroMemory(Spi, Size); + Current = (PUCHAR) Spi; + SpiCurrent = NULL; + } - do - { - SpiCurrent = (PSYSTEM_PROCESS_INFORMATION) Current; + SystemProcess = PsIdleProcess; + Process = SystemProcess; - ThreadsCount = 0; - CurrentEntry = Process->ThreadListHead.Flink; - while (CurrentEntry != &Process->ThreadListHead) - { + do + { + ThreadsCount = 0; + CurrentEntry = Process->ThreadListHead.Flink; + while (CurrentEntry != &Process->ThreadListHead) + { ThreadsCount++; CurrentEntry = CurrentEntry->Flink; - } + } - // size of the structure for every process - CurrentSize = sizeof(SYSTEM_PROCESS_INFORMATION) + sizeof(SYSTEM_THREAD_INFORMATION) * ThreadsCount; - ImageNameLength = 0; - Status = SeLocateProcessImageName(Process, &ProcessImageName); - szSrc = NULL; - if (NT_SUCCESS(Status)) - { - szSrc = (PWCHAR)((PCHAR)ProcessImageName->Buffer + ProcessImageName->Length); - /* Loop the file name*/ - while (szSrc > ProcessImageName->Buffer) + // size of the structure for every process + CurrentSize = sizeof(SYSTEM_PROCESS_INFORMATION) + sizeof(SYSTEM_THREAD_INFORMATION) * ThreadsCount; + ImageNameLength = 0; + Status = SeLocateProcessImageName(Process, &ProcessImageName); + szSrc = NULL; + if (NT_SUCCESS(Status) && ProcessImageName->Length > 0) { - /* Make sure this isn't a backslash */ - if (*--szSrc == OBJ_NAME_PATH_SEPARATOR) + szSrc = (PWCHAR)((PCHAR)ProcessImageName->Buffer + ProcessImageName->Length); + /* Loop the file name*/ + while (szSrc > ProcessImageName->Buffer) { + /* Make sure this isn't a backslash */ + if (*--szSrc == OBJ_NAME_PATH_SEPARATOR) + { szSrc++; break; + } + else + { + ImageNameLength += sizeof(WCHAR); + } + } + } + if (!ImageNameLength && Process != PsIdleProcess && Process->ImageFileName) + { + ImageNameLength = strlen(Process->ImageFileName) * sizeof(WCHAR); + } + + /* Round up the image name length as NT does */ + ImageNameMaximumLength = + (ImageNameLength > 0 ? ROUND_UP(ImageNameLength+1, 8) : 0); + + if (OSMode & 2) + TotalSize += CurrentSize + ImageNameMaximumLength; + + if ((OSMode & 1) && Buffer && TotalSize <= Size) + { + //Set prev structure NextEntryOffset next structure only exists write buffer + if (SpiCurrent && TotalSize <= Size) + SpiCurrent->NextEntryOffset = Current - (PUCHAR)SpiCurrent;// relative offset to the beginnnig of the next structure + SpiCurrent = (PSYSTEM_PROCESS_INFORMATION) Current; + + /* Fill system information */ + 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); + } + else if (Process->ImageFileName) + { + RtlInitAnsiString(&ImageName, Process->ImageFileName); + RtlAnsiStringToUnicodeString(&SpiCurrent->ImageName, &ImageName, FALSE); + } } else { - ImageNameLength += sizeof(WCHAR); + 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); } - } - if (!ImageNameLength && Process != PsIdleProcess && Process->ImageFileName) - { - ImageNameLength = strlen(Process->ImageFileName) * sizeof(WCHAR); - } + /* Release the memory allocated by SeLocateProcessImageName */ + if (NT_SUCCESS(Status)) ExFreePool(ProcessImageName); - /* Round up the image name length as NT does */ - ImageNameMaximumLength = ROUND_UP(ImageNameLength, 8); + /* Handle idle process entry */ + if (Process == PsIdleProcess) Process = NULL; - TotalSize += CurrentSize + ImageNameMaximumLength; - - if (TotalSize > Size) - { - *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 - } - - /* 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) + Process = PsGetNextProcess(Process); + ThreadsCount = 0; + if ((Process == SystemProcess) || (Process == NULL)) { - 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; - - Process = PsGetNextProcess(Process); - ThreadsCount = 0; - if ((Process == SystemProcess) || (Process == NULL)) - { - SpiCurrent->NextEntryOffset = 0; break; - } - else - Current += CurrentSize + ImageNameMaximumLength; + } + else + { + if (Current) + Current += CurrentSize + ImageNameMaximumLength; + } } while ((Process != SystemProcess) && (Process != NULL)); + //Break parameters information for only calc size + if ((Size == 0) || (!Buffer)) + break; + //Stop write in to buffer + if (OSMode & 1) + OSMode ^= 1; + //Only first cycle calc size + if (OSMode & 2) + OSMode ^= 2; + //Vista next cycle write in to Buffer + if (OSMode & 4) + { + OSMode |= 1; + OSMode ^= 4; + } + }; - if(Process != NULL) - ObDereferenceObject(Process); + if(Process != NULL) + ObDereferenceObject(Process); + if ((Size == 0) || (!Buffer) || (TotalSize > Size)) + Status = STATUS_INFO_LENGTH_MISMATCH; + else Status = STATUS_SUCCESS; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) @@ -1888,8 +1925,9 @@ NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass, if (PreviousMode != KernelMode) { /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */ - ProbeForWrite(SystemInformation, Length, 1); - if (UnsafeResultLength != NULL) + if (SystemInformation) + ProbeForWrite(SystemInformation, Length, 1); + if (UnsafeResultLength) ProbeForWriteUlong(UnsafeResultLength); }