2020-03-11 15:53:49 -07:00
# include "pch.h"
2020-12-15 15:16:09 +03:00
# include <common/SettingsAPI/settings_objects.h>
2020-03-11 15:53:49 -07:00
# include "powerpreview.h"
# include "trace.h"
# include "settings.h"
2020-08-24 15:10:50 -07:00
# include "Generated Files/resource.h"
2020-12-15 15:16:09 +03:00
# include <common/notifications/dont_show_again.h>
# include <common/notifications/notifications.h>
# include <common/utils/elevation.h>
# include <common/utils/resources.h>
# include <common/utils/os-detect.h>
2020-10-09 14:45:30 -07:00
// Constructor
PowerPreviewModule : : PowerPreviewModule ( ) :
m_moduleName ( GET_RESOURCE_STRING ( IDS_MODULE_NAME ) ) ,
2020-10-20 15:01:45 +03:00
app_key ( powerpreviewConstants : : ModuleKey )
2020-03-11 15:53:49 -07:00
{
2021-08-04 13:42:19 +01:00
// Initialize the preview modules.
2020-10-20 15:01:45 +03:00
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 > ( ) ) ) ;
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 > ( ) ) ) ;
2021-08-26 23:43:26 +02:00
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 > ( ) ) ) ;
2020-10-20 15:01:45 +03:00
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} " ) ) ;
2021-08-04 13:42:19 +01:00
// Initialize the toggle states for each module.
init_settings ( ) ;
2021-04-21 03:16:01 -07:00
// 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 ( ) ;
2020-10-09 14:45:30 -07:00
}
2020-07-21 16:27:12 -07:00
2020-10-09 14:45:30 -07:00
// Destroy the powertoy and free memory.
void PowerPreviewModule : : destroy ( )
{
Trace : : Destroyed ( ) ;
2020-03-11 15:53:49 -07:00
delete this ;
}
2020-10-19 16:07:02 -07:00
// Return the localized display name of the powertoy
2020-03-11 15:53:49 -07:00
const wchar_t * PowerPreviewModule : : get_name ( )
{
return m_moduleName . c_str ( ) ;
}
2020-10-19 16:07:02 -07:00
// Return the non localized key of the powertoy, this will be cached by the runner
const wchar_t * PowerPreviewModule : : get_key ( )
{
return app_key . c_str ( ) ;
}
2020-03-11 15:53:49 -07:00
// Return JSON with the configuration options.
bool PowerPreviewModule : : get_config ( _Out_ wchar_t * buffer , _Out_ int * buffer_size )
{
HINSTANCE hinstance = reinterpret_cast < HINSTANCE > ( & __ImageBase ) ;
// Create a Settings object.
PowerToysSettings : : Settings settings ( hinstance , get_name ( ) ) ;
// General Settings.
settings . set_description ( GET_RESOURCE_STRING ( IDS_GENERAL_DESCRIPTION ) ) ;
settings . set_icon_key ( GET_RESOURCE_STRING ( IDS_ICON_KEY_NAME ) ) ;
2020-06-11 10:16:39 -07:00
settings . set_overview_link ( L " https://aka.ms/PowerToysOverview_FileExplorerAddOns " ) ;
2020-03-11 15:53:49 -07:00
// Preview Pane: Settings Group Header.
settings . add_header_szLarge (
GET_RESOURCE_STRING ( IDS_PRVPANE_FILE_PREV_STTNGS_GROUP_HEADER_ID ) ,
GET_RESOURCE_STRING ( IDS_PRVPANE_FILE_PREV_STTNGS_GROUP_DESC ) ,
GET_RESOURCE_STRING ( IDS_PRVPANE_FILE_PREV_STTNGS_GROUP_TEXT ) ) ;
2020-10-20 15:01:45 +03:00
for ( auto & fileExplorerModule : m_fileExplorerModules )
2020-07-21 16:27:12 -07:00
{
settings . add_bool_toggle (
2020-10-09 14:45:30 -07:00
fileExplorerModule - > GetToggleSettingName ( ) ,
fileExplorerModule - > GetToggleSettingDescription ( ) ,
fileExplorerModule - > GetToggleSettingState ( ) ) ;
2020-07-21 16:27:12 -07:00
}
2020-03-11 15:53:49 -07:00
return settings . serialize_to_buffer ( buffer , buffer_size ) ;
}
// Called by the runner to pass the updated settings values as a serialized JSON.
void PowerPreviewModule : : set_config ( const wchar_t * config )
{
try
{
2020-10-19 16:07:02 -07:00
PowerToysSettings : : PowerToyValues settings = PowerToysSettings : : PowerToyValues : : from_json_string ( config , get_key ( ) ) ;
2020-03-11 15:53:49 -07:00
2020-10-09 14:45:30 -07:00
bool updateSuccess = true ;
bool isElevated = is_process_elevated ( false ) ;
2020-10-20 15:01:45 +03:00
for ( auto & fileExplorerModule : m_fileExplorerModules )
2020-03-11 15:53:49 -07:00
{
2021-04-21 03:16:01 -07:00
// 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 ) ;
2020-03-11 15:53:49 -07:00
}
2020-10-09 14:45:30 -07:00
if ( ! updateSuccess )
2020-07-21 16:27:12 -07:00
{
2020-10-09 14:45:30 -07:00
show_update_warning_message ( ) ;
2020-07-21 16:27:12 -07:00
}
2020-03-24 16:23:27 -07:00
settings . save_to_settings_file ( ) ;
2020-03-11 15:53:49 -07:00
}
catch ( std : : exception const & e )
{
Trace : : SetConfigInvalidJSON ( e . what ( ) ) ;
}
}
// Enable preview handlers.
void PowerPreviewModule : : enable ( )
{
2020-03-24 16:23:27 -07:00
if ( ! this - > m_enabled )
{
Trace : : EnabledPowerPreview ( true ) ;
}
2020-03-11 15:53:49 -07:00
this - > m_enabled = true ;
}
2020-03-24 16:23:27 -07:00
// Disable active preview handlers.
2020-03-11 15:53:49 -07:00
void PowerPreviewModule : : disable ( )
{
2020-10-09 14:45:30 -07:00
elevation_check_wrapper ( [ this ] ( ) {
2020-10-20 15:01:45 +03:00
for ( auto & fileExplorerModule : m_fileExplorerModules )
2020-10-09 14:45:30 -07:00
{
fileExplorerModule - > Disable ( ) ;
}
} ) ;
2020-07-21 16:27:12 -07:00
2020-03-24 16:23:27 -07:00
if ( this - > m_enabled )
{
Trace : : EnabledPowerPreview ( false ) ;
}
2020-03-11 15:53:49 -07:00
this - > 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 =
2020-10-19 16:07:02 -07:00
PowerToysSettings : : PowerToyValues : : load_from_settings_file ( PowerPreviewModule : : get_key ( ) ) ;
2020-03-11 15:53:49 -07:00
// Load settings states.
2020-10-20 15:01:45 +03:00
for ( auto & fileExplorerModule : m_fileExplorerModules )
2020-03-11 15:53:49 -07:00
{
2020-10-09 14:45:30 -07:00
fileExplorerModule - > LoadState ( settings ) ;
2020-03-11 15:53:49 -07:00
}
2020-10-09 14:45:30 -07:00
}
catch ( std : : exception const & e )
{
Trace : : InitSetErrorLoadingFile ( e . what ( ) ) ;
}
}
2020-07-21 16:27:12 -07:00
2020-10-09 14:45:30 -07:00
// Function to check if the registry states need to be updated
bool PowerPreviewModule : : is_registry_update_required ( )
{
2020-10-20 15:01:45 +03:00
for ( auto & fileExplorerModule : m_fileExplorerModules )
2020-10-09 14:45:30 -07:00
{
if ( fileExplorerModule - > GetToggleSettingState ( ) ! = fileExplorerModule - > CheckRegistryState ( ) )
2020-07-21 16:27:12 -07:00
{
2020-10-09 14:45:30 -07:00
return true ;
2020-07-21 16:27:12 -07:00
}
2020-03-11 15:53:49 -07:00
}
2020-10-09 14:45:30 -07:00
return false ;
}
// Function to warn the user that PowerToys needs to run as administrator for changes to take effect
void PowerPreviewModule : : show_update_warning_message ( )
{
2020-10-20 01:27:24 +03:00
using namespace notifications ;
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 ) ) ;
}
2020-10-09 14:45:30 -07:00
}
// 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 )
{
// Check if a registry update is required
if ( is_registry_update_required ( ) )
2020-03-11 15:53:49 -07:00
{
2020-10-09 14:45:30 -07:00
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 ( ) ;
2020-03-11 15:53:49 -07:00
}
2020-10-09 14:45:30 -07:00
// Show a warning if it doesn't have permissions
else
{
show_update_warning_message ( ) ;
}
}
// Function that updates the registry state to match the toggle states
void PowerPreviewModule : : update_registry_to_match_toggles ( )
{
registry_and_elevation_check_wrapper ( [ this ] ( ) {
2020-10-20 15:01:45 +03:00
for ( auto & fileExplorerModule : m_fileExplorerModules )
2020-10-09 14:45:30 -07:00
{
if ( fileExplorerModule - > GetToggleSettingState ( ) )
{
// Enable all the modules with initial state set as true.
fileExplorerModule - > Enable ( ) ;
}
else
{
fileExplorerModule - > Disable ( ) ;
}
}
} ) ;
}