mirror of
https://github.com/aelurum/AssetStudio.git
synced 2025-05-25 05:40:21 -04:00
[GUI] Add support for .lnk files via Drag&Drop. Close #13
This commit is contained in:
parent
51d259464b
commit
632e5f8d08
@ -82,7 +82,7 @@ namespace AssetStudio
|
||||
MergeSplitAssets(fullPath, true);
|
||||
fileList.AddRange(Directory.GetFiles(fullPath, "*.*", SearchOption.AllDirectories));
|
||||
}
|
||||
else
|
||||
else if (File.Exists(fullPath))
|
||||
{
|
||||
parentPath = Path.GetDirectoryName(fullPath);
|
||||
fileList.Add(fullPath);
|
||||
|
@ -35,10 +35,13 @@ namespace AssetStudio
|
||||
return "";
|
||||
}
|
||||
|
||||
public static string ReadStringToNull(this BinaryReader reader, int maxLength = 32767)
|
||||
public static string ReadStringToNull(this BinaryReader reader, int maxLength = 32767, Encoding encoding = null)
|
||||
{
|
||||
if (encoding?.CodePage == 1200) //Unicode (UTF-16LE)
|
||||
return reader.ReadUnicodeStringToNull(maxLength * 2);
|
||||
|
||||
var bytes = new List<byte>();
|
||||
int count = 0;
|
||||
var count = 0;
|
||||
while (reader.BaseStream.Position != reader.BaseStream.Length && count < maxLength)
|
||||
{
|
||||
var b = reader.ReadByte();
|
||||
@ -49,7 +52,24 @@ namespace AssetStudio
|
||||
bytes.Add(b);
|
||||
count++;
|
||||
}
|
||||
return Encoding.UTF8.GetString(bytes.ToArray());
|
||||
return encoding?.GetString(bytes.ToArray()) ?? Encoding.UTF8.GetString(bytes.ToArray());
|
||||
}
|
||||
|
||||
private static string ReadUnicodeStringToNull(this BinaryReader reader, int maxLength)
|
||||
{
|
||||
var bytes = new List<byte>();
|
||||
var count = 0;
|
||||
while (reader.BaseStream.Position != reader.BaseStream.Length && count < maxLength)
|
||||
{
|
||||
var b = reader.ReadBytes(2);
|
||||
if (b.Length < 2 || (b[0] == 0 && b[1] == 0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
bytes.AddRange(b);
|
||||
count += 2;
|
||||
}
|
||||
return Encoding.Unicode.GetString(bytes.ToArray());
|
||||
}
|
||||
|
||||
public static Quaternion ReadQuaternion(this BinaryReader reader)
|
||||
|
@ -146,15 +146,26 @@ namespace AssetStudioGUI
|
||||
private async void AssetStudioGUIForm_DragDrop(object sender, DragEventArgs e)
|
||||
{
|
||||
var paths = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||
if (paths.Length > 0)
|
||||
{
|
||||
if (paths.Length == 0)
|
||||
return;
|
||||
|
||||
ResetForm();
|
||||
for (var i = 0; i < paths.Length; i++)
|
||||
{
|
||||
if (paths[i].ToLower().EndsWith(".lnk"))
|
||||
{
|
||||
var targetPath = LnkReader.GetLnkTarget(paths[i]);
|
||||
if (!string.IsNullOrEmpty(targetPath))
|
||||
{
|
||||
paths[i] = targetPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
|
||||
await Task.Run(() => assetsManager.LoadFilesAndFolders(out openDirectoryBackup, paths));
|
||||
saveDirectoryBackup = openDirectoryBackup;
|
||||
BuildAssetStructures();
|
||||
}
|
||||
}
|
||||
|
||||
private async void loadFile_Click(object sender, EventArgs e)
|
||||
{
|
||||
|
164
AssetStudioGUI/Components/LnkReader.cs
Normal file
164
AssetStudioGUI/Components/LnkReader.cs
Normal file
@ -0,0 +1,164 @@
|
||||
// Shortcut (.lnk) file reader
|
||||
// by aelurum
|
||||
// Based on https://github.com/libyal/liblnk/blob/main/documentation/Windows%20Shortcut%20File%20(LNK)%20format.asciidoc
|
||||
|
||||
using AssetStudio;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudioGUI
|
||||
{
|
||||
public static class LnkReader
|
||||
{
|
||||
[Flags]
|
||||
private enum LnkDataFlags
|
||||
{
|
||||
//The LNK file contains a link target identifier
|
||||
HasTargetIDList = 0x00000001,
|
||||
//The LNK file contains location information
|
||||
HasLinkInfo = 0x00000002,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum LnkLocFlags
|
||||
{
|
||||
//The linked file is on a volume
|
||||
//If set the volume information and the local path contain data
|
||||
VolumeIDAndLocalBasePath = 0x0001,
|
||||
//The linked file is on a network share
|
||||
//If set the network share information and common path contain data
|
||||
CommonNetworkRelativeLinkAndPathSuffix = 0x0002
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum PathTypeFlags
|
||||
{
|
||||
IsUnicodeLocalPath = 0x01,
|
||||
IsUnicodeNetShareName = 0x02,
|
||||
IsUnicodeCommonPath = 0x04
|
||||
}
|
||||
|
||||
public static string GetLnkTarget(string filePath)
|
||||
{
|
||||
var targetPath = string.Empty;
|
||||
var pathType = (PathTypeFlags)0;
|
||||
Encoding sysEncoding;
|
||||
try
|
||||
{
|
||||
sysEncoding = GetSysEncoding();
|
||||
Logger.Debug($"System default text encoding: {sysEncoding.CodePage}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error("Text encoding error", ex);
|
||||
return null;
|
||||
}
|
||||
|
||||
using (var reader = new FileReader(filePath))
|
||||
{
|
||||
reader.Endian = EndianType.LittleEndian;
|
||||
|
||||
var headerSize = reader.ReadUInt32(); //76 bytes
|
||||
reader.Position = 20; //skip LNK class identifier (GUID)
|
||||
var dataFlags = (LnkDataFlags)reader.ReadUInt32();
|
||||
if ((dataFlags & LnkDataFlags.HasLinkInfo) == 0)
|
||||
{
|
||||
Logger.Warning("Unsupported type of .lnk file. Link info was not found.");
|
||||
return null;
|
||||
}
|
||||
reader.Position = headerSize;
|
||||
|
||||
//Skip the shell item ID list
|
||||
if ((dataFlags & LnkDataFlags.HasTargetIDList) != 0)
|
||||
{
|
||||
var itemIDListSize = reader.ReadUInt16();
|
||||
reader.Position += itemIDListSize;
|
||||
}
|
||||
|
||||
//The offsets is relative to the start of the location information block
|
||||
var locInfoPos = reader.Position;
|
||||
var locInfoFullSize = reader.ReadUInt32();
|
||||
if (locInfoFullSize == 0)
|
||||
{
|
||||
Logger.Warning("Unsupported type of .lnk file. Link info was not found.");
|
||||
return null;
|
||||
}
|
||||
var locInfoHeaderSize = reader.ReadUInt32();
|
||||
var locFlags = (LnkLocFlags)reader.ReadUInt32();
|
||||
//Offset to the volume information block
|
||||
var offsetVolumeInfo = reader.ReadUInt32();
|
||||
//Offset to the ANSI local path
|
||||
var offsetLocalPath = reader.ReadUInt32();
|
||||
//Offset to the network share information block
|
||||
var offsetNetInfo = reader.ReadUInt32();
|
||||
//Offset to the ANSI common path. 0 if not available
|
||||
var offsetCommonPath = reader.ReadUInt32();
|
||||
if (locInfoHeaderSize > 28)
|
||||
{
|
||||
//Offset to the Unicode local path
|
||||
offsetLocalPath = reader.ReadUInt32();
|
||||
pathType |= PathTypeFlags.IsUnicodeLocalPath;
|
||||
}
|
||||
if (locInfoHeaderSize > 32)
|
||||
{
|
||||
//Offset to the Unicode common path
|
||||
offsetCommonPath = reader.ReadUInt32();
|
||||
pathType |= PathTypeFlags.IsUnicodeCommonPath;
|
||||
}
|
||||
|
||||
//Read local path, if exist
|
||||
if (offsetLocalPath > 0)
|
||||
{
|
||||
reader.Position = locInfoPos + offsetLocalPath;
|
||||
targetPath = (pathType & PathTypeFlags.IsUnicodeLocalPath) != 0
|
||||
? reader.ReadStringToNull(encoding: Encoding.Unicode)
|
||||
: reader.ReadStringToNull(encoding: sysEncoding);
|
||||
}
|
||||
|
||||
//Read network path, if exist
|
||||
if (locFlags == LnkLocFlags.CommonNetworkRelativeLinkAndPathSuffix)
|
||||
{
|
||||
reader.Position = locInfoPos + offsetNetInfo;
|
||||
var netInfoSize = reader.ReadUInt32();
|
||||
var netInfoFlags = reader.ReadUInt32();
|
||||
//Offset to the ANSI network share name. The offset is relative to the start of the network share information block
|
||||
var offsetNetShareName = reader.ReadUInt32();
|
||||
if (offsetNetShareName > 20)
|
||||
{
|
||||
reader.Position = locInfoPos + offsetNetInfo + 20;
|
||||
//Offset to the Unicode network share name
|
||||
offsetNetShareName = reader.ReadUInt32();
|
||||
pathType |= PathTypeFlags.IsUnicodeNetShareName;
|
||||
}
|
||||
if (offsetNetShareName > 0)
|
||||
{
|
||||
reader.Position = locInfoPos + offsetNetInfo + offsetNetShareName;
|
||||
targetPath = (pathType & PathTypeFlags.IsUnicodeNetShareName) != 0
|
||||
? reader.ReadStringToNull(encoding: Encoding.Unicode)
|
||||
: reader.ReadStringToNull(encoding: sysEncoding);
|
||||
}
|
||||
}
|
||||
|
||||
//Read common path, if exist
|
||||
if (offsetCommonPath > 0)
|
||||
{
|
||||
reader.Position = locInfoPos + offsetCommonPath;
|
||||
var commonPath = (pathType & PathTypeFlags.IsUnicodeCommonPath) != 0
|
||||
? reader.ReadStringToNull(encoding: Encoding.Unicode)
|
||||
: reader.ReadStringToNull(encoding: sysEncoding);
|
||||
targetPath = Path.Combine(targetPath, commonPath);
|
||||
}
|
||||
}
|
||||
return targetPath;
|
||||
}
|
||||
|
||||
private static Encoding GetSysEncoding()
|
||||
{
|
||||
#if !NETFRAMEWORK
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
#endif
|
||||
return Encoding.GetEncoding(0);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user