Как завершить задачу в Windows NT (а заодно получить PID задачи)?
Материал из DRKB
Как завершить задачу в 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