blob: 673bc5afc2c1bb58e0552a231e67822b61e8b99b [file] [log] [blame]
/*
* 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.google.common.io.Files;
import com.google.common.io.InputSupplier;
import com.pme.exe.ExeFormat;
import com.pme.exe.ExeReader;
import com.pme.exe.SectionReader;
import com.pme.exe.res.DirectoryEntry;
import com.pme.exe.res.RawResource;
import com.pme.exe.res.ResourceSectionReader;
import com.pme.exe.res.StringTableDirectory;
import com.pme.exe.res.icon.IconResourceInjector;
import com.pme.exe.res.vi.StringTable;
import com.pme.exe.res.vi.VersionInfo;
import com.pme.util.OffsetTrackingInputStream;
import java.io.*;
/**
* Date: May 6, 2006
* Time: 10:43:01 AM
*/
public class LauncherGenerator {
private File myTemplate;
private File myExePath;
private StringTableDirectory myStringTableDirectory;
private DirectoryEntry myRoot;
private ExeReader myReader;
private VersionInfo myVersionInfo;
public LauncherGenerator(File template, File exePath) {
myTemplate = template;
myExePath = exePath;
}
public void load() throws IOException {
RandomAccessFile stream = new RandomAccessFile(myTemplate, "r");
ExeReader formatReader = new ExeReader(myTemplate.getName(), ExeFormat.UNKNOWN);
formatReader.read(stream);
stream.seek(0L);
myReader = new ExeReader(myTemplate.getName(), formatReader.getExeFormat());
myReader.read(stream);
stream.close();
SectionReader sectionReader = myReader.getSectionReader(".rsrc");
ResourceSectionReader resourceReader = (ResourceSectionReader) sectionReader.getMember(".rsrc");
myRoot = resourceReader.getRoot();
DirectoryEntry subDir = myRoot.findSubDir("IRD6");
myStringTableDirectory = new StringTableDirectory(subDir);
RawResource versionInfoResource = getVersionInfoResource();
ByteArrayInputStream bytesStream = new ByteArrayInputStream(versionInfoResource.getBytes().getBytes());
myVersionInfo = new VersionInfo();
myVersionInfo.read(new OffsetTrackingInputStream(new DataInputStream(bytesStream)));
}
private RawResource getVersionInfoResource() {
DirectoryEntry viDir = myRoot.findSubDir("IRD16").findSubDir( "IRD1" );
return viDir.getRawResource(0);
}
private void saveVersionInfo() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
myVersionInfo.resetOffsets(0);
myVersionInfo.write(new DataOutputStream(baos));
getVersionInfoResource().setBytes(baos.toByteArray());
}
public void generate() throws IOException {
myStringTableDirectory.save();
saveVersionInfo();
myReader.resetOffsets(0);
myExePath.getParentFile().mkdirs();
myExePath.createNewFile();
RandomAccessFile exeStream = new RandomAccessFile(myExePath, "rw");
myReader.write(exeStream);
exeStream.close();
// verifyVersionInfo();
}
private void verifyVersionInfo() throws IOException {
String versionInfoPath = myExePath + ".version";
RandomAccessFile versionInfoStream = new RandomAccessFile(versionInfoPath, "rw");
try {
myVersionInfo.resetOffsets(0);
myVersionInfo.write(versionInfoStream);
}
finally {
versionInfoStream.close();
}
VersionInfo copy = new VersionInfo();
copy.read(new OffsetTrackingInputStream(new DataInputStream(new FileInputStream(versionInfoPath))));
}
public void setResourceString(int id, String value) {
myStringTableDirectory.setString(id, value);
}
public void setVersionInfoString(String key, String value) {
StringTable stringTable = myVersionInfo.getStringFileInfo().getFirstStringTable();
if (stringTable != null) {
stringTable.setStringValue(key, value);
}
}
public void injectBitmap(int id, byte[] bitmapFileData) {
DirectoryEntry subDirBmp = myRoot.findSubDir("IRD2").findSubDir("IRD" + id);
RawResource bmpRes = subDirBmp.getRawResource(0);
// strip off BITMAPFILEHEADER
byte[] bitmapResourceData = new byte[bitmapFileData.length-14];
System.arraycopy(bitmapFileData, 14, bitmapResourceData, 0, bitmapResourceData.length);
bmpRes.setBytes(bitmapResourceData);
}
public void injectIcon(int id, final InputStream iconStream) throws IOException {
File f = File.createTempFile("launcher", "ico");
Files.copy(new InputSupplier<InputStream>() {
@Override
public InputStream getInput() throws IOException {
return iconStream;
}
}, f);
IconResourceInjector iconInjector = new IconResourceInjector();
iconInjector.injectIcon(f, myRoot, "IRD" + id);
}
public void setVersionNumber(int majorVersion, int minorVersion, int bugfixVersion) {
int mostSignificantVersion = majorVersion << 16 | minorVersion;
int leastSignificantVersion = bugfixVersion << 16;
myVersionInfo.getFixedFileInfo().setFileVersion(mostSignificantVersion, leastSignificantVersion);
myVersionInfo.getFixedFileInfo().setProductVersion(mostSignificantVersion, leastSignificantVersion);
}
}