diff --git a/reactos/include/ndk/pstypes.h b/reactos/include/ndk/pstypes.h index d0f2fecc982..d7a90a349cf 100644 --- a/reactos/include/ndk/pstypes.h +++ b/reactos/include/ndk/pstypes.h @@ -222,6 +222,12 @@ Author: #define STA_ADDRESS_SPACE_OWNER_BIT 0x4 #define STA_OWNS_WORKING_SET_BITS 0x1F8 +// +// Kernel Process flags (maybe in ketypes.h?) +// +#define KPSF_AUTO_ALIGNMENT_BIT 0 +#define KPSF_DISABLE_BOOST_BIT 1 + // // Process Flags // @@ -762,6 +768,11 @@ typedef struct _PROCESS_PRIORITY_CLASS UCHAR PriorityClass; } PROCESS_PRIORITY_CLASS, *PPROCESS_PRIORITY_CLASS; +typedef struct _PROCESS_FOREGROUND_BACKGROUND +{ + BOOLEAN Foreground; +} PROCESS_FOREGROUND_BACKGROUND, *PPROCESS_FOREGROUND_BACKGROUND; + // // Thread Information Structures for NtQueryProcessInformation // diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index 2d29738cdee..8133b1c021c 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -269,6 +269,34 @@ KeSetDisableBoostThread( IN BOOLEAN Disable ); +BOOLEAN +NTAPI +KeSetDisableBoostProcess( + IN PKPROCESS Process, + IN BOOLEAN Disable +); + +BOOLEAN +NTAPI +KeSetAutoAlignmentProcess( + IN PKPROCESS Process, + IN BOOLEAN Enable +); + +KAFFINITY +NTAPI +KeSetAffinityProcess( + IN PKPROCESS Process, + IN KAFFINITY Affinity +); + +VOID +NTAPI +KeBoostPriorityThread( + IN PKTHREAD Thread, + IN KPRIORITY Increment +); + VOID NTAPI KeBalanceSetManager(IN PVOID Context); diff --git a/reactos/ntoskrnl/ke/procobj.c b/reactos/ntoskrnl/ke/procobj.c index 6802f2553da..7051c8241e1 100644 --- a/reactos/ntoskrnl/ke/procobj.c +++ b/reactos/ntoskrnl/ke/procobj.c @@ -260,6 +260,90 @@ KeSetQuantumProcess(IN PKPROCESS Process, KiReleaseProcessLock(&ProcessLock); } +KAFFINITY +NTAPI +KeSetAffinityProcess(IN PKPROCESS Process, + IN KAFFINITY Affinity) +{ + + KLOCK_QUEUE_HANDLE ProcessLock; + PLIST_ENTRY NextEntry, ListHead; + KAFFINITY OldAffinity; + PKTHREAD Thread; + ASSERT_PROCESS(Process); + ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); + ASSERT((Affinity & KeActiveProcessors) != 0); + + /* Lock the process */ + KiAcquireProcessLock(Process, &ProcessLock); + + /* Acquire the dispatcher lock */ + KiAcquireDispatcherLockAtDpcLevel(); + + /* Capture old affinity and update it */ + OldAffinity = Process->Affinity; + Process->Affinity = Affinity; + + /* Loop all child threads */ + ListHead = &Process->ThreadListHead; + NextEntry = ListHead->Flink; + while (ListHead != NextEntry) + { + /* Get the thread */ + Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry); + + /* Set affinity on it */ + KiSetAffinityThread(Thread, Affinity); + NextEntry = NextEntry->Flink; + } + + /* Release Dispatcher Database */ + KiReleaseDispatcherLockFromDpcLevel(); + + /* Release the process lock */ + KiReleaseProcessLockFromDpcLevel(&ProcessLock); + KiExitDispatcher(ProcessLock.OldIrql); + + /* Return previous affinity */ + return OldAffinity; +} + +BOOLEAN +NTAPI +KeSetAutoAlignmentProcess(IN PKPROCESS Process, + IN BOOLEAN Enable) +{ + /* Set or reset the bit depending on what the enable flag says */ + if (Enable) + { + return InterlockedBitTestAndSet(&Process->ProcessFlags, + KPSF_AUTO_ALIGNMENT_BIT); + } + else + { + return InterlockedBitTestAndReset(&Process->ProcessFlags, + KPSF_AUTO_ALIGNMENT_BIT); + } +} + +BOOLEAN +NTAPI +KeSetDisableBoostProcess(IN PKPROCESS Process, + IN BOOLEAN Disable) +{ + /* Set or reset the bit depending on what the disable flag says */ + if (Disable) + { + return InterlockedBitTestAndSet(&Process->ProcessFlags, + KPSF_DISABLE_BOOST_BIT); + } + else + { + return InterlockedBitTestAndReset(&Process->ProcessFlags, + KPSF_DISABLE_BOOST_BIT); + } +} + KPRIORITY NTAPI KeSetPriorityAndQuantumProcess(IN PKPROCESS Process, diff --git a/reactos/ntoskrnl/ke/thrdobj.c b/reactos/ntoskrnl/ke/thrdobj.c index 34bfa4bdc5c..cfccf0de1b2 100644 --- a/reactos/ntoskrnl/ke/thrdobj.c +++ b/reactos/ntoskrnl/ke/thrdobj.c @@ -224,6 +224,53 @@ KeAlertThread(IN PKTHREAD Thread, return PreviousState; } +VOID +NTAPI +KeBoostPriorityThread(IN PKTHREAD Thread, + IN KPRIORITY Increment) +{ + KIRQL OldIrql; + KPRIORITY Priority; + ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); + + /* Lock the Dispatcher Database */ + OldIrql = KiAcquireDispatcherLock(); + + /* Only threads in the dynamic range get boosts */ + if (Thread->Priority < LOW_REALTIME_PRIORITY) + { + /* Lock the thread */ + KiAcquireThreadLock(Thread); + + /* Check again, and make sure there's not already a boost */ + if ((Thread->Priority < LOW_REALTIME_PRIORITY) && + !(Thread->PriorityDecrement)) + { + /* Compute the new priority and see if it's higher */ + Priority = Thread->BasePriority + Increment; + if (Priority > Thread->Priority) + { + if (Priority >= LOW_REALTIME_PRIORITY) + { + Priority = LOW_REALTIME_PRIORITY - 1; + } + + /* Reset the quantum */ + Thread->Quantum = Thread->QuantumReset; + + /* Set the new Priority */ + KiSetPriorityThread(Thread, Priority); + } + } + + /* Release thread lock */ + KiReleaseThreadLock(Thread); + } + + /* Release the dispatcher lokc */ + KiReleaseDispatcherLock(OldIrql); +} + ULONG NTAPI KeForceResumeThread(IN PKTHREAD Thread) diff --git a/reactos/ntoskrnl/ps/query.c b/reactos/ntoskrnl/ps/query.c index 740cbfa6cfb..15ec9123c1c 100644 --- a/reactos/ntoskrnl/ps/query.c +++ b/reactos/ntoskrnl/ps/query.c @@ -14,6 +14,9 @@ #define NDEBUG #include +/* FIXME: From winbase.h... what to do? */ +#define SEM_NOALIGNMENTFAULTEXCEPT 0x04 + /* Include Information Class Tables */ #include "internal/ps_i.h" @@ -247,6 +250,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, _SEH2_TRY { + /* FIXME: Call KeQueryValuesProcess */ IoCounters->ReadOperationCount = Process->ReadOperationCount.QuadPart; IoCounters->ReadTransferCount = Process->ReadTransferCount.QuadPart; IoCounters->WriteOperationCount = Process->WriteOperationCount.QuadPart; @@ -292,11 +296,12 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, _SEH2_TRY { /* Copy time information from EPROCESS/KPROCESS */ + /* FIXME: Call KeQueryRuntimeProcess */ ProcessTime->CreateTime = Process->CreateTime; ProcessTime->UserTime.QuadPart = Process->Pcb.UserTime * - 100000LL; + KeMaximumIncrement; ProcessTime->KernelTime.QuadPart = Process->Pcb.KernelTime * - 100000LL; + KeMaximumIncrement; ProcessTime->ExitTime = Process->ExitTime; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) @@ -349,27 +354,6 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, 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; - case ProcessHandleCount: /* Set the return length*/ @@ -435,50 +419,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, _SEH2_TRY { /* Write back the Session ID */ - SessionInfo->SessionId = Process->Session; - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - /* Get the exception code */ - 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; - - /* Protect write in SEH */ - _SEH2_TRY - { -#ifdef _WIN64 - DPRINT1("Not implemented: ProcessWow64Information\n"); - Status = STATUS_NOT_IMPLEMENTED; -#else - /* Wow64 not present */ - *(PULONG_PTR)ProcessInformation = 0; -#endif + SessionInfo->SessionId = Process->Session; //MmGetSessionId(Process); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -494,15 +435,17 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, /* Virtual Memory Statistics */ case ProcessVmCounters: - /* Set the return length */ - Length = sizeof(VM_COUNTERS); - - if (ProcessInformationLength != Length) + /* Validate the input length */ + if ((ProcessInformationLength != sizeof(VM_COUNTERS)) && + (ProcessInformationLength != sizeof(VM_COUNTERS_EX))) { Status = STATUS_INFO_LENGTH_MISMATCH; break; } + /* Set the return length */ + Length = ProcessInformationLength; + /* Reference the process */ Status = ObReferenceObjectByHandle(ProcessHandle, PROCESS_QUERY_INFORMATION, @@ -525,9 +468,9 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, VmCounters->QuotaPagedPoolUsage = Process->QuotaUsage[0]; VmCounters->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[1]; VmCounters->QuotaNonPagedPoolUsage = Process->QuotaUsage[1]; - VmCounters->PagefileUsage = Process->QuotaUsage[2]; - VmCounters->PeakPagefileUsage = Process->QuotaPeak[2]; - + VmCounters->PagefileUsage = Process->QuotaUsage[2] << PAGE_SHIFT; + VmCounters->PeakPagefileUsage = Process->QuotaPeak[2] << PAGE_SHIFT; + //VmCounters->PrivateUsage = Process->CommitCharge << PAGE_SHIFT; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -582,7 +525,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, /* Priority Boosting status */ case ProcessPriorityBoost: - /* Set the return length*/ + /* Set the return length */ Length = sizeof(ULONG); if (ProcessInformationLength != Length) @@ -621,12 +564,20 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, /* DOS Device Map */ case ProcessDeviceMap: - /* Set the return length*/ + /* Set the return length */ Length = sizeof(PROCESS_DEVICEMAP_INFORMATION); if (ProcessInformationLength != Length) { - Status = STATUS_INFO_LENGTH_MISMATCH; + if (ProcessInformationLength == sizeof(PROCESS_DEVICEMAP_INFORMATION_EX)) + { + DPRINT1("PROCESS_DEVICEMAP_INFORMATION_EX not supported!\n"); + Status = STATUS_NOT_IMPLEMENTED; + } + else + { + Status = STATUS_INFO_LENGTH_MISMATCH; + } break; } @@ -751,6 +702,42 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, ObDereferenceObject(Process); break; + case ProcessDebugFlags: + + /* 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 debug flag state */ + *(PULONG)ProcessInformation = Process->NoDebugInherit ? 0 : 1; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Get the exception code */ + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + /* Dereference the process */ + ObDereferenceObject(Process); + break; + case ProcessBreakOnTermination: /* Set the return length*/ @@ -831,20 +818,52 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, } _SEH2_END; break; + + case ProcessImageInformation: + DPRINT1("Image Information Query Not implemented: %lx\n", ProcessInformationClass); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessDebugObjectHandle: + DPRINT1("Debug Object Query Not implemented: %lx\n", ProcessInformationClass); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessHandleTracing: + DPRINT1("Handle tracing Not implemented: %lx\n", ProcessInformationClass); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessLUIDDeviceMapsEnabled: + DPRINT1("LUID Device Maps Not implemented: %lx\n", ProcessInformationClass); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessExecuteFlags: + DPRINT1("No execute Not implemented: %lx\n", ProcessInformationClass); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessWow64Information: + case ProcessLdtInformation: + case ProcessWx86Information: + DPRINT1("VDM/16-bit implemented: %lx\n", ProcessInformationClass); + Status = STATUS_NOT_IMPLEMENTED; + break; - /* Not yet implemented, or unknown */ - case ProcessBasePriority: - case ProcessRaisePriority: - case ProcessExceptionPort: - case ProcessAccessToken: - case ProcessLdtSize: - case ProcessIoPortHandlers: - case ProcessUserModeIOPL: - case ProcessEnableAlignmentFaultFixup: - case ProcessAffinityMask: - case ProcessForegroundInformation: + case ProcessWorkingSetWatch: + DPRINT1("WS Watch Not implemented: %lx\n", ProcessInformationClass); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessPooledUsageAndLimits: + DPRINT1("Pool limits Not implemented: %lx\n", ProcessInformationClass); + Status = STATUS_NOT_IMPLEMENTED; + break; + + /* Not supported by Server 2003 */ default: - DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass); + DPRINT1("Unsupported info class: %lx\n", ProcessInformationClass); Status = STATUS_INVALID_INFO_CLASS; } @@ -882,8 +901,14 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, HANDLE TokenHandle = NULL; PROCESS_SESSION_INFORMATION SessionInfo = {0}; PROCESS_PRIORITY_CLASS PriorityClass = {0}; + PROCESS_FOREGROUND_BACKGROUND Foreground = {0}; PVOID ExceptionPort; ULONG Break; + KAFFINITY ValidAffinity, Affinity = 0; + ULONG DefaultHardErrorMode = 0, BasePriority = 0, MemoryPriority = 0; + ULONG DisableBoost = 0, DebugFlags = 0, EnableFixup = 0, Boost = 0; + PLIST_ENTRY Next; + PETHREAD Thread; PAGED_CODE(); /* Verify Information Class validity */ @@ -946,6 +971,14 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, } _SEH2_END; + /* Setting the error port requires the SeTcbPrivilege */ + if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode)) + { + /* Can't set the session ID, bail out. */ + Status = STATUS_PRIVILEGE_NOT_HELD; + break; + } + /* Get the LPC Port */ Status = ObReferenceObjectByHandle(PortHandle, 0, @@ -1008,16 +1041,29 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, /* Enter SEH for direct buffer read */ _SEH2_TRY { - /* Update the current mode abd return the previous one */ - InterlockedExchange((LONG*)&Process->DefaultHardErrorProcessing, - *(PLONG)ProcessInformation); + DefaultHardErrorMode = *(PULONG)ProcessInformation; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Get exception code */ Status = _SEH2_GetExceptionCode(); + _SEH2_YIELD(break); } _SEH2_END; + + /* Set the mode */ + Process->DefaultHardErrorProcessing = DefaultHardErrorMode; + + /* Call Ke for the update */ + if (DefaultHardErrorMode & SEM_NOALIGNMENTFAULTEXCEPT) + { + KeSetAutoAlignmentProcess(&Process->Pcb, TRUE); + } + else + { + KeSetAutoAlignmentProcess(&Process->Pcb, FALSE); + } + Status = STATUS_SUCCESS; break; /* Session ID */ @@ -1119,7 +1165,12 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, break; } - /* TODO: Check privileges */ + if ((PriorityClass.PriorityClass != Process->PriorityClass) && + (PriorityClass.PriorityClass == PROCESS_PRIORITY_CLASS_REALTIME)) + { + /* TODO: Check privileges */ + DPRINT1("Should check privilege\n"); + } /* Check if we have a job */ if (Process->Job) @@ -1132,75 +1183,150 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, /* Set process priority mode (foreground or background) */ PsSetProcessPriorityByClass(Process, - !PriorityClass.Foreground ? PsProcessPriorityBackground : - PsProcessPriorityForeground); - + PriorityClass.Foreground ? + PsProcessPriorityForeground : + PsProcessPriorityBackground); Status = STATUS_SUCCESS; break; - case ProcessQuotaLimits: + case ProcessForegroundInformation: /* Check buffer length */ - if (ProcessInformationLength != sizeof(QUOTA_LIMITS)) + if (ProcessInformationLength != sizeof(PROCESS_FOREGROUND_BACKGROUND)) { Status = STATUS_INFO_LENGTH_MISMATCH; break; } - DPRINT1("Not implemented: ProcessQuotaLimits\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; + /* Enter SEH for capture */ + _SEH2_TRY + { + /* Capture the caller's buffer */ + Foreground = *(PPROCESS_FOREGROUND_BACKGROUND)ProcessInformation; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Return the exception code */ + Status = _SEH2_GetExceptionCode(); + _SEH2_YIELD(break); + } + _SEH2_END; + /* Set process priority mode (foreground or background) */ + PsSetProcessPriorityByClass(Process, + Foreground.Foreground ? + PsProcessPriorityForeground : + PsProcessPriorityBackground); + Status = STATUS_SUCCESS; + break; + case ProcessBasePriority: - /* Check buffer length */ + /* Validate input length */ if (ProcessInformationLength != sizeof(KPRIORITY)) { Status = STATUS_INFO_LENGTH_MISMATCH; break; } - DPRINT1("Not implemented: ProcessBasePriority\n"); - Status = STATUS_NOT_IMPLEMENTED; + /* Enter SEH for direct buffer read */ + _SEH2_TRY + { + BasePriority = *(PULONG)ProcessInformation; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Get exception code */ + Break = 0; + Status = _SEH2_GetExceptionCode(); + _SEH2_YIELD(break); + } + _SEH2_END; + + /* Extract the memory priority out of there */ + if (BasePriority & 0x80000000) + { + MemoryPriority = MEMORY_PRIORITY_FOREGROUND; + BasePriority &= ~0x80000000; + } + else + { + MemoryPriority = MEMORY_PRIORITY_BACKGROUND; + } + + /* Validate the number */ + if ((BasePriority > HIGH_PRIORITY) || (BasePriority <= LOW_PRIORITY)) + { + return STATUS_INVALID_PARAMETER; + } + + /* Check if the new base is higher */ + if (BasePriority > Process->Pcb.BasePriority) + { + DPRINT1("Should check privilege\n"); + } + + /* Call Ke */ + KeSetPriorityAndQuantumProcess(&Process->Pcb, BasePriority, 0); + + /* Now set the memory priority */ + MmSetMemoryPriorityProcess(Process, MemoryPriority); + Status = STATUS_SUCCESS; break; case ProcessRaisePriority: - /* Check buffer length */ + /* Validate input 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)) + /* Enter SEH for direct buffer read */ + _SEH2_TRY { - Status = STATUS_INFO_LENGTH_MISMATCH; - break; + Boost = *(PULONG)ProcessInformation; } - - DPRINT1("Not implemented: ProcessWx86Information\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; - - case ProcessDebugPort: - - /* Check buffer length */ - if (ProcessInformationLength != sizeof(HANDLE)) + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - Status = STATUS_INFO_LENGTH_MISMATCH; - break; + /* Get exception code */ + Break = 0; + Status = _SEH2_GetExceptionCode(); + _SEH2_YIELD(break); } + _SEH2_END; - DPRINT1("Not implemented: ProcessDebugPort\n"); - Status = STATUS_NOT_IMPLEMENTED; + /* Make sure the process isn't dying */ + if (ExAcquireRundownProtection(&Process->RundownProtect)) + { + /* Lock it */ + KeEnterCriticalRegion(); + ExAcquirePushLockShared(&Process->ProcessLock); + + /* Loop the threads */ + for (Next = Process->ThreadListHead.Flink; + Next != &Process->ThreadListHead; + Next = Next->Flink) + { + /* Call Ke for the thread */ + Thread = CONTAINING_RECORD(Next, ETHREAD, ThreadListEntry); + KeBoostPriorityThread(&Thread->Tcb, Boost); + } + + /* Release the lock and rundown */ + ExReleasePushLockShared(&Process->ProcessLock); + KeLeaveCriticalRegion(); + ExReleaseRundownProtection(&Process->RundownProtect); + + /* Set success code */ + Status = STATUS_SUCCESS; + } + else + { + /* Avoid race conditions */ + Status = STATUS_PROCESS_IS_TERMINATING; + } break; case ProcessBreakOnTermination: @@ -1244,28 +1370,249 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, } break; + + case ProcessAffinityMask: + + /* Check buffer length */ + if (ProcessInformationLength != sizeof(KAFFINITY)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + /* Enter SEH for direct buffer read */ + _SEH2_TRY + { + Affinity = *(PKAFFINITY)ProcessInformation; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Get exception code */ + Break = 0; + Status = _SEH2_GetExceptionCode(); + _SEH2_YIELD(break); + } + _SEH2_END; + + /* Make sure it's valid for the CPUs present */ + ValidAffinity = Affinity & KeActiveProcessors; + if (!Affinity || (ValidAffinity != Affinity)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + /* Check if it's within job affinity limits */ + if (Process->Job) + { + /* Not yet implemented */ + UNIMPLEMENTED; + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + /* Make sure the process isn't dying */ + if (ExAcquireRundownProtection(&Process->RundownProtect)) + { + /* Lock it */ + KeEnterCriticalRegion(); + ExAcquirePushLockShared(&Process->ProcessLock); + + /* Call Ke to do the work */ + KeSetAffinityProcess(&Process->Pcb, ValidAffinity); + + /* Release the lock and rundown */ + ExReleasePushLockShared(&Process->ProcessLock); + KeLeaveCriticalRegion(); + ExReleaseRundownProtection(&Process->RundownProtect); + + /* Set success code */ + Status = STATUS_SUCCESS; + } + else + { + /* Avoid race conditions */ + Status = STATUS_PROCESS_IS_TERMINATING; + } + break; + + /* Priority Boosting status */ + case ProcessPriorityBoost: + + /* Validate input length */ + if (ProcessInformationLength != sizeof(ULONG)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + + /* Enter SEH for direct buffer read */ + _SEH2_TRY + { + DisableBoost = *(PULONG)ProcessInformation; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Get exception code */ + Break = 0; + Status = _SEH2_GetExceptionCode(); + _SEH2_YIELD(break); + } + _SEH2_END; + + /* Make sure the process isn't dying */ + if (ExAcquireRundownProtection(&Process->RundownProtect)) + { + /* Lock it */ + KeEnterCriticalRegion(); + ExAcquirePushLockShared(&Process->ProcessLock); + + /* Call Ke to do the work */ + KeSetDisableBoostProcess(&Process->Pcb, DisableBoost); + + /* Loop the threads too */ + for (Next = Process->ThreadListHead.Flink; + Next != &Process->ThreadListHead; + Next = Next->Flink) + { + /* Call Ke for the thread */ + Thread = CONTAINING_RECORD(Next, ETHREAD, ThreadListEntry); + KeSetDisableBoostThread(&Thread->Tcb, DisableBoost); + } + + /* Release the lock and rundown */ + ExReleasePushLockShared(&Process->ProcessLock); + KeLeaveCriticalRegion(); + ExReleaseRundownProtection(&Process->RundownProtect); + + /* Set success code */ + Status = STATUS_SUCCESS; + } + else + { + /* Avoid race conditions */ + Status = STATUS_PROCESS_IS_TERMINATING; + } + break; + + case ProcessDebugFlags: + + /* Check buffer length */ + if (ProcessInformationLength != sizeof(ULONG)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + + /* Enter SEH for direct buffer read */ + _SEH2_TRY + { + DebugFlags = *(PULONG)ProcessInformation; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Get exception code */ + Status = _SEH2_GetExceptionCode(); + _SEH2_YIELD(break); + } + _SEH2_END; + + /* Set the mode */ + if (DebugFlags & ~1) + { + Status = STATUS_INVALID_PARAMETER; + } + else + { + if (DebugFlags & 1) + { + PspClearProcessFlag(Process, PSF_NO_DEBUG_INHERIT_BIT); + } + else + { + PspSetProcessFlag(Process, PSF_NO_DEBUG_INHERIT_BIT); + } + } + + /* Done */ + Status = STATUS_SUCCESS; + break; + + case ProcessEnableAlignmentFaultFixup: + + /* Check buffer length */ + if (ProcessInformationLength != sizeof(ULONG)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + + /* Enter SEH for direct buffer read */ + _SEH2_TRY + { + EnableFixup = *(PULONG)ProcessInformation; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Get exception code */ + Status = _SEH2_GetExceptionCode(); + _SEH2_YIELD(break); + } + _SEH2_END; + + /* Set the mode */ + if (EnableFixup) + { + Process->DefaultHardErrorProcessing |= SEM_NOALIGNMENTFAULTEXCEPT; + } + else + { + Process->DefaultHardErrorProcessing &= ~SEM_NOALIGNMENTFAULTEXCEPT; + } + + /* Call Ke for the update */ + KeSetAutoAlignmentProcess(&Process->Pcb, FALSE); + Status = STATUS_SUCCESS; + break; + /* We currently don't implement any of these */ case ProcessLdtInformation: case ProcessLdtSize: case ProcessIoPortHandlers: - case ProcessWorkingSetWatch: case ProcessUserModeIOPL: - case ProcessEnableAlignmentFaultFixup: - case ProcessAffinityMask: - DPRINT1("Not implemented: %lx\n", ProcessInformationClass); + case ProcessWx86Information: + DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessQuotaLimits: + DPRINT1("Quota Limits not implemented\n"); Status = STATUS_NOT_IMPLEMENTED; break; - - /* Supposedly these are invalid...!? verify! */ - case ProcessBasicInformation: - case ProcessIoCounters: - case ProcessTimes: - case ProcessPooledUsageAndLimits: - case ProcessHandleCount: - case ProcessWow64Information: + + case ProcessWorkingSetWatch: + DPRINT1("WS watch not implemented\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessDeviceMap: + DPRINT1("Device map not implemented\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessHandleTracing: + DPRINT1("Handle tracing not implemented\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessExecuteFlags: + DPRINT1("No execute support not implemented\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + /* Anything else is invalid */ default: - DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass); + DPRINT1("Invalid Server 2003 Info Class: %lx\n", ProcessInformationClass); Status = STATUS_INVALID_INFO_CLASS; } @@ -1434,6 +1781,7 @@ NtSetInformationThread(IN HANDLE ThreadHandle, { /* Get the exception code */ Status = _SEH2_GetExceptionCode(); + _SEH2_YIELD(break); } _SEH2_END;