Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.137.185.180] |
|
Сообщ.
#1
,
|
|
|
В общем, как и обещал, реализация второго пункта без Resume/Suspend, а прямо на лету На этот раз даже с проверками на ошибки. "Полезные" здесь функции IsThreadSuspended и GetThreadIdByHandle, остальные - просто рабочие.
uses SysConst, JwaNative, JwaWinType, JwaNtStatus; function NtErrorMessage(Code: NTSTATUS): String; var hMod: Cardinal; Buffer: array[0..255] of Char; Len: Integer; begin hMod:=GetModuleHandle(ntdll); Len := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_IGNORE_INSERTS or FORMAT_MESSAGE_ARGUMENT_ARRAY or FORMAT_MESSAGE_FROM_HMODULE, Pointer(hMod), Code, 0, Buffer, SizeOf(Buffer), nil); while (Len > 0) and (Buffer[Len - 1] in [#0..#32, '.']) do Dec(Len); SetString(Result, Buffer, Len); end; function NtSuccess(Code: NTSTATUS): Boolean; begin Result:=Code >= 0; end; procedure NtCheck(Code: NTSTATUS); begin if not NtSuccess(Code) then begin raise EOSError.CreateResFmt(@SOSError, [Code,NtErrorMessage(Code)]); end; end; function GetSystemInfoTable(ASystemInformationClass: SYSTEM_INFORMATION_CLASS; out Info: Pointer; out Size: Cardinal): NTSTATUS; var SystemInfo: TSystemInfo; ReturnSize: Cardinal; ContinueFlag: Boolean; begin GetSystemInfo(SystemInfo); Size:=SystemInfo.dwPageSize; repeat Info:=VirtualAlloc(nil,Size,MEM_COMMIT or MEM_RESERVE,PAGE_READWRITE); if Info = nil then RaiseLastOSError; Result:=NtQuerySystemInformation(ASystemInformationClass,Info,Size,@ReturnSize); ContinueFlag:=Result = STATUS_INFO_LENGTH_MISMATCH; if ContinueFlag then begin Win32Check(VirtualFree(Info,0,MEM_RELEASE)); if ReturnSize = 0 then Size:=Size + SystemInfo.dwPageSize else Size:=ReturnSize; end; until not ContinueFlag; end; function GetThreadIdByHandle(Handle: THandle): Cardinal; var Info: _THREAD_BASIC_INFORMATION; begin NtCheck(NtQueryInformationThread(Handle,ThreadBasicInformation,@Info, SizeOf(_THREAD_BASIC_INFORMATION),nil)); Result:=Info.ClientId.UniqueThread; end; function IsThreadSuspended(ThreadID: Cardinal): Boolean; var Info, Entry: Pointer; Size, i: Cardinal; ContinueFlag: Boolean; begin Result:=false; NtCheck(GetSystemInfoTable(SystemProcessesAndThreadsInformation,Info,Size)); try Entry:=Info; ContinueFlag:=true; while ContinueFlag do begin for i:=0 to PSYSTEM_PROCESSES(Entry)^.ThreadCount - 1 do begin if PSYSTEM_PROCESSES(Entry)^.Threads[i].ClientId.UniqueThread = ThreadID then begin Result:=PSYSTEM_PROCESSES(Entry)^.Threads[i].WaitReason = Suspended; ContinueFlag:=false; Break; end; end; if (PSYSTEM_PROCESSES(Entry)^.NextEntryDelta <> 0) then Cardinal(Entry):=Cardinal(Entry) + PSYSTEM_PROCESSES(Entry)^.NextEntryDelta else ContinueFlag:=false; end; finally VirtualFree(Info,0,MEM_RELEASE); end; end; |