package copyto.paste.chat.miranda; import static com.sun.jna.examples.win32.ComCtl32.TCIF_PARAM; import static com.sun.jna.examples.win32.ComCtl32.TCIF_TEXT; import static com.sun.jna.examples.win32.ComCtl32.TCM_GETITEM; import static com.sun.jna.examples.win32.ComCtl32.TCM_GETITEMCOUNT; import static com.sun.jna.examples.win32.Kernel32.MEM_COMMIT; import static com.sun.jna.examples.win32.Kernel32.MEM_RELEASE; import static com.sun.jna.examples.win32.Kernel32.PAGE_READWRITE; import static com.sun.jna.examples.win32.Kernel32.PROCESS_QUERY_INFORMATION; import static com.sun.jna.examples.win32.Kernel32.PROCESS_VM_OPERATION; import static com.sun.jna.examples.win32.Kernel32.PROCESS_VM_READ; import static com.sun.jna.examples.win32.Kernel32.PROCESS_VM_WRITE; import static com.sun.jna.examples.win32.User32.GWL_USERDATA; import static com.sun.jna.examples.win32.User32.IDOK; import static com.sun.jna.examples.win32.User32.WM_COMMAND; import static com.sun.jna.examples.win32.User32.WM_SETTEXT; import static com.sun.jna.examples.win32.User32.WM_USER; import miranda.api.chat.dll.SESSION_INFO; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import com.sun.jna.examples.win32.Kernel32; import com.sun.jna.examples.win32.User32; import com.sun.jna.examples.win32.ComCtl32.TCITEM; import com.sun.jna.examples.win32.W32API.HANDLE; import com.sun.jna.examples.win32.W32API.HWND; import com.sun.jna.examples.win32.W32API.SIZE_T; import com.sun.jna.examples.win32.ext.ProcessAddressSpace; import com.sun.jna.examples.win32.ext.ProcessWindowVisitor; import com.sun.jna.examples.win32.ext.Shell32; import com.sun.jna.examples.win32.ext.Visitor; import com.sun.jna.examples.win32.ext.Windows; import com.sun.jna.examples.win32.ext.ProcessAddressSpace.SendMessageRunnable; import com.sun.jna.ptr.IntByReference; public class MirandaIRC { private static final int IDC_TAB = 1074; // lParam = tabIndex private static int GC_SWITCHTAB = WM_USER + 137; private static int IDC_MESSAGE = 1009; private HWND window; private HANDLE process; private String path; private final static User32 user32 = User32.INSTANCE; private final static Kernel32 kernel32 = Kernel32.INSTANCE; public MirandaIRC(HANDLE process, String path, HWND window) { IntByReference processId = new IntByReference(); user32.GetWindowThreadProcessId(window, processId); // TODO: Use DuplicateHandle here? this.process = kernel32.OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION, false, processId.getValue()); this.window = window; this.path = path; } public void dispose() { if (process != null) { kernel32.CloseHandle(process); process = null; } } @Override protected void finalize() throws Throwable { dispose(); super.finalize(); } public void visitSessions(final Visitor<SESSION_INFO> visitor) { visitTabs(TCIF_PARAM, new TabVisitor() { public boolean visit(TCITEM item, int index) { int lParam = item.lParam.intValue(); if (lParam != 0) { SESSION_INFO info = new SESSION_INFO(process, lParam); visitor.visit(info); } return true; } }); } public interface TabVisitor { boolean visit(TCITEM item, int index); } public void visitTabs(int mask, TabVisitor visitor) { final HWND tab = user32.GetDlgItem(window, IDC_TAB); int count = user32.SendMessage(tab, TCM_GETITEMCOUNT, 0, 0); if (count == 0) { return; } TCITEM item = new TCITEM(); item.mask = mask; final ProcessAddressSpace mirandaSpace = new ProcessAddressSpace( process); int textMemory = 0; if ((mask & TCIF_TEXT) == TCIF_TEXT) { item.cchTextMax = 64; textMemory = kernel32.VirtualAllocEx(process, null, new SIZE_T( item.cchTextMax), MEM_COMMIT, PAGE_READWRITE); item.pszText = textMemory; } try { while (count-- > 0) { try { // A previous call could have reset the pszText pointer (see // API docs) if (textMemory != 0) { item.pszText = textMemory; } mirandaSpace.run(item, new SendMessageRunnable(tab, TCM_GETITEM, count)); if (!visitor.visit(item, count)) { break; } } catch (Throwable e) { e.printStackTrace(); } } } finally { mirandaSpace.dispose(); if (textMemory != 0) { kernel32.VirtualFreeEx(process, textMemory, 0, MEM_RELEASE); } } } static SESSION_INFO sessionFromWindow(HANDLE process, HWND window) { int baseAddress = user32.GetWindowLong(window, GWL_USERDATA); if (baseAddress != 0) { return new SESSION_INFO(process, baseAddress); } return null; } private int findChannelTab(final String channel) { final int tabIndex[] = new int[] { -1 }; visitTabs(TCIF_PARAM | TCIF_TEXT, new TabVisitor() { public boolean visit(TCITEM item, int index) { if (channel.equals(ProcessAddressSpace.readStringW(process, item.pszText))) { tabIndex[0] = index; return false; } return true; } }); return tabIndex[0]; } public void sendMessage(String channel, final String message) { final HWND messageWindow = user32.GetDlgItem(window, IDC_MESSAGE); if (user32.IsWindow(messageWindow)) { int tabIndex = findChannelTab(channel); if (tabIndex != -1) { user32.SendMessage(window, GC_SWITCHTAB, null, tabIndex); user32.SendMessage(messageWindow, WM_SETTEXT, 0, message); // This will enable the IDOK button user32.PostMessage(window, WM_COMMAND, IDC_MESSAGE, 0); // Whose enablement is checked when its command is received. user32.PostMessage(window, WM_COMMAND, IDOK, 0); } } } public static class MirandaWindowFinder extends ProcessWindowVisitor { private MirandaIRC found; public MirandaWindowFinder() { super("miranda32.exe"); } @Override protected boolean visit(HANDLE process, String path, HWND window) { final HWND tab = user32.GetDlgItem(window, IDC_TAB); if (user32.IsWindow(tab)) { int result = user32.GetWindowLong(window, GWL_USERDATA); if (result != 0) { found = new MirandaIRC(process, path, window); return false; } } return true; } public MirandaIRC getFound() { return found; } } static public MirandaIRC find() { MirandaIRC.MirandaWindowFinder visitor = new MirandaWindowFinder(); Windows.visitWindows(visitor); return visitor.getFound(); } public ImageDescriptor getIcon() { int icon = Shell32.INSTANCE.ExtractIcon(Kernel32.INSTANCE .GetModuleHandle(null), path, 0); if (icon != 0) { Image image = Image.win32_new(null, SWT.ICON, icon); try { return ImageDescriptor .createFromImageData(image.getImageData()); } finally { image.dispose(); } } return null; } }