[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / ps / query.c
index 235efb5..d27ff3e 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,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,13 +123,23 @@ 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 */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Write all the information from the EPROCESS/KPROCESS */
                 ProcessBasicInfo->ExitStatus = Process->ExitStatus;
@@ -139,26 +152,119 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
                 ProcessBasicInfo->BasePriority = Process->Pcb.BasePriority;
 
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _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,14 +273,23 @@ 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 */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Copy time information from EPROCESS/KPROCESS */
                 ProcessTime->CreateTime = Process->CreateTime;
@@ -184,39 +299,74 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
                                                    100000LL;
                 ProcessTime->ExitTime = Process->ExitTime;
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _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 */
-            _SEH_TRY
+            _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);
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _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,51 +375,104 @@ 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 */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Return the count of handles */
                 *(PULONG)ProcessInformation = HandleCount;
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _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 */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Write back the Session ID */
                 SessionInfo->SessionId = Process->Session;
-
-                /* Set the return length */
-                Length = sizeof(PROCESS_SESSION_INFORMATION);
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _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,14 +482,23 @@ 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 */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Return data from EPROCESS */
                 VmCounters->PeakVirtualSize = Process->PeakVirtualSize;
@@ -302,100 +514,185 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
                 VmCounters->PeakPagefileUsage = Process->QuotaPeak[2];
 
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _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 */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Write the current processing mode */
                 *(PULONG)ProcessInformation = Process->
                                               DefaultHardErrorProcessing;
-
-                /* Set the return length */
-                Length = sizeof(ULONG);
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _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 */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Return boost status */
                 *(PULONG)ProcessInformation = Process->Pcb.DisableBoost ?
-                                              FALSE : TRUE;
-
-                /* Set the return length */
-                Length = sizeof(ULONG);
+                                              TRUE : FALSE;
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _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);
 
             /* Enter SEH for writing back data */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 *(PPROCESS_DEVICEMAP_INFORMATION)ProcessInformation = DeviceMap;
-
-                /* Set the return length */
-                Length = sizeof(PROCESS_DEVICEMAP_INFORMATION);
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _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 */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Return current priority class */
-                *(PUSHORT)ProcessInformation = Process->PriorityClass;
-
-                /* Set the return length */
-                Length = sizeof(USHORT);
+                PsPriorityClass->PriorityClass = Process->PriorityClass;
+                PsPriorityClass->Foreground = FALSE;
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _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))
@@ -408,7 +705,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
                 if (Length <= ProcessInformationLength)
                 {
                     /* Enter SEH to protect write */
-                    _SEH_TRY
+                    _SEH2_TRY
                     {
                         /* Copy it */
                         RtlCopyMemory(ProcessInformation,
@@ -419,12 +716,12 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
                         ((PUNICODE_STRING)ProcessInformation)->Buffer =
                             (PWSTR)((PUNICODE_STRING)ProcessInformation + 1);
                    }
-                    _SEH_HANDLE
+                    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
                     {
                         /* Get the exception code */
-                        Status = _SEH_GetExceptionCode();
+                        Status = _SEH2_GetExceptionCode();
                     }
-                    _SEH_END;
+                    _SEH2_END;
                 }
                 else
                 {
@@ -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,18 +801,21 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
                 Length = sizeof(ULONG);
             }
 
+            /* Indicate success */
+            Status = STATUS_SUCCESS;
+
             /* Enter SEH to protect write */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Write back the cookie */
                 *(PULONG)ProcessInformation = Cookie;
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _SEH2_END;
             break;
 
         /* Not yet implemented, or unknown */
@@ -491,24 +830,23 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
         case ProcessAffinityMask:
         case ProcessForegroundInformation:
         default:
+            DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass);
             Status = STATUS_INVALID_INFO_CLASS;
     }
 
     /* Protect write with SEH */
-    _SEH_TRY
+    _SEH2_TRY
     {
         /* Check if caller wanted return length */
         if (ReturnLength) *ReturnLength = Length;
     }
-    _SEH_HANDLE
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
         /* Get exception code */
-        Status = _SEH_GetExceptionCode();
+        Status = _SEH2_GetExceptionCode();
     }
