Skip to content

Commit

Permalink
FIle Explorer: Fix Pin to Start/Unpin from Start from Explorer and fi…
Browse files Browse the repository at this point in the history
…x command bar option not being applied to non-primary Explorer instances
  • Loading branch information
Amrsatrio committed Oct 5, 2023
1 parent fbaad56 commit 001e8d8
Show file tree
Hide file tree
Showing 4 changed files with 374 additions and 40 deletions.
16 changes: 12 additions & 4 deletions ExplorerPatcher/ExplorerPatcher.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,26 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
Expand Down Expand Up @@ -343,10 +343,18 @@
<ResourceCompile Include="ExplorerPatcher.rc" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="settings.reg" />
<None Include="settings10.reg" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\Microsoft.Windows.ImplementationLibrary.1.0.230824.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\packages\Microsoft.Windows.ImplementationLibrary.1.0.230824.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Microsoft.Windows.ImplementationLibrary.1.0.230824.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.ImplementationLibrary.1.0.230824.2\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
</Target>
</Project>
3 changes: 2 additions & 1 deletion ExplorerPatcher/ExplorerPatcher.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -225,5 +225,6 @@
<None Include="settings10.reg">
<Filter>Settings</Filter>
</None>
<None Include="packages.config" />
</ItemGroup>
</Project>
</Project>
220 changes: 219 additions & 1 deletion ExplorerPatcher/StartMenuSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,24 @@
#include <windows.system.h>
#include <winrt/windows.foundation.collections.h>
#include <winrt/windows.system.h>
#include <roapi.h>
#include <wil/winrt.h>

extern "C" extern DWORD dwStartShowClassicMode;

static void EPWilLogCallback(wil::FailureInfo const &failure) noexcept
{
wchar_t message[2048];
HRESULT hr = GetFailureLogString(message, ARRAYSIZE(message), failure);
if (SUCCEEDED(hr))
{
wprintf(L"%s", message); // message includes newline
}
}

extern "C" void InitializeWilLogCallback()
{
SetResultLoggingCallback(EPWilLogCallback);
}

static std::vector<winrt::guid> GlobalStartData_GetPlacesFromRegistry()
{
Expand Down Expand Up @@ -137,3 +154,204 @@ extern "C" BOOL NeedsRo_SyncSettingsFromRegToCDS()

return TRUE;
}

namespace ABI::WindowsInternal::Shell::UnifiedTile
{
MIDL_INTERFACE("d3653510-4fff-4bfa-905b-ea038b142fa5")
IUnifiedTileIdentifier : public IInspectable
{
};

MIDL_INTERFACE("0e7735be-a965-44a6-a75f-54b8bcd67bec")
IWin32UnifiedTileIdentifierFactory : public IInspectable
{
virtual HRESULT STDMETHODCALLTYPE Create(HSTRING, IUnifiedTileIdentifier**) = 0;
};
}

namespace ABI::WindowsInternal::Shell::UnifiedTile::Private
{
MIDL_INTERFACE("0083831c-82d6-4e8f-bcc2-a8ac2691be49")
IUnifiedTileUserPinHelperStatics : public IInspectable
{
virtual HRESULT STDMETHODCALLTYPE CreateUserPinnedShortcutTile(IUnifiedTileIdentifier*) = 0;
};
}

namespace ABI::WindowsInternal::Shell::UnifiedTile::CuratedTileCollections
{
enum class CollectionAttributes {};
enum class PackageStatusChangeType {};
enum class StartCollectionCustomizationRestrictionType {};
enum class TilePinSize {};

namespace DataStoreCache::CuratedTileCollectionTransformer
{
class CuratedTile;
}

MIDL_INTERFACE("ffffffff-ffff-ffff-ffff-ffffffffffff")
ICuratedTileGroup : public IInspectable
{
};

MIDL_INTERFACE("ffffffff-ffff-ffff-ffff-ffffffffffff")
ICuratedTile : public IInspectable
{
};

MIDL_INTERFACE("51a07090-3a1f-49ef-9932-a971b8154790")
ICuratedTileCollection : public IInspectable
{
virtual HRESULT STDMETHODCALLTYPE get_CollectionName(HSTRING*) = 0;
virtual HRESULT STDMETHODCALLTYPE get_Attributes(CollectionAttributes*) = 0;
virtual HRESULT STDMETHODCALLTYPE put_Attributes(CollectionAttributes) = 0;
virtual HRESULT STDMETHODCALLTYPE get_Version(unsigned int*) = 0;
virtual HRESULT STDMETHODCALLTYPE put_Version(unsigned int) = 0;
virtual HRESULT STDMETHODCALLTYPE GetGroups(Windows::Foundation::Collections::IMapView<GUID, ICuratedTileGroup*>**) = 0;
virtual HRESULT STDMETHODCALLTYPE GetTiles(Windows::Foundation::Collections::IMapView<GUID, ICuratedTile*>**) = 0;
virtual HRESULT STDMETHODCALLTYPE GetAllTilesInCollection(Windows::Foundation::Collections::IMapView<GUID, ICuratedTile*>**) = 0;
virtual HRESULT STDMETHODCALLTYPE DoesCollectionContainTile(IUnifiedTileIdentifier*, ICuratedTile**, unsigned char*) = 0;
virtual HRESULT STDMETHODCALLTYPE FindTileAndParentGroup(IUnifiedTileIdentifier*, ICuratedTile**, ICuratedTileGroup**, unsigned char*) = 0;
virtual HRESULT STDMETHODCALLTYPE MoveExistingGroupToNewParent(ICuratedTileGroup*, ICuratedTileGroup*) = 0;
virtual HRESULT STDMETHODCALLTYPE CreateNewGroup(ICuratedTileGroup**) = 0;
virtual HRESULT STDMETHODCALLTYPE GetGroup(GUID, ICuratedTileGroup**) = 0;
virtual HRESULT STDMETHODCALLTYPE DeleteGroup(GUID) = 0;
virtual HRESULT STDMETHODCALLTYPE RemoveGroup(GUID) = 0;
virtual HRESULT STDMETHODCALLTYPE MoveExistingTileToNewParent(ICuratedTile*, ICuratedTileGroup*) = 0;
virtual HRESULT STDMETHODCALLTYPE AddTile(IUnifiedTileIdentifier*, ICuratedTile**) = 0;
virtual HRESULT STDMETHODCALLTYPE AddTileWithId(IUnifiedTileIdentifier*, GUID, ICuratedTile**) = 0;
virtual HRESULT STDMETHODCALLTYPE GetTile(GUID, ICuratedTile**) = 0;
virtual HRESULT STDMETHODCALLTYPE DeleteTile(GUID) = 0;
virtual HRESULT STDMETHODCALLTYPE RemoveTile(GUID) = 0;
virtual HRESULT STDMETHODCALLTYPE Commit() = 0;
virtual HRESULT STDMETHODCALLTYPE CommitAsync(Windows::Foundation::IAsyncAction**) = 0;
virtual HRESULT STDMETHODCALLTYPE CommitAsyncWithTimerBypass(Windows::Foundation::IAsyncAction**) = 0;
virtual HRESULT STDMETHODCALLTYPE ResetToDefault() = 0;
virtual HRESULT STDMETHODCALLTYPE ResetToDefaultAsync(Windows::Foundation::IAsyncAction**) = 0;
virtual HRESULT STDMETHODCALLTYPE CheckForUpdate() = 0;
virtual HRESULT STDMETHODCALLTYPE GetCustomProperty(const HSTRING, HSTRING*) = 0;
virtual HRESULT STDMETHODCALLTYPE HasCustomProperty(const HSTRING, unsigned char*) = 0;
virtual HRESULT STDMETHODCALLTYPE RemoveCustomProperty(const HSTRING) = 0;
virtual HRESULT STDMETHODCALLTYPE SetCustomProperty(const HSTRING, HSTRING) = 0;
virtual HRESULT STDMETHODCALLTYPE EnsureTileRegistration() = 0;
virtual HRESULT STDMETHODCALLTYPE ResurrectTile(std::shared_ptr<DataStoreCache::CuratedTileCollectionTransformer::CuratedTile>, const GUID&) = 0;
virtual HRESULT STDMETHODCALLTYPE OnTileAddedWithinCollection(IUnifiedTileIdentifier*) = 0;
virtual HRESULT STDMETHODCALLTYPE OnTileRemovedWithinCollection(IUnifiedTileIdentifier*) = 0;
};

MIDL_INTERFACE("adbf8965-6056-4126-ab26-6660af4661ce")
IStartTileCollection : public IInspectable
{
virtual HRESULT STDMETHODCALLTYPE PinToStart(IUnifiedTileIdentifier*, TilePinSize);
virtual HRESULT STDMETHODCALLTYPE PinToStartAtLocation(IUnifiedTileIdentifier*, ICuratedTileGroup*, Windows::Foundation::Point, Windows::Foundation::Size);
virtual HRESULT STDMETHODCALLTYPE UnpinFromStart(IUnifiedTileIdentifier*);
virtual HRESULT STDMETHODCALLTYPE ReplaceTinyOrMediumTile(IUnifiedTileIdentifier*, IUnifiedTileIdentifier*);
virtual HRESULT STDMETHODCALLTYPE get_LastGroupId(GUID*);
virtual HRESULT STDMETHODCALLTYPE put_LastGroupId(GUID);
virtual HRESULT STDMETHODCALLTYPE get_CustomizationRestriction(StartCollectionCustomizationRestrictionType*);
virtual HRESULT STDMETHODCALLTYPE put_CustomizationRestriction(StartCollectionCustomizationRestrictionType);
virtual HRESULT STDMETHODCALLTYPE get_GroupCellWidth(unsigned int*);
virtual HRESULT STDMETHODCALLTYPE put_GroupCellWidth(unsigned int);
virtual HRESULT STDMETHODCALLTYPE get_PreferredColumnCount(unsigned int*);
virtual HRESULT STDMETHODCALLTYPE put_PreferredColumnCount(unsigned int);
virtual HRESULT STDMETHODCALLTYPE get_CurrentColumnCount(unsigned int*);
virtual HRESULT STDMETHODCALLTYPE put_CurrentColumnCount(unsigned int);
};

MIDL_INTERFACE("ffffffff-ffff-ffff-ffff-ffffffffffff")
ICuratedTileCollectionOptions : public IInspectable
{
};

MIDL_INTERFACE("ffffffff-ffff-ffff-ffff-ffffffffffff")
ICuratedTileCollectionManager : public IInspectable
{
virtual HRESULT STDMETHODCALLTYPE NotifyPackageStatusChanged(HSTRING, PackageStatusChangeType) = 0;
virtual HRESULT STDMETHODCALLTYPE GetCollection(HSTRING, ICuratedTileCollection**) = 0;
virtual HRESULT STDMETHODCALLTYPE GetCollectionWithOptions(HSTRING, ICuratedTileCollectionOptions*, ICuratedTileCollection**) = 0;
virtual HRESULT STDMETHODCALLTYPE DeleteCollection(HSTRING) = 0;
virtual HRESULT STDMETHODCALLTYPE CollectionExists(HSTRING, unsigned char*) = 0;
virtual HRESULT STDMETHODCALLTYPE InitializeCollection(HSTRING) = 0;
};

MIDL_INTERFACE("15f254ac-49b3-4e6e-9c62-806ffaf554f9")
ICuratedTileCollectionManagerStatics : public IInspectable
{
virtual HRESULT STDMETHODCALLTYPE CreateWithUser(Windows::System::IUser*, ICuratedTileCollectionManager**) = 0;
};
}

struct CCacheShortcut
{
public:
const wchar_t* GetAppID(const void* a2) const
{
DWORD dwOffset = *((DWORD*)this + 11); // Same offset in Windows 10 and 11
return dwOffset != -1 ? (wchar_t*)((char*)a2 + dwOffset) : nullptr;
}
};

extern "C"
{
HRESULT(*AppResolver_CAppResolverCacheBuilder__AddUserPinnedShortcutToStartFunc)(const CCacheShortcut* a2, const void* a3);
HRESULT AppResolver_CAppResolverCacheBuilder__AddUserPinnedShortcutToStart(const CCacheShortcut* a2, const void* a3)
{
using namespace ABI::WindowsInternal::Shell::UnifiedTile;
using namespace ABI::WindowsInternal::Shell::UnifiedTile::Private;
using namespace ABI::WindowsInternal::Shell::UnifiedTile::CuratedTileCollections;

if (dwStartShowClassicMode)
{
return AppResolver_CAppResolverCacheBuilder__AddUserPinnedShortcutToStartFunc(a2, a3);
}

Microsoft::WRL::ComPtr<IWin32UnifiedTileIdentifierFactory> pTileIdentifierFactory;
RETURN_IF_FAILED(Windows::Foundation::GetActivationFactory(
Microsoft::WRL::Wrappers::HStringReference(L"WindowsInternal.Shell.UnifiedTile.UnifiedTileIdentifier").Get(),
pTileIdentifierFactory.GetAddressOf()
));

Microsoft::WRL::ComPtr<IUnifiedTileIdentifier> pTileIdentifier;
const wchar_t* pwszAppId = a2->GetAppID(a3);
RETURN_IF_FAILED(pTileIdentifierFactory->Create(
Microsoft::WRL::Wrappers::HStringReference(pwszAppId).Get(),
pTileIdentifier.GetAddressOf()
));

Microsoft::WRL::ComPtr<IUnifiedTileUserPinHelperStatics> pTileUserPinHelper;
RETURN_IF_FAILED(Windows::Foundation::GetActivationFactory(
Microsoft::WRL::Wrappers::HStringReference(L"WindowsInternal.Shell.UnifiedTile.Private.UnifiedTileUserPinHelper").Get(),
pTileUserPinHelper.GetAddressOf()
));

RETURN_IF_FAILED(pTileUserPinHelper->CreateUserPinnedShortcutTile(
pTileIdentifier.Get()
));

// At this point, on Windows 11 the Windows 10 code doesn't exist anymore, so we'll add them here
Microsoft::WRL::ComPtr<ICuratedTileCollectionManager> pTileCollectionManager;
RETURN_IF_FAILED(RoActivateInstance(
Microsoft::WRL::Wrappers::HStringReference(L"WindowsInternal.Shell.UnifiedTile.CuratedTileCollections.CuratedTileCollectionManager").Get(),
(IInspectable**)pTileCollectionManager.GetAddressOf()
));

Microsoft::WRL::ComPtr<ICuratedTileCollection> pTileCollection;
RETURN_IF_FAILED(pTileCollectionManager->GetCollection(
Microsoft::WRL::Wrappers::HStringReference(L"Start.TileGrid").Get(),
pTileCollection.GetAddressOf()
));

Microsoft::WRL::ComPtr<IStartTileCollection> pStartTileCollection;
RETURN_IF_FAILED(pTileCollection.As(&pStartTileCollection));

RETURN_IF_FAILED(pStartTileCollection->PinToStart(
pTileIdentifier.Get(),
static_cast<TilePinSize>(0)
));

RETURN_IF_FAILED(pTileCollection->Commit());

return S_OK;
}
}
Loading

0 comments on commit 001e8d8

Please sign in to comment.