Skip to content

Commit 33efe98

Browse files
committed
Init
1 parent 6017192 commit 33efe98

File tree

20 files changed

+675
-302
lines changed

20 files changed

+675
-302
lines changed

src/Files.App.BackgroundTasks/Files.App.BackgroundTasks.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,8 @@
2424
<PackageReference Include="Microsoft.Windows.CsWinRT" />
2525
</ItemGroup>
2626

27+
<ItemGroup>
28+
<ProjectReference Include="..\Files.App.Storage\Files.App.Storage.csproj" />
29+
</ItemGroup>
30+
2731
</Project>
Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
// Copyright (c) Files Community
22
// Licensed under the MIT License.
33

4-
using System;
4+
using Files.App.Storage;
55
using System.IO;
6-
using System.Linq;
76
using System.Threading.Tasks;
87
using Windows.ApplicationModel.Background;
98
using Windows.Storage;
10-
using Windows.UI.StartScreen;
119

1210
namespace Files.App.BackgroundTasks
1311
{
@@ -19,8 +17,8 @@ private async Task RunAsync(IBackgroundTaskInstance taskInstance)
1917
{
2018
var deferral = taskInstance.GetDeferral();
2119

22-
// Refresh jump list to update string resources
23-
try { await RefreshJumpListAsync(); } catch { }
20+
// Sync the jump list with Explorer
21+
try { RefreshJumpList(); } catch { }
2422

2523
// Delete previous version log files
2624
try { DeleteLogFiles(); } catch { }
@@ -34,30 +32,19 @@ private void DeleteLogFiles()
3432
File.Delete(Path.Combine(ApplicationData.Current.LocalFolder.Path, "debug_fulltrust.log"));
3533
}
3634

37-
private async Task RefreshJumpListAsync()
35+
private void RefreshJumpList()
3836
{
39-
if (JumpList.IsSupported())
37+
// Make sure to delete the Files' custom destinations binary files
38+
var recentFolder = JumpListManager.Default.GetRecentFolderPath();
39+
File.Delete($"{recentFolder}\\CustomDestinations\\3b19d860a346d7da.customDestinations-ms");
40+
File.Delete($"{recentFolder}\\CustomDestinations\\1265066178db259d.customDestinations-ms");
41+
File.Delete($"{recentFolder}\\CustomDestinations\\8e2322986488aba5.customDestinations-ms");
42+
File.Delete($"{recentFolder}\\CustomDestinations\\6b0bf5ca007c8bea.customDestinations-ms");
43+
44+
_ = STATask.Run(() =>
4045
{
41-
var instance = await JumpList.LoadCurrentAsync();
42-
// Disable automatic jumplist. It doesn't work with Files UWP.
43-
instance.SystemGroupKind = JumpListSystemGroupKind.None;
44-
45-
var jumpListItems = instance.Items.ToList();
46-
47-
// Clear all items to avoid localization issues
48-
instance.Items.Clear();
49-
50-
foreach (var temp in jumpListItems)
51-
{
52-
var jumplistItem = JumpListItem.CreateWithArguments(temp.Arguments, temp.DisplayName);
53-
jumplistItem.Description = jumplistItem.Arguments;
54-
jumplistItem.GroupName = "ms-resource:///Resources/JumpListRecentGroupHeader";
55-
jumplistItem.Logo = new Uri("ms-appx:///Assets/FolderIcon.png");
56-
instance.Items.Add(jumplistItem);
57-
}
58-
59-
await instance.SaveAsync();
60-
}
46+
JumpListManager.Default.FetchJumpListFromExplorer();
47+
});
6148
}
6249
}
6350
}

