[NTOSKRNL]: Implement ProcessDebugObjectHandle and a bunch more query/set process...
authorAlex Ionescu <aionescu@gmail.com>
Mon, 20 Feb 2012 06:42:02 +0000 (06:42 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Mon, 20 Feb 2012 06:42:02 +0000 (06:42 +0000)
[NTOSKRNL]: We should not be setting *ReturnLength in most failure cases, so no longer do so. Fixes Winetests.

svn path=/trunk/; revision=55734

reactos/ntoskrnl/dbgk/dbgkobj.c
reactos/ntoskrnl/include/internal/dbgk.h
reactos/ntoskrnl/include/internal/mm.h
reactos/ntoskrnl/mm/ARM3/pagfault.c
reactos/ntoskrnl/ps/query.c

index 347a96d..f8446c3 100644 (file)
@@ -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 **********************************************************/
 
 /*
index d1e8f81..dfa22a3 100644 (file)
@@ -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;
 
index bfbc60a..156972e 100644 (file)
@@ -1507,6 +1507,10 @@ NTSTATUS
 NTAPI
 MmSetExecuteOptions(IN ULONG ExecuteOptions);
 
+NTSTATUS
+NTAPI
+MmGetExecuteOptions(IN PULONG ExecuteOptions);
+
 VOID
 NTAPI
 MmDeleteProcessPageDirectory(struct _EPROCESS *Process);
index 4d3fb90..478725b 100644 (file)
@@ -1096,9 +1096,50 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
 
 NTSTATUS
 NTAPI
-MmSetExecuteOptions(IN ULONG ExecuteOptions)
+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;
index f4fd894..9d308b4 100644 (file)
@@ -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;