Как завершить задачу в Windows NT (а заодно получить PID задачи)?

=== Как завершить задачу в Windows NT (а заодно получить PID задачи)? ===
Ниже приведён unit, который позволяет убить задачу в Windows NT.
Entry :
function Kill_By_Pid(pid: LongInt): Integer;
// где pid, это число, представляющее pid задачи
function EnumProcessWithPid(list: TStrings): Integer;
// где список, это объект TStrings, который будет содержать имя задачи и pid в полях Object.
// ( list.Items[i] для имени, integer(list.Object[i]) для PID)
Дальше следует сам код:
procedure GenerateBlueScreen;
var
 Task: TStringList;
 i: integer;
begin
 Task := TStringList.Create;
 try
 EnumProcessWithPid(Task);
 for i := 0 to Task.Count - 1 do
 begin
 TaskName := UpperCase(Task[i]);
 if (TaskName = 'WINLOGON.EXE') then
 begin // Generate a nice BlueScreenOfDeath
 Kill_By_Pid(Integer(Task.Objects[i]));
 Beep;
 break;
 end;
 end;
 finally
 Task.Free;
 end;
end;
unit U_Kill;
{** JF 15/02/2000 - U_Kill.pas
** This unit allow you to list and to kill runnign process. (Work only on NT)
** Entry point : EnumProcessWithPid and Kill_By_Pid.
** v1.2 JF correct a bug in Kill_By_Pid
** v1.3 JF change a thing for D5 05/09/2000
**}
interface
uses
 Classes;
//** Error code **//
const
 KILL_NOERR = 0;
 KILL_NOTSUPPORTED = -1;
 KILL_ERR_OPENPROCESS = -2;
 KILL_ERR_TERMINATEPROCESS = -3;
 ENUM_NOERR = 0;
 ENUM_NOTSUPPORTED = -1;
 ENUM_ERR_OPENPROCESSTOKEN = -2;
 ENUM_ERR_LookupPrivilegeValue = -3;
 ENUM_ERR_AdjustTokenPrivileges = -4;
 GETTASKLIST_ERR_RegOpenKeyEx = -1;
 GETTASKLIST_ERR_RegQueryValueEx = -2;
function Kill_By_Pid(pid: LongInt): Integer;
function EnumProcessWithPid(list: TStrings): Integer;
implementation
uses
 Windows,
 Registry,
 SysUtils;
var
 VerInfo: TOSVersionInfo;
const
 SE_DEBUG_NAME = 'SeDebugPrivilege';
 INITIAL_SIZE = 51200;
 EXTEND_SIZE = 25600;
 REGKEY_PERF = 'software\microsoft\windows nt\currentversion\perflib';
 REGSUBKEY_COUNTERS = 'Counters';
 PROCESS_COUNTER = 'process';
 PROCESSID_COUNTER = 'id process';
 UNKNOWN_TASK = 'unknown';
type
 ArrayOfChar = array[0..1024] of Char;
 pArrayOfChar = ^pArrayOfChar;
type
 TPerfDataBlock = record
 Signature: array[0..3] of WCHAR;
 LittleEndian: DWORD;
 Version: DWORD;
 Revision: DWORD;
 TotalByteLength: DWORD;
 HeaderLength: DWORD;
 NumObjectTypes: DWORD;
 DefaultObject: Integer;
 SystemTime: TSystemTime;
 PerfTime: TLargeInteger;
 PerfFreq: TLargeInteger;
 PerfTime100nSec: TLargeInteger;
 SystemNameLength: DWORD;
 SystemNameOffset: DWORD;
 end;
 pTPerfDataBlock = ^TPerfDataBlock;
 TPerfObjectType = record
 TotalByteLength: DWORD;
 DefinitionLength: DWORD;
 HeaderLength: DWORD;
 ObjectNameTitleIndex: DWORD;
 ObjectNameTitle: LPWSTR;
 ObjectHelpTitleIndex: DWORD;
 ObjectHelpTitle: LPWSTR;
 DetailLevel: DWORD;
 NumCounters: DWORD;
 DefaultCounter: Integer;
 NumInstances: Integer;
 CodePage: DWORD;
 PerfTime: TLargeInteger;
 PerfFreq: TLargeInteger;
 end;
 pTPerfObjectType = ^TPerfObjectType;
 TPerfInstanceDefinition = record
 ByteLength: DWORD;
 ParentObjectTitleIndex: DWORD;
 ParentObjectInstance: DWORD;
 UniqueID: Integer;
 NameOffset: DWORD;
 NameLength: DWORD;
 end;
 pTPerfInstanceDefinition = ^TPerfInstanceDefinition;
 TPerfCounterBlock = record
 ByteLength: DWORD;
 end;
 pTPerfCounterBlock = ^TPerfCounterBlock;
 TPerfCounterDefinition = record
 ByteLength: DWORD;
 CounterNameTitleIndex: DWORD;
 CounterNameTitle: LPWSTR;
 CounterHelpTitleIndex: DWORD;
 CounterHelpTitle: LPWSTR;
 DefaultScale: Integer;
 DetailLevel: DWORD;
 CounterType: DWORD;
 CounterSize: DWORD;
 CounterOffset: DWORD;
 end;
 pTPerfCounterDefinition = ^TPerfCounterDefinition;
