Mega Code Archive

 
Categories / Delphi / System
 

Kill Enum task in Windows NT

Title: Kill / Enum task in Windows NT Question: Q: How to kill a task in windows Nt ? Q: How to get task number (PID) in windows nt ? Answer: Here is a unit a wrote to kill a task in Windows nt (Based on kill.cpp in MSDN) Update : now work with D5 (without the Empty string bug ) 22/01/2001 Richard Hierro correct the buf^ bug ! Entry : function Kill_By_Pid(pid : longint) : integer; where pid is a number representing the pid of the task function EnumProcessWithPid(list : TStrings) : integer; where list is a TStrings object will contains the task name and the pid in Object fields. (use list.Items[i] to get the name, integer(list.Object[i]) to get the PID) Sample code and example : 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)) *) 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 (cend; function min(a,b : integer) : integer; begin if (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); // Oups, bug corrected by Richard Hierro 22/01/2001 end else goto EndOfProc; end; pObj := pTPerfObjectType( DWORD(pPerf) + pPerf^.HeaderLength); pCounterDef := pTPerfCounterDefinition( DWORD(pObj) + pObj^.HeaderLength); dwProcessIdCounter := 0; i := 0; while (i 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 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); // Get the process 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.