mirror of
https://github.com/MobileTooling/Ffu2Vhdx.git
synced 2026-07-27 12:48:20 -07:00
Further Refactoring/Cleanup
This commit is contained in:
@@ -8,8 +8,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageCommon", "ImageCommon\
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageStorageServiceManaged", "ImageStorageServiceManaged\ImageStorageServiceManaged.csproj", "{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PkgToolBox", "PkgToolBox\PkgToolBox.csproj", "{7C88E232-991D-44AB-8F2B-FA59C58FCD11}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscUtils.Core", "DiscUtils\DiscUtils.Core\DiscUtils.Core.csproj", "{A76FBCBD-08EB-413D-8DD7-8264D4E50304}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscUtils.Streams", "DiscUtils\DiscUtils.Streams\DiscUtils.Streams.csproj", "{37E19DC2-07BE-4E1E-8878-7A7BA28F5D45}"
|
||||
@@ -94,26 +92,6 @@ Global
|
||||
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Release|x64.Build.0 = Release|x64
|
||||
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Release|x86.ActiveCfg = Release|x86
|
||||
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Release|x86.Build.0 = Release|x86
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Debug|ARM32.ActiveCfg = Debug|ARM32
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Debug|ARM32.Build.0 = Debug|ARM32
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Debug|x64.Build.0 = Debug|x64
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Debug|x86.Build.0 = Debug|x86
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Release|ARM32.ActiveCfg = Release|ARM32
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Release|ARM32.Build.0 = Release|ARM32
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Release|x64.ActiveCfg = Release|x64
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Release|x64.Build.0 = Release|x64
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Release|x86.ActiveCfg = Release|x86
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11}.Release|x86.Build.0 = Release|x86
|
||||
{A76FBCBD-08EB-413D-8DD7-8264D4E50304}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A76FBCBD-08EB-413D-8DD7-8264D4E50304}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A76FBCBD-08EB-413D-8DD7-8264D4E50304}.Debug|ARM32.ActiveCfg = Debug|ARM32
|
||||
@@ -181,7 +159,6 @@ Global
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{8CA492CB-6F12-4862-991C-B28468172730} = {6B6B2266-D083-4F82-9A0A-4A2D8D8F3F16}
|
||||
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16} = {6B6B2266-D083-4F82-9A0A-4A2D8D8F3F16}
|
||||
{7C88E232-991D-44AB-8F2B-FA59C58FCD11} = {6B6B2266-D083-4F82-9A0A-4A2D8D8F3F16}
|
||||
{A76FBCBD-08EB-413D-8DD7-8264D4E50304} = {A431EF08-BBEF-4228-A12D-88149C3844F6}
|
||||
{37E19DC2-07BE-4E1E-8878-7A7BA28F5D45} = {A431EF08-BBEF-4228-A12D-88149C3844F6}
|
||||
{77D1F20E-4CD6-4810-9C5C-EF6CA3A9BC53} = {A431EF08-BBEF-4228-A12D-88149C3844F6}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
using Microsoft.WindowsPhone.Imaging;
|
||||
|
||||
namespace Ffu2Vhdx
|
||||
{
|
||||
internal class FfuFile
|
||||
{
|
||||
private readonly FullFlashUpdateImage ffuImage;
|
||||
|
||||
private readonly PayloadReader payloadReader;
|
||||
|
||||
public FfuFile(Stream stream)
|
||||
{
|
||||
ffuImage = new(stream);
|
||||
Stream imageStream = ffuImage.GetImageStream();
|
||||
payloadReader = new(imageStream);
|
||||
|
||||
if (payloadReader.Payloads.Count() != ffuImage.StoreCount)
|
||||
{
|
||||
throw new ImageStorageException("Store counts in metadata and store header do not match.");
|
||||
}
|
||||
}
|
||||
|
||||
public int StoreCount => ffuImage.StoreCount;
|
||||
|
||||
public void WriteStoreToStream(int StoreIndex, Stream outputStream)
|
||||
{
|
||||
if (StoreIndex >= StoreCount || StoreIndex < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(StoreIndex));
|
||||
}
|
||||
|
||||
FullFlashUpdateStore fullFlashUpdateStore = ffuImage.Stores[StoreIndex];
|
||||
StorePayload storePayload = payloadReader.Payloads[StoreIndex];
|
||||
|
||||
payloadReader.WriteToStream(outputStream, storePayload, fullFlashUpdateStore.MinSectorCount, fullFlashUpdateStore.SectorSize);
|
||||
}
|
||||
|
||||
public uint GetMinSectorCount(int StoreIndex)
|
||||
{
|
||||
if (StoreIndex >= StoreCount || StoreIndex < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(StoreIndex));
|
||||
}
|
||||
|
||||
FullFlashUpdateStore fullFlashUpdateStore = ffuImage.Stores[StoreIndex];
|
||||
return fullFlashUpdateStore.MinSectorCount;
|
||||
}
|
||||
|
||||
public uint GetSectorSize(int StoreIndex)
|
||||
{
|
||||
if (StoreIndex >= StoreCount || StoreIndex < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(StoreIndex));
|
||||
}
|
||||
|
||||
FullFlashUpdateStore fullFlashUpdateStore = ffuImage.Stores[StoreIndex];
|
||||
return fullFlashUpdateStore.SectorSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-14
@@ -2,6 +2,7 @@
|
||||
using DiscUtils;
|
||||
using DiscUtils.Streams;
|
||||
using DiscUtils.Vhdx;
|
||||
using System.Text;
|
||||
|
||||
namespace Ffu2Vhdx
|
||||
{
|
||||
@@ -37,26 +38,19 @@ namespace Ffu2Vhdx
|
||||
{
|
||||
DiscUtils.Setup.SetupHelper.RegisterAssembly(typeof(Disk).Assembly);
|
||||
|
||||
FullFlashUpdateImage ffuImage = new(ffuPath);
|
||||
using FileStream imageStream = ffuImage.GetImageStream();
|
||||
PayloadReader payloadReader = new(imageStream);
|
||||
if (payloadReader.Payloads.Count() != ffuImage.StoreCount)
|
||||
{
|
||||
throw new ImageStorageException("Store counts in metadata and store header do not match.");
|
||||
}
|
||||
using FileStream ffuStream = File.OpenRead(ffuPath);
|
||||
FfuFile ffuFile = new(ffuStream);
|
||||
|
||||
for (int i = 0; i < ffuImage.StoreCount; i++)
|
||||
for (int i = 0; i < ffuFile.StoreCount; i++)
|
||||
{
|
||||
FullFlashUpdateStore fullFlashUpdateStore = ffuImage.Stores[i];
|
||||
StorePayload storePayload = payloadReader.Payloads[i];
|
||||
|
||||
string vhdfile = Path.Combine(outputDirectory, $"LUN{i}.vhdx");
|
||||
Console.WriteLine($"Dumping {vhdfile}...");
|
||||
|
||||
long diskCapacity = (long)fullFlashUpdateStore.MinSectorCount * fullFlashUpdateStore.SectorSize;
|
||||
long diskCapacity = (long)ffuFile.GetMinSectorCount(i) * ffuFile.GetSectorSize(i);
|
||||
using Stream fs = new FileStream(vhdfile, FileMode.CreateNew, FileAccess.ReadWrite);
|
||||
using VirtualDisk outDisk = Disk.InitializeDynamic(fs, Ownership.None, diskCapacity, logicalSectorSize: (int)fullFlashUpdateStore.SectorSize);
|
||||
payloadReader.WriteToStream(outDisk.Content, storePayload, fullFlashUpdateStore.MinSectorCount, fullFlashUpdateStore.SectorSize);
|
||||
using VirtualDisk outDisk = Disk.InitializeDynamic(fs, Ownership.None, diskCapacity, logicalSectorSize: (int)ffuFile.GetSectorSize(i));
|
||||
|
||||
ffuFile.WriteStoreToStream(i, outDisk.Content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,23 @@
|
||||
using Microsoft.Composition.ToolBox.IO;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.WindowsPhone.Imaging
|
||||
{
|
||||
[DefaultMember("Item")]
|
||||
public class FullFlashUpdateImage
|
||||
{
|
||||
public FullFlashUpdateImage()
|
||||
private readonly Stream imageStream;
|
||||
|
||||
public FullFlashUpdateImage(Stream imageStream)
|
||||
{
|
||||
this.imageStream = imageStream;
|
||||
|
||||
_ffuStoragePools = new List<FullFlashUpdateStoragePool>();
|
||||
_ffuStores = new List<FullFlashUpdateStore>();
|
||||
}
|
||||
|
||||
public FullFlashUpdateImage(string A_1) : this()
|
||||
{
|
||||
if (!FileToolBox.Exists(A_1))
|
||||
{
|
||||
throw new ImageCommonException(CodeSite.StorageService, ErrorCategory.MissingArtifact, "The FFU file '" + A_1 + "' does not exist.");
|
||||
}
|
||||
_imagePath = PathToolBox.GetFullPath(A_1);
|
||||
using FileStream imageStream = GetImageStream();
|
||||
using BinaryReader binaryReader = new(imageStream);
|
||||
using BinaryReader binaryReader = new(imageStream, Encoding.UTF8, true);
|
||||
uint num = binaryReader.ReadUInt32();
|
||||
byte[] signature = binaryReader.ReadBytes(12);
|
||||
if (num != FullFlashUpdateHeaders.SecurityHeaderSize || !SecurityHeader.ValidateSignature(signature))
|
||||
@@ -58,11 +51,10 @@ namespace Microsoft.WindowsPhone.Imaging
|
||||
_payloadOffset = imageStream.Position;
|
||||
}
|
||||
|
||||
public FileStream GetImageStream()
|
||||
public Stream GetImageStream()
|
||||
{
|
||||
FileStream fileStream = FileToolBox.Stream(_imagePath);
|
||||
fileStream.Position = _payloadOffset;
|
||||
return fileStream;
|
||||
imageStream.Position = _payloadOffset;
|
||||
return imageStream;
|
||||
}
|
||||
|
||||
internal void AddStoragePool(ManifestCategory A_1)
|
||||
@@ -148,14 +140,10 @@ namespace Microsoft.WindowsPhone.Imaging
|
||||
|
||||
private readonly List<FullFlashUpdateStore> _ffuStores;
|
||||
|
||||
private readonly string _imagePath;
|
||||
|
||||
private readonly long _payloadOffset;
|
||||
|
||||
private readonly ImageHeaderEx _imageHeader = new();
|
||||
|
||||
private SecurityHeader _securityHeader;
|
||||
|
||||
private readonly uint _defaultPartititionByteAlignment = 65536U;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Composition.ToolBox.IO;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.WindowsPhone.Imaging
|
||||
@@ -18,9 +17,6 @@ namespace Microsoft.WindowsPhone.Imaging
|
||||
|
||||
private void Initialize(FullFlashUpdateImage A_1, FullFlashUpdateStoragePool A_2, string A_3, string A_4, bool A_5, bool A_6, string A_7, string A_8, bool A_9, uint A_10, uint A_11)
|
||||
{
|
||||
_tempBackingStorePath = PathToolBox.GetTemporaryPath();
|
||||
DirectoryToolBox.CreateDirectory(_tempBackingStorePath);
|
||||
_tempBackingStoreFile = PathToolBox.Combine(_tempBackingStorePath, "FFUBackingStore");
|
||||
Image = A_1;
|
||||
StoragePool = A_2;
|
||||
Id = A_3;
|
||||
@@ -55,14 +51,6 @@ namespace Microsoft.WindowsPhone.Imaging
|
||||
{
|
||||
Partitions = null;
|
||||
}
|
||||
try
|
||||
{
|
||||
DirectoryToolBox.Delete(_tempBackingStorePath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Warning: ImageCommon!Dispose: Failed to delete temporary backing store directory/file '" + _tempBackingStorePath + "' with exception: " + ex.Message);
|
||||
}
|
||||
_alreadyDisposed = true;
|
||||
}
|
||||
|
||||
@@ -245,10 +233,6 @@ namespace Microsoft.WindowsPhone.Imaging
|
||||
|
||||
private uint _sectorsUsed;
|
||||
|
||||
private string _tempBackingStoreFile = string.Empty;
|
||||
|
||||
private string _tempBackingStorePath = string.Empty;
|
||||
|
||||
private bool _alreadyDisposed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,4 @@
|
||||
<AssemblyVersion>0.0.0.0</AssemblyVersion>
|
||||
<Platforms>x64;AnyCPU;ARM32;ARM64;x86</Platforms>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\PkgToolBox\PkgToolBox.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -6,7 +6,7 @@ namespace Microsoft.WindowsPhone.Imaging
|
||||
{
|
||||
public class PayloadReader
|
||||
{
|
||||
public PayloadReader(FileStream fileStream)
|
||||
public PayloadReader(Stream fileStream)
|
||||
{
|
||||
_payloadStream = fileStream;
|
||||
_payloadOffsets = new List<PayloadOffset>();
|
||||
@@ -115,7 +115,7 @@ namespace Microsoft.WindowsPhone.Imaging
|
||||
|
||||
private readonly List<PayloadOffset> _payloadOffsets;
|
||||
|
||||
private readonly FileStream _payloadStream;
|
||||
private readonly Stream _payloadStream;
|
||||
|
||||
private class PayloadOffset
|
||||
{
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Composition.ToolBox.IO
|
||||
{
|
||||
public static class DirectoryToolBox
|
||||
{
|
||||
public static bool Exists(string A_0)
|
||||
{
|
||||
return LongPathIO.Exists(A_0, LongPathIO.SystemType.Directory) || IsDriveRoot(A_0);
|
||||
}
|
||||
|
||||
public static void CreateDirectory(string A_0)
|
||||
{
|
||||
Create(A_0);
|
||||
}
|
||||
|
||||
private static bool IsVolumeGuidPath(string A_0)
|
||||
{
|
||||
int length = "\\\\?\\Volume{205ebf40-0ede-47c6-adc8-3cbf3826b843}".Length;
|
||||
int length2 = "\\\\?\\Volume".Length;
|
||||
|
||||
return A_0.Length == length && (A_0.StartsWithIgnoreCase("\\\\?\\Volume") || A_0.StartsWithIgnoreCase("\\\\.\\Volume")) && Guid.TryParse(A_0[length2..], out _);
|
||||
}
|
||||
|
||||
public static bool IsDriveRoot(string A_0)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(A_0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
string rootDirectory = GetRootDirectory(A_0);
|
||||
return A_0.CompareTo(rootDirectory) == 0 || A_0.CompareTo(rootDirectory + "\\") == 0;
|
||||
}
|
||||
|
||||
public static void Create(string A_0)
|
||||
{
|
||||
string text = A_0;
|
||||
LinkedList<string> linkedList = new();
|
||||
while (!Exists(text) && !IsVolumeGuidPath(text))
|
||||
{
|
||||
_ = linkedList.AddFirst(text);
|
||||
text = GetDirectoryFromFilePath(text);
|
||||
}
|
||||
foreach (string text2 in linkedList)
|
||||
{
|
||||
bool flag = NativeMethods.CreateDirectory(LongPathIO.UNCPath(text2), nint.Zero) != 0;
|
||||
int lastWin32Error = Marshal.GetLastWin32Error();
|
||||
if (!flag && lastWin32Error != 183)
|
||||
{
|
||||
throw new Exception(string.Format("Failed to create directory at {0}, GLE = {1}", text2, lastWin32Error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Delete(string A_0)
|
||||
{
|
||||
string text = LongPathIO.UNCPath(A_0);
|
||||
if (!Exists(text))
|
||||
{
|
||||
return;
|
||||
}
|
||||
nint intPtr = NativeMethods.FindFirstFile(Path.Combine(text, "*.*"), out NativeMethods.WIN32_FIND_DATA win32_FIND_DATA, out int num);
|
||||
try
|
||||
{
|
||||
if (intPtr == LongPathIO.InvalidHandleValue)
|
||||
{
|
||||
if (!LongPathIO.IsDirectory(text))
|
||||
{
|
||||
throw new DirectoryNotFoundException(string.Format("DirectoryToolBox::Delete Target '{0}' is not a directory.", text));
|
||||
}
|
||||
throw new Exception(string.Format("DirectoryToolBox::Paths Native FindFirstFile failed to load '{0}'. Error={1}", A_0, num));
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!win32_FIND_DATA.cFileName.EqualsIgnoreCase(".") && !win32_FIND_DATA.cFileName.EqualsIgnoreCase(".."))
|
||||
{
|
||||
if (LongPathIO.IsFile(win32_FIND_DATA.dwFileAttributes))
|
||||
{
|
||||
FileToolBox.Delete(PathToolBox.Combine(A_0, win32_FIND_DATA.cFileName));
|
||||
}
|
||||
else
|
||||
{
|
||||
Delete(PathToolBox.Combine(A_0, win32_FIND_DATA.cFileName));
|
||||
}
|
||||
}
|
||||
}
|
||||
while (NativeMethods.FindNextFile(intPtr, out win32_FIND_DATA) != 0);
|
||||
string text2 = LongPathIO.UNCPath(text);
|
||||
_ = NativeMethods.SetFileAttributes(text2, NativeMethods.EFileAttributes.Normal);
|
||||
if (NativeMethods.RemoveDirectory(text2) == 0)
|
||||
{
|
||||
throw new Exception(string.Format("Kernel32 failed to delete directory '{0}'. Error={1}", text, Marshal.GetLastWin32Error()));
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (LongPathIO.ValidHandle(intPtr))
|
||||
{
|
||||
_ = NativeMethods.FindClose(intPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetDirectoryFromFilePath(string A_0)
|
||||
{
|
||||
if (LongPathIO.IsDirectory(A_0))
|
||||
{
|
||||
return A_0;
|
||||
}
|
||||
int num = A_0.LastIndexOfIgnoreCase("\\");
|
||||
return num == -1 ? string.Empty : A_0[..num];
|
||||
}
|
||||
|
||||
public static string GetRootDirectory(string A_0)
|
||||
{
|
||||
string text = LongPathIO.StripUNCPrefix(A_0);
|
||||
string str = A_0[..^text.Length];
|
||||
if (!text.Contains("\\"))
|
||||
{
|
||||
return str + text;
|
||||
}
|
||||
string str2 = text[..text.IndexOfIgnoreCase("\\")];
|
||||
return str + str2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Composition.ToolBox.IO
|
||||
{
|
||||
public static class FileToolBox
|
||||
{
|
||||
public static bool Exists(string A_0)
|
||||
{
|
||||
return LongPathIO.Exists(A_0, LongPathIO.SystemType.File);
|
||||
}
|
||||
|
||||
public static void Delete(string A_0)
|
||||
{
|
||||
if (!Exists(A_0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
_ = NativeMethods.SetFileAttributes(LongPathIO.UNCPath(A_0), NativeMethods.EFileAttributes.Normal);
|
||||
if (NativeMethods.DeleteFile(LongPathIO.UNCPath(A_0)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
int lastWin32Error = Marshal.GetLastWin32Error();
|
||||
if (LongPathIO.IsDirectory(A_0))
|
||||
{
|
||||
throw new Exception(string.Format("FileToolBox::Delete: FileToolBox was used instead of DirectoryToolBox to delete directory '{0}'.", A_0));
|
||||
}
|
||||
throw new Exception(string.Format("FileToolBox::Delete: Native delete file failed to delete '{0}'. Error={1}", A_0, lastWin32Error));
|
||||
}
|
||||
|
||||
internal static bool FileModeRequiresFile(FileMode A_0)
|
||||
{
|
||||
return A_0 switch
|
||||
{
|
||||
FileMode.Open => true,
|
||||
FileMode.Truncate => true,
|
||||
FileMode.Append => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
internal static NativeMethods.ECreationDisposition FileModeToNativeCreationDisposition(FileMode A_0)
|
||||
{
|
||||
NativeMethods.ECreationDisposition result = A_0 switch
|
||||
{
|
||||
FileMode.CreateNew => NativeMethods.ECreationDisposition.CreateNew,
|
||||
FileMode.Create => NativeMethods.ECreationDisposition.CreateAlways,
|
||||
FileMode.Open => NativeMethods.ECreationDisposition.OpenExisting,
|
||||
FileMode.OpenOrCreate => NativeMethods.ECreationDisposition.OpenAlways,
|
||||
FileMode.Truncate => NativeMethods.ECreationDisposition.OpenAlways,
|
||||
FileMode.Append => NativeMethods.ECreationDisposition.OpenExisting,
|
||||
_ => throw new InvalidEnumArgumentException(string.Format("Invalid value for mode of type System.IO.FileMode: {0}", A_0)),
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
public static FileStream Stream(string A_0, FileMode A_1, FileAccess A_2)
|
||||
{
|
||||
string text = LongPathIO.UNCPath(A_0);
|
||||
if (A_1 is FileMode.Append or FileMode.Truncate)
|
||||
{
|
||||
throw new NotSupportedException(string.Format("FileToolBox::Stream: FileMode: {0} is not supported.", A_1));
|
||||
}
|
||||
if (FileMode.CreateNew == A_1 && Exists(text))
|
||||
{
|
||||
throw new IOException("FileToolBox::Stream: File '" + text + "' already exists.");
|
||||
}
|
||||
if (FileModeRequiresFile(A_1))
|
||||
{
|
||||
if (!Exists(text))
|
||||
{
|
||||
throw new FileNotFoundException("FileToolBox::Stream: File '" + text + "' was not found on disk.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DirectoryToolBox.Create(DirectoryToolBox.GetDirectoryFromFilePath(text));
|
||||
}
|
||||
NativeMethods.EFileShare dwShareMode = NativeMethods.EFileShare.All;
|
||||
NativeMethods.EFileAccess efileAccess = NativeMethods.EFileAccess.None;
|
||||
NativeMethods.ECreationDisposition dwCreationDisposition = FileModeToNativeCreationDisposition(A_1);
|
||||
if (A_2 is FileAccess.Read or FileAccess.ReadWrite)
|
||||
{
|
||||
efileAccess |= (NativeMethods.EFileAccess)2147483648U;
|
||||
}
|
||||
if (A_2 is FileAccess.Write or FileAccess.ReadWrite)
|
||||
{
|
||||
efileAccess |= NativeMethods.EFileAccess.GenericWrite;
|
||||
}
|
||||
SafeFileHandle safeFileHandle = NativeMethods.CreateFile(text, efileAccess, dwShareMode, nint.Zero, dwCreationDisposition, NativeMethods.EFileAttributes.BackupSemantics, nint.Zero);
|
||||
return safeFileHandle.IsInvalid
|
||||
? throw new Win32Exception(Marshal.GetLastWin32Error(), "File: " + text)
|
||||
: new FileStream(safeFileHandle, A_2);
|
||||
}
|
||||
|
||||
public static FileStream Stream(string A_0)
|
||||
{
|
||||
return Stream(A_0, FileMode.Open, FileAccess.Read);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Composition.ToolBox.IO
|
||||
{
|
||||
public static class LongPathIO
|
||||
{
|
||||
public static string StripUNCPrefix(string A_0)
|
||||
{
|
||||
if (A_0.StartsWithIgnoreCase("\\\\?\\UNC\\"))
|
||||
{
|
||||
string str = A_0["\\\\?\\UNC\\".Length..];
|
||||
return "\\\\" + str;
|
||||
}
|
||||
return A_0.StartsWithIgnoreCase("\\\\?\\") ? A_0["\\\\?\\".Length..] : A_0;
|
||||
}
|
||||
|
||||
internal static string UNCPath(string A_0)
|
||||
{
|
||||
if (string.IsNullOrEmpty(A_0))
|
||||
{
|
||||
throw new ArgumentException("filename cannot be an empty string", "filename");
|
||||
}
|
||||
StringBuilder stringBuilder = new(260);
|
||||
int fullPathName = NativeMethods.GetFullPathName(A_0, stringBuilder.Capacity, stringBuilder, null);
|
||||
if (stringBuilder.Length < fullPathName)
|
||||
{
|
||||
_ = stringBuilder.EnsureCapacity(fullPathName);
|
||||
_ = NativeMethods.GetFullPathName(A_0, stringBuilder.Capacity, stringBuilder, null);
|
||||
}
|
||||
string text = stringBuilder.ToString();
|
||||
if (!text.StartsWithIgnoreCase("\\\\.\\") && !text.StartsWithIgnoreCase("\\\\?\\") && !text.StartsWithIgnoreCase("\\\\?\\\\\\?\\UNC\\"))
|
||||
{
|
||||
text = text.StartsWithIgnoreCase("\\\\")
|
||||
? "\\\\?\\UNC\\" + text.TrimStart(new char[]
|
||||
{
|
||||
'\\'
|
||||
})
|
||||
: "\\\\?\\" + text;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
internal static bool Exists(string A_0, SystemType A_1)
|
||||
{
|
||||
string lpFileName = UNCPath(A_0);
|
||||
uint fileAttributes;
|
||||
try
|
||||
{
|
||||
fileAttributes = NativeMethods.GetFileAttributes(lpFileName);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new FormatException(string.Format("LongPathIO::Exists: Could not get the attributes of file '{0}'", A_0));
|
||||
}
|
||||
return A_1 == SystemType.File ? IsFile((FileAttributes)fileAttributes) : IsDirectory((FileAttributes)fileAttributes);
|
||||
}
|
||||
|
||||
internal static bool IsDirectory(string A_0)
|
||||
{
|
||||
string lpFileName = UNCPath(A_0);
|
||||
uint fileAttributes;
|
||||
try
|
||||
{
|
||||
fileAttributes = NativeMethods.GetFileAttributes(lpFileName);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new FormatException(string.Format("LongPathIO::IsDirectory: Could not get the attributes of file '{0}'", A_0));
|
||||
}
|
||||
return IsDirectory((FileAttributes)fileAttributes);
|
||||
}
|
||||
|
||||
internal static bool IsDirectory(FileAttributes A_0)
|
||||
{
|
||||
return (A_0 & FileAttributes.Directory) == FileAttributes.Directory && A_0 != (FileAttributes)(-1);
|
||||
}
|
||||
|
||||
internal static bool IsFile(FileAttributes A_0)
|
||||
{
|
||||
return (A_0 & FileAttributes.Directory) != FileAttributes.Directory && A_0 != (FileAttributes)(-1);
|
||||
}
|
||||
|
||||
internal static bool ValidHandle(nint A_0)
|
||||
{
|
||||
return A_0 != NullHandleValue && A_0 != InvalidHandleValue;
|
||||
}
|
||||
|
||||
internal static nint InvalidHandleValue = new(-1);
|
||||
|
||||
internal static nint NullHandleValue = new(0);
|
||||
|
||||
internal enum SystemType
|
||||
{
|
||||
File,
|
||||
Directory
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Composition.ToolBox.IO
|
||||
{
|
||||
internal class NativeMethods
|
||||
{
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||
[return: MarshalAs(UnmanagedType.U4)]
|
||||
public static extern int GetFullPathName(string inPath, int stringSize, StringBuilder longPath, StringBuilder fileName);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||
public static extern uint GetFileAttributes(string lpFileName);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern bool DeleteFile(string lpExistingFileName);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern bool SetFileAttributes(string lpExistingFileName, EFileAttributes dwFlagsAndAttributes);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern nint FindFirstFileEx(string lpFileName, int fInfoLevelId, out WIN32_FIND_DATA lpFindFileData, int fSearchOp, nint lpSearchFilter, uint dwAdditionalFlags);
|
||||
|
||||
public static nint FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData, out int win32Error)
|
||||
{
|
||||
nint result = FindFirstFileEx(lpFileName, 1, out lpFindFileData, 0, nint.Zero, 0U);
|
||||
win32Error = Marshal.GetLastWin32Error();
|
||||
return result;
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||
public static extern int FindNextFile(nint hFindFile, out WIN32_FIND_DATA lpFindFileData);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool FindClose(nint hFindFile);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern int CreateDirectory(string pszPath, nint psa);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern int RemoveDirectory(string pszPath);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
private static extern int GetFileAttributesEx(string lpFileName, int fInfoLevelId, out WIN32_FIND_DATA lpFileInformation);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern SafeFileHandle CreateFile(string lpFileName, EFileAccess dwDesiredAccess, EFileShare dwShareMode, nint lpSecurityAttributes, ECreationDisposition dwCreationDisposition, EFileAttributes dwFlagsAndAttributes, nint hTemplateFile);
|
||||
|
||||
internal const int MAX_PATH = 260;
|
||||
|
||||
internal const int COMPRESS_ALGORITHM_MSZIP = 2;
|
||||
|
||||
internal const int COMPRESS_ALGORITHM_XPRESS = 3;
|
||||
|
||||
internal const int COMPRESS_ALGORITHM_XPRESS_HUFF = 4;
|
||||
|
||||
internal const int COMPRESS_ALGORITHM_LZMS = 5;
|
||||
|
||||
internal enum ECreationDisposition : uint
|
||||
{
|
||||
CreateNew = 1U,
|
||||
CreateAlways,
|
||||
OpenExisting,
|
||||
OpenAlways,
|
||||
TruncateExisting
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum EFileAccess : uint
|
||||
{
|
||||
None = 0U,
|
||||
GenericRead = 2147483648U,
|
||||
GenericWrite = 1073741824U,
|
||||
GenericExecute = 536870912U,
|
||||
GenericAll = 268435456U
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum EFileAttributes : uint
|
||||
{
|
||||
None = 0U,
|
||||
Readonly = 1U,
|
||||
Hidden = 2U,
|
||||
System = 4U,
|
||||
Directory = 16U,
|
||||
Archive = 32U,
|
||||
Device = 64U,
|
||||
Normal = 128U,
|
||||
Temporary = 256U,
|
||||
SparseFile = 512U,
|
||||
ReparsePoint = 1024U,
|
||||
Compressed = 2048U,
|
||||
Offline = 4096U,
|
||||
NotContentIndexed = 8192U,
|
||||
Encrypted = 16384U,
|
||||
Write_Through = 2147483648U,
|
||||
Overlapped = 1073741824U,
|
||||
NoBuffering = 536870912U,
|
||||
RandomAccess = 268435456U,
|
||||
SequentialScan = 134217728U,
|
||||
DeleteOnClose = 67108864U,
|
||||
BackupSemantics = 33554432U,
|
||||
PosixSemantics = 16777216U,
|
||||
OpenReparsePoint = 2097152U,
|
||||
OpenNoRecall = 1048576U,
|
||||
FirstPipeInstance = 524288U
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum EFileShare : uint
|
||||
{
|
||||
None = 0U,
|
||||
Read = 1U,
|
||||
Write = 2U,
|
||||
Delete = 4U,
|
||||
All = 7U
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
internal struct WIN32_FIND_DATA
|
||||
{
|
||||
internal FileAttributes dwFileAttributes;
|
||||
|
||||
internal FILETIME ftCreationTime;
|
||||
|
||||
internal FILETIME ftLastAccessTime;
|
||||
|
||||
internal FILETIME ftLastWriteTime;
|
||||
|
||||
internal uint nFileSizeHigh;
|
||||
|
||||
internal uint nFileSizeLow;
|
||||
|
||||
internal int dwReserved0;
|
||||
|
||||
internal int dwReserved1;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
|
||||
internal string cFileName;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
|
||||
internal string cAlternate;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.Composition.ToolBox.IO
|
||||
{
|
||||
public static class PathToolBox
|
||||
{
|
||||
public static string GetFullPath(string A_0)
|
||||
{
|
||||
return LongPathIO.UNCPath(A_0);
|
||||
}
|
||||
|
||||
public static string Combine(string A_0, string A_1)
|
||||
{
|
||||
A_0 = A_0.TrimEnd(new char[]
|
||||
{
|
||||
'\\'
|
||||
});
|
||||
A_1 = A_1.TrimStart(new char[]
|
||||
{
|
||||
'\\'
|
||||
});
|
||||
return A_0 + "\\" + A_1;
|
||||
}
|
||||
|
||||
public static string GetTemporaryPath()
|
||||
{
|
||||
return GetTempPath();
|
||||
}
|
||||
|
||||
public static string GetTempPath()
|
||||
{
|
||||
DirectoryToolBox.Create(TemporaryDirectoryHandler.TempPathRoot);
|
||||
return Combine(TemporaryDirectoryHandler.TempPathRoot, Path.GetRandomFileName());
|
||||
}
|
||||
|
||||
public static class TemporaryDirectoryHandler
|
||||
{
|
||||
internal static string TempPathRoot => Combine(TempPathPartialRoot, Thread.CurrentThread.ManagedThreadId.ToString());
|
||||
|
||||
private static readonly Destructor Finalize = new();
|
||||
|
||||
internal static string TempPathPartialRoot = Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||
|
||||
internal static bool enforcementEnabled = Environment.GetEnvironmentVariable("OFFICIAL_BUILD_MACHINE") == null;
|
||||
|
||||
private sealed class Destructor
|
||||
{
|
||||
~Destructor()
|
||||
{
|
||||
if (enforcementEnabled && DirectoryToolBox.Exists(TempPathRoot))
|
||||
{
|
||||
throw new Exception("Users of temporary paths must call PathToolBox.CleanupTempDirectories() before exiting, this was leaked: " + TempPathRoot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>Microsoft.Composition.ToolBox</RootNamespace>
|
||||
<Company>Microsoft Corporation</Company>
|
||||
<Copyright>Copyright %28c%29 Microsoft Corporation. All rights reserved.</Copyright>
|
||||
<Product>Microsoft %28R%29 Windows %28R%29 Operating System</Product>
|
||||
<AssemblyVersion>0.0.0.0</AssemblyVersion>
|
||||
<Platforms>x64;AnyCPU;ARM32;ARM64;x86</Platforms>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -1,27 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Composition.ToolBox
|
||||
{
|
||||
public static class StringExtensions
|
||||
{
|
||||
public static bool EqualsIgnoreCase(this string A_0, string A_1)
|
||||
{
|
||||
return string.Equals(A_0, A_1, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public static bool StartsWithIgnoreCase(this string A_0, string A_1)
|
||||
{
|
||||
return A_0.StartsWith(A_1, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public static int IndexOfIgnoreCase(this string A_0, string A_1)
|
||||
{
|
||||
return A_0.IndexOf(A_1, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public static int LastIndexOfIgnoreCase(this string A_0, string A_1)
|
||||
{
|
||||
return A_0.LastIndexOf(A_1, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user