procedure InitKill;
begin
 VerInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
 GetVersionEx(VerInfo);
end;
(*
#define MAKELANGID(p, s) ((((WORD )(s)) << 10) | (WORD )(p))
*)
function MAKELANGID(p: DWORD; s: DWORD): Word;
begin
 Result := (s shl 10) or (p);
end;
function Kill_By_Pid(pid: LongInt): Integer;
var
 hProcess: THANDLE;
 TermSucc: BOOL;
begin
 if (verInfo.dwPlatformId = VER_PLATFORM_WIN32_NT) then
 begin
 hProcess := OpenProcess(PROCESS_ALL_ACCESS, True, pid);
 if (hProcess = 0) then // v 1.2 : was =-1
 begin
 Result := KILL_ERR_OPENPROCESS;
 end
 else
 begin
 TermSucc := TerminateProcess(hProcess, 0);
 if (TermSucc = False) then
 Result := KILL_ERR_TERMINATEPROCESS
 else
 Result := KILL_NOERR;
 end;
 end
 else
 Result := KILL_NOTSUPPORTED;
end;
function EnableDebugPrivilegeNT: Integer;
var
 hToken: THANDLE;
 DebugValue: TLargeInteger;
 tkp: TTokenPrivileges;
 ReturnLength: DWORD;
 PreviousState: TTokenPrivileges;
begin
 if (OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) = False) then
 Result := ENUM_ERR_OPENPROCESSTOKEN
 else
 begin
 if (LookupPrivilegeValue(nil, SE_DEBUG_NAME, DebugValue) = False) then
 Result := ENUM_ERR_LookupPrivilegeValue
 else
 begin
 ReturnLength := 0;
 tkp.PrivilegeCount := 1;
 tkp.Privileges[0].Luid := DebugValue;
 tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
 AdjustTokenPrivileges(hToken, False, tkp, SizeOf(TTokenPrivileges), PreviousState, ReturnLength);
 if (GetLastError <> ERROR_SUCCESS) then
 Result := ENUM_ERR_AdjustTokenPrivileges
 else
 Result := ENUM_NOERR;
 end;
 end;
end;
function IsDigit(c: Char): Boolean;
begin
 Result := (c >= '0') and (c <= '9');
end;
function min(a, b: Integer): Integer;
begin
 if (a < b) then
 Result := a
 else
 Result := b;
end;
function GetTaskListNT(pTask: TStrings): Integer;
var
 rc: DWORD;
 hKeyNames: HKEY;
 dwType: DWORD;
 dwSize: DWORd;
 buf: PBYTE;
 szSubkey: array[0..1024] of Char;
 lid: LANGID;
 p: PChar;
 p2: PChar;
 pPerf: pTPerfDataBlock;
 pObj: pTPerfObjectType;
 pInst: pTPerfInstanceDefinition;
 pCounter: pTPerfCounterBlock;
 pCounterDef: pTPerfCounterDefinition;
 i: DWORD;
 dwProcessIdTitle: DWORD;
 dwProcessIdCounter: DWORD;
 szProcessName: array[0..MAX_PATH] of Char;
 dwLimit: DWORD;
 dwNumTasks: dword;
 ProcessName: array[0..MAX_PATH] of Char;
 dwProcessID: DWORD;
label
 EndOfProc;
