Легенда:
новое сообщение
закрытая нитка
новое сообщение
в закрытой нитке
старое сообщение
|
- Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
- Новичкам также крайне полезно ознакомиться с данным документом.
вот NtSetInformationThread ее и вызыват (см внутри) 11.05.05 16:03 Число просмотров: 6695
Автор: Killer{R} <Dmitry> Статус: Elderman
|
NTSTATUS
NtSetInformationThread(
IN HANDLE ThreadHandle,
IN THREADINFOCLASS ThreadInformationClass,
IN PVOID ThreadInformation,
IN ULONG ThreadInformationLength
)
/*++
Routine Description:
This function sets the state of a thread object.
Arguments:
ThreadHandle - Supplies a handle to a thread object.
ThreadInformationClass - Supplies the class of information being
set.
ThreadInformation - Supplies a pointer to a record that contains the
information to set.
ThreadInformationLength - Supplies the length of the record that contains
the information to set.
Return Value:
TBS
--*/
{
PEEVENT_PAIR EventPair;
HANDLE EventPairHandle;
PETHREAD Thread;
PEPROCESS Process;
KPROCESSOR_MODE PreviousMode;
NTSTATUS st;
KAFFINITY Affinity, AffinityWithMasks;
ULONG_PTR BigAffinity;
KPRIORITY Priority;
LONG BasePriority;
ULONG TlsIndex;
PVOID TlsArrayAddress;
PVOID Win32StartAddressValue;
ULONG ProbeAlignment;
BOOLEAN EnableAlignmentFaultFixup;
ULONG IdealProcessor;
ULONG DisableBoost;
PVOID *ExpansionSlots;
HANDLE ImpersonationTokenHandle;
BOOLEAN HasPrivilege;
PAGED_CODE();
//
// Get previous processor mode and probe input argument if necessary.
//
PreviousMode = KeGetPreviousMode();
if (PreviousMode != KernelMode) {
try {
switch (ThreadInformationClass) {
case ThreadPriority :
ProbeAlignment = sizeof(KPRIORITY);
break;
case ThreadAffinityMask :
case ThreadQuerySetWin32StartAddress :
ProbeAlignment = sizeof (ULONG_PTR);
break;
case ThreadEnableAlignmentFaultFixup :
ProbeAlignment = sizeof (BOOLEAN);
break;
default :
ProbeAlignment = sizeof(ULONG);
}
ProbeForRead(
ThreadInformation,
ThreadInformationLength,
ProbeAlignment
);
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
}
//
// Check argument validity.
//
switch ( ThreadInformationClass ) {
case ThreadPriority:
if ( ThreadInformationLength != sizeof(KPRIORITY) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}
try {
Priority = *(KPRIORITY *)ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
if ( Priority > HIGH_PRIORITY| Priority <= LOW_PRIORITY ) {
return STATUS_INVALID_PARAMETER;
}
if ( Priority >= LOW_REALTIME_PRIORITY ) {
//
// Increasing the priority of a thread beyond
// LOW_REALTIME_PRIORITY is a privileged operation.
//
HasPrivilege = SeCheckPrivilegedObject(
SeIncreaseBasePriorityPrivilege,
ThreadHandle,
THREAD_SET_INFORMATION,
PreviousMode
);
if (!HasPrivilege) {
return STATUS_PRIVILEGE_NOT_HELD;
}
}
st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);
if ( !NT_SUCCESS(st) ) {
return st;
}
Process = THREAD_TO_PROCESS(Thread);
KeSetPriorityThread(&Thread->Tcb,Priority);
ObDereferenceObject(Thread);
return STATUS_SUCCESS;
case ThreadBasePriority:
if ( ThreadInformationLength != sizeof(LONG) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}
try {
BasePriority = *(PLONG)ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);
if ( !NT_SUCCESS(st) ) {
return st;
}
Process = THREAD_TO_PROCESS(Thread);
if ( BasePriority > THREAD_BASE_PRIORITY_MAX| BasePriority < THREAD_BASE_PRIORITY_MIN ) {
if ( BasePriority == THREAD_BASE_PRIORITY_LOWRT+1| BasePriority == THREAD_BASE_PRIORITY_IDLE-1 ) {
;
}
else {
//
// Allow csrss, or realtime processes to select any
// priority
//
if ( PsGetCurrentProcess() == ExpDefaultErrorPortProcess| Process->PriorityClass == PROCESS_PRIORITY_CLASS_REALTIME ){
;
}
else {
ObDereferenceObject(Thread);
return STATUS_INVALID_PARAMETER;
}
}
}
//
// If the thread is running within a job object, and the job
// object has a priority class limit, do not allow
// priority adjustments that raise the thread's priority, unless
// the priority class is realtime
//
if ( Process->Job && (Process->Job->LimitFlags & JOB_OBJECT_LIMIT_PRIORITY_CLASS) ) {
if ( Process->PriorityClass != PROCESS_PRIORITY_CLASS_REALTIME ){
if ( BasePriority > 0 ) {
ObDereferenceObject(Thread);
return STATUS_SUCCESS;
}
}
}
KeSetBasePriorityThread(&Thread->Tcb,BasePriority);
ObDereferenceObject(Thread);
return STATUS_SUCCESS;
case ThreadEnableAlignmentFaultFixup:
if ( ThreadInformationLength != sizeof(BOOLEAN) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}
try {
EnableAlignmentFaultFixup = *(PBOOLEAN)ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);
if ( !NT_SUCCESS(st) ) {
return st;
}
KeSetAutoAlignmentThread( &(Thread->Tcb), EnableAlignmentFaultFixup );
ObDereferenceObject(Thread);
return STATUS_SUCCESS;
case ThreadAffinityMask:
if ( ThreadInformationLength != sizeof(ULONG_PTR) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}
try {
BigAffinity = *(ULONG_PTR *) ThreadInformation;
Affinity = (KAFFINITY) BigAffinity;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
if ( !Affinity ) {
return STATUS_INVALID_PARAMETER;
}
st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);
if ( !NT_SUCCESS(st) ) {
return st;
}
Process = THREAD_TO_PROCESS(Thread);
//
// the following allows this api to properly if
// called while the exiting process is blocked holding the
// createdeletelock. This can happen during debugger/server
// lpc transactions that occur in pspexitthread
//
st = PsLockProcess(Process,PreviousMode,PsLockPollOnTimeout);
if ( st != STATUS_SUCCESS ) {
ObDereferenceObject(Thread);
return STATUS_PROCESS_IS_TERMINATING;
}
AffinityWithMasks = Affinity & Process->Pcb.Affinity;
if ( AffinityWithMasks != Affinity ) {
st = STATUS_INVALID_PARAMETER;
} else {
KeSetAffinityThread(
&Thread->Tcb,
AffinityWithMasks
);
st = STATUS_SUCCESS;
}
PsUnlockProcess(Process);
ObDereferenceObject(Thread);
return st;
case ThreadImpersonationToken:
if ( ThreadInformationLength != sizeof(HANDLE) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}
try {
ImpersonationTokenHandle = *(PHANDLE) ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_THREAD_TOKEN,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);
if ( !NT_SUCCESS(st) ) {
return st;
}
//
// Check for proper access to (and type of) the token, and assign
// it as the thread's impersonation token.
//
st = PsAssignImpersonationToken( Thread, ImpersonationTokenHandle );
ObDereferenceObject(Thread);
return st;
case ThreadQuerySetWin32StartAddress:
if ( ThreadInformationLength != sizeof(ULONG_PTR) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}
try {
Win32StartAddressValue = *(PVOID *) ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);
if ( !NT_SUCCESS(st) ) {
return st;
}
Thread->Win32StartAddress = (PVOID)Win32StartAddressValue;
ObDereferenceObject(Thread);
return st;
case ThreadIdealProcessor:
if ( ThreadInformationLength != sizeof(ULONG) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}
try {
IdealProcessor = *(PULONG)ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
if ( IdealProcessor > MAXIMUM_PROCESSORS ) {
return STATUS_INVALID_PARAMETER;
}
st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);
if ( !NT_SUCCESS(st) ) {
return st;
}
//
// this is sort of a slimey way of returning info from this set only
// api
//
st = (NTSTATUS)KeSetIdealProcessorThread(&Thread->Tcb,(CCHAR)IdealProcessor);
ObDereferenceObject(Thread);
return st;
case ThreadPriorityBoost:
if ( ThreadInformationLength != sizeof(ULONG) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}
try {
DisableBoost = *(PULONG)ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);
if ( !NT_SUCCESS(st) ) {
return st;
}
KeSetDisableBoostThread(&Thread->Tcb,DisableBoost ? TRUE : FALSE);
ObDereferenceObject(Thread);
return st;
case ThreadZeroTlsCell:
if ( ThreadInformationLength != sizeof(ULONG) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}
try {
TlsIndex = *(PULONG) ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);
if ( !NT_SUCCESS(st) ) {
return st;
}
if ( Thread != PsGetCurrentThread() ) {
ObDereferenceObject( Thread );
return STATUS_INVALID_PARAMETER;
}
{
NTSTATUS xst;
PTEB Teb;
PLIST_ENTRY Next;
PETHREAD OriginalThread;
OriginalThread = Thread;
Process = THREAD_TO_PROCESS(Thread);
//
// the following allows this api to properly if
// called while the exiting process is blocked holding the
// createdeletelock. This can happen during debugger/server
// lpc transactions that occur in pspexitthread
//
xst = PsLockProcess(Process,PreviousMode,PsLockPollOnTimeout);
if ( xst != STATUS_SUCCESS ) {
ObDereferenceObject( OriginalThread );
return STATUS_PROCESS_IS_TERMINATING;
}
// The 32bit TEB needs to be set if this is a WOW64 process on a 64BIT system.
// This code isn't 100% correct since threads have a conversion state where they
// are chaning from 64 to 32 and they don't have a TEB32 yet. Fortunatly, the slots
// will be zero when the thread is created so no damage is done by not clearing it here.
// Note that the test for the process type is inside the inner loop. This
// is bad programming, but this function is hardly time constrained and
// fixing this with complex macros would not be worth it due to the loss of clairity.
Next = Process->ThreadListHead.Flink;
while ( Next != &Process->ThreadListHead) {
Thread = (PETHREAD)(CONTAINING_RECORD(Next,ETHREAD,ThreadListEntry));
if ( !IS_SYSTEM_THREAD(Thread) ) {
if ( Thread->Tcb.Teb ) {
Teb = (PTEB)Thread->Tcb.Teb;
if ( TlsIndex > TLS_MINIMUM_AVAILABLE-1 ) {
if ( TlsIndex < (TLS_MINIMUM_AVAILABLE+TLS_EXPANSION_SLOTS) - 1 ) {
//
// This is an expansion slot, so see if the thread
// has an expansion cell
//
try {
#if defined(_WIN64)
if (Process->Wow64Process) { //Wow64 process.
PTEB32 Teb32;
PLONG ExpansionSlots32;
Teb32 = WOW64_GET_TEB32(Teb); //No probing needed on regular TEB.
if (Teb32) {
ExpansionSlots32 = ULongToPtr(ProbeAndReadLong(&(Teb32->TlsExpansionSlots)));
if (ExpansionSlots32) {
ProbeAndWriteLong(ExpansionSlots32 + TlsIndex - TLS_MINIMUM_AVAILABLE, 0);
}
}
}
else
#endif
{
ExpansionSlots = Teb->TlsExpansionSlots;
ProbeForRead(ExpansionSlots,TLS_EXPANSION_SLOTS*4,8);
if ( ExpansionSlots ) {
ExpansionSlots[TlsIndex-TLS_MINIMUM_AVAILABLE] = 0;
}
}
}
except(EXCEPTION_EXECUTE_HANDLER) {
;
}
}
}
else {
try {
#if defined(_WIN64)
if (Process->Wow64Process) { //wow64 process
PTEB32 Teb32;
Teb32 = WOW64_GET_TEB32(Teb); //No probing needed on regular TEB.
if(Teb32) {
ProbeAndWriteLong(Teb32->TlsSlots + TlsIndex, 0);
}
}
else
#endif
{
Teb->TlsSlots[TlsIndex] = NULL;
}
}
except(EXCEPTION_EXECUTE_HANDLER) {
;
}
}
}
}
Next = Next->Flink;
}
PsUnlockProcess(Process);
ObDereferenceObject(OriginalThread);
}
return st;
break;
case ThreadSetTlsArrayAddress:
if ( ThreadInformationLength != sizeof(PVOID) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}
try {
TlsArrayAddress = *(PVOID *)ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);
if ( !NT_SUCCESS(st) ) {
return st;
}
Thread->Tcb.TlsArray = TlsArrayAddress;
#if definedMIPS
if (Thread == PsGetCurrentThread()) {
PCR->TlsArray = TlsArrayAddress;
}
#endif
ObDereferenceObject(Thread);
return st;
break;
case ThreadHideFromDebugger:
if ( ThreadInformationLength != 0 ) {
return STATUS_INFO_LENGTH_MISMATCH;
}
st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);
if ( !NT_SUCCESS(st) ) {
return st;
}
Thread->HideFromDebugger = TRUE;
ObDereferenceObject(Thread);
return st;
break;
default:
return STATUS_INVALID_INFO_CLASS;
}
}
+ к этому описалово к
NTSTATUS
PsLockProcess(
IN PEPROCESS Process,
IN KPROCESSOR_MODE WaitMode,
IN PSLOCKPROCESSMODE LockMode
)
/*++
Routine Description:
This function is used to lock the process from create/delete and to
freeze threads from entering/exiting the process.
Arguments:
Process - Pointer to the process to lock
WaitMode - Supplies the processor mode to issue the wait under
LockMode - The type of lock to attempt
PsLockPollOnTimeout - Use a timeout and poll for the lock
bailing if the process exits.
PsLockReturnTimeout - Do not poll, just timeout wait and
return if you can not get the lock.
PsLockWaitForever - Wait without a timeout
Return Value:
STATUS_SUCCESS - You got the lock, you must call PsUnlocProcess later on
STATUS_TIMEOUT - You requested PsLockReturnTimeout, and the lock was not available
STATUS_PROCESS_IS_TERMINATING - The process you are trying to lock is terminating
--*/
|
|
|