[NTOS]: Fix Implementation of BreakOnTermination -- Process Flags should be accessed...
[reactos.git] / reactos / ntoskrnl / ps / query.c
index 0eeb748..342c818 100644 (file)
@@ -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,7 +64,7 @@ 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;
@@ -86,18 +87,20 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
         /* 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)
         {
-            /* Get the error code */
-            Status = _SEH2_GetExceptionCode();
+            /* Return the exception code */
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
         }
         _SEH2_END;
-        if(!NT_SUCCESS(Status)) return Status;
     }
 
     if((ProcessInformationClass == ProcessCookie) &&
@@ -145,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;
 
             }
@@ -191,8 +194,8 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
                         Process->Vm.MinimumWorkingSetSize << PAGE_SHIFT;
 
                 /* Set default time limits */
-                QuotaLimits->TimeLimit.LowPart = (ULONG)-1;
-                QuotaLimits->TimeLimit.HighPart = (ULONG)-1;
+                QuotaLimits->TimeLimit.LowPart = MAXULONG;
+                QuotaLimits->TimeLimit.HighPart = MAXULONG;
 
                 /* Is quota block a default one? */
                 if (Process->QuotaBlock == &PspDefaultQuotaBlock)
@@ -432,7 +435,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
             _SEH2_TRY
             {
                 /* Write back the Session ID */
-                SessionInfo->SessionId = PtrToUlong(Process->Session);
+                SessionInfo->SessionId = Process->Session;
             }
             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
@@ -733,6 +736,42 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
             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 */
         case ProcessCookie:
 
@@ -761,6 +800,9 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
                 Length = sizeof(ULONG);
             }
 
+            /* Indicate success */
+            Status = STATUS_SUCCESS;
+
             /* Enter SEH to protect write */
             _SEH2_TRY
             {
@@ -826,6 +868,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
     PROCESS_SESSION_INFORMATION SessionInfo = {0};
     PROCESS_PRIORITY_CLASS PriorityClass = {0};
     PVOID ExceptionPort;
+    ULONG Break;
     PAGED_CODE();
 
     /* Verify Information Class validity */
@@ -884,9 +927,9 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
             {
                 /* Get the exception code */
                 Status = _SEH2_GetExceptionCode();
+                _SEH2_YIELD(break);
             }
             _SEH2_END;
-            if (!NT_SUCCESS(Status)) break;
 
             /* Get the LPC Port */
             Status = ObReferenceObjectByHandle(PortHandle,
@@ -929,9 +972,9 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
             {
                 /* Get the exception code */
                 Status = _SEH2_GetExceptionCode();
+                _SEH2_YIELD(break);
             }
             _SEH2_END;
-            if (!NT_SUCCESS(Status)) break;
 
             /* Assign the actual token */
             Status = PspSetPrimaryToken(Process, TokenHandle, NULL);
@@ -982,9 +1025,9 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
             {
                 /* Get the exception code */
                 Status = _SEH2_GetExceptionCode();
+                _SEH2_YIELD(break);
             }
             _SEH2_END;
-            if (!NT_SUCCESS(Status)) break;
 
             /* Setting the session id requires the SeTcbPrivilege */
             if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
@@ -1048,11 +1091,11 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
             }
             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
-                /* Get the exception code */
+                /* Return the exception code */
                 Status = _SEH2_GetExceptionCode();
+                _SEH2_YIELD(break);
             }
             _SEH2_END;
-            if (!NT_SUCCESS(Status)) break;
 
             /* Check for invalid PriorityClass value */
             if (PriorityClass.PriorityClass > PROCESS_PRIORITY_CLASS_ABOVE_NORMAL)
@@ -1145,6 +1188,48 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
             Status = STATUS_NOT_IMPLEMENTED;
             break;
 
+        case ProcessBreakOnTermination:
+
+            /* Check buffer length */
+            if (ProcessInformationLength != sizeof(ULONG))
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
+            /* Enter SEH for direct buffer read */
+            _SEH2_TRY
+            {
+                Break = *(PULONG)ProcessInformation;
+            }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                /* Get exception code */
+                Break = 0;
+                Status = _SEH2_GetExceptionCode();
+                _SEH2_YIELD(break);
+            }
+            _SEH2_END;
+            
+            /* Setting 'break on termination' requires the SeDebugPrivilege */
+            if (!SeSinglePrivilegeCheck(SeDebugPrivilege, PreviousMode))
+            {
+                Status = STATUS_PRIVILEGE_NOT_HELD;
+                break;
+            }
+            
+            /* Set or clear the flag */
+            if (Break)
+            {
+                PspSetProcessFlag(Process, PSF_BREAK_ON_TERMINATION_BIT);
+            }
+            else
+            {
+                PspClearProcessFlag(Process, PSF_BREAK_ON_TERMINATION_BIT);
+            }
+
+            break;
+
         /* We currently don't implement any of these */
         case ProcessLdtInformation:
         case ProcessLdtSize:
