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