mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 18:18:18 +00:00
Add shell_update
to notify system to update shell
The `shell_update` function notifies the system when the shell needs to be updated due to a changed protocol or file association. An output parameter is added to the `shell_register_protocol` and `shell_register_extension` functions, to determine whether the shell needs to be updated after calling the functions. We only check whether the application path and program association were changed, instead of checking whether any key or value was changed, as this reduces the amount of necessary checks and we assume that the other values are not externally changed. Because updating the shell is a potentially expensive operation, this should only be done when necessary and only once after registering all protocols and extensions.
This commit is contained in:
parent
4e130a29e4
commit
8a3a8974d0
|
@ -58,7 +58,9 @@
|
||||||
#elif defined(CONF_FAMILY_WINDOWS)
|
#elif defined(CONF_FAMILY_WINDOWS)
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#undef _WIN32_WINNT
|
#undef _WIN32_WINNT
|
||||||
#define _WIN32_WINNT 0x0501 /* required for mingw to get getaddrinfo to work */
|
// 0x0501 (Windows XP) is required for mingw to get getaddrinfo to work
|
||||||
|
// 0x0600 (Windows Vista) is required to use RegGetValueW
|
||||||
|
#define _WIN32_WINNT 0x0600
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
|
@ -70,6 +72,7 @@
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
#include <share.h>
|
#include <share.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
#include <shlobj.h> // SHChangeNotify
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
#include <wincrypt.h>
|
#include <wincrypt.h>
|
||||||
#else
|
#else
|
||||||
|
@ -4321,7 +4324,7 @@ static std::wstring utf8_to_wstring(const char *str)
|
||||||
return wide_string;
|
return wide_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shell_register_protocol(const char *protocol_name, const char *executable)
|
bool shell_register_protocol(const char *protocol_name, const char *executable, bool *updated)
|
||||||
{
|
{
|
||||||
const std::wstring protocol_name_wide = utf8_to_wstring(protocol_name);
|
const std::wstring protocol_name_wide = utf8_to_wstring(protocol_name);
|
||||||
const std::wstring executable_wide = utf8_to_wstring(executable);
|
const std::wstring executable_wide = utf8_to_wstring(executable);
|
||||||
|
@ -4395,20 +4398,29 @@ bool shell_register_protocol(const char *protocol_name, const char *executable)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the default value for the key, which specifies the executable command associated with the protocol
|
// Get the previous default value for the key, so we can determine if it changed
|
||||||
|
wchar_t old_value_executable[MAX_PATH + 16];
|
||||||
|
DWORD old_size_executable = sizeof(old_value_executable);
|
||||||
|
const LRESULT result_old_value_executable = RegGetValueW(handle_subkey_shell_open_command, NULL, L"", RRF_RT_REG_SZ, NULL, (BYTE *)old_value_executable, &old_size_executable);
|
||||||
const std::wstring value_executable = L"\"" + executable_wide + L"\" \"%1\"";
|
const std::wstring value_executable = L"\"" + executable_wide + L"\" \"%1\"";
|
||||||
const LRESULT result_value_executable = RegSetValueExW(handle_subkey_shell_open_command, L"", 0, REG_SZ, (BYTE *)value_executable.c_str(), (value_executable.length() + 1) * sizeof(wchar_t));
|
if(result_old_value_executable != ERROR_SUCCESS || wcscmp(old_value_executable, value_executable.c_str()) != 0)
|
||||||
RegCloseKey(handle_subkey_shell_open_command);
|
|
||||||
if(result_value_executable != ERROR_SUCCESS)
|
|
||||||
{
|
{
|
||||||
windows_print_error("shell_register_protocol", "Error setting registry value", result_value_executable);
|
// Set the default value for the key, which specifies the executable command associated with the protocol
|
||||||
return false;
|
const LRESULT result_value_executable = RegSetValueExW(handle_subkey_shell_open_command, L"", 0, REG_SZ, (BYTE *)value_executable.c_str(), (value_executable.length() + 1) * sizeof(wchar_t));
|
||||||
|
RegCloseKey(handle_subkey_shell_open_command);
|
||||||
|
if(result_value_executable != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
windows_print_error("shell_register_protocol", "Error setting registry value", result_value_executable);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shell_register_extension(const char *extension, const char *description, const char *executable_name, const char *executable)
|
bool shell_register_extension(const char *extension, const char *description, const char *executable_name, const char *executable, bool *updated)
|
||||||
{
|
{
|
||||||
const std::wstring extension_wide = utf8_to_wstring(extension);
|
const std::wstring extension_wide = utf8_to_wstring(extension);
|
||||||
const std::wstring executable_name_wide = utf8_to_wstring(executable_name);
|
const std::wstring executable_name_wide = utf8_to_wstring(executable_name);
|
||||||
|
@ -4489,15 +4501,24 @@ bool shell_register_extension(const char *extension, const char *description, co
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the default value for the key, which specifies the executable command associated with the application
|
// Get the previous default value for the key, so we can determine if it changed
|
||||||
|
wchar_t old_value_executable[MAX_PATH + 16];
|
||||||
|
DWORD old_size_executable = sizeof(old_value_executable);
|
||||||
|
const LRESULT result_old_value_executable = RegGetValueW(handle_subkey_shell_open_command, NULL, L"", RRF_RT_REG_SZ, NULL, (BYTE *)old_value_executable, &old_size_executable);
|
||||||
const std::wstring value_executable = L"\"" + executable_wide + L"\" \"%1\"";
|
const std::wstring value_executable = L"\"" + executable_wide + L"\" \"%1\"";
|
||||||
const LRESULT result_value_executable = RegSetValueExW(handle_subkey_shell_open_command, L"", 0, REG_SZ, (BYTE *)value_executable.c_str(), (value_executable.length() + 1) * sizeof(wchar_t));
|
if(result_old_value_executable != ERROR_SUCCESS || wcscmp(old_value_executable, value_executable.c_str()) != 0)
|
||||||
RegCloseKey(handle_subkey_shell_open_command);
|
|
||||||
if(result_value_executable != ERROR_SUCCESS)
|
|
||||||
{
|
{
|
||||||
windows_print_error("shell_register_extension", "Error setting registry value", result_value_executable);
|
// Set the default value for the key, which specifies the executable command associated with the application
|
||||||
RegCloseKey(handle_subkey_classes);
|
const LRESULT result_value_executable = RegSetValueExW(handle_subkey_shell_open_command, L"", 0, REG_SZ, (BYTE *)value_executable.c_str(), (value_executable.length() + 1) * sizeof(wchar_t));
|
||||||
return false;
|
RegCloseKey(handle_subkey_shell_open_command);
|
||||||
|
if(result_value_executable != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
windows_print_error("shell_register_extension", "Error setting registry value", result_value_executable);
|
||||||
|
RegCloseKey(handle_subkey_classes);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the file extension key
|
// Create the file extension key
|
||||||
|
@ -4510,17 +4531,31 @@ bool shell_register_extension(const char *extension, const char *description, co
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the default value for the key, which associates the file extension with the program ID
|
// Get the previous default value for the key, so we can determine if it changed
|
||||||
const LRESULT result_value_application = RegSetValueExW(handle_subkey_extension, L"", 0, REG_SZ, (BYTE *)program_id_wide.c_str(), (program_id_wide.length() + 1) * sizeof(wchar_t));
|
wchar_t old_value_application[128];
|
||||||
RegCloseKey(handle_subkey_extension);
|
DWORD old_size_application = sizeof(old_value_application);
|
||||||
if(result_value_application != ERROR_SUCCESS)
|
const LRESULT result_old_value_application = RegGetValueW(handle_subkey_extension, NULL, L"", RRF_RT_REG_SZ, NULL, (BYTE *)old_value_application, &old_size_application);
|
||||||
|
if(result_old_value_application != ERROR_SUCCESS || wcscmp(old_value_application, program_id_wide.c_str()) != 0)
|
||||||
{
|
{
|
||||||
windows_print_error("shell_register_extension", "Error setting registry value", result_value_application);
|
// Set the default value for the key, which associates the file extension with the program ID
|
||||||
return false;
|
const LRESULT result_value_application = RegSetValueExW(handle_subkey_extension, L"", 0, REG_SZ, (BYTE *)program_id_wide.c_str(), (program_id_wide.length() + 1) * sizeof(wchar_t));
|
||||||
|
RegCloseKey(handle_subkey_extension);
|
||||||
|
if(result_value_application != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
windows_print_error("shell_register_extension", "Error setting registry value", result_value_application);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void shell_update()
|
||||||
|
{
|
||||||
|
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_t std::hash<NETADDR>::operator()(const NETADDR &Addr) const noexcept
|
size_t std::hash<NETADDR>::operator()(const NETADDR &Addr) const noexcept
|
||||||
|
|
|
@ -2578,10 +2578,13 @@ public:
|
||||||
*
|
*
|
||||||
* @param protocol_name The name of the protocol.
|
* @param protocol_name The name of the protocol.
|
||||||
* @param executable The absolute path of the executable that will be associated with the protocol.
|
* @param executable The absolute path of the executable that will be associated with the protocol.
|
||||||
|
* @param updated Pointer to a variable that will be set to true, iff the shell needs to be updated.
|
||||||
*
|
*
|
||||||
* @return true on success, false on failure.
|
* @return true on success, false on failure.
|
||||||
|
*
|
||||||
|
* @remark The caller must later call shell_update, iff the shell needs to be updated.
|
||||||
*/
|
*/
|
||||||
bool shell_register_protocol(const char *protocol_name, const char *executable);
|
bool shell_register_protocol(const char *protocol_name, const char *executable, bool *updated);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a file extension.
|
* Registers a file extension.
|
||||||
|
@ -2592,10 +2595,22 @@ bool shell_register_protocol(const char *protocol_name, const char *executable);
|
||||||
* @param description A readable description for the file extension.
|
* @param description A readable description for the file extension.
|
||||||
* @param executable_name A unique name that will used to describe the application.
|
* @param executable_name A unique name that will used to describe the application.
|
||||||
* @param executable The absolute path of the executable that will be associated with the file extension.
|
* @param executable The absolute path of the executable that will be associated with the file extension.
|
||||||
|
* @param updated Pointer to a variable that will be set to true, iff the shell needs to be updated.
|
||||||
*
|
*
|
||||||
* @return true on success, false on failure.
|
* @return true on success, false on failure.
|
||||||
|
*
|
||||||
|
* @remark The caller must later call shell_update, iff the shell needs to be updated.
|
||||||
*/
|
*/
|
||||||
bool shell_register_extension(const char *extension, const char *description, const char *executable_name, const char *executable);
|
bool shell_register_extension(const char *extension, const char *description, const char *executable_name, const char *executable, bool *updated);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the system that a protocol or file extension has been changed and the shell needs to be updated.
|
||||||
|
*
|
||||||
|
* @ingroup Shell
|
||||||
|
*
|
||||||
|
* @remark This is a potentially expensive operation, so it should only be called when necessary.
|
||||||
|
*/
|
||||||
|
void shell_update();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue