diff --git a/reactos/ntoskrnl/dbgk/dbgkobj.c b/reactos/ntoskrnl/dbgk/dbgkobj.c index 347a96d1057..f8446c3ca62 100644 --- a/reactos/ntoskrnl/dbgk/dbgkobj.c +++ b/reactos/ntoskrnl/dbgk/dbgkobj.c @@ -1504,6 +1504,46 @@ DbgkInitialize(VOID) &DbgkDebugObjectType); } +NTSTATUS +NTAPI +DbgkOpenProcessDebugPort(IN PEPROCESS Process, + IN KPROCESSOR_MODE PreviousMode, + OUT HANDLE *DebugHandle) +{ + PDEBUG_OBJECT DebugObject; + NTSTATUS Status; + PAGED_CODE(); + + /* If there's no debug port, just exit */ + if (!Process->DebugPort) return STATUS_PORT_NOT_SET; + + /* Otherwise, acquire the lock while we grab the port */ + ExAcquireFastMutex(&DbgkpProcessDebugPortMutex); + + /* Grab it and reference it if it exists */ + DebugObject = Process->DebugPort; + if (DebugObject) ObReferenceObject(DebugObject); + + /* Release the lock now */ + ExReleaseFastMutex(&DbgkpProcessDebugPortMutex); + + /* Bail out if it doesn't exist */ + if (!DebugObject) return STATUS_PORT_NOT_SET; + + /* Now get a handle to it */ + Status = ObOpenObjectByPointer(DebugObject, + 0, + NULL, + MAXIMUM_ALLOWED, + DbgkDebugObjectType, + PreviousMode, + DebugHandle); + if (!NT_SUCCESS(Status)) ObDereferenceObject(DebugObject); + + /* Return status */ + return Status; +} + /* PUBLIC FUNCTIONS **********************************************************/ /* diff --git a/reactos/ntoskrnl/include/internal/dbgk.h b/reactos/ntoskrnl/include/internal/dbgk.h index d1e8f814c2a..dfa22a3bbc1 100644 --- a/reactos/ntoskrnl/include/internal/dbgk.h +++ b/reactos/ntoskrnl/include/internal/dbgk.h @@ -134,6 +134,14 @@ DbgkClearProcessDebugObject( IN PDEBUG_OBJECT SourceDebugObject ); +NTSTATUS +NTAPI +DbgkOpenProcessDebugPort( + IN PEPROCESS Process, + IN KPROCESSOR_MODE PreviousMode, + OUT HANDLE *DebugHandle +); + extern ULONG DbgkpTraceLevel; extern POBJECT_TYPE DbgkDebugObjectType; diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index bfbc60a4295..156972e4078 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -1507,6 +1507,10 @@ NTSTATUS NTAPI MmSetExecuteOptions(IN ULONG ExecuteOptions); +NTSTATUS +NTAPI +MmGetExecuteOptions(IN PULONG ExecuteOptions); + VOID NTAPI MmDeleteProcessPageDirectory(struct _EPROCESS *Process); diff --git a/reactos/ntoskrnl/mm/ARM3/pagfault.c b/reactos/ntoskrnl/mm/ARM3/pagfault.c index 4d3fb903f57..478725b7e4e 100644 --- a/reactos/ntoskrnl/mm/ARM3/pagfault.c +++ b/reactos/ntoskrnl/mm/ARM3/pagfault.c @@ -1094,11 +1094,52 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction, return Status; } +NTSTATUS +NTAPI +MmGetExecuteOptions(IN PULONG ExecuteOptions) +{ + PKPROCESS CurrentProcess = &PsGetCurrentProcess()->Pcb; + ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); + + *ExecuteOptions = 0; + + if (CurrentProcess->Flags.ExecuteDisable) + { + *ExecuteOptions |= MEM_EXECUTE_OPTION_DISABLE; + } + + if (CurrentProcess->Flags.ExecuteEnable) + { + *ExecuteOptions |= MEM_EXECUTE_OPTION_ENABLE; + } + + if (CurrentProcess->Flags.DisableThunkEmulation) + { + *ExecuteOptions |= MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION; + } + + if (CurrentProcess->Flags.Permanent) + { + *ExecuteOptions |= MEM_EXECUTE_OPTION_PERMANENT; + } + + if (CurrentProcess->Flags.ExecuteDispatchEnable) + { + *ExecuteOptions |= MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE; + } + + if (CurrentProcess->Flags.ImageDispatchEnable) + { + *ExecuteOptions |= MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE; + } + + return STATUS_SUCCESS; +} + NTSTATUS NTAPI MmSetExecuteOptions(IN ULONG ExecuteOptions) { - PKPROCESS CurrentProcess = &PsGetCurrentProcess()->Pcb; KLOCK_QUEUE_HANDLE ProcessLock; NTSTATUS Status = STATUS_ACCESS_DENIED; diff --git a/reactos/ntoskrnl/ps/query.c b/reactos/ntoskrnl/ps/query.c index f4fd8946194..9d308b47109 100644 --- a/reactos/ntoskrnl/ps/query.c +++ b/reactos/ntoskrnl/ps/query.c @@ -69,6 +69,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); NTSTATUS Status; ULONG Length = 0; + HANDLE DebugPort = 0; PPROCESS_BASIC_INFORMATION ProcessBasicInfo = (PPROCESS_BASIC_INFORMATION)ProcessInformation; PKERNEL_USER_TIMES ProcessTime = (PKERNEL_USER_TIMES)ProcessInformation; @@ -81,7 +82,8 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, PQUOTA_LIMITS QuotaLimits = (PQUOTA_LIMITS)ProcessInformation; PROCESS_DEVICEMAP_INFORMATION DeviceMap; PUNICODE_STRING ImageName; - ULONG Cookie; + ULONG Cookie, ExecuteOptions = 0; + ULONG_PTR Wow64 = 0; PAGED_CODE(); /* Check for user-mode caller */ @@ -443,9 +445,6 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, break; } - /* Set the return length */ - Length = ProcessInformationLength; - /* Reference the process */ Status = ObReferenceObjectByHandle(ProcessHandle, PROCESS_QUERY_INFORMATION, @@ -471,6 +470,10 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, VmCounters->PagefileUsage = Process->QuotaUsage[2] << PAGE_SHIFT; VmCounters->PeakPagefileUsage = Process->QuotaPeak[2] << PAGE_SHIFT; //VmCounters->PrivateUsage = Process->CommitCharge << PAGE_SHIFT; + // + + /* Set the return length */ + Length = ProcessInformationLength; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -825,8 +828,42 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, break; case ProcessDebugObjectHandle: - DPRINT1("Debug Object Query Not implemented: %lx\n", ProcessInformationClass); - Status = STATUS_NOT_IMPLEMENTED; + + /* Set the 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; + + /* Get the debug port */ + Status = DbgkOpenProcessDebugPort(Process, PreviousMode, &DebugPort); + + /* Let go of the process */ + ObDereferenceObject(Process); + + /* Protect write in SEH */ + _SEH2_TRY + { + /* Return the count of handles */ + *(PHANDLE)ProcessInformation = DebugPort; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Get the exception code */ + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; break; case ProcessHandleTracing: @@ -835,6 +872,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, break; case ProcessLUIDDeviceMapsEnabled: + /* Set the return length */ Length = sizeof(ULONG); if (ProcessInformationLength != Length) @@ -860,15 +898,118 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, _SEH2_END; break; - case ProcessExecuteFlags: - DPRINT1("No execute Not implemented: %lx\n", ProcessInformationClass); - Status = STATUS_NOT_IMPLEMENTED; + case ProcessWx86Information: + + /* Set the return length */ + Length = sizeof(ULONG); + if (ProcessInformationLength != Length) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + + /* Indicate success */ + Status = STATUS_SUCCESS; + + /* Protect write in SEH */ + _SEH2_TRY + { + /* Return if the flag is set */ + *(PULONG)ProcessInformation = (ULONG)Process->VdmAllowed; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Get the exception code */ + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; break; case ProcessWow64Information: + + /* Set 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; + + /* Make sure the process isn't dying */ + if (ExAcquireRundownProtection(&Process->RundownProtect)) + { + /* Get the WOW64 process structure */ +#ifdef _WIN64 + Wow64 = Process->Wow64Process; +#else + Wow64 = 0; +#endif + /* Release the lock */ + ExReleaseRundownProtection(&Process->RundownProtect); + } + + /* Protect write with SEH */ + _SEH2_TRY + { + /* Return whether or not we have a debug port */ + *(PULONG_PTR)ProcessInformation = Wow64; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Get exception code */ + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + /* Dereference the process */ + ObDereferenceObject(Process); + break; + + case ProcessExecuteFlags: + + /* Set return length */ + Length = sizeof(ULONG); + if (ProcessInformationLength != Length) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + + if (ProcessHandle != NtCurrentProcess()) + { + return STATUS_INVALID_PARAMETER; + } + + /* Get the options */ + Status = MmGetExecuteOptions(&ExecuteOptions); + if (NT_SUCCESS(Status)) + { + /* Protect write with SEH */ + _SEH2_TRY + { + /* Return them */ + *(PULONG)ProcessInformation = ExecuteOptions; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Get exception code */ + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + } + break; + case ProcessLdtInformation: - case ProcessWx86Information: - DPRINT1("VDM/16-bit implemented: %lx\n", ProcessInformationClass); + DPRINT1("VDM/16-bit not implemented: %lx\n", ProcessInformationClass); Status = STATUS_NOT_IMPLEMENTED; break; @@ -892,7 +1033,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, _SEH2_TRY { /* Check if caller wanted return length */ - if (ReturnLength) *ReturnLength = Length; + if ((ReturnLength) && (Length)) *ReturnLength = Length; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -928,7 +1069,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, KAFFINITY ValidAffinity, Affinity = 0; ULONG DefaultHardErrorMode = 0, BasePriority = 0, MemoryPriority = 0; ULONG DisableBoost = 0, DebugFlags = 0, EnableFixup = 0, Boost = 0; - ULONG NoExecute = 0; + ULONG NoExecute = 0, VdmPower = 0; BOOLEAN HasPrivilege; PLIST_ENTRY Next; PETHREAD Thread; @@ -970,6 +1111,49 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, /* Check what kind of information class this is */ switch (ProcessInformationClass) { + case ProcessWx86Information: + + /* Check buffer length */ + if (ProcessInformationLength != sizeof(HANDLE)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + + /* Use SEH for capture */ + _SEH2_TRY + { + /* Capture the boolean */ + VdmPower = *(PULONG)ProcessInformation; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Get the exception code */ + Status = _SEH2_GetExceptionCode(); + _SEH2_YIELD(break); + } + _SEH2_END; + + /* Getting VDM powers requires the SeTcbPrivilege */ + if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode)) + { + /* Bail out */ + Status = STATUS_PRIVILEGE_NOT_HELD; + DPRINT1("Need TCB privilege\n"); + break; + } + + /* Set or clear the flag */ + if (VdmPower) + { + PspSetProcessFlag(Process, PSF_VDM_ALLOWED_BIT); + } + else + { + PspClearProcessFlag(Process, PSF_VDM_ALLOWED_BIT); + } + break; + /* Error/Exception Port */ case ProcessExceptionPort: @@ -1670,7 +1854,6 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, case ProcessLdtInformation: case ProcessLdtSize: case ProcessIoPortHandlers: - case ProcessWx86Information: DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass); Status = STATUS_NOT_IMPLEMENTED; break;