[PowerPreview] simplify and use modulesRegistry API

This commit is contained in:
yuyoyuppe
2021-10-05 18:54:42 +03:00
committed by Andrey Nekrasov
parent c324cd5953
commit 092ee49139
28 changed files with 217 additions and 1399 deletions

View File

@@ -313,7 +313,7 @@ namespace PowerToysSettings
return json::has(props, name) && json::has(props.GetNamedObject(name), L"value", type);
}
std::optional<bool> PowerToyValues::get_bool_value(std::wstring_view property_name)
std::optional<bool> PowerToyValues::get_bool_value(std::wstring_view property_name) const
{
if (!has_property(m_json, property_name, json::JsonValueType::Boolean))
{
@@ -322,7 +322,7 @@ namespace PowerToysSettings
return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedBoolean(L"value");
}
std::optional<int> PowerToyValues::get_int_value(std::wstring_view property_name)
std::optional<int> PowerToyValues::get_int_value(std::wstring_view property_name) const
{
if (!has_property(m_json, property_name, json::JsonValueType::Number))
{
@@ -331,7 +331,7 @@ namespace PowerToysSettings
return static_cast<int>(m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedNumber(L"value"));
}
std::optional<std::wstring> PowerToyValues::get_string_value(std::wstring_view property_name)
std::optional<std::wstring> PowerToyValues::get_string_value(std::wstring_view property_name) const
{
if (!has_property(m_json, property_name, json::JsonValueType::String))
{
@@ -340,7 +340,7 @@ namespace PowerToysSettings
return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedString(L"value").c_str();
}
std::optional<json::JsonObject> PowerToyValues::get_json(std::wstring_view property_name)
std::optional<json::JsonObject> PowerToyValues::get_json(std::wstring_view property_name) const
{
if (!has_property(m_json, property_name, json::JsonValueType::Object))
{

View File

@@ -79,10 +79,10 @@ namespace PowerToysSettings
m_json.GetNamedObject(L"properties").SetNamedValue(name, prop_value);
}
std::optional<bool> get_bool_value(std::wstring_view property_name);
std::optional<int> get_int_value(std::wstring_view property_name);
std::optional<std::wstring> get_string_value(std::wstring_view property_name);
std::optional<json::JsonObject> get_json(std::wstring_view property_name);
std::optional<bool> get_bool_value(std::wstring_view property_name) const;
std::optional<int> get_int_value(std::wstring_view property_name) const;
std::optional<std::wstring> get_string_value(std::wstring_view property_name) const;
std::optional<json::JsonObject> get_json(std::wstring_view property_name) const;
json::JsonObject get_raw_json();
std::wstring serialize();

View File

@@ -5,3 +5,4 @@
#include <winrt/Windows.Foundation.Collections.h>
#include <Shlwapi.h>
#include <ProjectTelemetry.h>

View File

@@ -2,7 +2,6 @@
#include <common/SettingsAPI/settings_objects.h>
#include "powerpreview.h"
#include "trace.h"
#include "settings.h"
#include "Generated Files/resource.h"
#include <common/notifications/dont_show_again.h>
#include <common/notifications/notifications.h>
@@ -10,62 +9,46 @@
#include <common/utils/elevation.h>
#include <common/utils/resources.h>
#include <common/utils/os-detect.h>
#include <common/utils/process_path.h>
// Constructor
PowerPreviewModule::PowerPreviewModule() :
m_moduleName(GET_RESOURCE_STRING(IDS_MODULE_NAME)),
app_key(powerpreviewConstants::ModuleKey)
{
// Initialize the preview modules.
m_fileExplorerModules.emplace_back(std::make_unique<PreviewHandlerSettings>(
true,
L"svg-previewer-toggle-setting",
GET_RESOURCE_STRING(IDS_PREVPANE_SVG_SETTINGS_DESCRIPTION),
L"{ddee2b8a-6807-48a6-bb20-2338174ff779}",
L"Svg Preview Handler",
std::make_unique<RegistryWrapper>()));
const std::wstring installationDir = get_module_folderpath();
const bool installPerUser = false;
m_fileExplorerModules.push_back({ .settingName = L"svg-previewer-toggle-setting",
.settingDescription = GET_RESOURCE_STRING(IDS_PREVPANE_SVG_SETTINGS_DESCRIPTION),
.registryChanges = getSvgPreviewHandlerChangset(installationDir, installPerUser) });
m_fileExplorerModules.emplace_back(std::make_unique<PreviewHandlerSettings>(
true,
L"md-previewer-toggle-setting",
GET_RESOURCE_STRING(IDS_PREVPANE_MD_SETTINGS_DESCRIPTION),
L"{45769bcc-e8fd-42d0-947e-02beef77a1f5}",
L"Markdown Preview Handler",
std::make_unique<RegistryWrapper>()));
m_fileExplorerModules.push_back({ .settingName = L"md-previewer-toggle-setting",
.settingDescription = GET_RESOURCE_STRING(IDS_PREVPANE_MD_SETTINGS_DESCRIPTION),
.registryChanges = getMdPreviewHandlerChangset(installationDir, installPerUser) });
m_fileExplorerModules.emplace_back(std::make_unique<PreviewHandlerSettings>(
true,
L"pdf-previewer-toggle-setting",
GET_RESOURCE_STRING(IDS_PREVPANE_PDF_SETTINGS_DESCRIPTION),
L"{07665729-6243-4746-95b7-79579308d1b2}",
L"PDF Preview Handler",
std::make_unique<RegistryWrapper>()));
m_fileExplorerModules.push_back({ .settingName = L"pdf-previewer-toggle-setting",
.settingDescription = GET_RESOURCE_STRING(IDS_PREVPANE_PDF_SETTINGS_DESCRIPTION),
.registryChanges = getPdfPreviewHandlerChangset(installationDir, installPerUser) });
m_fileExplorerModules.emplace_back(std::make_unique<ThumbnailProviderSettings>(
true,
L"svg-thumbnail-toggle-setting",
GET_RESOURCE_STRING(IDS_SVG_THUMBNAIL_PROVIDER_SETTINGS_DESCRIPTION),
L"{36B27788-A8BB-4698-A756-DF9F11F64F84}",
L"Svg Thumbnail Provider",
std::make_unique<RegistryWrapper>(),
L".svg\\shellex\\{E357FCCD-A995-4576-B01F-234630154E96}"));
m_fileExplorerModules.push_back({ .settingName = L"svg-thumbnail-toggle-setting",
.settingDescription = GET_RESOURCE_STRING(IDS_SVG_THUMBNAIL_PROVIDER_SETTINGS_DESCRIPTION),
.registryChanges = getSvgThumbnailHandlerChangset(installationDir, installPerUser) });
// PDF
m_fileExplorerModules.emplace_back(std::make_unique<ThumbnailProviderSettings>(
true,
L"pdf-thumbnail-toggle-setting",
GET_RESOURCE_STRING(IDS_PDF_THUMBNAIL_PROVIDER_SETTINGS_DESCRIPTION),
L"{BCC13D15-9720-4CC4-8371-EA74A274741E}",
L"Pdf Thumbnail Provider",
std::make_unique<RegistryWrapper>(),
L".pdf\\shellex\\{E357FCCD-A995-4576-B01F-234630154E96}"));
m_fileExplorerModules.push_back({ .settingName = L"pdf-thumbnail-toggle-setting",
.settingDescription = GET_RESOURCE_STRING(IDS_PDF_THUMBNAIL_PROVIDER_SETTINGS_DESCRIPTION),
.registryChanges = getPdfThumbnailHandlerChangset(installationDir, installPerUser) });
// Initialize the toggle states for each module.
init_settings();
try
{
PowerToysSettings::PowerToyValues settings =
PowerToysSettings::PowerToyValues::load_from_settings_file(PowerPreviewModule::get_key());
// File Explorer might be disabled if user updated from old to new settings.
// Initialize the registry state in the constructor as PowerPreviewModule::enable/disable will not be called on startup
update_registry_to_match_toggles();
apply_settings(settings);
}
catch (std::exception const& e)
{
Trace::InitSetErrorLoadingFile(e.what());
}
}
// Destroy the powertoy and free memory.
@@ -109,9 +92,9 @@ bool PowerPreviewModule::get_config(_Out_ wchar_t* buffer, _Out_ int* buffer_siz
for (auto& fileExplorerModule : m_fileExplorerModules)
{
settings.add_bool_toggle(
fileExplorerModule->GetToggleSettingName(),
fileExplorerModule->GetToggleSettingDescription(),
fileExplorerModule->GetToggleSettingState());
fileExplorerModule.settingName,
fileExplorerModule.settingDescription,
fileExplorerModule.registryChanges.isApplied());
}
return settings.serialize_to_buffer(buffer, buffer_size);
@@ -122,21 +105,8 @@ void PowerPreviewModule::set_config(const wchar_t* config)
{
try
{
PowerToysSettings::PowerToyValues settings = PowerToysSettings::PowerToyValues::from_json_string(config, get_key());
bool updateSuccess = true;
bool isElevated = is_process_elevated(false);
for (auto& fileExplorerModule : m_fileExplorerModules)
{
// The new settings interface does not have a toggle to modify enabled, consider File Explorer to always be enabled
updateSuccess = updateSuccess && fileExplorerModule->UpdateState(settings, true, isElevated);
}
if (!updateSuccess)
{
show_update_warning_message();
}
auto settings = PowerToysSettings::PowerToyValues::from_json_string(config, get_key());
apply_settings(settings);
settings.save_to_settings_file();
}
catch (std::exception const& e)
@@ -145,135 +115,102 @@ void PowerPreviewModule::set_config(const wchar_t* config)
}
}
// Enable preview handlers.
void PowerPreviewModule::enable()
{
if (!this->m_enabled)
if (!m_enabled)
{
Trace::EnabledPowerPreview(true);
}
this->m_enabled = true;
m_enabled = true;
}
// Disable active preview handlers.
void PowerPreviewModule::disable()
{
elevation_check_wrapper([this]() {
// Check if the process is elevated in order to have permissions to modify HKLM registry
if (is_process_elevated(false))
{
for (auto& fileExplorerModule : m_fileExplorerModules)
{
fileExplorerModule->Disable();
fileExplorerModule.registryChanges.unapply();
}
});
}
else
{
show_update_warning_message();
}
if (this->m_enabled)
if (m_enabled)
{
Trace::EnabledPowerPreview(false);
}
this->m_enabled = false;
m_enabled = false;
}
// Returns if the powertoys is enabled
bool PowerPreviewModule::is_enabled()
{
return this->m_enabled;
}
// Load the settings file.
void PowerPreviewModule::init_settings()
{
try
{
// Load and parse the settings file for this PowerToy.
PowerToysSettings::PowerToyValues settings =
PowerToysSettings::PowerToyValues::load_from_settings_file(PowerPreviewModule::get_key());
// Load settings states.
for (auto& fileExplorerModule : m_fileExplorerModules)
{
fileExplorerModule->LoadState(settings);
}
}
catch (std::exception const& e)
{
Trace::InitSetErrorLoadingFile(e.what());
}
}
// Function to check if the registry states need to be updated
bool PowerPreviewModule::is_registry_update_required()
{
for (auto& fileExplorerModule : m_fileExplorerModules)
{
if (fileExplorerModule->GetToggleSettingState() != fileExplorerModule->CheckRegistryState())
{
return true;
}
}
return false;
return m_enabled;
}
// Function to warn the user that PowerToys needs to run as administrator for changes to take effect
void PowerPreviewModule::show_update_warning_message()
{
using namespace notifications;
if (!is_toast_disabled(PreviewModulesDontShowAgainRegistryPath, PreviewModulesDisableIntervalInDays))
if (is_toast_disabled(PreviewModulesDontShowAgainRegistryPath, PreviewModulesDisableIntervalInDays))
{
std::vector<action_t> actions = {
link_button{ GET_RESOURCE_STRING(IDS_FILEEXPLORER_ADMIN_RESTART_WARNING_OPEN_SETTINGS),
L"powertoys://open_settings/" },
link_button{ GET_RESOURCE_STRING(IDS_FILEEXPLORER_ADMIN_RESTART_WARNING_DONT_SHOW_AGAIN),
L"powertoys://couldnt_toggle_powerpreview_modules_disable/" }
};
show_toast_with_activations(GET_RESOURCE_STRING(IDS_FILEEXPLORER_ADMIN_RESTART_WARNING_DESCRIPTION),
GET_RESOURCE_STRING(IDS_FILEEXPLORER_ADMIN_RESTART_WARNING_TITLE),
{},
std::move(actions));
return;
}
std::vector<action_t> actions = {
link_button{ GET_RESOURCE_STRING(IDS_FILEEXPLORER_ADMIN_RESTART_WARNING_OPEN_SETTINGS),
L"powertoys://open_settings/" },
link_button{ GET_RESOURCE_STRING(IDS_FILEEXPLORER_ADMIN_RESTART_WARNING_DONT_SHOW_AGAIN),
L"powertoys://couldnt_toggle_powerpreview_modules_disable/" }
};
show_toast_with_activations(GET_RESOURCE_STRING(IDS_FILEEXPLORER_ADMIN_RESTART_WARNING_DESCRIPTION),
GET_RESOURCE_STRING(IDS_FILEEXPLORER_ADMIN_RESTART_WARNING_TITLE),
{},
std::move(actions));
}
// Function that checks if a registry method is required and if so checks if the process is elevated and accordingly executes the method or shows a warning
void PowerPreviewModule::registry_and_elevation_check_wrapper(std::function<void()> method)
void PowerPreviewModule::apply_settings(const PowerToysSettings::PowerToyValues& settings)
{
// Check if a registry update is required
if (is_registry_update_required())
{
elevation_check_wrapper(method);
}
}
// Function that checks if the process is elevated and accordingly executes the method or shows a warning
void PowerPreviewModule::elevation_check_wrapper(std::function<void()> method)
{
// Check if the process is elevated in order to have permissions to modify HKLM registry
if (is_process_elevated(false))
{
method();
}
// Show a warning if it doesn't have permissions
else
const bool isElevated = is_process_elevated(false);
bool notifyShell = false;
if (!isElevated)
{
show_update_warning_message();
return;
}
for (auto& fileExplorerModule : m_fileExplorerModules)
{
const auto toggle = settings.get_bool_value(fileExplorerModule.settingName);
// Skip if no need to update
if (!toggle.has_value() || *toggle == fileExplorerModule.registryChanges.isApplied())
{
continue;
}
// (Un)Apply registry changes depending on the new setting value
const bool updated = *toggle ? fileExplorerModule.registryChanges.apply() : fileExplorerModule.registryChanges.unapply();
if (updated)
{
notifyShell = true;
Trace::PowerPreviewSettingsUpdated(fileExplorerModule.settingName.c_str(), !*toggle, *toggle, true);
}
else
{
Trace::PowerPreviewSettingsUpdateFailed(fileExplorerModule.settingName.c_str(), !*toggle, *toggle, true);
}
}
if (notifyShell)
{
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
}
}
// Function that updates the registry state to match the toggle states
void PowerPreviewModule::update_registry_to_match_toggles()
{
registry_and_elevation_check_wrapper([this]() {
for (auto& fileExplorerModule : m_fileExplorerModules)
{
if (fileExplorerModule->GetToggleSettingState())
{
// Enable all the modules with initial state set as true.
fileExplorerModule->Enable();
}
else
{
fileExplorerModule->Disable();
}
}
});
}

View File

@@ -1,15 +1,19 @@
#include "pch.h"
#include <interface/powertoy_module_interface.h>
#include "trace.h"
#include "settings.h"
#include "thumbnail_provider.h"
#include "preview_handler.h"
#include "registry_wrapper.h"
#include <powerpreview/powerpreviewConstants.h>
#include <functional>
using namespace PowerPreviewSettings;
#include <common/utils/modulesRegistry.h>
#include <common/SettingsAPI/settings_objects.h>
struct FileExplorerModule
{
std::wstring settingName;
std::wstring settingDescription;
registry::Changeset registryChanges;
};
// Implement the PowerToy Module Interface and all the required methods.
class PowerPreviewModule : public PowertoyModuleIface
@@ -18,25 +22,13 @@ private:
// The PowerToy state.
bool m_enabled = false;
std::wstring m_moduleName;
//contains the non localized key of the powertoy
// Contains the non localized key of the powertoy
std::wstring app_key;
std::vector<std::unique_ptr<FileExplorerPreviewSettings>> m_fileExplorerModules;
// Function to check if the registry states need to be updated
bool is_registry_update_required();
std::vector<FileExplorerModule> m_fileExplorerModules;
// Function to warn the user that PowerToys needs to run as administrator for changes to take effect
void show_update_warning_message();
// Function that checks if a registry method is required and if so checks if the process is elevated and accordingly executes the method or shows a warning
void registry_and_elevation_check_wrapper(std::function<void()> method);
// Function that checks if the process is elevated and accordingly executes the method or shows a warning
void elevation_check_wrapper(std::function<void()> method);
// Function that updates the registry state to match the toggle states
void update_registry_to_match_toggles();
void apply_settings(const PowerToysSettings::PowerToyValues& settings);
public:
PowerPreviewModule();
@@ -48,5 +40,4 @@ public:
virtual void enable();
virtual void disable();
virtual bool is_enabled();
virtual void init_settings();
};

View File

@@ -44,13 +44,8 @@
<ClInclude Include="CLSID.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="powerpreviewConstants.h" />
<ClInclude Include="preview_handler.h" />
<ClInclude Include="registry_wrapper.h" />
<ClInclude Include="registry_wrapper_interface.h" />
<ClInclude Include="Generated Files/resource.h" />
<None Include="resource.base.h" />
<ClInclude Include="settings.h" />
<ClInclude Include="thumbnail_provider.h" />
<ClInclude Include="trace.h" />
</ItemGroup>
<ItemGroup>
@@ -60,10 +55,6 @@
</ClCompile>
<ClCompile Include="powerpreview.cpp" />
<ClInclude Include="powerpreview.h" />
<ClCompile Include="preview_handler.cpp" />
<ClCompile Include="registry_wrapper.cpp" />
<ClCompile Include="settings.cpp" />
<ClCompile Include="thumbnail_provider.cpp" />
<ClCompile Include="trace.cpp" />
</ItemGroup>
<ItemGroup>

View File

@@ -10,21 +10,9 @@
<ClCompile Include="powerpreview.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="registry_wrapper.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="settings.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="trace.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="preview_handler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="thumbnail_provider.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
@@ -37,24 +25,9 @@
<ClInclude Include="powerpreview.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="registry_wrapper.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="registry_wrapper_interface.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="settings.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="trace.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="preview_handler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="thumbnail_provider.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="powerpreviewConstants.h" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,53 +0,0 @@
#include "pch.h"
#include "preview_handler.h"
namespace PowerPreviewSettings
{
const LPCWSTR PreviewHandlerSettings::preview_handlers_subkey = L"Software\\Microsoft\\Windows\\CurrentVersion\\PreviewHandlers";
// Function to enable the preview handler in registry
LONG PreviewHandlerSettings::Enable()
{
// Add registry value to enable preview.
return this->m_registryWrapper->SetRegistryValue(HKEY_LOCAL_MACHINE, preview_handlers_subkey, this->GetCLSID(), REG_SZ, (LPBYTE)this->GetRegistryValueData().c_str(), (DWORD)(this->GetRegistryValueData().length() * sizeof(wchar_t)));
}
// Function to disable the preview handler in registry
LONG PreviewHandlerSettings::Disable()
{
// Delete the registry key to disable preview.
return this->m_registryWrapper->DeleteRegistryValue(HKEY_LOCAL_MACHINE, preview_handlers_subkey, this->GetCLSID());
}
// Function to check if the preview handler is enabled in registry
bool PreviewHandlerSettings::CheckRegistryState()
{
DWORD dataType;
DWORD byteCount = 255;
wchar_t regValue[255] = { 0 };
LONG errorCode = this->m_registryWrapper->GetRegistryValue(HKEY_LOCAL_MACHINE, preview_handlers_subkey, this->GetCLSID(), &dataType, regValue, &byteCount);
// Registry value was found
if (errorCode == ERROR_SUCCESS)
{
// Check if the value type is string
if (dataType == REG_SZ)
{
// Check if the current registry value matches the expected value
if (wcscmp(regValue, this->GetRegistryValueData().c_str()) == 0)
{
return true;
}
}
}
return false;
}
// Function to retrieve the registry subkey
LPCWSTR PreviewHandlerSettings::GetSubkey()
{
return preview_handlers_subkey;
}
}

View File

@@ -1,31 +0,0 @@
#pragma once
#include "settings.h"
namespace PowerPreviewSettings
{
class PreviewHandlerSettings :
public FileExplorerPreviewSettings
{
private:
// Relative(HKLM/HKCU) sub key path of Preview Handlers list in registry. Registry key for Preview Handlers is generally HKLM\Software\Microsoft\Windows\CurrentVersion\PreviewHandlers, and the value name with CLSID of the handler in it is set to the name of the handler
static const LPCWSTR preview_handlers_subkey;
public:
PreviewHandlerSettings(bool toggleSettingEnabled, const std::wstring& toggleSettingName, const std::wstring& toggleSettingDescription, LPCWSTR clsid, const std::wstring& registryValueData, std::unique_ptr<RegistryWrapperIface> registryWrapper) :
FileExplorerPreviewSettings(toggleSettingEnabled, toggleSettingName, toggleSettingDescription, clsid, registryValueData, std::move(registryWrapper))
{
}
// Function to enable the preview handler in registry
LONG Enable();
// Function to disable the preview handler in registry
LONG Disable();
// Function to check if the preview handler is enabled in registry
bool CheckRegistryState();
// Function to retrieve the registry subkey
static LPCWSTR GetSubkey();
};
}

View File

@@ -1,63 +0,0 @@
#include "pch.h"
#include "registry_wrapper.h"
namespace PowerPreviewSettings
{
LONG RegistryWrapper::SetRegistryValue(HKEY keyScope, LPCWSTR subKey, LPCWSTR valueName, DWORD dwType, CONST BYTE* data, DWORD cbData)
{
HKEY OpenResult;
LONG err = RegOpenKeyExW(keyScope, subKey, 0, KEY_WRITE, &OpenResult);
if (err == ERROR_SUCCESS)
{
err = RegSetValueExW(
OpenResult,
valueName,
0, // This parameter is reserved and must be zero.
dwType,
data,
cbData);
RegCloseKey(OpenResult);
}
return err;
}
LONG RegistryWrapper::GetRegistryValue(HKEY keyScope, LPCWSTR subKey, LPCWSTR valueName, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData)
{
HKEY OpenResult;
LONG err = RegOpenKeyExW(keyScope, subKey, 0, KEY_READ, &OpenResult);
if (err == ERROR_SUCCESS)
{
err = RegGetValueW(
OpenResult,
NULL,
valueName,
RRF_RT_ANY,
pdwType,
pvData,
pcbData);
RegCloseKey(OpenResult);
}
return err;
}
LONG RegistryWrapper::DeleteRegistryValue(HKEY keyScope, LPCWSTR subKey, LPCWSTR valueName)
{
HKEY OpenResult;
LONG err = RegOpenKeyExW(keyScope, subKey, 0, KEY_WRITE, &OpenResult);
if (err == ERROR_SUCCESS)
{
err = RegDeleteKeyValueW(
OpenResult,
NULL,
valueName);
RegCloseKey(OpenResult);
}
return err;
}
}

View File

@@ -1,13 +0,0 @@
#pragma once
#include "registry_wrapper_interface.h"
namespace PowerPreviewSettings
{
class RegistryWrapper : public RegistryWrapperIface
{
public:
virtual LONG SetRegistryValue(HKEY keyScope, LPCWSTR subKey, LPCWSTR valueName, DWORD dwType, CONST BYTE* data, DWORD cbData);
virtual LONG DeleteRegistryValue(HKEY keyScope, LPCWSTR subKey, LPCWSTR valueName);
virtual LONG GetRegistryValue(HKEY keyScope, LPCWSTR subKey, LPCWSTR valueName, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData);
};
}

View File

@@ -1,14 +0,0 @@
#pragma once
class RegistryWrapperIface
{
public:
// Sets a registry value under the mentioned scope(HKCR, HKLM, etc).
virtual LONG SetRegistryValue(HKEY keyScope, LPCWSTR subKey, LPCWSTR valueName, DWORD dwType, CONST BYTE* data, DWORD cbData) = 0;
// Delete a registry value.
virtual LONG DeleteRegistryValue(HKEY keyScope, LPCWSTR subKey, LPCWSTR valueName) = 0;
// Reads a registry value.
virtual LONG GetRegistryValue(HKEY keyScope, LPCWSTR subKey, LPCWSTR valueName, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData) = 0;
};

View File

@@ -1,126 +0,0 @@
#include "pch.h"
#include "settings.h"
#include "trace.h"
#include <iostream>
#include <atlstr.h>
#include <powerpreview/thumbnail_provider.h>
#include <ShlObj_core.h>
using namespace std;
namespace PowerPreviewSettings
{
// Base Settings Class Implementation
FileExplorerPreviewSettings::FileExplorerPreviewSettings(bool toggleSettingEnabled, const std::wstring& toggleSettingName, const std::wstring& toggleSettingDescription, LPCWSTR clsid, const std::wstring& registryValueData, std::unique_ptr<RegistryWrapperIface> registryWrapper) :
m_toggleSettingEnabled(toggleSettingEnabled),
m_toggleSettingName(toggleSettingName),
m_toggleSettingDescription(toggleSettingDescription),
m_clsid(clsid),
m_registryValueData(registryValueData),
m_registryWrapper(std::move(registryWrapper))
{
}
bool FileExplorerPreviewSettings::GetToggleSettingState() const
{
return this->m_toggleSettingEnabled;
}
void FileExplorerPreviewSettings::UpdateToggleSettingState(bool state)
{
this->m_toggleSettingEnabled = state;
}
std::wstring FileExplorerPreviewSettings::GetToggleSettingName() const
{
return this->m_toggleSettingName;
}
std::wstring FileExplorerPreviewSettings::GetToggleSettingDescription() const
{
return this->m_toggleSettingDescription;
}
LPCWSTR FileExplorerPreviewSettings::GetCLSID() const
{
return this->m_clsid;
}
std::wstring FileExplorerPreviewSettings::GetRegistryValueData() const
{
return this->m_registryValueData;
}
// Load initial state of the file explorer module. If no inital state present initialize setting with default value.
void FileExplorerPreviewSettings::LoadState(PowerToysSettings::PowerToyValues& settings)
{
auto toggle = settings.get_bool_value(this->GetToggleSettingName());
if (toggle)
{
// If no existing setting found leave the default initialization value.
this->UpdateToggleSettingState(*toggle);
}
}
// Manage change in state of file explorer module settings.
bool FileExplorerPreviewSettings::UpdateState(PowerToysSettings::PowerToyValues& settings, bool enabled, bool isElevated)
{
auto toggle = settings.get_bool_value(this->GetToggleSettingName());
if (toggle)
{
auto lastState = this->GetToggleSettingState();
auto newState = *toggle;
if (lastState != newState)
{
this->UpdateToggleSettingState(newState);
// If global setting is enable. Add or remove the file explorer module otherwise just change the UI and save the updated config.
if (enabled)
{
// Check if the registry state does not match the new state, registry needs to be modified
if (this->CheckRegistryState() != newState)
{
if (isElevated)
{
LONG err;
if (lastState)
{
err = this->Disable();
}
else
{
err = this->Enable();
}
if (err == ERROR_SUCCESS)
{
Trace::PowerPreviewSettingsUpdated(this->GetToggleSettingName().c_str(), lastState, newState, enabled);
}
else
{
Trace::PowerPreviewSettingsUpdateFailed(this->GetToggleSettingName().c_str(), lastState, newState, enabled);
}
if (dynamic_cast<ThumbnailProviderSettings*>(this))
{
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
}
}
// If process is not elevated, return false as it is not possible to update the registry
else
{
return false;
}
}
// If it matches the new state, no update to registry is required
}
else
{
Trace::PowerPreviewSettingsUpdated(this->GetToggleSettingName().c_str(), lastState, newState, enabled);
}
}
}
return true;
}
}

View File

@@ -1,37 +0,0 @@
#pragma once
#include <string>
#include "Generated Files/resource.h"
#include <common/SettingsAPI/settings_objects.h>
#include "registry_wrapper_interface.h"
namespace PowerPreviewSettings
{
// PowerToy Windows Explorer File Preview Settings.
class FileExplorerPreviewSettings
{
private:
bool m_toggleSettingEnabled;
std::wstring m_toggleSettingName;
std::wstring m_toggleSettingDescription;
std::wstring m_registryValueData;
LPCWSTR m_clsid;
protected:
std::unique_ptr<RegistryWrapperIface> m_registryWrapper;
public:
FileExplorerPreviewSettings(bool toggleSettingEnabled, const std::wstring& toggleSettingName, const std::wstring& toggleSettingDescription, LPCWSTR clsid, const std::wstring& registryValueData, std::unique_ptr<RegistryWrapperIface>);
virtual bool GetToggleSettingState() const;
virtual void UpdateToggleSettingState(bool state);
virtual std::wstring GetToggleSettingName() const;
virtual std::wstring GetToggleSettingDescription() const;
virtual LPCWSTR GetCLSID() const;
virtual std::wstring GetRegistryValueData() const;
virtual void LoadState(PowerToysSettings::PowerToyValues& settings);
virtual bool UpdateState(PowerToysSettings::PowerToyValues& settings, bool enabled, bool isElevated);
virtual LONG Enable() = 0;
virtual LONG Disable() = 0;
virtual bool CheckRegistryState() = 0;
};
}

View File

@@ -1,51 +0,0 @@
#include "pch.h"
#include "thumbnail_provider.h"
namespace PowerPreviewSettings
{
// Function to enable the thumbnail provider in registry
LONG ThumbnailProviderSettings::Enable()
{
// Add registry value to enable thumbnail provider.
return this->m_registryWrapper->SetRegistryValue(HKEY_CLASSES_ROOT, thumbnail_provider_subkey, nullptr, REG_SZ, (LPBYTE)this->GetCLSID(), (DWORD)(wcslen(this->GetCLSID()) * sizeof(wchar_t)));
}
// Function to disable the thumbnail provider in registry
LONG ThumbnailProviderSettings::Disable()
{
// Delete the registry key to disable thumbnail provider.
return this->m_registryWrapper->DeleteRegistryValue(HKEY_CLASSES_ROOT, thumbnail_provider_subkey, nullptr);
}
// Function to check if the thumbnail provider is enabled in registry
bool ThumbnailProviderSettings::CheckRegistryState()
{
DWORD dataType;
DWORD byteCount = 255;
wchar_t regValue[255] = { 0 };
LONG errorCode = this->m_registryWrapper->GetRegistryValue(HKEY_CLASSES_ROOT, thumbnail_provider_subkey, nullptr, &dataType, regValue, &byteCount);
// Registry value was found
if (errorCode == ERROR_SUCCESS)
{
// Check if the value type is string
if (dataType == REG_SZ)
{
// Check if the current registry value matches the expected value
if (wcscmp(regValue, this->GetCLSID()) == 0)
{
return true;
}
}
}
return false;
}
// Function to retrieve the registry subkey
LPCWSTR ThumbnailProviderSettings::GetSubkey()
{
return thumbnail_provider_subkey;
}
}

View File

@@ -1,31 +0,0 @@
#pragma once
#include "settings.h"
namespace PowerPreviewSettings
{
class ThumbnailProviderSettings :
public FileExplorerPreviewSettings
{
private:
// Relative HKCR sub key path of thumbnail provider in registry. Registry key for Thumbnail Providers is generally HKCR\fileExtension\{E357FCCD-A995-4576-B01F-234630154E96}, and the default value in it is set to the CLSID of the provider
LPCWSTR thumbnail_provider_subkey;
public:
ThumbnailProviderSettings(bool toggleSettingEnabled, const std::wstring& toggleSettingName, const std::wstring& toggleSettingDescription, LPCWSTR clsid, const std::wstring& registryValueData, std::unique_ptr<RegistryWrapperIface> registryWrapper, LPCWSTR subkey) :
FileExplorerPreviewSettings(toggleSettingEnabled, toggleSettingName, toggleSettingDescription, clsid, registryValueData, std::move(registryWrapper)), thumbnail_provider_subkey(subkey)
{
}
// Function to enable the thumbnail provider in registry
LONG Enable();
// Function to disable the thumbnail provider in registry
LONG Disable();
// Function to check if the thumbnail provider is enabled in registry
bool CheckRegistryState();
// Function to retrieve the registry subkey
LPCWSTR GetSubkey();
};
}

View File

@@ -1,438 +0,0 @@
#include "pch.h"
#include "CppUnitTest.h"
#include <common/SettingsAPI/settings_objects.h>
#include <powerpreview/settings.cpp>
#include <powerpreview/trace.cpp>
#include <powerpreview/registry_wrapper.h>
#include <powerpreview/preview_handler.cpp>
#include <powerpreview/thumbnail_provider.cpp>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace PowerToysSettings;
using namespace PowerPreviewSettings;
namespace FileExplorerPreviewSettingsTest
{
struct FunctionProperties
{
public:
LONG ReturnValue = ERROR_SUCCESS;
int NumOfCalls = 0;
HKEY Scope = NULL;
LPCWSTR SubKey;
LPCWSTR ValueName;
wchar_t ValueData[255] = { 0 };
};
class RegistryMock : public RegistryWrapperIface
{
private:
wchar_t mockData[255] = { 0 };
public:
FunctionProperties SetRegistryMockProperties;
FunctionProperties DeleteRegistryMockProperties;
FunctionProperties GetRegistryMockProperties;
LONG SetRegistryValue(HKEY keyScope, LPCWSTR subKey, LPCWSTR valueName, DWORD dwType, CONST BYTE* data, DWORD cbData)
{
SetRegistryMockProperties.NumOfCalls += 1;
SetRegistryMockProperties.Scope = keyScope;
SetRegistryMockProperties.SubKey = subKey;
SetRegistryMockProperties.ValueName = valueName;
wcscpy_s(SetRegistryMockProperties.ValueData, cbData, (WCHAR*)data);
return SetRegistryMockProperties.ReturnValue;
}
LONG DeleteRegistryValue(HKEY keyScope, LPCWSTR subKey, LPCWSTR valueName)
{
DeleteRegistryMockProperties.NumOfCalls++;
DeleteRegistryMockProperties.Scope = keyScope;
DeleteRegistryMockProperties.SubKey = subKey;
DeleteRegistryMockProperties.ValueName = valueName;
return DeleteRegistryMockProperties.ReturnValue;
}
LONG GetRegistryValue(HKEY keyScope, LPCWSTR subKey, LPCWSTR valueName, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData)
{
GetRegistryMockProperties.NumOfCalls++;
GetRegistryMockProperties.Scope = keyScope;
GetRegistryMockProperties.SubKey = subKey;
GetRegistryMockProperties.ValueName = valueName;
*pdwType = REG_SZ;
wcscpy_s((LPWSTR)pvData, 255, mockData);
return GetRegistryMockProperties.ReturnValue;
}
void SetMockData(std::wstring data)
{
wcscpy_s(mockData, data.c_str());
}
};
TEST_CLASS (BaseSettingsTest)
{
public:
TEST_METHOD (LoadState_ShouldLoadValidState_IfInitalStateIsPresent)
{
// Arrange
bool defaultState = true;
RegistryMock* mockRegistryWrapper = new RegistryMock();
PreviewHandlerSettings previewSettings = GetPreviewHandlerSettingsObject(defaultState, mockRegistryWrapper);
auto settings = PowerToyValues::from_json_string(GetJSONSettings(previewSettings.GetToggleSettingName(), L"false"), L"FileExplorerPreviewTests");
// Act
previewSettings.LoadState(settings);
// Assert
Assert::IsFalse(previewSettings.GetToggleSettingState());
}
TEST_METHOD (LoadState_ShouldNotChangeDefaultState_IfNoInitalStateIsPresent)
{
// Arrange
bool defaultState = true;
RegistryMock* mockRegistryWrapper = new RegistryMock();
PreviewHandlerSettings previewSettings = GetPreviewHandlerSettingsObject(defaultState, mockRegistryWrapper);
auto settings = PowerToyValues::from_json_string(L"{\"name\":\"Module Name\"}", L"FileExplorerPreviewTests");
// Act
previewSettings.LoadState(settings);
// Assert
Assert::AreEqual(previewSettings.GetToggleSettingState(), defaultState);
}
TEST_METHOD (PreviewHandlerSettingsUpdateState_ShouldDisableInRegistry_IfPreviewsAreEnabledAndNewSettingsStateIsFalseAndPowerToysIsElevatedAndRegistryContainsThePreview)
{
// Arrange
bool enabled = true;
bool elevated = true;
RegistryMock* mockRegistryWrapper = new RegistryMock();
PreviewHandlerSettings previewSettings = GetPreviewHandlerSettingsObject(true, mockRegistryWrapper);
auto settings = PowerToyValues::from_json_string(GetJSONSettings(previewSettings.GetToggleSettingName(), L"false"), L"FileExplorerPreviewTests");
previewSettings.UpdateToggleSettingState(true);
// Add expected data in registry
mockRegistryWrapper->SetMockData(previewSettings.GetRegistryValueData());
// Act
previewSettings.UpdateState(settings, enabled, elevated);
// Assert
Assert::IsFalse(previewSettings.GetToggleSettingState());
Assert::AreEqual(mockRegistryWrapper->DeleteRegistryMockProperties.NumOfCalls, 1);
Assert::AreEqual(mockRegistryWrapper->GetRegistryMockProperties.NumOfCalls, 1);
}
TEST_METHOD (ThumbnailProviderSettingsUpdateState_ShouldDisableInRegistry_IfPreviewsAreEnabledAndNewSettingsStateIsFalseAndPowerToysIsElevatedAndRegistryContainsThePreview)
{
// Arrange
bool enabled = true;
bool elevated = true;
RegistryMock* mockRegistryWrapper = new RegistryMock();
ThumbnailProviderSettings thumbnailSettings = GetThumbnailProviderSettingsObject(true, mockRegistryWrapper);
auto settings = PowerToyValues::from_json_string(GetJSONSettings(thumbnailSettings.GetToggleSettingName(), L"false"), L"FileExplorerPreviewTests");
thumbnailSettings.UpdateToggleSettingState(true);
// Add expected data in registry
mockRegistryWrapper->SetMockData(thumbnailSettings.GetCLSID());
// Act
thumbnailSettings.UpdateState(settings, enabled, elevated);
// Assert
Assert::IsFalse(thumbnailSettings.GetToggleSettingState());
Assert::AreEqual(mockRegistryWrapper->DeleteRegistryMockProperties.NumOfCalls, 1);
Assert::AreEqual(mockRegistryWrapper->GetRegistryMockProperties.NumOfCalls, 1);
}
TEST_METHOD (UpdateState_ShouldNotDisableInRegistry_IfPreviewsAreEnabledAndNewSettingsStateIsFalseAndPowerToysIsElevatedAndRegistryDoesNotContainThePreview)
{
// Arrange
bool enabled = true;
bool elevated = true;
RegistryMock* mockRegistryWrapper = new RegistryMock();
PreviewHandlerSettings previewSettings = GetPreviewHandlerSettingsObject(true, mockRegistryWrapper);
auto settings = PowerToyValues::from_json_string(GetJSONSettings(previewSettings.GetToggleSettingName(), L"false"), L"FileExplorerPreviewTests");
previewSettings.UpdateToggleSettingState(true);
// Act
previewSettings.UpdateState(settings, enabled, elevated);
// Assert
Assert::IsFalse(previewSettings.GetToggleSettingState());
Assert::AreEqual(mockRegistryWrapper->DeleteRegistryMockProperties.NumOfCalls, 0);
Assert::AreEqual(mockRegistryWrapper->GetRegistryMockProperties.NumOfCalls, 1);
}
TEST_METHOD (UpdateState_ShouldNotDisableInRegistry_IfPreviewsAreEnabledAndNewSettingsStateIsFalseAndPowerToysIsNotElevated)
{
// Arrange
bool enabled = true;
bool elevated = false;
RegistryMock* mockRegistryWrapper = new RegistryMock();
PreviewHandlerSettings previewSettings = GetPreviewHandlerSettingsObject(true, mockRegistryWrapper);
auto settings = PowerToyValues::from_json_string(GetJSONSettings(previewSettings.GetToggleSettingName(), L"false"), L"FileExplorerPreviewTests");
previewSettings.UpdateToggleSettingState(true);
// Act
previewSettings.UpdateState(settings, enabled, elevated);
// Assert
Assert::IsFalse(previewSettings.GetToggleSettingState());
Assert::AreEqual(mockRegistryWrapper->DeleteRegistryMockProperties.NumOfCalls, 0);
Assert::AreEqual(mockRegistryWrapper->GetRegistryMockProperties.NumOfCalls, 1);
}
TEST_METHOD (UpdateState_ShouldEnableInRegistry_IfPreviewsAreEnabledAndNewSettingsStateIsTrueAndPowerToysIsElevatedAndRegistryDoesNotContainThePreview)
{
// Arrange
bool enabled = true;
bool elevated = true;
RegistryMock* mockRegistryWrapper = new RegistryMock();
PreviewHandlerSettings previewSettings = GetPreviewHandlerSettingsObject(true, mockRegistryWrapper);
auto settings = PowerToyValues::from_json_string(GetJSONSettings(previewSettings.GetToggleSettingName(), L"true"), L"FileExplorerPreviewTests");
previewSettings.UpdateToggleSettingState(false);
// Act
previewSettings.UpdateState(settings, enabled, elevated);
// Assert
Assert::AreEqual(mockRegistryWrapper->SetRegistryMockProperties.NumOfCalls, 1);
Assert::AreEqual(mockRegistryWrapper->GetRegistryMockProperties.NumOfCalls, 1);
}
TEST_METHOD (PreviewHandlerSettingsUpdateState_ShouldNotEnableInRegistry_IfPreviewsAreEnabledAndNewSettingsStateIsTrueAndPowerToysIsElevatedAndRegistryContainsThePreview)
{
// Arrange
bool enabled = true;
bool elevated = true;
RegistryMock* mockRegistryWrapper = new RegistryMock();
PreviewHandlerSettings previewSettings = GetPreviewHandlerSettingsObject(true, mockRegistryWrapper);
auto settings = PowerToyValues::from_json_string(GetJSONSettings(previewSettings.GetToggleSettingName(), L"true"), L"FileExplorerPreviewTests");
previewSettings.UpdateToggleSettingState(false);
// Add expected data in registry
mockRegistryWrapper->SetMockData(previewSettings.GetRegistryValueData());
// Act
previewSettings.UpdateState(settings, enabled, elevated);
// Assert
Assert::AreEqual(mockRegistryWrapper->SetRegistryMockProperties.NumOfCalls, 0);
Assert::AreEqual(mockRegistryWrapper->GetRegistryMockProperties.NumOfCalls, 1);
}
TEST_METHOD (ThumbnailProviderSettingsUpdateState_ShouldNotEnableInRegistry_IfPreviewsAreEnabledAndNewSettingsStateIsTrueAndPowerToysIsElevatedAndRegistryContainsThePreview)
{
// Arrange
bool enabled = true;
bool elevated = true;
RegistryMock* mockRegistryWrapper = new RegistryMock();
ThumbnailProviderSettings thumbnailSettings = GetThumbnailProviderSettingsObject(true, mockRegistryWrapper);
auto settings = PowerToyValues::from_json_string(GetJSONSettings(thumbnailSettings.GetToggleSettingName(), L"true"), L"FileExplorerPreviewTests");
thumbnailSettings.UpdateToggleSettingState(false);
// Add expected data in registry
mockRegistryWrapper->SetMockData(thumbnailSettings.GetCLSID());
// Act
thumbnailSettings.UpdateState(settings, enabled, elevated);
// Assert
Assert::AreEqual(mockRegistryWrapper->SetRegistryMockProperties.NumOfCalls, 0);
Assert::AreEqual(mockRegistryWrapper->GetRegistryMockProperties.NumOfCalls, 1);
}
TEST_METHOD (UpdateState_ShouldNotEnableInRegistry_IfPreviewsAreEnabledAndNewSettingsStateIsTrueAndPowerToysIsNotElevated)
{
// Arrange
bool enabled = true;
bool elevated = false;
RegistryMock* mockRegistryWrapper = new RegistryMock();
PreviewHandlerSettings previewSettings = GetPreviewHandlerSettingsObject(true, mockRegistryWrapper);
auto settings = PowerToyValues::from_json_string(GetJSONSettings(previewSettings.GetToggleSettingName(), L"true"), L"FileExplorerPreviewTests");
previewSettings.UpdateToggleSettingState(false);
// Act
previewSettings.UpdateState(settings, enabled, elevated);
// Assert
Assert::AreEqual(mockRegistryWrapper->SetRegistryMockProperties.NumOfCalls, 0);
Assert::AreEqual(mockRegistryWrapper->GetRegistryMockProperties.NumOfCalls, 1);
}
TEST_METHOD (UpdateState_ShouldUpdateToggleSettingState_IfPreviewsAreEnabledAndPowerToysIsElevated)
{
// Arrange
bool enabled = false;
bool elevated = true;
RegistryMock* mockRegistryWrapper = new RegistryMock();
PreviewHandlerSettings previewSettings = GetPreviewHandlerSettingsObject(true, mockRegistryWrapper);
auto settings = PowerToyValues::from_json_string(GetJSONSettings(previewSettings.GetToggleSettingName(), L"false"), L"FileExplorerPreviewTests");
// Act
previewSettings.UpdateState(settings, enabled, elevated);
// Assert
Assert::IsFalse(previewSettings.GetToggleSettingState());
}
TEST_METHOD (UpdateState_ShouldUpdateToggleSettingState_IfPreviewsAreEnabledAndPowerToysIsNotElevated)
{
// Arrange
bool enabled = false;
bool elevated = false;
RegistryMock* mockRegistryWrapper = new RegistryMock();
PreviewHandlerSettings previewSettings = GetPreviewHandlerSettingsObject(true, mockRegistryWrapper);
auto settings = PowerToyValues::from_json_string(GetJSONSettings(previewSettings.GetToggleSettingName(), L"false"), L"FileExplorerPreviewTests");
// Act
previewSettings.UpdateState(settings, enabled, elevated);
// Assert
Assert::IsFalse(previewSettings.GetToggleSettingState());
}
TEST_METHOD (UpdateState_ShouldOnlyUpdateToggleSettingState_IfPreviewsAreDisabledAndPowerToysIsElevated)
{
// Arrange
bool enabled = false;
bool elevated = true;
RegistryMock* mockRegistryWrapper = new RegistryMock();
PreviewHandlerSettings previewSettings = GetPreviewHandlerSettingsObject(true, mockRegistryWrapper);
auto settings = PowerToyValues::from_json_string(GetJSONSettings(previewSettings.GetToggleSettingName(), L"false"), L"FileExplorerPreviewTests");
// Act
previewSettings.UpdateState(settings, enabled, elevated);
// Assert
Assert::IsFalse(previewSettings.GetToggleSettingState());
Assert::AreEqual(mockRegistryWrapper->SetRegistryMockProperties.NumOfCalls, 0);
Assert::AreEqual(mockRegistryWrapper->DeleteRegistryMockProperties.NumOfCalls, 0);
}
TEST_METHOD (UpdateState_ShouldOnlyUpdateToggleSettingState_IfPreviewsAreDisabledAndPowerToysIsNotElevated)
{
// Arrange
bool enabled = false;
bool elevated = false;
RegistryMock* mockRegistryWrapper = new RegistryMock();
PreviewHandlerSettings previewSettings = GetPreviewHandlerSettingsObject(true, mockRegistryWrapper);
auto settings = PowerToyValues::from_json_string(GetJSONSettings(previewSettings.GetToggleSettingName(), L"false"), L"FileExplorerPreviewTests");
// Act
previewSettings.UpdateState(settings, enabled, elevated);
// Assert
Assert::IsFalse(previewSettings.GetToggleSettingState());
Assert::AreEqual(mockRegistryWrapper->SetRegistryMockProperties.NumOfCalls, 0);
Assert::AreEqual(mockRegistryWrapper->DeleteRegistryMockProperties.NumOfCalls, 0);
}
TEST_METHOD (UpdateToggleSettingState_ShouldUpdateState_WhenCalled)
{
// Arrange
bool updatedState = false;
PreviewHandlerSettings previewSettings = GetPreviewHandlerSettingsObject(true, new RegistryMock());
// Act
previewSettings.UpdateToggleSettingState(updatedState);
// Assert
Assert::AreEqual(previewSettings.GetToggleSettingState(), updatedState);
}
TEST_METHOD (PreviewHandlerSettingsEnable_ShouldCallSetRegistryValueWithValidArguments_WhenCalled)
{
// Arrange
RegistryMock* mockRegistryWrapper = new RegistryMock();
PreviewHandlerSettings previewSettings = GetPreviewHandlerSettingsObject(true, mockRegistryWrapper);
// Act
previewSettings.Enable();
// Assert
Assert::AreEqual(mockRegistryWrapper->SetRegistryMockProperties.NumOfCalls, 1);
Assert::AreEqual(mockRegistryWrapper->SetRegistryMockProperties.SubKey, PreviewHandlerSettings::GetSubkey());
Assert::AreEqual(mockRegistryWrapper->SetRegistryMockProperties.ValueName, previewSettings.GetCLSID());
Assert::AreEqual(mockRegistryWrapper->SetRegistryMockProperties.ValueData, previewSettings.GetRegistryValueData().c_str());
Assert::AreEqual((ULONG_PTR)(mockRegistryWrapper->SetRegistryMockProperties.Scope), (ULONG_PTR)(HKEY_LOCAL_MACHINE));
}
TEST_METHOD (PreviewHandlerDisable_ShouldCallDeleteRegistryValueWithValidArguments_WhenCalled)
{
// Arrange
RegistryMock* mockRegistryWrapper = new RegistryMock();
PreviewHandlerSettings previewSettings = GetPreviewHandlerSettingsObject(true, mockRegistryWrapper);
// Act
previewSettings.Disable();
// Assert
Assert::AreEqual(mockRegistryWrapper->DeleteRegistryMockProperties.NumOfCalls, 1);
Assert::AreEqual(mockRegistryWrapper->DeleteRegistryMockProperties.SubKey, PreviewHandlerSettings::GetSubkey());
Assert::AreEqual(mockRegistryWrapper->DeleteRegistryMockProperties.ValueName, previewSettings.GetCLSID());
Assert::AreEqual((ULONG_PTR)(mockRegistryWrapper->DeleteRegistryMockProperties.Scope), (ULONG_PTR)(HKEY_LOCAL_MACHINE));
}
TEST_METHOD (ThumbnailProviderSettingsEnable_ShouldCallSetRegistryValueWithValidArguments_WhenCalled)
{
// Arrange
RegistryMock* mockRegistryWrapper = new RegistryMock();
ThumbnailProviderSettings thumbnailSettings = GetThumbnailProviderSettingsObject(true, mockRegistryWrapper);
// Act
thumbnailSettings.Enable();
// Assert
Assert::AreEqual(mockRegistryWrapper->SetRegistryMockProperties.NumOfCalls, 1);
Assert::AreEqual(mockRegistryWrapper->SetRegistryMockProperties.SubKey, thumbnailSettings.GetSubkey());
Assert::AreEqual(mockRegistryWrapper->SetRegistryMockProperties.ValueName, nullptr);
Assert::AreEqual(mockRegistryWrapper->SetRegistryMockProperties.ValueData, thumbnailSettings.GetCLSID());
Assert::AreEqual((ULONG_PTR)(mockRegistryWrapper->SetRegistryMockProperties.Scope), (ULONG_PTR)(HKEY_CLASSES_ROOT));
}
TEST_METHOD (ThumbnailProviderSettingsDisable_ShouldCallDeleteRegistryValueWithValidArguments_WhenCalled)
{
// Arrange
RegistryMock* mockRegistryWrapper = new RegistryMock();
ThumbnailProviderSettings thumbnailSettings = GetThumbnailProviderSettingsObject(true, mockRegistryWrapper);
// Act
thumbnailSettings.Disable();
// Assert
Assert::AreEqual(mockRegistryWrapper->DeleteRegistryMockProperties.NumOfCalls, 1);
Assert::AreEqual(mockRegistryWrapper->DeleteRegistryMockProperties.SubKey, thumbnailSettings.GetSubkey());
Assert::AreEqual(mockRegistryWrapper->DeleteRegistryMockProperties.ValueName, nullptr);
Assert::AreEqual((ULONG_PTR)(mockRegistryWrapper->DeleteRegistryMockProperties.Scope), (ULONG_PTR)(HKEY_CLASSES_ROOT));
}
PreviewHandlerSettings GetPreviewHandlerSettingsObject(bool defaultState, RegistryWrapperIface* registryMock)
{
return PreviewHandlerSettings(
defaultState,
L"valid-name",
L"valid-description",
L"valid-guid",
L"valid-handler",
std::unique_ptr<RegistryWrapperIface>(registryMock));
}
ThumbnailProviderSettings GetThumbnailProviderSettingsObject(bool defaultState, RegistryWrapperIface* registryMock)
{
return ThumbnailProviderSettings(
defaultState,
L"valid-name",
L"valid-description",
L"valid-guid",
L"valid-handler",
std::unique_ptr<RegistryWrapperIface>(registryMock),
L"valid-subkey");
}
std::wstring GetJSONSettings(const std::wstring& _settingsNameId, const std::wstring& _value) const
{
return L"{\"name\":\"Module Name\",\"properties\" : {\"" + _settingsNameId + L"\":{\"value\":" + _value + L"}},\"version\" : \"1.0\" }";
}
};
}

View File

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

View File

@@ -1 +0,0 @@
#include "pch.h"

View File

@@ -1,17 +0,0 @@
// 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 <Shlwapi.h>
#include <windows.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include "CppUnitTest.h"
#endif //PCH_H

View File

@@ -1,36 +0,0 @@
#include <windows.h>
#include "resource.h"
#include "../../../common/version/version.h"
1 VERSIONINFO
FILEVERSION FILE_VERSION
PRODUCTVERSION PRODUCT_VERSION
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0x0L
#endif
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_DLL
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0" // US English (0x0409), Unicode (0x04B0) charset
BEGIN
VALUE "CompanyName", COMPANY_NAME
VALUE "FileDescription", FILE_DESCRIPTION
VALUE "FileVersion", FILE_VERSION_STRING
VALUE "InternalName", INTERNAL_NAME
VALUE "LegalCopyright", COPYRIGHT_NOTE
VALUE "OriginalFilename", ORIGINAL_FILENAME
VALUE "ProductName", PRODUCT_NAME
VALUE "ProductVersion", PRODUCT_VERSION_STRING
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200 // US English (0x0409), Unicode (1200) charset
END
END

View File

@@ -1,85 +0,0 @@
<?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.200729.8\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" />
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{47310AB4-9034-4BD1-8D8B-E88AD21A171B}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>powerpreviewTest</RootNamespace>
<ProjectSubType>NativeUnitTestProject</ProjectSubType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\FileExplorerPreview\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>..\;..\..\..\common;..\..\..\common\telemetry;..\..\;..\..\..\;..\..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="FileExplorerPreviewSettingsTest.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(CIBuild)'!='true'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\common\SettingsAPI\SetttingsAPI.vcxproj">
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="powerpreviewTest.rc" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\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.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets'))" />
</Target>
</Project>

View File

@@ -1,41 +0,0 @@
<?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;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;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>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FileExplorerPreviewSettingsTest.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="powerpreviewTest.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
</Project>

View File

@@ -1,13 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by powerpreviewTest.rc
//////////////////////////////
// Non-localizable
#define FILE_DESCRIPTION "PowerToys PowerPreview Test"
#define INTERNAL_NAME "powerpreviewTest"
#define ORIGINAL_FILENAME "powerpreviewTest.dll"
// Non-localizable
//////////////////////////////