Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenquery.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
1.7.6.1
|