ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

query.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Kernel
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            ntoskrnl/ps/query.c
00005  * PURPOSE:         Process Manager: Thread/Process Query/Set Information
00006  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
00007  *                  Thomas Weidenmueller (w3seek@reactos.org)
00008  *                  Eric Kohl
00009  */
00010 
00011 /* INCLUDES ******************************************************************/
00012 
00013 #include <ntoskrnl.h>
00014 #define NDEBUG
00015 #include <debug.h>
00016 
00017 /* FIXME: From winbase.h... what to do? */
00018 #define SEM_NOALIGNMENTFAULTEXCEPT 0x04
00019 
00020 /* Include Information Class Tables */
00021 #include "internal/ps_i.h"
00022 
00023 /* Debugging Level */
00024 ULONG PspTraceLevel = 0;
00025 
00026 /* PRIVATE FUNCTIONS *********************************************************/
00027 
00028 NTSTATUS
00029 NTAPI
00030 PsReferenceProcessFilePointer(IN PEPROCESS Process,
00031                               OUT PFILE_OBJECT *FileObject)
00032 {
00033     PSECTION Section;
00034     PAGED_CODE();
00035 
00036     /* Lock the process */
00037     ExAcquireRundownProtection(&Process->RundownProtect);
00038 
00039     /* Get the section */
00040     Section = Process->SectionObject;
00041     if (Section)
00042     {
00043         /* Get the file object and reference it */
00044         *FileObject = MmGetFileObjectForSection((PVOID)Section);
00045         ObReferenceObject(*FileObject);
00046     }
00047 
00048     /* Release the protection */
00049     ExReleaseRundownProtection(&Process->RundownProtect);
00050 
00051     /* Return status */
00052     return Section ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
00053 }
00054 
00055 /* PUBLIC FUNCTIONS **********************************************************/
00056 
00057 /*
00058  * @implemented
00059  */
00060 NTSTATUS
00061 NTAPI
00062 NtQueryInformationProcess(IN HANDLE ProcessHandle,
00063                           IN PROCESSINFOCLASS ProcessInformationClass,
00064                           OUT PVOID ProcessInformation,
00065                           IN ULONG ProcessInformationLength,
00066                           OUT PULONG ReturnLength OPTIONAL)
00067 {
00068     PEPROCESS Process;
00069     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
00070     NTSTATUS Status;
00071     ULONG Length = 0;
00072     HANDLE DebugPort = 0;
00073     PPROCESS_BASIC_INFORMATION ProcessBasicInfo =
00074         (PPROCESS_BASIC_INFORMATION)ProcessInformation;
00075     PKERNEL_USER_TIMES ProcessTime = (PKERNEL_USER_TIMES)ProcessInformation;
00076     PPROCESS_PRIORITY_CLASS PsPriorityClass = (PPROCESS_PRIORITY_CLASS)ProcessInformation;
00077     ULONG HandleCount;
00078     PPROCESS_SESSION_INFORMATION SessionInfo =
00079         (PPROCESS_SESSION_INFORMATION)ProcessInformation;
00080     PVM_COUNTERS VmCounters = (PVM_COUNTERS)ProcessInformation;
00081     PIO_COUNTERS IoCounters = (PIO_COUNTERS)ProcessInformation;
00082     PQUOTA_LIMITS QuotaLimits = (PQUOTA_LIMITS)ProcessInformation;
00083     PROCESS_DEVICEMAP_INFORMATION DeviceMap;
00084     PUNICODE_STRING ImageName;
00085     ULONG Cookie, ExecuteOptions = 0;
00086     ULONG_PTR Wow64 = 0;
00087     PAGED_CODE();
00088 
00089     /* Check for user-mode caller */
00090     if (PreviousMode != KernelMode)
00091     {
00092         /* Prepare to probe parameters */
00093         _SEH2_TRY
00094         {
00095             /* Probe the buffer */
00096             ProbeForWrite(ProcessInformation,
00097                           ProcessInformationLength,
00098                           sizeof(ULONG));
00099 
00100             /* Probe the return length if required */
00101             if (ReturnLength) ProbeForWriteUlong(ReturnLength);
00102         }
00103         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00104         {
00105             /* Return the exception code */
00106             _SEH2_YIELD(return _SEH2_GetExceptionCode());
00107         }
00108         _SEH2_END;
00109     }
00110 
00111     if((ProcessInformationClass == ProcessCookie) &&
00112         (ProcessHandle != NtCurrentProcess()))
00113     {
00114         /*
00115          * Retreiving the process cookie is only allowed for the calling process
00116          * itself! XP only allowes NtCurrentProcess() as process handles even if
00117          * a real handle actually represents the current process.
00118          */
00119         return STATUS_INVALID_PARAMETER;
00120     }
00121 
00122     /* Check the information class */
00123     switch (ProcessInformationClass)
00124     {
00125         /* Basic process information */
00126         case ProcessBasicInformation:
00127 
00128             /* Set return length */
00129             Length = sizeof(PROCESS_BASIC_INFORMATION);
00130 
00131             if (ProcessInformationLength != Length)
00132             {
00133                 Status = STATUS_INFO_LENGTH_MISMATCH;
00134                 break;
00135             }
00136 
00137             /* Reference the process */
00138             Status = ObReferenceObjectByHandle(ProcessHandle,
00139                                                PROCESS_QUERY_INFORMATION,
00140                                                PsProcessType,
00141                                                PreviousMode,
00142                                                (PVOID*)&Process,
00143                                                NULL);
00144             if (!NT_SUCCESS(Status)) break;
00145 
00146             /* Protect writes with SEH */
00147             _SEH2_TRY
00148             {
00149                 /* Write all the information from the EPROCESS/KPROCESS */
00150                 ProcessBasicInfo->ExitStatus = Process->ExitStatus;
00151                 ProcessBasicInfo->PebBaseAddress = Process->Peb;
00152                 ProcessBasicInfo->AffinityMask = Process->Pcb.Affinity;
00153                 ProcessBasicInfo->UniqueProcessId = (ULONG_PTR)Process->
00154                                                     UniqueProcessId;
00155                 ProcessBasicInfo->InheritedFromUniqueProcessId =
00156                     (ULONG)Process->InheritedFromUniqueProcessId;
00157                 ProcessBasicInfo->BasePriority = Process->Pcb.BasePriority;
00158 
00159             }
00160             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00161             {
00162                 /* Get exception code */
00163                 Status = _SEH2_GetExceptionCode();
00164             }
00165             _SEH2_END;
00166 
00167             /* Dereference the process */
00168             ObDereferenceObject(Process);
00169             break;
00170 
00171         /* Process quota limits */
00172         case ProcessQuotaLimits:
00173 
00174             Length = sizeof(QUOTA_LIMITS);
00175             if (ProcessInformationLength != Length)
00176             {
00177                 Status = STATUS_INFO_LENGTH_MISMATCH;
00178                 break;
00179             }
00180 
00181             /* Reference the process */
00182             Status = ObReferenceObjectByHandle(ProcessHandle,
00183                                                PROCESS_QUERY_INFORMATION,
00184                                                PsProcessType,
00185                                                PreviousMode,
00186                                                (PVOID*)&Process,
00187                                                NULL);
00188             if (!NT_SUCCESS(Status)) break;
00189 
00190             /* Indicate success */
00191             Status = STATUS_SUCCESS;
00192 
00193             _SEH2_TRY
00194             {
00195                 /* Set max/min working set sizes */
00196                 QuotaLimits->MaximumWorkingSetSize =
00197                         Process->Vm.MaximumWorkingSetSize << PAGE_SHIFT;
00198                 QuotaLimits->MinimumWorkingSetSize =
00199                         Process->Vm.MinimumWorkingSetSize << PAGE_SHIFT;
00200 
00201                 /* Set default time limits */
00202                 QuotaLimits->TimeLimit.LowPart = MAXULONG;
00203                 QuotaLimits->TimeLimit.HighPart = MAXULONG;
00204 
00205                 /* Is quota block a default one? */
00206                 if (Process->QuotaBlock == &PspDefaultQuotaBlock)
00207                 {
00208                     /* Set default pools and pagefile limits */
00209                     QuotaLimits->PagedPoolLimit = (SIZE_T)-1;
00210                     QuotaLimits->NonPagedPoolLimit = (SIZE_T)-1;
00211                     QuotaLimits->PagefileLimit = (SIZE_T)-1;
00212                 }
00213                 else
00214                 {
00215                     /* Get limits from non-default quota block */
00216                     QuotaLimits->PagedPoolLimit =
00217                         Process->QuotaBlock->QuotaEntry[PagedPool].Limit;
00218                     QuotaLimits->NonPagedPoolLimit =
00219                         Process->QuotaBlock->QuotaEntry[NonPagedPool].Limit;
00220                     QuotaLimits->PagefileLimit =
00221                         Process->QuotaBlock->QuotaEntry[2].Limit;
00222                 }
00223             }
00224             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00225             {
00226                 /* Get exception code */
00227                 Status = _SEH2_GetExceptionCode();
00228             }
00229             _SEH2_END;
00230 
00231             /* Dereference the process */
00232             ObDereferenceObject(Process);
00233             break;
00234 
00235         case ProcessIoCounters:
00236 
00237             Length = sizeof(IO_COUNTERS);
00238             if (ProcessInformationLength != Length)
00239             {
00240                 Status = STATUS_INFO_LENGTH_MISMATCH;
00241                 break;
00242             }
00243 
00244             /* Reference the process */
00245             Status = ObReferenceObjectByHandle(ProcessHandle,
00246                                                PROCESS_QUERY_INFORMATION,
00247                                                PsProcessType,
00248                                                PreviousMode,
00249                                                (PVOID*)&Process,
00250                                                NULL);
00251             if (!NT_SUCCESS(Status)) break;
00252 
00253             _SEH2_TRY
00254             {
00255                 /* FIXME: Call KeQueryValuesProcess */
00256                 IoCounters->ReadOperationCount = Process->ReadOperationCount.QuadPart;
00257                 IoCounters->ReadTransferCount = Process->ReadTransferCount.QuadPart;
00258                 IoCounters->WriteOperationCount = Process->WriteOperationCount.QuadPart;
00259                 IoCounters->WriteTransferCount = Process->WriteTransferCount.QuadPart;
00260                 IoCounters->OtherOperationCount = Process->OtherOperationCount.QuadPart;
00261                 IoCounters->OtherTransferCount = Process->OtherTransferCount.QuadPart;
00262             }
00263             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00264             {
00265                 /* Ignore exception */
00266             }
00267             _SEH2_END;
00268 
00269             /* Set status to success in any case */
00270             Status = STATUS_SUCCESS;
00271 
00272             /* Dereference the process */
00273             ObDereferenceObject(Process);
00274             break;
00275 
00276         /* Timing */
00277         case ProcessTimes:
00278 
00279             /* Set the return length */
00280             Length = sizeof(KERNEL_USER_TIMES);
00281 
00282             if (ProcessInformationLength != Length)
00283             {
00284                 Status = STATUS_INFO_LENGTH_MISMATCH;
00285                 break;
00286             }
00287 
00288             /* Reference the process */
00289             Status = ObReferenceObjectByHandle(ProcessHandle,
00290                                                PROCESS_QUERY_INFORMATION,
00291                                                PsProcessType,
00292                                                PreviousMode,
00293                                                (PVOID*)&Process,
00294                                                NULL);
00295             if (!NT_SUCCESS(Status)) break;
00296 
00297             /* Protect writes with SEH */
00298             _SEH2_TRY
00299             {
00300                 /* Copy time information from EPROCESS/KPROCESS */
00301                 /* FIXME: Call KeQueryRuntimeProcess */
00302                 ProcessTime->CreateTime = Process->CreateTime;
00303                 ProcessTime->UserTime.QuadPart = Process->Pcb.UserTime *
00304                                                  KeMaximumIncrement;
00305                 ProcessTime->KernelTime.QuadPart = Process->Pcb.KernelTime *
00306                                                    KeMaximumIncrement;
00307                 ProcessTime->ExitTime = Process->ExitTime;
00308             }
00309             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00310             {
00311                 /* Get exception code */
00312                 Status = _SEH2_GetExceptionCode();
00313             }
00314             _SEH2_END;
00315 
00316             /* Dereference the process */
00317             ObDereferenceObject(Process);
00318             break;
00319 
00320         /* Process Debug Port */
00321         case ProcessDebugPort:
00322 
00323             /* Set return length */
00324             Length = sizeof(HANDLE);
00325 
00326             if (ProcessInformationLength != Length)
00327             {
00328                 Status = STATUS_INFO_LENGTH_MISMATCH;
00329                 break;
00330             }
00331 
00332             /* Reference the process */
00333             Status = ObReferenceObjectByHandle(ProcessHandle,
00334                                                PROCESS_QUERY_INFORMATION,
00335                                                PsProcessType,
00336                                                PreviousMode,
00337                                                (PVOID*)&Process,
00338                                                NULL);
00339             if (!NT_SUCCESS(Status)) break;
00340 
00341             /* Protect write with SEH */
00342             _SEH2_TRY
00343             {
00344                 /* Return whether or not we have a debug port */
00345                 *(PHANDLE)ProcessInformation = (Process->DebugPort ?
00346                                                 (HANDLE)-1 : NULL);
00347             }
00348             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00349             {
00350                 /* Get exception code */
00351                 Status = _SEH2_GetExceptionCode();
00352             }
00353             _SEH2_END;
00354 
00355             /* Dereference the process */
00356             ObDereferenceObject(Process);
00357             break;
00358 
00359         case ProcessHandleCount:
00360 
00361             /* Set the return length*/
00362             Length = sizeof(ULONG);
00363 
00364             if (ProcessInformationLength != Length)
00365             {
00366                 Status = STATUS_INFO_LENGTH_MISMATCH;
00367                 break;
00368             }
00369 
00370             /* Reference the process */
00371             Status = ObReferenceObjectByHandle(ProcessHandle,
00372                                                PROCESS_QUERY_INFORMATION,
00373                                                PsProcessType,
00374                                                PreviousMode,
00375                                                (PVOID*)&Process,
00376                                                NULL);
00377             if (!NT_SUCCESS(Status)) break;
00378 
00379             /* Count the number of handles this process has */
00380             HandleCount = ObGetProcessHandleCount(Process);
00381 
00382             /* Protect write in SEH */
00383             _SEH2_TRY
00384             {
00385                 /* Return the count of handles */
00386                 *(PULONG)ProcessInformation = HandleCount;
00387             }
00388             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00389             {
00390                 /* Get the exception code */
00391                 Status = _SEH2_GetExceptionCode();
00392             }
00393             _SEH2_END;
00394 
00395             /* Dereference the process */
00396             ObDereferenceObject(Process);
00397             break;
00398 
00399         /* Session ID for the process */
00400         case ProcessSessionInformation:
00401 
00402             /* Set the return length*/
00403             Length = sizeof(PROCESS_SESSION_INFORMATION);
00404 
00405             if (ProcessInformationLength != Length)
00406             {
00407                 Status = STATUS_INFO_LENGTH_MISMATCH;
00408                 break;
00409             }
00410 
00411             /* Reference the process */
00412             Status = ObReferenceObjectByHandle(ProcessHandle,
00413                                                PROCESS_QUERY_INFORMATION,
00414                                                PsProcessType,
00415                                                PreviousMode,
00416                                                (PVOID*)&Process,
00417                                                NULL);
00418             if (!NT_SUCCESS(Status)) break;
00419 
00420             /* Enter SEH for write safety */
00421             _SEH2_TRY
00422             {
00423                 /* Write back the Session ID */
00424                 SessionInfo->SessionId = PtrToUlong(PsGetProcessSessionId(Process));
00425             }
00426             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00427             {
00428                 /* Get the exception code */
00429                 Status = _SEH2_GetExceptionCode();
00430             }
00431             _SEH2_END;
00432 
00433             /* Dereference the process */
00434             ObDereferenceObject(Process);
00435             break;
00436 
00437         /* Virtual Memory Statistics */
00438         case ProcessVmCounters:
00439 
00440             /* Validate the input length */
00441             if ((ProcessInformationLength != sizeof(VM_COUNTERS)) &&
00442                 (ProcessInformationLength != sizeof(VM_COUNTERS_EX)))
00443             {
00444                 Status = STATUS_INFO_LENGTH_MISMATCH;
00445                 break;
00446             }
00447 
00448             /* Reference the process */
00449             Status = ObReferenceObjectByHandle(ProcessHandle,
00450                                                PROCESS_QUERY_INFORMATION,
00451                                                PsProcessType,
00452                                                PreviousMode,
00453                                                (PVOID*)&Process,
00454                                                NULL);
00455             if (!NT_SUCCESS(Status)) break;
00456 
00457             /* Enter SEH for write safety */
00458             _SEH2_TRY
00459             {
00460                 /* Return data from EPROCESS */
00461                 VmCounters->PeakVirtualSize = Process->PeakVirtualSize;
00462                 VmCounters->VirtualSize = Process->VirtualSize;
00463                 VmCounters->PageFaultCount = Process->Vm.PageFaultCount;
00464                 VmCounters->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize;
00465                 VmCounters->WorkingSetSize = Process->Vm.WorkingSetSize;
00466                 VmCounters->QuotaPeakPagedPoolUsage = Process->QuotaPeak[0];
00467                 VmCounters->QuotaPagedPoolUsage = Process->QuotaUsage[0];
00468                 VmCounters->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[1];
00469                 VmCounters->QuotaNonPagedPoolUsage = Process->QuotaUsage[1];
00470                 VmCounters->PagefileUsage = Process->QuotaUsage[2] << PAGE_SHIFT;
00471                 VmCounters->PeakPagefileUsage = Process->QuotaPeak[2] << PAGE_SHIFT;
00472                 //VmCounters->PrivateUsage = Process->CommitCharge << PAGE_SHIFT;
00473                 //
00474 
00475                 /* Set the return length */
00476                 Length = ProcessInformationLength;
00477             }
00478             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00479             {
00480                 /* Get the exception code */
00481                 Status = _SEH2_GetExceptionCode();
00482             }
00483             _SEH2_END;
00484 
00485             /* Dereference the process */
00486             ObDereferenceObject(Process);
00487             break;
00488 
00489         /* Hard Error Processing Mode */
00490         case ProcessDefaultHardErrorMode:
00491 
00492             /* Set the return length*/
00493             Length = sizeof(ULONG);
00494 
00495             if (ProcessInformationLength != Length)
00496             {
00497                 Status = STATUS_INFO_LENGTH_MISMATCH;
00498                 break;
00499             }
00500 
00501             /* Reference the process */
00502             Status = ObReferenceObjectByHandle(ProcessHandle,
00503                                                PROCESS_QUERY_INFORMATION,
00504                                                PsProcessType,
00505                                                PreviousMode,
00506                                                (PVOID*)&Process,
00507                                                NULL);
00508             if (!NT_SUCCESS(Status)) break;
00509 
00510             /* Enter SEH for writing back data */
00511             _SEH2_TRY
00512             {
00513                 /* Write the current processing mode */
00514                 *(PULONG)ProcessInformation = Process->
00515                                               DefaultHardErrorProcessing;
00516             }
00517             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00518             {
00519                 /* Get the exception code */
00520                 Status = _SEH2_GetExceptionCode();
00521             }
00522             _SEH2_END;
00523 
00524             /* Dereference the process */
00525             ObDereferenceObject(Process);
00526             break;
00527 
00528         /* Priority Boosting status */
00529         case ProcessPriorityBoost:
00530 
00531             /* Set the return length */
00532             Length = sizeof(ULONG);
00533 
00534             if (ProcessInformationLength != Length)
00535             {
00536                 Status = STATUS_INFO_LENGTH_MISMATCH;
00537                 break;
00538             }
00539 
00540             /* Reference the process */
00541             Status = ObReferenceObjectByHandle(ProcessHandle,
00542                                                PROCESS_QUERY_INFORMATION,
00543                                                PsProcessType,
00544                                                PreviousMode,
00545                                                (PVOID*)&Process,
00546                                                NULL);
00547             if (!NT_SUCCESS(Status)) break;
00548 
00549             /* Enter SEH for writing back data */
00550             _SEH2_TRY
00551             {
00552                 /* Return boost status */
00553                 *(PULONG)ProcessInformation = Process->Pcb.DisableBoost ?
00554                                               TRUE : FALSE;
00555             }
00556             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00557             {
00558                 /* Get the exception code */
00559                 Status = _SEH2_GetExceptionCode();
00560             }
00561             _SEH2_END;
00562 
00563             /* Dereference the process */
00564             ObDereferenceObject(Process);
00565             break;
00566 
00567         /* DOS Device Map */
00568         case ProcessDeviceMap:
00569 
00570             /* Set the return length */
00571             Length = sizeof(PROCESS_DEVICEMAP_INFORMATION);
00572 
00573             if (ProcessInformationLength != Length)
00574             {
00575                 if (ProcessInformationLength == sizeof(PROCESS_DEVICEMAP_INFORMATION_EX))
00576                 {
00577                     DPRINT1("PROCESS_DEVICEMAP_INFORMATION_EX not supported!\n");
00578                     Status = STATUS_NOT_IMPLEMENTED;
00579                 }
00580                 else
00581                 {
00582                     Status = STATUS_INFO_LENGTH_MISMATCH;
00583                 }
00584                 break;
00585             }
00586 
00587             /* Reference the process */
00588             Status = ObReferenceObjectByHandle(ProcessHandle,
00589                                                PROCESS_QUERY_INFORMATION,
00590                                                PsProcessType,
00591                                                PreviousMode,
00592                                                (PVOID*)&Process,
00593                                                NULL);
00594             if (!NT_SUCCESS(Status)) break;
00595 
00596             /* Query the device map information */
00597             ObQueryDeviceMapInformation(Process, &DeviceMap);
00598 
00599             /* Enter SEH for writing back data */
00600             _SEH2_TRY
00601             {
00602                 *(PPROCESS_DEVICEMAP_INFORMATION)ProcessInformation = DeviceMap;
00603             }
00604             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00605             {
00606                 /* Get the exception code */
00607                 Status = _SEH2_GetExceptionCode();
00608             }
00609             _SEH2_END;
00610 
00611             /* Dereference the process */
00612             ObDereferenceObject(Process);
00613             break;
00614 
00615         /* Priority class */
00616         case ProcessPriorityClass:
00617 
00618             /* Set the return length*/
00619             Length = sizeof(PROCESS_PRIORITY_CLASS);
00620 
00621             if (ProcessInformationLength != Length)
00622             {
00623                 Status = STATUS_INFO_LENGTH_MISMATCH;
00624                 break;
00625             }
00626 
00627             /* Reference the process */
00628             Status = ObReferenceObjectByHandle(ProcessHandle,
00629                                                PROCESS_QUERY_INFORMATION,
00630                                                PsProcessType,
00631                                                PreviousMode,
00632                                                (PVOID*)&Process,
00633                                                NULL);
00634             if (!NT_SUCCESS(Status)) break;
00635 
00636             /* Enter SEH for writing back data */
00637             _SEH2_TRY
00638             {
00639                 /* Return current priority class */
00640                 PsPriorityClass->PriorityClass = Process->PriorityClass;
00641                 PsPriorityClass->Foreground = FALSE;
00642             }
00643             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00644             {
00645                 /* Get the exception code */
00646                 Status = _SEH2_GetExceptionCode();
00647             }
00648             _SEH2_END;
00649 
00650             /* Dereference the process */
00651             ObDereferenceObject(Process);
00652             break;
00653 
00654         case ProcessImageFileName:
00655 
00656             /* Reference the process */
00657             Status = ObReferenceObjectByHandle(ProcessHandle,
00658                                                PROCESS_QUERY_INFORMATION,
00659                                                PsProcessType,
00660                                                PreviousMode,
00661                                                (PVOID*)&Process,
00662                                                NULL);
00663             if (!NT_SUCCESS(Status)) break;
00664 
00665             /* Get the image path */
00666             Status = SeLocateProcessImageName(Process, &ImageName);
00667             if (NT_SUCCESS(Status))
00668             {
00669                 /* Set return length */
00670                 Length = ImageName->MaximumLength +
00671                          sizeof(OBJECT_NAME_INFORMATION);
00672 
00673                 /* Make sure it's large enough */
00674                 if (Length <= ProcessInformationLength)
00675                 {
00676                     /* Enter SEH to protect write */
00677                     _SEH2_TRY
00678                     {
00679                         /* Copy it */
00680                         RtlCopyMemory(ProcessInformation,
00681                                       ImageName,
00682                                       Length);
00683 
00684                         /* Update pointer */
00685                         ((PUNICODE_STRING)ProcessInformation)->Buffer =
00686                             (PWSTR)((PUNICODE_STRING)ProcessInformation + 1);
00687                    }
00688                     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00689                     {
00690                         /* Get the exception code */
00691                         Status = _SEH2_GetExceptionCode();
00692                     }
00693                     _SEH2_END;
00694                 }
00695                 else
00696                 {
00697                     /* Buffer too small */
00698                     Status = STATUS_INFO_LENGTH_MISMATCH;
00699                 }
00700 
00701                 /* Free the image path */
00702                 ExFreePool(ImageName);
00703             }
00704             /* Dereference the process */
00705             ObDereferenceObject(Process);
00706             break;
00707 
00708         case ProcessDebugFlags:
00709 
00710             /* Set the return length*/
00711             Length = sizeof(ULONG);
00712             if (ProcessInformationLength != Length)
00713             {
00714                 Status = STATUS_INFO_LENGTH_MISMATCH;
00715                 break;
00716             }
00717 
00718             /* Reference the process */
00719             Status = ObReferenceObjectByHandle(ProcessHandle,
00720                                                PROCESS_QUERY_INFORMATION,
00721                                                PsProcessType,
00722                                                PreviousMode,
00723                                                (PVOID*)&Process,
00724                                                NULL);
00725             if (!NT_SUCCESS(Status)) break;
00726 
00727             /* Enter SEH for writing back data */
00728             _SEH2_TRY
00729             {
00730                 /* Return the debug flag state */
00731                 *(PULONG)ProcessInformation = Process->NoDebugInherit ? 0 : 1;
00732             }
00733             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00734             {
00735                 /* Get the exception code */
00736                 Status = _SEH2_GetExceptionCode();
00737             }
00738             _SEH2_END;
00739 
00740             /* Dereference the process */
00741             ObDereferenceObject(Process);
00742             break;
00743 
00744         case ProcessBreakOnTermination:
00745 
00746             /* Set the return length*/
00747             Length = sizeof(ULONG);
00748             if (ProcessInformationLength != Length)
00749             {
00750                 Status = STATUS_INFO_LENGTH_MISMATCH;
00751                 break;
00752             }
00753 
00754             /* Reference the process */
00755             Status = ObReferenceObjectByHandle(ProcessHandle,
00756                                                PROCESS_QUERY_INFORMATION,
00757                                                PsProcessType,
00758                                                PreviousMode,
00759                                                (PVOID*)&Process,
00760                                                NULL);
00761             if (!NT_SUCCESS(Status)) break;
00762 
00763             /* Enter SEH for writing back data */
00764             _SEH2_TRY
00765             {
00766                 /* Return the BreakOnTermination state */
00767                 *(PULONG)ProcessInformation = Process->BreakOnTermination;
00768             }
00769             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00770             {
00771                 /* Get the exception code */
00772                 Status = _SEH2_GetExceptionCode();
00773             }
00774             _SEH2_END;
00775 
00776             /* Dereference the process */
00777             ObDereferenceObject(Process);
00778             break;
00779 
00780         /* Per-process security cookie */
00781         case ProcessCookie:
00782 
00783             /* Get the current process and cookie */
00784             Process = PsGetCurrentProcess();
00785             Cookie = Process->Cookie;
00786             if (!Cookie)
00787             {
00788                 LARGE_INTEGER SystemTime;
00789                 ULONG NewCookie;
00790                 PKPRCB Prcb;
00791 
00792                 /* Generate a new cookie */
00793                 KeQuerySystemTime(&SystemTime);
00794                 Prcb = KeGetCurrentPrcb();
00795                 NewCookie = Prcb->KeSystemCalls ^ Prcb->InterruptTime ^
00796                             SystemTime.u.LowPart ^ SystemTime.u.HighPart;
00797 
00798                 /* Set the new cookie or return the current one */
00799                 Cookie = InterlockedCompareExchange((LONG*)&Process->Cookie,
00800                                                     NewCookie,
00801                                                     Cookie);
00802                 if (!Cookie) Cookie = NewCookie;
00803 
00804                 /* Set return length */
00805                 Length = sizeof(ULONG);
00806             }
00807 
00808             /* Indicate success */
00809             Status = STATUS_SUCCESS;
00810 
00811             /* Enter SEH to protect write */
00812             _SEH2_TRY
00813             {
00814                 /* Write back the cookie */
00815                 *(PULONG)ProcessInformation = Cookie;
00816             }
00817             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00818             {
00819                 /* Get the exception code */
00820                 Status = _SEH2_GetExceptionCode();
00821             }
00822             _SEH2_END;
00823             break;
00824 
00825         case ProcessImageInformation:
00826             DPRINT1("Image Information Query Not implemented: %lx\n", ProcessInformationClass);
00827             Status = STATUS_NOT_IMPLEMENTED;
00828             break;
00829 
00830         case ProcessDebugObjectHandle:
00831 
00832             /* Set the return length */
00833             Length = sizeof(HANDLE);
00834             if (ProcessInformationLength != Length)
00835             {
00836                 Status = STATUS_INFO_LENGTH_MISMATCH;
00837                 break;
00838             }
00839 
00840             /* Reference the process */
00841             Status = ObReferenceObjectByHandle(ProcessHandle,
00842                                                PROCESS_QUERY_INFORMATION,
00843                                                PsProcessType,
00844                                                PreviousMode,
00845                                                (PVOID*)&Process,
00846                                                NULL);
00847             if (!NT_SUCCESS(Status)) break;
00848 
00849             /* Get the debug port */
00850             Status = DbgkOpenProcessDebugPort(Process, PreviousMode, &DebugPort);
00851 
00852             /* Let go of the process */
00853             ObDereferenceObject(Process);
00854 
00855             /* Protect write in SEH */
00856             _SEH2_TRY
00857             {
00858                 /* Return debug port's handle */
00859                 *(PHANDLE)ProcessInformation = DebugPort;
00860             }
00861             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00862             {
00863                 /* Get the exception code */
00864                 Status = _SEH2_GetExceptionCode();
00865             }
00866             _SEH2_END;
00867             break;
00868 
00869         case ProcessHandleTracing:
00870             DPRINT1("Handle tracing Not implemented: %lx\n", ProcessInformationClass);
00871             Status = STATUS_NOT_IMPLEMENTED;
00872             break;
00873 
00874         case ProcessLUIDDeviceMapsEnabled:
00875 
00876             /* Set the return length */
00877             Length = sizeof(ULONG);
00878             if (ProcessInformationLength != Length)
00879             {
00880                 Status = STATUS_INFO_LENGTH_MISMATCH;
00881                 break;
00882             }
00883 
00884             /* Indicate success */
00885             Status = STATUS_SUCCESS;
00886 
00887             /* Protect write in SEH */
00888             _SEH2_TRY
00889             {
00890                 /* Return FALSE -- we don't support this */
00891                 *(PULONG)ProcessInformation = FALSE;
00892             }
00893             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00894             {
00895                 /* Get the exception code */
00896                 Status = _SEH2_GetExceptionCode();
00897             }
00898             _SEH2_END;
00899             break;
00900 
00901         case ProcessWx86Information:
00902 
00903             /* Set the return length */
00904             Length = sizeof(ULONG);
00905             if (ProcessInformationLength != Length)
00906             {
00907                 Status = STATUS_INFO_LENGTH_MISMATCH;
00908                 break;
00909             }
00910 
00911             /* Reference the process */
00912             Status = ObReferenceObjectByHandle(ProcessHandle,
00913                                                PROCESS_QUERY_INFORMATION,
00914                                                PsProcessType,
00915                                                PreviousMode,
00916                                                (PVOID*)&Process,
00917                                                NULL);
00918             if (!NT_SUCCESS(Status)) break;
00919 
00920             /* Protect write in SEH */
00921             _SEH2_TRY
00922             {
00923                 /* Return if the flag is set */
00924                 *(PULONG)ProcessInformation = (ULONG)Process->VdmAllowed;
00925             }
00926             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00927             {
00928                 /* Get the exception code */
00929                 Status = _SEH2_GetExceptionCode();
00930             }
00931             _SEH2_END;
00932 
00933             /* Dereference the process */
00934             ObDereferenceObject(Process);
00935             break;
00936 
00937         case ProcessWow64Information:
00938 
00939             /* Set return length */
00940             Length = sizeof(ULONG_PTR);
00941             if (ProcessInformationLength != Length)
00942             {
00943                 Status = STATUS_INFO_LENGTH_MISMATCH;
00944                 break;
00945             }
00946 
00947             /* Reference the process */
00948             Status = ObReferenceObjectByHandle(ProcessHandle,
00949                                                PROCESS_QUERY_INFORMATION,
00950                                                PsProcessType,
00951                                                PreviousMode,
00952                                                (PVOID*)&Process,
00953                                                NULL);
00954             if (!NT_SUCCESS(Status)) break;
00955 
00956             /* Make sure the process isn't dying */
00957             if (ExAcquireRundownProtection(&Process->RundownProtect))
00958             {
00959                 /* Get the WOW64 process structure */
00960 #ifdef _WIN64
00961                 Wow64 = (ULONG_PTR)Process->Wow64Process;
00962 #else
00963                 Wow64 = 0;
00964 #endif
00965                 /* Release the lock */
00966                 ExReleaseRundownProtection(&Process->RundownProtect);
00967             }
00968 
00969             /* Protect write with SEH */
00970             _SEH2_TRY
00971             {
00972                 /* Return whether or not we have a debug port */
00973                 *(PULONG_PTR)ProcessInformation = Wow64;
00974             }
00975             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00976             {
00977                 /* Get exception code */
00978                 Status = _SEH2_GetExceptionCode();
00979             }
00980             _SEH2_END;
00981 
00982             /* Dereference the process */
00983             ObDereferenceObject(Process);
00984             break;
00985 
00986         case ProcessExecuteFlags:
00987 
00988             /* Set return length */
00989             Length = sizeof(ULONG);
00990             if (ProcessInformationLength != Length)
00991             {
00992                 Status = STATUS_INFO_LENGTH_MISMATCH;
00993                 break;
00994             }
00995 
00996             if (ProcessHandle != NtCurrentProcess())
00997             {
00998                 return STATUS_INVALID_PARAMETER;
00999             }
01000 
01001             /* Get the options */
01002             Status = MmGetExecuteOptions(&ExecuteOptions);
01003             if (NT_SUCCESS(Status))
01004             {
01005                 /* Protect write with SEH */
01006                 _SEH2_TRY
01007                 {
01008                     /* Return them */
01009                     *(PULONG)ProcessInformation = ExecuteOptions;
01010                 }
01011                 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01012                 {
01013                     /* Get exception code */
01014                     Status = _SEH2_GetExceptionCode();
01015                 }
01016                 _SEH2_END;
01017             }
01018             break;
01019 
01020         case ProcessLdtInformation:
01021             DPRINT1("VDM/16-bit not implemented: %lx\n", ProcessInformationClass);
01022             Status = STATUS_NOT_IMPLEMENTED;
01023             break;
01024 
01025         case ProcessWorkingSetWatch:
01026             DPRINT1("WS Watch Not implemented: %lx\n", ProcessInformationClass);
01027             Status = STATUS_NOT_IMPLEMENTED;
01028             break;
01029 
01030         case ProcessPooledUsageAndLimits:
01031             DPRINT1("Pool limits Not implemented: %lx\n", ProcessInformationClass);
01032             Status = STATUS_NOT_IMPLEMENTED;
01033             break;
01034 
01035         /* Not supported by Server 2003 */
01036         default:
01037             DPRINT1("Unsupported info class: %lx\n", ProcessInformationClass);
01038             Status = STATUS_INVALID_INFO_CLASS;
01039     }
01040 
01041     /* Protect write with SEH */
01042     _SEH2_TRY
01043     {
01044         /* Check if caller wanted return length */
01045         if ((ReturnLength) && (Length)) *ReturnLength = Length;
01046     }
01047     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01048     {
01049         /* Get exception code */
01050         Status = _SEH2_GetExceptionCode();
01051     }
01052     _SEH2_END;
01053 
01054     return Status;
01055 }
01056 
01057 /*
01058  * @implemented
01059  */
01060 NTSTATUS
01061 NTAPI
01062 NtSetInformationProcess(IN HANDLE ProcessHandle,
01063                         IN PROCESSINFOCLASS ProcessInformationClass,
01064                         IN PVOID ProcessInformation,
01065                         IN ULONG ProcessInformationLength)
01066 {
01067     PEPROCESS Process;
01068     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
01069     ACCESS_MASK Access;
01070     NTSTATUS Status;
01071     HANDLE PortHandle = NULL;
01072     HANDLE TokenHandle = NULL;
01073     PROCESS_SESSION_INFORMATION SessionInfo = {0};
01074     PROCESS_PRIORITY_CLASS PriorityClass = {0};
01075     PROCESS_FOREGROUND_BACKGROUND Foreground = {0};
01076     PVOID ExceptionPort;
01077     ULONG Break;
01078     KAFFINITY ValidAffinity, Affinity = 0;
01079     KPRIORITY BasePriority = 0;
01080     UCHAR MemoryPriority = 0;
01081     BOOLEAN DisableBoost = 0;
01082     ULONG DefaultHardErrorMode = 0;
01083     ULONG DebugFlags = 0, EnableFixup = 0, Boost = 0;
01084     ULONG NoExecute = 0, VdmPower = 0;
01085     BOOLEAN HasPrivilege;
01086     PLIST_ENTRY Next;
01087     PETHREAD Thread;
01088     PAGED_CODE();
01089 
01090     /* Verify Information Class validity */
01091 #if 0
01092     Status = DefaultSetInfoBufferCheck(ProcessInformationClass,
01093                                        PsProcessInfoClass,
01094                                        RTL_NUMBER_OF(PsProcessInfoClass),
01095                                        ProcessInformation,
01096                                        ProcessInformationLength,
01097                                        PreviousMode);
01098     if (!NT_SUCCESS(Status)) return Status;
01099 #endif
01100 
01101     /* Check what class this is */
01102     Access = PROCESS_SET_INFORMATION;
01103     if (ProcessInformationClass == ProcessSessionInformation)
01104     {
01105         /* Setting the Session ID needs a special mask */
01106         Access |= PROCESS_SET_SESSIONID;
01107     }
01108     else if (ProcessInformationClass == ProcessExceptionPort)
01109     {
01110         /* Setting the exception port needs a special mask */
01111         Access |= PROCESS_SUSPEND_RESUME;
01112     }
01113 
01114     /* Reference the process */
01115     Status = ObReferenceObjectByHandle(ProcessHandle,
01116                                        Access,
01117                                        PsProcessType,
01118                                        PreviousMode,
01119                                        (PVOID*)&Process,
01120                                        NULL);
01121     if (!NT_SUCCESS(Status)) return Status;
01122 
01123     /* Check what kind of information class this is */
01124     switch (ProcessInformationClass)
01125     {
01126         case ProcessWx86Information:
01127 
01128             /* Check buffer length */
01129             if (ProcessInformationLength != sizeof(HANDLE))
01130             {
01131                 Status = STATUS_INFO_LENGTH_MISMATCH;
01132                 break;
01133             }
01134 
01135             /* Use SEH for capture */
01136             _SEH2_TRY
01137             {
01138                 /* Capture the boolean */
01139                 VdmPower = *(PULONG)ProcessInformation;
01140             }
01141             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01142             {
01143                 /* Get the exception code */
01144                 Status = _SEH2_GetExceptionCode();
01145                 _SEH2_YIELD(break);
01146             }
01147             _SEH2_END;
01148 
01149             /* Getting VDM powers requires the SeTcbPrivilege */
01150             if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
01151             {
01152                 /* Bail out */
01153                 Status = STATUS_PRIVILEGE_NOT_HELD;
01154                 DPRINT1("Need TCB privilege\n");
01155                 break;
01156             }
01157 
01158             /* Set or clear the flag */
01159             if (VdmPower)
01160             {
01161                 PspSetProcessFlag(Process, PSF_VDM_ALLOWED_BIT);
01162             }
01163             else
01164             {
01165                 PspClearProcessFlag(Process, PSF_VDM_ALLOWED_BIT);
01166             }
01167             break;
01168 
01169         /* Error/Exception Port */
01170         case ProcessExceptionPort:
01171 
01172             /* Check buffer length */
01173             if (ProcessInformationLength != sizeof(HANDLE))
01174             {
01175                 Status = STATUS_INFO_LENGTH_MISMATCH;
01176                 break;
01177             }
01178 
01179             /* Use SEH for capture */
01180             _SEH2_TRY
01181             {
01182                 /* Capture the handle */
01183                 PortHandle = *(PHANDLE)ProcessInformation;
01184             }
01185             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01186             {
01187                 /* Get the exception code */
01188                 Status = _SEH2_GetExceptionCode();
01189                 _SEH2_YIELD(break);
01190             }
01191             _SEH2_END;
01192 
01193             /* Setting the error port requires the SeTcbPrivilege */
01194             if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
01195             {
01196                 /* Can't set the session ID, bail out. */
01197                 Status = STATUS_PRIVILEGE_NOT_HELD;
01198                 break;
01199             }
01200 
01201             /* Get the LPC Port */
01202             Status = ObReferenceObjectByHandle(PortHandle,
01203                                                0,
01204                                                LpcPortObjectType,
01205                                                PreviousMode,
01206                                                (PVOID)&ExceptionPort,
01207                                                NULL);
01208             if (!NT_SUCCESS(Status)) break;
01209 
01210             /* Change the pointer */
01211             if (InterlockedCompareExchangePointer(&Process->ExceptionPort,
01212                                                   ExceptionPort,
01213                                                   NULL))
01214             {
01215                 /* We already had one, fail */
01216                 ObDereferenceObject(ExceptionPort);
01217                 Status = STATUS_PORT_ALREADY_SET;
01218             }
01219             break;
01220 
01221         /* Security Token */
01222         case ProcessAccessToken:
01223 
01224             /* Check buffer length */
01225             if (ProcessInformationLength != sizeof(PROCESS_ACCESS_TOKEN))
01226             {
01227                 Status = STATUS_INFO_LENGTH_MISMATCH;
01228                 break;
01229             }
01230 
01231             /* Use SEH for capture */
01232             _SEH2_TRY
01233             {
01234                 /* Save the token handle */
01235                 TokenHandle = ((PPROCESS_ACCESS_TOKEN)ProcessInformation)->
01236                                Token;
01237             }
01238             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01239             {
01240                 /* Get the exception code */
01241                 Status = _SEH2_GetExceptionCode();
01242                 _SEH2_YIELD(break);
01243             }
01244             _SEH2_END;
01245 
01246             /* Assign the actual token */
01247             Status = PspSetPrimaryToken(Process, TokenHandle, NULL);
01248             break;
01249 
01250         /* Hard error processing */
01251         case ProcessDefaultHardErrorMode:
01252 
01253             /* Check buffer length */
01254             if (ProcessInformationLength != sizeof(ULONG))
01255             {
01256                 Status = STATUS_INFO_LENGTH_MISMATCH;
01257                 break;
01258             }
01259 
01260             /* Enter SEH for direct buffer read */
01261             _SEH2_TRY
01262             {
01263                 DefaultHardErrorMode = *(PULONG)ProcessInformation;
01264             }
01265             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01266             {
01267                 /* Get exception code */
01268                 Status = _SEH2_GetExceptionCode();
01269                 _SEH2_YIELD(break);
01270             }
01271             _SEH2_END;
01272 
01273             /* Set the mode */
01274             Process->DefaultHardErrorProcessing = DefaultHardErrorMode;
01275 
01276             /* Call Ke for the update */
01277             if (DefaultHardErrorMode & SEM_NOALIGNMENTFAULTEXCEPT)
01278             {
01279                 KeSetAutoAlignmentProcess(&Process->Pcb, TRUE);
01280             }
01281             else
01282             {
01283                 KeSetAutoAlignmentProcess(&Process->Pcb, FALSE);
01284             }
01285             Status = STATUS_SUCCESS;
01286             break;
01287 
01288         /* Session ID */
01289         case ProcessSessionInformation:
01290 
01291             /* Check buffer length */
01292             if (ProcessInformationLength != sizeof(PROCESS_SESSION_INFORMATION))
01293             {
01294                 Status = STATUS_INFO_LENGTH_MISMATCH;
01295                 break;
01296             }
01297 
01298             /* Enter SEH for capture */
01299             _SEH2_TRY
01300             {
01301                 /* Capture the caller's buffer */
01302                 SessionInfo = *(PPROCESS_SESSION_INFORMATION)ProcessInformation;
01303             }
01304             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01305             {
01306                 /* Get the exception code */
01307                 Status = _SEH2_GetExceptionCode();
01308                 _SEH2_YIELD(break);
01309             }
01310             _SEH2_END;
01311 
01312             /* Setting the session id requires the SeTcbPrivilege */
01313             if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
01314             {
01315                 /* Can't set the session ID, bail out. */
01316                 Status = STATUS_PRIVILEGE_NOT_HELD;
01317                 break;
01318             }
01319 
01320             /* FIXME - update the session id for the process token */
01321             //Status = PsLockProcess(Process, FALSE);
01322             if (!NT_SUCCESS(Status)) break;
01323 
01324             /* Write the session ID in the EPROCESS */
01325             Process->Session = UlongToPtr(SessionInfo.SessionId); // HACK!!!
01326 
01327             /* Check if the process also has a PEB */
01328             if (Process->Peb)
01329             {
01330                 /*
01331                  * Attach to the process to make sure we're in the right
01332                  * context to access the PEB structure
01333                  */
01334                 KeAttachProcess(&Process->Pcb);
01335 
01336                 /* Enter SEH for write to user-mode PEB */
01337                 _SEH2_TRY
01338                 {
01339                     /* Write the session ID */
01340                     Process->Peb->SessionId = SessionInfo.SessionId;
01341                 }
01342                 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01343                 {
01344                     /* Get exception code */
01345                     Status = _SEH2_GetExceptionCode();
01346                 }
01347                 _SEH2_END;
01348 
01349                 /* Detach from the process */
01350                 KeDetachProcess();
01351             }
01352 
01353             /* Unlock the process */
01354             //PsUnlockProcess(Process);
01355             break;
01356 
01357         case ProcessPriorityClass:
01358 
01359             /* Check buffer length */
01360             if (ProcessInformationLength != sizeof(PROCESS_PRIORITY_CLASS))
01361             {
01362                 Status = STATUS_INFO_LENGTH_MISMATCH;
01363                 break;
01364             }
01365 
01366             /* Enter SEH for capture */
01367             _SEH2_TRY
01368             {
01369                 /* Capture the caller's buffer */
01370                 PriorityClass = *(PPROCESS_PRIORITY_CLASS)ProcessInformation;
01371             }
01372             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01373             {
01374                 /* Return the exception code */
01375                 Status = _SEH2_GetExceptionCode();
01376                 _SEH2_YIELD(break);
01377             }
01378             _SEH2_END;
01379 
01380             /* Check for invalid PriorityClass value */
01381             if (PriorityClass.PriorityClass > PROCESS_PRIORITY_CLASS_ABOVE_NORMAL)
01382             {
01383                 Status = STATUS_INVALID_PARAMETER;
01384                 break;
01385             }
01386 
01387             if ((PriorityClass.PriorityClass != Process->PriorityClass) &&
01388                 (PriorityClass.PriorityClass == PROCESS_PRIORITY_CLASS_REALTIME))
01389             {
01390                 /* Check the privilege */
01391                 HasPrivilege = SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege,
01392                                                        ProcessHandle,
01393                                                        PROCESS_SET_INFORMATION,
01394                                                        PreviousMode);
01395                 if (!HasPrivilege)
01396                 {
01397                     ObDereferenceObject(Process);
01398                     DPRINT1("Privilege to change priority to realtime lacking\n");
01399                     return STATUS_PRIVILEGE_NOT_HELD;
01400                 }
01401             }
01402 
01403             /* Check if we have a job */
01404             if (Process->Job)
01405             {
01406                 DPRINT1("Jobs not yet supported\n");
01407             }
01408 
01409             /* Set process priority class */
01410             Process->PriorityClass = PriorityClass.PriorityClass;
01411 
01412             /* Set process priority mode (foreground or background) */
01413             PsSetProcessPriorityByClass(Process,
01414                                         PriorityClass.Foreground ?
01415                                         PsProcessPriorityForeground :
01416                                         PsProcessPriorityBackground);
01417             Status = STATUS_SUCCESS;
01418             break;
01419 
01420         case ProcessForegroundInformation:
01421 
01422             /* Check buffer length */
01423             if (ProcessInformationLength != sizeof(PROCESS_FOREGROUND_BACKGROUND))
01424             {
01425                 Status = STATUS_INFO_LENGTH_MISMATCH;
01426                 break;
01427             }
01428 
01429             /* Enter SEH for capture */
01430             _SEH2_TRY
01431             {
01432                 /* Capture the caller's buffer */
01433                 Foreground = *(PPROCESS_FOREGROUND_BACKGROUND)ProcessInformation;
01434             }
01435             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01436             {
01437                 /* Return the exception code */
01438                 Status = _SEH2_GetExceptionCode();
01439                 _SEH2_YIELD(break);
01440             }
01441             _SEH2_END;
01442 
01443             /* Set process priority mode (foreground or background) */
01444             PsSetProcessPriorityByClass(Process,
01445                                         Foreground.Foreground ?
01446                                         PsProcessPriorityForeground :
01447                                         PsProcessPriorityBackground);
01448             Status = STATUS_SUCCESS;
01449             break;
01450 
01451         case ProcessBasePriority:
01452 
01453             /* Validate input length */
01454             if (ProcessInformationLength != sizeof(KPRIORITY))
01455             {
01456                 Status = STATUS_INFO_LENGTH_MISMATCH;
01457                 break;
01458             }
01459 
01460             /* Enter SEH for direct buffer read */
01461             _SEH2_TRY
01462             {
01463                 BasePriority = *(KPRIORITY*)ProcessInformation;
01464             }
01465             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01466             {
01467                 /* Get exception code */
01468                 Break = 0;
01469                 Status = _SEH2_GetExceptionCode();
01470                 _SEH2_YIELD(break);
01471             }
01472             _SEH2_END;
01473 
01474             /* Extract the memory priority out of there */
01475             if (BasePriority & 0x80000000)
01476             {
01477                 MemoryPriority = MEMORY_PRIORITY_FOREGROUND;
01478                 BasePriority &= ~0x80000000;
01479             }
01480             else
01481             {
01482                 MemoryPriority = MEMORY_PRIORITY_BACKGROUND;
01483             }
01484 
01485             /* Validate the number */
01486             if ((BasePriority > HIGH_PRIORITY) || (BasePriority <= LOW_PRIORITY))
01487             {
01488                 return STATUS_INVALID_PARAMETER;
01489             }
01490 
01491             /* Check if the new base is higher */
01492             if (BasePriority > Process->Pcb.BasePriority)
01493             {
01494                 HasPrivilege = SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege,
01495                                                        ProcessHandle,
01496                                                        PROCESS_SET_INFORMATION,
01497                                                        PreviousMode);
01498                 if (!HasPrivilege)
01499                 {
01500                     ObDereferenceObject(Process);
01501                     DPRINT1("Privilege to change priority from %lx to %lx lacking\n", BasePriority, Process->Pcb.BasePriority);
01502                     return STATUS_PRIVILEGE_NOT_HELD;
01503                 }
01504             }
01505 
01506             /* Call Ke */
01507             KeSetPriorityAndQuantumProcess(&Process->Pcb, BasePriority, 0);
01508 
01509             /* Now set the memory priority */
01510             MmSetMemoryPriorityProcess(Process, MemoryPriority);
01511             Status = STATUS_SUCCESS;
01512             break;
01513 
01514         case ProcessRaisePriority:
01515 
01516             /* Validate input length */
01517             if (ProcessInformationLength != sizeof(ULONG))
01518             {
01519                 Status = STATUS_INFO_LENGTH_MISMATCH;
01520                 break;
01521             }
01522 
01523             /* Enter SEH for direct buffer read */
01524             _SEH2_TRY
01525             {
01526                 Boost = *(PULONG)ProcessInformation;
01527             }
01528             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01529             {
01530                 /* Get exception code */
01531                 Break = 0;
01532                 Status = _SEH2_GetExceptionCode();
01533                 _SEH2_YIELD(break);
01534             }
01535             _SEH2_END;
01536 
01537             /* Make sure the process isn't dying */
01538             if (ExAcquireRundownProtection(&Process->RundownProtect))
01539             {
01540                 /* Lock it */
01541                 KeEnterCriticalRegion();
01542                 ExAcquirePushLockShared(&Process->ProcessLock);
01543 
01544                 /* Loop the threads */
01545                 for (Next = Process->ThreadListHead.Flink;
01546                      Next != &Process->ThreadListHead;
01547                      Next = Next->Flink)
01548                 {
01549                     /* Call Ke for the thread */
01550                     Thread = CONTAINING_RECORD(Next, ETHREAD, ThreadListEntry);
01551                     KeBoostPriorityThread(&Thread->Tcb, Boost);
01552                 }
01553 
01554                 /* Release the lock and rundown */
01555                 ExReleasePushLockShared(&Process->ProcessLock);
01556                 KeLeaveCriticalRegion();
01557                 ExReleaseRundownProtection(&Process->RundownProtect);
01558 
01559                 /* Set success code */
01560                 Status = STATUS_SUCCESS;
01561             }
01562             else
01563             {
01564                 /* Avoid race conditions */
01565                 Status = STATUS_PROCESS_IS_TERMINATING;
01566             }
01567             break;
01568 
01569         case ProcessBreakOnTermination:
01570 
01571             /* Check buffer length */
01572             if (ProcessInformationLength != sizeof(ULONG))
01573             {
01574                 Status = STATUS_INFO_LENGTH_MISMATCH;
01575                 break;
01576             }
01577 
01578             /* Enter SEH for direct buffer read */
01579             _SEH2_TRY
01580             {
01581                 Break = *(PULONG)ProcessInformation;
01582             }
01583             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01584             {
01585                 /* Get exception code */
01586                 Break = 0;
01587                 Status = _SEH2_GetExceptionCode();
01588                 _SEH2_YIELD(break);
01589             }
01590             _SEH2_END;
01591 
01592             /* Setting 'break on termination' requires the SeDebugPrivilege */
01593             if (!SeSinglePrivilegeCheck(SeDebugPrivilege, PreviousMode))
01594             {
01595                 Status = STATUS_PRIVILEGE_NOT_HELD;
01596                 break;
01597             }
01598 
01599             /* Set or clear the flag */
01600             if (Break)
01601             {
01602                 PspSetProcessFlag(Process, PSF_BREAK_ON_TERMINATION_BIT);
01603             }
01604             else
01605             {
01606                 PspClearProcessFlag(Process, PSF_BREAK_ON_TERMINATION_BIT);
01607             }
01608 
01609             break;
01610 
01611         case ProcessAffinityMask:
01612 
01613             /* Check buffer length */
01614             if (ProcessInformationLength != sizeof(KAFFINITY))
01615             {
01616                 Status = STATUS_INFO_LENGTH_MISMATCH;
01617                 break;
01618             }
01619 
01620             /* Enter SEH for direct buffer read */
01621             _SEH2_TRY
01622             {
01623                 Affinity = *(PKAFFINITY)ProcessInformation;
01624             }
01625             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01626             {
01627                 /* Get exception code */
01628                 Break = 0;
01629                 Status = _SEH2_GetExceptionCode();
01630                 _SEH2_YIELD(break);
01631             }
01632             _SEH2_END;
01633 
01634             /* Make sure it's valid for the CPUs present */
01635             ValidAffinity = Affinity & KeActiveProcessors;
01636             if (!Affinity || (ValidAffinity != Affinity))
01637             {
01638                 Status = STATUS_INVALID_PARAMETER;
01639                 break;
01640             }
01641 
01642             /* Check if it's within job affinity limits */
01643             if (Process->Job)
01644             {
01645                 /* Not yet implemented */
01646                 UNIMPLEMENTED;
01647                 Status = STATUS_NOT_IMPLEMENTED;
01648                 break;
01649             }
01650 
01651             /* Make sure the process isn't dying */
01652             if (ExAcquireRundownProtection(&Process->RundownProtect))
01653             {
01654                 /* Lock it */
01655                 KeEnterCriticalRegion();
01656                 ExAcquirePushLockShared(&Process->ProcessLock);
01657 
01658                 /* Call Ke to do the work */
01659                 KeSetAffinityProcess(&Process->Pcb, ValidAffinity);
01660 
01661                 /* Release the lock and rundown */
01662                 ExReleasePushLockShared(&Process->ProcessLock);
01663                 KeLeaveCriticalRegion();
01664                 ExReleaseRundownProtection(&Process->RundownProtect);
01665 
01666                 /* Set success code */
01667                 Status = STATUS_SUCCESS;
01668             }
01669             else
01670             {
01671                 /* Avoid race conditions */
01672                 Status = STATUS_PROCESS_IS_TERMINATING;
01673             }
01674             break;
01675 
01676         /* Priority Boosting status */
01677         case ProcessPriorityBoost:
01678 
01679             /* Validate input length */
01680             if (ProcessInformationLength != sizeof(ULONG))
01681             {
01682                 Status = STATUS_INFO_LENGTH_MISMATCH;
01683                 break;
01684             }
01685 
01686             /* Enter SEH for direct buffer read */
01687             _SEH2_TRY
01688             {
01689                 DisableBoost = *(PBOOLEAN)ProcessInformation;
01690             }
01691             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01692             {
01693                 /* Get exception code */
01694                 Break = 0;
01695                 Status = _SEH2_GetExceptionCode();
01696                 _SEH2_YIELD(break);
01697             }
01698             _SEH2_END;
01699 
01700             /* Make sure the process isn't dying */
01701             if (ExAcquireRundownProtection(&Process->RundownProtect))
01702             {
01703                 /* Lock it */
01704                 KeEnterCriticalRegion();
01705                 ExAcquirePushLockShared(&Process->ProcessLock);
01706 
01707                 /* Call Ke to do the work */
01708                 KeSetDisableBoostProcess(&Process->Pcb, DisableBoost);
01709 
01710                 /* Loop the threads too */
01711                 for (Next = Process->ThreadListHead.Flink;
01712                      Next != &Process->ThreadListHead;
01713                      Next = Next->Flink)
01714                 {
01715                     /* Call Ke for the thread */
01716                     Thread = CONTAINING_RECORD(Next, ETHREAD, ThreadListEntry);
01717                     KeSetDisableBoostThread(&Thread->Tcb, DisableBoost);
01718                 }
01719 
01720                 /* Release the lock and rundown */
01721                 ExReleasePushLockShared(&Process->ProcessLock);
01722                 KeLeaveCriticalRegion();
01723                 ExReleaseRundownProtection(&Process->RundownProtect);
01724 
01725                 /* Set success code */
01726                 Status = STATUS_SUCCESS;
01727             }
01728             else
01729             {
01730                 /* Avoid race conditions */
01731                 Status = STATUS_PROCESS_IS_TERMINATING;
01732             }
01733             break;
01734 
01735         case ProcessDebugFlags:
01736 
01737             /* Check buffer length */
01738             if (ProcessInformationLength != sizeof(ULONG))
01739             {
01740                 Status = STATUS_INFO_LENGTH_MISMATCH;
01741                 break;
01742             }
01743 
01744             /* Enter SEH for direct buffer read */
01745             _SEH2_TRY
01746             {
01747                 DebugFlags = *(PULONG)ProcessInformation;
01748             }
01749             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01750             {
01751                 /* Get exception code */
01752                 Status = _SEH2_GetExceptionCode();
01753                 _SEH2_YIELD(break);
01754             }
01755             _SEH2_END;
01756 
01757             /* Set the mode */
01758             if (DebugFlags & ~1)
01759             {
01760                 Status = STATUS_INVALID_PARAMETER;
01761             }
01762             else
01763             {
01764                 if (DebugFlags & 1)
01765                 {
01766                     PspClearProcessFlag(Process, PSF_NO_DEBUG_INHERIT_BIT);
01767                 }
01768                 else
01769                 {
01770                     PspSetProcessFlag(Process, PSF_NO_DEBUG_INHERIT_BIT);
01771                 }
01772             }
01773 
01774             /* Done */
01775             Status = STATUS_SUCCESS;
01776             break;
01777 
01778         case ProcessEnableAlignmentFaultFixup:
01779 
01780             /* Check buffer length */
01781             if (ProcessInformationLength != sizeof(ULONG))
01782             {
01783                 Status = STATUS_INFO_LENGTH_MISMATCH;
01784                 break;
01785             }
01786 
01787             /* Enter SEH for direct buffer read */
01788             _SEH2_TRY
01789             {
01790                 EnableFixup = *(PULONG)ProcessInformation;
01791             }
01792             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01793             {
01794                 /* Get exception code */
01795                 Status = _SEH2_GetExceptionCode();
01796                 _SEH2_YIELD(break);
01797             }
01798             _SEH2_END;
01799 
01800             /* Set the mode */
01801             if (EnableFixup)
01802             {
01803                 Process->DefaultHardErrorProcessing |= SEM_NOALIGNMENTFAULTEXCEPT;
01804             }
01805             else
01806             {
01807                 Process->DefaultHardErrorProcessing &= ~SEM_NOALIGNMENTFAULTEXCEPT;
01808             }
01809 
01810             /* Call Ke for the update */
01811             KeSetAutoAlignmentProcess(&Process->Pcb, FALSE);
01812             Status = STATUS_SUCCESS;
01813             break;
01814 
01815         case ProcessUserModeIOPL:
01816 
01817             /* Only TCB can do this */
01818             if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
01819             {
01820                 /* Fail */
01821                 DPRINT1("Need TCB to set IOPL\n");
01822                 Status = STATUS_PRIVILEGE_NOT_HELD;
01823                 break;
01824             }
01825 
01826             /* Only supported on x86 */
01827 #if defined (_X86_)
01828             Ke386SetIOPL();
01829 #else
01830             Status = STATUS_NOT_IMPLEMENTED;
01831 #endif
01832             /* Done */
01833             break;
01834 
01835         case ProcessExecuteFlags:
01836 
01837             /* Check buffer length */
01838             if (ProcessInformationLength != sizeof(ULONG))
01839             {
01840                 Status = STATUS_INFO_LENGTH_MISMATCH;
01841                 break;
01842             }
01843 
01844             if (ProcessHandle != NtCurrentProcess())
01845             {
01846                 Status = STATUS_INVALID_PARAMETER;
01847                 break;
01848             }
01849 
01850             /* Enter SEH for direct buffer read */
01851             _SEH2_TRY
01852             {
01853                 NoExecute = *(PULONG)ProcessInformation;
01854             }
01855             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01856             {
01857                 /* Get exception code */
01858                 Status = _SEH2_GetExceptionCode();
01859                 _SEH2_YIELD(break);
01860             }
01861             _SEH2_END;
01862 
01863             /* Call Mm for the update */
01864             Status = MmSetExecuteOptions(NoExecute);
01865             break;
01866 
01867         /* We currently don't implement any of these */
01868         case ProcessLdtInformation:
01869         case ProcessLdtSize:
01870         case ProcessIoPortHandlers:
01871              DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass);
01872              Status = STATUS_NOT_IMPLEMENTED;
01873              break;
01874 
01875         case ProcessQuotaLimits:
01876             DPRINT1("Quota Limits not implemented\n");
01877             Status = STATUS_NOT_IMPLEMENTED;
01878             break;
01879 
01880         case ProcessWorkingSetWatch:
01881             DPRINT1("WS watch not implemented\n");
01882             Status = STATUS_NOT_IMPLEMENTED;
01883             break;
01884 
01885         case ProcessDeviceMap:
01886             DPRINT1("Device map not implemented\n");
01887             Status = STATUS_NOT_IMPLEMENTED;
01888             break;
01889 
01890         case ProcessHandleTracing:
01891             DPRINT1("Handle tracing not implemented\n");
01892             Status = STATUS_NOT_IMPLEMENTED;
01893             break;
01894 
01895         /* Anything else is invalid */
01896         default:
01897             DPRINT1("Invalid Server 2003 Info Class: %lx\n", ProcessInformationClass);
01898             Status = STATUS_INVALID_INFO_CLASS;
01899     }
01900 
01901     /* Dereference and return status */
01902     ObDereferenceObject(Process);
01903     return Status;
01904 }
01905 
01906 /*
01907  * @implemented
01908  */
01909 NTSTATUS
01910 NTAPI
01911 NtSetInformationThread(IN HANDLE ThreadHandle,
01912                        IN THREADINFOCLASS ThreadInformationClass,
01913                        IN PVOID ThreadInformation,
01914                        IN ULONG ThreadInformationLength)
01915 {
01916     PETHREAD Thread;
01917     ULONG Access;
01918     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
01919     NTSTATUS Status;
01920     HANDLE TokenHandle = NULL;
01921     KPRIORITY Priority = 0;
01922     KAFFINITY Affinity = 0, CombinedAffinity;
01923     PVOID Address = NULL;
01924     PEPROCESS Process;
01925     ULONG_PTR DisableBoost = 0;
01926     ULONG_PTR IdealProcessor = 0;
01927     ULONG_PTR Break = 0;
01928     PTEB Teb;
01929     ULONG_PTR TlsIndex = 0;
01930     PVOID *ExpansionSlots;
01931     PETHREAD ProcThread;
01932     PAGED_CODE();
01933 
01934     /* Verify Information Class validity */
01935 #if 0
01936     Status = DefaultSetInfoBufferCheck(ThreadInformationClass,
01937                                        PsThreadInfoClass,
01938                                        RTL_NUMBER_OF(PsThreadInfoClass),
01939                                        ThreadInformation,
01940                                        ThreadInformationLength,
01941                                        PreviousMode);
01942     if (!NT_SUCCESS(Status)) return Status;
01943 #endif
01944 
01945     /* Check what class this is */
01946     Access = THREAD_SET_INFORMATION;
01947     if (ThreadInformationClass == ThreadImpersonationToken)
01948     {
01949         /* Setting the impersonation token needs a special mask */
01950         Access = THREAD_SET_THREAD_TOKEN;
01951     }
01952 
01953     /* Reference the thread */
01954     Status = ObReferenceObjectByHandle(ThreadHandle,
01955                                        Access,
01956                                        PsThreadType,
01957                                        PreviousMode,
01958                                        (PVOID*)&Thread,
01959                                        NULL);
01960     if (!NT_SUCCESS(Status)) return Status;
01961 
01962     /* Check what kind of information class this is */
01963     switch (ThreadInformationClass)
01964     {
01965         /* Thread priority */
01966         case ThreadPriority:
01967 
01968             /* Check buffer length */
01969             if (ThreadInformationLength != sizeof(KPRIORITY))
01970             {
01971                 Status = STATUS_INFO_LENGTH_MISMATCH;
01972                 break;
01973             }
01974 
01975             /* Use SEH for capture */
01976             _SEH2_TRY
01977             {
01978                 /* Get the priority */
01979                 Priority = *(PLONG)ThreadInformation;
01980             }
01981             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01982             {
01983                 /* Get the exception code */
01984                 Status = _SEH2_GetExceptionCode();
01985                 _SEH2_YIELD(break);
01986             }
01987             _SEH2_END;
01988 
01989             /* Validate it */
01990             if ((Priority > HIGH_PRIORITY) ||
01991                 (Priority <= LOW_PRIORITY))
01992             {
01993                 /* Fail */
01994                 Status = STATUS_INVALID_PARAMETER;
01995                 break;
01996             }
01997 
01998             /* Set the priority */
01999             KeSetPriorityThread(&Thread->Tcb, Priority);
02000             break;
02001 
02002         case ThreadBasePriority:
02003 
02004             /* Check buffer length */
02005             if (ThreadInformationLength != sizeof(LONG))
02006             {
02007                 Status = STATUS_INFO_LENGTH_MISMATCH;
02008                 break;
02009             }
02010 
02011             /* Use SEH for capture */
02012             _SEH2_TRY
02013             {
02014                 /* Get the priority */
02015                 Priority = *(PLONG)ThreadInformation;
02016             }
02017             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
02018             {
02019                 /* Get the exception code */
02020                 Status = _SEH2_GetExceptionCode();
02021                 _SEH2_YIELD(break);
02022             }
02023             _SEH2_END;
02024 
02025             /* Validate it */
02026             if ((Priority > THREAD_BASE_PRIORITY_MAX) ||
02027                 (Priority < THREAD_BASE_PRIORITY_MIN))
02028             {
02029                 /* These ones are OK */
02030                 if ((Priority != THREAD_BASE_PRIORITY_LOWRT + 1) &&
02031                     (Priority != THREAD_BASE_PRIORITY_IDLE - 1))
02032                 {
02033                     /* Check if the process is real time */
02034                     if (PsGetCurrentProcess()->PriorityClass !=
02035                         PROCESS_PRIORITY_CLASS_REALTIME)
02036                     {
02037                         /* It isn't, fail */
02038                         Status = STATUS_INVALID_PARAMETER;
02039                         break;
02040                     }
02041                 }
02042             }
02043 
02044             /* Set the base priority */
02045             KeSetBasePriorityThread(&Thread->Tcb, Priority);
02046             break;
02047 
02048         case ThreadAffinityMask:
02049 
02050             /* Check buffer length */
02051             if (ThreadInformationLength != sizeof(ULONG_PTR))
02052             {
02053                 Status = STATUS_INFO_LENGTH_MISMATCH;
02054                 break;
02055             }
02056 
02057             /* Use SEH for capture */
02058             _SEH2_TRY
02059             {
02060                 /* Get the priority */
02061                 Affinity = *(PULONG_PTR)ThreadInformation;
02062             }
02063             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
02064             {
02065                 /* Get the exception code */
02066                 Status = _SEH2_GetExceptionCode();
02067                 _SEH2_YIELD(break);
02068             }
02069             _SEH2_END;
02070 
02071             /* Validate it */
02072             if (!Affinity)
02073             {
02074                 /* Fail */
02075                 Status = STATUS_INVALID_PARAMETER;
02076                 break;
02077             }
02078 
02079             /* Get the process */
02080             Process = Thread->ThreadsProcess;
02081 
02082             /* Try to acquire rundown */
02083             if (ExAcquireRundownProtection(&Process->RundownProtect))
02084             {
02085                 /* Lock it */
02086                 KeEnterCriticalRegion();
02087                 ExAcquirePushLockShared(&Process->ProcessLock);
02088 
02089                 /* Combine masks */
02090                 CombinedAffinity = Affinity & Process->Pcb.Affinity;
02091                 if (CombinedAffinity != Affinity)
02092                 {
02093                     /* Fail */
02094                     Status = STATUS_INVALID_PARAMETER;
02095                 }
02096                 else
02097                 {
02098                     /* Set the affinity */
02099                     KeSetAffinityThread(&Thread->Tcb, CombinedAffinity);
02100                 }
02101 
02102                 /* Release the lock and rundown */
02103                 ExReleasePushLockShared(&Process->ProcessLock);
02104                 KeLeaveCriticalRegion();
02105                 ExReleaseRundownProtection(&Process->RundownProtect);
02106             }
02107             else
02108             {
02109                 /* Too late */
02110                 Status = STATUS_PROCESS_IS_TERMINATING;
02111             }
02112 
02113             /* Return status */
02114             break;
02115 
02116         case ThreadImpersonationToken:
02117 
02118             /* Check buffer length */
02119             if (ThreadInformationLength != sizeof(HANDLE))
02120             {
02121                 Status = STATUS_INFO_LENGTH_MISMATCH;
02122                 break;
02123             }
02124 
02125             /* Use SEH for capture */
02126             _SEH2_TRY
02127             {
02128                 /* Save the token handle */
02129                 TokenHandle = *(PHANDLE)ThreadInformation;
02130             }
02131             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
02132             {
02133                 /* Get the exception code */
02134                 Status = _SEH2_GetExceptionCode();
02135                 _SEH2_YIELD(break);
02136             }
02137             _SEH2_END;
02138 
02139             /* Assign the actual token */
02140             Status = PsAssignImpersonationToken(Thread, TokenHandle);
02141             break;
02142 
02143         case ThreadQuerySetWin32StartAddress:
02144 
02145             /* Check buffer length */
02146             if (ThreadInformationLength != sizeof(ULONG_PTR))
02147             {
02148                 Status = STATUS_INFO_LENGTH_MISMATCH;
02149                 break;
02150             }
02151 
02152             /* Use SEH for capture */
02153             _SEH2_TRY
02154             {
02155                 /* Get the priority */
02156                 Address = *(PVOID*)ThreadInformation;
02157             }
02158             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
02159             {
02160                 /* Get the exception code */
02161                 Status = _SEH2_GetExceptionCode();
02162                 _SEH2_YIELD(break);
02163             }
02164             _SEH2_END;
02165 
02166             /* Set the address */
02167             Thread->Win32StartAddress = Address;
02168             break;
02169 
02170         case ThreadIdealProcessor:
02171 
02172             /* Check buffer length */
02173             if (ThreadInformationLength != sizeof(ULONG_PTR))
02174             {
02175                 Status = STATUS_INFO_LENGTH_MISMATCH;
02176                 break;
02177             }
02178 
02179             /* Use SEH for capture */
02180             _SEH2_TRY
02181             {
02182                 /* Get the priority */
02183                 IdealProcessor = *(PULONG_PTR)ThreadInformation;
02184             }
02185             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
02186             {
02187                 /* Get the exception code */
02188                 Status = _SEH2_GetExceptionCode();
02189                 _SEH2_YIELD(break);
02190             }
02191             _SEH2_END;
02192 
02193             /* Validate it */
02194             if (IdealProcessor > MAXIMUM_PROCESSORS)
02195             {
02196                 /* Fail */
02197                 Status = STATUS_INVALID_PARAMETER;
02198                 break;
02199             }
02200 
02201             /* Set the ideal */
02202             Status = KeSetIdealProcessorThread(&Thread->Tcb,
02203                                                (CCHAR)IdealProcessor);
02204 
02205             /* Get the TEB and protect the thread */
02206             Teb = Thread->Tcb.Teb;
02207             if ((Teb) && (ExAcquireRundownProtection(&Thread->RundownProtect)))
02208             {
02209                 /* Save the ideal processor */
02210                 Teb->IdealProcessor = Thread->Tcb.IdealProcessor;
02211 
02212                 /* Release rundown protection */
02213                 ExReleaseRundownProtection(&Thread->RundownProtect);
02214             }
02215 
02216             break;
02217 
02218         case ThreadPriorityBoost:
02219 
02220             /* Check buffer length */
02221             if (ThreadInformationLength != sizeof(ULONG_PTR))
02222             {
02223                 Status = STATUS_INFO_LENGTH_MISMATCH;
02224                 break;
02225             }
02226 
02227             /* Use SEH for capture */
02228             _SEH2_TRY
02229             {
02230                 /* Get the priority */
02231                 DisableBoost = *(PULONG_PTR)ThreadInformation;
02232             }
02233             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
02234             {
02235                 /* Get the exception code */
02236                 Status = _SEH2_GetExceptionCode();
02237                 _SEH2_YIELD(break);
02238             }
02239             _SEH2_END;
02240 
02241             /* Call the kernel */
02242             KeSetDisableBoostThread(&Thread->Tcb, (BOOLEAN)DisableBoost);
02243             break;
02244 
02245         case ThreadZeroTlsCell:
02246 
02247             /* Check buffer length */
02248             if (ThreadInformationLength != sizeof(ULONG_PTR))
02249             {
02250                 Status = STATUS_INFO_LENGTH_MISMATCH;
02251                 break;
02252             }
02253 
02254             /* Use SEH for capture */
02255             _SEH2_TRY
02256             {
02257                 /* Get the priority */
02258                 TlsIndex = *(PULONG_PTR)ThreadInformation;
02259             }
02260             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
02261             {
02262                 /* Get the exception code */
02263                 Status = _SEH2_GetExceptionCode();
02264                 _SEH2_YIELD(break);
02265             }
02266             _SEH2_END;
02267 
02268             /* This is only valid for the current thread */
02269             if (Thread != PsGetCurrentThread())
02270             {
02271                 /* Fail */
02272                 Status = STATUS_INVALID_PARAMETER;
02273                 break;
02274             }
02275 
02276             /* Get the process */
02277             Process = Thread->ThreadsProcess;
02278 
02279             /* Loop the threads */
02280             ProcThread = PsGetNextProcessThread(Process, NULL);
02281             while (ProcThread)
02282             {
02283                 /* Acquire rundown */
02284                 if (ExAcquireRundownProtection(&ProcThread->RundownProtect))
02285                 {
02286                     /* Get the TEB */
02287                     Teb = ProcThread->Tcb.Teb;
02288                     if (Teb)
02289                     {
02290                         /* Check if we're in the expansion range */
02291                         if (TlsIndex > TLS_MINIMUM_AVAILABLE - 1)
02292                         {
02293                             if (TlsIndex < (TLS_MINIMUM_AVAILABLE +
02294                                             TLS_EXPANSION_SLOTS) - 1)
02295                             {
02296                                 /* Check if we have expansion slots */
02297                                 ExpansionSlots = Teb->TlsExpansionSlots;
02298                                 if (ExpansionSlots)
02299                                 {
02300                                     /* Clear the index */
02301                                     ExpansionSlots[TlsIndex - TLS_MINIMUM_AVAILABLE] = 0;
02302                                 }
02303                             }
02304                         }
02305                         else
02306                         {
02307                             /* Clear the index */
02308                             Teb->TlsSlots[TlsIndex] = NULL;
02309                         }
02310                     }
02311 
02312                     /* Release rundown */
02313                     ExReleaseRundownProtection(&ProcThread->RundownProtect);
02314                 }
02315 
02316                 /* Go to the next thread */
02317                 ProcThread = PsGetNextProcessThread(Process, ProcThread);
02318             }
02319 
02320             /* All done */
02321             break;
02322 
02323         case ThreadBreakOnTermination:
02324 
02325             /* Check buffer length */
02326             if (ThreadInformationLength != sizeof(ULONG))
02327             {
02328                 Status = STATUS_INFO_LENGTH_MISMATCH;
02329                 break;
02330             }
02331 
02332             /* Enter SEH for direct buffer read */
02333             _SEH2_TRY
02334             {
02335                 Break = *(PULONG)ThreadInformation;
02336             }
02337             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
02338             {
02339                 /* Get exception code */
02340                 Break = 0;
02341                 Status = _SEH2_GetExceptionCode();
02342                 _SEH2_YIELD(break);
02343             }
02344             _SEH2_END;
02345 
02346             /* Setting 'break on termination' requires the SeDebugPrivilege */
02347             if (!SeSinglePrivilegeCheck(SeDebugPrivilege, PreviousMode))
02348             {
02349                 Status = STATUS_PRIVILEGE_NOT_HELD;
02350                 break;
02351             }
02352 
02353             /* Set or clear the flag */
02354             if (Break)
02355             {
02356                 PspSetCrossThreadFlag(Thread, CT_BREAK_ON_TERMINATION_BIT);
02357             }
02358             else
02359             {
02360                 PspClearCrossThreadFlag(Thread, CT_BREAK_ON_TERMINATION_BIT);
02361             }
02362             break;
02363 
02364         default:
02365             /* We don't implement it yet */
02366             DPRINT1("Not implemented: %d\n", ThreadInformationClass);
02367             Status = STATUS_NOT_IMPLEMENTED;
02368     }
02369 
02370     /* Dereference and return status */
02371     ObDereferenceObject(Thread);
02372     return Status;
02373 }
02374 
02375 /*
02376  * @implemented
02377  */
02378 NTSTATUS
02379 NTAPI
02380 NtQueryInformationThread(IN HANDLE ThreadHandle,
02381                          IN THREADINFOCLASS ThreadInformationClass,
02382                          OUT PVOID ThreadInformation,
02383                          IN ULONG ThreadInformationLength,
02384                          OUT PULONG ReturnLength OPTIONAL)
02385 {
02386     PETHREAD Thread;
02387     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
02388     NTSTATUS Status;
02389     ULONG Access;
02390     ULONG Length = 0;
02391     PTHREAD_BASIC_INFORMATION ThreadBasicInfo =
02392         (PTHREAD_BASIC_INFORMATION)ThreadInformation;
02393     PKERNEL_USER_TIMES ThreadTime = (PKERNEL_USER_TIMES)ThreadInformation;
02394     KIRQL OldIrql;
02395     PAGED_CODE();
02396 
02397     /* Check if we were called from user mode */
02398     if (PreviousMode != KernelMode)
02399     {
02400         /* Enter SEH */
02401         _SEH2_TRY
02402         {
02403             /* Probe the buffer */
02404             ProbeForWrite(ThreadInformation,
02405                           ThreadInformationLength,
02406                           sizeof(ULONG));
02407 
02408             /* Probe the return length if required */
02409             if (ReturnLength) ProbeForWriteUlong(ReturnLength);
02410         }
02411         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
02412         {
02413             /* Return the exception code */
02414             _SEH2_YIELD(return _SEH2_GetExceptionCode());
02415         }
02416         _SEH2_END;
02417     }
02418 
02419     /* Check what class this is */
02420     Access = THREAD_QUERY_INFORMATION;
02421 
02422     /* Reference the process */
02423     Status = ObReferenceObjectByHandle(ThreadHandle,
02424                                        Access,
02425                                        PsThreadType,
02426                                        PreviousMode,
02427                                        (PVOID*)&Thread,
02428                                        NULL);
02429     if (!NT_SUCCESS(Status)) return Status;
02430 
02431     /* Check what kind of information class this is */
02432     switch (ThreadInformationClass)
02433     {
02434         /* Basic thread information */
02435         case ThreadBasicInformation:
02436 
02437             /* Set return length */
02438             Length = sizeof(THREAD_BASIC_INFORMATION);
02439 
02440             if (ThreadInformationLength != Length)
02441             {
02442                 Status = STATUS_INFO_LENGTH_MISMATCH;
02443                 break;
02444             }
02445             /* Protect writes with SEH */
02446             _SEH2_TRY
02447             {
02448                 /* Write all the information from the ETHREAD/KTHREAD */
02449                 ThreadBasicInfo->ExitStatus = Thread->ExitStatus;
02450                 ThreadBasicInfo->TebBaseAddress = (PVOID)Thread->Tcb.Teb;
02451                 ThreadBasicInfo->ClientId = Thread->Cid;
02452                 ThreadBasicInfo->AffinityMask = Thread->Tcb.Affinity;
02453                 ThreadBasicInfo->Priority = Thread->Tcb.Priority;
02454                 ThreadBasicInfo->BasePriority = KeQueryBasePriorityThread(&Thread->Tcb);
02455             }
02456             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
02457             {
02458                 /* Get exception code */
02459                 Status = _SEH2_GetExceptionCode();
02460             }
02461             _SEH2_END;
02462             break;
02463 
02464         /* Thread time information */
02465         case ThreadTimes:
02466 
02467             /* Set the return length */
02468             Length = sizeof(KERNEL_USER_TIMES);
02469 
02470             if (ThreadInformationLength != Length)
02471             {
02472                 Status = STATUS_INFO_LENGTH_MISMATCH;
02473                 break;
02474             }
02475             /* Protect writes with SEH */
02476             _SEH2_TRY
02477             {
02478                 /* Copy time information from ETHREAD/KTHREAD */
02479                 ThreadTime->KernelTime.QuadPart = Thread->Tcb.KernelTime * KeMaximumIncrement;
02480                 ThreadTime->UserTime.QuadPart = Thread->Tcb.UserTime * KeMaximumIncrement;
02481                 ThreadTime->CreateTime = Thread->CreateTime;
02482 
02483                 /* Exit time is in a union and only valid on actual exit! */
02484                 if (KeReadStateThread(&Thread->Tcb))
02485                 {
02486                     ThreadTime->ExitTime = Thread->ExitTime;
02487                 }
02488                 else
02489                 {
02490                     ThreadTime->ExitTime.QuadPart = 0;
02491                 }
02492             }
02493             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
02494             {
02495                 /* Get exception code */
02496                 Status = _SEH2_GetExceptionCode();
02497             }
02498             _SEH2_END;
02499             break;
02500 
02501         case ThreadQuerySetWin32StartAddress:
02502 
02503             /* Set the return length*/
02504             Length = sizeof(PVOID);
02505 
02506             if (ThreadInformationLength != Length)
02507             {
02508                 Status = STATUS_INFO_LENGTH_MISMATCH;
02509                 break;
02510             }
02511             /* Protect write with SEH */
02512             _SEH2_TRY
02513             {
02514                 /* Return the Win32 Start Address */
02515                 *(PVOID*)ThreadInformation = Thread->Win32StartAddress;
02516             }
02517             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
02518             {
02519                 /* Get exception code */
02520                 Status = _SEH2_GetExceptionCode();
02521             }
02522             _SEH2_END;
02523             break;
02524 
02525         case ThreadPerformanceCount:
02526 
02527             /* Set the return length*/
02528             Length = sizeof(LARGE_INTEGER);
02529 
02530             if (ThreadInformationLength != Length)
02531             {
02532                 Status = STATUS_INFO_LENGTH_MISMATCH;
02533                 break;
02534             }
02535             /* Protect write with SEH */
02536             _SEH2_TRY
02537             {
02538                 /* FIXME */
02539                 (*(PLARGE_INTEGER)ThreadInformation).QuadPart = 0;
02540             }
02541             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
02542             {
02543                 /* Get exception code */
02544                 Status = _SEH2_GetExceptionCode();
02545             }
02546             _SEH2_END;
02547             break;
02548 
02549         case ThreadAmILastThread:
02550 
02551             /* Set the return length*/
02552             Length = sizeof(ULONG);
02553 
02554             if (ThreadInformationLength != Length)
02555             {
02556                 Status = STATUS_INFO_LENGTH_MISMATCH;
02557                 break;
02558             }
02559             /* Protect write with SEH */
02560             _SEH2_TRY
02561             {
02562                 /* Return whether or not we are the last thread */
02563                 *(PULONG)ThreadInformation = ((Thread->ThreadsProcess->
02564                                                ThreadListHead.Flink->Flink ==
02565                                                &Thread->ThreadsProcess->
02566                                                ThreadListHead) ?
02567                                               TRUE : FALSE);
02568             }
02569             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
02570             {
02571                 /* Get exception code */
02572                 Status = _SEH2_GetExceptionCode();
02573             }
02574             _SEH2_END;
02575             break;
02576 
02577         case ThreadIsIoPending:
02578 
02579             /* Set the return length*/
02580             Length = sizeof(ULONG);
02581 
02582             if (ThreadInformationLength != Length)
02583             {
02584                 Status = STATUS_INFO_LENGTH_MISMATCH;
02585                 break;
02586             }
02587             /* Raise the IRQL to protect the IRP list */
02588             KeRaiseIrql(APC_LEVEL, &OldIrql);
02589 
02590             /* Protect write with SEH */
02591             _SEH2_TRY
02592             {
02593                 /* Check if the IRP list is empty or not */
02594                 *(PULONG)ThreadInformation = !IsListEmpty(&Thread->IrpList);
02595             }
02596             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
02597             {
02598                 /* Get exception code */
02599                 Status = _SEH2_GetExceptionCode();
02600             }
02601             _SEH2_END;
02602 
02603             /* Lower IRQL back */
02604             KeLowerIrql(OldIrql);
02605             break;
02606 
02607         /* LDT and GDT information */
02608         case ThreadDescriptorTableEntry:
02609 
02610 #if defined(_X86_)
02611             /* Call the worker routine */
02612             Status = PspQueryDescriptorThread(Thread,
02613                                               ThreadInformation,
02614                                               ThreadInformationLength,
02615                                               ReturnLength);
02616 #else
02617             /* Only implemented on x86 */
02618             Status = STATUS_NOT_IMPLEMENTED;
02619 #endif
02620             break;
02621 
02622         case ThreadPriorityBoost:
02623 
02624             /* Set the return length*/
02625             Length = sizeof(ULONG);
02626 
02627             if (ThreadInformationLength != Length)
02628             {
02629                 Status = STATUS_INFO_LENGTH_MISMATCH;
02630                 break;
02631             }
02632 
02633             _SEH2_TRY
02634             {
02635                 *(PULONG)ThreadInformation = Thread->Tcb.DisableBoost ? 1 : 0;
02636             }
02637             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
02638             {
02639                 Status = _SEH2_GetExceptionCode();
02640             }
02641             _SEH2_END;
02642             break;
02643 
02644         /* Anything else */
02645         default:
02646 
02647             /* Not yet implemented */
02648             DPRINT1("Not implemented: %lx\n", ThreadInformationClass);
02649             Status = STATUS_NOT_IMPLEMENTED;
02650     }
02651 
02652     /* Protect write with SEH */
02653     _SEH2_TRY
02654     {
02655         /* Check if caller wanted return length */
02656         if (ReturnLength) *ReturnLength = Length;
02657     }
02658     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
02659     {
02660         /* Get exception code */
02661         Status = _SEH2_GetExceptionCode();
02662     }
02663     _SEH2_END;
02664 
02665     /* Dereference the thread, and return */
02666     ObDereferenceObject(Thread);
02667     return Status;
02668 }
02669 
02670 /* EOF */

Generated on Sun May 27 2012 04:17:03 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.