[NTOSKRNL] Add a raw implementation of !irpfind in kdbg
[reactos.git] / ntoskrnl / ps / query.c
index 15ec912..1f605be 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
-/* FIXME: From winbase.h... what to do? */
-#define SEM_NOALIGNMENTFAULTEXCEPT 0x04
-
-/* Include Information Class Tables */
-#include "internal/ps_i.h"
-
 /* Debugging Level */
 ULONG PspTraceLevel = 0;
 
@@ -34,7 +28,10 @@ PsReferenceProcessFilePointer(IN PEPROCESS Process,
     PAGED_CODE();
 
     /* Lock the process */
-    ExAcquireRundownProtection(&Process->RundownProtect);
+    if (!ExAcquireRundownProtection(&Process->RundownProtect))
+    {
+        return STATUS_PROCESS_IS_TERMINATING;
+    }
 
     /* Get the section */
     Section = Process->SectionObject;
@@ -69,9 +66,11 @@ 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;
+    ULONG UserTime, KernelTime;
     PPROCESS_PRIORITY_CLASS PsPriorityClass = (PPROCESS_PRIORITY_CLASS)ProcessInformation;
     ULONG HandleCount;
     PPROCESS_SESSION_INFORMATION SessionInfo =
@@ -81,7 +80,9 @@ 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;
+    PROCESS_VALUES ProcessValues;
     PAGED_CODE();
 
     /* Check for user-mode caller */
@@ -91,9 +92,9 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
         _SEH2_TRY
         {
             /* Probe the buffer */
-            ProbeForWrite(ProcessInformation,
-                          ProcessInformationLength,
-                          sizeof(ULONG));
+            ProbeForRead(ProcessInformation,
+                         ProcessInformationLength,
+                         sizeof(ULONG));
 
             /* Probe the return length if required */
             if (ReturnLength) ProbeForWriteUlong(ReturnLength);
@@ -106,12 +107,13 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
         _SEH2_END;
     }
 
-    if((ProcessInformationClass == ProcessCookie) &&
+    if (((ProcessInformationClass == ProcessCookie) ||
+         (ProcessInformationClass == ProcessImageInformation)) &&
         (ProcessHandle != NtCurrentProcess()))
     {
         /*
-         * Retreiving the process cookie is only allowed for the calling process
-         * itself! XP only allowes NtCurrentProcess() as process handles even if
+         * Retrieving the process cookie is only allowed for the calling process
+         * itself! XP only allows NtCurrentProcess() as process handles even if
          * a real handle actually represents the current process.
          */
         return STATUS_INVALID_PARAMETER;
@@ -123,15 +125,15 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
         /* Basic process information */
         case ProcessBasicInformation:
 
-            /* Set return length */
-            Length = sizeof(PROCESS_BASIC_INFORMATION);
-
-            if (ProcessInformationLength != Length)
+            if (ProcessInformationLength != sizeof(PROCESS_BASIC_INFORMATION))
             {
                 Status = STATUS_INFO_LENGTH_MISMATCH;
                 break;
             }
 
+            /* Set return length */
+            Length = sizeof(PROCESS_BASIC_INFORMATION);
+
             /* Reference the process */
             Status = ObReferenceObjectByHandle(ProcessHandle,
                                                PROCESS_QUERY_INFORMATION,
@@ -151,7 +153,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
                 ProcessBasicInfo->UniqueProcessId = (ULONG_PTR)Process->
                                                     UniqueProcessId;
                 ProcessBasicInfo->InheritedFromUniqueProcessId =
-                    (ULONG)Process->InheritedFromUniqueProcessId;
+                    (ULONG_PTR)Process->InheritedFromUniqueProcessId;
                 ProcessBasicInfo->BasePriority = Process->Pcb.BasePriority;
 
             }
@@ -169,13 +171,14 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
         /* Process quota limits */
         case ProcessQuotaLimits:
 
-            Length = sizeof(QUOTA_LIMITS);
-            if (ProcessInformationLength != Length)
+            if (ProcessInformationLength != sizeof(QUOTA_LIMITS))
             {
                 Status = STATUS_INFO_LENGTH_MISMATCH;
                 break;
             }
 
+            Length = sizeof(QUOTA_LIMITS);
+
             /* Reference the process */
             Status = ObReferenceObjectByHandle(ProcessHandle,
                                                PROCESS_QUERY_INFORMATION,
@@ -232,13 +235,14 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
 
         case ProcessIoCounters:
 
-            Length = sizeof(IO_COUNTERS);
-            if (ProcessInformationLength != Length)
+            if (ProcessInformationLength != sizeof(IO_COUNTERS))
             {
                 Status = STATUS_INFO_LENGTH_MISMATCH;
                 break;
             }
 
+            Length = sizeof(IO_COUNTERS);
+
             /* Reference the process */
             Status = ObReferenceObjectByHandle(ProcessHandle,
                                                PROCESS_QUERY_INFORMATION,
@@ -248,15 +252,12 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
                                                NULL);
             if (!NT_SUCCESS(Status)) break;
 
+            /* Query IO counters from the process */
+            KeQueryValuesProcess(&Process->Pcb, &ProcessValues);
+
             _SEH2_TRY
             {
-                /* FIXME: Call KeQueryValuesProcess */
-                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;
+                RtlCopyMemory(IoCounters, &ProcessValues.IoInfo, sizeof(IO_COUNTERS));
             }
             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
@@ -275,14 +276,14 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
         case ProcessTimes:
 
             /* Set the return length */
-            Length = sizeof(KERNEL_USER_TIMES);
-
-            if (ProcessInformationLength != Length)
+            if (ProcessInformationLength != sizeof(KERNEL_USER_TIMES))
             {
                 Status = STATUS_INFO_LENGTH_MISMATCH;
                 break;
             }
 
+            Length = sizeof(KERNEL_USER_TIMES);
+
             /* Reference the process */
             Status = ObReferenceObjectByHandle(ProcessHandle,
                                                PROCESS_QUERY_INFORMATION,
@@ -296,12 +297,10 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
             _SEH2_TRY
             {
                 /* Copy time information from EPROCESS/KPROCESS */
-                /* FIXME: Call KeQueryRuntimeProcess */
+                KernelTime = KeQueryRuntimeProcess(&Process->Pcb, &UserTime);
                 ProcessTime->CreateTime = Process->CreateTime;
-                ProcessTime->UserTime.QuadPart = Process->Pcb.UserTime *
-                                                 KeMaximumIncrement;
-                ProcessTime->KernelTime.QuadPart = Process->Pcb.KernelTime *
-                                                   KeMaximumIncrement;
+                ProcessTime->UserTime.QuadPart = (LONGLONG)UserTime * KeMaximumIncrement;
+                ProcessTime->KernelTime.QuadPart = (LONGLONG)KernelTime * KeMaximumIncrement;
                 ProcessTime->ExitTime = Process->ExitTime;
             }
             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@@ -318,15 +317,15 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
         /* Process Debug Port */
         case ProcessDebugPort:
 
-            /* Set return length */
-            Length = sizeof(HANDLE);
-
-            if (ProcessInformationLength != Length)
+            if (ProcessInformationLength != sizeof(HANDLE))
             {
                 Status = STATUS_INFO_LENGTH_MISMATCH;
                 break;
             }
 
+            /* Set return length */
+            Length = sizeof(HANDLE);
+
             /* Reference the process */
             Status = ObReferenceObjectByHandle(ProcessHandle,
                                                PROCESS_QUERY_INFORMATION,
@@ -356,15 +355,15 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
 
         case ProcessHandleCount:
 
-            /* Set the return length*/
-            Length = sizeof(ULONG);
-
-            if (ProcessInformationLength != Length)
+            if (ProcessInformationLength != sizeof(ULONG))
             {
                 Status = STATUS_INFO_LENGTH_MISMATCH;
                 break;
             }
 
+            /* Set the return length*/
+            Length = sizeof(ULONG);
+
             /* Reference the process */
             Status = ObReferenceObjectByHandle(ProcessHandle,
                                                PROCESS_QUERY_INFORMATION,
@@ -397,15 +396,15 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
         /* Session ID for the process */
         case ProcessSessionInformation:
 
-            /* Set the return length*/
-            Length = sizeof(PROCESS_SESSION_INFORMATION);
-
-            if (ProcessInformationLength != Length)
+            if (ProcessInformationLength != sizeof(PROCESS_SESSION_INFORMATION))
             {
                 Status = STATUS_INFO_LENGTH_MISMATCH;
                 break;
             }
 
+            /* Set the return length*/
+            Length = sizeof(PROCESS_SESSION_INFORMATION);
+
             /* Reference the process */
             Status = ObReferenceObjectByHandle(ProcessHandle,
                                                PROCESS_QUERY_INFORMATION,
@@ -419,7 +418,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
             _SEH2_TRY
             {
                 /* Write back the Session ID */
-                SessionInfo->SessionId = Process->Session; //MmGetSessionId(Process);
+                SessionInfo->SessionId = PsGetProcessSessionId(Process);
             }
             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
@@ -443,9 +442,6 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
                 break;
             }
 
-            /* Set the return length */
-            Length = ProcessInformationLength;
-
             /* Reference the process */
             Status = ObReferenceObjectByHandle(ProcessHandle,
                                                PROCESS_QUERY_INFORMATION,
@@ -471,6 +467,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)
             {
@@ -486,15 +486,15 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
         /* Hard Error Processing Mode */
         case ProcessDefaultHardErrorMode:
 
-            /* Set the return length*/
-            Length = sizeof(ULONG);
-
-            if (ProcessInformationLength != Length)
+            if (ProcessInformationLength != sizeof(ULONG))
             {
                 Status = STATUS_INFO_LENGTH_MISMATCH;
                 break;
             }
 
+            /* Set the return length*/
+            Length = sizeof(ULONG);
+
             /* Reference the process */
             Status = ObReferenceObjectByHandle(ProcessHandle,
                                                PROCESS_QUERY_INFORMATION,
@@ -525,15 +525,15 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
         /* Priority Boosting status */
         case ProcessPriorityBoost:
 
-            /* Set the return length */
-            Length = sizeof(ULONG);
-
-            if (ProcessInformationLength != Length)
+            if (ProcessInformationLength != sizeof(ULONG))
             {
                 Status = STATUS_INFO_LENGTH_MISMATCH;
                 break;
             }
 
+            /* Set the return length */
+            Length = sizeof(ULONG);
+
             /* Reference the process */
             Status = ObReferenceObjectByHandle(ProcessHandle,
                                                PROCESS_QUERY_INFORMATION,
@@ -564,10 +564,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
         /* DOS Device Map */
         case ProcessDeviceMap:
 
-            /* Set the return length */
-            Length = sizeof(PROCESS_DEVICEMAP_INFORMATION);
-
-            if (ProcessInformationLength != Length)
+            if (ProcessInformationLength != RTL_FIELD_SIZE(PROCESS_DEVICEMAP_INFORMATION, Query))
             {
                 if (ProcessInformationLength == sizeof(PROCESS_DEVICEMAP_INFORMATION_EX))
                 {
@@ -581,6 +578,9 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
                 break;
             }
 
+            /* Set the return length */
+            Length = sizeof(PROCESS_DEVICEMAP_INFORMATION);
+
             /* Reference the process */
             Status = ObReferenceObjectByHandle(ProcessHandle,
                                                PROCESS_QUERY_INFORMATION,
@@ -612,15 +612,15 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
         /* Priority class */
         case ProcessPriorityClass:
 
-            /* Set the return length*/
-            Length = sizeof(PROCESS_PRIORITY_CLASS);
-
-            if (ProcessInformationLength != Length)
+            if (ProcessInformationLength != sizeof(PROCESS_PRIORITY_CLASS))
             {
                 Status = STATUS_INFO_LENGTH_MISMATCH;
                 break;
             }
 
+            /* Set the return length*/
+            Length = sizeof(PROCESS_PRIORITY_CLASS);
+
             /* Reference the process */
             Status = ObReferenceObjectByHandle(ProcessHandle,
                                                PROCESS_QUERY_INFORMATION,
@@ -696,7 +696,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
                 }
 
                 /* Free the image path */
-                ExFreePool(ImageName);
+                ExFreePoolWithTag(ImageName, TAG_SEPA);
             }
             /* Dereference the process */
             ObDereferenceObject(Process);
@@ -704,14 +704,15 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
 
         case ProcessDebugFlags:
 
-            /* Set the return length*/
-            Length = sizeof(ULONG);
-            if (ProcessInformationLength != Length)
+            if (ProcessInformationLength != sizeof(ULONG))
             {
                 Status = STATUS_INFO_LENGTH_MISMATCH;
                 break;
             }
 
+            /* Set the return length*/
+            Length = sizeof(ULONG);
+
             /* Reference the process */
             Status = ObReferenceObjectByHandle(ProcessHandle,
                                                PROCESS_QUERY_INFORMATION,
@@ -740,14 +741,15 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
 
         case ProcessBreakOnTermination:
 
-            /* Set the return length*/
-            Length = sizeof(ULONG);
-            if (ProcessInformationLength != Length)
+            if (ProcessInformationLength != sizeof(ULONG))
             {
                 Status = STATUS_INFO_LENGTH_MISMATCH;
                 break;
             }
 
+            /* Set the return length */
+            Length = sizeof(ULONG);
+
             /* Reference the process */
             Status = ObReferenceObjectByHandle(ProcessHandle,
                                                PROCESS_QUERY_INFORMATION,
@@ -818,36 +820,232 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
             }
             _SEH2_END;
             break;
-            
+
         case ProcessImageInformation:
-            DPRINT1("Image Information Query Not implemented: %lx\n", ProcessInformationClass);
-            Status = STATUS_NOT_IMPLEMENTED;
+
+            if (ProcessInformationLength != sizeof(SECTION_IMAGE_INFORMATION))
+            {
+                /* Break out */
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
+            /* Set the length required and validate it */
+            Length = sizeof(SECTION_IMAGE_INFORMATION);
+
+            /* Enter SEH to protect write */
+            _SEH2_TRY
+            {
+                MmGetImageInformation((PSECTION_IMAGE_INFORMATION)ProcessInformation);
+            }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                /* Get the exception code */
+                Status = _SEH2_GetExceptionCode();
+            }
+            _SEH2_END;
+
+            /* Indicate success */
+            Status = STATUS_SUCCESS;
             break;
-            
+
         case ProcessDebugObjectHandle:
-            DPRINT1("Debug Object Query Not implemented: %lx\n", ProcessInformationClass);
-            Status = STATUS_NOT_IMPLEMENTED;
+
+            if (ProcessInformationLength != sizeof(HANDLE))
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
+            /* Set the return length */
+            Length = sizeof(HANDLE);
+
+            /* 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 debug port's handle */
+                *(PHANDLE)ProcessInformation = DebugPort;
+            }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                /* Get the exception code */
+                Status = _SEH2_GetExceptionCode();
+            }
+            _SEH2_END;
             break;
-            
+
         case ProcessHandleTracing:
             DPRINT1("Handle tracing Not implemented: %lx\n", ProcessInformationClass);
             Status = STATUS_NOT_IMPLEMENTED;
             break;
-          
+
         case ProcessLUIDDeviceMapsEnabled:
-            DPRINT1("LUID Device Maps Not implemented: %lx\n", ProcessInformationClass);
-            Status = STATUS_NOT_IMPLEMENTED;
+
+            if (ProcessInformationLength != sizeof(ULONG))
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
+            /* Set the return length */
+            Length = sizeof(ULONG);
+
+            /* Indicate success */
+            Status = STATUS_SUCCESS;
+
+            /* Protect write in SEH */
+            _SEH2_TRY
+            {
+                /* Return FALSE -- we don't support this */
+                *(PULONG)ProcessInformation = FALSE;
+            }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                /* Get the exception code */
+                Status = _SEH2_GetExceptionCode();
+            }
+            _SEH2_END;
             break;
-        
-        case ProcessExecuteFlags:
-            DPRINT1("No execute Not implemented: %lx\n", ProcessInformationClass);
-            Status = STATUS_NOT_IMPLEMENTED;
+
+        case ProcessWx86Information:
+
+            if (ProcessInformationLength != sizeof(ULONG))
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
+            /* Set the return length */
+            Length = sizeof(ULONG);
+
+            /* Reference the process */
+            Status = ObReferenceObjectByHandle(ProcessHandle,
+                                               PROCESS_QUERY_INFORMATION,
+                                               PsProcessType,
+                                               PreviousMode,
+                                               (PVOID*)&Process,
+                                               NULL);
+            if (!NT_SUCCESS(Status)) break;
+
+            /* Protect write in SEH */
+            _SEH2_TRY
+            {
+                /* 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;
+
+            /* Dereference the process */
+            ObDereferenceObject(Process);
             break;
-        
+
         case ProcessWow64Information:
+
+            if (ProcessInformationLength != sizeof(ULONG_PTR))
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
+            /* Set return length */
+            Length = sizeof(ULONG_PTR);
+
+            /* 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 = (ULONG_PTR)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:
+
+            if (ProcessInformationLength != sizeof(ULONG))
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
+            /* Set return length */
+            Length = sizeof(ULONG);
+
+            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;
 
@@ -855,12 +1053,12 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
             DPRINT1("WS Watch Not implemented: %lx\n", ProcessInformationClass);
             Status = STATUS_NOT_IMPLEMENTED;
             break;
-            
+
         case ProcessPooledUsageAndLimits:
             DPRINT1("Pool limits Not implemented: %lx\n", ProcessInformationClass);
             Status = STATUS_NOT_IMPLEMENTED;
             break;
-        
+
         /* Not supported by Server 2003 */
         default:
             DPRINT1("Unsupported info class: %lx\n", ProcessInformationClass);
@@ -871,7 +1069,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)
     {
@@ -905,8 +1103,13 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
     PVOID ExceptionPort;
     ULONG Break;
     KAFFINITY ValidAffinity, Affinity = 0;
-    ULONG DefaultHardErrorMode = 0, BasePriority = 0, MemoryPriority = 0;
-    ULONG DisableBoost = 0, DebugFlags = 0, EnableFixup = 0, Boost = 0;
+    KPRIORITY BasePriority = 0;
+    UCHAR MemoryPriority = 0;
+    BOOLEAN DisableBoost = 0;
+    ULONG DefaultHardErrorMode = 0;
+    ULONG DebugFlags = 0, EnableFixup = 0, Boost = 0;
+    ULONG NoExecute = 0, VdmPower = 0;
+    BOOLEAN HasPrivilege;
     PLIST_ENTRY Next;
     PETHREAD Thread;
     PAGED_CODE();
@@ -947,6 +1150,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))
+            {
+                /* We don't hold the privilege, 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:
 
@@ -974,11 +1220,11 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
             /* Setting the error port requires the SeTcbPrivilege */
             if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
             {
-                /* Can't set the session ID, bail out. */
+                /* We don't hold the privilege, bail out */
                 Status = STATUS_PRIVILEGE_NOT_HELD;
                 break;
             }
-            
+
             /* Get the LPC Port */
             Status = ObReferenceObjectByHandle(PortHandle,
                                                0,
@@ -1050,10 +1296,10 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
                 _SEH2_YIELD(break);
             }
             _SEH2_END;
-            
+
             /* Set the mode */
             Process->DefaultHardErrorProcessing = DefaultHardErrorMode;
-            
+
             /* Call Ke for the update */
             if (DefaultHardErrorMode & SEM_NOALIGNMENTFAULTEXCEPT)
             {
@@ -1093,17 +1339,19 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
             /* Setting the session id requires the SeTcbPrivilege */
             if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
             {
-                /* Can't set the session ID, bail out. */
+                /* We don't hold the privilege, bail out */
                 Status = STATUS_PRIVILEGE_NOT_HELD;
                 break;
             }
 
+#if 0 // OLD AND DEPRECATED CODE!!!!
+
             /* FIXME - update the session id for the process token */
             //Status = PsLockProcess(Process, FALSE);
             if (!NT_SUCCESS(Status)) break;
 
             /* Write the session ID in the EPROCESS */
-            Process->Session = SessionInfo.SessionId;
+            Process->Session = UlongToPtr(SessionInfo.SessionId); // HACK!!!
 
             /* Check if the process also has a PEB */
             if (Process->Peb)
@@ -1133,6 +1381,27 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
 
             /* Unlock the process */
             //PsUnlockProcess(Process);
+
+#endif
+
+            /*
+             * Since we cannot change the session ID of the given
+             * process anymore because it is set once and for all
+             * at process creation time and because it is stored
+             * inside the Process->Session structure managed by MM,
+             * we fake changing it: we just return success if the
+             * user-defined value is the same as the session ID of
+             * the process, and otherwise we fail.
+             */
+            if (SessionInfo.SessionId == PsGetProcessSessionId(Process))
+            {
+                Status = STATUS_SUCCESS;
+            }
+            else
+            {
+                Status = STATUS_ACCESS_DENIED;
+            }
+
             break;
 
         case ProcessPriorityClass:
@@ -1168,8 +1437,17 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
             if ((PriorityClass.PriorityClass != Process->PriorityClass) &&
                 (PriorityClass.PriorityClass == PROCESS_PRIORITY_CLASS_REALTIME))
             {
-                /* TODO: Check privileges */
-                DPRINT1("Should check privilege\n");
+                /* Check the privilege */
+                HasPrivilege = SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege,
+                                                       ProcessHandle,
+                                                       PROCESS_SET_INFORMATION,
+                                                       PreviousMode);
+                if (!HasPrivilege)
+                {
+                    ObDereferenceObject(Process);
+                    DPRINT1("Privilege to change priority to realtime lacking\n");
+                    return STATUS_PRIVILEGE_NOT_HELD;
+                }
             }
 
             /* Check if we have a job */
@@ -1219,7 +1497,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
                                         PsProcessPriorityBackground);
             Status = STATUS_SUCCESS;
             break;
-                
+
         case ProcessBasePriority:
 
             /* Validate input length */
@@ -1232,7 +1510,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
             /* Enter SEH for direct buffer read */
             _SEH2_TRY
             {
-                BasePriority = *(PULONG)ProcessInformation;
+                BasePriority = *(KPRIORITY*)ProcessInformation;
             }
             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
@@ -1242,7 +1520,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
                 _SEH2_YIELD(break);
             }
             _SEH2_END;
-            
+
             /* Extract the memory priority out of there */
             if (BasePriority & 0x80000000)
             {
@@ -1253,22 +1531,32 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
             {
                 MemoryPriority = MEMORY_PRIORITY_BACKGROUND;
             }
-            
+
             /* Validate the number */
             if ((BasePriority > HIGH_PRIORITY) || (BasePriority <= LOW_PRIORITY))
             {
+                ObDereferenceObject(Process);
                 return STATUS_INVALID_PARAMETER;
             }
-            
+
             /* Check if the new base is higher */
             if (BasePriority > Process->Pcb.BasePriority)
             {
-                DPRINT1("Should check privilege\n");
+                HasPrivilege = SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege,
+                                                       ProcessHandle,
+                                                       PROCESS_SET_INFORMATION,
+                                                       PreviousMode);
+                if (!HasPrivilege)
+                {
+                    ObDereferenceObject(Process);
+                    DPRINT1("Privilege to change priority from %lx to %lx lacking\n", BasePriority, Process->Pcb.BasePriority);
+                    return STATUS_PRIVILEGE_NOT_HELD;
+                }
             }
-            
+
             /* Call Ke */
             KeSetPriorityAndQuantumProcess(&Process->Pcb, BasePriority, 0);
-            
+
             /* Now set the memory priority */
             MmSetMemoryPriorityProcess(Process, MemoryPriority);
             Status = STATUS_SUCCESS;
@@ -1351,14 +1639,15 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
                 _SEH2_YIELD(break);
             }
             _SEH2_END;
-            
+
             /* Setting 'break on termination' requires the SeDebugPrivilege */
             if (!SeSinglePrivilegeCheck(SeDebugPrivilege, PreviousMode))
             {
+                /* We don't hold the privilege, bail out */
                 Status = STATUS_PRIVILEGE_NOT_HELD;
                 break;
             }
-            
+
             /* Set or clear the flag */
             if (Break)
             {
@@ -1370,9 +1659,9 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
             }
 
             break;
-            
+
         case ProcessAffinityMask:
-        
+
             /* Check buffer length */
             if (ProcessInformationLength != sizeof(KAFFINITY))
             {
@@ -1393,7 +1682,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
                 _SEH2_YIELD(break);
             }
             _SEH2_END;
-        
+
             /* Make sure it's valid for the CPUs present */
             ValidAffinity = Affinity & KeActiveProcessors;
             if (!Affinity || (ValidAffinity != Affinity))
@@ -1435,7 +1724,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
                 Status = STATUS_PROCESS_IS_TERMINATING;
             }
             break;
-            
+
         /* Priority Boosting status */
         case ProcessPriorityBoost:
 
@@ -1449,7 +1738,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
             /* Enter SEH for direct buffer read */
             _SEH2_TRY
             {
-                DisableBoost = *(PULONG)ProcessInformation;
+                DisableBoost = *(PBOOLEAN)ProcessInformation;
             }
             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
@@ -1469,7 +1758,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
 
                 /* Call Ke to do the work */
                 KeSetDisableBoostProcess(&Process->Pcb, DisableBoost);
-                
+
                 /* Loop the threads too */
                 for (Next = Process->ThreadListHead.Flink;
                      Next != &Process->ThreadListHead;
@@ -1494,7 +1783,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
                 Status = STATUS_PROCESS_IS_TERMINATING;
             }
             break;
-            
+
         case ProcessDebugFlags:
 
             /* Check buffer length */
@@ -1516,7 +1805,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
                 _SEH2_YIELD(break);
             }
             _SEH2_END;
-            
+
             /* Set the mode */
             if (DebugFlags & ~1)
             {
@@ -1537,7 +1826,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
             /* Done */
             Status = STATUS_SUCCESS;
             break;
-            
+
         case ProcessEnableAlignmentFaultFixup:
 
             /* Check buffer length */
@@ -1559,7 +1848,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
                 _SEH2_YIELD(break);
             }
             _SEH2_END;
-            
+
             /* Set the mode */
             if (EnableFixup)
             {
@@ -1569,47 +1858,96 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
             {
                 Process->DefaultHardErrorProcessing &= ~SEM_NOALIGNMENTFAULTEXCEPT;
             }
-            
+
             /* Call Ke for the update */
             KeSetAutoAlignmentProcess(&Process->Pcb, FALSE);
             Status = STATUS_SUCCESS;
             break;
-            
+
+        case ProcessUserModeIOPL:
+
+            /* Only TCB can do this */
+            if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
+            {
+                /* We don't hold the privilege, bail out */
+                DPRINT1("Need TCB to set IOPL\n");
+                Status = STATUS_PRIVILEGE_NOT_HELD;
+                break;
+            }
+
+            /* Only supported on x86 */
+#if defined (_X86_)
+            Ke386SetIOPL();
+#else
+            Status = STATUS_NOT_IMPLEMENTED;
+#endif
+            /* Done */
+            break;
+
+        case ProcessExecuteFlags:
+
+            /* Check buffer length */
+            if (ProcessInformationLength != sizeof(ULONG))
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
+            if (ProcessHandle != NtCurrentProcess())
+            {
+                Status = STATUS_INVALID_PARAMETER;
+                break;
+            }
+
+            /* Enter SEH for direct buffer read */
+            _SEH2_TRY
+            {
+                NoExecute = *(PULONG)ProcessInformation;
+            }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                /* Get exception code */
+                Status = _SEH2_GetExceptionCode();
+                _SEH2_YIELD(break);
+            }
+            _SEH2_END;
+
+            /* Call Mm for the update */
+            Status = MmSetExecuteOptions(NoExecute);
+            break;
+
         /* We currently don't implement any of these */
         case ProcessLdtInformation:
         case ProcessLdtSize:
         case ProcessIoPortHandlers:
-        case ProcessUserModeIOPL:
-        case ProcessWx86Information:
              DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass);
              Status = STATUS_NOT_IMPLEMENTED;
              break;
-                
+
         case ProcessQuotaLimits:
-            DPRINT1("Quota Limits not implemented\n");
-            Status = STATUS_NOT_IMPLEMENTED;
+
+            Status = PspSetQuotaLimits(Process,
+                                     1,
+                                     ProcessInformation,
+                                     ProcessInformationLength,
+                                     PreviousMode);
             break;
-                
+
         case ProcessWorkingSetWatch:
             DPRINT1("WS watch not implemented\n");
             Status = STATUS_NOT_IMPLEMENTED;
             break;
-            
+
         case ProcessDeviceMap:
             DPRINT1("Device map not implemented\n");
             Status = STATUS_NOT_IMPLEMENTED;
             break;
-            
+
         case ProcessHandleTracing:
             DPRINT1("Handle tracing not implemented\n");
             Status = STATUS_NOT_IMPLEMENTED;
             break;
-            
-        case ProcessExecuteFlags:
-            DPRINT1("No execute support not implemented\n");
-            Status = STATUS_NOT_IMPLEMENTED;
-            break;
-            
+
         /* Anything else is invalid */
         default:
             DPRINT1("Invalid Server 2003 Info Class: %lx\n", ProcessInformationClass);
@@ -1642,6 +1980,7 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
     PEPROCESS Process;
     ULONG_PTR DisableBoost = 0;
     ULONG_PTR IdealProcessor = 0;
+    ULONG_PTR Break = 0;
     PTEB Teb;
     ULONG_PTR TlsIndex = 0;
     PVOID *ExpansionSlots;
@@ -2037,9 +2376,64 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
             /* All done */
             break;
 
+        case ThreadBreakOnTermination:
+
+            /* Check buffer length */
+            if (ThreadInformationLength != sizeof(ULONG))
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
+            /* Enter SEH for direct buffer read */
+            _SEH2_TRY
+            {
+                Break = *(PULONG)ThreadInformation;
+            }
+            _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))
+            {
+                /* We don't hold the privilege, bail out */
+                Status = STATUS_PRIVILEGE_NOT_HELD;
+                break;
+            }
+
+            /* Set or clear the flag */
+            if (Break)
+            {
+                PspSetCrossThreadFlag(Thread, CT_BREAK_ON_TERMINATION_BIT);
+            }
+            else
+            {
+                PspClearCrossThreadFlag(Thread, CT_BREAK_ON_TERMINATION_BIT);
+            }
+            break;
+
+        case ThreadHideFromDebugger:
+
+            /* Check buffer length */
+            if (ThreadInformationLength != 0)
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
+            /* Set the flag */
+            PspSetCrossThreadFlag(Thread, CT_HIDE_FROM_DEBUGGER_BIT);
+            break;
+
         default:
             /* We don't implement it yet */
-            DPRINT1("Not implemented: %lx\n", ThreadInformationClass);
+            DPRINT1("Not implemented: %d\n", ThreadInformationClass);
             Status = STATUS_NOT_IMPLEMENTED;
     }
 
