[PowerRename][ImageResizer] Tier1 Win11 Context menu (#19000)

* Test win11 tier1 context menu

* Try to test signing

* Cleanup

* Cleanup project file

* Sign dll
Add PowerToys preffix
Add assets to installer

* expect.txt

* Switch to named pipes
Unregister package on uninstall
Remove unneeded files
Cleanup

* Bring back check if package registered but use per-user method

* Fix win11 check

* expect.txt

* Check if package already registered

* Revert "Check if package already registered"

FindPackages() method needs admin privileges.

This reverts commit 5af584fed4.

* Fix PowerRename args checking

* Cleanup assets

* Tier1 context menu ImageResizer
Minor cleanups
Move logic to package.h

* [WIP] Signing and installer
Expect.txt

* Localized context menu title

* Retarget everything 10.0.18362.0 -> 10.0.19041.0

* Address PR comments
 - check if selection renamable
 - minor cleanup
 - struct initialization

* Fix ImageResizerLib project configuration

* More Windows version updates

* Remove unneeded file & try fix resource build error

* Add Microsoft.PowerToys prefix to packages

* Test

* Fix convert-resx-to-rc.ps1 script issue causing resource files compile error

Don't generate empty STRINGTABLE for resx files without data

* Avoid duplicate context menu items

* [BugReportTool] Report installed context menu packages
This commit is contained in:
Stefan Markovic
2022-06-30 22:10:14 +02:00
committed by GitHub
parent a0eacca17f
commit e637902892
148 changed files with 3163 additions and 384 deletions

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap2="http://schemas.microsoft.com/appx/manifest/uap/windows10/2"
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5"
xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10"
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
IgnorableNamespaces="uap uap2 uap3 rescap desktop desktop4 desktop5 uap10 com">
<Identity Name="PowerRenameContextMenu" ProcessorArchitecture="neutral" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" Version="1.0.0.0" />
<Properties>
<DisplayName>PowerRenameContextMenu</DisplayName>
<PublisherDisplayName>Microsoft</PublisherDisplayName>
<Logo>Assets\storelogo.png</Logo>
<uap10:AllowExternalContent>true</uap10:AllowExternalContent>
</Properties>
<Resources>
<Resource Language="en-us" />
</Resources>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18950.0" MaxVersionTested="10.0.19000.0" />
</Dependencies>
<Capabilities>
<rescap:Capability Name="runFullTrust" />
<rescap:Capability Name="unvirtualizedResources"/>
</Capabilities>
<Applications>
<Application Id="Microsoft.PowerToys.PowerRenameContextMenu" Executable="PowerRename.exe" uap10:TrustLevel="mediumIL" uap10:RuntimeBehavior="win32App">
<uap:VisualElements AppListEntry="none" DisplayName="Microsoft.PowerToys.PowerRenameContextMenu" Description="PowerRenameContextMenu" BackgroundColor="transparent" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" Square310x310Logo="Assets\LargeTile.png" Square71x71Logo="Assets\SmallTile.png"></uap:DefaultTile>
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
<Extensions>
<desktop4:Extension Category="windows.fileExplorerContextMenus">
<desktop4:FileExplorerContextMenus>
<desktop5:ItemType Type="Directory">
<desktop5:Verb Id="PowerRenameCommand" Clsid="1861E28B-A1F0-4EF4-A1FE-4C8CA88E2174" />
</desktop5:ItemType>
<desktop5:ItemType Type="Directory\Background">
<desktop5:Verb Id="PowerRenameCommand" Clsid="1861E28B-A1F0-4EF4-A1FE-4C8CA88E2174" />
</desktop5:ItemType>
<desktop5:ItemType Type="*">
<desktop5:Verb Id="PowerRenameCommand" Clsid="1861E28B-A1F0-4EF4-A1FE-4C8CA88E2174" />
</desktop5:ItemType>
</desktop4:FileExplorerContextMenus>
</desktop4:Extension>
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:SurrogateServer DisplayName="Context menu verb handler">
<com:Class Id="1861E28B-A1F0-4EF4-A1FE-4C8CA88E2174" Path="PowerToys.PowerRenameContextMenu.dll" ThreadingModel="STA"/>
</com:SurrogateServer>
</com:ComServer>
</com:Extension>
</Extensions>
</Application>
</Applications>
</Package>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

View File

@@ -0,0 +1,60 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE 9, 1
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props')" />
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{1dbbb112-4bb1-444b-8ebb-e66555c76ba6}</ProjectGuid>
<RootNamespace>PowerRenameContextMenu</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<TargetName>PowerToys.PowerRenameContextMenu</TargetName>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\PowerRename\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;POWERRENAMECONTEXTMENU_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<AdditionalIncludeDirectories>..\..\..\;..\lib\;..\..\;..\..\..\common\telemetry;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>runtimeobject.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>Source.def</ModuleDefinitionFile>
</Link>
<PreBuildEvent>
<Command>del $(OutDir)*.msix /q
MakeAppx.exe pack /d . /p $(OutDir)PowerRenameContextMenuPackage.msix /nv</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;POWERRENAMECONTEXTMENU_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<AdditionalIncludeDirectories>..\..\..\;..\lib\;..\..\;..\..\..\common\telemetry;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>runtimeobject.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>Source.def</ModuleDefinitionFile>
</Link>
<PreBuildEvent>
<Command>del $(OutDir)*.msix /q
MakeAppx.exe pack /d . /p $(OutDir)PowerRenameContextMenuPackage.msix /nv</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="framework.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="PowerRenameContextMenu.rc" />
</ItemGroup>
<ItemGroup>
<None Include="Assets\**" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>
<None Include="PowerRenameUI.ico" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
</ProjectReference>
<ProjectReference Include="..\lib\PowerRenameLib.vcxproj">
<Project>{51920f1f-c28c-4adf-8660-4238766796c2}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="..\..\..\..\deps\spdlog.props" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.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.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets'))" />
</Target>
</Project>

View File

@@ -0,0 +1,742 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="PowerRenameUI.ico">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
<None Include="Assets\**">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="PowerRenameContextMenu.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="Assets\SmallTile.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\SplashScreen.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square150x150Logo.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\storelogo.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Wide310x150Logo.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\*.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\BadgeLogo.scale-125.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\BadgeLogo.scale-150.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\BadgeLogo.scale-200.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\BadgeLogo.scale-400.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\LargeTile.scale-100.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\LargeTile.scale-125.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\LargeTile.scale-150.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\LargeTile.scale-200.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\LargeTile.scale-400.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\SmallTile.scale-100.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\SmallTile.scale-125.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\SmallTile.scale-150.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\SmallTile.scale-200.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\SmallTile.scale-400.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\SplashScreen.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\SplashScreen.scale-100.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\SplashScreen.scale-125.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\SplashScreen.scale-150.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\SplashScreen.scale-200.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\SplashScreen.scale-400.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.altform-lightunplated_targetsize-16.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.altform-lightunplated_targetsize-24.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.altform-lightunplated_targetsize-32.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.altform-lightunplated_targetsize-48.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.altform-lightunplated_targetsize-256.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.altform-unplated_targetsize-16.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.altform-unplated_targetsize-24.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.altform-unplated_targetsize-32.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.altform-unplated_targetsize-48.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.altform-unplated_targetsize-256.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.scale-100.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.scale-125.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.scale-150.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.scale-200.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.scale-400.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.targetsize-16.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.targetsize-24.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.targetsize-32.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.targetsize-48.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.targetsize-256.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square150x150Logo.scale-100.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square150x150Logo.scale-125.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square150x150Logo.scale-150.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square150x150Logo.scale-200.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Square150x150Logo.scale-400.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\storelogo.scale-100.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\storelogo.scale-125.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\storelogo.scale-150.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\storelogo.scale-200.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\storelogo.scale-400.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Wide310x150Logo.scale-100.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Wide310x150Logo.scale-125.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Wide310x150Logo.scale-150.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Wide310x150Logo.scale-200.png">
<Filter>Resource Files</Filter>
</Image>
<Image Include="Assets\Wide310x150Logo.scale-400.png">
<Filter>Resource Files</Filter>
</Image>
</ItemGroup>
</Project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

View File

@@ -0,0 +1,5 @@
LIBRARY
EXPORTS
DllCanUnloadNow PRIVATE
DllGetClassObject PRIVATE
DllGetActivationFactory PRIVATE

View File

@@ -0,0 +1,277 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <atlfile.h>
#include <atlstr.h>
#include <shobjidl_core.h>
#include <string>
#include <filesystem>
#include <sstream>
#include <Shlwapi.h>
#include <vector>
#include <wil\resource.h>
#include <wil\win32_helpers.h>
#include <wil\stl.h>
#include <wrl/module.h>
#include <wrl/implements.h>
#include <wrl/client.h>
#include <common/utils/elevation.h>
#include <common/utils/process_path.h>
#include <Helpers.h>
#include <Settings.h>
#include <trace.h>
#include <mutex>
#include <thread>
#include <shellapi.h>
using namespace Microsoft::WRL;
HINSTANCE g_hInst = 0;
#define BUFSIZE 4096 * 4
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_hInst = hModule;
Trace::RegisterProvider();
break;
case DLL_PROCESS_DETACH:
Trace::UnregisterProvider();
break;
}
return TRUE;
}
class __declspec(uuid("1861E28B-A1F0-4EF4-A1FE-4C8CA88E2174")) PowerRenameContextMenuCommand final : public RuntimeClass<RuntimeClassFlags<ClassicCom>, IExplorerCommand, IObjectWithSite>
{
public:
virtual const wchar_t* Title() { return L"PowerRename"; }
virtual const EXPCMDFLAGS Flags() { return ECF_DEFAULT; }
virtual const EXPCMDSTATE State(_In_opt_ IShellItemArray* selection) { return ECS_ENABLED; }
// IExplorerCommand
IFACEMETHODIMP GetTitle(_In_opt_ IShellItemArray* items, _Outptr_result_nullonfailure_ PWSTR* name)
{
return SHStrDup(app_name.c_str(), name);
}
IFACEMETHODIMP GetIcon(_In_opt_ IShellItemArray*, _Outptr_result_nullonfailure_ PWSTR* icon)
{
if (!CSettingsInstance().GetShowIconOnMenu())
{
*icon = nullptr;
return E_NOTIMPL;
}
std::wstring iconResourcePath = get_module_folderpath(g_hInst);
iconResourcePath += L"\\";
iconResourcePath += L"PowerRenameUI.ico";
return SHStrDup(iconResourcePath.c_str(), icon);
}
IFACEMETHODIMP GetToolTip(_In_opt_ IShellItemArray*, _Outptr_result_nullonfailure_ PWSTR* infoTip)
{
*infoTip = nullptr;
return E_NOTIMPL;
}
IFACEMETHODIMP GetCanonicalName(_Out_ GUID* guidCommandName)
{
*guidCommandName = __uuidof(this);
return S_OK;
}
IFACEMETHODIMP GetState(_In_opt_ IShellItemArray* selection, _In_ BOOL okToBeSlow, _Out_ EXPCMDSTATE* cmdState)
{
*cmdState = ECS_ENABLED;
if (!CSettingsInstance().GetEnabled())
{
*cmdState = ECS_HIDDEN;
return S_OK;
}
// Check if we should only be on the extended context menu
if (CSettingsInstance().GetExtendedContextMenuOnly())
{
*cmdState = ECS_HIDDEN;
return S_OK;
}
// Check if at least one of the selected items is actually renamable.
if (!ShellItemArrayContainsRenamableItem(selection))
{
*cmdState = ECS_HIDDEN;
return S_OK;
}
return S_OK;
}
IFACEMETHODIMP Invoke(_In_opt_ IShellItemArray* selection, _In_opt_ IBindCtx*) noexcept
try
{
if (selection)
{
RunPowerRename(selection);
}
return S_OK;
}
CATCH_RETURN();
IFACEMETHODIMP GetFlags(_Out_ EXPCMDFLAGS* flags)
{
*flags = Flags();
return S_OK;
}
IFACEMETHODIMP EnumSubCommands(_COM_Outptr_ IEnumExplorerCommand** enumCommands)
{
*enumCommands = nullptr;
return E_NOTIMPL;
}
// IObjectWithSite
IFACEMETHODIMP SetSite(_In_ IUnknown* site) noexcept
{
m_site = site;
return S_OK;
}
IFACEMETHODIMP GetSite(_In_ REFIID riid, _COM_Outptr_ void** site) noexcept { return m_site.CopyTo(riid, site); }
protected:
ComPtr<IUnknown> m_site;
private:
HRESULT StartNamedPipeServerAndSendData(std::wstring pipe_name)
{
hPipe = CreateNamedPipe(
pipe_name.c_str(),
PIPE_ACCESS_DUPLEX |
WRITE_DAC,
PIPE_TYPE_MESSAGE |
PIPE_READMODE_MESSAGE |
PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
BUFSIZE,
BUFSIZE,
0,
NULL);
if (hPipe == NULL || hPipe == INVALID_HANDLE_VALUE)
{
return E_FAIL;
}
// This call blocks until a client process connects to the pipe
BOOL connected = ConnectNamedPipe(hPipe, NULL);
if (!connected)
{
if (GetLastError() == ERROR_PIPE_CONNECTED)
{
return S_OK;
}
else
{
CloseHandle(hPipe);
}
return E_FAIL;
}
return S_OK;
}
HRESULT RunPowerRename(IShellItemArray* psiItemArray)
{
if (CSettingsInstance().GetEnabled())
{
Trace::Invoked();
// Set the application path based on the location of the dll
std::wstring path = get_module_folderpath(g_hInst);
path = path + L"\\PowerToys.PowerRename.exe";
std::wstring pipe_name(L"\\\\.\\pipe\\powertoys_powerrenameinput_");
UUID temp_uuid;
wchar_t* uuid_chars = nullptr;
if (UuidCreate(&temp_uuid) == RPC_S_UUID_NO_ADDRESS)
{
auto val = get_last_error_message(GetLastError());
Logger::warn(L"UuidCreate can not create guid. {}", val.has_value() ? val.value() : L"");
}
else if (UuidToString(&temp_uuid, (RPC_WSTR*)&uuid_chars) != RPC_S_OK)
{
auto val = get_last_error_message(GetLastError());
Logger::warn(L"UuidToString can not convert to string. {}", val.has_value() ? val.value() : L"");
}
if (uuid_chars != nullptr)
{
pipe_name += std::wstring(uuid_chars);
RpcStringFree((RPC_WSTR*)&uuid_chars);
uuid_chars = nullptr;
}
create_pipe_thread = std::thread(&PowerRenameContextMenuCommand::StartNamedPipeServerAndSendData, this, pipe_name);
RunNonElevatedEx(path.c_str(), pipe_name, get_module_folderpath(g_hInst));
create_pipe_thread.join();
if (hPipe != INVALID_HANDLE_VALUE)
{
CAtlFile writePipe(hPipe);
DWORD fileCount = 0;
// Gets the list of files currently selected using the IShellItemArray
psiItemArray->GetCount(&fileCount);
// Iterate over the list of files
for (DWORD i = 0; i < fileCount; i++)
{
IShellItem* shellItem;
psiItemArray->GetItemAt(i, &shellItem);
LPWSTR itemName;
// Retrieves the entire file system path of the file from its shell item
shellItem->GetDisplayName(SIGDN_FILESYSPATH, &itemName);
CString fileName(itemName);
// File name can't contain '?'
fileName.Append(_T("?"));
// Write the file path into the input stream for image resizer
writePipe.Write(fileName, fileName.GetLength() * sizeof(TCHAR));
}
writePipe.Close();
}
}
Trace::InvokedRet(S_OK);
return S_OK;
}
std::thread create_pipe_thread;
HANDLE hPipe = INVALID_HANDLE_VALUE;
std::wstring app_name = L"PowerRename";
};
CoCreatableClass(PowerRenameContextMenuCommand)
CoCreatableClassWrlCreatorMapInclude(PowerRenameContextMenuCommand)
STDAPI DllGetActivationFactory(_In_ HSTRING activatableClassId, _COM_Outptr_ IActivationFactory** factory)
{
return Module<ModuleType::InProc>::GetModule().GetActivationFactory(activatableClassId, factory);
}
STDAPI DllCanUnloadNow()
{
return Module<InProc>::GetModule().GetObjectCount() == 0 ? S_OK : S_FALSE;
}
STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _COM_Outptr_ void** instance)
{
return Module<InProc>::GetModule().GetClassObject(rclsid, riid, instance);
}

