Skip to content

Commit e6f8bbe

Browse files
committed
Introduced WindowsStorableHelpers.GetRegistryValue
1 parent 676c925 commit e6f8bbe

File tree

3 files changed

+79
-11
lines changed

3 files changed

+79
-11
lines changed

src/Files.App.CsWin32/NativeMethods.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ QITIPF_FLAGS
225225
GetKeyboardState
226226
MapVirtualKey
227227
GetKeyboardLayout
228-
RegOpenKeyExW
229228
HKEY_CLASSES_ROOT
229+
HKEY_CURRENT_USER
230+
RegOpenKeyEx
230231
RegEnumKeyEx
232+
RegGetValue

src/Files.App.Storage/Storables/WindowsStorage/ShellNewManager.cs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,38 @@ namespace Files.App.Storage
1010
{
1111
public static partial class ShellNewManager
1212
{
13+
public const string CachedShellNewItemsRegistryPath = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Discardable\\PostSetup\\ShellNew";
14+
1315
public static IEnumerable<ShellNewItem> GetItems()
16+
{
17+
var cachedItems = GetItemsFromCache();
18+
if (cachedItems.Any())
19+
{
20+
foreach (var item in cachedItems)
21+
yield return item;
22+
23+
yield break;
24+
}
25+
26+
foreach (var item in GetItemsFromAssoc())
27+
yield return item;
28+
}
29+
30+
private static IEnumerable<ShellNewItem> GetItemsFromCache()
31+
{
32+
bool fRes = WindowsStorableHelpers.GetRegistryValue(HKEY.HKEY_CURRENT_USER, CachedShellNewItemsRegistryPath, "Classes", REG_ROUTINE_FLAGS.RRF_RT_REG_MULTI_SZ, out string? cachedExtensions);
33+
if (!fRes)
34+
{
35+
yield break;
36+
}
37+
38+
// TODO: Access each cached extension and get the ShellNewItem properties
39+
}
40+
41+
private static IEnumerable<ShellNewItem> GetItemsFromAssoc()
1442
{
1543
var newMenuItems = new List<ShellNewItem>();
16-
string[] extensionsExcluded = [ ".contact", ".library-ms", ".url", ".lnk" ];
44+
string[] extensionsExcluded = [".contact", ".library-ms", ".url", ".lnk"];
1745

1846
// Get a handle of HKEY_CLASSES_ROOT
1947
bool fRes = WindowsStorableHelpers.OpenRegistryKey(HKEY.HKEY_CLASSES_ROOT, string.Empty, REG_SAM_FLAGS.KEY_READ, out HKEY hKey);
@@ -41,6 +69,7 @@ public static IEnumerable<ShellNewItem> GetItems()
4169
// TODO: Add .txt if necessary
4270

4371
if (!hKey.IsNull) PInvoke.RegCloseKey(hKey);
72+
4473
}
4574
}
4675
}

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

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

4+
using System.Runtime.InteropServices;
45
using Windows.Win32;
56
using Windows.Win32.Foundation;
67
using Windows.Win32.System.Registry;
78

8-
// There are two kinds of ShellNew entry residence:
9-
//
10-
// 1.) .docx > Word.Document.12 > ShellNew
11-
// 2.) .mdb > SellNew
12-
13-
149
namespace Files.App.Storage
1510
{
1611
public unsafe static partial class WindowsStorableHelpers
1712
{
1813
public static bool OpenRegistryKey(HKEY hRootKey, string subKey, REG_SAM_FLAGS flags, out HKEY hKey)
1914
{
20-
hKey = default;
21-
22-
HKEY hResultKey = default;
2315
WIN32_ERROR dwResult = default;
16+
HKEY hResultKey = default;
2417

2518
fixed (char* pszSubKey = subKey)
2619
dwResult = PInvoke.RegOpenKeyEx(hRootKey, pszSubKey, 0, flags, &hResultKey);
@@ -30,6 +23,50 @@ public static bool OpenRegistryKey(HKEY hRootKey, string subKey, REG_SAM_FLAGS f
3023
return dwResult is WIN32_ERROR.ERROR_SUCCESS;
3124
}
3225

26+
public static bool GetRegistryValue<T>(HKEY hRootKey, string subKey, string valueName, REG_ROUTINE_FLAGS flags, out T? valueData)
27+
{
28+
valueData = default;
29+
30+
WIN32_ERROR dwResult = default;
31+
HKEY hKey = hRootKey;
32+
33+
if (!string.IsNullOrEmpty(subKey))
34+
{
35+
fixed (char* pszSubKey = subKey)
36+
dwResult = PInvoke.RegOpenKeyEx(hRootKey, pszSubKey, 0, REG_SAM_FLAGS.KEY_QUERY_VALUE, &hKey);
37+
38+
if (dwResult is not WIN32_ERROR.ERROR_SUCCESS)
39+
{
40+
if (!hKey.IsNull) PInvoke.RegCloseKey(hKey);
41+
return false;
42+
}
43+
}
44+
45+
byte* pData = null;
46+
uint cbData = 0U;
47+
48+
fixed (char* pszValueName = valueName)
49+
{
50+
dwResult = PInvoke.RegGetValue(hKey, default, pszValueName, flags, null, null, &cbData);
51+
52+
if (dwResult is WIN32_ERROR.ERROR_SUCCESS or WIN32_ERROR.ERROR_MORE_DATA)
53+
{
54+
if (cbData is 0U)
55+
return false;
56+
57+
pData = (byte*)NativeMemory.Alloc(cbData);
58+
dwResult = PInvoke.RegGetValue(hKey, default, pszValueName, flags, null, pData, &cbData);
59+
60+
valueData = Marshal.PtrToStructure<T>((nint)pData);
61+
NativeMemory.Free(pData);
62+
}
63+
}
64+
65+
if (!hKey.IsNull) PInvoke.RegCloseKey(hKey);
66+
67+
return dwResult is WIN32_ERROR.ERROR_SUCCESS;
68+
}
69+
3370
public static string[] EnumerateRegistryKeyNames(HKEY hKey)
3471
{
3572
WIN32_ERROR dwResult = default;

0 commit comments

Comments
 (0)