From 7167c8c77165211dd352549735a903318c78fde9 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 8 May 2021 17:20:50 +0100 Subject: [PATCH] Move some parts of window.c into putty.c. This prepares the ground for a second essentially similarly-shaped program reusing most of window.c but handling its command line and startup differently. A couple of large parts of WinMain() to do with backend selection and command-line handling are now subfunctions in a separate file putty.c. Also, our custom AppUserModelId is defined in that file, so that it can vary with the client application. --- windows/CMakeLists.txt | 2 + windows/jump-list.c | 3 +- windows/platform.h | 9 ++ windows/putty.c | 127 +++++++++++++++++++++ windows/window.c | 246 ++++++++++++++--------------------------- 5 files changed, 224 insertions(+), 163 deletions(-) create mode 100644 windows/putty.c diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index fb2b3028..6165df27 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -82,6 +82,7 @@ add_sources_from_current_dir(psocks nohelp.c) add_executable(putty window.c + putty.c help.c ${CMAKE_SOURCE_DIR}/be_all_s.c putty.rc) @@ -97,6 +98,7 @@ installed_program(putty) add_executable(puttytel window.c + putty.c help.c ${CMAKE_SOURCE_DIR}/be_nos_s.c ${CMAKE_SOURCE_DIR}/nogss.c diff --git a/windows/jump-list.c b/windows/jump-list.c index 358504fd..0aacee8f 100644 --- a/windows/jump-list.c +++ b/windows/jump-list.c @@ -735,7 +735,8 @@ bool set_explicit_app_user_model_id(void) if (p_SetCurrentProcessExplicitAppUserModelID) { - if (p_SetCurrentProcessExplicitAppUserModelID(L"SimonTatham.PuTTY") == S_OK) + const wchar_t *id = get_app_user_model_id(); + if (p_SetCurrentProcessExplicitAppUserModelID(id) == S_OK) { return true; } diff --git a/windows/platform.h b/windows/platform.h index 5c307cb0..b746c76d 100644 --- a/windows/platform.h +++ b/windows/platform.h @@ -705,4 +705,13 @@ void cli_main_loop(cliloop_pre_t pre, cliloop_post_t post, void *ctx); bool cliloop_null_pre(void *vctx, const HANDLE **, size_t *); bool cliloop_null_post(void *vctx, size_t); +/* Functions that parametrise window.c */ +void gui_term_process_cmdline(Conf *conf, char *cmdline); +const struct BackendVtable *backend_vt_from_conf(Conf *conf); +const wchar_t *get_app_user_model_id(void); +/* And functions in window.c that those files call back to */ +char *handle_restrict_acl_cmdline_prefix(char *cmdline); +bool handle_special_sessionname_cmdline(char *cmdline, Conf *conf); +bool handle_special_filemapping_cmdline(char *cmdline, Conf *conf); + #endif /* PUTTY_WINDOWS_PLATFORM_H */ diff --git a/windows/putty.c b/windows/putty.c new file mode 100644 index 00000000..b17ad7dc --- /dev/null +++ b/windows/putty.c @@ -0,0 +1,127 @@ +#include "putty.h" +#include "storage.h" + +void gui_term_process_cmdline(Conf *conf, char *cmdline) +{ + char *p; + bool special_launchable_argument = false; + + settings_set_default_protocol(be_default_protocol); + /* Find the appropriate default port. */ + { + const struct BackendVtable *vt = + backend_vt_from_proto(be_default_protocol); + settings_set_default_port(0); /* illegal */ + if (vt) + settings_set_default_port(vt->default_port); + } + conf_set_int(conf, CONF_logtype, LGTYP_NONE); + + do_defaults(NULL, conf); + + p = handle_restrict_acl_cmdline_prefix(cmdline); + + if (handle_special_sessionname_cmdline(p, conf)) { + if (!conf_launchable(conf) && !do_config(conf)) { + cleanup_exit(0); + } + special_launchable_argument = true; + } else if (handle_special_filemapping_cmdline(p, conf)) { + special_launchable_argument = true; + } else if (!*p) { + /* Do-nothing case for an empty command line - or rather, + * for a command line that's empty _after_ we strip off + * the &R prefix. */ + } else { + /* + * Otherwise, break up the command line and deal with + * it sensibly. + */ + int argc, i; + char **argv; + + split_into_argv(cmdline, &argc, &argv, NULL); + + for (i = 0; i < argc; i++) { + char *p = argv[i]; + int ret; + + ret = cmdline_process_param(p, i+1default_port); - } - conf_set_int(conf, CONF_logtype, LGTYP_NONE); - - do_defaults(NULL, conf); - - p = cmdline; - - /* - * Process a couple of command-line options which are more - * easily dealt with before the line is broken up into words. - * These are the old-fashioned but convenient @sessionname and - * the internal-use-only &sharedmemoryhandle, plus the &R - * prefix for -restrict-acl, all of which are used by PuTTYs - * auto-launching each other via System-menu options. - */ - while (*p && isspace(*p)) - p++; - if (*p == '&' && p[1] == 'R' && - (!p[2] || p[2] == '@' || p[2] == '&')) { - /* &R restrict-acl prefix */ - restrict_process_acl(); - p += 2; - } - - if (*p == '@') { - /* - * An initial @ means that the whole of the rest of the - * command line should be treated as the name of a saved - * session, with _no quoting or escaping_. This makes it a - * very convenient means of automated saved-session - * launching, via IDM_SAVEDSESS or Windows 7 jump lists. - */ - int i = strlen(p); - while (i > 1 && isspace(p[i - 1])) - i--; - p[i] = '\0'; - do_defaults(p + 1, conf); - if (!conf_launchable(conf) && !do_config(conf)) { - cleanup_exit(0); - } - special_launchable_argument = true; - } else if (*p == '&') { - /* - * An initial & means we've been given a command line - * containing the hex value of a HANDLE for a file - * mapping object, which we must then interpret as a - * serialised Conf. - */ - HANDLE filemap; - void *cp; - unsigned cpsize; - if (sscanf(p + 1, "%p:%u", &filemap, &cpsize) == 2 && - (cp = MapViewOfFile(filemap, FILE_MAP_READ, - 0, 0, cpsize)) != NULL) { - BinarySource src[1]; - BinarySource_BARE_INIT(src, cp, cpsize); - if (!conf_deserialise(conf, src)) - modalfatalbox("Serialised configuration data was invalid"); - UnmapViewOfFile(cp); - CloseHandle(filemap); - } else if (!do_config(conf)) { - cleanup_exit(0); - } - special_launchable_argument = true; - } else if (!*p) { - /* Do-nothing case for an empty command line - or rather, - * for a command line that's empty _after_ we strip off - * the &R prefix. */ - } else { - /* - * Otherwise, break up the command line and deal with - * it sensibly. - */ - int argc, i; - char **argv; - - split_into_argv(cmdline, &argc, &argv, NULL); - - for (i = 0; i < argc; i++) { - char *p = argv[i]; - int ret; - - ret = cmdline_process_param(p, i+1 0 && + isspace(((unsigned char *)sessionname.ptr)[sessionname.len-1])) + sessionname.len--; + + char *dup = mkstr(sessionname); + bool loaded = do_defaults(dup, conf); + sfree(dup); + + return loaded; +} + +bool handle_special_filemapping_cmdline(char *p, Conf *conf) +{ + /* + * Process the special form of command line with an initial & + * followed by the hex value of a HANDLE for a file mapping object + * and the size of the data contained in it, which we must + * interpret as a serialised Conf. + * + * If successful, the whole command line has been interpreted in + * this way, so there's nothing left to parse into other arguments. + */ + + if (*p != '&') + return false; + + HANDLE filemap; + unsigned cpsize; + if (sscanf(p + 1, "%p:%u", &filemap, &cpsize) != 2) + return false; + + void *cp = MapViewOfFile(filemap, FILE_MAP_READ, 0, 0, cpsize); + if (!cp) + return false; + + BinarySource src[1]; + BinarySource_BARE_INIT(src, cp, cpsize); + if (!conf_deserialise(conf, src)) + modalfatalbox("Serialised configuration data was invalid"); + UnmapViewOfFile(cp); + CloseHandle(filemap); + return true; +} + static void setup_clipboards(Terminal *term, Conf *conf) { assert(term->mouse_select_clipboards[0] == CLIP_LOCAL);