View File

@@ -0,0 +1,5 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <windows.h>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.220418.1" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.220201.1" targetFramework="native" />
</packages>

View File

@@ -0,0 +1,5 @@
// pch.cpp: source file corresponding to the pre-compiled header
#include "pch.h"
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.

View File

@@ -0,0 +1,13 @@
// pch.h: This is a precompiled header file.
// Files listed below are compiled only once, improving build performance for future builds.
// This also affects IntelliSense performance, including code completion and many code browsing features.
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
// Do not add files here that you will be updating frequently as this negates the performance advantage.
#ifndef PCH_H
#define PCH_H
// add headers that you want to pre-compile here
#include "framework.h"
#endif //PCH_H

View File

@@ -0,0 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by PowerRenameContextMenu.rc
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -53,15 +53,60 @@ void App::OnLaunched(LaunchActivatedEventArgs const&)
{
LoggerHelpers::init_logger(moduleName, L"", LogSettings::powerRenameLoggerName);
#define BUFSIZE 4096 * 4
auto args = std::wstring{ GetCommandLine() };
size_t pos{ args.rfind(L"\\\\.\\pipe\\") };
std::wstring pipe_name;
if (pos != std::wstring::npos)
{
pipe_name = args.substr(pos);
}
HANDLE hStdin;
if (pipe_name.size() > 0)
{
while (1)
{
hStdin = CreateFile(
pipe_name.c_str(), // pipe name
GENERIC_READ | GENERIC_WRITE, // read and write
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
0, // default attributes
NULL); // no template file
// Break if the pipe handle is valid.
if (hStdin != INVALID_HANDLE_VALUE)
break;
// Exit if an error other than ERROR_PIPE_BUSY occurs.
auto error = GetLastError();
if (error != ERROR_PIPE_BUSY)
{
break;
}
if (!WaitNamedPipe(pipe_name.c_str(), 3))
{
printf("Could not open pipe: 20 second wait timed out.");
}
}
}
else
{
hStdin = GetStdHandle(STD_INPUT_HANDLE);
}
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
if (hStdin == INVALID_HANDLE_VALUE)
{
Logger::error(L"Invalid input handle.");
ExitProcess(1);
}
#define BUFSIZE 4096 * 4
BOOL bSuccess;
WCHAR chBuf[BUFSIZE];
DWORD dwRead;
@@ -86,6 +131,7 @@ void App::OnLaunched(LaunchActivatedEventArgs const&)
if (!bSuccess)
break;
}
CloseHandle(hStdin);
Logger::debug(L"Starting PowerRename with {} files selected", g_files.size());