begin
 dwNumTasks := 255;
 dwLimit := dwNumTasks - 1;
 StrCopy(ProcessName, );
 lid := MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL);
 StrFmt(szSubKey, '%s\%.3X', [REGKEY_PERF, lid]);
 rc := RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_READ, hKeyNames);
 if (rc <> ERROR_SUCCESS) then
 Result := GETTASKLIST_ERR_RegOpenKeyEx
 else
 begin
 Result := 0;
 rc := RegQueryValueEx(hKeyNames, REGSUBKEY_COUNTERS, nil, @dwType, nil, @dwSize);
 if (rc <> ERROR_SUCCESS) then
 Result := GETTASKLIST_ERR_RegQueryValueEx
 else
 begin
 GetMem(buf, dwSize);
 FillChar(buf^, dwSize, 0);
 RegQueryValueEx(hKeyNames, REGSUBKEY_COUNTERS, nil, @dwType, buf, @dwSize);
 p := PChar(buf);
 dwProcessIdTitle := 0;
 while (p^ <> #0) do
 begin
 if (p > buf) then
 begin
 p2 := p - 2;
 while (isDigit(p2^)) do
 Dec(p2);
 end;
 if (StrIComp(p, PROCESS_COUNTER) = 0) then
 begin
 p2 := p - 2;
 while (IsDigit(p2^)) do
 Dec(p2);
 StrCopy(szSubKey, p2 + 1);
 end
 else
 if (StrIComp(p, PROCESSID_COUNTER) = 0) then
 begin
 p2 := p - 2;
 while (IsDigit(p2^)) do
 Dec(p2);
 dwProcessIdTitle := StrToIntDef(p2 + 1, -1);
 end;
 p := p + (Length(p) + 1);
 end;
 FreeMem(buf);
 buf := nil;
 dwSize := INITIAL_SIZE;
 GetMem(buf, dwSize);
 FillChar(buf^, dwSize, 0);
 pPerf := nil;
 while (True) do
 begin
 rc := RegQueryValueEx(HKEY_PERFORMANCE_DATA, szSubKey, nil, @dwType, buf, @dwSize);
 pPerf := pTPerfDataBlock(buf);
 if ((rc = ERROR_SUCCESS) and (dwSize > 0)
 and (pPerf^.Signature[0] = WCHAR('P'))
 and (pPerf^.Signature[1] = WCHAR('E'))
 and (pPerf^.Signature[2] = WCHAR('R'))
 and (pPerf^.Signature[3] = WCHAR('F'))) then
 begin
 break;
 end;
 if (rc = ERROR_MORE_DATA) then
 begin
 dwSize := dwSize + EXTEND_SIZE;
 FreeMem(buf);
 buf := nil;
 GetMem(buf, dwSize);
 FillChar(buf^, dwSize, 0);
 end
 else
 goto EndOfProc;
 end;
 pObj := pTPerfObjectType(DWORD(pPerf) + pPerf^.HeaderLength);
 pCounterDef := pTPerfCounterDefinition(DWORD(pObj) + pObj^.HeaderLength);
 dwProcessIdCounter := 0;
 i := 0;
 while (i < pObj^.NumCounters) do
 begin
 if (pCounterDef^.CounterNameTitleIndex = dwProcessIdTitle) then
 begin
 dwProcessIdCounter := pCounterDEf^.CounterOffset;
 break;
 end;
 Inc(pCounterDef);
 Inc(i);
 end;
 dwNumTasks := min(dwLimit, pObj^.NumInstances);
 pInst := PTPerfInstanceDefinition(DWORD(pObj) + pObj^.DefinitionLength);
 i := 0;
 while (i < dwNumTasks) do
 begin
 p := PChar(DWORD(pInst) + pInst^.NameOffset);
 rc := WideCharToMultiByte(CP_ACP, 0, LPCWSTR(p), -1, szProcessName,
 SizeOf(szProcessName), nil, nil);
 {** This is changed for working with D3 and D5 05/09/2000 **}
 if (rc = 0) then
 StrCopy(ProcessName, UNKNOWN_TASK)
 else
 StrCopy(ProcessName, szProcessName);
 // Получаем ID процесса
 pCounter := pTPerfCounterBlock(DWORD(pInst) + pInst^.ByteLength);
 dwProcessId := LPDWORD(DWORD(pCounter) + dwProcessIdCounter)^;
 if (dwProcessId = 0) then
 dwProcessId := DWORD(0);
 pTask.AddObject(ProcessName, TObject(dwProcessID));
 pInst := pTPerfInstanceDefinition(DWORD(pCounter) + pCounter^.ByteLength);
 Inc(i);
 end;
 Result := dwNumTasks;
 end;
 end;
EndOfProc:
 if (buf <> nil) then
 FreeMem(buf);
 RegCloseKey(hKeyNames);
 RegCloseKey(HKEY_PERFORMANCE_DATA);
 RegCloseKey(hKeyNames);
 RegCloseKey(HKEY_PERFORMANCE_DATA);
end;
function EnumProcessWithPid(list: TStrings): Integer;
begin
 if (verInfo.dwPlatformId = VER_PLATFORM_WIN32_NT) then
 begin
 EnableDebugPrivilegeNT;
 Result := GetTaskListNT(list);
 end
 else
 Result := ENUM_NOTSUPPORTED;
end;
initialization
InitKill;
end.
Source: Взято из http://forum.sources.ru
ID: 02102