Skip to content
Snippets Groups Projects
Commit e6fbaf24 authored by Dmitry Shamrikov's avatar Dmitry Shamrikov
Browse files

LinkInfo reading/writing

parent ccc5b706
No related branches found
No related tags found
No related merge requests found
Showing
with 742 additions and 39 deletions
......@@ -44,6 +44,13 @@ public class ByteReader extends InputStream {
return pos;
}
public boolean seek(int n) throws IOException {
if (n == 0) return false;
for (int i=0; i<n; i++)
read();
return true;
}
@Override
public int read() throws IOException {
pos++;
......@@ -133,6 +140,34 @@ public class ByteReader extends InputStream {
else
return b7 | (b6 << 8) | (b5 << 16) | (b4 << 24) | (b3 << 32) | (b2 << 40) | (b1 << 48) | (b0 << 56);
}
public String readString(int start, int size) throws IOException {
int sz = size + start - getPosition();
if (sz == 0) return null;
byte[] buf = new byte[sz];
int i = 0;
for (;; i++) {
int b = read();
if (b == 0) break;
buf[i] = (byte)b;
}
if (i == 0) return null;
return new String(buf, 0, i);
}
public String readUnicodeString(int start, int size) throws IOException {
int sz = (size + start - getPosition())>>1;
if (sz == 0) return null;
char[] buf = new char[sz];
int i = 0;
for (;; i++) {
char c = (char)read2bytes();
if (c == 0) break;
buf[i] = c;
}
if (i == 0) return null;
return new String(buf, 0, i);
}
}
enum Endianness {
......
......@@ -7,6 +7,8 @@ public class ByteWriter extends OutputStream {
private OutputStream stream;
private Endianness end = Endianness.LITTLE_ENDIAN;
private int pos = 0;
public ByteWriter(OutputStream out) {
stream = out;
......@@ -38,8 +40,13 @@ public class ByteWriter extends OutputStream {
return end == Endianness.LITTLE_ENDIAN;
}
public int getPosition() {
return pos;
}
@Override
public void write(int b) throws IOException {
pos++;
stream.write(b);
}
......@@ -137,4 +144,9 @@ public class ByteWriter extends OutputStream {
write(b7); write(b6); write(b5); write(b4); write(b3); write(b2); write(b1); write(b0);
}
}
public void writeBytes(byte[] b) throws IOException {
for (byte i : b)
write(i);
}
}
......@@ -39,12 +39,12 @@ public class Bytes {
return (Bytes.l(b7) << 56) | (Bytes.l(b6) << 48) | (Bytes.l(b5) << 40) | (Bytes.l(b4) << 32) | (Bytes.l(b3) << 24) | (Bytes.l(b2) << 16) | (Bytes.l(b1) << 8) | Bytes.l(b0);
}
static int i(byte b) {
return b & 0xff;
}
static long l(byte b) {
return b & 0xffL;
}
static int i(byte b) {
return b & 0xff;
}
}
package mslinks;
import io.ByteReader;
import io.ByteWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import mslinks.data.*;
public class LinkInfo implements Serializable {
private LinkInfoFlags lif;
private VolumeID vid;
private String localBasePath;
private CNRLink cnrlink;
private String commonPathSuffix;
public LinkInfo() {
createVolumeID();
}
public LinkInfo(ByteReader data) throws IOException, ShellLinkException {
int pos = data.getPosition();
int size = (int)data.read4bytes();
int hsize = (int)data.read4bytes();
lif = new LinkInfoFlags(data);
int vidoffset = (int)data.read4bytes();
int lbpoffset = (int)data.read4bytes();
int cnrloffset = (int)data.read4bytes();
int cpsoffset = (int)data.read4bytes();
int lbpoffset_u = 0, cpfoffset_u = 0;
if (hsize >= 0x24) {
lbpoffset_u = (int)data.read4bytes();
cpfoffset_u = (int)data.read4bytes();
}
if (lif.hasVolumeIDAndLocalBasePath()) {
data.seek(pos + vidoffset - data.getPosition());
vid = new VolumeID(data);
data.seek(pos + lbpoffset - data.getPosition());
localBasePath = data.readString(pos, size);
}
if (lif.hasCommonNetworkRelativeLinkAndPathSuffix()) {
data.seek(pos + cnrloffset - data.getPosition());
cnrlink = new CNRLink(data);
data.seek(pos + cpsoffset - data.getPosition());
commonPathSuffix = data.readString(pos, size);
}
if (lif.hasVolumeIDAndLocalBasePath() && lbpoffset_u != 0) {
data.seek(pos + lbpoffset_u - data.getPosition());
localBasePath = data.readUnicodeString(pos, size);
}
if (lif.hasCommonNetworkRelativeLinkAndPathSuffix() && cpfoffset_u != 0) {
data.seek(pos + cpfoffset_u - data.getPosition());
commonPathSuffix = data.readUnicodeString(pos, size);
}
data.seek(pos + size - data.getPosition());
}
public void serialize(ByteWriter bw) throws IOException {
int pos = bw.getPosition();
int hsize = 28;
CharsetEncoder ce = Charset.defaultCharset().newEncoder();
if (localBasePath != null && !ce.canEncode(localBasePath) || commonPathSuffix != null && !ce.canEncode(commonPathSuffix))
hsize += 8;
byte[] vid_b = null, localBasePath_b = null, cnrlink_b = null, commonPathSuffix_b = null;
if (lif.hasVolumeIDAndLocalBasePath()) {
vid_b = toByteArray(vid, bw.isLitteEndian());
localBasePath_b = localBasePath.getBytes();
commonPathSuffix_b = new byte[0];
}
if (lif.hasCommonNetworkRelativeLinkAndPathSuffix()) {
cnrlink_b = toByteArray(cnrlink, bw.isLitteEndian());
commonPathSuffix_b = commonPathSuffix.getBytes();
}
int size = hsize
+ (vid_b == null? 0 : vid_b.length)
+ (localBasePath_b == null? 0 : localBasePath_b.length + 1)
+ (cnrlink_b == null? 0 : cnrlink_b.length)
+ commonPathSuffix_b.length + 1;
if (hsize > 28) {
if (lif.hasVolumeIDAndLocalBasePath()) {
size += localBasePath.length() * 2 + 2;
size += 1;
}
if (lif.hasCommonNetworkRelativeLinkAndPathSuffix()) {
size += commonPathSuffix.length() * 2 + 2;
} else
size += 2;
}
bw.write4bytes(size);
bw.write4bytes(hsize);
lif.serialize(bw);
int off = hsize;
if (lif.hasVolumeIDAndLocalBasePath()) {
bw.write4bytes(off); // volumeid offset
off += vid_b.length;
bw.write4bytes(off); // localBasePath offset
off += localBasePath_b.length + 1;
bw.write4bytes(0); // CommonNetworkRelativeLinkOffset
bw.write4bytes(size - (hsize > 28 ? 4 : 1)); // fake commonPathSuffix offset
}
if (lif.hasCommonNetworkRelativeLinkAndPathSuffix()) {
bw.write4bytes(0); // volumeid offset
bw.write4bytes(0); // localBasePath offset
bw.write4bytes(off); // CommonNetworkRelativeLink offset
off += cnrlink_b.length;
bw.write4bytes(off); // commonPathSuffix
off += commonPathSuffix_b.length + 1;
}
if (hsize > 28) {
if (lif.hasVolumeIDAndLocalBasePath()) {
bw.write4bytes(off); // LocalBasePathOffsetUnicode
off += localBasePath.length() * 2 + 2;
bw.write4bytes(size - 2); // fake CommonPathSuffixUnicode offset
} else {
bw.write4bytes(0);
bw.write4bytes(off); // CommonPathSuffixUnicode offset
off += commonPathSuffix.length() * 2 + 2;
}
}
if (lif.hasVolumeIDAndLocalBasePath()) {
bw.writeBytes(vid_b);
bw.writeBytes(localBasePath_b);
bw.write(0);
}
if (lif.hasCommonNetworkRelativeLinkAndPathSuffix()) {
bw.writeBytes(cnrlink_b);
bw.writeBytes(commonPathSuffix_b);
bw.write(0);
}
if (hsize > 28) {
if (lif.hasVolumeIDAndLocalBasePath()) {
for (int i=0; i<localBasePath.length(); i++)
bw.write2bytes(localBasePath.charAt(i));
bw.write2bytes(0);
}
if (lif.hasCommonNetworkRelativeLinkAndPathSuffix()) {
for (int i=0; i<commonPathSuffix.length(); i++)
bw.write2bytes(commonPathSuffix.charAt(i));
bw.write2bytes(0);
}
}
while (bw.getPosition() < pos + size)
bw.write(0);
}
private byte[] toByteArray(Serializable o, boolean le) throws IOException {
ByteArrayOutputStream arr = new ByteArrayOutputStream();
ByteWriter bt = new ByteWriter(arr);
if (le) bt.setLittleEndian();
else bt.setBigEndian();
o.serialize(bt);
return arr.toByteArray();
}
public VolumeID getVolumeID() { return vid; }
/**
* Creates VolumeID and LocalBasePath that is empty string, clears CommonNetworkRelativeLink and CommonPathSuffix
*/
public VolumeID createVolumeID() {
cnrlink = null;
commonPathSuffix = null;
lif.clearCommonNetworkRelativeLinkAndPathSuffix();
vid = new VolumeID();
localBasePath = "";
lif.setVolumeIDAndLocalBasePath();
return vid;
}
public String getLocalBasePath() { return localBasePath; }
/**
* Set LocalBasePath and creates new VolumeID (if it not exists), clears CommonNetworkRelativeLink and CommonPathSuffix.
* If s is null takes no effect
*/
public void setLocalBasePath(String s) {
if (s == null) return;
localBasePath = s;
if (vid == null) vid = new VolumeID();
lif.setVolumeIDAndLocalBasePath();
cnrlink = null;
commonPathSuffix = null;
lif.clearCommonNetworkRelativeLinkAndPathSuffix();
}
public CNRLink getCommonNetworkRelativeLink() { return cnrlink; }
/**
* Creates CommonNetworkRelativeLink and CommonPathSuffix that is empty string, clears VolumeID and LocalBasePath
*/
public CNRLink createCommonNetworkRelativeLink() {
cnrlink = new CNRLink();
commonPathSuffix = "";
lif.setCommonNetworkRelativeLinkAndPathSuffix();
vid = null;
localBasePath = null;
lif.clearVolumeIDAndLocalBasePath();
return cnrlink;
}
public String getCommonPathSuffix() { return commonPathSuffix; }
/**
* Set CommonPathSuffix and creates new CommonNetworkRelativeLink (if it not exists), clears VolumeID and LocalBasePath.
* If s is null takes no effect
*/
public void setCommonPathSuffix(String s) {
if (s == null) return;
localBasePath = null;
vid = null;
lif.clearVolumeIDAndLocalBasePath();
commonPathSuffix = s;
if (cnrlink == null) cnrlink = new CNRLink();
lif.setCommonNetworkRelativeLinkAndPathSuffix();
}
}
......@@ -6,13 +6,13 @@ import io.ByteWriter;
import java.io.IOException;
import java.util.LinkedList;
public class LinkTargetIDList {
public class LinkTargetIDList implements Serializable {
private LinkedList<byte[]> list = new LinkedList<>();
public LinkTargetIDList(ByteReader data) throws IOException, ShellLinkException {
int size = (int)data.read2bytes();
int check = data.getPosition();
int pos = data.getPosition();
int s = (int)data.read2bytes();
while (s != 0) {
......@@ -24,8 +24,8 @@ public class LinkTargetIDList {
s = (int)data.read2bytes();
}
check = data.getPosition() - check;
if (check != size)
pos = data.getPosition() - pos;
if (pos != size)
throw new ShellLinkException();
}
......
......@@ -9,8 +9,12 @@ import mslinks.data.Filetime;
public class Main {
public static void main(String[] args) throws IOException, ShellLinkException {
ShellLink link = new ShellLink("testlink.lnk");
Filetime ft = link.getWriteTime();
//for (String i : Charset.availableCharsets().keySet())
// System.out.println(i);
//if (true) return;
ShellLink link = new ShellLink("testlink3.lnk");
Filetime ft = link.getHeader().getWriteTime();
System.out.println(String.format("%d:%d:%d %d.%d.%d", ft.get(GregorianCalendar.HOUR_OF_DAY), ft.get(GregorianCalendar.MINUTE), ft.get(GregorianCalendar.SECOND),
ft.get(GregorianCalendar.DAY_OF_MONTH), ft.get(GregorianCalendar.MONTH) + 1, ft.get(GregorianCalendar.YEAR)));
......
package mslinks;
import java.io.IOException;
import io.ByteWriter;
public interface Serializable {
void serialize(ByteWriter bw) throws IOException;
}
......@@ -8,16 +8,12 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import mslinks.data.FileAttributesFlags;
import mslinks.data.Filetime;
import mslinks.data.HotKeyFlags;
import mslinks.data.LinkFlags;
public class ShellLink {
private boolean le;
private ShellLinkHeader header;
private LinkTargetIDList idlist;
private LinkInfo info;
public ShellLink(String file) throws IOException, ShellLinkException {
this(Paths.get(file));
......@@ -39,6 +35,8 @@ public class ShellLink {
header = new ShellLinkHeader(data);
if (header.getLinkFlags().hasLinkTargetIDList())
idlist = new LinkTargetIDList(data);
if (header.getLinkFlags().hasLinkInfo())
info = new LinkInfo(data);
le = data.isLitteEndian();
}
......@@ -47,23 +45,17 @@ public class ShellLink {
if (le) bw.setLittleEndian();
else bw.setBigEndian();
header.serialize(bw);
idlist.serialize(bw);
if (header.getLinkFlags().hasLinkTargetIDList())
idlist.serialize(bw);
if (header.getLinkFlags().hasLinkInfo())
info.serialize(bw);
}
/* to header */
public LinkFlags getLinkFlags() { return header.getLinkFlags(); }
public FileAttributesFlags getFileAttributesFlags() { return header.getFileAttributesFlags(); }
public Filetime getCreationTime() { return header.getCreationTime(); }
public Filetime getAccessTime() { return header.getAccessTime(); }
public Filetime getWriteTime() { return header.getWriteTime(); }
public HotKeyFlags getHotKeyFlags() { return header.getHotKeyFlags(); }
public int getFileSize() { return header.getFileSize(); }
public void setFileSize(long n) { header.setFileSize(n); }
public ShellLinkHeader getHeader() { return header; }
public int getIconIndex() { return header.getIconIndex(); }
public void setIconIndex(int n) { header.setIconIndex(n); }
public int getShowCommand() { return header.getShowCommand(); }
public void setShowCommand(int n) throws ShellLinkException { header.setShowCommand(n); }
public LinkInfo getLinkInfo() { return info; }
public void createLinkInfo() {
info = new LinkInfo();
header.getLinkFlags().setHasLinkInfo();
}
}
......@@ -12,7 +12,7 @@ import mslinks.data.GUID;
import mslinks.data.HotKeyFlags;
import mslinks.data.LinkFlags;
public class ShellLinkHeader {
public class ShellLinkHeader implements Serializable {
private static byte b(int i) { return (byte)i; }
private static int headerSize = 0x0000004C;
private static GUID clsid = new GUID(new byte[] {
......@@ -22,9 +22,9 @@ public class ShellLinkHeader {
b(0xc0), b(0x00),
b(0x00), b(0x00), b(0x00), b(0x00), b(0x00), b(0x46) });
public static int SW_SHOWNORMAL = 1;
public static int SW_SHOWMAXIMIZED = 3;
public static int SW_SHOWMINNOACTIVE = 7;
public static final int SW_SHOWNORMAL = 1;
public static final int SW_SHOWMAXIMIZED = 3;
public static final int SW_SHOWMINNOACTIVE = 7;
private LinkFlags lf;
private FileAttributesFlags faf;
......@@ -54,6 +54,8 @@ public class ShellLinkHeader {
fileSize = (int)data.read4bytes();
iconIndex = (int)data.read4bytes();
showCommand = (int)data.read4bytes();
if (showCommand != SW_SHOWNORMAL && showCommand != SW_SHOWMAXIMIZED && showCommand != SW_SHOWMINNOACTIVE)
throw new ShellLinkException();
hkf = new HotKeyFlags(data);
data.read2bytes();
data.read8bytes();
......
......@@ -5,7 +5,9 @@ import io.ByteWriter;
import java.io.IOException;
public class BitSet32 {
import mslinks.Serializable;
public class BitSet32 implements Serializable {
private int d;
public BitSet32(int n) {
......
package mslinks.data;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import mslinks.Serializable;
import mslinks.ShellLinkException;
import io.ByteReader;
import io.ByteWriter;
public class CNRLink implements Serializable {
public static final int WNNC_NET_AVID = 0x001A000;
public static final int WNNC_NET_DOCUSPACE = 0x001B000;
public static final int WNNC_NET_MANGOSOFT = 0x001C000;
public static final int WNNC_NET_SERNET = 0x001D000;
public static final int WNNC_NET_RIVERFRONT1 = 0X001E000;
public static final int WNNC_NET_RIVERFRONT2 = 0x001F000;
public static final int WNNC_NET_DECORB = 0x0020000;
public static final int WNNC_NET_PROTSTOR = 0x0021000;
public static final int WNNC_NET_FJ_REDIR = 0x0022000;
public static final int WNNC_NET_DISTINCT = 0x0023000;
public static final int WNNC_NET_TWINS = 0x0024000;
public static final int WNNC_NET_RDR2SAMPLE = 0x0025000;
public static final int WNNC_NET_CSC = 0x0026000;
public static final int WNNC_NET_3IN1 = 0x0027000;
public static final int WNNC_NET_EXTENDNET = 0x0029000;
public static final int WNNC_NET_STAC = 0x002A000;
public static final int WNNC_NET_FOXBAT = 0x002B000;
public static final int WNNC_NET_YAHOO = 0x002C000;
public static final int WNNC_NET_EXIFS = 0x002D000;
public static final int WNNC_NET_DAV = 0x002E000;
public static final int WNNC_NET_KNOWARE = 0x002F000;
public static final int WNNC_NET_OBJECT_DIRE = 0x0030000;
public static final int WNNC_NET_MASFAX = 0x0031000;
public static final int WNNC_NET_HOB_NFS = 0x0032000;
public static final int WNNC_NET_SHIVA = 0x0033000;
public static final int WNNC_NET_IBMAL = 0x0034000;
public static final int WNNC_NET_LOCK = 0x0035000;
public static final int WNNC_NET_TERMSRV = 0x0036000;
public static final int WNNC_NET_SRT = 0x0037000;
public static final int WNNC_NET_QUINCY = 0x0038000;
public static final int WNNC_NET_OPENAFS = 0x0039000;
public static final int WNNC_NET_AVID1 = 0X003A000;
public static final int WNNC_NET_DFS = 0x003B000;
public static final int WNNC_NET_KWNP = 0x003C000;
public static final int WNNC_NET_ZENWORKS = 0x003D000;
public static final int WNNC_NET_DRIVEONWEB = 0x003E000;
public static final int WNNC_NET_VMWARE = 0x003F000;
public static final int WNNC_NET_RSFX = 0x0040000;
public static final int WNNC_NET_MFILES = 0x0041000;
public static final int WNNC_NET_MS_NFS = 0x0042000;
public static final int WNNC_NET_GOOGLE = 0x0043000;
private CNRLinkFlags flags;
private int nptype;
private String netname, devname;
public CNRLink() {
netname = "";
}
public CNRLink(ByteReader data) throws ShellLinkException, IOException {
int pos = data.getPosition();
int size = (int)data.read4bytes();
if (size < 0x14)
throw new ShellLinkException();
flags = new CNRLinkFlags(data);
int nnoffset = (int)data.read4bytes();
int dnoffset = (int)data.read4bytes();
if (!flags.isValidDevice())
dnoffset = 0;
nptype = (int)data.read4bytes();
if (flags.isValidNetType())
checkNptype(nptype);
else nptype = 0;
int nnoffset_u = 0, dnoffset_u = 0;
if (nnoffset > 0x14) {
nnoffset_u = (int)data.read4bytes();
dnoffset_u = (int)data.read4bytes();
}
data.seek(pos + nnoffset - data.getPosition());
netname = data.readString( pos, size);
if (dnoffset != 0) {
data.seek(pos + dnoffset - data.getPosition());
devname = data.readString(pos, size);
}
if (nnoffset_u != 0) netname = data.readUnicodeString(pos, size);
if (dnoffset_u != 0) devname = data.readUnicodeString(pos, size);
}
private void checkNptype(int type) throws ShellLinkException {
int mod = Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL;
for (Field f : this.getClass().getFields()) {
try {
if ((f.getModifiers() & mod) == mod && type == ((Integer)f.get(null)).intValue())
return;
} catch (Exception e) {}
}
throw new ShellLinkException("incorrect network type");
}
@Override
public void serialize(ByteWriter bw) throws IOException {
int size = 20;
boolean u = false;
CharsetEncoder ce = Charset.defaultCharset().newEncoder();
u = !ce.canEncode(netname) || devname != null && !ce.canEncode(devname);
if (u) size += 8;
byte[] netname_b = null, devname_b = null;
netname_b = netname.getBytes();
if (devname != null) devname_b = devname.getBytes();
size += netname_b.length + 1;
if (devname_b != null) size += devname_b.length + 1;
if (u) {
size += netname.length() * 2 + 2;
if (devname != null) size += devname.length() * 2 + 2;
}
bw.write4bytes(size);
flags.serialize(bw);
int off = 20;
if (u) off += 8;
bw.write4bytes(off); // netname offset
off += netname_b.length + 1;
if (devname_b != null) {
bw.write4bytes(off); // devname offset
off += devname_b.length + 1;
} else bw.write4bytes(0);
bw.write4bytes(nptype);
if (u) {
bw.write4bytes(off);
off += netname.length() * 2 + 2;
if (devname != null) {
bw.write4bytes(off);
off += devname.length() * 2 + 2;
} else bw.write4bytes(0);
}
bw.writeBytes(netname_b);
bw.write(0);
if (devname_b != null) {
bw.writeBytes(devname_b);
bw.write(0);
}
if (u) {
for (int i=0; i<netname.length(); i++)
bw.write2bytes(netname.charAt(i));
bw.write2bytes(0);
if (devname != null) {
for (int i=0; i<devname.length(); i++)
bw.write2bytes(devname.charAt(i));
bw.write2bytes(0);
}
}
}
public int getNetworkType() { return nptype; }
/**
* pass zero to switch off network type
*/
public void setNetworlType(int n) throws ShellLinkException {
if (n == 0) {
flags.clearValidNetType();
nptype = n;
} else {
checkNptype(n);
flags.setValidNetType();
nptype = n;
}
}
public String getNetName() { return netname; }
/**
* if s is null take no effect
*/
public void setNetName(String s) throws ShellLinkException {
if (s == null) return;
netname = s;
}
public String getDeviceName() { return devname; }
/**
* pass null to switch off device info
*/
public void setDeviceName(String s) {
if (s == null) {
devname = null;
flags.clearValidDevice();
} else {
devname = s;
flags.setValidDevice();
}
}
}
package mslinks.data;
import io.ByteReader;
import java.io.IOException;
public class CNRLinkFlags extends BitSet32 {
public CNRLinkFlags(int n) {
super(n);
reset();
}
public CNRLinkFlags(ByteReader data) throws IOException {
super(data);
reset();
}
private void reset() {
for (int i=2; i<32; i++)
clear(i);
}
public boolean isValidDevice() { return get(0); }
public boolean isValidNetType() { return get(1); }
public void setValidDevice() { set(0); }
public void setValidNetType() { set(1); }
public void clearValidDevice() { clear(0); }
public void clearValidNetType() { clear(1); }
}
......@@ -7,10 +7,19 @@ import java.io.IOException;
public class FileAttributesFlags extends BitSet32 {
public FileAttributesFlags(int n) {
super(n);
reset();
}
public FileAttributesFlags(ByteReader data) throws IOException {
super(data);
reset();
}
private void reset() {
clear(3);
clear(6);
for (int i=15; i<32; i++)
clear(i);
}
public boolean isReadonly() { return get(0); }
......
......@@ -6,7 +6,9 @@ import io.ByteWriter;
import java.io.IOException;
import java.util.GregorianCalendar;
public class Filetime extends GregorianCalendar {
import mslinks.Serializable;
public class Filetime extends GregorianCalendar implements Serializable {
private long residue;
public Filetime(ByteReader data) throws IOException {
......
......@@ -6,7 +6,9 @@ import io.Bytes;
import java.io.IOException;
public class GUID {
import mslinks.Serializable;
public class GUID implements Serializable {
private int d1;
private short d2, d3, d4;
private long d5;
......
......@@ -6,7 +6,9 @@ import io.ByteWriter;
import java.io.IOException;
import java.util.HashMap;
public class HotKeyFlags {
import mslinks.Serializable;
public class HotKeyFlags implements Serializable {
private static HashMap<Byte, String> keys = new HashMap<Byte, String>() {{
put((byte)0x30, "0");
put((byte)0x31, "1");
......
......@@ -8,10 +8,19 @@ public class LinkFlags extends BitSet32 {
public LinkFlags(int n) {
super(n);
reset();
}
public LinkFlags(ByteReader data) throws IOException {
super(data);
reset();
}
private void reset() {
clear(11);
clear(16);
for (int i=27; i<32; i++)
clear(i);
}
public boolean hasLinkTargetIDList() { return get(0); }
......
package mslinks.data;
import io.ByteReader;
import java.io.IOException;
public class LinkInfoFlags extends BitSet32 {
public LinkInfoFlags(int n) {
super(n);
reset();
}
public LinkInfoFlags(ByteReader data) throws IOException {
super(data);
reset();
}
private void reset() {
for (int i=2; i<32; i++)
clear(i);
}
public boolean hasVolumeIDAndLocalBasePath() { return get(0); }
public boolean hasCommonNetworkRelativeLinkAndPathSuffix() { return get(1); }
public void setVolumeIDAndLocalBasePath() { set(0); }
public void setCommonNetworkRelativeLinkAndPathSuffix() { set(1); }
public void clearVolumeIDAndLocalBasePath() { clear(0); }
public void clearCommonNetworkRelativeLinkAndPathSuffix() { clear(1); }
}
package mslinks.data;
import java.io.IOException;
import java.nio.charset.Charset;
import mslinks.Serializable;
import mslinks.ShellLinkException;
import io.ByteReader;
import io.ByteWriter;
public class VolumeID implements Serializable {
public static final int DRIVE_UNKNOWN = 0;
public static final int DRIVE_NO_ROOT_DIR = 1;
public static final int DRIVE_REMOVABLE = 2;
public static final int DRIVE_FIXED = 3;
public static final int DRIVE_REMOTE = 4;
public static final int DRIVE_CDROM = 5;
public static final int DRIVE_RAMDISK = 6;
private int dt;
private int dsn;
private String label;
public VolumeID() {
dt = DRIVE_UNKNOWN;
dsn = (int)(Math.random() * Long.MAX_VALUE);
label = "";
}
public VolumeID(ByteReader data) throws ShellLinkException, IOException {
int pos = data.getPosition();
int size = (int)data.read4bytes();
if (size <= 0x10)
throw new ShellLinkException();
dt = (int)data.read4bytes();
if (dt != DRIVE_NO_ROOT_DIR && dt != DRIVE_REMOVABLE && dt != DRIVE_FIXED
&& dt != DRIVE_REMOTE && dt != DRIVE_CDROM && dt != DRIVE_RAMDISK)
dt = DRIVE_UNKNOWN;
dsn = (int)data.read4bytes();
int vloffset = (int)data.read4bytes();
boolean u = false;
if (vloffset == 0x14) {
vloffset = (int)data.read4bytes();
u = true;
}
data.seek(pos + vloffset - data.getPosition());
int i=0;
if (u) {
char[] buf = new char[(size-vloffset)>>1];
for (;; i++) {
char c = (char)data.read2bytes();
if (c == 0) break;
buf[i] = c;
}
label = new String(buf, 0, i);
} else {
byte[] buf = new byte[size-vloffset];
for (;; i++) {
int b = data.read();
if (b == 0) break;
buf[i] = (byte)b;
}
label = new String(buf, 0, i);
}
}
public void serialize(ByteWriter bw) throws IOException {
int size = 16;
byte[] label_b = label.getBytes();
size += label_b.length + 1;
boolean u = false;
if (!Charset.defaultCharset().newEncoder().canEncode(label)) {
size += 4 + 1 + label.length() * 2 + 2;
u = true;
}
bw.write4bytes(size);
bw.write4bytes(dt);
bw.write4bytes(dsn);
int off = 16;
if (u) off += 4;
bw.write4bytes(off);
off += label_b.length + 1;
if (u) {
off++;
bw.write4bytes(off);
off += label.length() * 2 + 2;
}
bw.writeBytes(label_b);
bw.write(0);
if (u) {
bw.write(0);
for (int i=0; i<label.length(); i++)
bw.write2bytes(label.charAt(i));
bw.write2bytes(0);
}
}
public int getDriveType() { return dt;}
public void setDriveType(int n) throws ShellLinkException {
if (n == DRIVE_UNKNOWN || n == DRIVE_NO_ROOT_DIR || n == DRIVE_REMOVABLE || n == DRIVE_FIXED
|| n == DRIVE_REMOTE || n == DRIVE_CDROM || n == DRIVE_RAMDISK)
dt = n;
else
throw new ShellLinkException("incorrect drive type");
}
public int getSerialNumber() { return dsn; }
public void setSerialNumber(int n) { dsn = n; }
public String getLabel() { return label; }
/**
* if s is null take no effect
*/
public void setLabel(String s) {
if (s == null) return;
label = s;
}
}
No preview for this file type
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment