X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fntoskrnl%2Fps%2Fquery.c;h=be90e24ba95c5073cdb319a7065ec0186e15dcbf;hp=3e6034cb232eba0f96011b3a518109539c6a1b47;hb=8481c1fa105172e71517334bcfa085da87b85258;hpb=72a6942f36953471e7183b724f3d99d804eb769a diff --git a/reactos/ntoskrnl/ps/query.c b/reactos/ntoskrnl/ps/query.c index 3e6034cb232..be90e24ba95 100644 --- a/reactos/ntoskrnl/ps/query.c +++ b/reactos/ntoskrnl/ps/query.c @@ -62,7 +62,7 @@ static const INFORMATION_CLASS_INFO PsProcessInfoClass[] = 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 */ }; @@ -75,7 +75,7 @@ static const struct { BOOLEAN Implemented; ULONG Size; -} QueryInformationData[MaxThreadInfoClass + 1] = +} QueryInformationData[MaxThreadInfoClass + 1] = { {TRUE, sizeof(THREAD_BASIC_INFORMATION)}, // ThreadBasicInformation {TRUE, sizeof(KERNEL_USER_TIMES)}, // ThreadTimes @@ -101,7 +101,7 @@ static const struct { BOOLEAN Implemented; ULONG Size; -} SetInformationData[MaxThreadInfoClass + 1] = +} SetInformationData[MaxThreadInfoClass + 1] = { {TRUE, 0}, // ThreadBasicInformation {TRUE, 0}, // ThreadTimes @@ -138,24 +138,24 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, 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, @@ -176,7 +176,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, real handle actually represents the current process. */ return STATUS_INVALID_PARAMETER; } - + switch (ProcessInformationClass) { case ProcessBasicInformation: @@ -190,9 +190,9 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, 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; @@ -254,7 +254,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, _SEH_END; break; } - + case ProcessLdtInformation: case ProcessWorkingSetWatch: case ProcessWx86Information: @@ -264,7 +264,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, case ProcessHandleCount: { ULONG HandleCount = ObpGetHandleCountByHandleTable(Process->ObjectTable); - + _SEH_TRY { *(PULONG)ProcessInformation = HandleCount; @@ -287,7 +287,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, _SEH_TRY { - SessionInfo->SessionId = Process->SessionId; + SessionInfo->SessionId = Process->Session; if (ReturnLength) { *ReturnLength = sizeof(PROCESS_SESSION_INFORMATION); @@ -300,7 +300,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, _SEH_END; break; } - + case ProcessWow64Information: DPRINT1("We currently don't support the ProcessWow64Information information class!\n"); Status = STATUS_NOT_IMPLEMENTED; @@ -309,7 +309,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, case ProcessVmCounters: { PVM_COUNTERS pOut = (PVM_COUNTERS)ProcessInformation; - + _SEH_TRY { pOut->PeakVirtualSize = Process->PeakVirtualSize; @@ -318,16 +318,16 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, * 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) { @@ -364,7 +364,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, case ProcessPriorityBoost: { PULONG BoostEnabled = (PULONG)ProcessInformation; - + _SEH_TRY { *BoostEnabled = Process->Pcb.DisableBoost ? FALSE : TRUE; @@ -385,7 +385,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, case ProcessDeviceMap: { PROCESS_DEVICEMAP_INFORMATION DeviceMap; - + ObQueryDeviceMapInformation(Process, &DeviceMap); _SEH_TRY @@ -427,139 +427,59 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, 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! */ @@ -571,16 +491,16 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, 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, @@ -592,7 +512,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, Cookie = NewCookie; } } - + _SEH_TRY { *(PULONG)ProcessInformation = Cookie; @@ -606,7 +526,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, Status = _SEH_GetExceptionCode(); } _SEH_END; - + break; } @@ -632,7 +552,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, { ObDereferenceObject(Process); } - + return Status; } @@ -649,24 +569,24 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, 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: @@ -680,7 +600,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, Access = PROCESS_SET_INFORMATION; break; } - + Status = ObReferenceObjectByHandle(ProcessHandle, Access, PsProcessType, @@ -715,11 +635,11 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, 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 */ @@ -732,8 +652,8 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, 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)) { /* @@ -751,7 +671,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, ObDereferenceObject(ExceptionPort); Status = STATUS_PORT_ALREADY_SET; } - PsUnlockProcess(Process); + PsUnlockProcess((PROS_EPROCESS)Process); } else { @@ -801,14 +721,14 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, _SEH_END; break; } - + case ProcessSessionInformation: { PROCESS_SESSION_INFORMATION SessionInfo; Status = STATUS_SUCCESS; - + RtlZeroMemory(&SessionInfo, sizeof(SessionInfo)); - + _SEH_TRY { /* copy the structure to the stack */ @@ -819,11 +739,11 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, 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! */ @@ -835,13 +755,13 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, 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) @@ -865,12 +785,12 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, KeDetachProcess(); } - PsUnlockProcess(Process); + PsUnlockProcess((PROS_EPROCESS)Process); } } break; } - + case ProcessPriorityClass: { PROCESS_PRIORITY_CLASS ppc; @@ -884,14 +804,14 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, Status = _SEH_GetExceptionCode(); } _SEH_END; - + if(NT_SUCCESS(Status)) { } - + break; } - + case ProcessLdtInformation: case ProcessLdtSize: case ProcessIoPortHandlers: @@ -923,7 +843,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, * 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 @@ -945,16 +865,16 @@ PiQuerySystemProcessInformation(PVOID Buffer, 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); @@ -991,14 +911,14 @@ PiQuerySystemProcessInformation(PVOID Buffer, 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 ); /* @@ -1015,9 +935,9 @@ PiQuerySystemProcessInformation(PVOID Buffer, /* THREAD */ for ( pInfoT = & CurrentP->ThreadSysInfo [0], CurrentEntryT = CurrentP->ThreadListHead.Flink; - + (CurrentEntryT != & CurrentP->ThreadListHead); - + pInfoT = & CurrentP->ThreadSysInfo [pInfoP->ThreadCount], CurrentEntryT = CurrentEntryT->Flink ) @@ -1044,14 +964,14 @@ PiQuerySystemProcessInformation(PVOID Buffer, 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 ); /* @@ -1074,7 +994,7 @@ PiQuerySystemProcessInformation(PVOID Buffer, pInfoT->State = CurrentT-> ; /* DWORD */ pInfoT->WaitReason = CurrentT-> ; /* KWAIT_REASON */ /* - * Count the number of threads + * Count the number of threads * this process has. */ ++ pInfoP->ThreadCount; @@ -1091,9 +1011,9 @@ PiQuerySystemProcessInformation(PVOID Buffer, */ 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; @@ -1120,7 +1040,7 @@ PiQuerySystemProcessInformation(PVOID Buffer, * Mark the end of the snapshot. */ pInfoP->RelativeOffset = 0L; - /* OK */ + /* OK */ return STATUS_SUCCESS; #endif } @@ -1135,7 +1055,6 @@ NtSetInformationThread (IN HANDLE ThreadHandle, IN ULONG ThreadInformationLength) { PETHREAD Thread; - NTSTATUS Status; union { KPRIORITY Priority; @@ -1144,8 +1063,12 @@ NtSetInformationThread (IN HANDLE ThreadHandle, HANDLE Handle; PVOID Address; }u; - + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + PAGED_CODE(); + + PreviousMode = ExGetPreviousMode(); if (ThreadInformationClass <= MaxThreadInfoClass && !SetInformationData[ThreadInformationClass].Implemented) @@ -1162,20 +1085,43 @@ NtSetInformationThread (IN HANDLE ThreadHandle, 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) @@ -1188,19 +1134,31 @@ NtSetInformationThread (IN HANDLE ThreadHandle, } 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; @@ -1209,9 +1167,9 @@ NtSetInformationThread (IN HANDLE ThreadHandle, /* Shoult never occure if the data table is correct */ KEBUGCHECK(0); } + ObDereferenceObject (Thread); } - ObDereferenceObject (Thread); - + return Status; } @@ -1226,7 +1184,6 @@ NtQueryInformationThread (IN HANDLE ThreadHandle, OUT PULONG ReturnLength OPTIONAL) { PETHREAD Thread; - NTSTATUS Status; union { THREAD_BASIC_INFORMATION TBI; @@ -1235,8 +1192,12 @@ NtQueryInformationThread (IN HANDLE ThreadHandle, LARGE_INTEGER Count; BOOLEAN Last; }u; - + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + PAGED_CODE(); + + PreviousMode = ExGetPreviousMode(); if (ThreadInformationClass <= MaxThreadInfoClass && !QueryInformationData[ThreadInformationClass].Implemented) @@ -1253,6 +1214,30 @@ NtQueryInformationThread (IN HANDLE ThreadHandle, 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, @@ -1268,17 +1253,17 @@ NtQueryInformationThread (IN HANDLE ThreadHandle, { 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; @@ -1311,23 +1296,41 @@ NtQueryInformationThread (IN HANDLE ThreadHandle, /* 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);