/*
* Autopsy Forensic Browser
*
* Copyright 2012-2014 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.coreutils;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.Kernel32Util;
import com.sun.jna.platform.win32.Tlhelp32;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinNT;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
/**
* Class that represents a Windows process. It uses JNA to access the Win32 API.
* This code is based on
* http://stackoverflow.com/questions/10124299/how-do-i-terminate-a-process-tree-from-java
*/
public class Win32Process {
WinNT.HANDLE handle;
int pid;
/**
* Create a Win32Process object for the given Process object. Reflection is
* used to construct a Windows process handle.
*
* @param process A Java Process object
*
* @throws Exception
*/
Win32Process(Process process) throws Exception {
if (process.getClass().getName().equals("java.lang.Win32Process") || // NON-NLS
process.getClass().getName().equals("java.lang.ProcessImpl")) { // NON-NLS
try {
Field f = process.getClass().getDeclaredField("handle"); // NON-NLS
f.setAccessible(true);
long handleVal = f.getLong(process);
handle = new WinNT.HANDLE(Pointer.createConstant(handleVal));
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
throw new Exception(ex.getMessage()); // NON-NLS
}
}
this.pid = Kernel32.INSTANCE.GetProcessId(handle);
}
/**
* Create a Win32Process object for the given process id.
*
* @param pid Process Id
*
* @throws Exception
*/
Win32Process(int pid) throws Exception {
handle = Kernel32.INSTANCE.OpenProcess(
0x0400
| /*
* PROCESS_QUERY_INFORMATION
*/ 0x0800
| /*
* PROCESS_SUSPEND_RESUME
*/ 0x0001
| /*
* PROCESS_TERMINATE
*/ 0x00100000 /*
* SYNCHRONIZE
*/,
false,
pid);
if (handle == null) {
throw new Exception(Kernel32Util.formatMessageFromLastErrorCode(Kernel32.INSTANCE.GetLastError()));
}
this.pid = Kernel32.INSTANCE.GetProcessId(handle);
}
@Override
protected void finalize() throws Throwable {
Kernel32.INSTANCE.CloseHandle(handle);
super.finalize();
}
/**
* Kill the process. Note that this does not kill children.
*/
public void terminate() {
Kernel32.INSTANCE.TerminateProcess(handle, 0);
}
/**
* Get children of current process object.
*
* @return list of child processes
*
* @throws IOException
*/
public List<Win32Process> getChildren() throws Exception {
ArrayList<Win32Process> result = new ArrayList<>();
WinNT.HANDLE hSnap = Kernel32.INSTANCE.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPPROCESS, new DWORD(0));
Tlhelp32.PROCESSENTRY32.ByReference ent = new Tlhelp32.PROCESSENTRY32.ByReference();
if (!Kernel32.INSTANCE.Process32First(hSnap, ent)) {
return result;
}
do {
if (ent.th32ParentProcessID.intValue() == pid) {
result.add(new Win32Process(ent.th32ProcessID.intValue()));
}
} while (Kernel32.INSTANCE.Process32Next(hSnap, ent));
Kernel32.INSTANCE.CloseHandle(hSnap);
return result;
}
}