1
0
mirror of https://github.com/moparisthebest/davmail synced 2024-12-13 11:12:22 -05:00

Update Jsmooth patch with 64bits exe support

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@1681 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2011-05-16 08:47:54 +00:00
parent 3a058507c9
commit b35b3db630
8 changed files with 2957 additions and 500 deletions

View File

@ -0,0 +1,408 @@
/*
JSmooth: a VM wrapper toolkit for Windows
Copyright (C) 2003 Rodrigo Reyes <reyes@charabia.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; either version 2 of the License, or
(at your option) any later version.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* JSmoothModelBean.java
*
* Created on 7 aout 2003, 18:32
*/
package net.charabia.jsmoothgen.application;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Vector;
public class JSmoothModelBean {
private String m_skeletonName;
private String m_executableName;
private String m_currentDirectory;
private String m_iconLocation;
private boolean m_embedJar = false;
private String m_jarLocation;
private String m_mainClassName;
private String m_arguments;
private String[] m_classPath;
private String m_minimumVersion = "";
private String m_maximumVersion = "";
private String[] m_jvmSearch = null;
private int m_maxHeap = -1;
private int m_initialHeap = -1;
private String m_vmParamter;
private int m_uacRequireAdmin;
private String m_noJvmMessage;
private String m_noJvmURL;
private String m_bundledJVM = null;
private JavaPropertyPair[] m_javaprops = new JavaPropertyPair[0];
private JSmoothModelBean.Property[] m_skelproperties;
static public class Property {
public String Key;
public String Value;
public void setKey(String key) {
this.Key = key;
}
public String getKey() {
return this.Key;
}
public void setValue(String val) {
this.Value = val;
}
public String getValue() {
return this.Value;
}
public String toString() {
return getKey() + "==" + getValue();
}
}
transient Vector m_listeners = new Vector();
public static interface Listener {
public void dataChanged();
}
transient Vector m_skeletonChangedListener = new Vector();
public static interface SkeletonChangedListener {
public void skeletonChanged();
}
/**
* Creates a new instance of JSmoothModelBean
*/
public JSmoothModelBean() {
}
public void addListener(JSmoothModelBean.Listener l) {
m_listeners.add(l);
}
public void removeListener(JSmoothModelBean.Listener l) {
m_listeners.remove(l);
}
public void addSkeletonChangedListener(JSmoothModelBean.SkeletonChangedListener l) {
m_skeletonChangedListener.add(l);
}
public void removeSkeletonChangedListener(JSmoothModelBean.SkeletonChangedListener l) {
m_skeletonChangedListener.remove(l);
}
private void fireChanged() {
for (Iterator i = m_listeners.iterator(); i.hasNext();) {
JSmoothModelBean.Listener l = (JSmoothModelBean.Listener)i.next();
l.dataChanged();
}
}
private void fireSkeletonChanged() {
for (Iterator i = m_skeletonChangedListener.iterator(); i.hasNext();) {
JSmoothModelBean.SkeletonChangedListener l = (JSmoothModelBean.SkeletonChangedListener)i.next();
l.skeletonChanged();
}
}
public void setSkeletonName(String name) {
if (name != m_skeletonName) {
m_skeletonName = name;
fireSkeletonChanged();
fireChanged();
}
}
public String getSkeletonName() {
return m_skeletonName;
}
public void setExecutableName(String name) {
if (name != m_executableName) {
m_executableName = name;
fireChanged();
}
}
public void setCurrentDirectory(String curdir) {
if (curdir != m_currentDirectory) {
m_currentDirectory = curdir;
fireChanged();
}
}
public String getCurrentDirectory() {
return m_currentDirectory;
}
public String getExecutableName() {
return m_executableName;
}
public void setIconLocation(String name) {
if (name != m_iconLocation) {
m_iconLocation = name;
fireChanged();
}
}
public String getIconLocation() {
return m_iconLocation;
}
public boolean getEmbeddedJar() {
return m_embedJar;
}
public void setEmbeddedJar(boolean b) {
m_embedJar = b;
fireChanged();
}
public void setJarLocation(String name) {
if (name != m_jarLocation) {
m_jarLocation = name;
fireChanged();
}
}
public String getJarLocation() {
return m_jarLocation;
}
public void setMainClassName(String name) {
if (name != m_mainClassName) {
m_mainClassName = name;
fireChanged();
}
}
public String getMainClassName() {
return m_mainClassName;
}
public void setArguments(String args) {
m_arguments = args;
fireChanged();
}
public String getArguments() {
return m_arguments;
}
public void setClassPath(String[] cp) {
m_classPath = cp;
fireChanged();
}
public String[] getClassPath() {
return m_classPath;
}
public void setMaximumVersion(String version) {
m_maximumVersion = version;
fireChanged();
}
public String getMaximumVersion() {
return m_maximumVersion;
}
public void setMinimumVersion(String version) {
m_minimumVersion = version;
fireChanged();
}
public String getMinimumVersion() {
return m_minimumVersion;
}
public void setJVMSearchPath(String[] path) {
m_jvmSearch = path;
fireChanged();
}
public String[] getJVMSearchPath() {
return m_jvmSearch;
}
public void setSkeletonProperties(JSmoothModelBean.Property[] props) {
// for (int i=0; i<props.length; i++)
// System.out.println("SET PROPERTY: " + props[i].getIdName() + "=" + props[i].getValue());
m_skelproperties = props;
fireChanged();
}
public JSmoothModelBean.Property[] getSkeletonProperties() {
return m_skelproperties;
}
public void setNoJvmMessage(String msg) {
m_noJvmMessage = msg;
fireChanged();
}
public String getNoJvmMessage() {
return m_noJvmMessage;
}
public void setNoJvmURL(String url) {
m_noJvmURL = url;
fireChanged();
}
public String getNoJvmURL() {
return m_noJvmURL;
}
public String getBundledJVMPath() {
return m_bundledJVM;
}
public void setBundledJVMPath(String path) {
m_bundledJVM = path;
fireChanged();
}
public void setJavaProperties(JavaPropertyPair[] pairs) {
m_javaprops = pairs;
}
public JavaPropertyPair[] getJavaProperties() {
return m_javaprops;
}
public void setMaximumMemoryHeap(int size) {
m_maxHeap = size;
}
public int getMaximumMemoryHeap() {
return m_maxHeap;
}
public void setInitialMemoryHeap(int size) {
m_initialHeap = size;
}
public int getInitialMemoryHeap() {
return m_initialHeap;
}
public void setVmParameter(String parameter) {
m_vmParamter = parameter;
}
public String getVmParameter() {
return m_vmParamter;
}
public void setUacRequireAdministrator(int parameter) {
m_uacRequireAdmin = parameter;
}
public int getUacRequireAdministrator() {
return m_uacRequireAdmin;
}
public boolean isUacRequireAdmin() {
return m_uacRequireAdmin > 0;
}
public String[] normalizePaths(java.io.File filebase) {
return normalizePaths(filebase, true);
}
public String[] normalizePaths(java.io.File filebase, boolean toRelativePath) {
// System.out.println("Normalize Path " + filebase + " / " + toRelativePath);
Vector result = new Vector();
m_iconLocation = checkRelativePath(filebase, m_iconLocation, result, "Icon location", toRelativePath);
m_jarLocation = checkRelativePath(filebase, m_jarLocation, result, "Jar location", toRelativePath);
m_bundledJVM = checkRelativePath(filebase, m_bundledJVM, result, "Bundle JVM location", toRelativePath);
m_executableName = checkRelativePath(filebase, m_executableName, result, "Executable location", toRelativePath);
if (m_executableName != null) {
File exebase = new File(m_executableName);
if (exebase.isAbsolute() == false)
exebase = new File(filebase, exebase.toString()).getParentFile();
// System.out.println("EXE FILEBASE: " + exebase.toString());
if ((m_currentDirectory != null) && (m_currentDirectory.indexOf("${") >= 0))
m_currentDirectory = checkRelativePath(exebase, m_currentDirectory, result, "Current directory", toRelativePath);
}
if (m_classPath != null) {
for (int i = 0; i < m_classPath.length; i++) {
m_classPath[i] = checkRelativePath(filebase, m_classPath[i], result, "Classpath entry (" + i + ")", toRelativePath);
}
}
if (result.size() == 0)
return null;
String[] res = new String[result.size()];
result.toArray(res);
return res;
}
private String checkRelativePath(java.io.File root, String value, java.util.Vector errors, String name, boolean toRelativePath) {
if (value == null)
return value;
if (toRelativePath) {
File nf = JSmoothModelPersistency.makePathRelativeIfPossible(root, new File(value));
if (nf.isAbsolute()) {
errors.add(name);
}
return nf.toString();
} else {
File nf = new File(value);
if (nf.isAbsolute() == false) {
nf = new File(root, value);
nf = nf.getAbsoluteFile();
try {
nf = nf.getCanonicalFile();
nf = nf.getAbsoluteFile();
} catch (IOException iox) {
// do nothing
}
}
return nf.toString();
}
}
}

View File

@ -0,0 +1,250 @@
/*
JSmooth: a VM wrapper toolkit for Windows
Copyright (C) 2003 Rodrigo Reyes <reyes@charabia.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; either version 2 of the License, or
(at your option) any later version.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package net.charabia.jsmoothgen.application;
import java.io.File;
import net.charabia.jsmoothgen.skeleton.SkeletonBean;
/**
* @author Rodrigo
*/
public class PropertiesBuilder {
/**
* Creates a text containing all the relevant properties of a
* JSmoothModelBean object. The properties are output in the form
* "key=value".
* <p/>
* <p/>
* Note that all the paths are converted to be made relative to
* the basedir parameter provided. All the paths converted are
* expected to be relative to the targetted executable binary
* (before the conversion is applied, that is).
*/
static public String makeProperties(File basedir, JSmoothModelBean obj) {
StringBuffer out = new StringBuffer();
addPair("arguments", obj.getArguments(), out);
addPair("mainclassname", obj.getMainClassName(), out);
addPair("jvmsearch", makePathConc(obj.getJVMSearchPath()), out);
addPair("minversion", obj.getMinimumVersion(), out);
addPair("maxversion", obj.getMaximumVersion(), out);
addPair("currentdir", obj.getCurrentDirectory(), out);
if (obj.getEmbeddedJar() && (obj.getJarLocation().trim().length() > 0)) {
addPair("embedjar", "true", out);
} else {
addPair("embedjar", "false", out);
}
if (obj.getMaximumMemoryHeap() > 1) {
addPair("maxheap", Integer.toString(obj.getMaximumMemoryHeap()), out);
}
if (obj.getInitialMemoryHeap() > 1) {
addPair("initialheap", Integer.toString(obj.getInitialMemoryHeap()), out);
}
if ((obj.getVmParameter() != null) && (!obj.getVmParameter().isEmpty())) {
addPair("vmparameter", obj.getVmParameter(), out);
}
// BundledVM & classpaths are changed to be accessible
// from the current directory
File curdir = new File(obj.getExecutableName()).getParentFile();
if (curdir == null)
curdir = basedir.getAbsoluteFile();
if (curdir.isAbsolute() == false) {
curdir = new File(basedir, curdir.toString());
}
// System.out.println("... curdir1 : " + curdir.toString());
if (obj.getCurrentDirectory() != null) {
File newcurdir = new File(obj.getCurrentDirectory());
// System.out.println("... curdir1.5 : " + obj.getCurrentDirectory());
if (!"${EXECUTABLEPATH}".equalsIgnoreCase(obj.getCurrentDirectory())) {
if (newcurdir.isAbsolute() == false) {
curdir = new File(curdir, newcurdir.toString());
} else
curdir = newcurdir;
}
}
// System.out.println("... curdir2 : " + curdir.toString());
if (obj.getBundledJVMPath() != null)
addPair("bundledvm", getRenormalizedPathIfNeeded(obj.getBundledJVMPath(), basedir, curdir), out);
if (obj.getClassPath() != null) {
String[] relcp = new String[obj.getClassPath().length];
for (int i = 0; i < relcp.length; i++) {
relcp[i] = getRenormalizedPathIfNeeded(obj.getClassPath()[i], basedir, curdir);
}
addPair("classpath", makePathConc(relcp), out);
}
//
// Adds all the skeleton-specific properties
//
if (obj.getSkeletonProperties() != null) {
for (int i = 0; i < obj.getSkeletonProperties().length; i++) {
JSmoothModelBean.Property prop = obj.getSkeletonProperties()[i];
if (prop.getKey() != null) {
String val = prop.getValue();
if (val == null)
val = "";
addPair("skel_" + prop.getKey(), val, out);
}
}
}
//
// Adds all the java properties. Those properties are
// typically passed as -Dname=value arguments for the sun's
// JVM.
//
JavaPropertyPair[] javapairs = obj.getJavaProperties();
if (javapairs != null) {
addPair("javapropertiescount", new Integer(javapairs.length).toString(), out);
for (int i = 0; i < javapairs.length; i++) {
addPair("javaproperty_name_" + i, javapairs[i].getName(), out);
addPair("javaproperty_value_" + i, javapairs[i].getValue(), out);
}
}
return out.toString();
}
/**
* Create a manifest entry for windows right elevation
*
* @param data
* @param skel
* @return the manifest xml
*/
public static String makeManifest(JSmoothModelBean data, SkeletonBean skel) {
StringBuilder retVal = new StringBuilder();
String platform = "x86";
String shortName = skel.getShortName();
if (shortName.contains("64")) {
platform = "ia64";
}
retVal.append("<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>").append("\n");
retVal.append("<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">").append("\n");
retVal.append(" <assemblyIdentity type=\"win32\"").append("\n");
retVal.append(" name=\"").append(shortName).append("\"").append("\n");
retVal.append(" version=\"1.0.0.0\"").append("\n");
retVal.append(" processorArchitecture=\"").append(platform).append("\"").append("\n");
retVal.append(" />").append("\n");
retVal.append(" <dependency>").append("\n");
retVal.append(" <dependentAssembly>").append("\n");
retVal
.append(
" <assemblyIdentity type=\"win32\" name=\"Microsoft.Windows.Common-Controls\" version=\"6.0.0.0\" processorArchitecture=\"*\" publicKeyToken=\"6595b64144ccf1df\" language=\"*\"/>")
.append("\n");
retVal.append(" </dependentAssembly>").append("\n");
retVal.append(" </dependency>").append("\n");
if (data.isUacRequireAdmin()) {
retVal.append(" <trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v2\">").append("\n");
retVal.append(" <security>").append("\n");
retVal.append(" <requestedPrivileges>").append("\n");
retVal.append(" <requestedExecutionLevel level=\"requireAdministrator\"/>").append("\n");
retVal.append(" </requestedPrivileges>").append("\n");
retVal.append(" </security>").append("\n");
retVal.append(" </trustInfo>").append("\n");
}
retVal.append("</assembly>");
return retVal.toString();
}
/**
* Converts a path relative to previousbasedir into a path
* relative to newbasedir.
*/
static public String getRenormalizedPathIfNeeded(String value, File previousbasedir, File newbasedir) {
// File f = new File(value);
// if (f.isAbsolute())
// return value;
if (newbasedir == null)
return value;
if (value == null)
return "";
File abs = new File(previousbasedir, value).getAbsoluteFile();
File n = JSmoothModelPersistency.makePathRelativeIfPossible(newbasedir, abs);
return n.toString();
}
static public String escapeString(String str) {
if (str == null)
return "";
StringBuffer out = new StringBuffer();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
switch (c) {
case '\n':
out.append("\\n");
break;
case '\t':
out.append("\\t");
break;
case '\r':
out.append("\\r");
break;
case '\\':
out.append("\\\\");
break;
default:
out.append(c);
}
}
return out.toString();
}
static private void addPair(String name, String value, StringBuffer out) {
out.append(escapeString(name));
out.append("=");
out.append(escapeString(value));
out.append("\n");
}
static public String makePathConc(String[] elements) {
StringBuffer buf = new StringBuffer();
if (elements != null)
for (int i = 0; i < elements.length; i++) {
buf.append(elements[i]);
if ((i + 1) < elements.length)
buf.append(";");
}
return buf.toString();
}
}

View File

@ -0,0 +1,126 @@
/*
JSmooth: a VM wrapper toolkit for Windows
Copyright (C) 2003 Rodrigo Reyes <reyes@charabia.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; either version 2 of the License, or
(at your option) any later version.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package net.charabia.jsmoothgen.application.gui.util;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.io.*;
import java.util.*;
import javax.swing.text.html.*;
import javax.swing.event.*;
import java.net.*;
/**
*
*/
public class HTMLPane extends JPanel
{
private JScrollPane m_scroller;
private JEditorPane m_html;
private URL m_baseurl;
edu.stanford.ejalbert.BrowserLauncher m_launcher;
class Hyperactive implements HyperlinkListener {
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
JEditorPane pane = (JEditorPane)e.getSource();
if (e instanceof HTMLFrameHyperlinkEvent) {
HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent)e;
HTMLDocument doc = (HTMLDocument)pane.getDocument();
doc.processHTMLFrameHyperlinkEvent(evt);
} else {
try {
URL nurl = e.getURL();
if (nurl == null)
nurl = new URL(m_baseurl, e.getDescription());
if (jsmooth.Native.isAvailable())
{
jsmooth.Native.shellExecute(jsmooth.Native.SHELLEXECUTE_OPEN, nurl.toString(), null, null, jsmooth.Native.SW_NORMAL);
}
else
m_launcher.openURLinBrowser(nurl.toExternalForm());
} catch (Throwable t) {
t.printStackTrace();
}
}
}
}
}
public HTMLPane()
{
try {
m_baseurl = new File(".").toURI().toURL();
} catch (Exception ex) { ex.printStackTrace(); }
m_html = new JEditorPane("text/html","<html></html>") {
public boolean getScrollableTracksViewportWidth()
{
return true;
}
};
HTMLEditorKit hek = new HTMLEditorKit();
m_html.setEditorKit(hek);
m_scroller = new JScrollPane(m_html);
setLayout(new BorderLayout());
m_html.setEditable(false);
add(m_scroller, BorderLayout.CENTER);
// add(m_html, BorderLayout.CENTER);
m_html.addHyperlinkListener(new Hyperactive());
try {
m_launcher = new edu.stanford.ejalbert.BrowserLauncher();
}catch (Exception ex)
{
ex.printStackTrace();
}
}
public java.awt.Dimension getPreferredSize()
{
return new java.awt.Dimension(200,200);
}
public void setPage(URL url)
{
try {
URL u = new URL(m_baseurl, url.toExternalForm());
m_html.setPage(u);
} catch (Exception ex) { ex.printStackTrace(); }
}
public void setText(String s)
{
m_html.setContentType("text/html");
m_html.setText(s);
m_html.setCaretPosition(0);
}
}

View File

@ -0,0 +1,478 @@
/*
JSmooth: a VM wrapper toolkit for Windows
Copyright (C) 2003 Rodrigo Reyes <reyes@charabia.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; either version 2 of the License, or
(at your option) any later version.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* PEFile.java
*
* Created on 28 juillet 2003, 21:28
*/
package net.charabia.jsmoothgen.pe;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Vector;
import net.charabia.jsmoothgen.pe.res.ResIcon;
import net.charabia.jsmoothgen.pe.res.ResIconDir;
/**
* @author Rodrigo
*/
public class PEFile {
private File m_file;
private FileInputStream m_in = null;
private FileChannel m_channel = null;
private PEOldMSHeader m_oldmsheader;
private PEHeader m_header;
private Vector m_sections = new Vector();
private PEResourceDirectory m_resourceDir;
/**
* Creates a new instance of PEFile
*/
public PEFile(File f) {
m_file = f;
}
public void close() throws IOException {
m_in.close();
}
public void open() throws FileNotFoundException, IOException {
m_in = new FileInputStream(m_file);
m_channel = m_in.getChannel();
m_oldmsheader = new PEOldMSHeader(this);
m_oldmsheader.read();
// m_oldmsheader.dump(System.out);
long headoffset = m_oldmsheader.e_lfanew;
m_header = new PEHeader(this, headoffset);
m_header.read();
// m_header.dump(System.out);
int seccount = m_header.NumberOfSections;
// System.out.println("LOADING " + seccount + " sections...");
long offset = headoffset + (m_header.NumberOfRvaAndSizes * 8) + 24 + getPeHeaderOffset();
for (int i = 0; i < seccount; i++) {
// System.out.println("Offset: " + offset + " (" + this.m_channel.position());
PESection sect = new PESection(this, offset);
sect.read();
// sect.dump(System.out);
m_sections.add(sect);
offset += 40;
}
// System.out.println("After sections: " + this.m_channel.position() + " (" + offset + ")");
ByteBuffer resbuf = null;
long resourceoffset = m_header.ResourceDirectory_VA;
for (int i = 0; i < seccount; i++) {
PESection sect = (PESection)m_sections.get(i);
if (sect.VirtualAddress == resourceoffset) {
// System.out.println(" Resource section found: " + resourceoffset);
PEResourceDirectory prd = new PEResourceDirectory(this, sect);
resbuf = prd.buildResource(sect.VirtualAddress);
break;
}
}
}
private int getPeHeaderOffset() {
int pe32Offset = 96;
if (m_header.isPe32Plus()) {
// It is a pe32+ header (x64)
pe32Offset = 112;
}
return pe32Offset;
}
public FileChannel getChannel() {
return m_channel;
}
public static void main(String args[]) throws IOException, CloneNotSupportedException, Exception {
// (no)PEFile pe = new PEFile(new File("F:/Program Files/LAN Search PRO/lansearch.exe"));
PEFile pe = new PEFile(new File("c:/scratch/rc3.exe"));
// PEFile pe = new PEFile(new File("c:/projects/jwrap/Copie.exe"));
// PEFile pe = new PEFile(new File("c:/projects/jwrap/test.exe"));
// PEFile pe = new PEFile(new File("F:/Program Files/bQuery/bQuery.exe"));
// PEFile pe = new PEFile(new File("F:/Program Files/Server Query/query.exe"));
// PEFile pe = new PEFile(new File("F:/Program Files/AvRack/rtlrack.exe"));
pe.open();
System.out.println("OldMSHeader");
pe.m_oldmsheader.dump(System.out);
System.out.println("COFFHeader");
pe.m_header.dump(System.out);
// System.out.println("===============\nADDING A RES");
// File fout = new File("F:/Documents and Settings/Rodrigo/Mes documents/projects/jsmooth/skeletons/simplewrap/gen-application.jar");
// FileInputStream fis = new FileInputStream(fout);
//
// ByteBuffer data = ByteBuffer.allocate((int)fout.length());
// data.order(ByteOrder.LITTLE_ENDIAN);
// FileChannel fischan = fis.getChannel();
// fischan.read(data);
// data.position(0);
// fis.close();
PEResourceDirectory resdir = pe.getResourceDirectory();
System.out.println("ResourceDirectory");
resdir.dump(System.out);
// DataEntry inputResData = resdir.getData("JAVA", "#" + String.valueOf(103), "#" + String.valueOf(1033));
// ByteBuffer inputResDataBuffer = ByteBuffer.allocate(inputResData.diskSize() + 1024);
// inputResDataBuffer.order(ByteOrder.LITTLE_ENDIAN);
// inputResData.buildBuffer(inputResDataBuffer, 0, 0);
// int inputResDataBufferSize = inputResDataBuffer.position();
// inputResDataBuffer.flip();
// int offset = inputResDataBuffer.getInt();
// inputResDataBuffer.position(offset);
// StringBuilder inputResDataString = new StringBuilder(inputResDataBufferSize);
// while (inputResDataBuffer.position() <= inputResDataBufferSize - 2) {
// byte dummyByte = inputResDataBuffer.get();
// inputResDataString.append((char)dummyByte);
// }
// // Modify the data...
// String newInputResDataString = inputResDataString.toString();
// newInputResDataString = newInputResDataString.replace("samplejar", "ThisIsMyJarAndOnlyMine");
//
// inputResDataBuffer = ByteBuffer.allocate(newInputResDataString.length() + 2);
// for (int index = 0; index < newInputResDataString.length(); index++) { // C- do not change because buffer can be modified during loop
// inputResDataBuffer.put((byte)newInputResDataString.charAt(index));
// }
// inputResDataBuffer.put((byte)0);
// inputResDataBuffer.put((byte)0);
// inputResDataBuffer.position(0);
//
// boolean resb = resdir.replaceResource("JAVA", 102, 1033, inputResDataBuffer);
// PEResourceDirectory.DataEntry entry = resdir.getData("#14", "A", "#1033");
// entry.Data.position(0);
// System.out.println("DataEntry found : " + entry + " (size=" + entry.Data.remaining() + ")");
// entry.Data.position(0);
//
// ResIconDir rid = new ResIconDir(entry.Data);
// System.out.println("ResIconDir :");
// System.out.println(rid.toString());
// int iconid = rid.getEntries()[0].dwImageOffset;
// System.out.println("Icon Index: " + iconid);
//
// PEResourceDirectory.DataEntry iconentry = resdir.getData("#3", "#"+iconid, "#1033");
// iconentry.Data.position(0);
// ResIcon icon = new ResIcon(iconentry.Data);
// System.out.println("Icon :");
// System.out.println(icon.toString());
// java.awt.Image img = java.awt.Toolkit.getDefaultToolkit().getImage ("c:\\test.gif");
// java.awt.Image img = java.awt.Toolkit.getDefaultToolkit().getImage ("c:\\gnome-day2.png");
// java.awt.Image img = java.awt.Toolkit.getDefaultToolkit().getImage("c:\\gnome-color-browser2.png");
//
// java.awt.MediaTracker mt = new java.awt.MediaTracker(new javax.swing.JLabel("toto"));
// mt.addImage(img, 1);
// try {
// mt.waitForAll();
// } catch (Exception exc) {
// exc.printStackTrace();
// }
//
// ResIcon newicon = new ResIcon(img);
//
// pe.replaceDefaultIcon(newicon);
// System.out.println("-----------------\nNEW ICON:");
// System.out.println(newicon.toString());
//
// rid.getEntries()[0].bWidth = (short)newicon.Width;
// rid.getEntries()[0].bHeight = (short)(newicon.Height/2);
// rid.getEntries()[0].bColorCount = (short)(1 <<newicon.BitsPerPixel);
// rid.getEntries()[0].wBitCount = newicon.BitsPerPixel;
// rid.getEntries()[0].dwBytesInRes = newicon.getData().remaining();
//
// iconentry.Data = newicon.getData();
// iconentry.Size = iconentry.Data.remaining();
//
// entry.setData(rid.getData());
// System.out.println("POST CHANGE ResIconDir :");
// System.out.println(rid.toString());
// ResIcon test = new ResIcon(icon.getData());
// System.out.println("PROOF-TEST:\n" + test.toString());
// / BACK
//
// rid.getEntries()[0].bWidth = (short)icon.Width;
// rid.getEntries()[0].bHeight = (short)(icon.Height/2);
// rid.getEntries()[0].bColorCount = (short)(1 <<icon.BitsPerPixel);
// rid.getEntries()[0].wBitCount = icon.BitsPerPixel;
// iconentry.Data = icon.getData();
// iconentry.Size = iconentry.Data.remaining();
// resdir.addNewResource("POUET", "A666", "#1033", data);
// resdir.dump(System.out);
// System.out.println("New size = " + resdir.size());
File out = new File("c:/scratch/COPIE.exe");
pe.dumpTo(out);
}
public PEResourceDirectory getResourceDirectory() throws IOException {
if (m_resourceDir != null)
return m_resourceDir;
long resourceoffset = m_header.ResourceDirectory_VA;
for (int i = 0; i < m_sections.size(); i++) {
PESection sect = (PESection)m_sections.get(i);
if (sect.VirtualAddress == resourceoffset) {
m_resourceDir = new PEResourceDirectory(this, sect);
return m_resourceDir;
}
}
return null;
}
public void dumpTo(File destination) throws IOException, CloneNotSupportedException {
int outputcount = 0;
FileOutputStream fos = new FileOutputStream(destination);
FileChannel out = fos.getChannel();
//
// Make a copy of the Header, for safe modifications
//
PEOldMSHeader oldmsheader = (PEOldMSHeader)this.m_oldmsheader.clone();
PEHeader peheader = (PEHeader)m_header.clone();
Vector sections = new Vector();
for (int i = 0; i < m_sections.size(); i++) {
PESection sect = (PESection)m_sections.get(i);
PESection cs = (PESection)sect.clone();
sections.add(cs);
}
//
// First, write the old MS Header, the one starting
// with "MZ"...
//
long newexeoffset = oldmsheader.e_lfanew;
ByteBuffer msheadbuffer = oldmsheader.get();
outputcount = out.write(msheadbuffer);
this.m_channel.position(64);
out.transferFrom(this.m_channel, 64, newexeoffset - 64);
//
// Then Write the new Header...
//
ByteBuffer headbuffer = peheader.get();
out.position(newexeoffset);
outputcount = out.write(headbuffer);
//
// After the header, there are all the section
// headers...
//
long offset = oldmsheader.e_lfanew + (m_header.NumberOfRvaAndSizes * 8) + 24 + getPeHeaderOffset();
out.position(offset);
for (int i = 0; i < sections.size(); i++) {
// System.out.println(" offset: " + out.position());
PESection sect = (PESection)sections.get(i);
ByteBuffer buf = sect.get();
outputcount = out.write(buf);
}
//
// Now, we write the real data: each of the section
// and their data...
//
// Not sure why it's always at 1024... ?
offset = 1024;
//
// Dump each section data
//
long virtualAddress = offset;
if ((virtualAddress % peheader.SectionAlignment) > 0)
virtualAddress += peheader.SectionAlignment - (virtualAddress % peheader.SectionAlignment);
long resourceoffset = m_header.ResourceDirectory_VA;
for (int i = 0; i < sections.size(); i++) {
PESection sect = (PESection)sections.get(i);
if (resourceoffset == sect.VirtualAddress) {
// System.out.println("Dumping RES section " + i + " at " + offset + " from " + sect.PointerToRawData + " (VA=" + virtualAddress + ")");
out.position(offset);
long sectoffset = offset;
PEResourceDirectory prd = this.getResourceDirectory();
ByteBuffer resbuf = prd.buildResource(sect.VirtualAddress);
resbuf.position(0);
out.write(resbuf);
offset += resbuf.capacity();
long rem = offset % this.m_header.FileAlignment;
if (rem != 0)
offset += this.m_header.FileAlignment - rem;
if (out.size() + 1 < offset) {
ByteBuffer padder = ByteBuffer.allocate(1);
out.write(padder, offset - 1);
}
long virtualSize = resbuf.capacity();
if ((virtualSize % peheader.SectionAlignment) > 0)
virtualSize += peheader.SectionAlignment - (virtualSize % peheader.SectionAlignment);
sect.PointerToRawData = sectoffset;
sect.SizeOfRawData = resbuf.capacity();
if ((sect.SizeOfRawData % this.m_header.FileAlignment) > 0)
sect.SizeOfRawData += (this.m_header.FileAlignment - (sect.SizeOfRawData % this.m_header.FileAlignment));
sect.VirtualAddress = virtualAddress;
sect.VirtualSize = virtualSize;
// System.out.println(" VS=" + virtualSize + " at VA=" + virtualAddress);
virtualAddress += virtualSize;
} else if (sect.PointerToRawData > 0) {
// System.out.println("Dumping section " + i + "/" + sect.getName() + " at " + offset + " from " + sect.PointerToRawData + " (VA=" + virtualAddress + ")");
out.position(offset);
this.m_channel.position(sect.PointerToRawData);
long sectoffset = offset;
out.position(offset + sect.SizeOfRawData);
ByteBuffer padder = ByteBuffer.allocate(1);
out.write(padder, offset + sect.SizeOfRawData - 1);
long outted = out.transferFrom(this.m_channel, offset, sect.SizeOfRawData);
offset += sect.SizeOfRawData;
// System.out.println("offset before alignment, " + offset);
long rem = offset % this.m_header.FileAlignment;
if (rem != 0) {
offset += this.m_header.FileAlignment - rem;
}
// System.out.println("offset after alignment, " + offset);
// long virtualSize = sect.SizeOfRawData;
// if ((virtualSize % peheader.SectionAlignment)>0)
// virtualSize += peheader.SectionAlignment - (virtualSize%peheader.SectionAlignment);
sect.PointerToRawData = sectoffset;
// sect.SizeOfRawData =
sect.VirtualAddress = virtualAddress;
// sect.VirtualSize = virtualSize;
virtualAddress += sect.VirtualSize;
if ((virtualAddress % peheader.SectionAlignment) > 0)
virtualAddress += peheader.SectionAlignment - (virtualAddress % peheader.SectionAlignment);
} else {
// generally a BSS, with a virtual size but no
// data in the file...
// System.out.println("Dumping section " + i + " at " + offset + " from " + sect.PointerToRawData + " (VA=" + virtualAddress + ")");
long virtualSize = sect.VirtualSize;
if ((virtualSize % peheader.SectionAlignment) > 0)
virtualSize += peheader.SectionAlignment - (virtualSize % peheader.SectionAlignment);
sect.VirtualAddress = virtualAddress;
// sect.VirtualSize = virtualSize;
virtualAddress += virtualSize;
}
}
//
// Now that all the sections have been written, we have the
// correct VirtualAddress and Sizes, so we can update the new
// header and all the section headers...
peheader.updateVAAndSize(m_sections, sections);
headbuffer = peheader.get();
out.position(newexeoffset);
outputcount = out.write(headbuffer);
// peheader.dump(System.out);
// System.out.println("Dumping the section again...");
offset = oldmsheader.e_lfanew + (m_header.NumberOfRvaAndSizes * 8) + 24 + getPeHeaderOffset();
out.position(offset);
for (int i = 0; i < sections.size(); i++) {
// System.out.println(" offset: " + out.position());
PESection sect = (PESection)sections.get(i);
// sect.dump(System.out);
ByteBuffer buf = sect.get();
outputcount = out.write(buf);
}
fos.flush();
fos.close();
}
/*
*/
public void replaceDefaultIcon(ResIcon icon) throws Exception {
PEResourceDirectory resdir = getResourceDirectory();
PEResourceDirectory.DataEntry entry = resdir.getData("#14", null, null);
if (entry == null) {
throw new Exception("Can't find any icon group in the file!");
}
entry.Data.position(0);
// System.out.println("DataEntry found : " + entry + " (size=" + entry.Data.remaining() + ")");
entry.Data.position(0);
ResIconDir rid = new ResIconDir(entry.Data);
// System.out.println("ResIconDir :");
// System.out.println(rid.toString());
int iconid = rid.getEntries()[0].dwImageOffset;
// System.out.println("Icon Index: " + iconid);
PEResourceDirectory.DataEntry iconentry = resdir.getData("#3", "#" + iconid, null);
iconentry.Data.position(0);
// System.out.println("Icon :");
// System.out.println(icon.toString());
rid.getEntries()[0].bWidth = (short)icon.Width;
rid.getEntries()[0].bHeight = (short)(icon.Height / 2);
rid.getEntries()[0].bColorCount = (short)(1 << icon.BitsPerPixel);
rid.getEntries()[0].wBitCount = icon.BitsPerPixel;
rid.getEntries()[0].dwBytesInRes = icon.getData().remaining();
iconentry.Data = icon.getData();
iconentry.Size = iconentry.Data.remaining();
entry.setData(rid.getData());
}
}

View File

@ -0,0 +1,482 @@
/*
JSmooth: a VM wrapper toolkit for Windows
Copyright (C) 2003 Rodrigo Reyes <reyes@charabia.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; either version 2 of the License, or
(at your option) any later version.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* PEHeader.java
*
* Created on 28 juillet 2003, 21:38
*/
package net.charabia.jsmoothgen.pe;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.util.Vector;
/**
* @author Rodrigo Reyes
*/
public class PEHeader implements Cloneable {
private int PeMagic; // 0
public int Machine; // 4
public int NumberOfSections; // 6
public long TimeDateStamp; // 8
public long PointerToSymbolTable; // C
public long NumberOfSymbols; // 10
public int SizeOfOptionalHeader; // 14
public int Characteristics; // 16
// Optional Header
public int Magic; // 18
public short MajorLinkerVersion; // 1a
public short MinorLinkerVersion; // 1b
public long SizeOfCode; // 1c
public long SizeOfInitializedData; // 20
public long SizeOfUninitializedData; // 24
public long AddressOfEntryPoint; // 28
public long BaseOfCode; // 2c
public long BaseOfData; // NT additional fields. 30
public long ImageBase; // 34
public long SectionAlignment; // 38
public long FileAlignment; // 3c
public int MajorOperatingSystemVersion; // 40
public int MinorOperatingSystemVersion; // 42
public int MajorImageVersion; // 44
public int MinorImageVersion; // 46
public int MajorSubsystemVersion; // 48
public int MinorSubsystemVersion; // 4a
public long Reserved1; // 4c
public long SizeOfImage; // 50
public long SizeOfHeaders; // 54
public long CheckSum; // 58
public int Subsystem; // 5c
public int DllCharacteristics; // 5e
public long SizeOfStackReserve; // 60
public long SizeOfStackCommit; // 64
public long SizeOfHeapReserve; // 68
public long SizeOfHeapCommit; // 6c
public long LoaderFlags; // 70
public long NumberOfRvaAndSizes; // 74
public long ExportDirectory_VA; // 78
public long ExportDirectory_Size; // 7c
public long ImportDirectory_VA; // 80
public long ImportDirectory_Size; // 84
public long ResourceDirectory_VA; // 88
public long ResourceDirectory_Size; // 8c
public long ExceptionDirectory_VA; // 90
public long ExceptionDirectory_Size; // 94
public long SecurityDirectory_VA; // 98
public long SecurityDirectory_Size; // 9c
public long BaseRelocationTable_VA; // a0
public long BaseRelocationTable_Size; // a4
public long DebugDirectory_VA; // a8
public long DebugDirectory_Size; // ac
public long ArchitectureSpecificData_VA; // b0
public long ArchitectureSpecificData_Size; // b4
public long RVAofGP_VA; // b8
public long RVAofGP_Size; // bc
public long TLSDirectory_VA; // c0
public long TLSDirectory_Size; // c4
public long LoadConfigurationDirectory_VA; // c8
public long LoadConfigurationDirectory_Size; // cc
public long BoundImportDirectoryinheaders_VA; // d0
public long BoundImportDirectoryinheaders_Size; // d4
public long ImportAddressTable_VA; // d8
public long ImportAddressTable_Size; // dc
public long DelayLoadImportDescriptors_VA; // e0
public long DelayLoadImportDescriptors_Size; // e4
public long COMRuntimedescriptor_VA; // e8
public long COMRuntimedescriptor_Size; // ec
private long m_baseoffset;
private PEFile m_pe;
/**
* Creates a new instance of PEHeader
*/
public PEHeader(PEFile pef, long baseoffset) {
m_pe = pef;
m_baseoffset = baseoffset;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public void read() throws IOException {
FileChannel ch = m_pe.getChannel();
ByteBuffer head = ByteBuffer.allocate(350);
head.order(ByteOrder.LITTLE_ENDIAN);
ch.position(m_baseoffset);
ch.read(head);
head.position(0);
PeMagic = head.getInt();
// System.out.println("MAGIC::: " + pemagic);
Machine = head.getShort(); // 4
NumberOfSections = head.getShort(); // 6
TimeDateStamp = head.getInt(); // 8
PointerToSymbolTable = head.getInt(); // C
NumberOfSymbols = head.getInt(); // 10
SizeOfOptionalHeader = head.getShort(); // 14
Characteristics = head.getShort(); // 16
// Optional Header
Magic = head.getShort(); // 18
MajorLinkerVersion = head.get(); // 1a
MinorLinkerVersion = head.get(); // 1b
SizeOfCode = head.getInt(); // 1c
SizeOfInitializedData = head.getInt(); // 20
SizeOfUninitializedData = head.getInt(); // 24
AddressOfEntryPoint = head.getInt(); // 28
BaseOfCode = head.getInt(); // 2c
if (isPe32Plus()) {
ImageBase = head.getLong(); // 34
} else {
BaseOfData = head.getInt(); // // NT additional fields. // 30
ImageBase = head.getInt(); // 34
}
SectionAlignment = head.getInt(); // 38
FileAlignment = head.getInt(); // 3c
MajorOperatingSystemVersion = head.getShort(); // 40
MinorOperatingSystemVersion = head.getShort(); // 42
MajorImageVersion = head.getShort(); // 44
MinorImageVersion = head.getShort(); // 46
MajorSubsystemVersion = head.getShort(); // 48
MinorSubsystemVersion = head.getShort(); // 4a
Reserved1 = head.getInt(); // 4c
SizeOfImage = head.getInt(); // 50
SizeOfHeaders = head.getInt(); // 54
CheckSum = head.getInt(); // 58
Subsystem = head.getShort(); // 5c
DllCharacteristics = head.getShort(); // 5e
if (isPe32Plus()) {
SizeOfStackReserve = head.getLong(); // 60
SizeOfStackCommit = head.getLong(); // 64
SizeOfHeapReserve = head.getLong(); // 68
SizeOfHeapCommit = head.getLong(); // 6c
} else {
SizeOfStackReserve = head.getInt(); // 60
SizeOfStackCommit = head.getInt(); // 64
SizeOfHeapReserve = head.getInt(); // 68
SizeOfHeapCommit = head.getInt(); // 6c
}
LoaderFlags = head.getInt(); // 70
NumberOfRvaAndSizes = head.getInt(); // 74
ExportDirectory_VA = head.getInt(); // 78
ExportDirectory_Size = head.getInt(); // 7c
ImportDirectory_VA = head.getInt(); // 80
ImportDirectory_Size = head.getInt(); // 84
ResourceDirectory_VA = head.getInt(); // 88
ResourceDirectory_Size = head.getInt(); // 8c
ExceptionDirectory_VA = head.getInt(); // 90
ExceptionDirectory_Size = head.getInt(); // 94
SecurityDirectory_VA = head.getInt(); // 98
SecurityDirectory_Size = head.getInt(); // 9c
BaseRelocationTable_VA = head.getInt(); // a0
BaseRelocationTable_Size = head.getInt(); // a4
DebugDirectory_VA = head.getInt(); // a8
DebugDirectory_Size = head.getInt(); // ac
ArchitectureSpecificData_VA = head.getInt(); // b0
ArchitectureSpecificData_Size = head.getInt(); // b4
RVAofGP_VA = head.getInt(); // b8
RVAofGP_Size = head.getInt(); // bc
TLSDirectory_VA = head.getInt(); // c0
TLSDirectory_Size = head.getInt(); // c4
LoadConfigurationDirectory_VA = head.getInt(); // c8
LoadConfigurationDirectory_Size = head.getInt(); // cc
BoundImportDirectoryinheaders_VA = head.getInt(); // d0
BoundImportDirectoryinheaders_Size = head.getInt(); // d4
ImportAddressTable_VA = head.getInt(); // d8
ImportAddressTable_Size = head.getInt(); // dc
DelayLoadImportDescriptors_VA = head.getInt(); // e0
DelayLoadImportDescriptors_Size = head.getInt(); // e4
COMRuntimedescriptor_VA = head.getInt(); // e8
COMRuntimedescriptor_Size = head.getInt(); // ec
}
public void dump(PrintStream out) {
out.println("HEADER:");
out.println("int Machine=" + Machine + " // 4");
out.println("int NumberOfSections=" + NumberOfSections + " // 6");
out.println("long TimeDateStamp=" + TimeDateStamp + " // 8");
out.println("long PointerToSymbolTable=" + PointerToSymbolTable + " // C");
out.println("long NumberOfSymbols=" + NumberOfSymbols + " // 10");
out.println("int SizeOfOptionalHeader=" + SizeOfOptionalHeader + " // 14");
out.println("int Characteristics=" + Characteristics + " // 16");
// Optional Header
out.println("int Magic=" + Magic + " // 18");
out.println("short MajorLinkerVersion=" + MajorLinkerVersion + " // 1a");
out.println("short MinorLinkerVersion=" + MinorLinkerVersion + " // 1b");
out.println("long SizeOfCode=" + SizeOfCode + " // 1c");
out.println("long SizeOfInitializedData=" + SizeOfInitializedData + " // 20");
out.println("long SizeOfUninitializedData=" + SizeOfUninitializedData + " // 24");
out.println("long AddressOfEntryPoint=" + AddressOfEntryPoint + " // 28");
out.println("long BaseOfCode=" + BaseOfCode + " // 2c");
out.println("long BaseOfData=" + BaseOfData + " // // NT additional fields. // 30");
//
out.println("long ImageBase=" + ImageBase + " // 34");
out.println("long SectionAlignment=" + SectionAlignment + " // 38");
out.println("long FileAlignment=" + FileAlignment + " // 3c");
out.println("int MajorOperatingSystemVersion=" + MajorOperatingSystemVersion + " // 40");
out.println("int MinorOperatingSystemVersion=" + MinorOperatingSystemVersion + " // 42");
out.println("int MajorImageVersion=" + MajorImageVersion + " // 44");
out.println("int MinorImageVersion=" + MinorImageVersion + " // 46");
out.println("int MajorSubsystemVersion=" + MajorSubsystemVersion + " // 48");
out.println("int MinorSubsystemVersion=" + MinorSubsystemVersion + " // 4a");
out.println("long Reserved1=" + Reserved1 + " // 4c");
out.println("long SizeOfImage=" + SizeOfImage + " // 50");
out.println("long SizeOfHeaders=" + SizeOfHeaders + " // 54");
out.println("long CheckSum=" + CheckSum + " // 58");
out.println("int Subsystem=" + Subsystem + " // 5c");
out.println("int DllCharacteristics=" + DllCharacteristics + " // 5e");
out.println("long SizeOfStackReserve=" + SizeOfStackReserve + " // 60");
out.println("long SizeOfStackCommit=" + SizeOfStackCommit + " // 64");
out.println("long SizeOfHeapReserve=" + SizeOfHeapReserve + " // 68");
out.println("long SizeOfHeapCommit=" + SizeOfHeapCommit + " // 6c");
out.println("long LoaderFlags=" + LoaderFlags + " // 70");
out.println("long NumberOfRvaAndSizes=" + NumberOfRvaAndSizes + " // 74");
out.println("long ExportDirectory_VA=" + ExportDirectory_VA + " // 78");
out.println("long ExportDirectory_Size=" + ExportDirectory_Size + " // 7c");
out.println("long ImportDirectory_VA=" + ImportDirectory_VA + " // 80");
out.println("long ImportDirectory_Size=" + ImportDirectory_Size + " // 84");
out.println("long ResourceDirectory_VA=" + ResourceDirectory_VA + " // 88");
out.println("long ResourceDirectory_Size=" + ResourceDirectory_Size + " // 8c");
out.println("long ExceptionDirectory_VA=" + ExceptionDirectory_VA + " // 90");
out.println("long ExceptionDirectory_Size=" + ExceptionDirectory_Size + " // 94");
out.println("long SecurityDirectory_VA=" + SecurityDirectory_VA + " // 98");
out.println("long SecurityDirectory_Size=" + SecurityDirectory_Size + " // 9c");
out.println("long BaseRelocationTable_VA=" + BaseRelocationTable_VA + " // a0");
out.println("long BaseRelocationTable_Size=" + BaseRelocationTable_Size + " // a4");
out.println("long DebugDirectory_VA=" + DebugDirectory_VA + " // a8");
out.println("long DebugDirectory_Size=" + DebugDirectory_Size + " // ac");
out.println("long ArchitectureSpecificData_VA=" + ArchitectureSpecificData_VA + " // b0");
out.println("long ArchitectureSpecificData_Size=" + ArchitectureSpecificData_Size + " // b4");
out.println("long RVAofGP_VA=" + RVAofGP_VA + " // b8");
out.println("long RVAofGP_Size=" + RVAofGP_Size + " // bc");
out.println("long TLSDirectory_VA=" + TLSDirectory_VA + " // c0");
out.println("long TLSDirectory_Size=" + TLSDirectory_Size + " // c4");
out.println("long LoadConfigurationDirectory_VA=" + LoadConfigurationDirectory_VA + " // c8");
out.println("long LoadConfigurationDirectory_Size=" + LoadConfigurationDirectory_Size + " // cc");
out.println("long BoundImportDirectoryinheaders_VA=" + BoundImportDirectoryinheaders_VA + " // d0");
out.println("long BoundImportDirectoryinheaders_Size=" + BoundImportDirectoryinheaders_Size + " // d4");
out.println("long ImportAddressTable_VA=" + ImportAddressTable_VA + " // d8");
out.println("long ImportAddressTable_Size=" + ImportAddressTable_Size + " // dc");
out.println("long DelayLoadImportDescriptors_VA=" + DelayLoadImportDescriptors_VA + " // e0");
out.println("long DelayLoadImportDescriptors_Size=" + DelayLoadImportDescriptors_Size + " // e4");
out.println("long COMRuntimedescriptor_VA=" + COMRuntimedescriptor_VA + " // e8");
out.println("long COMRuntimedescriptor_Size=" + COMRuntimedescriptor_Size + " // ec");
}
public ByteBuffer get() {
ByteBuffer head = ByteBuffer.allocate(16 + this.SizeOfOptionalHeader);
head.order(ByteOrder.LITTLE_ENDIAN);
head.position(0);
head.putInt(PeMagic);
head.putShort((short)Machine); // 4
head.putShort((short)NumberOfSections); // 6
head.putInt((int)TimeDateStamp); // 8
head.putInt((int)PointerToSymbolTable); // C
head.putInt((int)NumberOfSymbols); // 10
head.putShort((short)SizeOfOptionalHeader); // 14
head.putShort((short)Characteristics); // 16
// Optional Header
head.putShort((short)Magic); // 18
head.put((byte)MajorLinkerVersion); // 1a
head.put((byte)MinorLinkerVersion); // 1b
head.putInt((int)SizeOfCode); // 1c
head.putInt((int)SizeOfInitializedData); // 20
head.putInt((int)SizeOfUninitializedData); // 24
head.putInt((int)AddressOfEntryPoint); // 28
head.putInt((int)BaseOfCode); // 2c
if (isPe32Plus()) {
head.putLong(ImageBase); // 34
} else {
head.putInt((int)BaseOfData); // // NT additional fields. // 30
head.putInt((int)ImageBase); // 34
}
head.putInt((int)SectionAlignment); // 38
head.putInt((int)FileAlignment); // 3c
head.putShort((short)MajorOperatingSystemVersion); // 40
head.putShort((short)MinorOperatingSystemVersion); // 42
head.putShort((short)MajorImageVersion); // 44
head.putShort((short)MinorImageVersion); // 46
head.putShort((short)MajorSubsystemVersion); // 48
head.putShort((short)MinorSubsystemVersion); // 4a
head.putInt((int)Reserved1); // 4c
head.putInt((int)SizeOfImage); // 50
head.putInt((int)SizeOfHeaders); // 54
head.putInt((int)CheckSum); // 58
head.putShort((short)Subsystem); // 5c
head.putShort((short)DllCharacteristics); // 5e
if (isPe32Plus()) {
head.putLong(SizeOfStackReserve); // 60
head.putLong(SizeOfStackCommit); // 64
head.putLong(SizeOfHeapReserve); // 68
head.putLong(SizeOfHeapCommit); // 6c
} else {
head.putInt((int)SizeOfStackReserve); // 60
head.putInt((int)SizeOfStackCommit); // 64
head.putInt((int)SizeOfHeapReserve); // 68
head.putInt((int)SizeOfHeapCommit); // 6c
}
head.putInt((int)LoaderFlags); // 70
head.putInt((int)NumberOfRvaAndSizes); // 74
head.putInt((int)ExportDirectory_VA); // 78
head.putInt((int)ExportDirectory_Size); // 7c
head.putInt((int)ImportDirectory_VA); // 80
head.putInt((int)ImportDirectory_Size); // 84
head.putInt((int)ResourceDirectory_VA); // 88
head.putInt((int)ResourceDirectory_Size); // 8c
head.putInt((int)ExceptionDirectory_VA); // 90
head.putInt((int)ExceptionDirectory_Size); // 94
head.putInt((int)SecurityDirectory_VA); // 98
head.putInt((int)SecurityDirectory_Size); // 9c
head.putInt((int)BaseRelocationTable_VA); // a0
head.putInt((int)BaseRelocationTable_Size); // a4
head.putInt((int)DebugDirectory_VA); // a8
head.putInt((int)DebugDirectory_Size); // ac
head.putInt((int)ArchitectureSpecificData_VA); // b0
head.putInt((int)ArchitectureSpecificData_Size); // b4
head.putInt((int)RVAofGP_VA); // b8
head.putInt((int)RVAofGP_Size); // bc
head.putInt((int)TLSDirectory_VA); // c0
head.putInt((int)TLSDirectory_Size); // c4
head.putInt((int)LoadConfigurationDirectory_VA); // c8
head.putInt((int)LoadConfigurationDirectory_Size); // cc
head.putInt((int)BoundImportDirectoryinheaders_VA); // d0
head.putInt((int)BoundImportDirectoryinheaders_Size); // d4
head.putInt((int)ImportAddressTable_VA); // d8
head.putInt((int)ImportAddressTable_Size); // dc
head.putInt((int)DelayLoadImportDescriptors_VA); // e0
head.putInt((int)DelayLoadImportDescriptors_Size); // e4
head.putInt((int)COMRuntimedescriptor_VA); // e8
head.putInt((int)COMRuntimedescriptor_Size); // ec
head.position(0);
return head;
}
public void updateVAAndSize(Vector oldsections, Vector newsections) {
long codebase = findNewVA(this.BaseOfCode, oldsections, newsections);
long codesize = findNewSize(this.BaseOfCode, oldsections, newsections);
// System.out.println("New BaseOfCode=" + codebase + " (size=" + codesize + ")");
this.BaseOfCode = codebase;
this.SizeOfCode = codesize;
this.AddressOfEntryPoint = findNewVA(this.AddressOfEntryPoint, oldsections, newsections);
long database = findNewVA(this.BaseOfData, oldsections, newsections);
long datasize = findNewSize(this.BaseOfData, oldsections, newsections);
// System.out.println("New BaseOfData=" + database + " (size=" + datasize + ")");
this.BaseOfData = database;
long imagesize = 0;
for (int i = 0; i < newsections.size(); i++) {
PESection sect = (PESection)newsections.get(i);
long curmax = sect.VirtualAddress + sect.VirtualSize;
if (curmax > imagesize)
imagesize = curmax;
}
this.SizeOfImage = imagesize;
// this.SizeOfInitializedData = datasize;
ExportDirectory_Size = findNewSize(ExportDirectory_VA, oldsections, newsections);
ExportDirectory_VA = findNewVA(ExportDirectory_VA, oldsections, newsections);
ImportDirectory_Size = findNewSize(ImportDirectory_VA, oldsections, newsections);
ImportDirectory_VA = findNewVA(ImportDirectory_VA, oldsections, newsections);
ResourceDirectory_Size = findNewSize(ResourceDirectory_VA, oldsections, newsections);
ResourceDirectory_VA = findNewVA(ResourceDirectory_VA, oldsections, newsections);
ExceptionDirectory_Size = findNewSize(ExceptionDirectory_VA, oldsections, newsections);
ExceptionDirectory_VA = findNewVA(ExceptionDirectory_VA, oldsections, newsections);
SecurityDirectory_Size = findNewSize(SecurityDirectory_VA, oldsections, newsections);
SecurityDirectory_VA = findNewVA(SecurityDirectory_VA, oldsections, newsections);
BaseRelocationTable_Size = findNewSize(BaseRelocationTable_VA, oldsections, newsections);
BaseRelocationTable_VA = findNewVA(BaseRelocationTable_VA, oldsections, newsections);
DebugDirectory_Size = findNewSize(DebugDirectory_VA, oldsections, newsections);
DebugDirectory_VA = findNewVA(DebugDirectory_VA, oldsections, newsections);
ArchitectureSpecificData_Size = findNewSize(ArchitectureSpecificData_VA, oldsections, newsections);
ArchitectureSpecificData_VA = findNewVA(ArchitectureSpecificData_VA, oldsections, newsections);
RVAofGP_Size = findNewSize(RVAofGP_VA, oldsections, newsections);
RVAofGP_VA = findNewVA(RVAofGP_VA, oldsections, newsections);
TLSDirectory_Size = findNewSize(TLSDirectory_VA, oldsections, newsections);
TLSDirectory_VA = findNewVA(TLSDirectory_VA, oldsections, newsections);
LoadConfigurationDirectory_Size = findNewSize(LoadConfigurationDirectory_VA, oldsections, newsections);
LoadConfigurationDirectory_VA = findNewVA(LoadConfigurationDirectory_VA, oldsections, newsections);
BoundImportDirectoryinheaders_Size = findNewSize(BoundImportDirectoryinheaders_VA, oldsections, newsections);
BoundImportDirectoryinheaders_VA = findNewVA(BoundImportDirectoryinheaders_VA, oldsections, newsections);
ImportAddressTable_Size = findNewSize(ImportAddressTable_VA, oldsections, newsections);
ImportAddressTable_VA = findNewVA(ImportAddressTable_VA, oldsections, newsections);
DelayLoadImportDescriptors_Size = findNewSize(DelayLoadImportDescriptors_VA, oldsections, newsections);
DelayLoadImportDescriptors_VA = findNewVA(DelayLoadImportDescriptors_VA, oldsections, newsections);
COMRuntimedescriptor_Size = findNewSize(COMRuntimedescriptor_VA, oldsections, newsections);
COMRuntimedescriptor_VA = findNewVA(COMRuntimedescriptor_VA, oldsections, newsections);
}
public boolean isPe32Plus() {
return Magic == 523;
}
private long findNewVA(long current, Vector oldsections, Vector newsections) {
for (int i = 0; i < oldsections.size(); i++) {
PESection sect = (PESection)oldsections.get(i);
if (sect.VirtualAddress == current) {
PESection newsect = (PESection)newsections.get(i);
// System.out.println("Translation VA found for " + current + " = " + i + " (" +newsect.VirtualAddress + ")=" + newsect.getName());
return newsect.VirtualAddress;
} else if ((current > sect.VirtualAddress) && (current < (sect.VirtualAddress + sect.VirtualSize))) {
long diff = current - sect.VirtualAddress;
PESection newsect = (PESection)newsections.get(i);
// System.out.println("Translation VA found INSIDE " + current + " = " + i + " (" +newsect.VirtualAddress + ")=" + newsect.getName());
return newsect.VirtualAddress + diff;
}
}
return 0;
}
private long findNewSize(long current, Vector oldsections, Vector newsections) {
for (int i = 0; i < oldsections.size(); i++) {
PESection sect = (PESection)oldsections.get(i);
if (sect.VirtualAddress == current) {
PESection newsect = (PESection)newsections.get(i);
// System.out.println("Translation Size found for " + current + " = " + i + " (" +newsect.VirtualAddress + ")=" + newsect.getName());
// System.out.println(" Old size " + sect.VirtualSize + " vs new size " + newsect.VirtualSize);
return newsect.VirtualSize;
}
}
return 0;
}
}

View File

@ -0,0 +1,625 @@
/*
JSmooth: a VM wrapper toolkit for Windows
Copyright (C) 2003 Rodrigo Reyes <reyes@charabia.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; either version 2 of the License, or
(at your option) any later version.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* PEResourceDirectory.java
*
* Created on 2 aout 2003, 01:28
*/
package net.charabia.jsmoothgen.pe;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.util.Iterator;
import java.util.Vector;
/**
* @author Rodrigo
*/
public class PEResourceDirectory {
/*
typedef struct IMAGE_RESOURCE_DIRECTORY {
uint32_t Characteristics;
uint32_t TimeDateStamp;
uint16_t MajorVersion;
uint16_t MinorVersion;
uint16_t NumberOfNamedEntries;
uint16_t NumberOfIdEntries;
}
*/
public class DataEntry {
long OffsetToData; // To update at each change
long Size;
long CodePage; // never changed
long Reserved; // never changed
ByteBuffer Data;
public DataEntry(ByteBuffer data) {
this.Data = data;
this.Size = data.capacity();
}
public DataEntry(FileChannel chan, long offset) throws IOException {
long orgpos = chan.position();
chan.position(PEResourceDirectory.this.m_offsetBase + offset);
ByteBuffer buf = ByteBuffer.allocate(16);
buf.order(ByteOrder.LITTLE_ENDIAN);
chan.read(buf);
buf.position(0);
OffsetToData = buf.getInt();
Size = buf.getInt();
CodePage = buf.getInt();
Reserved = buf.getInt();
long datapos = PEResourceDirectory.this.m_master.PointerToRawData + (OffsetToData - PEResourceDirectory.this.m_master.VirtualAddress);
Data = ByteBuffer.allocate((int)Size);
Data.order(ByteOrder.LITTLE_ENDIAN);
chan.position(datapos);
chan.read(Data);
Data.position(0);
chan.position(orgpos);
}
public int diskSize() {
int size = 16 + (int)this.Size;
if ((size % 4) > 0)
size += 4 - (size % 4);
return size;
}
public void dump(PrintStream out, int level) {
indent(level, out);
out.println("OffsetToData=" + OffsetToData);
indent(level, out);
out.println("Size=" + Size);
indent(level, out);
out.println("CodePage=" + CodePage);
indent(level, out);
out.println("Reserved=" + Reserved);
indent(level, out);
out.print("Data={ ");
for (int i = 0; i < this.Data.capacity(); i++) {
out.print("" + Integer.toHexString((byte)Data.get()) + ",");
}
out.println(" }");
}
private void indent(int level, PrintStream out) {
for (int i = 0; i < level; i++)
out.print(" ");
}
public int buildBuffer(ByteBuffer buffer, long virtualBaseOffset, int dataOffset) {
// System.out.println("Building Data Entry buffer @ " + buffer.position() + " (" + dataOffset + ")");
dataOffset = buffer.position() + 16;
buffer.putInt((int)(dataOffset + virtualBaseOffset));
buffer.putInt((int)Size);
buffer.putInt((int)CodePage);
buffer.putInt((int)Reserved);
Data.position(0);
buffer.put(Data);
dataOffset += Size;
if ((dataOffset % 4) > 0)
dataOffset += (4 - (dataOffset % 4));
return dataOffset;
}
public void setData(ByteBuffer data) {
Data = data;
Size = data.capacity();
}
}
public class ResourceEntry {
int Id;
String Name;
ImageResourceDirectory Directory;
DataEntry Data;
public ResourceEntry(int id, DataEntry data) {
this.Id = id;
this.Data = data;
}
public ResourceEntry(String name, DataEntry data) {
this.Name = name;
this.Data = data;
}
public ResourceEntry(int id, ImageResourceDirectory dir) {
this.Id = id;
this.Directory = dir;
}
public ResourceEntry(String name, ImageResourceDirectory dir) {
this.Name = name;
this.Directory = dir;
}
public ResourceEntry(FileChannel chan) throws IOException {
// System.out.println("Resource Entry Offset: " + chan.position());
ByteBuffer buf = ByteBuffer.allocate(8);
buf.order(ByteOrder.LITTLE_ENDIAN);
chan.read(buf);
buf.position(0);
long orgchanpos = chan.position();
int val = buf.getInt();
long offsetToData = buf.getInt();
// System.out.println("Entry: Val=" + val);
// System.out.println(" Off=" + offsetToData);
if (val < 0) {
val &= 0x7FFFFFFF;
Name = extractStringAt(chan, val);
Id = -1;
// System.out.println(" String at " + val + " = " + Name);
} else {
Id = val;
}
if (offsetToData < 0) {
offsetToData &= 0x7FFFFFFF;
long orgpos = chan.position();
chan.position(PEResourceDirectory.this.m_offsetBase + offsetToData);
Directory = new PEResourceDirectory.ImageResourceDirectory(chan);
chan.position(orgpos);
} else {
Data = new DataEntry(chan, offsetToData);
}
}
public String extractStringAt(FileChannel chan, int offset) throws IOException {
long orgchanpos = chan.position();
chan.position(PEResourceDirectory.this.m_offsetBase + offset);
ByteBuffer sizebuf = ByteBuffer.allocate(2);
sizebuf.order(ByteOrder.LITTLE_ENDIAN);
chan.read(sizebuf);
sizebuf.position(0);
int size = sizebuf.getShort();
ByteBuffer buffer = ByteBuffer.allocate(size * 2);
buffer.order(ByteOrder.LITTLE_ENDIAN);
chan.read(buffer);
buffer.position(0);
StringBuffer buf = new StringBuffer(size);
for (int i = 0; i < size; i++) {
int c = buffer.getShort();
buf.append((char)c);
}
chan.position(orgchanpos);
return buf.toString();
}
public int diskSize() {
int size = 8;
if (Name != null)
size += (Name.length() * 2) + 2;
if (Directory != null)
size += Directory.diskSize();
else if (Data != null)
size += Data.diskSize();
if ((size % 4) > 0)
size += 4 - (size % 4);
return size;
}
public void dump(PrintStream out, int level) {
indent(level, out);
if (this.Name != null)
out.println("Name=" + Name);
else
out.println("Id=#" + Id);
indent(level, out);
if (this.Directory != null) {
out.println("ENTRY: DIRECTORY POINTER");
this.Directory.dump(out, level + 1);
} else {
out.println("ENTRY: DATA ENTRY");
Data.dump(out, level + 1);
}
}
private void indent(int level, PrintStream out) {
for (int i = 0; i < level; i++)
out.print(" ");
}
public int buildBuffer(ByteBuffer buffer, long virtualBaseOffset, int dataOffset) {
// System.out.println("Building Resource Entry buffer " + Name + "/" + Id + " @ " + buffer.position() + " (" + dataOffset + ")");
if (Name != null) {
buffer.putInt((int)(dataOffset | 0x80000000));
int stringoffset = dataOffset;
ByteBuffer strbuf = ByteBuffer.allocate(Name.length() * 2 + 2);
strbuf.order(ByteOrder.LITTLE_ENDIAN);
strbuf.putShort((short)Name.length());
for (int i = 0; i < Name.length(); i++) {
strbuf.putShort((short)Name.charAt(i));
}
strbuf.position(0);
long oldpos = buffer.position();
buffer.position(dataOffset);
buffer.put(strbuf);
dataOffset += Name.length() * 2 + 2;
if ((dataOffset % 4) != 0)
dataOffset += 4 - (dataOffset % 4);
buffer.position((int) oldpos);
} else {
buffer.putInt(Id);
}
if (Directory != null) {
buffer.putInt((int)(dataOffset | 0x80000000));
int oldpos = buffer.position();
buffer.position(dataOffset);
int dirsize = Directory.buildBuffer(buffer, virtualBaseOffset);
dataOffset = dirsize;
buffer.position(oldpos);
} else if (Data != null) {
buffer.putInt(dataOffset);
int oldpos = buffer.position();
buffer.position(dataOffset);
dataOffset = Data.buildBuffer(buffer, virtualBaseOffset, dataOffset);
buffer.position(oldpos);
} else {
throw new RuntimeException("Directory and Data are both null!");
}
return dataOffset;
}
}
public class ImageResourceDirectory {
long Characteristics; // uint32_t
long TimeDateStamp; // uint32_t
int MajorVersion; // uint16_t
int MinorVersion; // uint16_t
int NumberOfNamedEntries; // uint16_t
int NumberOfIdEntries; // uint16_t
Vector NamedEntries = new Vector();
Vector IdEntries = new Vector();
public ImageResourceDirectory() {
}
public ImageResourceDirectory(FileChannel chan) throws IOException {
ByteBuffer header = ByteBuffer.allocate(16);
header.order(ByteOrder.LITTLE_ENDIAN);
chan.read(header);
header.position(0);
Characteristics = header.getInt();
TimeDateStamp = header.getInt();
MajorVersion = header.getShort();
MinorVersion = header.getShort();
NumberOfNamedEntries = header.getShort();
NumberOfIdEntries = header.getShort();
for (int i = 0; i < NumberOfNamedEntries; i++) {
ResourceEntry re = new ResourceEntry(chan);
NamedEntries.add(re);
}
for (int i = 0; i < NumberOfIdEntries; i++) {
ResourceEntry re = new ResourceEntry(chan);
IdEntries.add(re);
}
}
public void addNamedEntry(ResourceEntry entry) {
this.NamedEntries.add(entry);
}
public void addIdEntry(ResourceEntry entry) {
this.IdEntries.add(entry);
}
public void addEntry(ResourceEntry entry) {
if (entry.Name != null)
addNamedEntry(entry);
else
addIdEntry(entry);
}
public void dump(PrintStream out, int level) {
indent(level, out);
out.println("Directory: ");
indent(level, out);
out.println("Characteristics=" + this.Characteristics);
indent(level, out);
out.println("TimeDateStamp=" + this.TimeDateStamp);
indent(level, out);
out.println("MajorVersion=" + this.MajorVersion);
indent(level, out);
out.println("MinorVersion=" + this.MinorVersion);
indent(level, out);
out.println("NumberOfNamedEntries=" + this.NumberOfNamedEntries);
indent(level, out);
out.println("NumberOfIdEntries=" + this.NumberOfIdEntries);
indent(level, out);
out.println("Named Entries:");
for (int i = 0; i < NumberOfNamedEntries; i++) {
ResourceEntry re = (ResourceEntry)NamedEntries.get(i);
re.dump(out, level + 1);
}
indent(level, out);
out.println("Id Entries:");
for (int i = 0; i < NumberOfIdEntries; i++) {
ResourceEntry re = (ResourceEntry)IdEntries.get(i);
re.dump(out, level + 1);
}
}
private void indent(int level, PrintStream out) {
for (int i = 0; i < level; i++)
out.print(" ");
}
public int diskSize() {
int size = 16;
for (int i = 0; i < this.NamedEntries.size(); i++) {
ResourceEntry re = (ResourceEntry)NamedEntries.get(i);
size += re.diskSize();
}
for (int i = 0; i < this.IdEntries.size(); i++) {
ResourceEntry re = (ResourceEntry)IdEntries.get(i);
size += re.diskSize();
}
if ((size % 4) > 0)
size += 4 - (size % 4);
return size;
}
public int buildBuffer(ByteBuffer buffer, long virtualBaseOffset) {
// System.out.println("Building Directory Entry buffer @ " + buffer.position());
buffer.putInt((int)this.Characteristics);
buffer.putInt((int)this.TimeDateStamp);
buffer.putShort((short)this.MajorVersion);
buffer.putShort((short)this.MinorVersion);
buffer.putShort((short)this.NamedEntries.size());
buffer.putShort((short)this.IdEntries.size());
int dataOffset = buffer.position() + (NamedEntries.size() * 8) + (IdEntries.size() * 8);
for (int i = 0; i < this.NamedEntries.size(); i++) {
ResourceEntry re = (ResourceEntry)this.NamedEntries.get(i);
dataOffset = re.buildBuffer(buffer, virtualBaseOffset, dataOffset);
}
for (int i = 0; i < this.IdEntries.size(); i++) {
ResourceEntry re = (ResourceEntry)this.IdEntries.get(i);
dataOffset = re.buildBuffer(buffer, virtualBaseOffset, dataOffset);
}
buffer.position(dataOffset);
return dataOffset;
}
public ResourceEntry getResourceEntry(String name) {
// If name == null, get the first entry in lexical
// order. If no entry in lexical order, choose the
// lowest integer id entry.
if (name == null) {
if (NamedEntries.size() > 0) {
return (PEResourceDirectory.ResourceEntry)NamedEntries.get(0);
}
if (IdEntries.size() > 0) {
return (PEResourceDirectory.ResourceEntry)IdEntries.get(0);
}
return null;
}
if ((name.length() > 0) && (name.charAt(0) == '#')) {
try {
String nb = name.substring(1);
int i = Integer.parseInt(nb);
return getResourceEntry(i);
} catch (Exception exc) {
exc.printStackTrace();
}
}
for (Iterator i = this.NamedEntries.iterator(); i.hasNext();) {
ResourceEntry re = (ResourceEntry)i.next();
if (name.equals(re.Name)) {
return re;
}
}
return null;
}
public ResourceEntry getResourceEntry(int id) {
for (Iterator i = this.IdEntries.iterator(); i.hasNext();) {
ResourceEntry re = (ResourceEntry)i.next();
if (id == re.Id) {
return re;
}
}
return null;
}
}
PESection m_master;
PEFile m_file;
long m_offsetBase;
PEResourceDirectory.ImageResourceDirectory m_root;
/**
* Creates a new instance of PEResourceDirectory
*/
public PEResourceDirectory(PEFile file, PESection sect) throws IOException {
m_master = sect;
m_file = file;
m_offsetBase = sect.PointerToRawData;
init();
// System.out.println("--------\nTOTAL SIZE: " + m_root.diskSize());
// System.out.println("\n\n");
}
public void init() throws IOException {
// / System.out.println("RESOURCE INIT");
// System.out.println(" Offset: " + m_master.PointerToRawData);
FileChannel chan = m_file.getChannel();
chan.position(m_master.PointerToRawData);
PEResourceDirectory.ImageResourceDirectory dir = new PEResourceDirectory.ImageResourceDirectory(chan);
// System.out.println("-----------------\nDUMP\n---------------");
m_root = dir;
// dir.dump(System.out, 0);
}
public void dump(PrintStream out) {
m_root.dump(out, 0);
}
public int size() {
return m_root.diskSize();
}
public ByteBuffer buildResource(long virtualBaseOffset) {
// System.out.println("BUILDING RESOURCE / VIRTUAL: " + virtualBaseOffset);
int resourceSize = m_root.diskSize();
ByteBuffer resbuf = ByteBuffer.allocate(resourceSize);
resbuf.order(ByteOrder.LITTLE_ENDIAN);
resbuf.position(0);
m_root.buildBuffer(resbuf, virtualBaseOffset);
return resbuf;
}
public PEResourceDirectory.ImageResourceDirectory getRoot() {
return m_root;
}
public boolean replaceManifest(int resourceId, int langId, ByteBuffer data) {
ResourceEntry catEntry = m_root.getResourceEntry(24);
if ((catEntry != null) && (catEntry.Directory != null)) {
ResourceEntry identEntry = catEntry.Directory.getResourceEntry(resourceId);
if ((identEntry != null) && (identEntry.Directory != null)) {
ResourceEntry langEntry = identEntry.Directory.getResourceEntry(langId);
if ((langEntry != null) && (langEntry.Data != null)) {
DataEntry dataslot = langEntry.Data;
dataslot.setData(data);
return true;
}
}
}
return false;
}
public boolean replaceResource(String catId, int resourceId, int langId, ByteBuffer data) {
ResourceEntry catEntry = m_root.getResourceEntry(catId);
if ((catEntry != null) && (catEntry.Directory != null)) {
ResourceEntry identEntry = catEntry.Directory.getResourceEntry(resourceId);
if ((identEntry != null) && (identEntry.Directory != null)) {
ResourceEntry langEntry = identEntry.Directory.getResourceEntry(langId);
if ((langEntry != null) && (langEntry.Data != null)) {
DataEntry dataslot = langEntry.Data;
dataslot.setData(data);
return true;
}
}
}
return false;
}
public void addNewResource(String catId, String resourceId, String languageId, ByteBuffer data) {
DataEntry dataEntry = new DataEntry(data);
ResourceEntry languageEntry = buildResourceEntry(languageId, dataEntry);
ImageResourceDirectory languageDir = new ImageResourceDirectory();
languageDir.TimeDateStamp = 0x3F2CCF64;
languageDir.addEntry(languageEntry);
ResourceEntry identEntry = buildResourceEntry(resourceId, languageDir);
ImageResourceDirectory identDir = new ImageResourceDirectory();
identDir.TimeDateStamp = 0x3F2CCF64;
identDir.addEntry(identEntry);
ResourceEntry catEntry = buildResourceEntry(catId, identDir);
m_root.addEntry(catEntry);
}
public DataEntry getData(String catId, String resourceId, String langId) {
ResourceEntry catEntry = m_root.getResourceEntry(catId);
if ((catEntry != null) && (catEntry.Directory != null)) {
ResourceEntry identEntry = catEntry.Directory.getResourceEntry(resourceId);
if ((identEntry != null) && (identEntry.Directory != null)) {
ResourceEntry langEntry = identEntry.Directory.getResourceEntry(langId);
if ((langEntry != null) && (langEntry.Data != null)) {
DataEntry dataslot = langEntry.Data;
return dataslot;
}
}
}
return null;
}
public ResourceEntry buildResourceEntry(String id, DataEntry data) {
if ((id.length() > 1) && (id.charAt(0) == '#')) {
int intid = Integer.parseInt(id.substring(1));
return new ResourceEntry(intid, data);
}
return new ResourceEntry(id, data);
}
public ResourceEntry buildResourceEntry(String id, ImageResourceDirectory dir) {
if ((id.length() > 1) && (id.charAt(0) == '#')) {
int intid = Integer.parseInt(id.substring(1));
return new ResourceEntry(intid, dir);
}
return new ResourceEntry(id, dir);
}
}

View File

@ -0,0 +1,133 @@
/*
JSmooth: a VM wrapper toolkit for Windows
Copyright (C) 2003 Rodrigo Reyes <reyes@charabia.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; either version 2 of the License, or
(at your option) any later version.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* PESection.java
*
* Created on 29 juillet 2003, 21:34
*/
package net.charabia.jsmoothgen.pe;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
/**
* @author Rodrigo
*/
public class PESection implements Cloneable {
byte[] ANSI_Name; // Name of the Section. Can be anything (0)(8BYTES)
long VirtualSize; // The size of the section when it is mapped to memory. Must be a multiple of 4096. (8)(DWORD)
long VirtualAddress; // An rva to where it should be mapped in memory. (12)(DWORD)
long SizeOfRawData; // The size of the section in the PE file. Must be a multiple of 512 (16)(DWORD)
long PointerToRawData; // A file based offset which points to the location of this sections data (20)(DWORD)
long PointerToRelocations; // In EXE's this field is meaningless, and is set 0 (24)(DWORD)
long PointerToLinenumbers; // This is the file-based offset of the line number table. This field is only used for debug purposes, and is usualy set to 0 (28)(DWORD)
int NumberOfRelocations; // In EXE's this field is meaningless, and is set 0 (32)(WORD)
int NumberOfLinenumbers; // The number of line numbers in the line number table for this section. This field is only used for debug purposes, and is usualy set to 0 (34)(WORD)
long Characteristics; // The kind of data stored in this section ie. Code, Data, Import data, Relocation data (36)(DWORD)
private long m_baseoffset;
private PEFile m_pe;
/**
* Creates a new instance of PESection
*/
public PESection(PEFile pef, long baseoffset) {
m_pe = pef;
m_baseoffset = baseoffset;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public String getName() {
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < 8; i++)
buffer.append((char) ANSI_Name[i]);
return buffer.toString();
}
public void read() throws IOException {
FileChannel ch = m_pe.getChannel();
ByteBuffer head = ByteBuffer.allocate(40);
head.order(ByteOrder.LITTLE_ENDIAN);
ch.position(m_baseoffset);
ch.read(head);
head.position(0);
ANSI_Name = new byte[8];
for (int i = 0; i < 8; i++)
ANSI_Name[i] = head.get();
VirtualSize = head.getInt();
VirtualAddress = head.getInt();
SizeOfRawData = head.getInt();
PointerToRawData = head.getInt();
PointerToRelocations = head.getInt();
PointerToLinenumbers = head.getInt();
NumberOfRelocations = head.getShort();
NumberOfLinenumbers = head.getShort();
Characteristics = head.getInt();
}
public void dump(PrintStream out) {
out.println("SECTION:");
out.println(" Name= "+getName());
out.println(" VirtualSize= " + VirtualSize + " // The size of the section when it is mapped to memory. Must be a multiple of 4096. (8)(DWORD)");
out.println(" VirtualAddress= " + VirtualAddress + " // An rva to where it should be mapped in memory. (12)(DWORD)");
out.println(" SizeOfRawData= " + SizeOfRawData + " // The size of the section in the PE file. Must be a multiple of 512 (16)(DWORD)");
out.println(" PointerToRawData= " + PointerToRawData + " // A file based offset which points to the location of this sections data (20)(DWORD)");
out.println(" PointerToRelocations= " + PointerToRelocations + " // In EXE's this field is meaningless, and is set 0 (24)(DWORD)");
out.println(" PointerToLinenumbers= " + PointerToLinenumbers + " // This is the file-based offset of the line number table. This field is only used for debug purposes, and is usualy set to 0 (28)(DWORD)");
out.println(" NumberOfRelocations= " + NumberOfRelocations + " // In EXE's this field is meaningless, and is set 0 (32)(WORD)");
out.println(" NumberOfLinenumbers= " + NumberOfLinenumbers + " // The number of line numbers in the line number table for this section. This field is only used for debug purposes, and is usualy set to 0 (34)(WORD)");
out.println(" Characteristics= " + Characteristics + " // The kind of data stored in this section ie. Code, Data, Import data, Relocation data (36)(DWORD)");
}
public ByteBuffer get() {
ByteBuffer head = ByteBuffer.allocate(40);
head.order(ByteOrder.LITTLE_ENDIAN);
head.position(0);
for (int i = 0; i < 8; i++)
head.put((byte)ANSI_Name[i]);
head.putInt((int)VirtualSize);
head.putInt((int)VirtualAddress);
head.putInt((int)SizeOfRawData);
head.putInt((int)PointerToRawData);
head.putInt((int)PointerToRelocations);
head.putInt((int)PointerToLinenumbers);
head.putShort((short)NumberOfRelocations);
head.putShort((short)NumberOfLinenumbers);
head.putInt((int)Characteristics);
head.position(0);
return head;
}
}