Skip to content

Code Quality: Introduced the new NativeStorable #16307

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions src/Files.App.Storage/Files.App.Storage.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,24 @@
<TargetFramework>net8.0-windows10.0.22621.0</TargetFramework>
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<IsTrimmable>true</IsTrimmable>
<Configurations>Debug;Release;Stable;Preview;Store</Configurations>
<Platforms>x86;x64;arm64</Platforms>
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
<DefineConstants Condition="'$(Configuration)' == 'Debug'">TRACE;DEBUG;NETFX_CORE</DefineConstants>
<DefineConstants Condition="'$(Configuration)' != 'Debug'">TRACE;RELEASE;NETFX_CORE</DefineConstants>
<Optimize Condition="'$(Configuration)' != 'Debug'">true</Optimize>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FluentFTP" Version="43.0.1" />
</ItemGroup>

<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<DefineConstants>TRACE;DEBUG;NETFX_CORE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' != 'Debug'">
<DefineConstants>TRACE;RELEASE;NETFX_CORE</DefineConstants>
<Optimize>true</Optimize>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Files.App.CsWin32\Files.App.CsWin32.csproj" />
<ProjectReference Include="..\Files.Core.Storage\Files.Core.Storage.csproj" />
<ProjectReference Include="..\Files.Shared\Files.Shared.csproj" />
</ItemGroup>

</Project>
</Project>
12 changes: 12 additions & 0 deletions src/Files.App.Storage/Storables/Archive/ArchiveFile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

namespace Files.App.Storage.Storables
{
/// <summary>
/// Represents a file that is powered by SevenZipSharp and 7zip.
/// </summary>
public class ArchiveFile : ArchiveStorable/*, IFile*/
{
}
}
12 changes: 12 additions & 0 deletions src/Files.App.Storage/Storables/Archive/ArchiveFolder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

namespace Files.App.Storage.Storables
{
/// <summary>
/// Represents a folder that is powered by SevenZipSharp and 7zip.
/// </summary>
public class ArchiveFolder : ArchiveStorable/*, IFolder*/
{
}
}
12 changes: 12 additions & 0 deletions src/Files.App.Storage/Storables/Archive/ArchiveFolderView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

namespace Files.App.Storage.Storables
{
/// <summary>
/// Represents a folder view that is powered by SevenZipSharp and 7zip.
/// </summary>
public class ArchiveFolderView : IFolderView
{
}
}
24 changes: 24 additions & 0 deletions src/Files.App.Storage/Storables/Archive/ArchiveStorable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

using System.Runtime.InteropServices;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.System.Com;
using Windows.Win32.UI.Shell;

namespace Files.App.Storage.Storables
{
/// <inheritdoc cref="IArchiveStorable"/>
public abstract class ArchiveStorable : IArchiveStorable
{
/// <inheritdoc/>
public string Path { get; protected set; }

/// <inheritdoc/>
public string Name { get; protected set; }

/// <inheritdoc/>
public string Id { get; protected set; }
}
}
12 changes: 12 additions & 0 deletions src/Files.App.Storage/Storables/Archive/IArchiveStorable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

namespace Files.App.Storage.Storables
{
/// <summary>
/// Represents a storable that is powered by SevenZipSharp and 7zip.
/// </summary>
public interface IArchiveStorable : IStorable
{
}
}
13 changes: 13 additions & 0 deletions src/Files.App.Storage/Storables/Native/INativeStorable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

namespace Files.App.Storage.Storables
{
/// <summary>
/// Represents a storable that is natively supported by Windows Shell API.
/// </summary>
public interface INativeStorable : IStorable
{
public string GetPropertyAsync(string id);
}
}
12 changes: 12 additions & 0 deletions src/Files.App.Storage/Storables/Native/NativeFile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

namespace Files.App.Storage.Storables
{
/// <summary>
/// Represents a file that is natively supported by Windows Shell API.
/// </summary>
public class NativeFile : NativeStorable/*, IFile*/
{
}
}
38 changes: 38 additions & 0 deletions src/Files.App.Storage/Storables/Native/NativeFolder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