@@ -2068,6 +2462,7 @@ NtQueryInformationThread(IN HANDLE ThreadHandle,
         (PTHREAD_BASIC_INFORMATION)ThreadInformation;
     PKERNEL_USER_TIMES ThreadTime = (PKERNEL_USER_TIMES)ThreadInformation;
     KIRQL OldIrql;
+    ULONG ThreadTerminated;
     PAGED_CODE();
 
     /* Check if we were called from user mode */
@@ -2152,12 +2547,19 @@ NtQueryInformationThread(IN HANDLE ThreadHandle,
             _SEH2_TRY
             {
                 /* Copy time information from ETHREAD/KTHREAD */
-                ThreadTime->KernelTime.QuadPart = Thread->Tcb.KernelTime *
-                                                   100000LL;
-                ThreadTime->UserTime.QuadPart = Thread->Tcb.UserTime *
-                                                 100000LL;
+                ThreadTime->KernelTime.QuadPart = Thread->Tcb.KernelTime * KeMaximumIncrement;
+                ThreadTime->UserTime.QuadPart = Thread->Tcb.UserTime * KeMaximumIncrement;
                 ThreadTime->CreateTime = Thread->CreateTime;
-                ThreadTime->ExitTime = Thread->ExitTime;
+
+                /* Exit time is in a union and only valid on actual exit! */
+                if (KeReadStateThread(&Thread->Tcb))
+                {
+                    ThreadTime->ExitTime = Thread->ExitTime;
+                }
+                else
+                {
+                    ThreadTime->ExitTime.QuadPart = 0;
+                }
             }
             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
@@ -2310,6 +2712,31 @@ NtQueryInformationThread(IN HANDLE ThreadHandle,
             _SEH2_END;
             break;
 
+        case ThreadIsTerminated:
+
+            /* Set the return length*/
+            Length = sizeof(ThreadTerminated);
+
+            if (ThreadInformationLength != Length)
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
+            ThreadTerminated = PsIsThreadTerminating(Thread);
+
+            _SEH2_TRY
+            {
+                *(PULONG)ThreadInformation = ThreadTerminated ? 1 : 0;
+            }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                Status = _SEH2_GetExceptionCode();
+            }
+            _SEH2_END;
+
+            break;
+
         /* Anything else */
         default: