diff --git a/tools/launcher-generator/.gitignore b/tools/launcher-generator/.gitignore
new file mode 100644
index 000000000000..1fcb1529f8e5
--- /dev/null
+++ b/tools/launcher-generator/.gitignore
@@ -0,0 +1 @@
+out
diff --git a/tools/launcher-generator/.idea/.name b/tools/launcher-generator/.idea/.name
new file mode 100644
index 000000000000..3bb134aeb122
--- /dev/null
+++ b/tools/launcher-generator/.idea/.name
@@ -0,0 +1 @@
+launcher-generator
\ No newline at end of file
diff --git a/tools/launcher-generator/.idea/ant.xml b/tools/launcher-generator/.idea/ant.xml
new file mode 100644
index 000000000000..2581ca3fe84c
--- /dev/null
+++ b/tools/launcher-generator/.idea/ant.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/tools/launcher-generator/.idea/codeStyleSettings.xml b/tools/launcher-generator/.idea/codeStyleSettings.xml
new file mode 100644
index 000000000000..a0d3b90a93f5
--- /dev/null
+++ b/tools/launcher-generator/.idea/codeStyleSettings.xml
@@ -0,0 +1,231 @@
+
+
+
+
+
+
+
+
diff --git a/tools/launcher-generator/.idea/compiler.xml b/tools/launcher-generator/.idea/compiler.xml
new file mode 100644
index 000000000000..b22c943f13ac
--- /dev/null
+++ b/tools/launcher-generator/.idea/compiler.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tools/launcher-generator/.idea/copyright/apache_2_productiveme.xml b/tools/launcher-generator/.idea/copyright/apache_2_productiveme.xml
new file mode 100644
index 000000000000..88d237bf5e24
--- /dev/null
+++ b/tools/launcher-generator/.idea/copyright/apache_2_productiveme.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/launcher-generator/.idea/copyright/profiles_settings.xml b/tools/launcher-generator/.idea/copyright/profiles_settings.xml
new file mode 100644
index 000000000000..ad23b0748861
--- /dev/null
+++ b/tools/launcher-generator/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/launcher-generator/.idea/encodings.xml b/tools/launcher-generator/.idea/encodings.xml
new file mode 100644
index 000000000000..e206d70d8595
--- /dev/null
+++ b/tools/launcher-generator/.idea/encodings.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/tools/launcher-generator/.idea/misc.xml b/tools/launcher-generator/.idea/misc.xml
new file mode 100644
index 000000000000..97320410eec7
--- /dev/null
+++ b/tools/launcher-generator/.idea/misc.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/tools/launcher-generator/.idea/modules.xml b/tools/launcher-generator/.idea/modules.xml
new file mode 100644
index 000000000000..36572af8a642
--- /dev/null
+++ b/tools/launcher-generator/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/tools/launcher-generator/.idea/scopes/scope_settings.xml b/tools/launcher-generator/.idea/scopes/scope_settings.xml
new file mode 100644
index 000000000000..922003b8433b
--- /dev/null
+++ b/tools/launcher-generator/.idea/scopes/scope_settings.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/launcher-generator/.idea/uiDesigner.xml b/tools/launcher-generator/.idea/uiDesigner.xml
new file mode 100644
index 000000000000..3b0002030884
--- /dev/null
+++ b/tools/launcher-generator/.idea/uiDesigner.xml
@@ -0,0 +1,125 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
+
diff --git a/tools/launcher-generator/.idea/vcs.xml b/tools/launcher-generator/.idea/vcs.xml
new file mode 100644
index 000000000000..a5dd08645f6f
--- /dev/null
+++ b/tools/launcher-generator/.idea/vcs.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/tools/launcher-generator/launcher-generator.iml b/tools/launcher-generator/launcher-generator.iml
new file mode 100644
index 000000000000..d5c074327501
--- /dev/null
+++ b/tools/launcher-generator/launcher-generator.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tools/launcher-generator/src/com/pme/exe/Bin.java b/tools/launcher-generator/src/com/pme/exe/Bin.java
new file mode 100644
index 000000000000..338793924de7
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/Bin.java
@@ -0,0 +1,631 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe;
+
+import com.pme.util.BitsUtil;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.lang.reflect.Array;
+
+/**
+ * Date: Mar 31, 2006
+ * Time: 6:17:24 PM
+ */
+public abstract class Bin {
+ private String myName;
+ private String myDescription;
+ private long myOffset = 0;
+ ArrayList myOffsetHolders = new ArrayList(0);
+ ArrayList mySizeHolders = new ArrayList(0);
+
+ public Bin(String name) {
+ myName = name;
+ }
+
+ public String getName() {
+ return myName;
+ }
+
+ public void setName(String name) {
+ myName = name;
+ }
+
+ public String getDescription() {
+ if (myDescription != null) {
+ return myDescription;
+ }
+ return myName;
+ }
+
+ public long getOffset() {
+ return myOffset;
+ }
+
+ public void resetOffsets(long offset) {
+ myOffset = offset;
+ for (Value holder : myOffsetHolders) {
+ holder.setValue(offset);
+ }
+ for (Value holder : mySizeHolders) {
+ holder.setValue(sizeInBytes());
+ }
+ }
+
+ public void copyFrom(Bin value) {
+ }
+
+ public void addOffsetHolder(Value offsetHolder) {
+ myOffsetHolders.add( offsetHolder );
+ }
+
+ public void addSizeHolder(Value sizeHolder) {
+ mySizeHolders.add( sizeHolder );
+ }
+
+ public abstract long sizeInBytes();
+
+ public void setDescription(String description) {
+ myDescription = description;
+ }
+
+ public abstract void read(DataInput stream) throws IOException;
+
+ public abstract void write(DataOutput stream) throws IOException;
+
+ public abstract void report(OutputStreamWriter writer) throws IOException;
+
+ public static class Comment extends Bin {
+ public Comment(String comment) {
+ super(comment);
+ }
+
+ public long sizeInBytes() {
+ return 0;
+ }
+
+ public void read(DataInput stream) throws IOException {
+ }
+
+ public void write(DataOutput stream) throws IOException {
+ }
+
+ public void report(OutputStreamWriter writer) throws IOException {
+ _report(writer, getName());
+ }
+ }
+
+ public static class Structure extends Bin {
+ private ArrayList myMembers = new ArrayList(1);
+ private HashMap myMembersMap = new HashMap(1);
+
+ public Structure(String name) {
+ super(name);
+ }
+
+ public void resetOffsets(long newOffset) {
+ super.resetOffsets(newOffset);
+ long offset = getOffset();
+ for (Bin bin : myMembers) {
+ bin.resetOffsets(offset);
+ offset = offset + bin.sizeInBytes();
+ }
+ }
+
+ public void copyFrom(Bin binStructure) {
+ Bin.Structure structure = (Bin.Structure)binStructure;
+ ArrayList members = structure.getMembers();
+ for (Bin bin : members) {
+ Bin valueMember = getMember(bin.getName());
+ if (valueMember != null) {
+ valueMember.copyFrom(bin);
+ }
+ }
+ }
+
+ public long sizeInBytes() {
+ long size = 0;
+ for (Bin bin : myMembers) {
+ size += bin.sizeInBytes();
+ }
+ return size;
+ }
+
+ public ArrayList getMembers() {
+ return myMembers;
+ }
+ public void addMember(Bin bin, String description) {
+ bin.setDescription(description);
+ addMember(bin);
+ }
+
+ public void addComment(String message) {
+ myMembers.add(new Comment(message));
+ }
+
+ public Bin insertMember(int index, Bin bin) {
+ ArrayList list = new ArrayList( myMembers.size() + 1 );
+ for ( int i = 0; i < index; ++i ){
+ list.add( myMembers.get( i ) );
+ }
+ list.add( bin );
+ for ( int i = index; i < myMembers.size(); ++i ){
+ list.add( myMembers.get( i ) );
+ }
+ myMembers = list;
+ addMemberToMapOnly(bin);
+ return bin;
+ }
+
+ public Bin addMember(Bin bin) {
+ myMembers.add(bin);
+ addMemberToMapOnly(bin);
+ return bin;
+ }
+
+ //such members are not read by framework
+ //it is read by parent in 'read' overrided method
+ public void addMemberToMapOnly(Bin bin) {
+ myMembersMap.put(bin.getName(), bin);
+ }
+
+ public Bin getMember(String name) {
+ return (Bin) myMembersMap.get(name);
+ }
+
+ public Bin.Value getValueMember(String name) {
+ return (Bin.Value) myMembersMap.get(name);
+ }
+
+ public Bin.Structure getStructureMember(String name) {
+ return (Bin.Structure) myMembersMap.get(name);
+ }
+
+ public long getValue(String name) {
+ return ((Bin.Value) myMembersMap.get(name)).getValue();
+ }
+
+ public void read(DataInput stream) throws IOException {
+ for (Bin bin : myMembers) {
+ bin.read(stream);
+ }
+ }
+
+ public void write(DataOutput stream) throws IOException {
+ for (Bin bin : myMembers) {
+ bin.write(stream);
+ }
+ }
+
+ public void report(OutputStreamWriter writer) throws IOException {
+ _report(writer, "--- '" + getName() + "' Structure --- size = " + sizeInBytes());
+ _report(writer, "{Offset = " + Long.toHexString(getOffset()) + "}");
+ for (Bin bin : myMembers) {
+ bin.report(writer);
+ }
+ _report(writer, "--- End Of '" + getName() + "' Structure ---");
+ }
+ }
+
+ public abstract static class Value extends Bin {
+ private long myValue;
+
+ public Value(String name) {
+ super(name);
+ }
+
+ public abstract long getValue();
+ public abstract Value setValue(long value);
+
+ public void copyFrom(Bin value) {
+ setValue(((Value)value).getValue());
+ }
+
+ public long getRawValue() {
+ return myValue;
+ }
+
+ public Value setRawValue(long value) {
+ myValue = value;
+ return this;
+ }
+
+ public Value setValue(short value) {
+ myValue = BitsUtil.revertBytesOfShort(value);
+ return this;
+ }
+ }
+
+ public static class Byte extends Value {
+ public Byte(String name) {
+ super(name);
+ }
+
+ public long sizeInBytes() {
+ return 1;
+ }
+
+ public long getValue() {
+ return getRawValue();
+ }
+ public Value setValue(long value) {
+ setRawValue(value);
+ return this;
+ }
+
+ public void read(DataInput stream) throws IOException {
+ setRawValue(stream.readByte());
+ }
+
+ public void write(DataOutput stream) throws IOException {
+ stream.writeByte((byte) getRawValue());
+ }
+
+ public void report(OutputStreamWriter writer) throws IOException {
+ _report(writer, getDescription(), (byte) getValue());
+ }
+
+ }
+
+ public static class Word extends Value {
+ public Word() {
+ super("");
+ }
+
+ public Word(String name) {
+ super(name);
+ }
+
+ public long sizeInBytes() {
+ return 2;
+ }
+
+ public long getValue() {
+ return BitsUtil.revertBytesOfShort((short) super.getRawValue());
+ }
+
+ public Value setValue(long value) {
+ setRawValue(BitsUtil.revertBytesOfShort((short) value));
+ return this;
+ }
+
+ public void read(DataInput stream) throws IOException {
+ setRawValue(stream.readShort());
+ }
+
+ public void write(DataOutput stream) throws IOException {
+ stream.writeShort((short) getRawValue());
+ }
+
+ public void report(OutputStreamWriter writer) throws IOException {
+ short sh = (short) getValue();
+ _report(writer, getDescription(), sh);
+ }
+ public String toString() {
+ return BitsUtil.shortToHexString( (int)getValue() );
+ }
+ }
+
+ public static class DWord extends Value {
+ public DWord(String name) {
+ super(name);
+ }
+
+ public long sizeInBytes() {
+ return 4;
+ }
+
+ public Value setValue(long value) {
+ setRawValue(BitsUtil.revertBytesOfInt((int) value));
+ return this;
+ }
+
+ public long getValue() {
+ return BitsUtil.revertBytesOfInt((int) super.getRawValue());
+ }
+
+ public void read(DataInput stream) throws IOException {
+ setRawValue(stream.readInt());
+ }
+
+ public void write(DataOutput stream) throws IOException {
+ stream.writeInt((int) getRawValue());
+ }
+
+ public void report(OutputStreamWriter writer) throws IOException {
+ _report(writer, getDescription(), (int) getValue());
+ }
+ public String toString() {
+ return BitsUtil.intToHexString( (int)getValue() );
+ }
+ }
+
+ public static class Txt extends Bin {
+ private StringBuffer myBuffer = new StringBuffer();
+ private Bin.Value mySize;
+ private byte[] myBytes;
+
+ public Txt(String name, byte[] bytes) {
+ super(name);
+ myBytes = bytes;
+ mySize = new DWord("").setValue(bytes.length);
+ setValue();
+ }
+ public Txt(String name, String string) {
+ super(name);
+ myBytes = new byte[string.length() * 2];
+ byte[] bytes = string.getBytes();
+ for (int i = 0; i < bytes.length; ++i) {
+ myBytes[i * 2] = bytes[i];
+ myBytes[i * 2 + 1] = 0;
+ }
+ mySize = new DWord("").setValue(myBytes.length);
+ setValue();
+ }
+
+ public Txt(String name, Bin.Value size) {
+ super(name);
+ mySize = size;
+ }
+
+ public Txt(String name, int size) {
+ this(name, new DWord("size").setValue(size));
+ }
+
+ public String getText() {
+ return myBuffer.toString();
+ }
+
+ public long sizeInBytes() {
+ return mySize.getValue();
+ }
+
+ private void setValue(){
+ for (int i = 0; i < mySize.getValue(); ++i) {
+ int b = BitsUtil.unsignedByte(myBytes[i]);
+ if (b != 0) {
+ myBuffer.append((char) b);
+ }
+ }
+ }
+
+ public void read(DataInput stream) throws IOException {
+ myBuffer.setLength(0);
+ myBytes = new byte[(int) mySize.getValue()];
+ for (int i = 0; i < mySize.getValue(); ++i) {
+ myBytes[i] = stream.readByte();
+ }
+ setValue();
+ }
+
+ public void write(DataOutput stream) throws IOException {
+ stream.write(myBytes);
+ }
+
+ public void report(OutputStreamWriter writer) throws IOException {
+ _report(writer, myBuffer.toString());
+ }
+ }
+
+ public static class Bytes extends Bin {
+ private byte[] myBytes;
+ private Value myStartOffset;
+ private Value mySize;
+ private int myBytesInRow = 16;
+
+ public Bytes(String name, Bin.Value size) {
+ super(name);
+ mySize = size;
+ }
+
+ public Bytes(String name, long size) {
+ super(name);
+ mySize = new DWord("size").setValue(size);
+ }
+
+ public Bytes(String name, Bin.Value startOffset, Bin.Value size) {
+ super(name);
+ reset(startOffset, size);
+ }
+
+ public void reset(int startOffset, int size) {
+ reset(new DWord("startOffset").setValue(startOffset), new DWord("size").setValue(size));
+ }
+
+ public void reset(Bin.Value startOffset, Bin.Value size) {
+ myStartOffset = startOffset;
+ mySize = size;
+ }
+
+ public byte[] getBytes() {
+ return myBytes;
+ }
+
+ public void setBytes(byte[] bytes) {
+ setBytes(bytes, bytes.length);
+ }
+
+ public void setBytes(byte[] bytes, int size) {
+ if (bytes.length < size) {
+ throw new RuntimeException("bytes.length < size");
+ }
+ myBytes = bytes;
+ mySize.setValue(size);
+ }
+
+ public long sizeInBytes() {
+ return mySize.getValue();
+ }
+
+ public void read(DataInput stream) throws IOException {
+ if (myStartOffset != null) {
+ RandomAccessFile file = (RandomAccessFile) stream;
+ file.seek(myStartOffset.getValue());
+ }
+ myBytes = new byte[(int) mySize.getValue()];
+ stream.readFully(myBytes);
+ }
+
+ public void write(DataOutput stream) throws IOException {
+ stream.write(myBytes, 0, (int) sizeInBytes());
+ }
+
+ private StringBuffer myBuffer = new StringBuffer();
+
+ public void report(OutputStreamWriter writer) throws IOException {
+ _report(writer, getName());
+ _report(writer, "Number of bytes: " + mySize.getValue());
+ int rowCount = (myBytes.length / myBytesInRow);
+ if (myBytes.length % myBytesInRow != 0) {
+ rowCount++;
+ }
+ int byteCount = 0;
+ for (int i = 0; i < rowCount; i++) {
+ myBuffer.setLength(0);
+ myBuffer.append("\n");
+ for (int j = 0; j < myBytesInRow && byteCount < myBytes.length; j++) {
+ byte aByte = myBytes[byteCount++];
+ myBuffer.append(" ").append(BitsUtil.byteToHexString(aByte));
+ }
+ writer.write(myBuffer.toString());
+ }
+ }
+ }
+
+ public static class ArrayOfBins extends Bin {
+ private Bin[] myValues;
+ private Bin.Value mySize;
+ private Class myClass;
+ private Bin.Value myCountHolder = null;
+
+ public ArrayOfBins(String name, Class cl, Bin.Value size) {
+ super(name);
+ myClass = cl;
+ mySize = size;
+ init();
+ }
+
+ public ArrayOfBins(String name, Class cl, int size) {
+ this(name, cl, new DWord("size").setValue(size));
+ }
+
+ public void addBin( Bin bin ){
+ Bin[] newArray = new Bin[myValues.length+1];
+ System.arraycopy( myValues, 0, newArray, 0, myValues.length );
+ newArray[myValues.length] = bin;
+ myValues = newArray;
+ mySize.setValue( mySize.getValue() + 1 );
+ }
+
+ public void copyFrom(Bin bin) {
+ ArrayOfBins value = (ArrayOfBins)bin;
+ for (int i = 0; i < myValues.length; i++) {
+ myValues[i].copyFrom( value.get(i) );
+ }
+ }
+
+ public void setCountHolder(Value countHolder) {
+ myCountHolder = countHolder;
+ }
+
+ private void init() {
+ myValues = (Bin[]) Array.newInstance(myClass, (int) mySize.getValue());
+
+ for (int i = 0; i < myValues.length; i++) {
+ try {
+ Bin bin = (Bin) myClass.newInstance();
+ bin.setName("[" + i + "]");
+ myValues[i] = bin;
+ } catch (InstantiationException e) {
+ throw new RuntimeException(e.getMessage());
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+ }
+
+ public void resetOffsets(long newOffset) {
+ super.resetOffsets(newOffset);
+ long offset = getOffset();
+ if (myCountHolder != null) {
+ myCountHolder.setValue(myValues.length);
+ }
+ for (Bin bin : myValues) {
+ bin.resetOffsets(offset);
+ offset = offset + bin.sizeInBytes();
+ }
+ }
+
+ public int size() {
+ return myValues.length;
+ }
+
+ public Bin[] getArray() {
+ return myValues;
+ }
+
+ public Bin get(int index) {
+ return myValues[index];
+ }
+
+ public long sizeInBytes() {
+ int size = 0;
+ for (Bin value : myValues) {
+ size += value.sizeInBytes();
+ }
+ return size;
+ }
+
+ public void read(DataInput stream) throws IOException {
+ init();
+ for (Bin value : myValues) {
+ value.read(stream);
+ }
+ }
+
+ public void write(DataOutput stream) throws IOException {
+ for (Bin value : myValues) {
+ value.write(stream);
+ }
+ }
+
+ public void report(OutputStreamWriter writer) throws IOException {
+ writer.write("\n" + "Array size: " + myValues.length);
+ for (Bin value : myValues) {
+ value.report(writer);
+ }
+ }
+ }
+
+ protected void _report(OutputStreamWriter buffer, String name, int value) throws IOException {
+ buffer.write("\n" + name + " : " + BitsUtil.intToHexString(value));
+ }
+
+ protected void _report(OutputStreamWriter buffer, String name, short value) throws IOException {
+ buffer.write("\n" + name + " : " + BitsUtil.shortToHexString(value));
+ }
+
+ protected void _report(OutputStreamWriter buffer, String name, byte value) throws IOException {
+ buffer.write("\n" + name + " : " + BitsUtil.byteToHexString(value));
+ }
+
+ protected void _report(OutputStreamWriter buffer, String message) throws IOException {
+ buffer.write("\n" + message);
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/ExeReader.java b/tools/launcher-generator/src/com/pme/exe/ExeReader.java
new file mode 100644
index 000000000000..b9c1649a8624
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/ExeReader.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe;
+
+import com.pme.exe.res.ValuesAdd;
+
+import java.io.*;
+
+/**
+ * Date: Mar 30, 2006
+ * Time: 4:14:38 PM
+ */
+public class ExeReader extends Bin.Structure{
+ private ArrayOfBins mySectionHeaders;
+ private SectionReader[] mySections;
+ private PeHeaderReader myPeHeader;
+ private ImageOptionalHeader myImageOptionalHeader;
+ private Bin.Bytes myBytes;
+ private Bin.Bytes myMsDosStub;
+ private MsDosHeader myMsDosHeader;
+ public ExeReader(String name) {
+ super(name);
+ myMsDosHeader = new MsDosHeader();
+ addMember( myMsDosHeader );
+ Bin.Value member = myMsDosHeader.getValueMember("lfanew");
+ ValuesAdd size = new ValuesAdd( member, new DWord("").setValue( myMsDosHeader.sizeInBytes() ) );
+ myMsDosStub = new Bytes( "MsDos stub program", size );
+ addMember( myMsDosStub );
+ myPeHeader = new PeHeaderReader( member );
+ addMember( myPeHeader );
+ myImageOptionalHeader = (ImageOptionalHeader) myPeHeader.getMember("Image Optional Header");
+ mySectionHeaders = (ArrayOfBins)myPeHeader.getMember( "ImageSectionHeaders" );
+ addSizeHolder( myImageOptionalHeader.getValueMember( "SizeOfImage" ) ); //b164
+ }
+
+ public long sizeOfHeaders(){
+ return myPeHeader.sizeInBytes() + myMsDosStub.sizeInBytes() + myMsDosHeader.sizeInBytes();
+ }
+
+ public long sizeInBytes() {
+ long result = 0;
+ long va = 0;
+ for ( int i = 0; i < mySectionHeaders.size(); ++i){
+ ImageSectionHeader header = (ImageSectionHeader)mySectionHeaders.get(i);
+ Value virtualAddress = header.getValueMember("VirtualAddress");
+ if ( va < virtualAddress.getValue() ){
+ result = mySections[i].sizeInBytes() + virtualAddress.getValue();
+ }
+ }
+ long div = result / 0x1000;
+ long r = result % 0x1000;
+ if ( r != 0 ){
+ div++;
+ }
+ result = div * 0x1000;
+ return result;
+ }
+
+ public SectionReader[] getSections(){
+ return mySections;
+ }
+ public ArrayOfBins getSectionHeaders(){
+ return mySectionHeaders;
+ }
+
+ public SectionReader getSectionReader( String sectionName ){
+ for (int i = 0; i < mySections.length; i++) {
+ SectionReader section = mySections[i];
+ if ( sectionName.equals( section.getSectionName() )){
+ return section;
+ }
+ }
+ return null;
+ }
+
+ public void read(DataInput stream) throws IOException {
+ super.read(stream);
+
+ long filePointer = getOffset() + sizeOfHeaders();
+
+ Bin.Value mainSectionsOffset;
+ mySections = new SectionReader[mySectionHeaders.size()];
+ for ( int i = 0; i < mySectionHeaders.size(); ++i ){
+ ImageSectionHeader sectionHeader = (ImageSectionHeader)mySectionHeaders.get(i);
+ Bin.Value startOffset = sectionHeader.getValueMember( "PointerToRawData" );
+ Bin.Value rva = sectionHeader.getValueMember( "VirtualAddress" );
+
+ if ( i == 0 ){
+ long size = startOffset.getValue() - filePointer;
+ if ( myBytes == null ){
+ myBytes = new Bytes( "Aligment", size );
+ addMemberToMapOnly( myBytes );
+ } else {
+ myBytes = (Bytes)getMember( "Aligment" );
+ myBytes.reset( (int)filePointer, (int)size );
+ }
+ myBytes.read( stream );
+ }
+
+ mainSectionsOffset = new ValuesAdd( rva, startOffset );
+ mySections[i] = new SectionReader( sectionHeader, startOffset, mainSectionsOffset, myImageOptionalHeader );
+ mySections[i].read( stream );
+ }
+ resetOffsets( 0 );
+ }
+
+ public void resetOffsets(long newOffset) {
+ super.resetOffsets(newOffset);
+ long mainOffset = myPeHeader.getOffset() + myPeHeader.sizeInBytes() + myBytes.sizeInBytes();
+ long offset = 0;
+ for (int i = 0; i < mySections.length; i++) {
+ Bin section = mySections[i];
+ section.resetOffsets( mainOffset + offset );
+ offset += section.sizeInBytes();
+ }
+ }
+
+ public void write(DataOutput stream) throws IOException {
+ super.write(stream);
+ myBytes.write( stream );
+ for (int i = 0; i < mySections.length; i++) {
+ mySections[i].write( stream );
+ }
+ }
+
+ public void report(OutputStreamWriter writer) throws IOException {
+ super.report(writer);
+ myBytes.report( writer );
+ mySectionHeaders.report( writer );
+ for ( int i = 0; i < mySections.length; ++i ){
+ mySections[i].report( writer );
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ ExeReader reader = new ExeReader( "SeaShell.exe" );
+ File file = new File( "C:\\work\\SeaShell.exe" );
+ RandomAccessFile stream = new RandomAccessFile( file, "r" );
+ reader.read( stream );
+ stream.close();
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/ImageDataDirectory.java b/tools/launcher-generator/src/com/pme/exe/ImageDataDirectory.java
new file mode 100644
index 000000000000..1fe592cc14f7
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/ImageDataDirectory.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe;
+
+/**
+ * Date: Mar 31, 2006
+ * Time: 10:40:56 PM
+ */
+public class ImageDataDirectory extends Bin.Structure {
+ public ImageDataDirectory(String name) {
+ super(name);
+ addMember( new DWord( "VirtualAddress" ) );
+ addMember( new DWord( "Size" ) );
+ }
+ public ImageDataDirectory( ){
+ this("");
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/ImageFileHeader.java b/tools/launcher-generator/src/com/pme/exe/ImageFileHeader.java
new file mode 100644
index 000000000000..50eb512b7f65
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/ImageFileHeader.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe;
+
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+
+/**
+ * Date: Mar 31, 2006
+ * Time: 5:17:01 PM
+ */
+public class ImageFileHeader extends Bin.Structure {
+ public ImageFileHeader() {
+ super("Image File Header");
+ addMember( new Machine( ) );
+ addMember( new Word( "NumberOfSections" ) );
+ addMember( new DWord( "TimeDateStamp" ) );
+ addMember( new DWord( "PointerToSymbolTable" ) );
+ addMember( new DWord( "NumberOfSymbols" ) );
+ addMember( new Word( "SizeOfOptionalHeader" ) );
+ addMember( new Word( "Characteristics" ) );
+ }
+
+ class Machine extends Bin.Word{
+
+ public Machine() {
+ super("Machine");
+ }
+
+ public void report( OutputStreamWriter writer ) throws IOException {
+ super.report( writer );
+ long machine = getValue();
+ if ( machine == 0x014c ){
+ _report(writer ,"Machine: Intel 386" );
+ } else if ( machine == 0x0002 ) {
+ _report( writer, "Machine: Intel 64" );
+ } else {
+ _report( writer, "Machine: Unknown" );
+ }
+ }
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/ImageOptionalHeader.java b/tools/launcher-generator/src/com/pme/exe/ImageOptionalHeader.java
new file mode 100644
index 000000000000..bfb007766e0c
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/ImageOptionalHeader.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe;
+
+/**
+ * Date: Mar 31, 2006
+ * Time: 6:01:16 PM
+ */
+public class ImageOptionalHeader extends Bin.Structure {
+ public ImageOptionalHeader() {
+ super("Image Optional Header");
+ addMember( new Word( "Magic" ) );
+ addMember( new Byte( "MajorLinkerVersion"));
+ addMember( new Byte( "MinorLinkerVersion"));
+ addMember( new DWord( "SizeOfCode" ) );
+ addMember( new DWord( "SizeOfInitializedData" ) );
+ addMember( new DWord( "SizeOfUninitializedData" ) );
+ addMember( new DWord( "AddressOfEntryPoint" ) );
+ addMember( new DWord( "BaseOfCode" ) );
+ addMember( new DWord( "BaseOfData" ) );
+ addMember( new DWord( "ImageBase" ) );
+ addMember( new DWord( "SectionAlignment" ) );
+ addMember( new DWord( "FileAlignment" ) );
+ addMember( new Word( "MajorOperatingSystemVersion" ) );
+ addMember( new Word( "MinorOperatingSystemVersion" ) );
+ addMember( new Word( "MajorImageVersion" ) );
+ addMember( new Word( "MinorImageVersion" ) );
+ addMember( new Word( "MajorSubsystemVersion" ) );
+ addMember( new Word( "MinorSubsystemVersion" ) );
+ addMember( new DWord( "Win32VersionValue" ) );
+ addMember( new DWord( "SizeOfImage" ) );
+ addMember( new DWord( "SizeOfHeaders" ) );
+ addMember( new DWord( "CheckSum" ) );
+ addMember( new Word( "Subsystem" ) );
+ addMember( new Word( "DllCharacteristics" ) );
+ addMember( new DWord( "SizeOfStackReserve" ) );
+ addMember( new DWord( "SizeOfStackCommit" ) );
+ addMember( new DWord( "SizeOfHeapReserve" ) );
+ addMember( new DWord( "SizeOfHeapCommit" ) );
+ addMember( new DWord( "LoaderFlags" ) );
+ DWord numberOfRvaAndSizes = (DWord)addMember( new DWord( "NumberOfRvaAndSizes") );
+ ArrayOfBins imageDataDirectories = new ArrayOfBins( "ImageDataDirectories", ImageDataDirectory.class, numberOfRvaAndSizes);
+ imageDataDirectories.setCountHolder( numberOfRvaAndSizes );
+
+ addMember( imageDataDirectories );
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/ImageSectionHeader.java b/tools/launcher-generator/src/com/pme/exe/ImageSectionHeader.java
new file mode 100644
index 000000000000..9fd68121451b
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/ImageSectionHeader.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe;
+
+/**
+ * Date: Apr 1, 2006
+ * Time: 1:54:57 PM
+ */
+public class ImageSectionHeader extends Bin.Structure{
+ public ImageSectionHeader() {
+ super("Image section header");
+ addMember( new Txt( "Name", 8 ));
+ addMember( new DWord( "VirtualSize"));
+ addMember( new DWord( "VirtualAddress"));
+ addMember( new DWord( "SizeOfRawData"));
+ addMember( new DWord( "PointerToRawData"));
+ addMember( new DWord( "PointerToRelocations"));
+ addMember( new DWord( "PointerToLinenumbers"));
+ addMember( new Word( "NumberOfRelocations"));
+ addMember( new Word( "NumberOfLinenumbers"));
+ addMember( new DWord( "Characteristics"));
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/InvalidMsDosHeaderException.java b/tools/launcher-generator/src/com/pme/exe/InvalidMsDosHeaderException.java
new file mode 100644
index 000000000000..5c0e482d9073
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/InvalidMsDosHeaderException.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe;
+
+import java.io.IOException;
+
+/**
+ * Date: Mar 31, 2006
+ * Time: 2:09:25 PM
+ */
+public class InvalidMsDosHeaderException extends IOException {
+ public InvalidMsDosHeaderException() {
+ }
+
+ public InvalidMsDosHeaderException(String s) {
+ super(s);
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/MsDosHeader.java b/tools/launcher-generator/src/com/pme/exe/MsDosHeader.java
new file mode 100644
index 000000000000..cf53f21e464a
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/MsDosHeader.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe;
+
+import java.io.IOException;
+import java.io.DataInput;
+
+/**
+ * Date: Mar 31, 2006
+ * Time: 2:10:01 PM
+ */
+public class MsDosHeader extends Bin.Structure {
+ public MsDosHeader() {
+ super("MSDOS Header");
+ addMember( new Word( "magic" ), "Magic number" );
+ addMember( new Word( "cblp" ), "Bytes on last page of file" );
+ addMember( new Word( "cp" ), "Pages in file" );
+ addMember( new Word( "crlc" ), "Relocations" );
+ addMember( new Word( "cparhdr" ), "Size of header in paragraphs" );
+ addMember( new Word( "minalloc" ), "Minimum extra paragraphs needed" );
+ addMember( new Word( "maxalloc" ), "Maximum extra paragraphs needed" );
+ addMember( new Word( "ss" ), "Initial (relative) SS value" );
+ addMember( new Word( "sp" ), "Initial SP value" );
+ addMember( new Word( "csum" ), "Checksum" );
+ addMember( new Word( "ip" ), "Initial IP value" );
+ addMember( new Word( "cs" ), "Initial (relative) CS value" );
+ addMember( new Word( "lfarlc" ), "File address of relocation table" );
+ addMember( new Word( "ovno" ), "Overlay number" );
+ addMember( new ArrayOfBins( "res", Word.class,4 ), "Reserved words" );
+ addMember( new Word( "oemid" ), "OEM identifier (for e_oeminfo)" );
+ addMember( new Word( "oeminfo" ), "OEM information; e_oemid specific" );
+ addMember( new ArrayOfBins( "res2", Word.class, 10 ), "Reserved words" );
+ addMember( new DWord( "lfanew" ), "File address of new exe header" );
+ }
+
+ public void read(DataInput stream) throws IOException {
+ super.read( stream );
+ long magic = getValue( "magic" );
+ if (magic != 0x5a4d) {
+ throw new InvalidMsDosHeaderException("First two chars in exe file must be 'MZ'");
+ }
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/PeHeaderReader.java b/tools/launcher-generator/src/com/pme/exe/PeHeaderReader.java
new file mode 100644
index 000000000000..6a5217c52899
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/PeHeaderReader.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe;
+
+import java.io.IOException;
+import java.io.DataInput;
+
+/**
+ * Date: Mar 31, 2006
+ * Time: 5:00:49 PM
+ */
+public class PeHeaderReader extends Bin.Structure{
+ private Bin.Value myStartOffset;
+
+ public PeHeaderReader( Bin.Value startOffset ){
+ super( "PE Header" );
+ myStartOffset = startOffset;
+ addOffsetHolder( myStartOffset );
+ addMember( new DWord( "Signature" ) );
+ ImageFileHeader imageFileHeader = new ImageFileHeader();
+ addMember( imageFileHeader );
+ addMember( new ImageOptionalHeader() );
+ Bin.Value numberOfSections = imageFileHeader.getValueMember( "NumberOfSections" );
+ ArrayOfBins imageSectionHeaders = new ArrayOfBins( "ImageSectionHeaders", ImageSectionHeader.class, numberOfSections );
+ imageSectionHeaders.setCountHolder( numberOfSections );
+ addMember( imageSectionHeaders );
+ }
+ public void read(DataInput stream) throws IOException {
+ super.read( stream );
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/SectionReader.java b/tools/launcher-generator/src/com/pme/exe/SectionReader.java
new file mode 100644
index 000000000000..9e95ecd453f6
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/SectionReader.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe;
+
+import com.pme.exe.res.ResourceSectionReader;
+
+import java.io.OutputStreamWriter;
+import java.io.IOException;
+
+/**
+ * Date: Apr 5, 2006
+ * Time: 9:48:35 AM
+ */
+public class SectionReader extends Bin.Structure{
+ private Bin.Txt myName;
+ public SectionReader( ImageSectionHeader sectionHeader, Bin.Value startOffset, Bin.Value mainSectionsOffset, ImageOptionalHeader imageOptionalHeader ) {
+ super("Section");
+
+ myName = (Bin.Txt)sectionHeader.getMember("Name");
+ String sectionName = myName.getText();
+ if ( ".rsrc".equals(sectionName) ){
+ addMember( new ResourceSectionReader( sectionHeader, startOffset, mainSectionsOffset, imageOptionalHeader ) );
+ } else {
+ Bin.Value size = sectionHeader.getValueMember( "SizeOfRawData" );
+ addMember( new Simple( sectionName, startOffset, size ) );
+ }
+ }
+
+ public String getSectionName(){
+ return myName.getText();
+ }
+
+ public void report(OutputStreamWriter writer) throws IOException {
+ _report( writer, "Section name: " + myName.getText() );
+ super.report(writer);
+ }
+
+ public static class Simple extends Bin.Structure{
+
+ public Simple(String name, Bin.Value startOffset, Bin.Value size) {
+ super(name);
+ addOffsetHolder( startOffset );
+ addSizeHolder( size );
+ addMember( new Bin.Bytes( "Raw data", size ) );
+ }
+ }
+
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/DataEntry.java b/tools/launcher-generator/src/com/pme/exe/res/DataEntry.java
new file mode 100644
index 000000000000..0166fe278833
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/DataEntry.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res;
+
+import com.pme.exe.Bin;
+
+import java.io.IOException;
+import java.io.DataInput;
+import java.io.DataOutput;
+
+/**
+ * Date: Apr 20, 2006
+ * Time: 3:58:05 PM
+ */
+public class DataEntry extends LevelEntry {
+ private ResourceSectionReader mySection;
+ private RawResource myRawResource = null;
+ public DataEntry( ResourceSectionReader section, Bin.Value offsetHolder ) {
+ super("DataEntry");
+ addMember(new DWord("RVA"));
+ addMember(new DWord("Size"));
+ addMember(new DWord("Code Page"));
+ addMember(new DWord("Reserved"));
+ mySection = section;
+ addOffsetHolder( new ValuesSub( offsetHolder, mySection.getStartOffset() ) );
+ }
+
+ public RawResource getRawResource() {
+ return myRawResource;
+ }
+
+ public void initRawData(){
+ myRawResource = new RawResource( mySection, (DWord) getValueMember("RVA"), (DWord) getValueMember("Size"));
+ getLevel().addLevelEntry( myRawResource );
+ }
+ public void insertRawData( int index ){
+ myRawResource = new RawResource( mySection, (DWord) getValueMember("RVA"), (DWord) getValueMember("Size"));
+ getLevel().insertLevelEntry( index, myRawResource );
+ }
+
+ public void read(DataInput stream) throws IOException {
+ super.read(stream);
+ initRawData();
+ }
+
+ public void write(DataOutput stream) throws IOException {
+ super.write(stream);
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/DirectoryEntry.java b/tools/launcher-generator/src/com/pme/exe/res/DirectoryEntry.java
new file mode 100644
index 000000000000..7b78a1773d11
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/DirectoryEntry.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res;
+
+import com.pme.exe.Bin;
+
+import java.io.*;
+import java.util.ArrayList;
+
+/**
+ * Date: Apr 6, 2006
+ * Time: 11:22:12 PM
+ */
+public class DirectoryEntry extends LevelEntry {
+ private ArrayOfBins myNamedEntries;
+ private ArrayOfBins myIdEntries;
+ private ResourceSectionReader mySection;
+ private ArrayList mySubDirs = new ArrayList();
+ private ArrayList myDatas = new ArrayList();
+
+ public DirectoryEntry( ResourceSectionReader section, EntryDescription entry ) {
+ super( createName( entry ) );
+ addMember(new DWord("Characteristics"));
+ addMember(new DWord("TimeDateStamp"));
+ addMember(new Word("MajorVersion"));
+ addMember(new Word("MinorVersion"));
+ addMember(new Word("NumberOfNamedEntries"));
+ addMember(new Word("NumberOfIdEntries"));
+ mySection = section;
+ if ( entry != null ){
+ Value flagValue = new DWord( "flag" ).setValue( 0x80000000 );
+ Bin.Value offset = entry.getValueMember("OffsetToData");
+ addOffsetHolder( new ValuesSub( offset, new ValuesAdd( mySection.getStartOffset(), flagValue ) ));
+ }
+ }
+
+ public ResourceSectionReader getSection(){
+ return mySection;
+ }
+
+ public static String createName( EntryDescription entry ){
+ String name = "IRD";
+ if ( entry != null ){
+ name += entry.getValueMember( "Name" ).getValue();
+ }
+ return name;
+ }
+
+ public DirectoryEntry findSubDir( String name ){
+ for (int i = 0; i < mySubDirs.size(); i++) {
+ DirectoryEntry directoryEntry = (DirectoryEntry) mySubDirs.get(i);
+ if ( directoryEntry.getName().equals( name ) ){
+ return directoryEntry;
+ }
+ }
+ return null;
+ }
+
+ public ArrayList getSubDirs(){
+ return mySubDirs;
+ }
+
+ public RawResource getRawResource( int index ){
+ DataEntry dataEntry = (DataEntry)myDatas.get(index);
+ return dataEntry.getRawResource();
+ }
+ public ArrayList getDatas() {
+ return myDatas;
+ }
+
+ public long sizeInBytes() {
+ return super.sizeInBytes();
+ }
+
+ public void insertDataEntry( int index, DataEntry dataEntry ){
+ myDatas.add( dataEntry );
+ getLevel().insertLevelEntry( index, dataEntry );
+ }
+
+ public void addDataEntry( DataEntry dataEntry ){
+ myDatas.add( dataEntry );
+ getLevel().addLevelEntry( dataEntry );
+ }
+
+ public void insertDirectoryEntry( int index, DirectoryEntry dir ){
+ getLevel().insertLevelEntry( index, dir );
+ mySubDirs.add( dir );
+ }
+
+ public void addDirectoryEntry( DirectoryEntry dir ){
+ getLevel().addLevelEntry( dir );
+ mySubDirs.add( dir );
+ }
+ public void addIdEntry( EntryDescription entry ){
+ if ( myIdEntries == null ){
+ Word numberOfNamedEntries = (Word) getMember("NumberOfIdEntries");
+ myIdEntries = new ArrayOfBins("Id entries", EntryDescription.class, 0);
+ addMember(myIdEntries);
+ myIdEntries.setCountHolder(numberOfNamedEntries);
+ }
+ myIdEntries.addBin( entry );
+ }
+
+ public void read(DataInput stream) throws IOException {
+ super.read(stream);
+
+ Word numberOfNamedEntries = (Word) getMember("NumberOfNamedEntries");
+ myNamedEntries = new ArrayOfBins("Named entries", EntryDescription.class, numberOfNamedEntries);
+ addMember(myNamedEntries);
+ myNamedEntries.setCountHolder(numberOfNamedEntries);
+ myNamedEntries.read(stream);
+
+ Word numberOfIdEntries = (Word) getMember("NumberOfIdEntries");
+ myIdEntries = new ArrayOfBins("Id entries", EntryDescription.class, numberOfIdEntries);
+ addMember(myIdEntries);
+ myIdEntries.setCountHolder(numberOfIdEntries);
+ myIdEntries.read(stream);
+
+ processEntries(myNamedEntries);
+ processEntries(myIdEntries);
+ }
+
+ private void processEntries(ArrayOfBins entries) {
+ for (int i = 0; i < entries.size(); ++i) {
+ EntryDescription entry = (EntryDescription) entries.get(i);
+ Bin.Value offset = entry.getValueMember("OffsetToData");
+ if ((offset.getValue() & 0x80000000) != 0) {
+ addDirectoryEntry( new DirectoryEntry( mySection, entry ) );
+ } else {
+ addDataEntry( new DataEntry( mySection, offset ) );
+ }
+ }
+ }
+
+ public void report(OutputStreamWriter writer) throws IOException {
+ super.report(writer);
+ }
+
+ public void write(DataOutput stream) throws IOException {
+ super.write(stream);
+ }
+
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/EntryDescription.java b/tools/launcher-generator/src/com/pme/exe/res/EntryDescription.java
new file mode 100644
index 000000000000..255f7aa7956a
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/EntryDescription.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res;
+
+import com.pme.exe.Bin;
+
+/**
+ * Date: Apr 20, 2006
+ * Time: 3:59:15 PM
+ */
+public class EntryDescription extends Bin.Structure {
+ public EntryDescription() {
+ super("Entry");
+ addMember(new DWord("Name"));
+ addMember(new DWord("OffsetToData"));
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/Level.java b/tools/launcher-generator/src/com/pme/exe/res/Level.java
new file mode 100644
index 000000000000..25ed950a66d2
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/Level.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res;
+
+import com.pme.exe.Bin;
+
+import java.io.*;
+
+/**
+ * Date: Apr 20, 2006
+ * Time: 3:56:31 PM
+ */
+public class Level extends Bin.Structure {
+ private Level mySubLevel = null;
+
+ public Level() {
+ super("Level");
+ }
+
+ public void addLevelEntry(LevelEntry dir) {
+ if (mySubLevel == null) {
+ mySubLevel = new Level();
+ }
+ dir.setLevel(mySubLevel);
+ addMember(dir);
+ }
+
+ public void insertLevelEntry(int index, LevelEntry dir) {
+ if (mySubLevel == null) {
+ mySubLevel = new Level();
+ }
+ dir.setLevel(mySubLevel);
+ insertMember(index,dir);
+ }
+
+ public long sizeInBytes() {
+ if (mySubLevel != null) {
+ return super.sizeInBytes() + mySubLevel.sizeInBytes();
+ }
+ return super.sizeInBytes();
+ }
+
+ public void resetOffsets(long newOffset) {
+ super.resetOffsets(newOffset);
+ if (mySubLevel != null) {
+ mySubLevel.resetOffsets(getOffset() + super.sizeInBytes());
+ }
+ }
+ /*
+ public void copyFrom(Bin structure) {
+ super.copyFrom(structure);
+ if (mySubLevel != null) {
+ mySubLevel.copyFrom(((Level)structure).mySubLevel);
+ }
+ }
+ */
+ public void read(DataInput stream) throws IOException {
+ super.read(stream);
+ if (mySubLevel != null) {
+ mySubLevel.read(stream);
+ }
+ }
+
+ public void write(DataOutput stream) throws IOException {
+ super.write(stream);
+ if (mySubLevel != null) {
+ mySubLevel.write(stream);
+ }
+ }
+
+ public void report(OutputStreamWriter writer) throws IOException {
+ super.report(writer);
+ if (mySubLevel != null) {
+ mySubLevel.report(writer);
+ }
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/LevelEntry.java b/tools/launcher-generator/src/com/pme/exe/res/LevelEntry.java
new file mode 100644
index 000000000000..f6088613db9b
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/LevelEntry.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res;
+
+import com.pme.exe.Bin;
+
+/**
+ * Date: Apr 17, 2006
+ * Time: 11:02:21 PM
+ */
+public abstract class LevelEntry extends Bin.Structure {
+ private Level myLevel = null;
+
+ public LevelEntry(String name) {
+ super(name);
+ }
+
+ public void setLevel(Level level) {
+ myLevel = level;
+ }
+
+ public Level getLevel() {
+ return myLevel;
+ }
+
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/RawResource.java b/tools/launcher-generator/src/com/pme/exe/res/RawResource.java
new file mode 100644
index 000000000000..81c3f5c832f1
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/RawResource.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res;
+
+/**
+ * Date: Apr 25, 2006
+ * Time: 3:12:58 PM
+ */
+public class RawResource extends LevelEntry {
+
+ public RawResource(ResourceSectionReader section, DWord rva, DWord size) {
+ super("Raw Resource");
+ Value offsetHolder = new ValuesAdd(rva, section.getMainSectionsOffset());
+ Bytes bytes = new Bytes("Raw Resource", offsetHolder, size);
+ bytes.addOffsetHolder(offsetHolder);
+ bytes.addSizeHolder(size);
+ addMember(bytes);
+ }
+ public Bytes getBytes(){
+ return (Bytes)getMember( "Raw Resource" );
+ }
+ public void setBytes( byte[] bytes ){
+ Bytes mem = (Bytes) getMember("Raw Resource");
+ mem.setBytes( bytes );
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/ResourceSectionReader.java b/tools/launcher-generator/src/com/pme/exe/res/ResourceSectionReader.java
new file mode 100644
index 000000000000..7c50191c33cd
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/ResourceSectionReader.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res;
+
+import com.pme.exe.Bin;
+import com.pme.exe.ImageSectionHeader;
+import com.pme.exe.ImageOptionalHeader;
+import com.pme.exe.ImageDataDirectory;
+
+import java.io.*;
+
+/**
+ * Date: Apr 6, 2006
+ * Time: 7:10:09 PM
+ */
+public class ResourceSectionReader extends Bin.Structure {
+ private Level myRoot = new Level();
+ private Bin.Value myStartOffset;
+ private Bin.Value myMainSectionsOffset;
+ private Bin.Value mySize;
+ private Bin.Bytes myBytes;
+
+ public ResourceSectionReader( ImageSectionHeader sectionHeader, Bin.Value startOffset, Bin.Value mainSectionsOffset, ImageOptionalHeader imageOptionalHeader) {
+ super(((Bin.Txt)sectionHeader.getMember("Name")).getText());
+ myStartOffset = startOffset;
+ mySize = sectionHeader.getValueMember( "SizeOfRawData" );
+ Bin.Value virtualSize = sectionHeader.getValueMember( "VirtualSize" );
+ myMainSectionsOffset = mainSectionsOffset;
+ addOffsetHolder(startOffset);
+
+ ArrayOfBins imageDataDirs = (ArrayOfBins)imageOptionalHeader.getMember( "ImageDataDirectories" );
+ Bin[] bins = imageDataDirs.getArray();
+ ImageDataDirectory imageDataDirectory = (ImageDataDirectory)bins[2];
+ Value size = imageDataDirectory.getValueMember("Size");
+
+ addSizeHolder(mySize);
+ addSizeHolder(virtualSize);
+ addSizeHolder(size);
+ myRoot.addLevelEntry(new DirectoryEntry( this, null ));
+ addMember(myRoot);
+ }
+
+ public DirectoryEntry getRoot(){
+ return (DirectoryEntry)myRoot.getMember( "IRD" );
+ }
+
+ public Value getStartOffset() {
+ return myStartOffset;
+ }
+
+ public Value getMainSectionsOffset() {
+ return myMainSectionsOffset;
+ }
+
+ public long sizeInBytes() {
+ return super.sizeInBytes() + myBytes.sizeInBytes();
+ }
+
+ public void read(DataInput stream) throws IOException {
+ super.read(stream);
+ DWord size = new DWord("size");
+ size.setValue((mySize.getValue() - myRoot.sizeInBytes()));
+ DWord startOffset = new DWord("startOffset");
+ startOffset.setValue((myStartOffset.getValue() + myRoot.sizeInBytes()));
+ myBytes = new Bin.Bytes("Raw data", startOffset, size);
+ myBytes.read(stream);
+ }
+
+ public void write(DataOutput stream) throws IOException {
+ super.write(stream);
+ myBytes.write(stream);
+ }
+
+ public void report(OutputStreamWriter writer) throws IOException {
+ super.report(writer);
+ myBytes.report(writer);
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/StringTable.java b/tools/launcher-generator/src/com/pme/exe/res/StringTable.java
new file mode 100644
index 000000000000..9339a0dbc584
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/StringTable.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res;
+
+import com.pme.exe.Bin;
+
+import java.io.*;
+
+/**
+ * Date: Apr 27, 2006
+ * Time: 12:43:28 PM
+ */
+public class StringTable {
+ String[] strings = new String[16];
+
+ public StringTable(byte[] bytes) throws IOException {
+ ByteArrayInputStream bytesStream = new ByteArrayInputStream(bytes);
+ DataInputStream stream = new DataInputStream(bytesStream);
+ Bin.Word count = new Bin.Word();
+ for (int i = 0; i < 16; ++i) {
+ count.read(stream);
+ if ( count.getValue() != 0 ){
+ Bin.Txt txt = new Bin.Txt("", (int)(count.getValue() * 2));
+ txt.read( stream );
+ strings[i] = txt.getText();
+ } else {
+ strings[i] = "";
+ }
+ }
+ }
+
+ public void setString( int index, String string ){
+ strings[index] = string;
+ }
+
+ public byte[] getBytes() throws IOException {
+ int size = 0;
+ for ( int i = 0; i < strings.length; ++i){
+ size += 2 + strings[i].length() * 2;
+ }
+ ByteArrayOutputStream bytesStream = new ByteArrayOutputStream(size);
+ DataOutputStream stream = new DataOutputStream(bytesStream);
+ for ( int i = 0; i < strings.length; ++i){
+ int count = strings[i].length();
+ new Bin.Word().setValue( count ).write( stream );
+ if ( count != 0 ){
+ new Bin.Txt( "", strings[i] ).write( stream );
+ }
+ }
+ return bytesStream.toByteArray();
+ }
+ }
diff --git a/tools/launcher-generator/src/com/pme/exe/res/ValuesAdd.java b/tools/launcher-generator/src/com/pme/exe/res/ValuesAdd.java
new file mode 100644
index 000000000000..86fe69d2a740
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/ValuesAdd.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res;
+
+import com.pme.exe.Bin;
+
+/**
+ * Date: Apr 20, 2006
+ * Time: 4:32:29 PM
+ */
+public class ValuesAdd extends Bin.DWord {
+ private Bin.Value myActual;
+ private Bin.Value myMinus;
+
+ public ValuesAdd(Bin.Value actual, Bin.Value minusConst) {
+ super(actual.getName());
+ myActual = actual;
+ myMinus = minusConst;
+ }
+
+ public Value setValue(long value) {
+ return myActual.setValue(value + myMinus.getValue());
+ }
+
+ public long getValue() {
+ return myActual.getValue() - myMinus.getValue();
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/ValuesSub.java b/tools/launcher-generator/src/com/pme/exe/res/ValuesSub.java
new file mode 100644
index 000000000000..79d8ebee1f37
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/ValuesSub.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res;
+
+import com.pme.exe.Bin;
+
+/**
+ * Date: Apr 20, 2006
+ * Time: 4:18:29 PM
+ */
+public class ValuesSub extends Bin.DWord {
+ private Bin.Value myActual;
+ private Bin.Value myMinus;
+
+ public ValuesSub(Bin.Value actual, Bin.Value minusConst) {
+ super(actual.getName());
+ myActual = actual;
+ myMinus = minusConst;
+ }
+
+ public Value setValue(long value) {
+ return myActual.setValue(value - myMinus.getValue());
+ }
+
+ public long getValue() {
+ return myActual.getValue() + myMinus.getValue();
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/bmp/BitmapFileHeader.java b/tools/launcher-generator/src/com/pme/exe/res/bmp/BitmapFileHeader.java
new file mode 100644
index 000000000000..7348672a33e5
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/bmp/BitmapFileHeader.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res.bmp;
+
+import com.pme.exe.Bin;
+
+/**
+ * Date: May 3, 2006
+ * Time: 12:34:47 PM
+ */
+public class BitmapFileHeader extends Bin.Structure{
+ public BitmapFileHeader() {
+ super("Bitmap File Header");
+ addMember( new Word( "bfType" ) );
+ addMember( new DWord( "bfSize" ) );
+ addMember( new Word( "bfReserved1" ) );
+ addMember( new Word( "bfReserved2" ) );
+ addMember( new DWord( "bfOffBits" ) );
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/bmp/BmpFile.java b/tools/launcher-generator/src/com/pme/exe/res/bmp/BmpFile.java
new file mode 100644
index 000000000000..93c9feed99a9
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/bmp/BmpFile.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res.bmp;
+
+import com.pme.exe.Bin;
+
+import java.io.File;
+import java.io.DataInput;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+/**
+ * Date: May 3, 2006
+ * Time: 12:33:01 PM
+ */
+public class BmpFile extends Bin.Structure {
+ private File myFile;
+ private BitmapFileHeader myHeader = new BitmapFileHeader();
+
+ public BmpFile(File file) {
+ super(file.getName());
+ myFile = file;
+ addMember( myHeader );
+ }
+
+ public void read() throws IOException {
+ RandomAccessFile stream = null;
+ try {
+ stream = new RandomAccessFile(myFile, "r");
+ read(stream);
+ } finally {
+ if (stream != null) {
+ stream.close();
+ }
+ }
+ }
+
+ public void read(DataInput stream) throws IOException {
+ super.read(stream);
+ Value bfSize = myHeader.getValueMember("bfSize");
+ long size = bfSize.getValue() - sizeInBytes();
+ Bytes bytes = new Bytes( "Data", size );
+ bytes.read( stream );
+ addMember( bytes );
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/bmp/PictureResourceInjector.java b/tools/launcher-generator/src/com/pme/exe/res/bmp/PictureResourceInjector.java
new file mode 100644
index 000000000000..09028007be27
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/bmp/PictureResourceInjector.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res.bmp;
+
+import com.pme.exe.res.DirectoryEntry;
+import com.pme.exe.res.RawResource;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+/**
+ * Date: May 3, 2006
+ * Time: 1:00:08 PM
+ */
+public class PictureResourceInjector {
+ public class PictureWrongFormat extends IOException {
+ public PictureWrongFormat(File file) {
+ super("Picture file is not found: " + file.getPath());
+ }
+ }
+
+ public void inject(File file, DirectoryEntry root, String resourceId) throws IOException {
+ byte[] bytes = new byte[(int) file.length()];
+ RandomAccessFile stream = null;
+ try {
+ stream = new RandomAccessFile(file, "r");
+ stream.read(bytes);
+ }
+ catch (IOException exception) {
+ throw new PictureWrongFormat(file);
+ }
+ finally {
+ if (stream != null) {
+ stream.close();
+ }
+ }
+ DirectoryEntry subDirBmp = root.findSubDir("IRD2").findSubDir(resourceId);
+ RawResource bmpRes = subDirBmp.getRawResource(0);
+ bmpRes.setBytes(bytes);
+ }
+
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/icon/GroupIconResource.java b/tools/launcher-generator/src/com/pme/exe/res/icon/GroupIconResource.java
new file mode 100644
index 000000000000..f3e19ae62082
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/icon/GroupIconResource.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res.icon;
+
+import com.pme.exe.Bin;
+import com.pme.exe.res.LevelEntry;
+import com.pme.exe.res.Level;
+
+/**
+ * Date: Apr 28, 2006
+ * Time: 11:35:48 AM
+ */
+public class GroupIconResource extends Bin.Structure {
+ public GroupIconResource( Bin.Value idCount ) {
+ super("GroupIcon");
+ addMember(new IconHeader());
+ Level level = new Level();
+ ArrayOfBins arrayOfBins = new ArrayOfBins("Icon directories", GroupIconResourceDirectory.class, idCount);
+
+ addMember(level);
+ Bin[] array = arrayOfBins.getArray();
+ for (Bin bin : array) {
+ level.addLevelEntry((LevelEntry) bin);
+ }
+
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/icon/GroupIconResourceDirectory.java b/tools/launcher-generator/src/com/pme/exe/res/icon/GroupIconResourceDirectory.java
new file mode 100644
index 000000000000..d1f0e17cda85
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/icon/GroupIconResourceDirectory.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res.icon;
+
+import com.pme.exe.res.LevelEntry;
+
+/**
+ * Date: Apr 28, 2006
+ * Time: 11:38:20 AM
+ */
+public class GroupIconResourceDirectory extends LevelEntry {
+ public GroupIconResourceDirectory() {
+ super("Icon Directory");
+ addMember( new Byte( "bWidth" ) );
+ addMember( new Byte( "bHeight" ) );
+ addMember( new Byte( "bColorCount" ) );
+ addMember( new Byte( "bReserved" ) );
+ addMember( new Word( "wPlanes" ) );
+ addMember( new Word( "wBitCount" ) );
+ addMember( new DWord( "dwBytesInRes" ) );
+ addMember( new Word( "dwId" ) );
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/icon/IconDirectory.java b/tools/launcher-generator/src/com/pme/exe/res/icon/IconDirectory.java
new file mode 100644
index 000000000000..0a48c51a3659
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/icon/IconDirectory.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res.icon;
+
+import com.pme.exe.res.LevelEntry;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+/**
+ * Date: Apr 27, 2006
+ * Time: 1:13:15 PM
+ */
+public class IconDirectory extends LevelEntry {
+ private RawBytes myRawBytes;
+ public IconDirectory() {
+ super("Icon Directory");
+ addMember( new Byte( "bWidth" ) );
+ addMember( new Byte( "bHeight" ) );
+ addMember( new Byte( "bColorCount" ) );
+ addMember( new Byte( "bReserved" ) );
+ addMember( new Word( "wPlanes" ) );
+ addMember( new Word( "wBitCount" ) );
+ addMember( new DWord( "dwBytesInRes" ) );
+ addMember( new DWord( "dwImageOffset" ) );
+ }
+
+ public byte[] getRawBytes(){
+ Bytes bytes = (Bytes)myRawBytes.getMember( "Raw Bytes" );
+ return bytes.getBytes();
+ }
+
+ public void read(DataInput stream) throws IOException {
+ super.read(stream);
+ RawBytes bytes = new RawBytes( getValueMember( "dwImageOffset" ),
+ getValueMember( "dwBytesInRes" ));
+ myRawBytes = bytes;
+ getLevel().addLevelEntry( bytes );
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/icon/IconFile.java b/tools/launcher-generator/src/com/pme/exe/res/icon/IconFile.java
new file mode 100644
index 000000000000..c4e8cf7c43dc
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/icon/IconFile.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res.icon;
+
+import com.pme.exe.Bin;
+import com.pme.exe.res.Level;
+import com.pme.exe.res.LevelEntry;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.io.File;
+import java.io.RandomAccessFile;
+
+/**
+ * Date: Apr 27, 2006
+ * Time: 12:52:09 PM
+ */
+public class IconFile extends Bin.Structure {
+ private Level myImages = new Level();
+ private File myFile;
+
+ public class IconWrongFormat extends IOException {
+ public IconWrongFormat( File file ) {
+ super("Icon file has wrong format:" + file.getPath());
+ }
+ }
+
+ public IconFile(File file) {
+ super(file.getName());
+ myFile = file;
+ addMember(new IconHeader());
+ }
+
+ public void read() throws IOException {
+ RandomAccessFile stream = null;
+ try {
+ stream = new RandomAccessFile(myFile, "r");
+ read(stream);
+ } finally {
+ if (stream != null) {
+ stream.close();
+ }
+ }
+ }
+
+ public void read(DataInput stream) throws IOException {
+ try {
+ super.read(stream);
+ Word idCount = (Word) ((Bin.Structure) getMember("Header")).getMember("idCount");
+ ArrayOfBins iconDirs = new ArrayOfBins("Icon directories", IconDirectory.class, idCount);
+ iconDirs.setCountHolder(idCount);
+ addMember(myImages);
+ Bin[] array = iconDirs.getArray();
+ for (int i = 0; i < array.length; i++) {
+ Bin bin = array[i];
+ myImages.addLevelEntry((LevelEntry) bin);
+ }
+ myImages.read(stream);
+ }
+ catch (IOException exception) {
+ throw new IconWrongFormat( myFile );
+ }
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/icon/IconHeader.java b/tools/launcher-generator/src/com/pme/exe/res/icon/IconHeader.java
new file mode 100644
index 000000000000..fe1f1548aab4
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/icon/IconHeader.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res.icon;
+
+import com.pme.exe.Bin;
+
+/**
+ * Date: Apr 28, 2006
+ * Time: 11:30:10 AM
+ */
+public class IconHeader extends Bin.Structure{
+ public IconHeader() {
+ super("Header");
+ addMember(new Word("idReserved"));
+ addMember(new Word("idType"));
+ addMember(new Word("idCount"));
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/icon/IconResourceInjector.java b/tools/launcher-generator/src/com/pme/exe/res/icon/IconResourceInjector.java
new file mode 100644
index 000000000000..59dba368fc46
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/icon/IconResourceInjector.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res.icon;
+
+import com.pme.exe.res.*;
+import com.pme.exe.Bin;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.util.ArrayList;
+
+/**
+ * Date: Apr 28, 2006
+ * Time: 10:56:55 AM
+ */
+public class IconResourceInjector {
+
+ public void injectIcon(File file, DirectoryEntry root, String iconId) throws IOException {
+ IconFile iconFile = new IconFile(file);
+ iconFile.read();
+
+ DirectoryEntry subDirGroupIcon = root.findSubDir("IRD14").findSubDir(iconId);
+ RawResource groupIcon = subDirGroupIcon.getRawResource(0);
+
+ Bin.Value idCount = iconFile.getStructureMember("Header").getValueMember("idCount");
+
+ GroupIconResource groupIconResource = new GroupIconResource(idCount);
+ groupIconResource.copyFrom(iconFile);
+ Level level = (Level) groupIconResource.getMember("Level");
+ ArrayList directories = level.getMembers();
+ for (int i = 0; i < directories.size(); ++i) {
+ GroupIconResourceDirectory grpDir = (GroupIconResourceDirectory) directories.get(i);
+ grpDir.getValueMember("dwId").setValue(i + 1);
+ }
+ long size = groupIconResource.sizeInBytes();
+ ByteArrayOutputStream bytesStream = new ByteArrayOutputStream((int) size);
+ DataOutputStream stream = new DataOutputStream(bytesStream);
+ groupIconResource.write(stream);
+ groupIcon.getBytes().setBytes(bytesStream.toByteArray());
+
+ DirectoryEntry iconsDir = root.findSubDir("IRD3");
+ DirectoryEntry subDirIcon = iconsDir.findSubDir("IRD1");
+ RawResource rawResource = subDirIcon.getRawResource(0);
+ Level iconFileLevel = (Level) iconFile.getMember("Level");
+ IconDirectory iconDirectory = (IconDirectory) iconFileLevel.getMembers().get(0);
+ rawResource.setBytes(iconDirectory.getRawBytes());
+
+ ArrayList icons = iconFileLevel.getMembers();
+ for (int i = 1; i < icons.size(); i++) {
+ insertIcon(iconsDir, (IconDirectory) icons.get(i), i);
+ }
+ }
+
+ private void insertIcon(DirectoryEntry iconsDir, IconDirectory iconDirectory, int index) {
+ EntryDescription entryDescription = new EntryDescription();
+ Bin.Value name = entryDescription.getValueMember("Name");
+ name.setValue(index + 1);
+
+ DirectoryEntry entryDirIcon2 = new DirectoryEntry(iconsDir.getSection(), entryDescription);
+ iconsDir.insertDirectoryEntry(index, entryDirIcon2);
+ iconsDir.addIdEntry(entryDescription);
+
+ EntryDescription entry409 = new EntryDescription();
+ Bin.Value name409 = entry409.getValueMember("Name");
+ name409.setValue(0x409);
+
+ entryDirIcon2.addIdEntry(entry409);
+
+ Bin.Value offset = entry409.getValueMember("OffsetToData");
+ DataEntry dataEntry = new DataEntry(entryDirIcon2.getSection(), offset);
+
+ entryDirIcon2.insertDataEntry(index, dataEntry);
+ dataEntry.insertRawData(index);
+ RawResource rawRes = dataEntry.getRawResource();
+ rawRes.setBytes(iconDirectory.getRawBytes());
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/icon/RawBytes.java b/tools/launcher-generator/src/com/pme/exe/res/icon/RawBytes.java
new file mode 100644
index 000000000000..f2b9ed526538
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/icon/RawBytes.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res.icon;
+
+import com.pme.exe.res.LevelEntry;
+import com.pme.exe.Bin;
+
+/**
+ * Date: Apr 27, 2006
+ * Time: 1:44:11 PM
+ */
+public class RawBytes extends LevelEntry {
+ public RawBytes( Bin.Value offsetHolder, Bin.Value size ) {
+ super("Raw Bytes");
+ Bytes bytes = new Bytes("Raw Bytes", offsetHolder, size);
+ bytes.addOffsetHolder( offsetHolder );
+ bytes.addSizeHolder( size );
+ addMember( bytes );
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/vi/FixedFileInfo.java b/tools/launcher-generator/src/com/pme/exe/res/vi/FixedFileInfo.java
new file mode 100644
index 000000000000..b6599a3c8bc0
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/vi/FixedFileInfo.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res.vi;
+
+import com.pme.exe.Bin;
+
+/**
+ * Date: May 10, 2006
+ * Time: 1:35:49 PM
+ */
+public class FixedFileInfo extends Bin.Structure {
+ public FixedFileInfo() {
+ super("FixedFileInfo");
+ addMember( new DWord( "dwSignature" ) );
+ addMember( new DWord( "dwStrucVersion" ) );
+ addMember( new DWord( "dwFileVersionMS" ) );
+ addMember( new DWord( "dwFileVersionLS" ) );
+ addMember( new DWord( "dwProductVersionMS" ) );
+ addMember( new DWord( "dwProductVersionLS" ) );
+ addMember( new DWord( "dwFileFlagsMask" ) );
+ addMember( new DWord( "dwFileFlags" ) );
+ addMember( new DWord( "dwFileOS" ) );
+ addMember( new DWord( "dwFileType" ) );
+ addMember( new DWord( "dwFileSubtype" ) );
+ addMember( new DWord( "dwFileDateMS" ) );
+ addMember( new DWord( "dwFileDateLS" ) );
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/vi/StringFileInfo.java b/tools/launcher-generator/src/com/pme/exe/res/vi/StringFileInfo.java
new file mode 100644
index 000000000000..2133db8c9b34
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/vi/StringFileInfo.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res.vi;
+
+import com.pme.exe.Bin;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+/**
+ * Date: May 10, 2006
+ * Time: 8:01:15 PM
+ */
+public class StringFileInfo extends Bin.Structure {
+ public StringFileInfo() {
+ super("StringFileInfo");
+ addMember( new Word( "wLength" ) );
+ addMember( new Word( "wValueLength" ) );
+ addMember( new Word( "wType" ) );
+ addMember( new Bytes( "Bytes", 30 ) );
+ }
+ public void readWithPadding( DataInput stream, long offset ) throws IOException {
+ read( stream );
+ StringTableReader stringTableReader = new StringTableReader();
+ stringTableReader.readWithPadding( stream, offset + sizeInBytes() );
+ addMember( stringTableReader );
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/vi/StringTableEntry.java b/tools/launcher-generator/src/com/pme/exe/res/vi/StringTableEntry.java
new file mode 100644
index 000000000000..03ed67071e8d
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/vi/StringTableEntry.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res.vi;
+
+import com.pme.exe.Bin;
+
+import java.io.*;
+import java.util.ArrayList;
+
+/**
+ * Date: May 10, 2006
+ * Time: 8:26:03 PM
+ */
+public class StringTableEntry extends Bin.Structure {
+ public StringTableEntry(String key) {
+ super(key);
+ addMember(new Word("wLength"));
+ addMember(new Word("wValueLength"));
+ addMember(new Word("wType"));
+ addMember(new Bytes("key", key.length() * 2));
+ }
+
+ public void readWithPadding(DataInput stream, long offset) throws IOException {
+ read(stream);
+ long off = offset + sizeInBytes();
+ Bytes padding = new Bytes("Padding", off % 8);
+ padding.read(stream);
+ addMember(padding);
+ ArrayList list = new ArrayList();
+ for(int i = 0;;++i){
+ Word word = new Word( "" + i );
+ word.read( stream );
+ list.add( word );
+ if ( word.getValue() == 0 ) break;
+ }
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(list.size() * 2);
+ DataOutputStream bytesStream = new DataOutputStream( byteArrayOutputStream );
+ for (int i = 0; i < list.size(); ++i) {
+ Word word = (Word)list.get(i);
+ word.write( bytesStream );
+ }
+ bytesStream.close();
+
+ Txt txt = new Txt("Value", byteArrayOutputStream.toByteArray());
+ System.out.println( txt.getText() );
+ addMember( txt );
+
+ offset += sizeInBytes();
+
+ System.out.println( "" + offset % 8 );
+ System.out.println( "" + offset % 4 );
+ System.out.println( "" + offset % 16 );
+ long r = offset % 8;
+ if ( r > 0 ){
+ Bytes padding2 = new Bytes( "Padding2", r );
+ padding2.read( stream );
+ addMember( padding2 );
+ }
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/vi/StringTableReader.java b/tools/launcher-generator/src/com/pme/exe/res/vi/StringTableReader.java
new file mode 100644
index 000000000000..360f19bdfe93
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/vi/StringTableReader.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res.vi;
+
+import com.pme.exe.Bin;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+/**
+ * Date: May 10, 2006
+ * Time: 8:09:42 PM
+ */
+public class StringTableReader extends Bin.Structure{
+
+ public StringTableReader() {
+ super("StringTable");
+ addMember( new Word( "wLength" ) );
+ addMember( new Word( "wValueLength" ) );
+ addMember( new Word( "wType" ) );
+ addMember( new Bytes( "Bytes", 18 ) );
+ }
+ public void readWithPadding( DataInput stream, long offset ) throws IOException {
+ read(stream);
+ StringTableEntry stringTableEntry = new StringTableEntry("CompanyName");
+ stringTableEntry.readWithPadding( stream, offset + sizeInBytes() );
+ addMember( stringTableEntry );
+
+ StringTableEntry desc = new StringTableEntry("FileDescription");
+ desc.readWithPadding( stream, offset + sizeInBytes() + stringTableEntry.sizeInBytes() );
+ addMember( desc );
+
+ StringTableEntry fileVersion = new StringTableEntry("FileVersion");
+ fileVersion.readWithPadding( stream, offset + sizeInBytes() + stringTableEntry.sizeInBytes() + desc.sizeInBytes() );
+ addMember( fileVersion );
+
+ StringTableEntry internalName = new StringTableEntry("InternalName");
+ internalName.readWithPadding( stream, offset + sizeInBytes() + stringTableEntry.sizeInBytes() + desc.sizeInBytes() + fileVersion.sizeInBytes() );
+ addMember( internalName );
+
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/exe/res/vi/VersionInfoReader.java b/tools/launcher-generator/src/com/pme/exe/res/vi/VersionInfoReader.java
new file mode 100644
index 000000000000..219c7e562911
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/exe/res/vi/VersionInfoReader.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.exe.res.vi;
+
+import com.pme.exe.Bin;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+/**
+ * Date: May 10, 2006
+ * Time: 1:33:34 PM
+ */
+public class VersionInfoReader extends Bin.Structure {
+ public VersionInfoReader() {
+ super("VersionInfo");
+ addMember( new Word("wLength") );
+ addMember( new Bytes( "Bytes", 38 ) );
+ addMember( new FixedFileInfo() );
+ }
+
+ public void read(DataInput stream) throws IOException {
+ super.read(stream);
+ StringFileInfo stringFileInfo = new StringFileInfo();
+ stringFileInfo.readWithPadding( stream, sizeInBytes() );
+ addMember( stringFileInfo );
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/launcher/LauncherGenerator.java b/tools/launcher-generator/src/com/pme/launcher/LauncherGenerator.java
new file mode 100644
index 000000000000..fe1da5c71068
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/launcher/LauncherGenerator.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.launcher;
+
+import com.pme.exe.ExeReader;
+import com.pme.exe.SectionReader;
+import com.pme.exe.Bin;
+import com.pme.exe.res.ResourceSectionReader;
+import com.pme.exe.res.DirectoryEntry;
+import com.pme.exe.res.RawResource;
+import com.pme.exe.res.StringTable;
+import com.pme.exe.res.bmp.PictureResourceInjector;
+import com.pme.exe.res.icon.IconResourceInjector;
+import com.pme.exe.res.vi.VersionInfoReader;
+
+import java.io.*;
+
+/**
+ * Date: May 6, 2006
+ * Time: 10:43:01 AM
+ */
+public class LauncherGenerator {
+ private File myTemplate;
+ private File myIcon;
+ private File myBmp;
+ private File myExePath;
+ private int mySplashTimeout = 3;
+ private String myJreBundlePath;
+ private String myVmParameters;
+ private String myStartJar;
+ private String myWorkDir;
+ private String myJavaVersion;
+ private boolean mySearchJdkOnly = false;
+
+ public LauncherGenerator(File template, File exePath) {
+ myTemplate = template;
+ myExePath = exePath;
+ }
+
+ public void setWorkDir(String workDir) {
+ myWorkDir = workDir;
+ }
+
+ public void setSplashTimeout(int splashTimeout) {
+ mySplashTimeout = splashTimeout;
+ }
+
+ public void setJreBundlePath(String jreBundlePath) {
+ myJreBundlePath = jreBundlePath;
+ }
+
+ public void setVmParameters(String vmParameters) {
+ myVmParameters = vmParameters;
+ }
+
+ public void setStartJar(String startJar) {
+ myStartJar = startJar;
+ }
+
+ public void setIcon(File icon) {
+ myIcon = icon;
+ }
+
+ public void setBmp(File bmp) {
+ myBmp = bmp;
+ }
+
+ public void generate() throws IOException {
+ ExeReader reader = new ExeReader(myTemplate.getName());
+ RandomAccessFile stream = new RandomAccessFile(myTemplate, "r");
+ reader.read(stream);
+ stream.close();
+ SectionReader sectionReader = reader.getSectionReader(".rsrc");
+ ResourceSectionReader resourceReader = (ResourceSectionReader) sectionReader.getMember(".rsrc");
+ DirectoryEntry root = resourceReader.getRoot();
+ DirectoryEntry subDir = root.findSubDir("IRD6");
+ DirectoryEntry ird7 = subDir.findSubDir("IRD7");
+
+ RawResource rawResource = ird7.getRawResource(0);
+ Bin.Bytes bytes = rawResource.getBytes();
+ StringTable srtingTable = new StringTable(bytes.getBytes());
+
+ if (myBmp != null) {
+ srtingTable.setString(0, "splash"); // show splash
+ }
+ srtingTable.setString(1, "alive"); // stay alive
+ srtingTable.setString(2, "" + mySplashTimeout); // splash timeout
+ if (myJreBundlePath != null) {
+ srtingTable.setString(3, myJreBundlePath); // jre bundled path
+ }
+ if (myVmParameters != null) {
+ srtingTable.setString(4, myVmParameters); // PROP_VM_PARAMETERS
+ }
+ if (myStartJar != null) {
+ srtingTable.setString(5, myStartJar); // PROP_START_JAR
+ }
+ srtingTable.setString(6, "waitForWindow"); // PROP_WAIT_FOR_WINDOW
+
+ if (myWorkDir != null) {
+ srtingTable.setString(7, myWorkDir); // PROP_WORK_DIR
+ }
+
+ if (myJavaVersion != null) {
+ StringBuffer buffer = new StringBuffer( myJavaVersion.length() );
+ for( int i = 0; i < myJavaVersion.length(); ++i){
+ char ch = myJavaVersion.charAt( i );
+ if ( Character.isDigit( ch ) || ch == '.' ){
+ buffer.append( ch );
+ }
+ }
+ srtingTable.setString(8, buffer.toString()); // PROP_JAVA_VERSION
+ }
+ if (mySearchJdkOnly) {
+ srtingTable.setString(9, "SearchJdkOnly"); // PROP_SEARCH_JDK_ONLY
+ }
+
+ byte[] a = srtingTable.getBytes();
+ rawResource.setBytes(a);
+
+ if (myIcon != null) {
+ IconResourceInjector iconInjector = new IconResourceInjector();
+ iconInjector.injectIcon(myIcon, root, "IRD101");
+ }
+
+ if (myBmp != null) {
+ PictureResourceInjector bmpInjector = new PictureResourceInjector();
+ bmpInjector.inject(myBmp, root, "IRD104");
+ }
+
+
+
+ DirectoryEntry viDir = root.findSubDir("IRD16").findSubDir( "IRD1" );
+ Bin.Bytes viBytes = viDir.getRawResource( 0 ).getBytes();
+ ByteArrayInputStream bytesStream = new ByteArrayInputStream(viBytes.getBytes());
+
+ VersionInfoReader viReader = new VersionInfoReader();
+ viReader.read(new DataInputStream(bytesStream));
+
+ reader.resetOffsets(0);
+
+ myExePath.getParentFile().mkdirs();
+ myExePath.createNewFile();
+ RandomAccessFile exeStream = new RandomAccessFile(myExePath, "rw");
+ reader.write(exeStream);
+ exeStream.close();
+ }
+
+ public void setJavaVersion(String javaVersion) {
+ myJavaVersion = javaVersion;
+ }
+
+ public void setSearchJdkOnly(boolean searchJdkOnly) {
+ mySearchJdkOnly = searchJdkOnly;
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/util/AttributeInfo.java b/tools/launcher-generator/src/com/pme/util/AttributeInfo.java
new file mode 100644
index 000000000000..b6706e975fac
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/util/AttributeInfo.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.util;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InvalidClassException;
+
+public class AttributeInfo {
+ private ConstantPoolInfo myName;
+ private byte myData[];
+
+ public ConstantPoolInfo getName() {
+ return myName;
+ }
+
+ public byte[] getData() {
+ return myData;
+ }
+
+ public void read(DataInputStream stream, ConstantPoolInfo pool[]) throws IOException {
+ myName = pool[stream.readShort()];
+ int len = stream.readInt();
+ myData = new byte[len];
+ len = stream.read(myData);
+ if (len != myData.length){
+ throw new InvalidClassException( "Cannot read content for attribute: " + myName.getStrValue() );
+ }
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/util/BitsUtil.java b/tools/launcher-generator/src/com/pme/util/BitsUtil.java
new file mode 100644
index 000000000000..73ebf7548252
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/util/BitsUtil.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.util;
+
+/**
+ * Date: Mar 30, 2006
+ * Time: 7:10:10 PM
+ */
+public class BitsUtil {
+ public static int revertBytesOfShort( short shortValue ){
+ return ((shortValue << 8) & 0xff00) + ((shortValue >> 8) & 0xff);
+ }
+ public static long revertBytesOfInt( int intValue ){
+ long result = (intValue & 0x000000ff);
+ result <<= 24;
+ result += ((intValue & 0x0000ff00) << 8) + ((intValue & 0x00ff0000) >> 8) + ((intValue >> 24) & 0xff);
+ return result;
+ }
+ public static int unsignedByte( byte byteValue ){
+ int result = byteValue;
+ return (result & 0xff);
+ }
+ private static String toHexString( long value, int size ){
+ String strValue = Long.toHexString( value );
+ if ( strValue.length() > size ){
+ strValue = strValue.substring( strValue.length() - size );
+ }
+ StringBuffer buffer = new StringBuffer( strValue.length() + 1 + size );
+ buffer.append( "0x" );
+ int dif = size - strValue.length();
+ for ( int i = 0; i < dif; ++i ){
+ buffer.append( "0" );
+ }
+ buffer.append( strValue );
+ return buffer.toString();
+ }
+
+ public static String intToHexString( long value ){
+ return toHexString( value, 8 );
+ }
+ public static String shortToHexString( int value ){
+ return toHexString( value, 4 );
+ }
+ public static String byteToHexString( int value ){
+ return toHexString( value, 2 );
+ }
+
+}
diff --git a/tools/launcher-generator/src/com/pme/util/ClassFile.java b/tools/launcher-generator/src/com/pme/util/ClassFile.java
new file mode 100644
index 000000000000..dadba339a0f0
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/util/ClassFile.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.util;
+
+import java.io.*;
+
+public class ClassFile {
+ private int myMagic;
+ private short myMajorVersion;
+ private short myMinorVersion;
+ private ConstantPoolInfo myConstantPool[];
+ private short myAccessFlags;
+ private ConstantPoolInfo myThisClass;
+ private ConstantPoolInfo mySuperClass;
+ private ConstantPoolInfo myInterfaces[];
+ private FieldInfo myFields[];
+ private MethodInfo myMethods[];
+ private AttributeInfo myAttributes[];
+
+ private void readConstantPool(DataInputStream stream) throws IOException {
+ myConstantPool = new ConstantPoolInfo[stream.readShort()];
+ myConstantPool[0] = new ConstantPoolInfo();
+ for (int i = 1; i < myConstantPool.length; i++) {
+ myConstantPool[i] = new ConstantPoolInfo();
+ myConstantPool[i].read(stream);
+ // These two types take up "two" spots in the table
+ if ((myConstantPool[i].getType() == ConstantPoolInfo.LONG) ||
+ (myConstantPool[i].getType() == ConstantPoolInfo.DOUBLE))
+ i++;
+ }
+ }
+
+ private void readInterfaces(DataInputStream stream) throws IOException {
+ int count = stream.readShort();
+ if (count != 0) {
+ myInterfaces = new ConstantPoolInfo[count];
+ for (int i = 0; i < count; i++) {
+ int index = stream.readShort();
+ if ((index < 1) || (index > myConstantPool.length - 1))
+ throw new InvalidClassException("Wrong count for constant pool");
+ myInterfaces[i] = myConstantPool[index];
+ }
+ }
+ }
+
+ private void readFields(DataInputStream stream) throws IOException {
+ int count = stream.readShort();
+ if (count != 0) {
+ myFields = new FieldInfo[count];
+ for (int i = 0; i < count; i++) {
+ myFields[i] = new FieldInfo();
+ myFields[i].read(stream, myConstantPool);
+ }
+ }
+ }
+
+ private void readMethods(DataInputStream stream) throws IOException {
+ int count = stream.readShort();
+ if (count != 0) {
+ myMethods = new MethodInfo[count];
+ for (int i = 0; i < count; i++) {
+ myMethods[i] = new MethodInfo();
+ myMethods[i].read(stream, myConstantPool);
+ }
+ }
+ }
+
+ private void readAttributes(DataInputStream stream) throws IOException {
+ int count = stream.readShort();
+ if (count != 0) {
+ myAttributes = new AttributeInfo[count];
+ for (int i = 0; i < count; i++) {
+ myAttributes[i] = new AttributeInfo();
+ myAttributes[i].read(stream, myConstantPool);
+ }
+ }
+ }
+
+ public static String readClassName(File file) throws IOException {
+ FileInputStream stream = new FileInputStream(file);
+ ClassFile classFile = new ClassFile();
+ try {
+ classFile.read(stream);
+ return classFile.getSourceName();
+ } finally{
+ stream.close();
+ }
+ }
+
+ public void read(InputStream in) throws IOException {
+ DataInputStream stream = new DataInputStream(in);
+ myMagic = stream.readInt();
+ if (myMagic != 0xCAFEBABE) {
+ throw new InvalidClassException("There is no magic number");
+ }
+
+ myMajorVersion = stream.readShort();
+ myMinorVersion = stream.readShort();
+
+ readConstantPool(stream);
+ myAccessFlags = stream.readShort();
+ myThisClass = myConstantPool[stream.readShort()];
+ mySuperClass = myConstantPool[stream.readShort()];
+ readInterfaces(stream);
+ readFields(stream);
+ readMethods(stream);
+ readAttributes(stream);
+ }
+
+ public String getSourceName() {
+ if (myAttributes != null) {
+ for (int i = 0; i < myAttributes.length; i++) {
+ String attrName = myAttributes[i].getName().getStrValue();
+ if ("SourceFile".compareTo(attrName) == 0) {
+ try {
+ DataInputStream dis = new DataInputStream(new ByteArrayInputStream(myAttributes[i].getData()));
+ ConstantPoolInfo cpi = myConstantPool[dis.readShort()];
+ return cpi.getStrValue();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/util/ConstantPoolInfo.java b/tools/launcher-generator/src/com/pme/util/ConstantPoolInfo.java
new file mode 100644
index 000000000000..fa28fa05e34f
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/util/ConstantPoolInfo.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.util;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+public class ConstantPoolInfo {
+ private int myType = -1;
+ private short myIindex1 = -1;
+ private short myIndex2 = -1;
+ private String myStrValue;
+ private int myIntValue;
+ private long myLongValue;
+ private float myFloatValue;
+ private double myDoubleValue;
+
+ public static final int CLASS = 7;
+ public static final int FIELDREF = 9;
+ public static final int METHODREF = 10;
+ public static final int STRING = 8;
+ public static final int INTEGER = 3;
+ public static final int FLOAT = 4;
+ public static final int LONG = 5;
+ public static final int DOUBLE = 6;
+ public static final int INTERFACE = 11;
+ public static final int NAMEANDTYPE = 12;
+ public static final int ASCIZ = 1;
+ public static final int UNICODE = 2;
+
+ public String getStrValue() {
+ return myStrValue;
+ }
+
+ public int getType() {
+ return myType;
+ }
+
+ public void read(DataInputStream stream)throws IOException {
+ myType = stream.readByte();
+ switch (myType) {
+ case CLASS:
+ myIindex1 = stream.readShort();
+ break;
+ case FIELDREF:
+ myIindex1 = stream.readShort();
+ myIndex2 = stream.readShort();
+ break;
+ case METHODREF:
+ myIindex1 = stream.readShort();
+ myIndex2 = stream.readShort();
+ break;
+ case INTERFACE:
+ myIindex1 = stream.readShort();
+ myIndex2 = stream.readShort();
+ break;
+ case NAMEANDTYPE:
+ myIindex1 = stream.readShort();
+ myIndex2 = stream.readShort();
+ break;
+ case STRING:
+ myIindex1 = stream.readShort();
+ break;
+ case INTEGER:
+ myIntValue = stream.readInt();
+ break;
+ case FLOAT:
+ myFloatValue = stream.readFloat();
+ break;
+ case LONG:
+ myLongValue = stream.readLong();
+ break;
+ case DOUBLE:
+ myDoubleValue = stream.readDouble();
+ break;
+ case ASCIZ:
+ case UNICODE:
+ StringBuffer buff = new StringBuffer();
+ int len = stream.readShort();
+ while (len > 0) {
+ char c = (char) (stream.readByte());
+ buff.append(c);
+ len--;
+ }
+ myStrValue = buff.toString();
+ break;
+ }
+ }
+
+}
diff --git a/tools/launcher-generator/src/com/pme/util/FieldInfo.java b/tools/launcher-generator/src/com/pme/util/FieldInfo.java
new file mode 100644
index 000000000000..64703311ec6a
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/util/FieldInfo.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.util;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+public class FieldInfo {
+ private short myAccessFlags;
+ private ConstantPoolInfo myName;
+ private ConstantPoolInfo mySignature;
+ private AttributeInfo myAttributes[];
+
+ public short getAccessFlags() {
+ return myAccessFlags;
+ }
+
+ public ConstantPoolInfo getName() {
+ return myName;
+ }
+
+ public ConstantPoolInfo getSignature() {
+ return mySignature;
+ }
+
+ public AttributeInfo[] getAttributes() {
+ return myAttributes;
+ }
+
+ public void read(DataInputStream stream, ConstantPoolInfo pool[]) throws IOException {
+ myAccessFlags = stream.readShort();
+ myName = pool[stream.readShort()];
+ mySignature = pool[stream.readShort()];
+ int count = stream.readShort();
+ if (count != 0) {
+ myAttributes = new AttributeInfo[count];
+ for (int i = 0; i < count; i++) {
+ myAttributes[i] = new AttributeInfo();
+ myAttributes[i].read(stream, pool);
+ }
+ }
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/util/MethodInfo.java b/tools/launcher-generator/src/com/pme/util/MethodInfo.java
new file mode 100644
index 000000000000..1fea3e92ba9b
--- /dev/null
+++ b/tools/launcher-generator/src/com/pme/util/MethodInfo.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2006 ProductiveMe Inc.
+ * Copyright 2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pme.util;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+public class MethodInfo {
+ private short myAccessFlags;
+ private ConstantPoolInfo myName;
+ private ConstantPoolInfo mySignature;
+ private AttributeInfo myAttributes[];
+
+ public short getAccessFlags() {
+ return myAccessFlags;
+ }
+
+ public ConstantPoolInfo getName() {
+ return myName;
+ }
+
+ public ConstantPoolInfo getSignature() {
+ return mySignature;
+ }
+
+ public AttributeInfo[] getAttributes() {
+ return myAttributes;
+ }
+
+ public void read(DataInputStream stream, ConstantPoolInfo pool[]) throws IOException {
+ myAccessFlags = stream.readShort();
+ myName = pool[stream.readShort()];
+ mySignature = pool[stream.readShort()];
+ int count = stream.readShort();
+ if (count != 0) {
+ myAttributes = new AttributeInfo[count];
+ for (int i = 0; i < count; i++) {
+ myAttributes[i] = new AttributeInfo(); // "code"
+ myAttributes[i].read(stream, pool);
+ }
+ }
+ }
+}