[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

@@ -2,13 +2,15 @@
#include "pch.h"
#include "ContextMenuHandler.h"
#include "Settings.h"
#include <Settings.h>
#include <trace.h>
#include <common/themes/icon_helpers.h>
#include <common/utils/process_path.h>
#include <common/utils/resources.h>
#include <common/utils/HDropIterator.h>
#include "trace.h"
#include <common/utils/package.h>
extern HINSTANCE g_hInst_imageResizer;
@@ -61,6 +63,9 @@ HRESULT CContextMenuHandler::Initialize(_In_opt_ PCIDLIST_ABSOLUTE pidlFolder, _
HRESULT CContextMenuHandler::QueryContextMenu(_In_ HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
if (package::IsWin11OrGreater())
return E_FAIL;
if (uFlags & CMF_DEFAULTONLY)
{
return S_OK;

View File

@@ -1,12 +0,0 @@
#pragma once
#include <string>
namespace ImageResizerConstants
{
// Name of the powertoy module.
inline const std::wstring ModuleKey = L"Image Resizer";
// Name of the ImageResizer save folder.
inline const std::wstring ModuleOldSaveFolderKey = L"ImageResizer";
inline const std::wstring ModuleSaveFolderKey = L"Image Resizer";
}

View File

@@ -32,7 +32,7 @@
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\..\common\inc;..\..\..\common\Telemetry;..\..\;..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\ImageResizerLib;..\..\..\common\inc;..\..\..\common\Telemetry;..\..\;..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<ModuleDefinitionFile>.\ImageResizerExt.def</ModuleDefinitionFile>
@@ -89,23 +89,18 @@
<PrecompiledHeader Condition="'$(CIBuild)'!='true'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="Settings.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(CIBuild)'!='true'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="trace.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="ContextMenuHandler.h" />
<ClInclude Include="dllmain.h" />
<None Include="resource.base.h" />
<ClInclude Include="ImageResizerConstants.h" />
<ClInclude Include="Settings.h" />
<ClInclude Include="Generated Files/resource.h" />
<ClInclude Include="ImageResizerExt_i.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="trace.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Generated Files/ImageResizerExt.rc" />
@@ -121,12 +116,18 @@
<Midl Include="ImageResizerExt.idl" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\common\SettingsAPI\SettingsAPI.vcxproj">
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\common\Themes\Themes.vcxproj">
<Project>{98537082-0fdb-40de-abd8-0dc5a4269bab}</Project>
</ProjectReference>
<ProjectReference Include="..\ImageResizerLib\ImageResizerLib.vcxproj">
<Project>{18b3db45-4ffe-4d01-97d6-5223feee1853}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Image Include="..\ui\Resources\ImageResizer.ico" />
@@ -135,6 +136,7 @@
<None Include="Resources.resx" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="..\..\..\..\deps\spdlog.props" />
<ImportGroup Label="ExtensionTargets">
<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>

View File

@@ -28,15 +28,6 @@
<ClCompile Include="ContextMenuHandler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Settings.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="trace.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClInclude Include="trace.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClCompile Include="ImageResizerExt_i.c">
<Filter>Generated Files</Filter>
</ClCompile>
@@ -54,9 +45,6 @@
<ClInclude Include="ContextMenuHandler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Settings.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ImageResizerExt_i.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -66,9 +54,6 @@
<ClInclude Include="Generated Files/resource.h">
<Filter>Generated Files</Filter>
</ClInclude>
<ClInclude Include="ImageResizerConstants.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="ImageResizerExt.rgs">

View File

@@ -1,125 +0,0 @@
#include "pch.h"
#include "Settings.h"
#include <common/utils/json.h>
#include <common/SettingsAPI/settings_helpers.h>
#include <filesystem>
#include <commctrl.h>
#include <imageresizer\dll\ImageResizerConstants.h>
namespace
{
const wchar_t c_imageResizerDataFilePath[] = L"\\image-resizer-settings.json";
const wchar_t c_rootRegPath[] = L"Software\\Microsoft\\ImageResizer";
const wchar_t c_enabled[] = L"Enabled";
unsigned int RegReadInteger(const std::wstring& valueName, unsigned int defaultValue)
{
DWORD type = REG_DWORD;
DWORD data = 0;
DWORD size = sizeof(DWORD);
if (SHGetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName.c_str(), &type, &data, &size) == ERROR_SUCCESS)
{
return data;
}
return defaultValue;
}
bool RegReadBoolean(const std::wstring& valueName, bool defaultValue)
{
DWORD value = RegReadInteger(valueName.c_str(), defaultValue ? 1 : 0);
return (value == 0) ? false : true;
}
bool LastModifiedTime(const std::wstring& filePath, FILETIME* lpFileTime)
{
WIN32_FILE_ATTRIBUTE_DATA attr{};
if (GetFileAttributesExW(filePath.c_str(), GetFileExInfoStandard, &attr))
{
*lpFileTime = attr.ftLastWriteTime;
return true;
}
return false;
}
}
CSettings::CSettings()
{
std::wstring oldSavePath = PTSettingsHelper::get_module_save_folder_location(ImageResizerConstants::ModuleOldSaveFolderKey);
std::wstring savePath = PTSettingsHelper::get_module_save_folder_location(ImageResizerConstants::ModuleSaveFolderKey);
std::error_code ec;
if (std::filesystem::exists(oldSavePath, ec))
{
std::filesystem::copy(oldSavePath, savePath, std::filesystem::copy_options::recursive, ec);
std::filesystem::remove_all(oldSavePath, ec);
}
jsonFilePath = savePath + std::wstring(c_imageResizerDataFilePath);
Load();
}
void CSettings::Save()
{
json::JsonObject jsonData;
jsonData.SetNamedValue(c_enabled, json::value(settings.enabled));
json::to_file(jsonFilePath, jsonData);
GetSystemTimeAsFileTime(&lastLoadedTime);
}
void CSettings::Load()
{
if (!std::filesystem::exists(jsonFilePath))
{
MigrateFromRegistry();
Save();
}
else
{
ParseJson();
}
}
void CSettings::Reload()
{
// Load json settings from data file if it is modified in the meantime.
FILETIME lastModifiedTime{};
if (LastModifiedTime(jsonFilePath, &lastModifiedTime) &&
CompareFileTime(&lastModifiedTime, &lastLoadedTime) == 1)
{
Load();
}
}
void CSettings::MigrateFromRegistry()
{
settings.enabled = RegReadBoolean(c_enabled, true);
}
void CSettings::ParseJson()
{
auto json = json::from_file(jsonFilePath);
if (json)
{
const json::JsonObject& jsonSettings = json.value();
try
{
if (json::has(jsonSettings, c_enabled, json::JsonValueType::Boolean))
{
settings.enabled = jsonSettings.GetNamedBoolean(c_enabled);
}
}
catch (const winrt::hresult_error&)
{
}
}
GetSystemTimeAsFileTime(&lastLoadedTime);
}
CSettings& CSettingsInstance()
{
static CSettings instance;
return instance;
}

View File

@@ -1,38 +0,0 @@
#pragma once
class CSettings
{
public:
CSettings();
inline bool GetEnabled()
{
Reload();
return settings.enabled;
}
inline void SetEnabled(bool enabled)
{
settings.enabled = enabled;
Save();
}
void Save();
void Load();
private:
struct Settings
{
bool enabled{ true };
};
void Reload();
void MigrateFromRegistry();
void ParseJson();
Settings settings;
std::wstring jsonFilePath;
FILETIME lastLoadedTime;
};
CSettings& CSettingsInstance();

View File

@@ -2,12 +2,18 @@
#include "Generated Files/resource.h"
#include "ImageResizerExt_i.h"
#include "dllmain.h"
#include <interface/powertoy_module_interface.h>
#include <ImageResizerConstants.h>
#include <Settings.h>
#include <trace.h>
#include <common/logger/logger.h>
#include <common/SettingsAPI/settings_objects.h>
#include <common/utils/package.h>
#include <common/utils/process_path.h>
#include <common/utils/resources.h>
#include "Settings.h"
#include "trace.h"
#include <imageresizer/dll/ImageResizerConstants.h>
#include <common/utils/logger_helper.h>
#include <interface/powertoy_module_interface.h>
CImageResizerExtModule _AtlModule;
HINSTANCE g_hInst_imageResizer = 0;
@@ -43,6 +49,7 @@ public:
m_enabled = CSettingsInstance().GetEnabled();
app_name = GET_RESOURCE_STRING(IDS_IMAGERESIZER);
app_key = ImageResizerConstants::ModuleKey;
LoggerHelpers::init_logger(app_key, L"ModuleInterface", LogSettings::imageResizerLoggerName);
};
// Destroy the powertoy and free memory
@@ -89,6 +96,20 @@ public:
{
m_enabled = true;
CSettingsInstance().SetEnabled(m_enabled);
if (package::IsWin11OrGreater())
{
std::wstring path = get_module_folderpath(g_hInst_imageResizer);
std::wstring packageUri = path + L"\\ImageResizerContextMenuPackage.msix";
std::wstring packageDisplayName{ L"ImageResizerContextMenu" };
if (!package::IsPackageRegistered(packageDisplayName))
{
package::RegisterSparsePackage(path, packageUri);
}
}
Trace::EnableImageResizer(m_enabled);
}

View File

@@ -1,59 +0,0 @@
#include "pch.h"
#include "trace.h"
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToys",
// {38e8889b-9731-53f5-e901-e8a7c1753074}
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
void Trace::RegisterProvider() noexcept
{
TraceLoggingRegister(g_hProvider);
}
void Trace::UnregisterProvider() noexcept
{
TraceLoggingUnregister(g_hProvider);
}
void Trace::EnableImageResizer(_In_ bool enabled) noexcept
{
TraceLoggingWrite(
g_hProvider,
"ImageResizer_EnableImageResizer",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingBoolean(enabled, "Enabled"));
}
void Trace::Invoked() noexcept
{
TraceLoggingWrite(
g_hProvider,
"ImageResizer_Invoked",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
}
void Trace::InvokedRet(_In_ HRESULT hr) noexcept
{
TraceLoggingWrite(
g_hProvider,
"ImageResizer_InvokedRet",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingHResult(hr),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
}
void Trace::QueryContextMenuError(_In_ HRESULT hr) noexcept
{
TraceLoggingWrite(
g_hProvider,
"ImageResizer_QueryContextMenuError",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingHResult(hr),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
}

View File

@@ -1,12 +0,0 @@
#pragma once
class Trace
{
public:
static void RegisterProvider() noexcept;
static void UnregisterProvider() noexcept;
static void EnableImageResizer(_In_ bool enabled) noexcept;
static void Invoked() noexcept;
static void InvokedRet(_In_ HRESULT hr) noexcept;
static void QueryContextMenuError(_In_ HRESULT hr) noexcept;
};