mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Merge #6217
6217: Register application separately to specify its displayed name r=def- a=Robyt3 Follow-up from #6199. Adding version information to the executable (#6203) doesn't result in the name being shown in the Windows settings. There is a separate registry key where applications can register a readable name. See: https://learn.microsoft.com/en-us/windows/win32/shell/app-registration ## Checklist - [X] Tested the change ingame - [ ] Provided screenshots if it is a visual change - [ ] Tested in combination with possibly related configuration options - [ ] Written a unit test (especially base/) or added coverage to integration test - [ ] Considered possible null pointers and out of bounds array indexing - [ ] Changed no physics that affect existing maps - [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional) Co-authored-by: Robert Müller <robytemueller@gmail.com>
This commit is contained in:
commit
29bf49ae31
|
@ -4324,6 +4324,12 @@ static std::wstring utf8_to_wstring(const char *str)
|
|||
return wide_string;
|
||||
}
|
||||
|
||||
static std::wstring filename_from_path(const std::wstring &path)
|
||||
{
|
||||
const size_t pos = path.find_last_of(L"/\\");
|
||||
return pos == std::wstring::npos ? path : path.substr(pos + 1);
|
||||
}
|
||||
|
||||
bool shell_register_protocol(const char *protocol_name, const char *executable, bool *updated)
|
||||
{
|
||||
const std::wstring protocol_name_wide = utf8_to_wstring(protocol_name);
|
||||
|
@ -4416,6 +4422,10 @@ bool shell_register_protocol(const char *protocol_name, const char *executable,
|
|||
|
||||
*updated = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
RegCloseKey(handle_subkey_shell_open_command);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -4548,11 +4558,64 @@ bool shell_register_extension(const char *extension, const char *description, co
|
|||
|
||||
*updated = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
RegCloseKey(handle_subkey_extension);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool shell_unregister(const char *shell_class, bool *updated)
|
||||
bool shell_register_application(const char *name, const char *executable, bool *updated)
|
||||
{
|
||||
const std::wstring name_wide = utf8_to_wstring(name);
|
||||
const std::wstring executable_filename = filename_from_path(utf8_to_wstring(executable));
|
||||
|
||||
// Open registry key for application registrations
|
||||
HKEY handle_subkey_applications;
|
||||
const LRESULT result_subkey_applications = RegOpenKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Classes\\Applications", 0, KEY_ALL_ACCESS, &handle_subkey_applications);
|
||||
if(result_subkey_applications != ERROR_SUCCESS)
|
||||
{
|
||||
windows_print_error("shell_register_application", "Error opening registry key", result_subkey_applications);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the program key
|
||||
HKEY handle_subkey_program;
|
||||
const LRESULT result_subkey_program = RegCreateKeyExW(handle_subkey_applications, executable_filename.c_str(), 0, NULL, 0, KEY_ALL_ACCESS, NULL, &handle_subkey_program, NULL);
|
||||
RegCloseKey(handle_subkey_applications);
|
||||
if(result_subkey_program != ERROR_SUCCESS)
|
||||
{
|
||||
windows_print_error("shell_register_application", "Error creating registry key", result_subkey_program);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the previous default value for the key, so we can determine if it changed
|
||||
wchar_t old_value_executable[MAX_PATH];
|
||||
DWORD old_size_executable = sizeof(old_value_executable);
|
||||
const LRESULT result_old_value_executable = RegGetValueW(handle_subkey_program, NULL, L"FriendlyAppName", RRF_RT_REG_SZ, NULL, (BYTE *)old_value_executable, &old_size_executable);
|
||||
if(result_old_value_executable != ERROR_SUCCESS || wcscmp(old_value_executable, name_wide.c_str()) != 0)
|
||||
{
|
||||
// Set the "FriendlyAppName" value, which specifies the displayed name of the application
|
||||
const LRESULT result_program_name = RegSetValueExW(handle_subkey_program, L"FriendlyAppName", 0, REG_SZ, (BYTE *)name_wide.c_str(), (name_wide.length() + 1) * sizeof(wchar_t));
|
||||
RegCloseKey(handle_subkey_program);
|
||||
if(result_program_name != ERROR_SUCCESS)
|
||||
{
|
||||
windows_print_error("shell_register_application", "Error setting registry value", result_program_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
*updated = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
RegCloseKey(handle_subkey_program);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool shell_unregister_class(const char *shell_class, bool *updated)
|
||||
{
|
||||
const std::wstring class_wide = utf8_to_wstring(shell_class);
|
||||
|
||||
|
@ -4561,18 +4624,49 @@ bool shell_unregister(const char *shell_class, bool *updated)
|
|||
const LRESULT result_subkey_classes = RegOpenKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Classes", 0, KEY_ALL_ACCESS, &handle_subkey_classes);
|
||||
if(result_subkey_classes != ERROR_SUCCESS)
|
||||
{
|
||||
windows_print_error("shell_unregister", "Error opening registry key", result_subkey_classes);
|
||||
windows_print_error("shell_unregister_class", "Error opening registry key", result_subkey_classes);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Delete the registry keys for the shell class (protocol or program ID)
|
||||
LRESULT result_delete = RegDeleteTreeW(handle_subkey_classes, class_wide.c_str());
|
||||
RegCloseKey(handle_subkey_classes);
|
||||
if(result_delete != ERROR_SUCCESS && result_delete != ERROR_FILE_NOT_FOUND)
|
||||
if(result_delete == ERROR_SUCCESS)
|
||||
{
|
||||
windows_print_error("shell_unregister", "Error deleting registry key", result_delete);
|
||||
if(result_delete == ERROR_SUCCESS)
|
||||
*updated = true;
|
||||
*updated = true;
|
||||
}
|
||||
else if(result_delete != ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
windows_print_error("shell_unregister_class", "Error deleting registry key", result_delete);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool shell_unregister_application(const char *executable, bool *updated)
|
||||
{
|
||||
const std::wstring executable_filename = filename_from_path(utf8_to_wstring(executable));
|
||||
|
||||
// Open registry key for application registrations
|
||||
HKEY handle_subkey_applications;
|
||||
const LRESULT result_subkey_applications = RegOpenKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Classes\\Applications", 0, KEY_ALL_ACCESS, &handle_subkey_applications);
|
||||
if(result_subkey_applications != ERROR_SUCCESS)
|
||||
{
|
||||
windows_print_error("shell_unregister_application", "Error opening registry key", result_subkey_applications);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Delete the registry keys for the application description
|
||||
LRESULT result_delete = RegDeleteTreeW(handle_subkey_applications, executable_filename.c_str());
|
||||
RegCloseKey(handle_subkey_applications);
|
||||
if(result_delete == ERROR_SUCCESS)
|
||||
{
|
||||
*updated = true;
|
||||
}
|
||||
else if(result_delete != ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
windows_print_error("shell_unregister_application", "Error deleting registry key", result_delete);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -2614,6 +2614,21 @@ bool shell_register_protocol(const char *protocol_name, const char *executable,
|
|||
*/
|
||||
bool shell_register_extension(const char *extension, const char *description, const char *executable_name, const char *executable, bool *updated);
|
||||
|
||||
/**
|
||||
* Registers an application.
|
||||
*
|
||||
* @ingroup Shell
|
||||
*
|
||||
* @param name Readable name of the application.
|
||||
* @param executable The absolute path of the executable being registered.
|
||||
* @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.
|
||||
*
|
||||
* @remark The caller must later call shell_update, iff the shell needs to be updated.
|
||||
*/
|
||||
bool shell_register_application(const char *name, const char *executable, bool *updated);
|
||||
|
||||
/**
|
||||
* Unregisters a protocol or file extension handler.
|
||||
*
|
||||
|
@ -2628,7 +2643,21 @@ bool shell_register_extension(const char *extension, const char *description, co
|
|||
*
|
||||
* @remark The caller must later call shell_update, iff the shell needs to be updated.
|
||||
*/
|
||||
bool shell_unregister(const char *shell_class, bool *updated);
|
||||
bool shell_unregister_class(const char *shell_class, bool *updated);
|
||||
|
||||
/**
|
||||
* Unregisters an application.
|
||||
*
|
||||
* @ingroup Shell
|
||||
*
|
||||
* @param executable The absolute path of the executable being unregistered.
|
||||
* @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.
|
||||
*
|
||||
* @remark The caller must later call shell_update, iff the shell needs to be updated.
|
||||
*/
|
||||
bool shell_unregister_application(const char *executable, bool *updated);
|
||||
|
||||
/**
|
||||
* Notifies the system that a protocol or file extension has been changed and the shell needs to be updated.
|
||||
|
|
|
@ -4906,22 +4906,8 @@ int CClient::UdpConnectivity(int NetType)
|
|||
#if defined(CONF_FAMILY_WINDOWS)
|
||||
void CClient::ShellRegister()
|
||||
{
|
||||
char aBinaryPath[IO_MAX_PATH_LENGTH];
|
||||
Storage()->GetBinaryPath(PLAT_CLIENT_EXEC, aBinaryPath, sizeof(aBinaryPath));
|
||||
char aFullPath[IO_MAX_PATH_LENGTH];
|
||||
if(fs_is_relative_path(aBinaryPath))
|
||||
{
|
||||
if(fs_getcwd(aFullPath, sizeof(aFullPath)))
|
||||
{
|
||||
str_append(aFullPath, "/", sizeof(aFullPath));
|
||||
str_append(aFullPath, aBinaryPath, sizeof(aFullPath));
|
||||
}
|
||||
else
|
||||
aFullPath[0] = '\0';
|
||||
}
|
||||
else
|
||||
str_copy(aFullPath, aBinaryPath);
|
||||
|
||||
Storage()->GetBinaryPathAbsolute(PLAT_CLIENT_EXEC, aFullPath, sizeof(aFullPath));
|
||||
if(!aFullPath[0])
|
||||
{
|
||||
dbg_msg("client", "Failed to register protocol and file extensions: could not determine absolute path");
|
||||
|
@ -4935,19 +4921,31 @@ void CClient::ShellRegister()
|
|||
dbg_msg("client", "Failed to register .map file extension");
|
||||
if(!shell_register_extension(".demo", "Demo File", GAME_NAME, aFullPath, &Updated))
|
||||
dbg_msg("client", "Failed to register .demo file extension");
|
||||
if(!shell_register_application(GAME_NAME, aFullPath, &Updated))
|
||||
dbg_msg("client", "Failed to register application");
|
||||
if(Updated)
|
||||
shell_update();
|
||||
}
|
||||
|
||||
void CClient::ShellUnregister()
|
||||
{
|
||||
char aFullPath[IO_MAX_PATH_LENGTH];
|
||||
Storage()->GetBinaryPathAbsolute(PLAT_CLIENT_EXEC, aFullPath, sizeof(aFullPath));
|
||||
if(!aFullPath[0])
|
||||
{
|
||||
dbg_msg("client", "Failed to unregister protocol and file extensions: could not determine absolute path");
|
||||
return;
|
||||
}
|
||||
|
||||
bool Updated = false;
|
||||
if(!shell_unregister("ddnet", &Updated))
|
||||
if(!shell_unregister_class("ddnet", &Updated))
|
||||
dbg_msg("client", "Failed to unregister ddnet protocol");
|
||||
if(!shell_unregister(GAME_NAME ".map", &Updated))
|
||||
if(!shell_unregister_class(GAME_NAME ".map", &Updated))
|
||||
dbg_msg("client", "Failed to unregister .map file extension");
|
||||
if(!shell_unregister(GAME_NAME ".demo", &Updated))
|
||||
if(!shell_unregister_class(GAME_NAME ".demo", &Updated))
|
||||
dbg_msg("client", "Failed to unregister .demo file extension");
|
||||
if(!shell_unregister_application(aFullPath, &Updated))
|
||||
dbg_msg("client", "Failed to unregister application");
|
||||
if(Updated)
|
||||
shell_update();
|
||||
}
|
||||
|
|
|
@ -677,6 +677,25 @@ public:
|
|||
return pBuffer;
|
||||
}
|
||||
|
||||
const char *GetBinaryPathAbsolute(const char *pFilename, char *pBuffer, unsigned BufferSize) override
|
||||
{
|
||||
char aBinaryPath[IO_MAX_PATH_LENGTH];
|
||||
GetBinaryPath(PLAT_CLIENT_EXEC, aBinaryPath, sizeof(aBinaryPath));
|
||||
if(fs_is_relative_path(aBinaryPath))
|
||||
{
|
||||
if(fs_getcwd(pBuffer, BufferSize))
|
||||
{
|
||||
str_append(pBuffer, "/", BufferSize);
|
||||
str_append(pBuffer, aBinaryPath, BufferSize);
|
||||
}
|
||||
else
|
||||
pBuffer[0] = '\0';
|
||||
}
|
||||
else
|
||||
str_copy(pBuffer, aBinaryPath, BufferSize);
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
static IStorage *Create(int StorageType, int NumArgs, const char **ppArguments)
|
||||
{
|
||||
CStorage *pStorage = new CStorage();
|
||||
|
|
|
@ -57,6 +57,7 @@ public:
|
|||
virtual bool RemoveBinaryFile(const char *pFilename) = 0;
|
||||
virtual bool RenameBinaryFile(const char *pOldFilename, const char *pNewFilename) = 0;
|
||||
virtual const char *GetBinaryPath(const char *pFilename, char *pBuffer, unsigned BufferSize) = 0;
|
||||
virtual const char *GetBinaryPathAbsolute(const char *pFilename, char *pBuffer, unsigned BufferSize) = 0;
|
||||
|
||||
static void StripPathAndExtension(const char *pFilename, char *pBuffer, int BufferSize);
|
||||
static const char *FormatTmpPath(char *aBuf, unsigned BufSize, const char *pPath);
|
||||
|
|
Loading…
Reference in a new issue