22// Licensed under the MIT License.
33
44using System . IO ;
5- using System . Reflection . Metadata . Ecma335 ;
65using System . Runtime . CompilerServices ;
76using System . Runtime . InteropServices ;
87using Windows . ApplicationModel ;
@@ -25,14 +24,18 @@ namespace Files.App.Storage
2524 /// </remarks>
2625 public unsafe class JumpListManager : IDisposable
2726 {
28- private static readonly Lazy < JumpListManager > _default = new ( ( ) => new JumpListManager ( ) , LazyThreadSafetyMode . ExecutionAndPublication ) ;
29- public static JumpListManager Default => _default . Value ;
27+ private static readonly Lazy < JumpListManager ? > _default = new ( ( ) => Create ( ) , LazyThreadSafetyMode . ExecutionAndPublication ) ;
28+ public static JumpListManager ? Default => _default . Value ;
3029
3130 private readonly static string _aumid = $ "{ Package . Current . Id . FamilyName } !App";
3231
3332 private FileSystemWatcher ? _explorerJumpListWatcher ;
3433 private FileSystemWatcher ? _filesJumpListWatcher ;
3534
35+ private IAutomaticDestinationList * _explorerADL ;
36+ private IAutomaticDestinationList * _filesADL ;
37+ private ICustomDestinationList * _filesCDL ;
38+
3639 public bool PullJumpListFromExplorer ( int maxCount = 40 )
3740 {
3841 if ( _filesJumpListWatcher is not null && _filesJumpListWatcher . EnableRaisingEvents )
@@ -53,7 +56,7 @@ public bool PushJumpListToExplorer(int maxCount = 40)
5356 if ( _explorerJumpListWatcher is not null && _explorerJumpListWatcher . EnableRaisingEvents )
5457 _explorerJumpListWatcher . EnableRaisingEvents = false ;
5558
56- // ClearAutomaticDestinationsOf("Microsoft.Windows.Explorer");
59+ ClearAutomaticDestinationsOf ( "Microsoft.Windows.Explorer" ) ;
5760
5861 //SyncJumpList(_aumid, "Microsoft.Windows.Explorer", maxCount);
5962
@@ -106,6 +109,32 @@ public string GetRecentFolderPath()
106109 return new ( pwszRecentFolderPath . Get ( ) ) ;
107110 }
108111
112+ private static JumpListManager ? Create ( )
113+ {
114+ HRESULT hr = default ;
115+
116+ void * pv = default ;
117+
118+ var instance = new JumpListManager ( ) ;
119+
120+ hr = PInvoke . CoCreateInstance ( CLSID . CLSID_AutomaticDestinationList , null , CLSCTX . CLSCTX_INPROC_SERVER , IID . IID_IAutomaticDestinationList , & pv ) ;
121+ if ( FAILED ( hr ) ) return null ;
122+ instance . _explorerADL = ( IAutomaticDestinationList * ) pv ;
123+ instance . _explorerADL ->Initialize ( ( PCWSTR ) Unsafe . AsPointer ( ref Unsafe . AsRef ( in "Microsoft.Windows.Explorer" . GetPinnableReference ( ) ) ) , default , default ) ;
124+
125+ hr = PInvoke . CoCreateInstance ( CLSID . CLSID_AutomaticDestinationList , null , CLSCTX . CLSCTX_INPROC_SERVER , IID . IID_IAutomaticDestinationList , & pv ) ;
126+ if ( FAILED ( hr ) ) return null ;
127+ instance . _filesADL = ( IAutomaticDestinationList * ) pv ;
128+ instance . _filesADL ->Initialize ( ( PCWSTR ) Unsafe . AsPointer ( ref Unsafe . AsRef ( in _aumid . GetPinnableReference ( ) ) ) , default , default ) ;
129+
130+ hr = PInvoke . CoCreateInstance ( CLSID . CLSID_DestinationList , null , CLSCTX . CLSCTX_INPROC_SERVER , IID . IID_ICustomDestinationList , & pv ) ;
131+ if ( FAILED ( hr ) ) return null ;
132+ instance . _filesCDL = ( ICustomDestinationList * ) pv ;
133+ instance . _filesCDL ->SetAppID ( ( PCWSTR ) Unsafe . AsPointer ( ref Unsafe . AsRef ( in _aumid . GetPinnableReference ( ) ) ) ) ;
134+
135+ return instance ;
136+ }
137+
109138 private bool SyncJumpList ( string sourceAppAUIMD , string destinationAppAUMID , int maxItemsToSync )
110139 {
111140 HRESULT hr = default ;
@@ -118,30 +147,9 @@ private bool SyncJumpList(string sourceAppAUIMD, string destinationAppAUMID, int
118147 using ComPtr < IObjectCollection > pPinnedOC = default ;
119148 GetPinnedItemsOf ( sourceAppAUIMD , maxItemsToSync , pPinnedOC . GetAddressOf ( ) ) ;
120149
121- using ComPtr < IAutomaticDestinationList > pSourceADL = default ;
122- hr = PInvoke . CoCreateInstance ( CLSID . CLSID_AutomaticDestinationList , null , CLSCTX . CLSCTX_INPROC_SERVER , IID . IID_IAutomaticDestinationList , ( void * * ) pSourceADL . GetAddressOf ( ) ) ;
123- if ( FAILED ( hr ) ) return false ;
124-
125- hr = pSourceADL . Get ( ) ->Initialize ( ( PCWSTR ) Unsafe . AsPointer ( ref Unsafe . AsRef ( in sourceAppAUIMD . GetPinnableReference ( ) ) ) , default , default ) ;
126- if ( FAILED ( hr ) ) return false ;
127-
128- using ComPtr < IAutomaticDestinationList > pDestinationADL = default ;
129- hr = PInvoke . CoCreateInstance ( CLSID . CLSID_AutomaticDestinationList , null , CLSCTX . CLSCTX_INPROC_SERVER , IID . IID_IAutomaticDestinationList , ( void * * ) pDestinationADL . GetAddressOf ( ) ) ;
130- if ( FAILED ( hr ) ) return false ;
131-
132- hr = pDestinationADL . Get ( ) ->Initialize ( ( PCWSTR ) Unsafe . AsPointer ( ref Unsafe . AsRef ( in destinationAppAUMID . GetPinnableReference ( ) ) ) , default , default ) ;
133- if ( FAILED ( hr ) ) return false ;
134-
135- using ComPtr < ICustomDestinationList > pDestinationCDL = default ;
136- hr = PInvoke . CoCreateInstance ( CLSID . CLSID_DestinationList , null , CLSCTX . CLSCTX_INPROC_SERVER , IID . IID_ICustomDestinationList , ( void * * ) pDestinationCDL . GetAddressOf ( ) ) ;
137- if ( FAILED ( hr ) ) return false ;
138-
139- hr = pDestinationCDL . Get ( ) ->SetAppID ( ( PCWSTR ) Unsafe . AsPointer ( ref Unsafe . AsRef ( in destinationAppAUMID . GetPinnableReference ( ) ) ) ) ;
140- if ( FAILED ( hr ) ) return false ;
141-
142150 uint cRecentItems = 0U ;
143151 hr = pRecentOC . Get ( ) ->GetCount ( & cRecentItems ) ;
144- if ( hr . Failed ) return false ;
152+ if ( FAILED ( hr ) ) return false ;
145153
146154 using ComPtr < IObjectCollection > pNewObjectCollection = default ;
147155 hr = PInvoke . CoCreateInstance ( CLSID . CLSID_EnumerableObjectCollection , null , CLSCTX . CLSCTX_INPROC_SERVER , IID . IID_IObjectCollection , ( void * * ) pNewObjectCollection . GetAddressOf ( ) ) ;
@@ -150,19 +158,19 @@ private bool SyncJumpList(string sourceAppAUIMD, string destinationAppAUMID, int
150158 {
151159 using ComPtr < IShellItem > psi = default ;
152160 hr = pRecentOC . Get ( ) ->GetAt ( ( uint ) index , IID . IID_IShellItem , ( void * * ) psi . GetAddressOf ( ) ) ;
153- if ( hr . Failed ) continue ;
161+ if ( FAILED ( hr ) ) continue ;
154162
155163 IShellLinkW * psl = default ;
156164 CreateLinkFromItem ( psi . Get ( ) , & psl ) ;
157165
158166 hr = pNewObjectCollection . Get ( ) ->AddObject ( ( IUnknown * ) psl ) ;
159- if ( hr . Failed ) continue ;
167+ if ( FAILED ( hr ) ) continue ;
160168
161169 int pinIndex = 0 ;
162- hr = pSourceADL . Get ( ) ->GetPinIndex ( ( IUnknown * ) psi . Get ( ) , & pinIndex ) ;
170+ hr = _explorerADL ->GetPinIndex ( ( IUnknown * ) psi . Get ( ) , & pinIndex ) ;
163171 if ( FAILED ( hr ) ) continue ; // If not pinned, HRESULT is E_NOT_SET
164172
165- hr = pDestinationADL . Get ( ) ->PinItem ( ( IUnknown * ) psl , - 1 ) ;
173+ hr = _filesADL ->PinItem ( ( IUnknown * ) psl , - 1 ) ;
166174 if ( FAILED ( hr ) ) continue ;
167175 }
168176
@@ -174,18 +182,18 @@ private bool SyncJumpList(string sourceAppAUIMD, string destinationAppAUMID, int
174182 hr = PInvoke . SHLoadIndirectString (
175183 ( PCWSTR ) Unsafe . AsPointer ( ref Unsafe . AsRef ( in "@{C:\\ Windows\\ SystemResources\\ Windows.UI.ShellCommon\\ Windows.UI.ShellCommon.pri? ms-resource://Windows.UI.ShellCommon/JumpViewUI/JumpViewCategoryType_Recent}" . GetPinnableReference ( ) ) ) ,
176184 pOutBuffer , 256U ) ;
177- if ( hr . Failed ) return false ;
185+ if ( FAILED ( hr ) ) return false ;
178186
179187 uint cMinSlots ;
180188 using ComPtr < IObjectArray > pRemovedObjectArray = default ;
181- hr = pDestinationCDL . Get ( ) ->BeginList ( & cMinSlots , IID . IID_IObjectArray , ( void * * ) pRemovedObjectArray . GetAddressOf ( ) ) ;
182- if ( hr . Failed ) return false ;
189+ hr = _filesCDL ->BeginList ( & cMinSlots , IID . IID_IObjectArray , ( void * * ) pRemovedObjectArray . GetAddressOf ( ) ) ;
190+ if ( FAILED ( hr ) ) return false ;
183191
184- hr = pDestinationCDL . Get ( ) ->AppendCategory ( pOutBuffer , pNewObjectArray . Get ( ) ) ;
185- if ( hr . Failed ) return false ;
192+ hr = _filesCDL ->AppendCategory ( pOutBuffer , pNewObjectArray . Get ( ) ) ;
193+ if ( FAILED ( hr ) ) return false ;
186194
187- hr = pDestinationCDL . Get ( ) ->CommitList ( ) ;
188- if ( hr . Failed ) return false ;
195+ hr = _filesCDL ->CommitList ( ) ;
196+ if ( FAILED ( hr ) ) return false ;
189197
190198 NativeMemory . Free ( pOutBuffer ) ;
191199
@@ -343,11 +351,21 @@ private void FilesJumpListWatcher_Changed(object sender, FileSystemEventArgs e)
343351
344352 public void Dispose ( )
345353 {
354+ if ( _filesJumpListWatcher is not null )
355+ {
356+ _filesJumpListWatcher . EnableRaisingEvents = false ;
357+ _filesJumpListWatcher . Dispose ( ) ;
358+ }
359+
346360 if ( _explorerJumpListWatcher is not null )
347361 {
348362 _explorerJumpListWatcher . EnableRaisingEvents = false ;
349363 _explorerJumpListWatcher . Dispose ( ) ;
350364 }
365+
366+ if ( _explorerADL is not null ) ( ( IUnknown * ) _explorerADL ) ->Release ( ) ;
367+ if ( _filesADL is not null ) ( ( IUnknown * ) _filesADL ) ->Release ( ) ;
368+ if ( _filesCDL is not null ) ( ( IUnknown * ) _filesCDL ) ->Release ( ) ;
351369 }
352370 }
353371}
0 commit comments