mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-07-08 18:06:41 +00:00
Code cleanup and slight modernization
This commit is contained in:
@@ -10,12 +10,14 @@ namespace CascLibSharp
|
||||
internal sealed class CascApi
|
||||
{
|
||||
#region Imported method signature type definitions
|
||||
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
internal delegate bool FnCascOpenStorage(
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string szDataPath,
|
||||
uint dwFlags,
|
||||
out CascStorageSafeHandle phStorage);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
internal delegate bool FnCascGetStorageInfo(
|
||||
@@ -24,6 +26,7 @@ namespace CascLibSharp
|
||||
ref uint pvStorageInfo,
|
||||
IntPtr cbStorageInfo,
|
||||
ref uint pcbLengthNeeded);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
internal delegate bool FnCascCloseStorage(IntPtr hStorage);
|
||||
@@ -35,6 +38,7 @@ namespace CascLibSharp
|
||||
ref QueryKey pIndexKey,
|
||||
uint dwFlags,
|
||||
out CascStorageFileSafeHandle phFile);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
internal delegate bool FnCascOpenFileByEncodingKey(
|
||||
@@ -42,6 +46,7 @@ namespace CascLibSharp
|
||||
ref QueryKey pEncodingKey,
|
||||
uint dwFlags,
|
||||
out CascStorageFileSafeHandle phFile);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
internal delegate bool FnCascOpenFile(
|
||||
@@ -50,6 +55,7 @@ namespace CascLibSharp
|
||||
uint dwLocale,
|
||||
uint dwFlags,
|
||||
out CascStorageFileSafeHandle phFile);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
internal delegate uint FnCascGetFileSize(
|
||||
CascStorageFileSafeHandle hFile,
|
||||
@@ -60,6 +66,7 @@ namespace CascLibSharp
|
||||
uint lFilePos,
|
||||
ref uint plFilePosHigh,
|
||||
SeekOrigin dwMoveMethod);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
internal delegate bool FnCascReadFile(
|
||||
@@ -67,6 +74,7 @@ namespace CascLibSharp
|
||||
IntPtr lpBuffer,
|
||||
uint dwToRead,
|
||||
out uint dwRead);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
internal delegate bool FnCascCloseFile(IntPtr hFile);
|
||||
@@ -77,17 +85,21 @@ namespace CascLibSharp
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szMask,
|
||||
ref CascFindData pFindData,
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string? szListFile);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
internal delegate bool FnCascFindNextFile(
|
||||
CascFileEnumerationSafeHandle hFind,
|
||||
ref CascFindData pFindData);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
internal delegate bool FnCascFindClose(IntPtr hFind);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Field and method defs
|
||||
|
||||
public readonly FnCascOpenStorage? CascOpenStorage;
|
||||
public readonly FnCascGetStorageInfo? CascGetStorageInfo;
|
||||
public readonly FnCascCloseStorage? CascCloseStorage;
|
||||
@@ -99,8 +111,7 @@ namespace CascLibSharp
|
||||
public readonly FnCascGetFileSize? CascGetFileSizeBase;
|
||||
public long CascGetFileSize(CascStorageFileSafeHandle hFile)
|
||||
{
|
||||
uint high;
|
||||
uint low = CascGetFileSizeBase!(hFile, out high);
|
||||
uint low = CascGetFileSizeBase!(hFile, out uint high);
|
||||
long result = (high << 32) | low;
|
||||
|
||||
return result;
|
||||
@@ -127,6 +138,7 @@ namespace CascLibSharp
|
||||
public readonly FnCascFindFirstFile? CascFindFirstFile;
|
||||
public readonly FnCascFindNextFile? CascFindNextFile;
|
||||
public readonly FnCascFindClose? CascFindClose;
|
||||
|
||||
#endregion
|
||||
|
||||
internal CascApi(IntPtr hModule)
|
||||
@@ -154,6 +166,7 @@ namespace CascLibSharp
|
||||
IntPtr procAddr = NativeMethods.GetProcAddress(hModule, procName);
|
||||
if (procAddr == IntPtr.Zero)
|
||||
throw new Win32Exception();
|
||||
|
||||
target = Marshal.GetDelegateForFunctionPointer(procAddr, typeof(T)) as T;
|
||||
}
|
||||
|
||||
@@ -194,7 +207,7 @@ namespace CascLibSharp
|
||||
#if NET20 || NET35
|
||||
private static CascApi? _sharedInstance = null;
|
||||
#else
|
||||
private static Lazy<CascApi> _sharedInstance = new Lazy<CascApi>(Load);
|
||||
private static readonly Lazy<CascApi> _sharedInstance = new(Load);
|
||||
#endif
|
||||
public static CascApi Instance
|
||||
{
|
||||
|
||||
@@ -10,8 +10,8 @@ namespace CascLibSharp
|
||||
/// </summary>
|
||||
public class CascFileStream : Stream
|
||||
{
|
||||
private CascStorageFileSafeHandle _handle;
|
||||
private CascApi _api;
|
||||
private readonly CascStorageFileSafeHandle _handle;
|
||||
private readonly CascApi _api;
|
||||
|
||||
internal CascFileStream(CascStorageFileSafeHandle? handle, CascApi? api)
|
||||
{
|
||||
@@ -110,11 +110,11 @@ namespace CascLibSharp
|
||||
AssertValidHandle();
|
||||
long len = Length;
|
||||
if (offset < 0 || offset > len)
|
||||
throw new ArgumentException("offset");
|
||||
throw new ArgumentException(nameof(offset));
|
||||
if (count < 0)
|
||||
throw new ArgumentException("count");
|
||||
throw new ArgumentException(nameof(count));
|
||||
if (offset + count > len)
|
||||
throw new ArgumentException("count");
|
||||
throw new ArgumentException(nameof(count));
|
||||
|
||||
uint read = 0;
|
||||
fixed (byte* pBuffer = &buffer[0])
|
||||
|
||||
@@ -9,9 +9,9 @@ namespace CascLibSharp
|
||||
public class CascFoundFile
|
||||
{
|
||||
#if NET20 || NET35 || NET40
|
||||
private WeakReference _ownerContext;
|
||||
private readonly WeakReference _ownerContext;
|
||||
#else
|
||||
private WeakReference<CascStorageContext> _ownerContext;
|
||||
private readonly WeakReference<CascStorageContext> _ownerContext;
|
||||
#endif
|
||||
|
||||
internal CascFoundFile(string? fileName, IntPtr plainName, byte[] encodingKey, CascLocales locales, long fileSize, CascStorageContext ownerContext)
|
||||
@@ -33,18 +33,22 @@ namespace CascLibSharp
|
||||
/// Gets the full path to this file.
|
||||
/// </summary>
|
||||
public string? FileName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plain (no directory-qualified) file name of this file.
|
||||
/// </summary>
|
||||
public string? PlainFileName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the CASC encoding key for this file.
|
||||
/// </summary>
|
||||
public byte[] EncodingKey { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the locales supported by this resource.
|
||||
/// </summary>
|
||||
public CascLocales Locales { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length of the file in bytes.
|
||||
/// </summary>
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace CascLibSharp
|
||||
/// </summary>
|
||||
public class CascStorageContext : IDisposable
|
||||
{
|
||||
private CascApi _api;
|
||||
private readonly CascApi _api;
|
||||
private CascStorageSafeHandle? _handle;
|
||||
#if NET20 || NET35
|
||||
private bool? _hasListfile = null;
|
||||
@@ -17,10 +17,10 @@ namespace CascLibSharp
|
||||
private long? _fileCount = null;
|
||||
private int? _gameBuild = null;
|
||||
#else
|
||||
private Lazy<bool> _hasListfile;
|
||||
private Lazy<CascKnownClient> _clientType;
|
||||
private Lazy<long> _fileCount;
|
||||
private Lazy<int> _gameBuild;
|
||||
private readonly Lazy<bool> _hasListfile;
|
||||
private readonly Lazy<CascKnownClient> _clientType;
|
||||
private readonly Lazy<long> _fileCount;
|
||||
private readonly Lazy<int> _gameBuild;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
@@ -82,20 +82,19 @@ namespace CascLibSharp
|
||||
if (_handle == null || _handle.IsInvalid)
|
||||
throw new ObjectDisposedException("CascStorageContext");
|
||||
|
||||
using (CoTaskMem mem = CoTaskMem.FromBytes(indexKey))
|
||||
{
|
||||
QueryKey qk = new QueryKey();
|
||||
qk.cbData = unchecked((uint)indexKey.Length);
|
||||
qk.pbData = mem.Pointer;
|
||||
using CoTaskMem mem = CoTaskMem.FromBytes(indexKey);
|
||||
|
||||
CascStorageFileSafeHandle hFile;
|
||||
if (!_api.CascOpenFileByIndexKey!(_handle, ref qk, 0, out hFile))
|
||||
throw new CascException();
|
||||
var qk = new QueryKey();
|
||||
qk.cbData = unchecked((uint)indexKey.Length);
|
||||
qk.pbData = mem.Pointer;
|
||||
|
||||
hFile.Api = _api;
|
||||
CascStorageFileSafeHandle hFile;
|
||||
if (!_api.CascOpenFileByIndexKey!(_handle, ref qk, 0, out hFile))
|
||||
throw new CascException();
|
||||
|
||||
return new CascFileStream(hFile, _api);
|
||||
}
|
||||
hFile.Api = _api;
|
||||
|
||||
return new CascFileStream(hFile, _api);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -110,20 +109,19 @@ namespace CascLibSharp
|
||||
if (_handle == null || _handle.IsInvalid)
|
||||
throw new ObjectDisposedException("CascStorageContext");
|
||||
|
||||
using (CoTaskMem mem = CoTaskMem.FromBytes(encodingKey))
|
||||
{
|
||||
QueryKey qk = new QueryKey();
|
||||
qk.cbData = unchecked((uint)encodingKey.Length);
|
||||
qk.pbData = mem.Pointer;
|
||||
using CoTaskMem mem = CoTaskMem.FromBytes(encodingKey);
|
||||
|
||||
CascStorageFileSafeHandle hFile;
|
||||
if (!_api.CascOpenFileByEncodingKey!(_handle, ref qk, 0, out hFile))
|
||||
throw new CascException();
|
||||
var qk = new QueryKey();
|
||||
qk.cbData = unchecked((uint)encodingKey.Length);
|
||||
qk.pbData = mem.Pointer;
|
||||
|
||||
hFile.Api = _api;
|
||||
CascStorageFileSafeHandle hFile;
|
||||
if (!_api.CascOpenFileByEncodingKey!(_handle, ref qk, 0, out hFile))
|
||||
throw new CascException();
|
||||
|
||||
return new CascFileStream(hFile, _api);
|
||||
}
|
||||
hFile.Api = _api;
|
||||
|
||||
return new CascFileStream(hFile, _api);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -138,26 +136,24 @@ namespace CascLibSharp
|
||||
throw new ObjectDisposedException("CascStorageContext");
|
||||
|
||||
#if NET20 || NET35
|
||||
if (this.GameClient == CascKnownClient.WorldOfWarcraft && string.IsNullOrEmpty(listFilePath))
|
||||
if (GameClient == CascKnownClient.WorldOfWarcraft && string.IsNullOrEmpty(listFilePath))
|
||||
#else
|
||||
if (this.GameClient == CascKnownClient.WorldOfWarcraft && string.IsNullOrWhiteSpace(listFilePath))
|
||||
if (GameClient == CascKnownClient.WorldOfWarcraft && string.IsNullOrWhiteSpace(listFilePath))
|
||||
#endif
|
||||
throw new ArgumentNullException("listFilePath");
|
||||
|
||||
CascFindData cfd = new CascFindData();
|
||||
using (var handle = _api.CascFindFirstFile!(_handle, mask, ref cfd, listFilePath))
|
||||
var cfd = new CascFindData();
|
||||
using var handle = _api.CascFindFirstFile!(_handle, mask, ref cfd, listFilePath);
|
||||
if (handle.IsInvalid)
|
||||
yield break;
|
||||
|
||||
handle.Api = _api;
|
||||
|
||||
yield return cfd.ToFoundFile(this);
|
||||
|
||||
while (_api.CascFindNextFile!(handle, ref cfd))
|
||||
{
|
||||
if (handle.IsInvalid)
|
||||
yield break;
|
||||
|
||||
handle.Api = _api;
|
||||
|
||||
yield return cfd.ToFoundFile(this);
|
||||
|
||||
while (_api.CascFindNextFile!(handle, ref cfd))
|
||||
{
|
||||
yield return cfd.ToFoundFile(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,6 +276,7 @@ namespace CascLibSharp
|
||||
}
|
||||
|
||||
#region IDisposable implementation
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes the storage context.
|
||||
/// </summary>
|
||||
@@ -303,15 +300,16 @@ namespace CascLibSharp
|
||||
/// <param name="disposing">True if this is being called via the Dispose() method; false if it's being called by the finalizer.</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && _handle != null)
|
||||
if (disposing)
|
||||
{
|
||||
if (!_handle.IsInvalid)
|
||||
if (_handle != null && !_handle.IsInvalid)
|
||||
{
|
||||
_handle.Close();
|
||||
_handle = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -325,74 +323,92 @@ namespace CascLibSharp
|
||||
/// All available locales.
|
||||
/// </summary>
|
||||
All = -1,
|
||||
|
||||
/// <summary>
|
||||
/// No locales.
|
||||
/// </summary>
|
||||
///
|
||||
None = 0,
|
||||
/// <summary>
|
||||
/// Unknown
|
||||
/// </summary>
|
||||
Unknown1 = 1,
|
||||
|
||||
/// <summary>
|
||||
/// English, United States
|
||||
/// </summary>
|
||||
EnUs = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Korean, South Korea
|
||||
/// </summary>
|
||||
KoKr = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Reserved (unknown)
|
||||
/// </summary>
|
||||
Reserved = 8,
|
||||
|
||||
/// <summary>
|
||||
/// French, France
|
||||
/// </summary>
|
||||
FrFr = 0x10,
|
||||
|
||||
/// <summary>
|
||||
/// German, Germany
|
||||
/// </summary>
|
||||
DeDe = 0x20,
|
||||
|
||||
/// <summary>
|
||||
/// Chinese, China
|
||||
/// </summary>
|
||||
ZhCn = 0x40,
|
||||
|
||||
/// <summary>
|
||||
/// Spanish, Spain
|
||||
/// </summary>
|
||||
EsEs = 0x80,
|
||||
|
||||
/// <summary>
|
||||
/// Chinese, Taiwan
|
||||
/// </summary>
|
||||
ZhTw = 0x100,
|
||||
|
||||
/// <summary>
|
||||
/// English, Great Britain
|
||||
/// </summary>
|
||||
EnGb = 0x200,
|
||||
|
||||
/// <summary>
|
||||
/// English, China
|
||||
/// </summary>
|
||||
EnCn = 0x400,
|
||||
|
||||
/// <summary>
|
||||
/// English, Taiwan
|
||||
/// </summary>
|
||||
EnTw = 0x800,
|
||||
|
||||
/// <summary>
|
||||
/// Spanish, Mexico
|
||||
/// </summary>
|
||||
EsMx = 0x1000,
|
||||
|
||||
/// <summary>
|
||||
/// Russian, Russia
|
||||
/// </summary>
|
||||
RuRu = 0x2000,
|
||||
|
||||
/// <summary>
|
||||
/// Portuguese, Brazil
|
||||
/// </summary>
|
||||
PtBr = 0x4000,
|
||||
|
||||
/// <summary>
|
||||
/// Italian, Italy
|
||||
/// </summary>
|
||||
ItIt = 0x8000,
|
||||
|
||||
/// <summary>
|
||||
/// Portuguese, Portugal
|
||||
/// </summary>
|
||||
@@ -408,22 +424,27 @@ namespace CascLibSharp
|
||||
/// The game client was unrecognized.
|
||||
/// </summary>
|
||||
Unknown = -1,
|
||||
|
||||
/// <summary>
|
||||
/// Heroes of the Storm
|
||||
/// </summary>
|
||||
HeroesOfTheStorm = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Diablo 3
|
||||
/// </summary>
|
||||
Diablo3 = 1,
|
||||
|
||||
/// <summary>
|
||||
/// World of Warcraft
|
||||
/// </summary>
|
||||
WorldOfWarcraft = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Overwatch
|
||||
/// </summary>
|
||||
Overwatch = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Starcraft 2
|
||||
/// </summary>
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace CascLibSharp.Native
|
||||
|
||||
public static CoTaskMem FromBytes(byte[] b)
|
||||
{
|
||||
CoTaskMem result = new CoTaskMem(b.Length);
|
||||
var result = new CoTaskMem(b.Length);
|
||||
Marshal.Copy(b, 0, result._mem, b.Length);
|
||||
|
||||
return result;
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace CascLibSharp.Native
|
||||
|
||||
internal static class GameConverterExtensions
|
||||
{
|
||||
private static Dictionary<CascGameId, CascKnownClient> GameClientMap = new Dictionary<CascGameId, CascKnownClient>
|
||||
private static readonly Dictionary<CascGameId, CascKnownClient> GameClientMap = new()
|
||||
{
|
||||
{ CascGameId.Hots, CascKnownClient.HeroesOfTheStorm },
|
||||
{ CascGameId.Wow6, CascKnownClient.WorldOfWarcraft },
|
||||
@@ -53,7 +53,7 @@ namespace CascLibSharp.Native
|
||||
{ CascGameId.Starcraft2, CascKnownClient.Starcraft2 },
|
||||
};
|
||||
|
||||
private static Dictionary<CascKnownClient, CascGameId> ClientGameMap = new Dictionary<CascKnownClient, CascGameId>()
|
||||
private static readonly Dictionary<CascKnownClient, CascGameId> ClientGameMap = new()
|
||||
{
|
||||
{ CascKnownClient.HeroesOfTheStorm, CascGameId.Hots },
|
||||
{ CascKnownClient.WorldOfWarcraft, CascGameId.Wow6 },
|
||||
@@ -64,8 +64,7 @@ namespace CascLibSharp.Native
|
||||
|
||||
public static CascKnownClient ToKnownClient(this CascGameId gameId)
|
||||
{
|
||||
CascKnownClient result;
|
||||
if (!GameClientMap.TryGetValue(gameId, out result))
|
||||
if (!GameClientMap.TryGetValue(gameId, out CascKnownClient result))
|
||||
result = CascKnownClient.Unknown;
|
||||
|
||||
return result;
|
||||
@@ -73,15 +72,12 @@ namespace CascLibSharp.Native
|
||||
|
||||
public static CascGameId ToGameId(this CascKnownClient knownClient)
|
||||
{
|
||||
CascGameId result;
|
||||
if (!ClientGameMap.TryGetValue(knownClient, out result))
|
||||
if (!ClientGameMap.TryGetValue(knownClient, out CascGameId result))
|
||||
throw new ArgumentException("Invalid client.");
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable 649
|
||||
internal struct QueryKey
|
||||
{
|
||||
public IntPtr pbData;
|
||||
@@ -107,6 +103,7 @@ namespace CascLibSharp.Native
|
||||
{
|
||||
fileName = Marshal.PtrToStringAnsi(new IntPtr(pFileName));
|
||||
}
|
||||
|
||||
byte[] encodingKey = new byte[16];
|
||||
fixed (void* pEncodingKey = EncodingKey)
|
||||
{
|
||||
@@ -116,5 +113,4 @@ namespace CascLibSharp.Native
|
||||
return new CascFoundFile(fileName, szPlainName, encodingKey, (CascLocales)dwLocaleFlags, dwFileSize, ownerContext);
|
||||
}
|
||||
}
|
||||
#pragma warning restore 649
|
||||
}
|
||||
|
||||
@@ -9,15 +9,17 @@ namespace StormLibSharp
|
||||
public class MpqArchive : IDisposable
|
||||
{
|
||||
private MpqArchiveSafeHandle? _handle;
|
||||
private List<MpqFileStream> _openFiles = new List<MpqFileStream>();
|
||||
private FileAccess _accessType;
|
||||
private List<MpqArchiveCompactingEventHandler> _compactCallbacks = new List<MpqArchiveCompactingEventHandler>();
|
||||
private readonly List<MpqFileStream> _openFiles = [];
|
||||
private readonly FileAccess _accessType;
|
||||
private readonly List<MpqArchiveCompactingEventHandler> _compactCallbacks = [];
|
||||
private SFILE_COMPACT_CALLBACK? _compactCallback;
|
||||
|
||||
#region Constructors / Factories
|
||||
|
||||
public MpqArchive(string filePath, FileAccess accessType)
|
||||
{
|
||||
_accessType = accessType;
|
||||
|
||||
SFileOpenArchiveFlags flags = SFileOpenArchiveFlags.TypeIsFile;
|
||||
if (accessType == FileAccess.Read)
|
||||
flags |= SFileOpenArchiveFlags.AccessReadOnly;
|
||||
@@ -63,9 +65,11 @@ namespace StormLibSharp
|
||||
{
|
||||
return new MpqArchive(mpqPath, version, listfileAttributes, attributesFileAttributes, maxFileCount);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
// TODO: Move to common location.
|
||||
// This is a global setting, not per-archive setting.
|
||||
|
||||
@@ -91,7 +95,8 @@ namespace StormLibSharp
|
||||
set
|
||||
{
|
||||
if (value < 0 || value > uint.MaxValue)
|
||||
throw new ArgumentException("value");
|
||||
throw new ArgumentException(nameof(value));
|
||||
|
||||
VerifyHandle();
|
||||
|
||||
if (!NativeMethods.SFileSetMaxFileCount(_handle, unchecked((uint)value)))
|
||||
@@ -113,6 +118,7 @@ namespace StormLibSharp
|
||||
return NativeMethods.SFileIsPatchedArchive(_handle);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void Flush()
|
||||
@@ -145,7 +151,7 @@ namespace StormLibSharp
|
||||
|
||||
private void _OnCompact(IntPtr pvUserData, uint dwWorkType, ulong bytesProcessed, ulong totalBytes)
|
||||
{
|
||||
MpqArchiveCompactingEventArgs args = new MpqArchiveCompactingEventArgs(dwWorkType, bytesProcessed, totalBytes);
|
||||
var args = new MpqArchiveCompactingEventArgs(dwWorkType, bytesProcessed, totalBytes);
|
||||
OnCompacting(args);
|
||||
}
|
||||
|
||||
@@ -220,11 +226,10 @@ namespace StormLibSharp
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
MpqFileSafeHandle fileHandle;
|
||||
if (!NativeMethods.SFileOpenFileEx(_handle, fileName, 0, out fileHandle))
|
||||
if (!NativeMethods.SFileOpenFileEx(_handle, fileName, 0, out MpqFileSafeHandle fileHandle))
|
||||
throw new Win32Exception();
|
||||
|
||||
MpqFileStream fs = new MpqFileStream(fileHandle, _accessType, this);
|
||||
var fs = new MpqFileStream(fileHandle, _accessType, this);
|
||||
_openFiles.Add(fs);
|
||||
return fs;
|
||||
}
|
||||
@@ -255,6 +260,7 @@ namespace StormLibSharp
|
||||
|
||||
|
||||
#region IDisposable implementation
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
@@ -270,16 +276,13 @@ namespace StormLibSharp
|
||||
if (disposing)
|
||||
{
|
||||
// Release owned files first.
|
||||
if (_openFiles != null)
|
||||
foreach (var file in _openFiles)
|
||||
{
|
||||
foreach (var file in _openFiles)
|
||||
{
|
||||
file.Dispose();
|
||||
}
|
||||
|
||||
_openFiles.Clear();
|
||||
file.Dispose();
|
||||
}
|
||||
|
||||
_openFiles.Clear();
|
||||
|
||||
// Release
|
||||
if (_handle != null && !_handle.IsInvalid)
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace StormLibSharp
|
||||
public class MpqFileStream : Stream
|
||||
{
|
||||
private MpqFileSafeHandle? _handle;
|
||||
private FileAccess _accessType;
|
||||
private readonly FileAccess _accessType;
|
||||
private MpqArchive? _owner;
|
||||
|
||||
internal MpqFileStream(MpqFileSafeHandle handle, FileAccess accessType, MpqArchive owner)
|
||||
@@ -78,11 +78,11 @@ namespace StormLibSharp
|
||||
public override unsafe int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (buffer == null)
|
||||
throw new ArgumentNullException("buffer");
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
if (offset > buffer.Length || (offset + count) > buffer.Length)
|
||||
throw new ArgumentException();
|
||||
if (count < 0)
|
||||
throw new ArgumentOutOfRangeException("count");
|
||||
throw new ArgumentOutOfRangeException(nameof(count));
|
||||
|
||||
VerifyHandle();
|
||||
|
||||
@@ -108,9 +108,8 @@ namespace StormLibSharp
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
uint low, high;
|
||||
low = unchecked((uint)(offset & 0xffffffffu));
|
||||
high = unchecked((uint)(offset >> 32));
|
||||
uint low = unchecked((uint)(offset & 0xffffffffu));
|
||||
uint high = unchecked((uint)(offset >> 32));
|
||||
return NativeMethods.SFileSetFilePointer(_handle, low, ref high, (uint)origin);
|
||||
}
|
||||
|
||||
@@ -124,11 +123,11 @@ namespace StormLibSharp
|
||||
VerifyHandle();
|
||||
|
||||
if (buffer == null)
|
||||
throw new ArgumentNullException("buffer");
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
if (offset > buffer.Length || (offset + count) > buffer.Length)
|
||||
throw new ArgumentException();
|
||||
if (count < 0)
|
||||
throw new ArgumentOutOfRangeException("count");
|
||||
throw new ArgumentOutOfRangeException(nameof(count));
|
||||
|
||||
VerifyHandle();
|
||||
|
||||
@@ -154,11 +153,8 @@ namespace StormLibSharp
|
||||
_handle = null;
|
||||
}
|
||||
|
||||
if (_owner != null)
|
||||
{
|
||||
_owner.RemoveOwnedFile(this);
|
||||
_owner = null;
|
||||
}
|
||||
_owner?.RemoveOwnedFile(this);
|
||||
_owner = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace StormLibSharp.Native
|
||||
public MpqArchiveSafeHandle(IntPtr handle)
|
||||
: base(true)
|
||||
{
|
||||
this.SetHandle(handle);
|
||||
SetHandle(handle);
|
||||
}
|
||||
|
||||
public MpqArchiveSafeHandle()
|
||||
@@ -16,7 +16,7 @@ namespace StormLibSharp.Native
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
return NativeMethods.SFileCloseArchive(this.handle);
|
||||
return NativeMethods.SFileCloseArchive(handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace StormLibSharp.Native
|
||||
public MpqFileSafeHandle(IntPtr handle)
|
||||
: base(true)
|
||||
{
|
||||
this.SetHandle(handle);
|
||||
SetHandle(handle);
|
||||
}
|
||||
|
||||
public MpqFileSafeHandle()
|
||||
@@ -18,7 +18,7 @@ namespace StormLibSharp.Native
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
return NativeMethods.SFileCloseFile(this.handle);
|
||||
return NativeMethods.SFileCloseFile(handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,13 +8,17 @@ namespace StormLibSharp.Native
|
||||
private const string STORMLIB = "stormlib.dll";
|
||||
|
||||
#region Functions for manipulation with StormLib global flags
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileGetLocale();
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileSetLocale(uint lcNewLocale);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functions for archive manipulation
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileOpenArchive(
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string szMpqName,
|
||||
@@ -48,22 +52,27 @@ namespace StormLibSharp.Native
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileFlushArchive(MpqArchiveSafeHandle? hMpq);
|
||||
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCloseArchive(IntPtr hMpq);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCloseArchive(MpqArchiveSafeHandle? hMpq);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Adds another listfile into MPQ.
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SFileAddListFile(
|
||||
MpqArchiveSafeHandle? hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szListFile
|
||||
);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Archive compacting
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileSetCompactCallback(
|
||||
MpqArchiveSafeHandle? hMpq,
|
||||
@@ -77,17 +86,21 @@ namespace StormLibSharp.Native
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szListFile,
|
||||
bool bReserved
|
||||
);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Maximum file count
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileGetMaxFileCount(MpqArchiveSafeHandle? hMpq);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileSetMaxFileCount(MpqArchiveSafeHandle? hMpq, uint dwMaxFileCount);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Changing (attributes) file
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileGetAttributes(MpqArchiveSafeHandle? hMpq);
|
||||
|
||||
@@ -99,9 +112,11 @@ namespace StormLibSharp.Native
|
||||
MpqArchiveSafeHandle? hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szFileName
|
||||
);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functions for manipulation with patch archives
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileOpenPatchArchive(
|
||||
MpqArchiveSafeHandle? hMpq,
|
||||
@@ -112,9 +127,11 @@ namespace StormLibSharp.Native
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileIsPatchedArchive(MpqArchiveSafeHandle? hMpq);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functions for file manipulation
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileHasFile(
|
||||
MpqArchiveSafeHandle? hMpq,
|
||||
@@ -180,6 +197,7 @@ namespace StormLibSharp.Native
|
||||
public static extern bool SFileCloseFile(MpqFileSafeHandle? hFile);
|
||||
|
||||
#region Retrieving info about a file in the archive
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileGetFileInfo(
|
||||
IntPtr hMpqOrFile,
|
||||
@@ -218,6 +236,7 @@ namespace StormLibSharp.Native
|
||||
IntPtr pvFileInfo,
|
||||
SFileInfoClass infoClass
|
||||
);
|
||||
|
||||
#endregion
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
@@ -231,6 +250,7 @@ namespace StormLibSharp.Native
|
||||
#endregion
|
||||
|
||||
#region Functions for file and archive verification
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileGetFileChecksums(
|
||||
MpqArchiveSafeHandle? hMpq,
|
||||
@@ -255,9 +275,11 @@ namespace StormLibSharp.Native
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileVerifyArchive(MpqArchiveSafeHandle? hMpq);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functions for file searching
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern IntPtr SFileFindFirstFile(
|
||||
MpqArchiveSafeHandle? hMpq,
|
||||
@@ -291,9 +313,11 @@ namespace StormLibSharp.Native
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SListFileFindClose(IntPtr hFind);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Locale support
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SFileEnumLocales(
|
||||
MpqArchiveSafeHandle? hMpq,
|
||||
@@ -302,9 +326,11 @@ namespace StormLibSharp.Native
|
||||
ref uint pdwMaxLocales,
|
||||
uint dwSearchScope
|
||||
);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Support for adding files to the MPQ
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCreateFile(
|
||||
MpqArchiveSafeHandle? hMpq,
|
||||
@@ -383,9 +409,11 @@ namespace StormLibSharp.Native
|
||||
SFILE_ADDFILE_CALLBACK AddFileCB,
|
||||
IntPtr pvUserData
|
||||
);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Compression and decompression
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SCompImplode(
|
||||
IntPtr pvOutBuffer,
|
||||
@@ -429,11 +457,10 @@ namespace StormLibSharp.Native
|
||||
int cbInBuffer
|
||||
);
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#pragma warning disable 0169,0649
|
||||
#pragma warning disable CS0169
|
||||
internal struct SFILE_CREATE_MPQ
|
||||
{
|
||||
public uint cbSize;
|
||||
@@ -448,6 +475,7 @@ namespace StormLibSharp.Native
|
||||
public uint dwRawChunkSize;
|
||||
public uint dwMaxFileCount;
|
||||
}
|
||||
#pragma warning restore CS0169
|
||||
|
||||
internal unsafe struct _SFILE_FIND_DATA
|
||||
{
|
||||
@@ -489,6 +517,4 @@ namespace StormLibSharp.Native
|
||||
public uint dwFileKey;
|
||||
public uint dwFilePos;
|
||||
}
|
||||
#pragma warning restore 0169,0649
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user