Skip to content

Commit 1a24835

Browse files
committed
Added generic T based parsers in GetRegistryValue
1 parent e6f8bbe commit 1a24835

File tree

4 files changed

+104
-39
lines changed

4 files changed

+104
-39
lines changed

src/Files.App.Storage/Storables/HomeFolder/HomeFolder.cs

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace Files.App.Storage.Storables
99
{
10-
public partial class HomeFolder : IHomeFolder
10+
public unsafe partial class HomeFolder : IHomeFolder
1111
{
1212
public string Id => "Home"; // Will be "files://Home" in the future.
1313

@@ -48,38 +48,36 @@ public IAsyncEnumerable<IStorableChild> GetQuickAccessFolderAsync(CancellationTo
4848
/// <inheritdoc/>
4949
public IAsyncEnumerable<IStorableChild> GetLogicalDrivesAsync(CancellationToken cancellationToken = default)
5050
{
51-
return GetLogicalDrives().ToAsyncEnumerable();
51+
var availableDrives = PInvoke.GetLogicalDrives();
52+
if (availableDrives is 0)
53+
return Enumerable.Empty<IStorableChild>().ToAsyncEnumerable();
5254

53-
IEnumerable<IStorableChild> GetLogicalDrives()
54-
{
55-
var availableDrives = PInvoke.GetLogicalDrives();
56-
if (availableDrives is 0)
57-
yield break;
58-
59-
int count = BitOperations.PopCount(availableDrives);
60-
var driveLetters = new char[count];
55+
int count = BitOperations.PopCount(availableDrives);
56+
var driveLetters = new char[count];
6157

62-
count = 0;
63-
char driveLetter = 'A';
64-
while (availableDrives is not 0)
65-
{
66-
if ((availableDrives & 1) is not 0)
67-
driveLetters[count++] = driveLetter;
58+
count = 0;
59+
char driveLetter = 'A';
60+
while (availableDrives is not 0)
61+
{
62+
if ((availableDrives & 1) is not 0)
63+
driveLetters[count++] = driveLetter;
6864

69-
availableDrives >>= 1;
70-
driveLetter++;
71-
}
65+
availableDrives >>= 1;
66+
driveLetter++;
67+
}
7268

73-
foreach (char letter in driveLetters)
74-
{
75-
cancellationToken.ThrowIfCancellationRequested();
69+
List<IStorableChild> items = [];
70+
foreach (char letter in driveLetters)
71+
{
72+
cancellationToken.ThrowIfCancellationRequested();
7673

77-
if (WindowsStorable.TryParse($"{letter}:\\") is not IWindowsStorable driveRoot)
78-
throw new InvalidOperationException();
74+
if (WindowsStorable.TryParse($"{letter}:\\") is not IWindowsStorable driveRoot)
75+
throw new InvalidOperationException();
7976

80-
yield return new WindowsFolder(driveRoot.ThisPtr);
81-
}
77+
items.Add(new WindowsFolder(driveRoot.ThisPtr));
8278
}
79+
80+
return items.ToAsyncEnumerable();
8381
}
8482

8583
/// <inheritdoc/>

src/Files.App.Storage/Storables/WindowsStorage/WindowsStorableHelpers.Registry.cs

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright (c) Files Community
22
// Licensed under the MIT License.
33

4+
using System.Buffers.Binary;
5+
using System.Runtime.CompilerServices;
46
using System.Runtime.InteropServices;
57
using Windows.Win32;
68
using Windows.Win32.Foundation;
@@ -23,16 +25,16 @@ public static bool OpenRegistryKey(HKEY hRootKey, string subKey, REG_SAM_FLAGS f
2325
return dwResult is WIN32_ERROR.ERROR_SUCCESS;
2426
}
2527

26-
public static bool GetRegistryValue<T>(HKEY hRootKey, string subKey, string valueName, REG_ROUTINE_FLAGS flags, out T? valueData)
28+
public static bool GetRegistryValue<T>(HKEY hRootKey, string szSubKey, string szValueName, REG_ROUTINE_FLAGS dwRoutineFlags, out T? valueData)
2729
{
2830
valueData = default;
2931

3032
WIN32_ERROR dwResult = default;
3133
HKEY hKey = hRootKey;
3234

33-
if (!string.IsNullOrEmpty(subKey))
35+
if (!string.IsNullOrEmpty(szSubKey))
3436
{
35-
fixed (char* pszSubKey = subKey)
37+
fixed (char* pszSubKey = szSubKey)
3638
dwResult = PInvoke.RegOpenKeyEx(hRootKey, pszSubKey, 0, REG_SAM_FLAGS.KEY_QUERY_VALUE, &hKey);
3739

3840
if (dwResult is not WIN32_ERROR.ERROR_SUCCESS)
@@ -42,22 +44,89 @@ public static bool GetRegistryValue<T>(HKEY hRootKey, string subKey, string valu
4244
}
4345
}
4446

47+
REG_VALUE_TYPE dwValueType = default;
4548
byte* pData = null;
4649
uint cbData = 0U;
4750

48-
fixed (char* pszValueName = valueName)
51+
fixed (char* pszValueName = szValueName)
4952
{
50-
dwResult = PInvoke.RegGetValue(hKey, default, pszValueName, flags, null, null, &cbData);
53+
dwResult = PInvoke.RegGetValue(hKey, default, pszValueName, dwRoutineFlags, null, null, &cbData);
5154

5255
if (dwResult is WIN32_ERROR.ERROR_SUCCESS or WIN32_ERROR.ERROR_MORE_DATA)
5356
{
5457
if (cbData is 0U)
5558
return false;
5659

5760
pData = (byte*)NativeMemory.Alloc(cbData);
58-
dwResult = PInvoke.RegGetValue(hKey, default, pszValueName, flags, null, pData, &cbData);
61+
dwResult = PInvoke.RegGetValue(hKey, default, pszValueName, dwRoutineFlags, &dwValueType, pData, &cbData);
62+
63+
64+
switch (dwValueType)
65+
{
66+
case REG_VALUE_TYPE.REG_NONE:
67+
case REG_VALUE_TYPE.REG_BINARY:
68+
{
69+
byte[] byteArrayData = new byte[cbData];
70+
Marshal.Copy((nint)pData, byteArrayData, 0, (int)cbData);
71+
72+
valueData = (T)(object)byteArrayData;
73+
}
74+
break;
75+
case REG_VALUE_TYPE.REG_DWORD:
76+
case REG_VALUE_TYPE.REG_QWORD:
77+
{
78+
valueData = cbData switch
79+
{
80+
4U => valueData = Unsafe.As<uint, T>(ref *(uint*)pData),
81+
8U => valueData = Unsafe.As<ulong, T>(ref *(ulong*)pData),
82+
_ => throw new InvalidCastException($"Registry value size of data \"{nameof(pData)}\" of \"{nameof(pszValueName)}\" is invalid (size: \"{cbData}\")."),
83+
};
84+
}
85+
break;
86+
case REG_VALUE_TYPE.REG_DWORD_BIG_ENDIAN:
87+
{
88+
var uint32Data = BinaryPrimitives.ReadUInt32BigEndian(new Span<byte>(pData, (int)cbData));
89+
valueData = Unsafe.As<uint, T>(ref uint32Data);
90+
}
91+
break;
92+
case REG_VALUE_TYPE.REG_SZ:
93+
case REG_VALUE_TYPE.REG_EXPAND_SZ:
94+
{
95+
valueData = (T)(object)new string((char*)pData);
96+
}
97+
break;
98+
case REG_VALUE_TYPE.REG_MULTI_SZ:
99+
{
100+
byte* dwPtrPosition = pData;
101+
uint dwSeparatorCount = 0U;
102+
103+
while (dwPtrPosition < pData + cbData)
104+
{
105+
if ((char)*dwPtrPosition is '\0')
106+
dwSeparatorCount++;
107+
108+
dwPtrPosition++;
109+
}
110+
111+
dwPtrPosition = pData;
112+
uint dwArrayIndex = 0U;
113+
string[] stringDataArray = new string[dwSeparatorCount + 1];
114+
115+
while (dwPtrPosition < pData + cbData)
116+
{
117+
if ((char)*dwPtrPosition is '\0')
118+
{
119+
dwArrayIndex++;
120+
continue;
121+
}
122+
123+
stringDataArray[dwArrayIndex] = new((char*)pData);
124+
dwPtrPosition += stringDataArray[dwArrayIndex].Length;
125+
}
126+
}
127+
break;
128+
}
59129

60-
valueData = Marshal.PtrToStructure<T>((nint)pData);
61130
NativeMemory.Free(pData);
62131
}
63132
}

src/Files.App/Utils/Serialization/Implementation/DefaultSettingsSerializer.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
using Windows.Win32.Foundation;
77
using Windows.Win32.Security;
88
using Windows.Win32.Storage.FileSystem;
9-
//using static Files.App.Helpers.Win32Helper;
10-
//using static Files.App.Helpers.Win32PInvoke;
119

1210
namespace Files.App.Utils.Serialization.Implementation
1311
{
@@ -51,14 +49,14 @@ public string ReadFromFile()
5149
{
5250
_ = _filePath ?? throw new ArgumentNullException(nameof(_filePath));
5351

54-
return ReadStringFromFile(_filePath);
52+
return Win32Helper.ReadStringFromFile(_filePath);
5553
}
5654

5755
public bool WriteToFile(string? text)
5856
{
5957
_ = _filePath ?? throw new ArgumentNullException(nameof(_filePath));
6058

61-
return WriteStringToFile(_filePath, text);
59+
return Win32Helper.WriteStringToFile(_filePath, text);
6260
}
6361
}
6462
}

src/Files.App/ViewModels/UserControls/Widgets/QuickAccessWidgetViewModel.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ public override async Task ExecutePinToSidebarCommand(WidgetCardItem? item)
198198

199199
unsafe
200200
{
201-
hr = PInvoke.RoGetAgileReference(AgileReferenceOptions.AGILEREFERENCE_DEFAULT, IID.IID_IShellItem, (IUnknown*)folderCardItem.Item.ThisPtr.Get(), pAgileReference.GetAddressOf());
201+
hr = PInvoke.RoGetAgileReference(AgileReferenceOptions.AGILEREFERENCE_DEFAULT, IID.IID_IShellItem, (IUnknown*)folderCardItem.Item.ThisPtr, pAgileReference.GetAddressOf());
202202
}
203203

204204
// Pin to Quick Access on Windows
@@ -234,7 +234,7 @@ public override async Task ExecuteUnpinFromSidebarCommand(WidgetCardItem? item)
234234

235235
unsafe
236236
{
237-
hr = PInvoke.RoGetAgileReference(AgileReferenceOptions.AGILEREFERENCE_DEFAULT, IID.IID_IShellItem, (IUnknown*)folderCardItem.Item.ThisPtr.Get(), pAgileReference.GetAddressOf());
237+
hr = PInvoke.RoGetAgileReference(AgileReferenceOptions.AGILEREFERENCE_DEFAULT, IID.IID_IShellItem, (IUnknown*)folderCardItem.Item.ThisPtr, pAgileReference.GetAddressOf());
238238
}
239239

240240
// Unpin from Quick Access on Windows

0 commit comments

Comments
 (0)