package me.test;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.OleAutomation;
import org.eclipse.swt.ole.win32.OleClientSite;
import org.eclipse.swt.ole.win32.OleFrame;
import org.eclipse.swt.ole.win32.Variant;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.LPARAM;
import com.sun.jna.platform.win32.WinDef.WPARAM;
/**
* An container for ActiveX/COM components with windows UI. <br/>
* For those without UI, U can also consider using Jacob etc. <br/>
*/
public class ComContainer extends Thread {
private Display display = null;
// private Shell shell = null;
private OleClientSite clientSite = null;
private OleAutomation ole = null;
private boolean stop = false;
private String progId = null;
private boolean ready = false;
// ----------------------------------------
private int passwordMaxLen = 6;
private String passwordChars = "1234567890aA";
private String publicKey = "BF6C2C496593917FEEDFE0F6C62BA237C32A99886D66CC3D20DBAEB38484D001C86EE38576C6A92CA3C94C03B1AD284A0F85498D3DEB9134DFC57BABE8271401";
private String JsOnKey = "JsOnKey";
private Properties initProps;
/**
* @param clsId
* e.g. "Word.Document",
* "{11111111-2222-3333-4444-555555555555}"
*/
public ComContainer(String progId) {
this.progId = progId;
ready = false;
stop = false;
}
public Text t;
public OleFrame frame;
private BlockingQueue<String> queue = new LinkedBlockingDeque<String>(1);
public BlockingQueue<String> resultQueue = new LinkedBlockingDeque<String>(
1);
protected void init() {
// 设置密码最大长度
int[] rgdispid = ole.getIDsOfNames(new String[]{"PasswordMaxLen"});
Variant var = ole.getProperty(rgdispid[0]);
System.out.println(var.getInt());
ole.setProperty(rgdispid[0], new Variant(passwordMaxLen));
// 设置允许的密码字符
rgdispid = ole.getIDsOfNames(new String[]{"PasswordChars"});
ole.setProperty(rgdispid[0], new Variant(passwordChars));
// 设置公钥
rgdispid = ole.getIDsOfNames(new String[]{"PublicKey"});
ole.setProperty(rgdispid[0], new Variant(publicKey));
rgdispid = ole.getIDsOfNames(new String[]{"JsOnKey"});
ole.setProperty(rgdispid[0], new Variant(JsOnKey));
// int[] rgdispid = null;
if (initProps != null) {
for (Entry<Object, Object> entry : initProps.entrySet()) {
String key = (String) entry.getKey();
String value = (String) entry.getValue();
rgdispid = ole.getIDsOfNames(new String[]{key});
ole.setProperty(rgdispid[0], new Variant(value));
}
}
}
public String enc(String password) {
Kernel32 kernel32 = Kernel32.INSTANCE;
User32 user32 = User32.INSTANCE;
MyUser32 myUser32 = MyUser32.INSTANCE;
kernel32.SetLastError(0);
final int MAPVK_VK_TO_VSC = 0;
// find the window handle of OleFrame
HWND h = new HWND(new Pointer(clientSite.handle));
// find the window handle of the ActiveX
h = user32.GetWindow(h, new DWORD(User32.GW_CHILD));
// find the window handle of the password input control
h = user32.GetWindow(h, new DWORD(User32.GW_CHILD));
OleAutomation ole = new OleAutomation(clientSite);
init();
// 清空密码
t.setFocus();
frame.setFocus();
// send the new password string
for (char c : password.toCharArray()) {
int errorNo = 0;
int tryTimes = 0;
kernel32.SetLastError(0);
do {
LParamUnion lUnion = LParamUnion.getDefaultVmChar();
lUnion.setScanCode((byte) myUser32.MapVirtualKey(VK.VK_A,
MAPVK_VK_TO_VSC));
MyUser32.INSTANCE.SendMessage(h, User32.WM_CHAR, new WPARAM(c),
new LPARAM(lUnion.toInt()));
tryTimes++;
errorNo = kernel32.GetLastError();
} while (errorNo != 0 && tryTimes < 3);
if (errorNo != 0) {
throw new RuntimeException("Could not complete the "
+ "password encoding. error code = " + errorNo);
}
}
// get the encrypted password
t.setFocus();
int[] rgdispid = ole.getIDsOfNames(new String[]{"Password"});
Variant var = ole.getProperty(rgdispid[0]);
System.out.println("ddddddddddddd" + var);
if (OLE.VT_NULL == var.getType()) {
return null;
} else if (OLE.VT_EMPTY == var.getType()) {
return "";
}
return var.getString();
}
public String encPp(String p) {
try {
queue.put(p);
return resultQueue.take();
} catch (InterruptedException e) {
return null;
}
}
@Override
public void run() {
ready = false;
stop = false;
display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
display.asyncExec(new Runnable() {
public void run() {
while (!stop) {
try {
String password = queue.take();
String encd = enc(password);
// t.setFocus();
// frame.setFocus();
resultQueue.put(encd);
} catch (InterruptedException e) {
break;
}
}
}
});
try {
frame = new OleFrame(shell, SWT.NONE);
clientSite = new OleClientSite(frame, SWT.NONE, progId);
clientSite.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);
ole = new OleAutomation(clientSite);
addFileMenu(frame); // TODO delete
} catch (SWTError e) {
e.printStackTrace();
display.dispose();
throw e;
}
t = new Text(shell, SWT.BORDER | SWT.MULTI);
t.forceFocus();
stop = false;
ready = true;
shell.setSize(400, 300);
shell.open(); // You can uncomment this for an direct view
// start to dispatch event
while (!stop && !shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
public void notifyStop() {
stop = true;
}
public OleClientSite getOleClientSite() {
return clientSite;
}
public boolean isReady() {
return ready;
}
void addFileMenu(final OleFrame frame) {
final Shell shell = frame.getShell();
Menu menuBar = shell.getMenuBar();
if (menuBar == null) {
menuBar = new Menu(shell, SWT.BAR);
shell.setMenuBar(menuBar);
}
MenuItem fileMenu = new MenuItem(menuBar, SWT.CASCADE);
fileMenu.setText("&Action");
Menu menuFile = new Menu(fileMenu);
fileMenu.setMenu(menuFile);
frame.setFileMenus(new MenuItem[]{fileMenu});
MenuItem menuHandle = new MenuItem(menuFile, SWT.CASCADE);
menuHandle.setText("View Activex Container's window handle");
menuHandle.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
MessageBox messageBox = new MessageBox(shell,
SWT.ICON_INFORMATION | SWT.OK);
messageBox.setText("Info");
// useful with SpyXX.exe
messageBox.setMessage("handle = ["
+ Long.toHexString(clientSite.handle).toUpperCase()
+ "]");
messageBox.open();
}
});
MenuItem menuTextData = new MenuItem(menuFile, SWT.CASCADE);
menuTextData.setText("View encrypted password");
menuTextData.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
OleAutomation ole = new OleAutomation(clientSite);
int[] rgdispid = ole.getIDsOfNames(new String[]{"Password"});
// rgdispid = ole.getIDsOfNames(new String[] { "PublicKey" });
Variant var = ole.getProperty(rgdispid[0]);
MessageBox messageBox = new MessageBox(shell,
SWT.ICON_INFORMATION | SWT.OK);
messageBox.setText("Info");
String str = null;
if (OLE.VT_NULL == var.getType()) {
str = null;
} else if (OLE.VT_EMPTY == var.getType()) {
str = "";
} else {
str = var.getString();
}
messageBox.setMessage("encrypted password = [" + str + "]");
System.out.println(messageBox.getMessage());
// messageBox.open();
}
});
MenuItem menuDelete = new MenuItem(menuFile, SWT.CASCADE);
menuDelete.setText("Delete last input char");
menuDelete.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Kernel32 kernel32 = Kernel32.INSTANCE;
kernel32.SetLastError(0);
User32 user32 = User32.INSTANCE;
// 找到包含密码框的java窗体的handle
HWND handle = new HWND(new Pointer(clientSite.handle));
// 找到ActiveX的handle
handle = user32.GetWindow(handle, new DWORD(User32.GW_CHILD));
// 找到ActiveX中密码输入框的handle
handle = user32.GetWindow(handle, new DWORD(User32.GW_CHILD));
// 发送消息
final WPARAM CHAR_BS = new WPARAM(0x08);
final int WM_CHAR = 0x0102;
LPARAM l = new LPARAM(0);
user32.PostMessage(handle, WM_CHAR, CHAR_BS, l);
int lastError = kernel32.GetLastError();
if (lastError != 0) {
System.out.println("last error = " + lastError);
}
}
});
MenuItem menuPostMessage = new MenuItem(menuFile, SWT.CASCADE);
menuPostMessage.setText("Append a char '1'");
menuPostMessage.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
}
});
}
}