-    _SEH_END;
+    _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,28 +907,29 @@ 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 */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Capture the handle */
                 PortHandle = *(PHANDLE)ProcessInformation;
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _SEH2_END;
+
             if (!NT_SUCCESS(Status)) break;
 
             /* Get the LPC Port */
@@ -615,19 +955,27 @@ 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 */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Save the token handle */
                 TokenHandle = ((PPROCESS_ACCESS_TOKEN)ProcessInformation)->
                                Token;
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _SEH2_END;
+
             if (!NT_SUCCESS(Status)) break;
 
             /* Assign the actual token */
@@ -637,36 +985,51 @@ 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 */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Update the current mode abd return the previous one */
                 InterlockedExchange((LONG*)&Process->DefaultHardErrorProcessing,
                                     *(PLONG)ProcessInformation);
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _SEH2_END;
             break;
 
         /* Session ID */
         case ProcessSessionInformation:
 
+            /* Check buffer length */
+            if (ProcessInformationLength != sizeof(PROCESS_SESSION_INFORMATION))
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
             /* Enter SEH for capture */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Capture the caller's buffer */
                 SessionInfo = *(PPROCESS_SESSION_INFORMATION)ProcessInformation;
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _SEH2_END;
+
             if (!NT_SUCCESS(Status)) break;
 
             /* Setting the session id requires the SeTcbPrivilege */
@@ -694,17 +1057,17 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
                 KeAttachProcess(&Process->Pcb);
 
                 /* Enter SEH for write to user-mode PEB */
-                _SEH_TRY
+                _SEH2_TRY
                 {
                     /* Write the session ID */
                     Process->Peb->SessionId = SessionInfo.SessionId;
                 }
-                _SEH_HANDLE
+                _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
                 {
                     /* Get exception code */
-                    Status = _SEH_GetExceptionCode();
+                    Status = _SEH2_GetExceptionCode();
                 }
-                _SEH_END;
+                _SEH2_END;
 
                 /* Detach from the process */
                 KeDetachProcess();
@@ -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,18 +1311,26 @@ 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 */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Get the priority */
                 Priority = *(PLONG)ThreadInformation;
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _SEH2_END;
+
             if (!NT_SUCCESS(Status)) break;
 
             /* Validate it */
@@ -837,18 +1348,26 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
 
         case ThreadBasePriority:
 
+            /* Check buffer length */
+            if (ThreadInformationLength != sizeof(LONG))
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
             /* Use SEH for capture */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Get the priority */
                 Priority = *(PLONG)ThreadInformation;
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _SEH2_END;
+
             if (!NT_SUCCESS(Status)) break;
 
             /* Validate it */
@@ -876,19 +1395,25 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
 
         case ThreadAffinityMask:
 
+            /* Check buffer length */
+            if (ThreadInformationLength != sizeof(ULONG_PTR))
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
             /* Use SEH for capture */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Get the priority */
                 Affinity = *(PULONG_PTR)ThreadInformation;
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
-            if (!NT_SUCCESS(Status)) break;
+            _SEH2_END;
 
             /* Validate it */
             if (!Affinity)
@@ -937,18 +1462,26 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
 
         case ThreadImpersonationToken:
 
+            /* Check buffer length */
+            if (ThreadInformationLength != sizeof(HANDLE))
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
             /* Use SEH for capture */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Save the token handle */
                 TokenHandle = *(PHANDLE)ThreadInformation;
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _SEH2_END;
+
             if (!NT_SUCCESS(Status)) break;
 
             /* Assign the actual token */
@@ -957,18 +1490,26 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
 
         case ThreadQuerySetWin32StartAddress:
 
+            /* Check buffer length */
+            if (ThreadInformationLength != sizeof(ULONG_PTR))
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
             /* Use SEH for capture */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Get the priority */
                 Address = *(PVOID*)ThreadInformation;
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _SEH2_END;
+
             if (!NT_SUCCESS(Status)) break;
 
             /* Set the address */
@@ -977,18 +1518,26 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
 
         case ThreadIdealProcessor:
 
+            /* Check buffer length */
+            if (ThreadInformationLength != sizeof(ULONG_PTR))
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
             /* Use SEH for capture */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Get the priority */
                 IdealProcessor = *(PULONG_PTR)ThreadInformation;
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _SEH2_END;
+
             if (!NT_SUCCESS(Status)) break;
 
             /* Validate it */