src/Files.App.CsWin32/ComPtr`1.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@ public void Attach(T* other)
5050
return ptr;
5151
}
5252

53+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
54+
public readonly HRESULT CopyTo(T** ptr)
55+
{
56+
InternalAddRef();
57+
*ptr = _ptr;
58+
59+
return HRESULT.S_OK;
60+
}
61+
5362
[MethodImpl(MethodImplOptions.AggressiveInlining)]
5463
public readonly T* Get()
5564
{
@@ -80,6 +89,14 @@ public readonly HRESULT CoCreateInstance(Guid* rclsid, IUnknown* pUnkOuter = nul
8089
return PInvoke.CoCreateInstance(rclsid, pUnkOuter, dwClsContext, (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in T.Guid)), (void**)this.GetAddressOf());
8190
}
8291

92+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
93+
private readonly void InternalAddRef()
94+
{
95+
T* ptr = _ptr;
96+
if (ptr != null)
97+
_ = ((IUnknown*)ptr)->AddRef();
98+
}
99+
83100
// Disposer
84101

85102
[MethodImpl(MethodImplOptions.AggressiveInlining)]
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// Copyright (c) Files Community
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Runtime.CompilerServices;
6+
using System.Runtime.InteropServices;
7+
using Windows.Win32.Foundation;
8+
using Windows.Win32.UI.Shell;
9+
10+
namespace Windows.Win32.System.Com
11+
{
12+
/// <summary>
13+
/// Defines unmanaged raw vtable for the <see cref="IAutomaticDestinationList"/> interface.
14+
/// </summary>
15+
public unsafe partial struct IAutomaticDestinationList : IComIID
16+
{
17+
#pragma warning disable CS0649 // Field 'field' is never assigned to, and will always have its default value 'value'
18+
private void** lpVtbl;
19+
#pragma warning restore CS0649 // Field 'field' is never assigned to, and will always have its default value 'value'
20+
21+
/// <summary>
22+
/// Initializes this instance of <see cref="IAutomaticDestinationList"/> with the specified Application User Model ID (AMUID).
23+
/// </summary>
24+
/// <param name="szAppId">The Application User Model ID to initialize this instance of <see cref="IAutomaticDestinationList"/> with.</param>
25+
/// <param name="a2">Unknown argument. Apparently this can be NULL.</param>
26+
/// <param name="a3">Unknown argument. Apparently this can be NULL.</param>
27+
/// <returns>Returns <see cref="HRESULT.S_OK"/> if successful, or an error value otherwise.</returns>
28+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
29+
public HRESULT Initialize(PCWSTR szAppId, PCWSTR a2, PCWSTR a3)
30+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IAutomaticDestinationList*, PCWSTR, PCWSTR, PCWSTR, int>)lpVtbl[3])
31+
((IAutomaticDestinationList*)Unsafe.AsPointer(ref this), szAppId, a2, a3);
32+
33+
/// <summary>
34+
/// Gets a value that determines whether this <see cref="IAutomaticDestinationList"/> has any list.
35+
/// </summary>
36+
/// <param name="pfHasList">A pointer to a <see cref="BOOL"/> that receives the result. <see cref="BOOL.TRUE"/> if there's any list; otherwise, <see cref="BOOL.FALSE"/>.</param>
37+
/// <returns>Returns <see cref="HRESULT.S_OK"/> if successful, or an error value otherwise.</returns>
38+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
39+
public HRESULT HasList(BOOL* pfHasList)
40+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IAutomaticDestinationList*, BOOL*, int>)lpVtbl[4])
41+
((IAutomaticDestinationList*)Unsafe.AsPointer(ref this), pfHasList);
42+
43+
/// <summary>
44+
/// Gets the list of automatic destinations of the specified type.
45+
/// </summary>
46+
/// <param name="type">The type to get the automatic destinations of.</param>
47+
/// <param name="maxCount">The max count to get the automatic destinations up to.</param>
48+
/// <param name="flags">The flags to filter up the queried destinations.</param>
49+
/// <param name="riid">A reference to the interface identifier (IID) of the interface being queried for.</param>
50+
/// <param name="ppvObject">The address of a pointer to an interface with the IID specified in the riid parameter.</param>
51+
/// <returns>Returns <see cref="HRESULT.S_OK"/> if successful, or an error value otherwise.</returns>
52+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
53+
public HRESULT GetList(DESTLISTTYPE type, int maxCount, GETDESTLISTFLAGS flags, Guid* riid, void** ppvObject)
54+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IAutomaticDestinationList*, DESTLISTTYPE, int, GETDESTLISTFLAGS, Guid*, void**, int>)lpVtbl[5])
55+
((IAutomaticDestinationList*)Unsafe.AsPointer(ref this), type, maxCount, flags, riid, ppvObject);
56+
57+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
58+
public HRESULT AddUsagePoint(IUnknown* pUnk)
59+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IAutomaticDestinationList*, IUnknown*, int>)lpVtbl[6])
60+
((IAutomaticDestinationList*)Unsafe.AsPointer(ref this), pUnk);
61+
62+
/// <summary>
63+
/// Pins an item to the list.
64+
/// </summary>
65+
/// <param name="pUnk">The native object to pin to the list.</param>
66+
/// <param name="index">-1 to pin to the last, -2 to unpin, zero or positive numbers (>= 0) indicate the index to pin to the list at. Passing the other numbers are *UB*.</param>
67+
/// <returns>Returns <see cref="HRESULT.S_OK"/> if successful, or an error value otherwise.</returns>
68+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
69+
public HRESULT PinItem(IUnknown* pUnk, int index)
70+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IAutomaticDestinationList*, IUnknown*, int, int>)lpVtbl[7])
71+
((IAutomaticDestinationList*)Unsafe.AsPointer(ref this), pUnk, index);
72+
73+
/// <summary>
74+
/// Gets the index of a pinned item in the Pinned list.
75+
/// </summary>
76+
/// <remarks>
77+
/// According to the debug symbols, this method is called "IsPinned" and other definitions out there also define so
78+
/// but it is inappropriate based on the fact it actually calls an internal method that gets the index of a pinned item
79+
/// and returns it in the second argument. If you want to check if an item is pinned, you should use IShellItem::Compare for IShellItem,
80+
/// or compare IShellLinkW::GetPath, IShellLinkW::GetArguments and PKEY_Title for IShellLinkW, which is actually done, at least, in Windows 7 era.
81+
/// </remarks>
82+
/// <param name="punk">The native object to get its index in the list.</param>
83+
/// <param name="piIndex">A pointer that points to an int value that takes the index of the item passed.</param>
84+
/// <returns>Returns <see cref="HRESULT.S_OK"/> if successful, or an error value otherwise. If the passed item doesn't belong to the <see cref="DESTLISTTYPE.PINNED"/> list, HRESULT.E_NOT_SET is returned.</returns>
85+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
86+
public HRESULT GetPinIndex(IUnknown* punk, int* piIndex)
87+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IAutomaticDestinationList*, IUnknown*, int*, int>)lpVtbl[8])
88+
((IAutomaticDestinationList*)Unsafe.AsPointer(ref this), punk, piIndex);
89+
90+
/// <summary>
91+
/// Removes a destination from the automatic destinations list.
92+
/// </summary>
93+
/// <param name="psi">The destination to remove from the automatic destinations list.</param>
94+
/// <returns>Returns <see cref="HRESULT.S_OK"/> if successful, or an error value otherwise.
95+
public HRESULT RemoveDestination(IUnknown* psi)
96+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IAutomaticDestinationList*, IUnknown*, int>)lpVtbl[9])
97+
((IAutomaticDestinationList*)Unsafe.AsPointer(ref this), psi);
98+
99+
public HRESULT SetUsageData(IUnknown* pItem, float* a2, long* pFileTime)
100+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IAutomaticDestinationList*, IUnknown*, float*, long*, int>)lpVtbl[10])
101+
((IAutomaticDestinationList*)Unsafe.AsPointer(ref this), pItem, a2, pFileTime);
102+
103+
public HRESULT GetUsageData(IUnknown* pItem, float* a2, long* pFileTime)
104+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IAutomaticDestinationList*, IUnknown*, float*, long*, int>)lpVtbl[11])
105+
((IAutomaticDestinationList*)Unsafe.AsPointer(ref this), pItem, a2, pFileTime);
106+
107+
public HRESULT ResolveDestination(HWND hWnd, int a2, IShellItem* pShellItem, Guid* riid, void** ppvObject)
108+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IAutomaticDestinationList*, HWND, int, IShellItem*, Guid*, void**, int>)lpVtbl[12])
109+
((IAutomaticDestinationList*)Unsafe.AsPointer(ref this), hWnd, a2, pShellItem, riid, ppvObject);
110+
111+
public HRESULT ClearList(BOOL clearPinsToo)
112+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IAutomaticDestinationList*, BOOL, int>)lpVtbl[13])
113+
((IAutomaticDestinationList*)Unsafe.AsPointer(ref this), clearPinsToo);
114+
115+
[GuidRVAGen.Guid("E9C5EF8D-FD41-4F72-BA87-EB03BAD5817C")]
116+
public static partial ref readonly Guid Guid { get; }
117+
118+
internal static ref readonly Guid IID_Guid
119+
=> ref MemoryMarshal.AsRef<Guid>([0xBF, 0xDE, 0x32, 0x63, 0xB5, 0x87, 0x70, 0x46, 0x90, 0xC0, 0x5E, 0x57, 0xB4, 0x08, 0xA4, 0x9E]);
120+
121+
internal static Guid* IID_Guid2
122+
=> (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_Guid));
123+
124+
static ref readonly Guid IComIID.Guid => ref IID_Guid;
125+
}
126+
127+
public enum DESTLISTTYPE : uint
128+
{
129+
PINNED,
130+
RECENT,
131+
FREQUENT,
132+
}
133+
134+
public enum GETDESTLISTFLAGS : uint
135+
{
136+
NONE,
137+
EXCLUDE_UNNAMED_DESTINATIONS,
138+
}
139+
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
// Copyright (c) 0x5BFA. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Runtime.CompilerServices;
6+
using System.Runtime.InteropServices;
7+
using Windows.Win32.Foundation;
8+
using Windows.Win32.UI.Shell;
9+
10+
namespace Windows.Win32.System.Com
11+
{
12+
/// <summary>
13+
/// Defines unmanaged raw vtable for the <see cref="IInternalCustomDestinationList"/> interface.
14+
/// </summary>
15+
/// <remarks>
16+
/// - <a href="https://github.com/GigabyteProductions/classicshell/blob/HEAD/src/ClassicStartMenu/ClassicStartMenuDLL/JumpLists.cpp"/>
17+
/// </remarks>
18+
public unsafe partial struct IInternalCustomDestinationList : IComIID
19+
{
20+
#pragma warning disable CS0649 // Field 'field' is never assigned to, and will always have its default value 'value'
21+
private void** lpVtbl;
22+
#pragma warning restore CS0649 // Field 'field' is never assigned to, and will always have its default value 'value'
23+
24+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
25+
public HRESULT SetMinItems(uint dwMinItems)
26+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IInternalCustomDestinationList*, uint, int>)lpVtbl[3])(
27+
(IInternalCustomDestinationList*)Unsafe.AsPointer(ref this), dwMinItems);
28+
29+
/// <summary>
30+
/// Initializes this instance of <see cref="IInternalCustomDestinationList"/> with the specified Application User Model ID (AMUID).
31+
/// </summary>
32+
/// <param name="pszAppID">The Application User Model ID to initialize this instance of <see cref="IInternalCustomDestinationList"/> with.</param>
33+
/// <returns>Returns <see cref="HRESULT.S_OK"/> if successful, or an error value otherwise.</returns>
34+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
35+
public HRESULT SetApplicationID(PCWSTR pszAppID)
36+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IInternalCustomDestinationList*, PCWSTR, int>)lpVtbl[4])(
37+
(IInternalCustomDestinationList*)Unsafe.AsPointer(ref this), pszAppID);
38+
39+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
40+
public HRESULT GetSlotCount(uint* pSlotCount)
41+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IInternalCustomDestinationList*, uint*, int>)lpVtbl[5])(
42+
(IInternalCustomDestinationList*)Unsafe.AsPointer(ref this), pSlotCount);
43+
44+
/// <summary>
45+
/// Gets the number of categories in the custom destination list.
46+
/// </summary>
47+
/// <param name="pdwCategoryCount">A pointer that points to a valid <see langword="uint"/> var.</param>
48+
/// <returns>Returns <see cref="HRESULT.S_OK"/> if successful, or an error value otherwise.</returns>
49+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
50+
public HRESULT GetCategoryCount(uint* pCategoryCount)
51+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IInternalCustomDestinationList*, uint*, int>)lpVtbl[6])(
52+
(IInternalCustomDestinationList*)Unsafe.AsPointer(ref this), pCategoryCount);
53+
54+
/// <summary>
55+
/// Gets the category at the specified index in the custom destination list.
56+
/// </summary>
57+
/// <param name="index">The index to get the category in the custom destination list at.</param>
58+
/// <param name="flags">The flags to filter up the queried destinations.</param>
59+
/// <param name="pCategory">A pointer that points to a valid <see cref="APPDESTCATEGORY"/> var.</param>
60+
/// <returns>Returns <see cref="HRESULT.S_OK"/> if successful, or an error value otherwise.</returns>
61+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
62+
public HRESULT GetCategory(uint index, GETCATFLAG flags, APPDESTCATEGORY* pCategory)
63+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IInternalCustomDestinationList*, uint, GETCATFLAG, APPDESTCATEGORY*, int>)lpVtbl[7])(
64+
(IInternalCustomDestinationList*)Unsafe.AsPointer(ref this), index, flags, pCategory);
65+
66+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
67+
public HRESULT DeleteCategory(uint index, BOOL deletePermanently)
68+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IInternalCustomDestinationList*, uint, BOOL, int>)lpVtbl[8])(
69+
(IInternalCustomDestinationList*)Unsafe.AsPointer(ref this), index, deletePermanently);
70+
71+
/// <summary>
72+
/// Enumerates the destinations at the specific index in the categories in the custom destinations.
73+
/// </summary>
74+
/// <param name="index">The index to get the destinations at in the categories.</param>
75+
/// <param name="riid">A reference to the interface identifier (IID) of the interface being queried for.</param>
76+
/// <param name="ppvObject">The address of a pointer to an interface with the IID specified in the riid parameter.</param>
77+
/// <returns>Returns <see cref="HRESULT.S_OK"/> if successful, or an error value otherwise.</returns>
78+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
79+
public HRESULT EnumerateCategoryDestinations(uint index, Guid* riid, void** ppvObject)
80+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IInternalCustomDestinationList*, uint, Guid*, void**, int>)lpVtbl[9])(
81+
(IInternalCustomDestinationList*)Unsafe.AsPointer(ref this), index, riid, ppvObject);
82+
83+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
84+
public HRESULT RemoveDestination(IUnknown* pUnk)
85+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IInternalCustomDestinationList*, IUnknown*, int>)lpVtbl[10])
86+
((IInternalCustomDestinationList*)Unsafe.AsPointer(ref this), pUnk);
87+
88+
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
89+
//public HRESULT ResolveDestination(...)
90+
// => (HRESULT)((delegate* unmanaged[MemberFunction]<IInternalCustomDestinationList*, ..., int>)lpVtbl[11])
91+
// ((IInternalCustomDestinationList*)Unsafe.AsPointer(ref this), ...);
92+
93+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
94+
public HRESULT HasListEx(int* a1, int* a2)
95+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IInternalCustomDestinationList*, int*, int*, int>)lpVtbl[12])
96+
((IInternalCustomDestinationList*)Unsafe.AsPointer(ref this), a1, a2);
97+
98+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
99+
public HRESULT ClearRemovedDestinations()
100+
=> (HRESULT)((delegate* unmanaged[MemberFunction]<IInternalCustomDestinationList*, int>)lpVtbl[13])
101+
((IInternalCustomDestinationList*)Unsafe.AsPointer(ref this));
102+
103+
static ref readonly Guid IComIID.Guid => throw new NotImplementedException();
104+
}
105+
106+
[StructLayout(LayoutKind.Sequential)]
107+
public unsafe struct APPDESTCATEGORY
108+
{
109+
[StructLayout(LayoutKind.Explicit)]
110+
public struct _Anonymous_e__Union
111+
{
112+
[FieldOffset(0)]
113+
public PWSTR Name;
114+
115+
[FieldOffset(0)]
116+
public int SubType;
117+
}
118+
119+
public APPDESTCATEGORYTYPE Type;
120+
121+
public _Anonymous_e__Union Anonymous;
122+
123+
public int Count;
124+
125+
public fixed int Padding[10];
126+
}
127+
128+
public enum GETCATFLAG : uint
129+
{
130+
// 1 is the only valid value?
131+
DEFAULT = 1,
132+
}
133+
134+
public enum APPDESTCATEGORYTYPE : uint
135+
{
136+
CUSTOM = 0,
137+
KNOWN = 1,
138+
TASKS = 2,
139+
}
140+
}

0 commit comments

Comments
 (0)