namespace Files.App.Storage.Storables
{
/// <summary>
/// Represents a folder that is natively supported by Windows Shell API.
/// </summary>
public class NativeFolder : NativeStorable/*, IFolder*/
{
public async IAsyncEnumerable<IStorable> GetChildrenAsync()
{
foreach (var storable in GetChildren())
{
await Task.Yield();

yield return storable;
}

unsafe IEnumerable<NativeStorable> GetChildren()
{
using ComPtr<IEnumShellItems> pEnumShellItems = default;
fixed (Guid* pBHID = PInvoke.BHID_EnumItems)
{
hr = pRecycleBinFolderShellItem.Get()->BindToHandler(
null,
pBHID,
(Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IEnumShellItems.Guid)),
(void**)pEnumShellItems.GetAddressOf());

ComPtr<IShellItem> pShellItem = default;
while (pEnumShellItems.Get()->Next(1, pShellItem.GetAddressOf()) == HRESULT.S_OK)
yield return NativeStorable(pShellItem);
}
}
}
}
}
12 changes: 12 additions & 0 deletions src/Files.App.Storage/Storables/Native/NativeFolderView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

namespace Files.App.Storage.Storables
{
/// <summary>
/// Represents a folder view that is natively supported by Windows Shell API.
/// </summary>
public class NativeFolderView : IFolderView
{
}
}
107 changes: 107 additions & 0 deletions src/Files.App.Storage/Storables/Native/NativeStorable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

using System.Runtime.InteropServices;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.System.Com;
using Windows.Win32.UI.Shell;

namespace Files.App.Storage.Storables
{
/// <summary>
/// Represents a storable that is natively supported by Windows Shell API.
/// </summary>
public abstract class NativeStorable : INativeStorable
{
/// <inheritdoc/>
/// <remarks>
/// This must be a path that can be parsed by SHCreateItemFromParsingName.
/// </remarks>
public string Path { get; protected set; }

/// <inheritdoc/>
/// <remarks>
/// This must be a path that can be parsed by SHParseDisplayName.
/// </remarks>
public string Name { get; protected set; }

/// <inheritdoc/>
public string Id { get; protected set; } // Won't use

protected ComPtr<IShellItem> m_pShellItem { get; private set; }

/// <summary>
/// Initializes an instance of <see cref="NativeStorable"/> class.
/// </summary>
/// <param name="path">Win32 file namespace, shell namespace, or UNC path.</param>
public unsafe NativeStorable(string path)
{
HRESULT hr = PInvoke.SHCreateItemFromParsingName(
path,
null,
(Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IShellItem.Guid)),

Check failure on line 43 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

The name 'Unsafe' does not exist in the current context

Check failure on line 43 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

The name 'Unsafe' does not exist in the current context

Check failure on line 43 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

'IShellItem' does not contain a definition for 'Guid'

Check failure on line 43 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

The name 'Unsafe' does not exist in the current context

Check failure on line 43 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

The name 'Unsafe' does not exist in the current context

Check failure on line 43 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

'IShellItem' does not contain a definition for 'Guid'

Check failure on line 43 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, x64)

The name 'Unsafe' does not exist in the current context

Check failure on line 43 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, x64)

The name 'Unsafe' does not exist in the current context

Check failure on line 43 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, x64)

'IShellItem' does not contain a definition for 'Guid'

Check failure on line 43 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

The name 'Unsafe' does not exist in the current context

Check failure on line 43 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

The name 'Unsafe' does not exist in the current context

Check failure on line 43 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

'IShellItem' does not contain a definition for 'Guid'
(void**)m_pShellItem.GetAddressOf());
}

/// <summary>
/// Initializes an instance of <see cref="NativeStorable"/> class.
/// </summary>
/// <param name="shellGuid">An instance of GUID that represents a shell folder.</param>
public unsafe NativeStorable(Guid shellGuid)
{
HRESULT hr = default;

// For known folders
fixed (Guid* pFolderId = &shellGuid)

Check failure on line 56 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

You cannot use the fixed statement to take the address of an already fixed expression

Check failure on line 56 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

You cannot use the fixed statement to take the address of an already fixed expression

Check failure on line 56 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, x64)

You cannot use the fixed statement to take the address of an already fixed expression

Check failure on line 56 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

You cannot use the fixed statement to take the address of an already fixed expression
{
hr = PInvoke.SHGetKnownFolderItem(
pFolderId,
KNOWN_FOLDER_FLAG.KF_FLAG_DEFAULT,
HANDLE.Null,
(Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IShellItem.Guid)),

Check failure on line 62 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

The name 'Unsafe' does not exist in the current context

Check failure on line 62 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

The name 'Unsafe' does not exist in the current context

Check failure on line 62 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

'IShellItem' does not contain a definition for 'Guid'

Check failure on line 62 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

The name 'Unsafe' does not exist in the current context

Check failure on line 62 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

The name 'Unsafe' does not exist in the current context

Check failure on line 62 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

'IShellItem' does not contain a definition for 'Guid'

Check failure on line 62 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, x64)

The name 'Unsafe' does not exist in the current context

Check failure on line 62 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, x64)

The name 'Unsafe' does not exist in the current context

Check failure on line 62 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, x64)

'IShellItem' does not contain a definition for 'Guid'

Check failure on line 62 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

The name 'Unsafe' does not exist in the current context

Check failure on line 62 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

The name 'Unsafe' does not exist in the current context

Check failure on line 62 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

'IShellItem' does not contain a definition for 'Guid'
(void**)m_pShellItem.GetAddressOf());
}

if (hr == HRESULT.S_OK)
return;

string path = $"Shell:::{shellGuid.ToString("B")}";

hr = PInvoke.SHCreateItemFromParsingName(
path,
null,
(Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IShellItem.Guid)),

Check failure on line 74 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

The name 'Unsafe' does not exist in the current context

Check failure on line 74 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

The name 'Unsafe' does not exist in the current context

Check failure on line 74 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

'IShellItem' does not contain a definition for 'Guid'

Check failure on line 74 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

The name 'Unsafe' does not exist in the current context

Check failure on line 74 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

The name 'Unsafe' does not exist in the current context

Check failure on line 74 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

'IShellItem' does not contain a definition for 'Guid'

Check failure on line 74 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, x64)

The name 'Unsafe' does not exist in the current context

Check failure on line 74 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, x64)

The name 'Unsafe' does not exist in the current context

Check failure on line 74 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, x64)

'IShellItem' does not contain a definition for 'Guid'

Check failure on line 74 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

The name 'Unsafe' does not exist in the current context

Check failure on line 74 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

The name 'Unsafe' does not exist in the current context

Check failure on line 74 in src/Files.App.Storage/Storables/Native/NativeStorable.cs

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

'IShellItem' does not contain a definition for 'Guid'
(void**)m_pShellItem.GetAddressOf());
}

/// <summary>
/// Initializes an instance of <see cref="NativeStorable"/> class.
/// </summary>
/// <param name="pShellItem">An instance of <see cref="IShellItem"/>.</param>
public NativeStorable(ComPtr<IShellItem> pShellItem)
{
m_pShellItem = pShellItem;
}

/// <inheritdoc/>
public string GetPropertyAsync(string id)
{
using ComPtr<IShellItem2> pShellItem2 = default;
hr = pShellItem.Get()->QueryInterface(
(Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IShellItem2.Guid)),
(void**)pShellItem2.GetAddressOf());

hr = PInvoke.PSGetPropertyKeyFromName(
id,
out var propertyKey);

using ComHeapPtr<LPWSTR> pszPropertyValue = default;
//hr = pShellItem2.Get()->GetString(
// &propertyKey,
// pszPropertyValue.GetAddressOf());

return pszPropertyValue.Get()->ToString();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
namespace Files.App.Storage.Storables
{
/// <inheritdoc cref="IFile"/>
public class NativeFile : NativeStorable<FileInfo>, ILocatableFile, IModifiableFile, IFileExtended, INestedFile
public class NativeFileOld : NativeStorableOld<FileInfo>, ILocatableFile, IModifiableFile, IFileExtended, INestedFile
{
public NativeFile(FileInfo fileInfo, string? name = null)
public NativeFileOld(FileInfo fileInfo, string? name = null)
: base(fileInfo, name)
{
}

public NativeFile(string path, string? name = null)
public NativeFileOld(string path, string? name = null)
: this(new FileInfo(path), name)
{
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
namespace Files.App.Storage.Storables
{
/// <inheritdoc cref="IFolder"/>
public class NativeFolder : NativeStorable<DirectoryInfo>, ILocatableFolder, IModifiableFolder, IMutableFolder, IFolderExtended, INestedFolder, IDirectCopy, IDirectMove
public class NativeFolderOld : NativeStorableOld<DirectoryInfo>, ILocatableFolder, IModifiableFolder, IMutableFolder, IFolderExtended, INestedFolder, IDirectCopy, IDirectMove
{
public NativeFolder(DirectoryInfo directoryInfo, string? name = null)
public NativeFolderOld(DirectoryInfo directoryInfo, string? name = null)
: base(directoryInfo, name)
{
}

public NativeFolder(string path, string? name = null)
public NativeFolderOld(string path, string? name = null)
: this(new DirectoryInfo(path), name)
{
}
Expand All @@ -27,7 +27,7 @@ public virtual Task<INestedFile> GetFileAsync(string fileName, CancellationToken
if (!File.Exists(path))
throw new FileNotFoundException();

return Task.FromResult<INestedFile>(new NativeFile(path));
return Task.FromResult<INestedFile>(new NativeFileOld(path));
}

/// <inheritdoc/>
Expand All @@ -46,21 +46,21 @@ public virtual async IAsyncEnumerable<INestedStorable> GetItemsAsync(StorableKin
if (kind == StorableKind.Files)
{
foreach (var item in Directory.EnumerateFiles(Path))
yield return new NativeFile(item);
yield return new NativeFileOld(item);
}
else if (kind == StorableKind.Folders)
{
foreach (var item in Directory.EnumerateDirectories(Path))
yield return new NativeFolder(item);
yield return new NativeFolderOld(item);
}
else
{
foreach (var item in Directory.EnumerateFileSystemEntries(Path))
{
if (File.Exists(item))
yield return new NativeFile(item);
yield return new NativeFileOld(item);
else
yield return new NativeFolder(item);
yield return new NativeFolderOld(item);
}
}

Expand Down Expand Up @@ -96,7 +96,7 @@ public virtual async Task<INestedStorable> CreateCopyOfAsync(INestedStorable ite
var newPath = System.IO.Path.Combine(Path, itemToCopy.Name);
File.Copy(sourceLocatableFile.Path, newPath, overwrite);

return new NativeFile(newPath);
return new NativeFileOld(newPath);
}

var copiedFile = await CreateFileAsync(itemToCopy.Name, overwrite, cancellationToken);
Expand Down Expand Up @@ -124,7 +124,7 @@ public virtual async Task<INestedStorable> MoveFromAsync(INestedStorable itemToM
var newPath = System.IO.Path.Combine(Path, itemToMove.Name);
File.Move(sourceLocatableFile.Path, newPath, overwrite);

return new NativeFile(newPath);
return new NativeFileOld(newPath);
}
else
{
Expand Down Expand Up @@ -161,7 +161,7 @@ public virtual Task<INestedFolder> CreateFolderAsync(string desiredName, bool ov
Directory.Delete(path, true);

_ = Directory.CreateDirectory(path);
return Task.FromResult<INestedFolder>(new NativeFolder(path));
return Task.FromResult<INestedFolder>(new NativeFolderOld(path));
}
}
}
Loading
Loading