44using System . IO ;
55using System . Runtime . CompilerServices ;
66using Windows . ApplicationModel ;
7+ using Windows . Devices . Enumeration . Pnp ;
78using Windows . Win32 ;
89using Windows . Win32 . Foundation ;
910using Windows . Win32 . System . Com ;
@@ -167,7 +168,7 @@ private HRESULT SyncFilesJumpListWithExplorer(int maxItemsToSync)
167168 {
168169 HRESULT hr = default ;
169170
170- // If the Explorer 's Automatic Destination has no items, nothing to sync
171+ // Get whether the Files 's Automatic Destination has items
171172 BOOL hasList = default ;
172173 hr = _filesADL ->HasList ( & hasList ) ;
173174 if ( FAILED ( hr ) ) return hr ;
@@ -192,27 +193,27 @@ private HRESULT SyncFilesJumpListWithExplorer(int maxItemsToSync)
192193 hr = poc . Get ( ) ->GetCount ( & dwItemsCount ) ;
193194 if ( FAILED ( hr ) ) return hr ;
194195
195- // for (uint dwIndex = 0; dwIndex < dwItemsCount; dwIndex++)
196- // {
197- // // Get an instance of IShellItem
198- // using ComPtr<IShellItem> psi = default;
199- // hr = poc.Get()->GetAt(dwIndex, IID.IID_IShellItem, (void**)psi.GetAddressOf());
200- // if (FAILED(hr)) continue;
196+ for ( uint dwIndex = 0 ; dwIndex < dwItemsCount ; dwIndex ++ )
197+ {
198+ // Get an instance of IShellItem
199+ using ComPtr < IShellItem > psi = default ;
200+ hr = poc . Get ( ) ->GetAt ( dwIndex , IID . IID_IShellItem , ( void * * ) psi . GetAddressOf ( ) ) ;
201+ if ( FAILED ( hr ) ) continue ;
201202
202- // // Get its pin index
203- // int pinIndex = 0;
204- // hr = _explorerADL->GetPinIndex((IUnknown*)psi.Get(), &pinIndex);
205- // if (FAILED(hr)) continue;
203+ // Get its pin index
204+ int pinIndex = 0 ;
205+ hr = _explorerADL ->GetPinIndex ( ( IUnknown * ) psi . Get ( ) , & pinIndex ) ;
206+ if ( FAILED ( hr ) ) continue ;
206207
207- // // Get an instance of IShellLinkW from the IShellItem instance
208- // IShellLinkW* psl = default;
209- // hr = CreateLinkFromItem(psi.Get(), &psl);
210- // if (FAILED(hr)) continue;
208+ // Get an instance of IShellLinkW from the IShellItem instance
209+ IShellLinkW * psl = default ;
210+ hr = CreateLinkFromItem ( psi . Get ( ) , & psl ) ;
211+ if ( FAILED ( hr ) ) continue ;
211212
212- // // Pin it to the Files' Automatic Destinations
213- // hr = _filesADL->PinItem((IUnknown*)psl, pinIndex);
214- // if (FAILED(hr)) continue;
215- // }
213+ // Pin it to the Files' Automatic Destinations
214+ hr = _filesADL ->PinItem ( ( IUnknown * ) psl , pinIndex ) ;
215+ if ( FAILED ( hr ) ) continue ;
216+ }
216217
217218 // Get the Explorer's Recent items from its Automatic Destination
218219 poc . Dispose ( ) ;
@@ -226,6 +227,7 @@ private HRESULT SyncFilesJumpListWithExplorer(int maxItemsToSync)
226227 // Instantiate an instance of IObjectCollection
227228 using ComPtr < IObjectCollection > pNewObjectCollection = default ;
228229 hr = PInvoke . CoCreateInstance ( CLSID . CLSID_EnumerableObjectCollection , null , CLSCTX . CLSCTX_INPROC_SERVER , IID . IID_IObjectCollection , ( void * * ) pNewObjectCollection . GetAddressOf ( ) ) ;
230+ if ( FAILED ( hr ) ) return hr ;
229231
230232 for ( uint dwIndex = 0 ; dwIndex < dwItemsCount ; dwIndex ++ )
231233 {
@@ -260,8 +262,11 @@ private HRESULT SyncFilesJumpListWithExplorer(int maxItemsToSync)
260262 hr = _filesCDL ->BeginList ( & cMinSlots , IID . IID_IObjectArray , ( void * * ) pRemovedObjectArray . GetAddressOf ( ) ) ;
261263 if ( FAILED ( hr ) ) return hr ;
262264
265+ hr = pRemovedObjectArray . Get ( ) ->GetCount ( out var count ) ;
266+ if ( FAILED ( hr ) ) return hr ;
267+
263268 // Append "Recent" category
264- hr = _filesCDL ->AppendCategory ( ( PCWSTR ) Unsafe . AsPointer ( ref Unsafe . AsRef ( in _localizedRecentCategoryName . GetPinnableReference ( ) ) ) , pNewObjectArray . Get ( ) ) ;
269+ hr = _filesCDL ->AppendCategory ( ( PCWSTR ) Unsafe . AsPointer ( ref Unsafe . AsRef ( in "Recent" . GetPinnableReference ( ) ) ) , pNewObjectArray . Get ( ) ) ;
265270 if ( FAILED ( hr ) ) return hr ;
266271
267272 // Commit the collection updates
@@ -275,71 +280,106 @@ private HRESULT SyncExplorerJumpListWithFiles(int maxItemsToSync)
275280 {
276281 HRESULT hr = default ;
277282
283+ // Get whether the Explorer's Automatic Destination has items
278284 BOOL hasList = default ;
279285 hr = _explorerADL ->HasList ( & hasList ) ;
280286 if ( FAILED ( hr ) ) return hr ;
281287
288+ // Clear the Explorer' Automatic Destination if any
282289 if ( hasList )
283290 {
284291 hr = _explorerADL ->ClearList ( true ) ;
285292 if ( FAILED ( hr ) ) return hr ;
286293 }
287294
295+ // Get the count of categories in the Files' Custom Destinations
288296 uint count = 0U ;
289297 _filesICDL ->GetCategoryCount ( & count ) ;
290298
291- uint dwDestinationsIndex = 0U ;
292- for ( uint dwIndex = 0U ; dwIndex < count ; dwIndex ++ )
299+ // Find the "Recent" category index
300+ uint indexOfRecentCategory = 0U ;
301+ for ( uint index = 0U ; index < count ; index ++ )
293302 {
294303 APPDESTCATEGORY category = default ;
295304
296305 try
297306 {
298- hr = _filesICDL ->GetCategory ( dwIndex , GETCATFLAG . DEFAULT , & category ) ;
307+ hr = _filesICDL ->GetCategory ( index , GETCATFLAG . DEFAULT , & category ) ;
299308 if ( FAILED ( hr ) ||
300309 category . Type is not APPDESTCATEGORYTYPE . CUSTOM ||
301310 ! _localizedRecentCategoryName . Equals ( new ( category . Anonymous . Name ) , StringComparison . OrdinalIgnoreCase ) )
302311 continue ;
303312
304- dwDestinationsIndex = dwIndex ;
313+ indexOfRecentCategory = index ;
305314 }
306315 finally
307-
308316 {
309317 // The memory layout at Name can be either PWSTR or int depending on the category type
310318 if ( category . Anonymous . Name . Value is not null && category . Type is APPDESTCATEGORYTYPE . CUSTOM )
311319 PInvoke . CoTaskMemFree ( category . Anonymous . Name ) ;
312320 }
313321 }
314322
315- using ComPtr < IObjectCollection > pDestinationsObjectCollection = default ;
316- hr = _filesICDL ->EnumerateCategoryDestinations ( dwDestinationsIndex , IID . IID_IObjectCollection , ( void * * ) pDestinationsObjectCollection . GetAddressOf ( ) ) ;
323+ // Get the items in the "Recent" category
324+ using ComPtr < IObjectCollection > poc = default ;
325+ hr = _filesICDL ->EnumerateCategoryDestinations ( indexOfRecentCategory , IID . IID_IObjectCollection , ( void * * ) poc . GetAddressOf ( ) ) ;
326+
327+ // Get the count of items in the "Recent" category
328+ uint countOfItems = 0U ;
329+ hr = poc . Get ( ) ->GetCount ( & countOfItems ) ;
330+ if ( FAILED ( hr ) ) return hr ;
331+
332+ // Copy them to the Explorer's Automatic Destination
333+ for ( uint index = 0U ; index < countOfItems && index < maxItemsToSync ; index ++ )
334+ {
335+ using ComPtr < IShellLinkW > psl = default ;
336+ hr = poc . Get ( ) ->GetAt ( index , IID . IID_IShellLinkW , ( void * * ) psl . GetAddressOf ( ) ) ;
337+ if ( FAILED ( hr ) ) continue ;
338+
339+ using ComHeapPtr < char > pszParseablePath = default ;
340+ pszParseablePath . Allocate ( PInvoke . MAX_PATH ) ;
341+ hr = psl . Get ( ) ->GetArguments ( pszParseablePath . Get ( ) , ( int ) PInvoke . MAX_PATH ) ;
342+
343+ using ComHeapPtr < IShellItem > psi = default ;
344+ hr = PInvoke . SHCreateItemFromParsingName ( pszParseablePath . Get ( ) , null , IID . IID_IShellItem , ( void * * ) psi . GetAddressOf ( ) ) ;
345+ if ( FAILED ( hr ) ) continue ;
346+
347+ hr = _explorerADL ->AddUsagePoint ( ( IUnknown * ) psi . Get ( ) ) ;
348+ if ( FAILED ( hr ) ) continue ;
349+ }
350+
351+ // Get the Explorer's Pinned items from its Automatic Destination
352+ poc . Dispose ( ) ;
353+ hr = _filesADL ->GetList ( DESTLISTTYPE . PINNED , maxItemsToSync , GETDESTLISTFLAGS . NONE , IID . IID_IObjectCollection , ( void * * ) poc . GetAddressOf ( ) ) ;
354+ if ( FAILED ( hr ) ) return hr ;
317355
318- uint dwItems = 0U ;
319- hr = pDestinationsObjectCollection . Get ( ) ->GetCount ( & dwItems ) ;
356+ // Get the count of the Explorer's Pinned items
357+ hr = poc . Get ( ) ->GetCount ( & countOfItems ) ;
320358 if ( FAILED ( hr ) ) return hr ;
321359
322- for ( uint dwIndex = 0U ; dwIndex < dwItems && dwIndex < maxItemsToSync ; dwIndex ++ )
360+ // Copy them to the Explorer's Automatic Destination
361+ for ( uint index = 0U ; index < countOfItems ; index ++ )
323362 {
324363 using ComPtr < IShellLinkW > psl = default ;
325- hr = pDestinationsObjectCollection . Get ( ) ->GetAt ( dwIndex , IID . IID_IShellLinkW , ( void * * ) psl . GetAddressOf ( ) ) ;
364+ hr = poc . Get ( ) ->GetAt ( index , IID . IID_IShellLinkW , ( void * * ) psl . GetAddressOf ( ) ) ;
326365 if ( FAILED ( hr ) ) continue ;
327366
328- using ComHeapPtr < ITEMIDLIST > pidl = default ;
329- hr = psl . Get ( ) ->GetIDList ( pidl . GetAddressOf ( ) ) ;
367+ using ComHeapPtr < char > pszParseablePath = default ;
368+ pszParseablePath . Allocate ( PInvoke . MAX_PATH ) ;
369+ hr = psl . Get ( ) ->GetArguments ( pszParseablePath . Get ( ) , ( int ) PInvoke . MAX_PATH ) ;
330370
331371 using ComHeapPtr < IShellItem > psi = default ;
332- hr = PInvoke . SHCreateItemFromIDList ( pidl . Get ( ) , IID . IID_IShellItem , ( void * * ) psi . GetAddressOf ( ) ) ;
372+ hr = PInvoke . SHCreateItemFromParsingName ( pszParseablePath . Get ( ) , null , IID . IID_IShellItem , ( void * * ) psi . GetAddressOf ( ) ) ;
333373 if ( FAILED ( hr ) ) continue ;
334374
335375 hr = _explorerADL ->AddUsagePoint ( ( IUnknown * ) psi . Get ( ) ) ;
336376 if ( FAILED ( hr ) ) continue ;
337377
338- int pinIndex = 0 ;
339- hr = _explorerADL ->GetPinIndex ( ( IUnknown * ) psl . Get ( ) , & pinIndex ) ;
340- if ( FAILED ( hr ) ) continue ; // If not pinned, HRESULT is E_NOT_SET
378+ int pinIndex ;
379+ hr = _filesADL ->GetPinIndex ( ( IUnknown * ) psl . Get ( ) , & pinIndex ) ;
380+ if ( FAILED ( hr ) ) continue ;
341381
342- hr = _filesADL ->PinItem ( ( IUnknown * ) psi . Get ( ) , - 1 ) ;
382+ hr = _explorerADL ->PinItem ( ( IUnknown * ) psi . Get ( ) , pinIndex ) ;
343383 if ( FAILED ( hr ) ) continue ;
344384 }
345385
@@ -348,38 +388,46 @@ category.Type is not APPDESTCATEGORYTYPE.CUSTOM ||
348388
349389 private HRESULT CreateLinkFromItem ( IShellItem * psi , IShellLinkW * * ppsl )
350390 {
391+ // Instantiate a default instance of IShellLinkW
351392 using ComPtr < IShellLinkW > psl = default ;
352393 HRESULT hr = PInvoke . CoCreateInstance ( CLSID . CLSID_ShellLink , null , CLSCTX . CLSCTX_INPROC_SERVER , IID . IID_IShellLinkW , ( void * * ) psl . GetAddressOf ( ) ) ;
353394 if ( FAILED ( hr ) ) return hr ;
354395
355- fixed ( char * pszFilesEntryPointPath = $ "Shell:AppsFolder\\ { _filesAUMID } ")
396+ // Set the Files package path in the shell namespace
397+ fixed ( char * pszFilesEntryPointPath = $ "files-dev.exe")
356398 hr = psl . Get ( ) ->SetPath ( pszFilesEntryPointPath ) ;
357399 if ( FAILED ( hr ) ) return hr ;
358400
401+ // Get the full path of the folder
359402 using ComHeapPtr < char > pszParseablePath = default ;
360403 hr = psi ->GetDisplayName ( SIGDN . SIGDN_DESKTOPABSOLUTEPARSING , ( PWSTR * ) pszParseablePath . GetAddressOf ( ) ) ;
361404 if ( FAILED ( hr ) ) return hr ;
362405
363- hr = psl . Get ( ) ->SetArguments ( new ( pszParseablePath . Get ( ) ) ) ;
406+ // Set it as the argument of the link
407+ hr = psl . Get ( ) ->SetArguments ( pszParseablePath . Get ( ) ) ;
364408 if ( FAILED ( hr ) ) return hr ;
365409
410+ // Get the icon location of the folder
366411 using ComHeapPtr < char > pszIconLocation = default ;
367- pszIconLocation . Allocate ( PInvoke . MAX_PATH ) ;
368- int index = 0 ;
412+ pszIconLocation . Allocate ( PInvoke . MAX_PATH ) ; int index = 0 ;
369413 hr = GetFolderIconLocation ( psi , ( PWSTR * ) pszIconLocation . GetAddressOf ( ) , PInvoke . MAX_PATH , & index ) ;
370414 if ( FAILED ( hr ) ) return hr ;
371415
416+ // Set it as the icon location of the link
372417 hr = psl . Get ( ) ->SetIconLocation ( pszIconLocation . Get ( ) , index ) ;
373418 if ( FAILED ( hr ) ) return hr ;
374419
420+ // Get the display name of the folder
375421 using ComHeapPtr < char > pszDisplayName = default ;
376422 hr = psi ->GetDisplayName ( SIGDN . SIGDN_PARENTRELATIVEFORUI , ( PWSTR * ) pszDisplayName . GetAddressOf ( ) ) ;
377423 if ( FAILED ( hr ) ) return hr ;
378424
425+ // Set it as the tooltip of the link
379426 fixed ( char * pszTooltip = $ "{ new ( pszDisplayName . Get ( ) ) } ({ new ( pszParseablePath . Get ( ) ) } )")
380427 hr = psl . Get ( ) ->SetDescription ( pszTooltip ) ;
381428 if ( FAILED ( hr ) ) return hr ;
382429
430+ // Query an instance of IPropertyStore
383431 using ComPtr < IPropertyStore > pps = default ;
384432 hr = psl . Get ( ) ->QueryInterface ( IID . IID_IPropertyStore , ( void * * ) pps . GetAddressOf ( ) ) ;
385433 if ( FAILED ( hr ) ) return hr ;
@@ -399,8 +447,8 @@ private HRESULT CreateLinkFromItem(IShellItem* psi, IShellLinkW** ppsl)
399447 hr = PInvoke . PropVariantClear ( & PVAR_Title ) ;
400448 if ( FAILED ( hr ) ) return hr ;
401449
402- hr = psl . Get ( ) ->QueryInterface ( IID . IID_IShellLinkW , ( void * * ) ppsl ) ;
403- if ( FAILED ( hr ) ) return hr ;
450+ psl . Get ( ) ->AddRef ( ) ;
451+ * ppsl = psl . Get ( ) ;
404452
405453 return hr ;
406454 }
@@ -427,7 +475,7 @@ private void ExplorerJumpListWatcher_Changed(object sender, FileSystemEventArgs
427475
428476 private void FilesJumpListWatcher_Changed ( object sender , FileSystemEventArgs e )
429477 {
430- // PushJumpListToExplorer();
478+ PushJumpListToExplorer ( ) ;
431479 }
432480
433481 public void Dispose ( )
0 commit comments