2014-11-20 13:21:19 +00:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2013 Laurent CLOUET
|
|
|
|
|
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
|
* as published by the Free Software Foundation; version 2
|
|
|
|
|
* of the License.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package com.sheepit.client.os.windows;
|
|
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.lang.reflect.Field;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
|
|
import com.sun.jna.Native;
|
|
|
|
|
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.WinDef.DWORD;
|
|
|
|
|
import com.sun.jna.platform.win32.WinNT;
|
|
|
|
|
|
|
|
|
|
public class WinProcess {
|
|
|
|
|
public static final int PRIORITY_IDLE = 0x40;
|
|
|
|
|
public static final int PRIORITY_BELOW_NORMAL = 0x4000;
|
|
|
|
|
public static final int PRIORITY_NORMAL = 0x20;
|
|
|
|
|
public static final int PRIORITY_ABOVE_NORMAL = 0x8000;
|
|
|
|
|
public static final int PRIORITY_HIGH = 0x80;
|
|
|
|
|
public static final int PRIORITY_REALTIME = 0x100;
|
|
|
|
|
|
|
|
|
|
private WinNT.HANDLE handle;
|
|
|
|
|
private int pid;
|
|
|
|
|
Kernel32Lib kernel32lib;
|
|
|
|
|
|
|
|
|
|
public WinProcess() {
|
|
|
|
|
this.handle = null;
|
|
|
|
|
this.pid = -1;
|
|
|
|
|
this.kernel32lib = null;
|
|
|
|
|
try {
|
|
|
|
|
this.kernel32lib = (Kernel32Lib) Native.loadLibrary(Kernel32Lib.path, Kernel32Lib.class);
|
|
|
|
|
}
|
|
|
|
|
catch (java.lang.UnsatisfiedLinkError e) {
|
|
|
|
|
System.out.println("WinProcess::construct " + e);
|
|
|
|
|
}
|
|
|
|
|
catch (java.lang.ExceptionInInitializerError e) {
|
|
|
|
|
System.out.println("WinProcess::construct " + e);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e) {
|
|
|
|
|
System.out.println("WinProcess::construct " + e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public WinProcess(Process process) {
|
|
|
|
|
this();
|
|
|
|
|
try {
|
|
|
|
|
Field f = process.getClass().getDeclaredField("handle");
|
|
|
|
|
f.setAccessible(true);
|
|
|
|
|
long val = f.getLong(process);
|
|
|
|
|
this.handle = new WinNT.HANDLE();
|
|
|
|
|
this.handle.setPointer(Pointer.createConstant(val));
|
|
|
|
|
this.pid = Kernel32.INSTANCE.GetProcessId(this.handle);
|
|
|
|
|
}
|
|
|
|
|
catch (NoSuchFieldException e) {
|
|
|
|
|
}
|
|
|
|
|
catch (IllegalArgumentException e) {
|
|
|
|
|
}
|
|
|
|
|
catch (IllegalAccessException e) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public WinProcess(int pid_) throws IOException {
|
|
|
|
|
this.handle = Kernel32.INSTANCE.OpenProcess(0x0400 | // PROCESS_QUERY_INFORMATION
|
|
|
|
|
0x0800 | // PROCESS_SUSPEND_RESUME
|
|
|
|
|
0x0001 | // PROCESS_TERMINATE
|
|
|
|
|
0x0200 | // PROCESS_SET_INFORMATION
|
|
|
|
|
0x00100000, // SYNCHRONIZE
|
2014-11-24 20:55:08 +00:00
|
|
|
false, pid_);
|
2014-11-20 13:21:19 +00:00
|
|
|
if (this.handle == null) {
|
|
|
|
|
throw new IOException("OpenProcess failed: " + Kernel32Util.formatMessageFromLastErrorCode(Kernel32.INSTANCE.GetLastError()) + " (pid: " + pid_ + ")");
|
|
|
|
|
}
|
|
|
|
|
this.pid = pid_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void finalize() throws Throwable {
|
|
|
|
|
if (this.handle != null) {
|
|
|
|
|
Kernel32.INSTANCE.CloseHandle(this.handle);
|
|
|
|
|
this.handle = null;
|
|
|
|
|
}
|
|
|
|
|
this.pid = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean kill() {
|
|
|
|
|
try {
|
|
|
|
|
List<WinProcess> children = this.getChildren();
|
|
|
|
|
this.terminate();
|
|
|
|
|
for (WinProcess child : children) {
|
|
|
|
|
child.kill();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (IOException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean setPriority(int priority) {
|
|
|
|
|
return this.kernel32lib.SetPriorityClass(this.handle, priority);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void terminate() {
|
|
|
|
|
Kernel32.INSTANCE.TerminateProcess(this.handle, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<WinProcess> getChildren() throws IOException {
|
|
|
|
|
ArrayList<WinProcess> result = new ArrayList<WinProcess>();
|
|
|
|
|
|
|
|
|
|
WinNT.HANDLE hSnap = this.kernel32lib.CreateToolhelp32Snapshot(Kernel32Lib.TH32CS_SNAPPROCESS, new DWORD(0));
|
|
|
|
|
Kernel32Lib.PROCESSENTRY32.ByReference ent = new Kernel32Lib.PROCESSENTRY32.ByReference();
|
|
|
|
|
if (!this.kernel32lib.Process32First(hSnap, ent)) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
do {
|
|
|
|
|
if (ent.th32ParentProcessID.intValue() == this.pid) {
|
|
|
|
|
try {
|
|
|
|
|
result.add(new WinProcess(ent.th32ProcessID.intValue()));
|
|
|
|
|
}
|
|
|
|
|
catch (IOException e) {
|
|
|
|
|
System.err.println("WinProcess::getChildren, IOException " + e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
while (this.kernel32lib.Process32Next(hSnap, ent));
|
|
|
|
|
|
|
|
|
|
Kernel32.INSTANCE.CloseHandle(hSnap);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public String toString() {
|
|
|
|
|
return "WinProcess(pid: " + this.pid + ", handle " + this.handle + ")";
|
|
|
|
|
}
|
|
|
|
|
}
|