View File

@@ -22,7 +22,7 @@
<WindowsPackageType>None</WindowsPackageType>
<ApplicationType>Windows Store</ApplicationType>
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.17763.0</WindowsTargetPlatformMinVersion>
<UseWinUI>true</UseWinUI>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>

View File

@@ -6,9 +6,10 @@
#include <Settings.h>
#include "Generated Files/resource.h"
#include <common/utils/resources.h>
#include <common/utils/process_path.h>
#include <common/utils/HDropIterator.h>
#include <common/utils/resources.h>
#include <common/utils/package.h>
#include <common/utils/process_path.h>
extern HINSTANCE g_hInst;
@@ -63,9 +64,24 @@ HRESULT CPowerRenameMenu::QueryContextMenu(HMENU hMenu, UINT index, UINT uIDFirs
if (!CSettingsInstance().GetEnabled())
return E_FAIL;
// Check if we should only be on the extended context menu
if (CSettingsInstance().GetExtendedContextMenuOnly() && (!(uFlags & CMF_EXTENDEDVERBS)))
return E_FAIL;
// Win11 context menu can't distinguish between extended and default menu, so use this one
if (package::IsWin11OrGreater())
{
if (CSettingsInstance().GetExtendedContextMenuOnly() && (uFlags & CMF_EXTENDEDVERBS))
{
// continue
}
else
{
return E_FAIL;
}
}
else
{
// Check if we should only be on the extended context menu
if (CSettingsInstance().GetExtendedContextMenuOnly() && (!(uFlags & CMF_EXTENDEDVERBS)))
return E_FAIL;
}
// Check if at least one of the selected items is actually renamable.
if (!DataObjectContainsRenamableItem(m_spdo))

View File

@@ -8,7 +8,7 @@
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{B25AC7A5-FB9F-4789-B392-D5C85E948670}</ProjectGuid>
<RootNamespace>PowerRenameExt</RootNamespace>
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">
@@ -64,6 +64,9 @@
<ProjectReference Include="..\..\..\common\Themes\Themes.vcxproj">
<Project>{98537082-0fdb-40de-abd8-0dc5a4269bab}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\common\version\version.vcxproj">
<Project>{cc6e41ac-8174-4e8a-8d22-85dd7f4851df}</Project>
</ProjectReference>
<ProjectReference Include="..\lib\PowerRenameLib.vcxproj">
<Project>{51920f1f-c28c-4adf-8660-4238766796c2}</Project>
</ProjectReference>

View File

@@ -1,15 +1,22 @@
#include "pch.h"
#include "Generated Files/resource.h"
#include "PowerRenameConstants.h"
#include "PowerRenameExt.h"
#include <interface/powertoy_module_interface.h>
#include <settings.h>
#include <trace.h>
#include <VersionHelpers.h>
#include <common/SettingsAPI/settings_objects.h>
#include <common/logger/logger.h>
#include <common/utils/logger_helper.h>
#include <common/utils/package.h>
#include <common/utils/process_path.h>
#include <common/utils/resources.h>
#include "Generated Files/resource.h"
#include <atomic>
#include <dll/PowerRenameConstants.h>
std::atomic<DWORD> g_dwModuleRefCount = 0;
HINSTANCE g_hInst = 0;
@@ -161,6 +168,8 @@ private:
std::wstring app_key;
public:
// Return the localized display name of the powertoy
virtual PCWSTR get_name() override
{
@@ -178,6 +187,19 @@ public:
{
Logger::info(L"PowerRename enabled");
m_enabled = true;
if (package::IsWin11OrGreater())
{
std::wstring path = get_module_folderpath(g_hInst);
std::wstring packageUri = path + L"\\PowerRenameContextMenuPackage.msix";
std::wstring packageDisplayName{ L"PowerRenameContextMenu" };
if (!package::IsPackageRegistered(packageDisplayName))
{
package::RegisterSparsePackage(path, packageUri);
}
}
save_settings();
}

View File

@@ -520,6 +520,31 @@ BOOL GetEnumeratedFileName(__out_ecount(cchMax) PWSTR pszUniqueName, UINT cchMax
return fRet;
}
// Iterate through the shell items array and checks if at least 1 item has SFGAO_CANRENAME.
// We do not enumerate child items - only the items the user selected.
bool ShellItemArrayContainsRenamableItem(_In_ IShellItemArray* shellItemArray)
{
bool hasRenamable = false;
IEnumShellItems* spesi;
if (SUCCEEDED(shellItemArray->EnumItems(&spesi)))
{
ULONG celtFetched;
IShellItem* spsi;
while ((S_OK == spesi->Next(1, &spsi, &celtFetched)))
{
SFGAOF attrs;
if (SUCCEEDED(spsi->GetAttributes(SFGAO_CANRENAME, &attrs)) &&
attrs & SFGAO_CANRENAME)
{
hasRenamable = true;
break;
}
}
}
return hasRenamable;
}
// Iterate through the data source and checks if at least 1 item has SFGAO_CANRENAME.
// We do not enumerate child items - only the items the user selected.
bool DataObjectContainsRenamableItem(_In_ IUnknown* dataSource)

View File

@@ -8,6 +8,7 @@ HRESULT GetTrimmedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source);
HRESULT GetTransformedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, DWORD flags, bool isFolder);
HRESULT GetDatedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, SYSTEMTIME fileTime);
bool isFileTimeUsed(_In_ PCWSTR source);
bool ShellItemArrayContainsRenamableItem(_In_ IShellItemArray* shellItemArray);
bool DataObjectContainsRenamableItem(_In_ IUnknown* dataSource);
HRESULT GetShellItemArrayFromDataObject(_In_ IUnknown* dataSource, _COM_Outptr_ IShellItemArray** items);
BOOL GetEnumeratedFileName(