X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fntoskrnl%2Fps%2Fquery.c;h=d27ff3e4dfe2ee8ab97b00450da7480a544022d8;hp=be390cb5af74560fe17e55574b64bc067ed55a79;hb=c5cc4a4bd77cb3c8b2cf1d7a9e54c68a839de18d;hpb=79287b3e31267c36221956f0a8aa38b0ee5fbbae diff --git a/reactos/ntoskrnl/ps/query.c b/reactos/ntoskrnl/ps/query.c index be390cb5af7..d27ff3e4dfe 100644 --- a/reactos/ntoskrnl/ps/query.c +++ b/reactos/ntoskrnl/ps/query.c @@ -5,6 +5,7 @@ * PURPOSE: Process Manager: Thread/Process Query/Set Information * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) * Thomas Weidenmueller (w3seek@reactos.org) + * Eric Kohl */ /* INCLUDES ******************************************************************/ @@ -63,45 +64,47 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, { PEPROCESS Process; KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); - NTSTATUS Status = STATUS_SUCCESS; + NTSTATUS Status; ULONG Length = 0; 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), - ProcessInformation, - ProcessInformationLength, - ReturnLength, - PreviousMode); - if (!NT_SUCCESS(Status)) return Status; -#endif - - /* Check if this isn't the cookie class */ - if(ProcessInformationClass != ProcessCookie) + /* Check for user-mode caller */ + if (PreviousMode != KernelMode) { - /* Reference the process */ - Status = ObReferenceObjectByHandle(ProcessHandle, - PROCESS_QUERY_INFORMATION, - PsProcessType, - PreviousMode, - (PVOID*)&Process, - NULL); - if (!NT_SUCCESS(Status)) return Status; + /* Prepare to probe parameters */ + _SEH2_TRY + { + /* Probe the buffer */ + ProbeForWrite(ProcessInformation, + ProcessInformationLength, + sizeof(ULONG)); + + /* Probe the return length if required */ + if (ReturnLength) ProbeForWriteUlong(ReturnLength); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Return the exception code */ + _SEH2_YIELD(return _SEH2_GetExceptionCode()); + } + _SEH2_END; } - else if(ProcessHandle != NtCurrentProcess()) + + if((ProcessInformationClass == ProcessCookie) && + (ProcessHandle != NtCurrentProcess())) { /* * Retreiving the process cookie is only allowed for the calling process @@ -120,11 +123,21 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, /* Set return length */ Length = sizeof(PROCESS_BASIC_INFORMATION); - if ( ProcessInformationLength != Length ) + 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 */ _SEH2_TRY { @@ -135,7 +148,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, ProcessBasicInfo->UniqueProcessId = (ULONG_PTR)Process-> UniqueProcessId; ProcessBasicInfo->InheritedFromUniqueProcessId = - (ULONG_PTR)Process->InheritedFromUniqueProcessId; + (ULONG)Process->InheritedFromUniqueProcessId; ProcessBasicInfo->BasePriority = Process->Pcb.BasePriority; } @@ -145,20 +158,113 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, Status = _SEH2_GetExceptionCode(); } _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 = MAXULONG; + QuotaLimits->TimeLimit.HighPart = MAXULONG; + + /* 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: Length = sizeof(IO_COUNTERS); - if ( ProcessInformationLength != Length ) + if (ProcessInformationLength != Length) { Status = STATUS_INFO_LENGTH_MISMATCH; break; } - Status = STATUS_NOT_IMPLEMENTED; + /* 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 */ @@ -167,12 +273,21 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, /* Set the return length */ Length = sizeof(KERNEL_USER_TIMES); - if ( ProcessInformationLength != Length ) + 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 */ _SEH2_TRY { @@ -190,20 +305,38 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, Status = _SEH2_GetExceptionCode(); } _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 */ _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); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -211,12 +344,29 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, Status = _SEH2_GetExceptionCode(); } _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; @@ -225,14 +375,23 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, /* Set the return length*/ Length = sizeof(ULONG); - if ( ProcessInformationLength != Length ) + 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 */ _SEH2_TRY @@ -246,19 +405,37 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, Status = _SEH2_GetExceptionCode(); } _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 */ _SEH2_TRY { /* Write back the Session ID */ - SessionInfo->SessionId = PtrToUlong(Process->Session); - - /* Set the return length */ - Length = sizeof(PROCESS_SESSION_INFORMATION); + SessionInfo->SessionId = Process->Session; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -266,10 +443,36 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, Status = _SEH2_GetExceptionCode(); } _SEH2_END; + + /* Dereference the process */ + ObDereferenceObject(Process); break; /* WOW64: Not implemented */ case ProcessWow64Information: + + /* Set the return length */ + Length = sizeof(ULONG_PTR); + + 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; + + DPRINT1("Not implemented: ProcessWow64Information\n"); + + /* Dereference the process */ + ObDereferenceObject(Process); Status = STATUS_NOT_IMPLEMENTED; break; @@ -279,12 +482,21 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, /* Set the return length */ Length = sizeof(VM_COUNTERS); - if ( ProcessInformationLength != Length ) + 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 */ _SEH2_TRY { @@ -308,20 +520,38 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, Status = _SEH2_GetExceptionCode(); } _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 */ _SEH2_TRY { /* Write the current processing mode */ *(PULONG)ProcessInformation = Process-> DefaultHardErrorProcessing; - - /* Set the return length */ - Length = sizeof(ULONG); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -329,20 +559,38 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, Status = _SEH2_GetExceptionCode(); } _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 */ _SEH2_TRY { /* Return boost status */ *(PULONG)ProcessInformation = Process->Pcb.DisableBoost ? - FALSE : TRUE; - - /* Set the return length */ - Length = sizeof(ULONG); + TRUE : FALSE; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -350,11 +598,32 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, Status = _SEH2_GetExceptionCode(); } _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); @@ -362,9 +631,6 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, _SEH2_TRY { *(PPROCESS_DEVICEMAP_INFORMATION)ProcessInformation = DeviceMap; - - /* Set the return length */ - Length = sizeof(PROCESS_DEVICEMAP_INFORMATION); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -372,19 +638,38 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, Status = _SEH2_GetExceptionCode(); } _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 */ _SEH2_TRY { /* Return current priority class */ - *(PUSHORT)ProcessInformation = Process->PriorityClass; - - /* Set the return length */ - Length = sizeof(USHORT); + PsPriorityClass->PriorityClass = Process->PriorityClass; + PsPriorityClass->Foreground = FALSE; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -392,10 +677,22 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, Status = _SEH2_GetExceptionCode(); } _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 = SeLocateProcessImageName(Process, &ImageName); if (NT_SUCCESS(Status)) @@ -435,6 +732,45 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, /* Free the image path */ ExFreePool(ImageName); } + /* Dereference the process */ + ObDereferenceObject(Process); + break; + + case ProcessBreakOnTermination: + + /* 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 */ + _SEH2_TRY + { + /* Return the BreakOnTermination state */ + *(PULONG)ProcessInformation = Process->BreakOnTermination; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Get the exception code */ + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + /* Dereference the process */ + ObDereferenceObject(Process); break; /* Per-process security cookie */ @@ -465,6 +801,9 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, Length = sizeof(ULONG); } + /* Indicate success */ + Status = STATUS_SUCCESS; + /* Enter SEH to protect write */ _SEH2_TRY { @@ -491,6 +830,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, case ProcessAffinityMask: case ProcessForegroundInformation: default: + DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass); Status = STATUS_INVALID_INFO_CLASS; } @@ -507,8 +847,6 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, } _SEH2_END; - /* If we referenced the process, dereference it */ - if(ProcessInformationClass != ProcessCookie) ObDereferenceObject(Process); return Status; } @@ -529,6 +867,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, HANDLE PortHandle = NULL; HANDLE TokenHandle = NULL; PROCESS_SESSION_INFORMATION SessionInfo = {0}; + PROCESS_PRIORITY_CLASS PriorityClass = {0}; PVOID ExceptionPort; PAGED_CODE(); @@ -568,16 +907,16 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, /* 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 */ _SEH2_TRY { @@ -590,6 +929,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, Status = _SEH2_GetExceptionCode(); } _SEH2_END; + if (!NT_SUCCESS(Status)) break; /* Get the LPC Port */ @@ -615,6 +955,13 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, /* Security Token */ case ProcessAccessToken: + /* Check buffer length */ + if (ProcessInformationLength != sizeof(PROCESS_ACCESS_TOKEN)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + /* Use SEH for capture */ _SEH2_TRY { @@ -628,6 +975,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, Status = _SEH2_GetExceptionCode(); } _SEH2_END; + if (!NT_SUCCESS(Status)) break; /* Assign the actual token */ @@ -637,6 +985,13 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, /* Hard error processing */ case ProcessDefaultHardErrorMode: + /* Check buffer length */ + if (ProcessInformationLength != sizeof(ULONG)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + /* Enter SEH for direct buffer read */ _SEH2_TRY { @@ -655,6 +1010,13 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, /* Session ID */ case ProcessSessionInformation: + /* Check buffer length */ + if (ProcessInformationLength != sizeof(PROCESS_SESSION_INFORMATION)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + /* Enter SEH for capture */ _SEH2_TRY { @@ -667,6 +1029,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, Status = _SEH2_GetExceptionCode(); } _SEH2_END; + if (!NT_SUCCESS(Status)) break; /* Setting the session id requires the SeTcbPrivilege */ @@ -714,8 +1077,148 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, //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) + { + /* Return 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; + + case ProcessQuotaLimits: + + /* Check buffer length */ + if (ProcessInformationLength != sizeof(QUOTA_LIMITS)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + + DPRINT1("Not implemented: ProcessQuotaLimits\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessBasePriority: + + /* Check buffer length */ + if (ProcessInformationLength != sizeof(KPRIORITY)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + + DPRINT1("Not implemented: ProcessBasePriority\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessRaisePriority: + + /* Check buffer length */ + if (ProcessInformationLength != sizeof(ULONG)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + + DPRINT1("Not implemented: ProcessRaisePriority\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessWx86Information: + + /* Check buffer length */ + if (ProcessInformationLength != sizeof(HANDLE)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + + DPRINT1("Not implemented: ProcessWx86Information\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessDebugPort: + + /* Check buffer length */ + if (ProcessInformationLength != sizeof(HANDLE)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + + DPRINT1("Not implemented: ProcessDebugPort\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessBreakOnTermination: + + /* Check buffer length */ + if (ProcessInformationLength != sizeof(ULONG)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + + /* Setting 'break on termination' requires the SeDebugPrivilege */ + if (!SeSinglePrivilegeCheck(SeDebugPrivilege, PreviousMode)) + { + Status = STATUS_PRIVILEGE_NOT_HELD; + break; + } + + /* Enter SEH for direct buffer read */ + _SEH2_TRY + { + Process->BreakOnTermination = *(PULONG)ProcessInformation; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Get exception code */ + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; break; /* We currently don't implement any of these */ @@ -726,6 +1229,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, case ProcessUserModeIOPL: case ProcessEnableAlignmentFaultFixup: case ProcessAffinityMask: + DPRINT1("Not implemented: %lx\n", ProcessInformationClass); Status = STATUS_NOT_IMPLEMENTED; break; @@ -734,11 +1238,10 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, case ProcessIoCounters: case ProcessTimes: case ProcessPooledUsageAndLimits: - case ProcessWx86Information: case ProcessHandleCount: case ProcessWow64Information: - case ProcessDebugPort: default: + DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass); Status = STATUS_INVALID_INFO_CLASS; } @@ -793,7 +1296,7 @@ NtSetInformationThread(IN HANDLE ThreadHandle, Access = THREAD_SET_THREAD_TOKEN; } - /* Reference the process */ + /* Reference the thread */ Status = ObReferenceObjectByHandle(ThreadHandle, Access, PsThreadType, @@ -808,6 +1311,13 @@ NtSetInformationThread(IN HANDLE ThreadHandle, /* Thread priority */ case ThreadPriority: + /* Check buffer length */ + if (ThreadInformationLength != sizeof(KPRIORITY)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + /* Use SEH for capture */ _SEH2_TRY { @@ -820,6 +1330,7 @@ NtSetInformationThread(IN HANDLE ThreadHandle, Status = _SEH2_GetExceptionCode(); } _SEH2_END; + if (!NT_SUCCESS(Status)) break; /* Validate it */ @@ -837,6 +1348,13 @@ NtSetInformationThread(IN HANDLE ThreadHandle, case ThreadBasePriority: + /* Check buffer length */ + if (ThreadInformationLength != sizeof(LONG)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + /* Use SEH for capture */ _SEH2_TRY { @@ -849,6 +1367,7 @@ NtSetInformationThread(IN HANDLE ThreadHandle, Status = _SEH2_GetExceptionCode(); } _SEH2_END; + if (!NT_SUCCESS(Status)) break; /* Validate it */ @@ -876,6 +1395,13 @@ NtSetInformationThread(IN HANDLE ThreadHandle, case ThreadAffinityMask: + /* Check buffer length */ + if (ThreadInformationLength != sizeof(ULONG_PTR)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + /* Use SEH for capture */ _SEH2_TRY { @@ -888,7 +1414,6 @@ NtSetInformationThread(IN HANDLE ThreadHandle, Status = _SEH2_GetExceptionCode(); } _SEH2_END; - if (!NT_SUCCESS(Status)) break; /* Validate it */ if (!Affinity) @@ -937,6 +1462,13 @@ NtSetInformationThread(IN HANDLE ThreadHandle, case ThreadImpersonationToken: + /* Check buffer length */ + if (ThreadInformationLength != sizeof(HANDLE)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + /* Use SEH for capture */ _SEH2_TRY { @@ -949,6 +1481,7 @@ NtSetInformationThread(IN HANDLE ThreadHandle, Status = _SEH2_GetExceptionCode(); } _SEH2_END; + if (!NT_SUCCESS(Status)) break; /* Assign the actual token */ @@ -957,6 +1490,13 @@ NtSetInformationThread(IN HANDLE ThreadHandle, case ThreadQuerySetWin32StartAddress: + /* Check buffer length */ + if (ThreadInformationLength != sizeof(ULONG_PTR)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + /* Use SEH for capture */ _SEH2_TRY { @@ -969,6 +1509,7 @@ NtSetInformationThread(IN HANDLE ThreadHandle, Status = _SEH2_GetExceptionCode(); } _SEH2_END; + if (!NT_SUCCESS(Status)) break; /* Set the address */ @@ -977,6 +1518,13 @@ NtSetInformationThread(IN HANDLE ThreadHandle, case ThreadIdealProcessor: + /* Check buffer length */ + if (ThreadInformationLength != sizeof(ULONG_PTR)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + /* Use SEH for capture */ _SEH2_TRY { @@ -989,6 +1537,7 @@ NtSetInformationThread(IN HANDLE ThreadHandle, Status = _SEH2_GetExceptionCode(); } _SEH2_END; + if (!NT_SUCCESS(Status)) break; /* Validate it */ @@ -1018,6 +1567,13 @@ NtSetInformationThread(IN HANDLE ThreadHandle, case ThreadPriorityBoost: + /* Check buffer length */ + if (ThreadInformationLength != sizeof(ULONG_PTR)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + /* Use SEH for capture */ _SEH2_TRY { @@ -1030,6 +1586,7 @@ NtSetInformationThread(IN HANDLE ThreadHandle, Status = _SEH2_GetExceptionCode(); } _SEH2_END; + if (!NT_SUCCESS(Status)) break; /* Call the kernel */ @@ -1038,6 +1595,13 @@ NtSetInformationThread(IN HANDLE ThreadHandle, case ThreadZeroTlsCell: + /* Check buffer length */ + if (ThreadInformationLength != sizeof(ULONG_PTR)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + /* Use SEH for capture */ _SEH2_TRY { @@ -1050,6 +1614,7 @@ NtSetInformationThread(IN HANDLE ThreadHandle, Status = _SEH2_GetExceptionCode(); } _SEH2_END; + if (!NT_SUCCESS(Status)) break; /* This is only valid for the current thread */ @@ -1131,7 +1696,7 @@ NtQueryInformationThread(IN HANDLE ThreadHandle, { PETHREAD Thread; KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); - NTSTATUS Status = STATUS_SUCCESS; + NTSTATUS Status; ULONG Access; ULONG Length = 0; PTHREAD_BASIC_INFORMATION ThreadBasicInfo = @@ -1140,17 +1705,27 @@ NtQueryInformationThread(IN HANDLE ThreadHandle, KIRQL OldIrql; PAGED_CODE(); - /* Verify Information Class validity */ -#if 0 - Status = DefaultQueryInfoBufferCheck(ThreadInformationClass, - PsThreadInfoClass, - RTL_NUMBER_OF(PsThreadInfoClass), - ThreadInformation, - ThreadInformationLength, - ReturnLength, - PreviousMode); - if (!NT_SUCCESS(Status)) return Status; -#endif + /* Check if we were called from user mode */ + if (PreviousMode != KernelMode) + { + /* Enter SEH */ + _SEH2_TRY + { + /* Probe the buffer */ + ProbeForWrite(ThreadInformation, + ThreadInformationLength, + sizeof(ULONG)); + + /* Probe the return length if required */ + if (ReturnLength) ProbeForWriteUlong(ReturnLength); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Return the exception code */ + _SEH2_YIELD(return _SEH2_GetExceptionCode()); + } + _SEH2_END; + } /* Check what class this is */ Access = THREAD_QUERY_INFORMATION; @@ -1170,6 +1745,14 @@ NtQueryInformationThread(IN HANDLE ThreadHandle, /* Basic thread information */ case ThreadBasicInformation: + /* Set return length */ + Length = sizeof(THREAD_BASIC_INFORMATION); + + if (ThreadInformationLength != Length) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } /* Protect writes with SEH */ _SEH2_TRY { @@ -1180,9 +1763,6 @@ NtQueryInformationThread(IN HANDLE ThreadHandle, ThreadBasicInfo->AffinityMask = Thread->Tcb.Affinity; ThreadBasicInfo->Priority = Thread->Tcb.Priority; ThreadBasicInfo->BasePriority = KeQueryBasePriorityThread(&Thread->Tcb); - - /* Set return length */ - Length = sizeof(THREAD_BASIC_INFORMATION); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -1195,6 +1775,14 @@ NtQueryInformationThread(IN HANDLE ThreadHandle, /* Thread time information */ case ThreadTimes: + /* Set the return length */ + Length = sizeof(KERNEL_USER_TIMES); + + if (ThreadInformationLength != Length) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } /* Protect writes with SEH */ _SEH2_TRY { @@ -1205,9 +1793,6 @@ NtQueryInformationThread(IN HANDLE ThreadHandle, 100000LL; ThreadTime->CreateTime = Thread->CreateTime; ThreadTime->ExitTime = Thread->ExitTime; - - /* Set the return length */ - Length = sizeof(KERNEL_USER_TIMES); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -1219,14 +1804,19 @@ NtQueryInformationThread(IN HANDLE ThreadHandle, case ThreadQuerySetWin32StartAddress: + /* 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; - - /* Set the return length*/ - Length = sizeof(PVOID); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -1238,14 +1828,19 @@ NtQueryInformationThread(IN HANDLE ThreadHandle, case ThreadPerformanceCount: + /* 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; - - /* Set the return length*/ - Length = sizeof(LARGE_INTEGER); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -1257,6 +1852,14 @@ NtQueryInformationThread(IN HANDLE ThreadHandle, case ThreadAmILastThread: + /* Set the return length*/ + Length = sizeof(ULONG); + + if (ThreadInformationLength != Length) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } /* Protect write with SEH */ _SEH2_TRY { @@ -1266,9 +1869,6 @@ NtQueryInformationThread(IN HANDLE ThreadHandle, &Thread->ThreadsProcess-> ThreadListHead) ? TRUE : FALSE); - - /* Set the return length*/ - Length = sizeof(ULONG); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -1280,6 +1880,14 @@ NtQueryInformationThread(IN HANDLE ThreadHandle, case ThreadIsIoPending: + /* Set the return length*/ + Length = sizeof(ULONG); + + if (ThreadInformationLength != Length) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } /* Raise the IRQL to protect the IRP list */ KeRaiseIrql(APC_LEVEL, &OldIrql); @@ -1288,9 +1896,6 @@ NtQueryInformationThread(IN HANDLE ThreadHandle, { /* Check if the IRP list is empty or not */ *(PULONG)ThreadInformation = !IsListEmpty(&Thread->IrpList); - - /* Set the return length*/ - Length = sizeof(ULONG); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -1303,6 +1908,43 @@ NtQueryInformationThread(IN HANDLE ThreadHandle, KeLowerIrql(OldIrql); break; + /* LDT and GDT information */ + case ThreadDescriptorTableEntry: + +#if defined(_X86_) + /* Call the worker routine */ + Status = PspQueryDescriptorThread(Thread, + ThreadInformation, + ThreadInformationLength, + ReturnLength); +#else + /* Only implemented on x86 */ + Status = STATUS_NOT_IMPLEMENTED; +#endif + 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: