Skip to content
Merged
32 changes: 32 additions & 0 deletions src/Files.App.CsWin32/NativeMethods.txt
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,35 @@ GetMenuItemCount
GetMenuItemInfo
IsWow64Process2
GetCurrentProcess
CertFreeCertificateContext
CryptMsgGetParam
CryptMsgClose
CryptMsgOpenToDecode
CryptMsgUpdate
CertOpenStore
CryptDecodeObject
CertFindCertificateInStore
CertComparePublicKeyInfo
CryptQueryObject
CertCloseStore
WinVerifyTrust
FileTimeToSystemTime
FileTimeToLocalFileTime
SystemTimeToFileTime
CRYPTOAPI_BLOB
CMSG_SIGNER_INFO
SignDataHandle
CRYPT_ATTRIBUTE
FILETIME
CRYPT_BIT_BLOB
CERT_ALT_NAME_INFO
CERT_CONTEXT
CERT_INFO
CRYPT_ALGORITHM_IDENTIFIER
CERT_PUBLIC_KEY_INFO
CATALOG_INFO
WINTRUST_FILE_INFO
WINTRUST_DATA
HCERTSTORE
HCRYPTMSG
CERT_QUERY_ENCODING_TYPE
5 changes: 5 additions & 0 deletions src/Files.App/Data/Enums/PropertiesNavigationViewItemType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,10 @@ public enum PropertiesNavigationViewItemType
/// Shortcut page type
/// </summary>
Shortcut,

/// <summary>
/// Signatures page type
/// </summary>
Signatures,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,25 @@

using Files.Shared.Helpers;
using Microsoft.UI.Xaml;
using System.Collections.Frozen;
using Windows.Storage;