@@ -1018,18 +1567,26 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
 
         case ThreadPriorityBoost:
 
+            /* Check buffer length */
+            if (ThreadInformationLength != sizeof(ULONG_PTR))
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
             /* Use SEH for capture */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Get the priority */
                 DisableBoost = *(PULONG_PTR)ThreadInformation;
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _SEH2_END;
+
             if (!NT_SUCCESS(Status)) break;
 
             /* Call the kernel */
@@ -1038,18 +1595,26 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
 
         case ThreadZeroTlsCell:
 
+            /* Check buffer length */
+            if (ThreadInformationLength != sizeof(ULONG_PTR))
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
             /* Use SEH for capture */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Get the priority */
                 TlsIndex = *(PULONG_PTR)ThreadInformation;
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get the exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _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,8 +1745,16 @@ 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 */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Write all the information from the ETHREAD/KTHREAD */
                 ThreadBasicInfo->ExitStatus = Thread->ExitStatus;
@@ -1180,23 +1763,28 @@ 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);
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _SEH2_END;
             break;
 
         /* 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 */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Copy time information from ETHREAD/KTHREAD */
                 ThreadTime->KernelTime.QuadPart = Thread->Tcb.KernelTime *
@@ -1205,60 +1793,75 @@ NtQueryInformationThread(IN HANDLE ThreadHandle,
                                                  100000LL;
                 ThreadTime->CreateTime = Thread->CreateTime;
                 ThreadTime->ExitTime = Thread->ExitTime;
-
-                /* Set the return length */
-                Length = sizeof(KERNEL_USER_TIMES);
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _SEH2_END;
             break;
 
         case ThreadQuerySetWin32StartAddress:
 
+            /* Set the return length*/
+            Length = sizeof(PVOID);
+
+            if (ThreadInformationLength != Length)
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
             /* Protect write with SEH */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Return the Win32 Start Address */
                 *(PVOID*)ThreadInformation = Thread->Win32StartAddress;
-
-                /* Set the return length*/
-                Length = sizeof(PVOID);
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _SEH2_END;
             break;
 
         case ThreadPerformanceCount:
 
+            /* Set the return length*/
+            Length = sizeof(LARGE_INTEGER);
+
+            if (ThreadInformationLength != Length)
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
             /* Protect write with SEH */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* FIXME */
                 (*(PLARGE_INTEGER)ThreadInformation).QuadPart = 0;
-
-                /* Set the return length*/
-                Length = sizeof(LARGE_INTEGER);
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _SEH2_END;
             break;
 
         case ThreadAmILastThread:
 
+            /* Set the return length*/
+            Length = sizeof(ULONG);
+
+            if (ThreadInformationLength != Length)
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
             /* Protect write with SEH */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Return whether or not we are the last thread */
                 *(PULONG)ThreadInformation = ((Thread->ThreadsProcess->
@@ -1266,43 +1869,82 @@ NtQueryInformationThread(IN HANDLE ThreadHandle,
                                                &Thread->ThreadsProcess->
                                                ThreadListHead) ?
                                               TRUE : FALSE);
-
-                /* Set the return length*/
-                Length = sizeof(ULONG);
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _SEH2_END;
             break;
 
         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);
 
             /* Protect write with SEH */
-            _SEH_TRY
+            _SEH2_TRY
             {
                 /* Check if the IRP list is empty or not */
                 *(PULONG)ThreadInformation = !IsListEmpty(&Thread->IrpList);
-
-                /* Set the return length*/
-                Length = sizeof(ULONG);
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
                 /* Get exception code */
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _SEH2_END;
 
             /* Lower IRQL back */
             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:
 
@@ -1312,17 +1954,17 @@ NtQueryInformationThread(IN HANDLE ThreadHandle,
     }
 
     /* Protect write with SEH */
-    _SEH_TRY
+    _SEH2_TRY
     {
         /* Check if caller wanted return length */
         if (ReturnLength) *ReturnLength = Length;
     }
-    _SEH_HANDLE
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
         /* Get exception code */
-        Status = _SEH_GetExceptionCode();
+        Status = _SEH2_GetExceptionCode();
     }
-    _SEH_END;
+    _SEH2_END;
 
     /* Dereference the thread, and return */
     ObDereferenceObject(Thread);