unit PM.ProcessLockdown; interface uses Winapi.Windows; function GetPidOfTcpConnection(ALocalPort, ARemotePort: Word): DWORD; function IsDescendantOfCurrentProcess(APid: DWORD): Boolean; implementation uses System.SysUtils, System.Generics.Collections, Winapi.WinSock, Winapi.TlHelp32; const IPHLPAPI = 'iphlpapi.dll'; AF_INET_LOCAL = 2; TCP_TABLE_OWNER_PID_CONNECTIONS = 4; NO_ERROR = 0; type MIB_TCPROW_OWNER_PID = record dwState: DWORD; dwLocalAddr: DWORD; dwLocalPort: DWORD; dwRemoteAddr: DWORD; dwRemotePort: DWORD; dwOwningPid: DWORD; end; MIB_TCPTABLE_OWNER_PID = record dwNumEntries: DWORD; table: array[0..0] of MIB_TCPROW_OWNER_PID; end; PMIB_TCPTABLE_OWNER_PID = ^MIB_TCPTABLE_OWNER_PID; function GetExtendedTcpTable(pTcpTable: Pointer; pdwSize: PDWORD; bOrder: BOOL; ulAf: ULONG; TableClass: DWORD; Reserved: ULONG): DWORD; stdcall; external IPHLPAPI; function GetPidOfTcpConnection(ALocalPort, ARemotePort: Word): DWORD; var Size: DWORD; Buffer: PMIB_TCPTABLE_OWNER_PID; i: Integer; Row: ^MIB_TCPROW_OWNER_PID; WantedLocal, WantedRemote: Word; begin Result := 0; Size := 0; GetExtendedTcpTable(nil, @Size, False, AF_INET_LOCAL, TCP_TABLE_OWNER_PID_CONNECTIONS, 0); if Size = 0 then Exit; GetMem(Buffer, Size); try if GetExtendedTcpTable(Buffer, @Size, False, AF_INET_LOCAL, TCP_TABLE_OWNER_PID_CONNECTIONS, 0) <> NO_ERROR then Exit; WantedLocal := ntohs(ALocalPort); WantedRemote := ntohs(ARemotePort); Row := @Buffer.table[0]; for i := 0 to Buffer.dwNumEntries - 1 do begin if (Word(Row.dwLocalPort) = WantedLocal) and (Word(Row.dwRemotePort) = WantedRemote) then Exit(Row.dwOwningPid); Inc(Row); end; finally FreeMem(Buffer); end; end; function IsDescendantOfCurrentProcess(APid: DWORD): Boolean; const MaxDepth = 32; var Snap: THandle; Entry: TProcessEntry32W; ParentMap: TDictionary; Current, RootPid: DWORD; Depth: Integer; begin Result := False; if APid = 0 then Exit; RootPid := GetCurrentProcessId; if APid = RootPid then Exit(True); Snap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if Snap = INVALID_HANDLE_VALUE then Exit; ParentMap := TDictionary.Create; try Entry.dwSize := SizeOf(Entry); if Process32FirstW(Snap, Entry) then repeat ParentMap.AddOrSetValue(Entry.th32ProcessID, Entry.th32ParentProcessID); until not Process32NextW(Snap, Entry); Current := APid; for Depth := 0 to MaxDepth do begin if Current = RootPid then Exit(True); if not ParentMap.TryGetValue(Current, Current) then Exit; if (Current = 0) or (Current = 4) then Exit; end; finally ParentMap.Free; CloseHandle(Snap); end; end; end.