mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
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.
This commit is contained in:
parent
3de2f13b89
commit
7167c8c771
@ -82,6 +82,7 @@ add_sources_from_current_dir(psocks nohelp.c)
|
|||||||
|
|
||||||
add_executable(putty
|
add_executable(putty
|
||||||
window.c
|
window.c
|
||||||
|
putty.c
|
||||||
help.c
|
help.c
|
||||||
${CMAKE_SOURCE_DIR}/be_all_s.c
|
${CMAKE_SOURCE_DIR}/be_all_s.c
|
||||||
putty.rc)
|
putty.rc)
|
||||||
@ -97,6 +98,7 @@ installed_program(putty)
|
|||||||
|
|
||||||
add_executable(puttytel
|
add_executable(puttytel
|
||||||
window.c
|
window.c
|
||||||
|
putty.c
|
||||||
help.c
|
help.c
|
||||||
${CMAKE_SOURCE_DIR}/be_nos_s.c
|
${CMAKE_SOURCE_DIR}/be_nos_s.c
|
||||||
${CMAKE_SOURCE_DIR}/nogss.c
|
${CMAKE_SOURCE_DIR}/nogss.c
|
||||||
|
@ -735,7 +735,8 @@ bool set_explicit_app_user_model_id(void)
|
|||||||
|
|
||||||
if (p_SetCurrentProcessExplicitAppUserModelID)
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -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_pre(void *vctx, const HANDLE **, size_t *);
|
||||||
bool cliloop_null_post(void *vctx, 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 */
|
#endif /* PUTTY_WINDOWS_PLATFORM_H */
|
||||||
|
127
windows/putty.c
Normal file
127
windows/putty.c
Normal file
@ -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+1<argc?argv[i+1]:NULL,
|
||||||
|
1, conf);
|
||||||
|
if (ret == -2) {
|
||||||
|
cmdline_error("option \"%s\" requires an argument", p);
|
||||||
|
} else if (ret == 2) {
|
||||||
|
i++; /* skip next argument */
|
||||||
|
} else if (ret == 1) {
|
||||||
|
continue; /* nothing further needs doing */
|
||||||
|
} else if (!strcmp(p, "-cleanup")) {
|
||||||
|
/*
|
||||||
|
* `putty -cleanup'. Remove all registry
|
||||||
|
* entries associated with PuTTY, and also find
|
||||||
|
* and delete the random seed file.
|
||||||
|
*/
|
||||||
|
char *s1, *s2;
|
||||||
|
s1 = dupprintf("This procedure will remove ALL Registry entries\n"
|
||||||
|
"associated with %s, and will also remove\n"
|
||||||
|
"the random seed file. (This only affects the\n"
|
||||||
|
"currently logged-in user.)\n"
|
||||||
|
"\n"
|
||||||
|
"THIS PROCESS WILL DESTROY YOUR SAVED SESSIONS.\n"
|
||||||
|
"Are you really sure you want to continue?",
|
||||||
|
appname);
|
||||||
|
s2 = dupprintf("%s Warning", appname);
|
||||||
|
if (message_box(NULL, s1, s2,
|
||||||
|
MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2,
|
||||||
|
HELPCTXID(option_cleanup)) == IDYES) {
|
||||||
|
cleanup_all();
|
||||||
|
}
|
||||||
|
sfree(s1);
|
||||||
|
sfree(s2);
|
||||||
|
exit(0);
|
||||||
|
} else if (!strcmp(p, "-pgpfp")) {
|
||||||
|
pgp_fingerprints_msgbox(NULL);
|
||||||
|
exit(1);
|
||||||
|
} else if (*p != '-') {
|
||||||
|
cmdline_error("unexpected argument \"%s\"", p);
|
||||||
|
} else {
|
||||||
|
cmdline_error("unknown option \"%s\"", p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdline_run_saved(conf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bring up the config dialog if the command line hasn't
|
||||||
|
* (explicitly) specified a launchable configuration.
|
||||||
|
*/
|
||||||
|
if (!(special_launchable_argument || cmdline_host_ok(conf))) {
|
||||||
|
if (!do_config(conf))
|
||||||
|
cleanup_exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare_session(conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct BackendVtable *backend_vt_from_conf(Conf *conf)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Select protocol. This is farmed out into a table in a
|
||||||
|
* separate file to enable an ssh-free variant.
|
||||||
|
*/
|
||||||
|
const struct BackendVtable *vt = backend_vt_from_proto(
|
||||||
|
conf_get_int(conf, CONF_protocol));
|
||||||
|
if (!vt) {
|
||||||
|
char *str = dupprintf("%s Internal Error", appname);
|
||||||
|
MessageBox(NULL, "Unsupported protocol number found",
|
||||||
|
str, MB_OK | MB_ICONEXCLAMATION);
|
||||||
|
sfree(str);
|
||||||
|
cleanup_exit(1);
|
||||||
|
}
|
||||||
|
return vt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const wchar_t *get_app_user_model_id(void)
|
||||||
|
{
|
||||||
|
return L"SimonTatham.PuTTY";
|
||||||
|
}
|
246
windows/window.c
246
windows/window.c
@ -359,18 +359,7 @@ static void start_backend(void)
|
|||||||
char *error, *realhost;
|
char *error, *realhost;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*
|
vt = backend_vt_from_conf(conf);
|
||||||
* Select protocol. This is farmed out into a table in a
|
|
||||||
* separate file to enable an ssh-free variant.
|
|
||||||
*/
|
|
||||||
vt = backend_vt_from_proto(conf_get_int(conf, CONF_protocol));
|
|
||||||
if (!vt) {
|
|
||||||
char *str = dupprintf("%s Internal Error", appname);
|
|
||||||
MessageBox(NULL, "Unsupported protocol number found",
|
|
||||||
str, MB_OK | MB_ICONEXCLAMATION);
|
|
||||||
sfree(str);
|
|
||||||
cleanup_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
seat_set_trust_status(&wgs.seat, true);
|
seat_set_trust_status(&wgs.seat, true);
|
||||||
error = backend_init(vt, &wgs.seat, &backend, logctx, conf,
|
error = backend_init(vt, &wgs.seat, &backend, logctx, conf,
|
||||||
@ -511,156 +500,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
|||||||
/*
|
/*
|
||||||
* Process the command line.
|
* Process the command line.
|
||||||
*/
|
*/
|
||||||
{
|
gui_term_process_cmdline(conf, 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 = 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<argc?argv[i+1]:NULL,
|
|
||||||
1, conf);
|
|
||||||
if (ret == -2) {
|
|
||||||
cmdline_error("option \"%s\" requires an argument", p);
|
|
||||||
} else if (ret == 2) {
|
|
||||||
i++; /* skip next argument */
|
|
||||||
} else if (ret == 1) {
|
|
||||||
continue; /* nothing further needs doing */
|
|
||||||
} else if (!strcmp(p, "-cleanup")) {
|
|
||||||
/*
|
|
||||||
* `putty -cleanup'. Remove all registry
|
|
||||||
* entries associated with PuTTY, and also find
|
|
||||||
* and delete the random seed file.
|
|
||||||
*/
|
|
||||||
char *s1, *s2;
|
|
||||||
s1 = dupprintf("This procedure will remove ALL Registry entries\n"
|
|
||||||
"associated with %s, and will also remove\n"
|
|
||||||
"the random seed file. (This only affects the\n"
|
|
||||||
"currently logged-in user.)\n"
|
|
||||||
"\n"
|
|
||||||
"THIS PROCESS WILL DESTROY YOUR SAVED SESSIONS.\n"
|
|
||||||
"Are you really sure you want to continue?",
|
|
||||||
appname);
|
|
||||||
s2 = dupprintf("%s Warning", appname);
|
|
||||||
if (message_box(NULL, s1, s2,
|
|
||||||
MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2,
|
|
||||||
HELPCTXID(option_cleanup)) == IDYES) {
|
|
||||||
cleanup_all();
|
|
||||||
}
|
|
||||||
sfree(s1);
|
|
||||||
sfree(s2);
|
|
||||||
exit(0);
|
|
||||||
} else if (!strcmp(p, "-pgpfp")) {
|
|
||||||
pgp_fingerprints_msgbox(NULL);
|
|
||||||
exit(1);
|
|
||||||
} else if (*p != '-') {
|
|
||||||
cmdline_error("unexpected argument \"%s\"", p);
|
|
||||||
} else {
|
|
||||||
cmdline_error("unknown option \"%s\"", p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cmdline_run_saved(conf);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Bring up the config dialog if the command line hasn't
|
|
||||||
* (explicitly) specified a launchable configuration.
|
|
||||||
*/
|
|
||||||
if (!(special_launchable_argument || cmdline_host_ok(conf))) {
|
|
||||||
if (!do_config(conf))
|
|
||||||
cleanup_exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
prepare_session(conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!prev) {
|
if (!prev) {
|
||||||
WNDCLASSW wndclass;
|
WNDCLASSW wndclass;
|
||||||
@ -960,6 +800,88 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
|||||||
return msg.wParam; /* ... but optimiser doesn't know */
|
return msg.wParam; /* ... but optimiser doesn't know */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *handle_restrict_acl_cmdline_prefix(char *p)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Process the &R prefix on a command line, which is equivalent to
|
||||||
|
* -restrict-acl but lexically easier to prepend when another
|
||||||
|
* instance of ourself automatically constructs a command line.
|
||||||
|
*
|
||||||
|
* If successful, restricts the process ACL and advances the input
|
||||||
|
* pointer past the prefix. Returns the updated pointer (whether
|
||||||
|
* it moved or not).
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handle_special_sessionname_cmdline(char *p, Conf *conf)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Process the special form of command line with an initial @
|
||||||
|
* followed by the name of a saved session with _no quoting or
|
||||||
|
* escaping_. This is a very convenient means of automated
|
||||||
|
* saved-session launching, via IDM_SAVEDSESS or Windows 7 jump
|
||||||
|
* lists.
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
ptrlen sessionname = ptrlen_from_asciz(p + 1);
|
||||||
|
while (sessionname.len > 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)
|
static void setup_clipboards(Terminal *term, Conf *conf)
|
||||||
{
|
{
|
||||||
assert(term->mouse_select_clipboards[0] == CLIP_LOCAL);
|
assert(term->mouse_select_clipboards[0] == CLIP_LOCAL);
|
||||||
|
Loading…
Reference in New Issue
Block a user