namespace Files.App.Data.Factories
{
public static class PropertiesNavigationViewItemFactory
{
private static readonly FrozenSet<string> _signableTypes = new HashSet<string>()
{
".aab", ".apk", ".application", ".appx", ".appxbundle", ".arx", ".cab", ".cat", ".cbx",
".cpl", ".crx", ".dbx", ".deploy", ".dll", ".doc", ".docm", ".dot", ".dotm", ".drx",
".ear", ".efi", ".exe", ".jar", ".js", ".manifest", ".mpp", ".mpt", ".msi", ".msix",
".msixbundle", ".msm", ".msp", ".nupkg", ".ocx", ".pot", ".potm", ".ppa", ".ppam", ".pps",
".ppsm", ".ppt", ".pptm", ".ps1", ".psm1", ".psi", ".pub", ".sar", ".stl", ".sys", ".vbs",
".vdw", ".vdx", ".vsd", ".vsdm", ".vss", ".vssm", ".vst", ".vstm", ".vsto", ".vsix", ".vsx", ".vtx",
".vxd", ".war", ".wiz", ".wsf", ".xap", ".xla", ".xlam", ".xls", ".xlsb", ".xlsm", ".xlt",
".xltm", ".xlsm", ".xsn"
}.ToFrozenSet();

public static ObservableCollection<NavigationViewItemButtonStyleItem> Initialize(object item)
{
ObservableCollection<NavigationViewItemButtonStyleItem> PropertiesNavigationViewItems = [];
Expand Down Expand Up @@ -61,8 +74,15 @@ public static ObservableCollection<NavigationViewItemButtonStyleItem> Initialize
ItemType = PropertiesNavigationViewItemType.Compatibility,
ThemedIconStyle = (Style)Application.Current.Resources["App.ThemedIcons.Properties.Compatability"],
};
var signaturesItem = new NavigationViewItemButtonStyleItem()
{
Name = Strings.Signatures.GetLocalizedResource(),
ItemType = PropertiesNavigationViewItemType.Signatures,
ThemedIconStyle = (Style)Application.Current.Resources["App.ThemedIcons.Properties.Signatures"],
};

PropertiesNavigationViewItems.Add(generalItem);
PropertiesNavigationViewItems.Add(signaturesItem);
PropertiesNavigationViewItems.Add(securityItem);
PropertiesNavigationViewItems.Add(hashesItem);
PropertiesNavigationViewItems.Add(shortcutItem);
Expand All @@ -89,6 +109,7 @@ public static ObservableCollection<NavigationViewItemButtonStyleItem> Initialize
PropertiesNavigationViewItems.Remove(securityItem);
PropertiesNavigationViewItems.Remove(customizationItem);
PropertiesNavigationViewItems.Remove(hashesItem);
PropertiesNavigationViewItems.Remove(signaturesItem);
}
else if (item is ListedItem listedItem)
{
Expand All @@ -102,13 +123,17 @@ public static ObservableCollection<NavigationViewItemButtonStyleItem> Initialize
var detailsItemEnabled = !(isFolder && !listedItem.IsArchive) && !isLibrary && !listedItem.IsRecycleBinItem;
var customizationItemEnabled = !isLibrary && (isFolder && !listedItem.IsArchive || isShortcut && !listedItem.IsLinkItem);
var compatibilityItemEnabled = FileExtensionHelpers.IsExecutableFile(listedItem is IShortcutItem sht ? sht.TargetPath : fileExt, true);
var signaturesItemEnabled = !isFolder && !isLibrary && !listedItem.IsRecycleBinItem && _signableTypes.Contains(fileExt);

if (!securityItemEnabled)
PropertiesNavigationViewItems.Remove(securityItem);

if (!hashItemEnabled)
PropertiesNavigationViewItems.Remove(hashesItem);

if (!signaturesItemEnabled)
PropertiesNavigationViewItems.Remove(signaturesItem);

if (!isShortcut)
PropertiesNavigationViewItems.Remove(shortcutItem);

Expand All @@ -132,6 +157,7 @@ public static ObservableCollection<NavigationViewItemButtonStyleItem> Initialize
PropertiesNavigationViewItems.Remove(detailsItem);
PropertiesNavigationViewItems.Remove(customizationItem);
PropertiesNavigationViewItems.Remove(compatibilityItem);
PropertiesNavigationViewItems.Remove(signaturesItem);
}

return PropertiesNavigationViewItems;
Expand Down
18 changes: 18 additions & 0 deletions src/Files.App/Data/Items/CertNodeInfoItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) Files Community
// Licensed under the MIT License.

namespace Files.App.Data.Items
{
public class CertNodeInfoItem
{
public string IssuedTo { get; set; } = string.Empty;

public string IssuedBy { get; set; } = string.Empty;

public string Version { get; set; } = string.Empty;

public string ValidFrom { get; set; } = string.Empty;

public string ValidTo { get; set; } = string.Empty;
}
}
92 changes: 92 additions & 0 deletions src/Files.App/Data/Models/SignatureInfoItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright (c) Files Community
// Licensed under the MIT License.

using Files.App.Utils.Signatures;
using System.Windows.Input;
using Windows.Win32.Foundation;

namespace Files.App.Data.Models
{
public sealed partial class SignatureInfoItem : ObservableObject
{
private readonly string _fileName;

private readonly HWND _hwndParent;

private readonly int _index;

private string _Version = string.Empty;
public string Version
{
get => _Version;
set => SetProperty(ref _Version, value);
}

private string _IssuedBy = string.Empty;
public string IssuedBy
{
get => _IssuedBy;
set => SetProperty(ref _IssuedBy, value);
}

private string _IssuedTo = string.Empty;
public string IssuedTo
{
get => _IssuedTo;
set => SetProperty(ref _IssuedTo, value);
}

private string _ValidFromTimestamp = string.Empty;
public string ValidFromTimestamp
{
get => _ValidFromTimestamp;
set => SetProperty(ref _ValidFromTimestamp, value);
}

private string _ValidToTimestamp = string.Empty;
public string ValidToTimestamp
{
get => _ValidToTimestamp;
set => SetProperty(ref _ValidToTimestamp, value);
}

private string _VerifiedTimestamp = string.Empty;
public string VerifiedTimestamp
{
get => _VerifiedTimestamp;
set => SetProperty(ref _VerifiedTimestamp, value);
}

private bool _Verified = false;
public bool Verified
{
get => _Verified;
set
{
if (SetProperty(ref _Verified, value))
OnPropertyChanged(nameof(Glyph));
}
}

public List<CertNodeInfoItem> SignChain { get; }

public string Glyph => Verified ? "\uE930" : "\uEA39";

public ICommand OpenDetailsCommand { get; }

public SignatureInfoItem(string fileName, int index, HWND hWnd, List<CertNodeInfoItem> chain)
{
_fileName = fileName;
_hwndParent = hWnd;
_index = index;
SignChain = chain ?? new List<CertNodeInfoItem>();
OpenDetailsCommand = new AsyncRelayCommand(DoOpenDetails);
}

private Task DoOpenDetails()
{
DigitalSignaturesUtil.DisplaySignerInfoDialog(_fileName, _hwndParent, _index);
return Task.CompletedTask;
}
}
}
4 changes: 2 additions & 2 deletions src/Files.App/Helpers/Win32/Win32Helper.Storage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -902,13 +902,13 @@ public static SafeFileHandle OpenFileForRead(string filePath, bool readWrite = f
(uint)FILE_ACCESS_RIGHTS.FILE_GENERIC_READ | (uint)(readWrite ? FILE_ACCESS_RIGHTS.FILE_GENERIC_WRITE : 0u), (uint)(Win32PInvoke.FILE_SHARE_READ | (readWrite ? 0 : Win32PInvoke.FILE_SHARE_WRITE)), IntPtr.Zero, Win32PInvoke.OPEN_EXISTING, (uint)Win32PInvoke.File_Attributes.BackupSemantics | flags, IntPtr.Zero), true);
}

public static bool GetFileDateModified(string filePath, out FILETIME dateModified)
public static bool GetFileDateModified(string filePath, out System.Runtime.InteropServices.ComTypes.FILETIME dateModified)
{
using var hFile = new SafeFileHandle(Win32PInvoke.CreateFileFromApp(filePath, (uint)FILE_ACCESS_RIGHTS.FILE_GENERIC_READ, Win32PInvoke.FILE_SHARE_READ, IntPtr.Zero, Win32PInvoke.OPEN_EXISTING, (uint)Win32PInvoke.File_Attributes.BackupSemantics, IntPtr.Zero), true);
return Win32PInvoke.GetFileTime(hFile.DangerousGetHandle(), out _, out _, out dateModified);
}

public static bool SetFileDateModified(string filePath, FILETIME dateModified)
public static bool SetFileDateModified(string filePath, System.Runtime.InteropServices.ComTypes.FILETIME dateModified)
{
using var hFile = new SafeFileHandle(Win32PInvoke.CreateFileFromApp(filePath, (uint)FILE_ACCESS_RIGHTS.FILE_WRITE_ATTRIBUTES, 0, IntPtr.Zero, Win32PInvoke.OPEN_EXISTING, (uint)Win32PInvoke.File_Attributes.BackupSemantics, IntPtr.Zero), true);
return Win32PInvoke.SetFileTime(hFile.DangerousGetHandle(), new(), new(), dateModified);
Expand Down
35 changes: 25 additions & 10 deletions src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.
// Copyright (c) Files Community
// Licensed under the MIT License.

using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using Windows.Win32.Foundation;
using Windows.Win32.Security.Cryptography;
using Windows.Win32.System.Com;

namespace Files.App.Helpers
Expand Down Expand Up @@ -232,17 +232,17 @@ public static extern bool WriteFileEx(
[DllImport("api-ms-win-core-file-l1-2-1.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern bool GetFileTime(
[In] IntPtr hFile,
out FILETIME lpCreationTime,
out FILETIME lpLastAccessTime,
out FILETIME lpLastWriteTime
out System.Runtime.InteropServices.ComTypes.FILETIME lpCreationTime,
out System.Runtime.InteropServices.ComTypes.FILETIME lpLastAccessTime,
out System.Runtime.InteropServices.ComTypes.FILETIME lpLastWriteTime
);

[DllImport("api-ms-win-core-file-l1-2-1.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern bool SetFileTime(
[In] IntPtr hFile,
in FILETIME lpCreationTime,
in FILETIME lpLastAccessTime,
in FILETIME lpLastWriteTime
in System.Runtime.InteropServices.ComTypes.FILETIME lpCreationTime,
in System.Runtime.InteropServices.ComTypes.FILETIME lpLastAccessTime,
in System.Runtime.InteropServices.ComTypes.FILETIME lpLastWriteTime
);

[DllImport("api-ms-win-core-file-l2-1-1.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
Expand Down Expand Up @@ -288,7 +288,7 @@ IntPtr hFindFile

[DllImport("api-ms-win-core-timezone-l1-1-0.dll", SetLastError = true)]
public static extern bool FileTimeToSystemTime(
ref FILETIME lpFileTime,
ref System.Runtime.InteropServices.ComTypes.FILETIME lpFileTime,
out SYSTEMTIME lpSystemTime
);

Expand Down Expand Up @@ -347,5 +347,20 @@ public static extern int SHGetKnownFolderPath(
IntPtr hToken,
out IntPtr pszPath
);

// crypt32.dll
[DllImport("crypt32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public unsafe static extern uint CertGetNameStringA(
CERT_CONTEXT* pCertContext,
uint dwType,
uint dwFlags,
void* pvTypePara,
PCSTR pszNameString,
uint cchNameString
);

// cryptui.dll
[DllImport("cryptui.dll", SetLastError = true, CharSet = CharSet.Auto)]
public unsafe static extern bool CryptUIDlgViewSignerInfo(CRYPTUI_VIEWSIGNERINFO_STRUCT* pViewInfo);
}
}
47 changes: 40 additions & 7 deletions src/Files.App/Helpers/Win32/Win32PInvoke.Structs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using Windows.Win32.Foundation;
using Windows.Win32.Security.Cryptography;

namespace Files.App.Helpers
{
Expand Down Expand Up @@ -90,9 +91,9 @@ public struct REPARSE_DATA_BUFFER
public struct WIN32_FILE_ATTRIBUTE_DATA
{
public FileAttributes dwFileAttributes;
public FILETIME ftCreationTime;
public FILETIME ftLastAccessTime;
public FILETIME ftLastWriteTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
}
Expand Down Expand Up @@ -183,9 +184,9 @@ public struct WIN32_FIND_DATA
{
public uint dwFileAttributes;

public FILETIME ftCreationTime;
public FILETIME ftLastAccessTime;
public FILETIME ftLastWriteTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;

public uint nFileSizeHigh;
public uint nFileSizeLow;
Expand All @@ -198,5 +199,37 @@ public struct WIN32_FIND_DATA
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;
}

[StructLayout(LayoutKind.Sequential)]
public unsafe struct SignDataHandle
{
public uint dwObjSize;
public CMSG_SIGNER_INFO* pSignerInfo;
public HCERTSTORE hCertStoreHandle;
}

[StructLayout(LayoutKind.Sequential)]
public unsafe struct CRYPTOAPI_BLOB
{
public uint cbData;
public void* pbData;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public unsafe struct CRYPTUI_VIEWSIGNERINFO_STRUCT
{
public uint dwSize;
public HWND hwndParent;
public uint dwFlags;
public PCSTR szTitle;
public CMSG_SIGNER_INFO* pSignerInfo;
public void* hMsg;
public PCSTR pszOID;
public uint? dwReserved;
public uint cStores;
public HCERTSTORE* rghStores;
public uint cPropPages;
public void* rgPropPages;
}
}
}
Loading