@@ -1220,7 +1305,7 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
         Access = THREAD_SET_THREAD_TOKEN;
     }
 
-    /* Reference the process */
+    /* Reference the thread */
     Status = ObReferenceObjectByHandle(ThreadHandle,
                                        Access,
                                        PsThreadType,
@@ -1252,9 +1337,9 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
             {
                 /* Get the exception code */
                 Status = _SEH2_GetExceptionCode();
+                _SEH2_YIELD(break);
             }
             _SEH2_END;
-            if (!NT_SUCCESS(Status)) break;
 
             /* Validate it */
             if ((Priority > HIGH_PRIORITY) ||
@@ -1288,9 +1373,9 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
             {
                 /* Get the exception code */
                 Status = _SEH2_GetExceptionCode();
+                _SEH2_YIELD(break);
             }
             _SEH2_END;
-            if (!NT_SUCCESS(Status)) break;
 
             /* Validate it */
             if ((Priority > THREAD_BASE_PRIORITY_MAX) ||
@@ -1336,7 +1421,6 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
                 Status = _SEH2_GetExceptionCode();
             }
             _SEH2_END;
-            if (!NT_SUCCESS(Status)) break;
 
             /* Validate it */
             if (!Affinity)
@@ -1402,9 +1486,9 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
             {
                 /* Get the exception code */
                 Status = _SEH2_GetExceptionCode();
+                _SEH2_YIELD(break);
             }
             _SEH2_END;
-            if (!NT_SUCCESS(Status)) break;
 
             /* Assign the actual token */
             Status = PsAssignImpersonationToken(Thread, TokenHandle);
@@ -1429,9 +1513,9 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
             {
                 /* Get the exception code */
                 Status = _SEH2_GetExceptionCode();
+                _SEH2_YIELD(break);
             }
             _SEH2_END;
-            if (!NT_SUCCESS(Status)) break;
 
             /* Set the address */
             Thread->Win32StartAddress = Address;
@@ -1456,9 +1540,9 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
             {
                 /* Get the exception code */
                 Status = _SEH2_GetExceptionCode();
+                _SEH2_YIELD(break);
             }
             _SEH2_END;
-            if (!NT_SUCCESS(Status)) break;
 
             /* Validate it */
             if (IdealProcessor > MAXIMUM_PROCESSORS)
@@ -1504,9 +1588,9 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
             {
                 /* Get the exception code */
                 Status = _SEH2_GetExceptionCode();
+                _SEH2_YIELD(break);
             }
             _SEH2_END;
-            if (!NT_SUCCESS(Status)) break;
 
             /* Call the kernel */
             KeSetDisableBoostThread(&Thread->Tcb, (BOOLEAN)DisableBoost);
@@ -1531,9 +1615,9 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
             {
                 /* Get the exception code */
                 Status = _SEH2_GetExceptionCode();
+                _SEH2_YIELD(break);
             }
             _SEH2_END;
-            if (!NT_SUCCESS(Status)) break;
 
             /* This is only valid for the current thread */
             if (Thread != PsGetCurrentThread())
@@ -1614,7 +1698,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 =
@@ -1623,26 +1707,26 @@ NtQueryInformationThread(IN HANDLE ThreadHandle,
     KIRQL OldIrql;
     PAGED_CODE();
 
+    /* Check if we were called from user mode */
     if (PreviousMode != KernelMode)
     {
+        /* Enter SEH */
         _SEH2_TRY
         {
+            /* Probe the buffer */
             ProbeForWrite(ThreadInformation,
                           ThreadInformationLength,
                           sizeof(ULONG));
 
-            if (ReturnLength)
-            {
-                ProbeForWriteUlong(ReturnLength);
-            }
+            /* Probe the return length if required */
+            if (ReturnLength) ProbeForWriteUlong(ReturnLength);
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
-            Status = _SEH2_GetExceptionCode();
+            /* Return the exception code */
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
         }
         _SEH2_END;
-
-        if (!NT_SUCCESS(Status)) return Status;
     }
 
     /* Check what class this is */
@@ -1826,9 +1910,19 @@ NtQueryInformationThread(IN HANDLE ThreadHandle,
             KeLowerIrql(OldIrql);
             break;
 
+        /* LDT and GDT information */
         case ThreadDescriptorTableEntry:
-            DPRINT1("NtQueryInformationThread(): case ThreadDescriptorTableEntry not implemented!\n");
+
+#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: