2000-10-18 15:36:32 +00:00
|
|
|
/*
|
2021-04-18 06:58:27 +00:00
|
|
|
* windows/platform.h: Windows-specific inter-module stuff.
|
2000-10-18 15:36:32 +00:00
|
|
|
*/
|
|
|
|
|
2021-04-18 06:58:27 +00:00
|
|
|
#ifndef PUTTY_WINDOWS_PLATFORM_H
|
|
|
|
#define PUTTY_WINDOWS_PLATFORM_H
|
2002-10-07 16:45:23 +00:00
|
|
|
|
Replace mkfiles.pl with a CMake build system.
This brings various concrete advantages over the previous system:
- consistent support for out-of-tree builds on all platforms
- more thorough support for Visual Studio IDE project files
- support for Ninja-based builds, which is particularly useful on
Windows where the alternative nmake has no parallel option
- a really simple set of build instructions that work the same way on
all the major platforms (look how much shorter README is!)
- better decoupling of the project configuration from the toolchain
configuration, so that my Windows cross-building doesn't need
(much) special treatment in CMakeLists.txt
- configure-time tests on Windows as well as Linux, so that a lot of
ad-hoc #ifdefs second-guessing a particular feature's presence from
the compiler version can now be replaced by tests of the feature
itself
Also some longer-term software-engineering advantages:
- other people have actually heard of CMake, so they'll be able to
produce patches to the new build setup more easily
- unlike the old mkfiles.pl, CMake is not my personal problem to
maintain
- most importantly, mkfiles.pl was just a horrible pile of
unmaintainable cruft, which even I found it painful to make changes
to or to use, and desperately needed throwing in the bin. I've
already thrown away all the variants of it I had in other projects
of mine, and was only delaying this one so we could make the 0.75
release branch first.
This change comes with a noticeable build-level restructuring. The
previous Recipe worked by compiling every object file exactly once,
and then making each executable by linking a precisely specified
subset of the same object files. But in CMake, that's not the natural
way to work - if you write the obvious command that puts the same
source file into two executable targets, CMake generates a makefile
that compiles it once per target. That can be an advantage, because it
gives you the freedom to compile it differently in each case (e.g.
with a #define telling it which program it's part of). But in a
project that has many executable targets and had carefully contrived
to _never_ need to build any module more than once, all it does is
bloat the build time pointlessly!
To avoid slowing down the build by a large factor, I've put most of
the modules of the code base into a collection of static libraries
organised vaguely thematically (SSH, other backends, crypto, network,
...). That means all those modules can still be compiled just once
each, because once each library is built it's reused unchanged for all
the executable targets.
One upside of this library-based structure is that now I don't have to
manually specify exactly which objects go into which programs any more
- it's enough to specify which libraries are needed, and the linker
will figure out the fine detail automatically. So there's less
maintenance to do in CMakeLists.txt when the source code changes.
But that reorganisation also adds fragility, because of the trad Unix
linker semantics of walking along the library list once each, so that
cyclic references between your libraries will provoke link errors. The
current setup builds successfully, but I suspect it only just manages
it.
(In particular, I've found that MinGW is the most finicky on this
score of the Windows compilers I've tried building with. So I've
included a MinGW test build in the new-look Buildscr, because
otherwise I think there'd be a significant risk of introducing
MinGW-only build failures due to library search order, which wasn't a
risk in the previous library-free build organisation.)
In the longer term I hope to be able to reduce the risk of that, via
gradual reorganisation (in particular, breaking up too-monolithic
modules, to reduce the risk of knock-on references when you included a
module for function A and it also contains function B with an
unsatisfied dependency you didn't really need). Ideally I want to
reach a state in which the libraries all have sensibly described
purposes, a clearly documented (partial) order in which they're
permitted to depend on each other, and a specification of what stubs
you have to put where if you're leaving one of them out (e.g.
nocrypto) and what callbacks you have to define in your non-library
objects to satisfy dependencies from things low in the stack (e.g.
out_of_memory()).
One thing that's gone completely missing in this migration,
unfortunately, is the unfinished MacOS port linked against Quartz GTK.
That's because it turned out that I can't currently build it myself,
on my own Mac: my previous installation of GTK had bit-rotted as a
side effect of an Xcode upgrade, and I haven't yet been able to
persuade jhbuild to make me a new one. So I can't even build the MacOS
port with the _old_ makefiles, and hence, I have no way of checking
that the new ones also work. I hope to bring that port back to life at
some point, but I don't want it to block the rest of this change.
2021-04-10 14:21:11 +00:00
|
|
|
#include <winsock2.h>
|
2003-10-12 13:46:12 +00:00
|
|
|
#include <windows.h>
|
2019-09-08 19:29:00 +00:00
|
|
|
#include <stdio.h> /* for FILENAME_MAX */
|
2003-02-01 12:54:40 +00:00
|
|
|
|
2015-09-28 18:52:38 +00:00
|
|
|
/* We use uintptr_t for Win32/Win64 portability, so we should in
|
|
|
|
* principle include stdint.h, which defines it according to the C
|
Replace mkfiles.pl with a CMake build system.
This brings various concrete advantages over the previous system:
- consistent support for out-of-tree builds on all platforms
- more thorough support for Visual Studio IDE project files
- support for Ninja-based builds, which is particularly useful on
Windows where the alternative nmake has no parallel option
- a really simple set of build instructions that work the same way on
all the major platforms (look how much shorter README is!)
- better decoupling of the project configuration from the toolchain
configuration, so that my Windows cross-building doesn't need
(much) special treatment in CMakeLists.txt
- configure-time tests on Windows as well as Linux, so that a lot of
ad-hoc #ifdefs second-guessing a particular feature's presence from
the compiler version can now be replaced by tests of the feature
itself
Also some longer-term software-engineering advantages:
- other people have actually heard of CMake, so they'll be able to
produce patches to the new build setup more easily
- unlike the old mkfiles.pl, CMake is not my personal problem to
maintain
- most importantly, mkfiles.pl was just a horrible pile of
unmaintainable cruft, which even I found it painful to make changes
to or to use, and desperately needed throwing in the bin. I've
already thrown away all the variants of it I had in other projects
of mine, and was only delaying this one so we could make the 0.75
release branch first.
This change comes with a noticeable build-level restructuring. The
previous Recipe worked by compiling every object file exactly once,
and then making each executable by linking a precisely specified
subset of the same object files. But in CMake, that's not the natural
way to work - if you write the obvious command that puts the same
source file into two executable targets, CMake generates a makefile
that compiles it once per target. That can be an advantage, because it
gives you the freedom to compile it differently in each case (e.g.
with a #define telling it which program it's part of). But in a
project that has many executable targets and had carefully contrived
to _never_ need to build any module more than once, all it does is
bloat the build time pointlessly!
To avoid slowing down the build by a large factor, I've put most of
the modules of the code base into a collection of static libraries
organised vaguely thematically (SSH, other backends, crypto, network,
...). That means all those modules can still be compiled just once
each, because once each library is built it's reused unchanged for all
the executable targets.
One upside of this library-based structure is that now I don't have to
manually specify exactly which objects go into which programs any more
- it's enough to specify which libraries are needed, and the linker
will figure out the fine detail automatically. So there's less
maintenance to do in CMakeLists.txt when the source code changes.
But that reorganisation also adds fragility, because of the trad Unix
linker semantics of walking along the library list once each, so that
cyclic references between your libraries will provoke link errors. The
current setup builds successfully, but I suspect it only just manages
it.
(In particular, I've found that MinGW is the most finicky on this
score of the Windows compilers I've tried building with. So I've
included a MinGW test build in the new-look Buildscr, because
otherwise I think there'd be a significant risk of introducing
MinGW-only build failures due to library search order, which wasn't a
risk in the previous library-free build organisation.)
In the longer term I hope to be able to reduce the risk of that, via
gradual reorganisation (in particular, breaking up too-monolithic
modules, to reduce the risk of knock-on references when you included a
module for function A and it also contains function B with an
unsatisfied dependency you didn't really need). Ideally I want to
reach a state in which the libraries all have sensibly described
purposes, a clearly documented (partial) order in which they're
permitted to depend on each other, and a specification of what stubs
you have to put where if you're leaving one of them out (e.g.
nocrypto) and what callbacks you have to define in your non-library
objects to satisfy dependencies from things low in the stack (e.g.
out_of_memory()).
One thing that's gone completely missing in this migration,
unfortunately, is the unfinished MacOS port linked against Quartz GTK.
That's because it turned out that I can't currently build it myself,
on my own Mac: my previous installation of GTK had bit-rotted as a
side effect of an Xcode upgrade, and I haven't yet been able to
persuade jhbuild to make me a new one. So I can't even build the MacOS
port with the _old_ makefiles, and hence, I have no way of checking
that the new ones also work. I hope to bring that port back to life at
some point, but I don't want it to block the rest of this change.
2021-04-10 14:21:11 +00:00
|
|
|
* standard. But older versions of Visual Studio don't provide
|
2015-09-28 18:52:38 +00:00
|
|
|
* stdint.h at all, but do (non-standardly) define uintptr_t in
|
|
|
|
* stddef.h. So here we try to make sure _some_ standard header is
|
|
|
|
* included which defines uintptr_t. */
|
|
|
|
#include <stddef.h>
|
Replace mkfiles.pl with a CMake build system.
This brings various concrete advantages over the previous system:
- consistent support for out-of-tree builds on all platforms
- more thorough support for Visual Studio IDE project files
- support for Ninja-based builds, which is particularly useful on
Windows where the alternative nmake has no parallel option
- a really simple set of build instructions that work the same way on
all the major platforms (look how much shorter README is!)
- better decoupling of the project configuration from the toolchain
configuration, so that my Windows cross-building doesn't need
(much) special treatment in CMakeLists.txt
- configure-time tests on Windows as well as Linux, so that a lot of
ad-hoc #ifdefs second-guessing a particular feature's presence from
the compiler version can now be replaced by tests of the feature
itself
Also some longer-term software-engineering advantages:
- other people have actually heard of CMake, so they'll be able to
produce patches to the new build setup more easily
- unlike the old mkfiles.pl, CMake is not my personal problem to
maintain
- most importantly, mkfiles.pl was just a horrible pile of
unmaintainable cruft, which even I found it painful to make changes
to or to use, and desperately needed throwing in the bin. I've
already thrown away all the variants of it I had in other projects
of mine, and was only delaying this one so we could make the 0.75
release branch first.
This change comes with a noticeable build-level restructuring. The
previous Recipe worked by compiling every object file exactly once,
and then making each executable by linking a precisely specified
subset of the same object files. But in CMake, that's not the natural
way to work - if you write the obvious command that puts the same
source file into two executable targets, CMake generates a makefile
that compiles it once per target. That can be an advantage, because it
gives you the freedom to compile it differently in each case (e.g.
with a #define telling it which program it's part of). But in a
project that has many executable targets and had carefully contrived
to _never_ need to build any module more than once, all it does is
bloat the build time pointlessly!
To avoid slowing down the build by a large factor, I've put most of
the modules of the code base into a collection of static libraries
organised vaguely thematically (SSH, other backends, crypto, network,
...). That means all those modules can still be compiled just once
each, because once each library is built it's reused unchanged for all
the executable targets.
One upside of this library-based structure is that now I don't have to
manually specify exactly which objects go into which programs any more
- it's enough to specify which libraries are needed, and the linker
will figure out the fine detail automatically. So there's less
maintenance to do in CMakeLists.txt when the source code changes.
But that reorganisation also adds fragility, because of the trad Unix
linker semantics of walking along the library list once each, so that
cyclic references between your libraries will provoke link errors. The
current setup builds successfully, but I suspect it only just manages
it.
(In particular, I've found that MinGW is the most finicky on this
score of the Windows compilers I've tried building with. So I've
included a MinGW test build in the new-look Buildscr, because
otherwise I think there'd be a significant risk of introducing
MinGW-only build failures due to library search order, which wasn't a
risk in the previous library-free build organisation.)
In the longer term I hope to be able to reduce the risk of that, via
gradual reorganisation (in particular, breaking up too-monolithic
modules, to reduce the risk of knock-on references when you included a
module for function A and it also contains function B with an
unsatisfied dependency you didn't really need). Ideally I want to
reach a state in which the libraries all have sensibly described
purposes, a clearly documented (partial) order in which they're
permitted to depend on each other, and a specification of what stubs
you have to put where if you're leaving one of them out (e.g.
nocrypto) and what callbacks you have to define in your non-library
objects to satisfy dependencies from things low in the stack (e.g.
out_of_memory()).
One thing that's gone completely missing in this migration,
unfortunately, is the unfinished MacOS port linked against Quartz GTK.
That's because it turned out that I can't currently build it myself,
on my own Mac: my previous installation of GTK had bit-rotted as a
side effect of an Xcode upgrade, and I haven't yet been able to
persuade jhbuild to make me a new one. So I can't even build the MacOS
port with the _old_ makefiles, and hence, I have no way of checking
that the new ones also work. I hope to bring that port back to life at
some point, but I don't want it to block the rest of this change.
2021-04-10 14:21:11 +00:00
|
|
|
#if !HAVE_NO_STDINT_H
|
2015-09-28 18:52:38 +00:00
|
|
|
#include <stdint.h>
|
|
|
|
#endif
|
|
|
|
|
2018-05-24 07:59:01 +00:00
|
|
|
#include "defs.h"
|
2019-02-20 06:52:54 +00:00
|
|
|
#include "marshal.h"
|
2018-05-24 07:59:01 +00:00
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
#include "tree234.h"
|
|
|
|
|
2021-04-23 05:19:05 +00:00
|
|
|
#include "help.h"
|
2003-03-05 22:07:40 +00:00
|
|
|
|
2018-05-31 17:12:01 +00:00
|
|
|
#if defined _M_IX86 || defined _M_AMD64
|
|
|
|
#define BUILDINFO_PLATFORM "x86 Windows"
|
|
|
|
#elif defined _M_ARM || defined _M_ARM64
|
|
|
|
#define BUILDINFO_PLATFORM "Arm Windows"
|
|
|
|
#else
|
2017-01-21 14:55:53 +00:00
|
|
|
#define BUILDINFO_PLATFORM "Windows"
|
2018-05-31 17:12:01 +00:00
|
|
|
#endif
|
2017-01-21 14:55:53 +00:00
|
|
|
|
2022-09-02 15:09:40 +00:00
|
|
|
#if defined __GNUC__ || defined __clang__
|
|
|
|
#define THREADLOCAL __thread
|
|
|
|
#elif defined _MSC_VER
|
|
|
|
#define THREADLOCAL __declspec(thread)
|
|
|
|
#else
|
|
|
|
#error Do not know how to declare thread-local storage with this toolchain
|
|
|
|
#endif
|
|
|
|
|
2022-01-03 11:15:07 +00:00
|
|
|
/* Randomly-chosen dwData value identifying a WM_COPYDATA message as
|
|
|
|
* being a Pageant transaction */
|
|
|
|
#define AGENT_COPYDATA_ID 0x804e50ba
|
|
|
|
|
2003-02-01 12:54:40 +00:00
|
|
|
struct Filename {
|
Some support for wide-character filenames in Windows.
The Windows version of the Filename structure now contains three
versions of the pathname, in UTF-16, UTF-8 and the system code page.
Callers can use whichever is most convenient.
All uses of filenames for actually opening files now use the UTF-16
version, which means they can tolerate 'exotic' filenames, by which I
mean those including Unicode characters outside the host system's
CP_ACP default code page.
Other uses of Filename structures inside the 'windows' subdirectory do
something appropriate, e.g. when printing a filename inside a message
box or a console message, we use the UTF-8 version of the filename
with the UTF-8 version of the appropriate API.
There are three remaining pieces to full Unicode filename support:
One is that the cross-platform code has many calls to
filename_to_str(), embodying the assumption that a file name can be
reliably converted into the unspecified current character set; those
will all need changing in some way.
Another is that write_setting_filename(), in windows/storage.c, still
saves filenames to the Registry as an ordinary REG_SZ in the system
code page. So even if an exotic filename were stored in a Conf, that
Conf couldn't round-trip via the Registry and back without corrupting
that filename by coercing it back to a string that fits in CP_ACP and
therefore doesn't represent the same file. This can't be fixed without
a compatibility break in the storage format, and I don't want to make
a minimal change in that area: if we're going to break compatibility,
then we should break it good and hard (the Nanny Ogg principle), and
devise a completely fresh storage representation that fixes as many
other legacy problems as possible at the same time. So that's my plan,
not yet started.
The final point, much more obviously, is that we're still short of
methods to _construct_ any Filename structures using a Unicode input
string! It should now work to enter one in the GUI configurer (either
by manual text input or via the file selector), but it won't
round-trip through a save and load (as discussed above), and there's
still no way to specify one on the command line (the groundwork is
laid by commit 10e1ac7752de928 but not yet linked up).
But this is a start.
2023-05-28 10:30:59 +00:00
|
|
|
/*
|
|
|
|
* A Windows Filename stores a path in three formats:
|
|
|
|
*
|
|
|
|
* - wchar_t (in Windows UTF-16 encoding). The best format to use
|
|
|
|
* for actual file API functions, because all legal Windows
|
|
|
|
* file names are representable.
|
|
|
|
*
|
|
|
|
* - char, in the system default codepage. A fallback to use if
|
|
|
|
* necessary, e.g. in diagnostics written to somewhere that is
|
|
|
|
* unavoidably encoded _in_ the system codepage.
|
|
|
|
*
|
|
|
|
* - char, in UTF-8. An equally general representation to wpath,
|
|
|
|
* but suitable for keeping in char-typed strings.
|
|
|
|
*/
|
|
|
|
wchar_t *wpath;
|
|
|
|
char *cpath, *utf8path;
|
2003-02-01 12:54:40 +00:00
|
|
|
};
|
Some support for wide-character filenames in Windows.
The Windows version of the Filename structure now contains three
versions of the pathname, in UTF-16, UTF-8 and the system code page.
Callers can use whichever is most convenient.
All uses of filenames for actually opening files now use the UTF-16
version, which means they can tolerate 'exotic' filenames, by which I
mean those including Unicode characters outside the host system's
CP_ACP default code page.
Other uses of Filename structures inside the 'windows' subdirectory do
something appropriate, e.g. when printing a filename inside a message
box or a console message, we use the UTF-8 version of the filename
with the UTF-8 version of the appropriate API.
There are three remaining pieces to full Unicode filename support:
One is that the cross-platform code has many calls to
filename_to_str(), embodying the assumption that a file name can be
reliably converted into the unspecified current character set; those
will all need changing in some way.
Another is that write_setting_filename(), in windows/storage.c, still
saves filenames to the Registry as an ordinary REG_SZ in the system
code page. So even if an exotic filename were stored in a Conf, that
Conf couldn't round-trip via the Registry and back without corrupting
that filename by coercing it back to a string that fits in CP_ACP and
therefore doesn't represent the same file. This can't be fixed without
a compatibility break in the storage format, and I don't want to make
a minimal change in that area: if we're going to break compatibility,
then we should break it good and hard (the Nanny Ogg principle), and
devise a completely fresh storage representation that fixes as many
other legacy problems as possible at the same time. So that's my plan,
not yet started.
The final point, much more obviously, is that we're still short of
methods to _construct_ any Filename structures using a Unicode input
string! It should now work to enter one in the GUI configurer (either
by manual text input or via the file selector), but it won't
round-trip through a save and load (as discussed above), and there's
still no way to specify one on the command line (the groundwork is
laid by commit 10e1ac7752de928 but not yet linked up).
But this is a start.
2023-05-28 10:30:59 +00:00
|
|
|
Filename *filename_from_wstr(const wchar_t *str);
|
|
|
|
FILE *f_open(const Filename *filename, const char *mode, bool isprivate);
|
2003-02-01 12:54:40 +00:00
|
|
|
|
2023-09-22 12:55:33 +00:00
|
|
|
#ifndef SUPERSEDE_FONTSPEC_FOR_TESTING
|
2003-02-01 12:54:40 +00:00
|
|
|
struct FontSpec {
|
2011-10-01 17:38:59 +00:00
|
|
|
char *name;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool isbold;
|
2003-02-01 12:54:40 +00:00
|
|
|
int height;
|
|
|
|
int charset;
|
|
|
|
};
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
struct FontSpec *fontspec_new(
|
|
|
|
const char *name, bool bold, int height, int charset);
|
2023-09-22 12:55:33 +00:00
|
|
|
#endif
|
2003-02-01 12:54:40 +00:00
|
|
|
|
2006-01-11 23:42:02 +00:00
|
|
|
#ifndef CLEARTYPE_QUALITY
|
|
|
|
#define CLEARTYPE_QUALITY 5
|
|
|
|
#endif
|
|
|
|
#define FONT_QUALITY(fq) ( \
|
|
|
|
(fq) == FQ_DEFAULT ? DEFAULT_QUALITY : \
|
|
|
|
(fq) == FQ_ANTIALIASED ? ANTIALIASED_QUALITY : \
|
|
|
|
(fq) == FQ_NONANTIALIASED ? NONANTIALIASED_QUALITY : \
|
|
|
|
CLEARTYPE_QUALITY)
|
|
|
|
|
2009-03-24 22:24:31 +00:00
|
|
|
#define PLATFORM_IS_UTF16 /* enable UTF-16 processing when exchanging
|
2019-09-08 19:29:00 +00:00
|
|
|
* wchar_t strings with environment */
|
2009-03-24 22:24:31 +00:00
|
|
|
|
2017-12-09 12:00:13 +00:00
|
|
|
#define PLATFORM_CLIPBOARDS(X) \
|
|
|
|
X(CLIP_SYSTEM, "system clipboard") \
|
|
|
|
/* end of list */
|
|
|
|
|
2006-01-27 20:49:59 +00:00
|
|
|
/*
|
|
|
|
* Where we can, we use GetWindowLongPtr and friends because they're
|
|
|
|
* more useful on 64-bit platforms, but they're a relatively recent
|
|
|
|
* innovation, missing from VC++ 6 and older MinGW. Degrade nicely.
|
|
|
|
* (NB that on some systems, some of these things are available but
|
|
|
|
* not others...)
|
|
|
|
*/
|
2006-01-11 23:42:02 +00:00
|
|
|
|
2006-01-27 20:49:59 +00:00
|
|
|
#ifndef GCLP_HCURSOR
|
|
|
|
/* GetClassLongPtr and friends */
|
|
|
|
#undef GetClassLongPtr
|
|
|
|
#define GetClassLongPtr GetClassLong
|
|
|
|
#undef SetClassLongPtr
|
|
|
|
#define SetClassLongPtr SetClassLong
|
|
|
|
#define GCLP_HCURSOR GCL_HCURSOR
|
|
|
|
/* GetWindowLongPtr and friends */
|
|
|
|
#undef GetWindowLongPtr
|
2006-01-11 23:42:02 +00:00
|
|
|
#define GetWindowLongPtr GetWindowLong
|
2006-01-27 20:49:59 +00:00
|
|
|
#undef SetWindowLongPtr
|
2006-01-11 23:42:02 +00:00
|
|
|
#define SetWindowLongPtr SetWindowLong
|
2006-01-27 20:49:59 +00:00
|
|
|
#undef GWLP_USERDATA
|
2006-01-11 23:42:02 +00:00
|
|
|
#define GWLP_USERDATA GWL_USERDATA
|
2006-01-27 20:49:59 +00:00
|
|
|
#undef DWLP_MSGRESULT
|
2006-01-11 23:42:02 +00:00
|
|
|
#define DWLP_MSGRESULT DWL_MSGRESULT
|
2006-01-27 20:49:59 +00:00
|
|
|
/* Since we've clobbered the above functions, we should clobber the
|
|
|
|
* associated type regardless of whether it's defined. */
|
|
|
|
#undef LONG_PTR
|
|
|
|
#define LONG_PTR LONG
|
2006-01-11 23:42:02 +00:00
|
|
|
#endif
|
|
|
|
|
New library-style 'utils' subdirectories.
Now that the new CMake build system is encouraging us to lay out the
code like a set of libraries, it seems like a good idea to make them
look more _like_ libraries, by putting things into separate modules as
far as possible.
This fixes several previous annoyances in which you had to link
against some object in order to get a function you needed, but that
object also contained other functions you didn't need which included
link-time symbol references you didn't want to have to deal with. The
usual offender was subsidiary supporting programs including misc.c for
some innocuous function and then finding they had to deal with the
requirements of buildinfo().
This big reorganisation introduces three new subdirectories called
'utils', one at the top level and one in each platform subdir. In each
case, the directory contains basically the same files that were
previously placed in the 'utils' build-time library, except that the
ones that were extremely miscellaneous (misc.c, utils.c, uxmisc.c,
winmisc.c, winmiscs.c, winutils.c) have been split up into much
smaller pieces.
2021-04-17 14:22:20 +00:00
|
|
|
#if !HAVE_STRTOUMAX
|
|
|
|
/* Work around lack of strtoumax in older MSVC libraries */
|
|
|
|
static inline uintmax_t strtoumax(const char *nptr, char **endptr, int base)
|
|
|
|
{ return _strtoui64(nptr, endptr, base); }
|
|
|
|
#endif
|
|
|
|
|
2022-04-25 13:08:00 +00:00
|
|
|
typedef INT_PTR (*ShinyDlgProc)(HWND hwnd, UINT msg, WPARAM wParam,
|
|
|
|
LPARAM lParam, void *ctx);
|
|
|
|
int ShinyDialogBox(HINSTANCE hinst, LPCTSTR tmpl, const char *winclass,
|
|
|
|
HWND hwndparent, ShinyDlgProc proc, void *ctx);
|
|
|
|
void ShinyEndDialog(HWND hwnd, int ret);
|
2003-06-16 23:55:26 +00:00
|
|
|
|
2022-04-24 12:34:15 +00:00
|
|
|
void centre_window(HWND hwnd);
|
|
|
|
|
2017-02-14 23:19:13 +00:00
|
|
|
#ifndef __WINE__
|
2017-02-05 11:13:45 +00:00
|
|
|
/* Up-to-date Windows headers warn that the unprefixed versions of
|
|
|
|
* these names are deprecated. */
|
|
|
|
#define stricmp _stricmp
|
|
|
|
#define strnicmp _strnicmp
|
2017-02-14 23:19:13 +00:00
|
|
|
#else
|
|
|
|
/* Compiling with winegcc, _neither_ version of these functions
|
|
|
|
* exists. Use the POSIX names. */
|
|
|
|
#define stricmp strcasecmp
|
|
|
|
#define strnicmp strncasecmp
|
|
|
|
#endif
|
2017-02-05 11:13:45 +00:00
|
|
|
|
2009-11-08 18:47:41 +00:00
|
|
|
/*
|
2010-03-13 15:14:30 +00:00
|
|
|
* Dynamically linked functions. These come in two flavours:
|
|
|
|
*
|
|
|
|
* - GET_WINDOWS_FUNCTION does not expose "name" to the preprocessor,
|
|
|
|
* so will always dynamically link against exactly what is specified
|
|
|
|
* in "name". If you're not sure, use this one.
|
|
|
|
*
|
|
|
|
* - GET_WINDOWS_FUNCTION_PP allows "name" to be redirected via
|
|
|
|
* preprocessor definitions like "#define foo bar"; this is principally
|
|
|
|
* intended for the ANSI/Unicode DoSomething/DoSomethingA/DoSomethingW.
|
|
|
|
* If your function has an argument of type "LPTSTR" or similar, this
|
|
|
|
* is the variant to use.
|
|
|
|
* (However, it can't always be used, as it trips over more complicated
|
|
|
|
* macro trickery such as the WspiapiGetAddrInfo wrapper for getaddrinfo.)
|
|
|
|
*
|
|
|
|
* (DECL_WINDOWS_FUNCTION works with both these variants.)
|
2009-11-08 18:47:41 +00:00
|
|
|
*/
|
Add automatic type-checking to GET_WINDOWS_FUNCTION.
This gives me an extra safety-check against having mistyped one of the
function prototypes that we load at run time from DLLs: we verify that
the typedef we defined based on the prototype in our source code
matches the type of the real function as declared in the Windows
headers.
This was an idea I had while adding a pile of further functions using
this mechanism. It didn't catch any errors (either in the new
functions or in the existing collection), but that's no reason not to
keep it anyway now that I've thought of it!
In VS2015, this automated type-check works for most functions, but a
couple manage to break it. SetCurrentProcessExplicitAppUserModelID in
winjump.c can't be type-checked, because including <shobjidl.h> where
that function is declared would also bring in a load of other stuff
that conflicts with the painful manual COM declarations in winjump.c.
(That stuff could probably be removed now we're on an up-to-date
Visual Studio, on the other hand, but that's a separate chore.) And
gai_strerror, used in winnet.c, does _have_ an implementation in a
DLL, but the header files like to provide an inline version with a
different calling convention, which defeats this error-checking trick.
And in the older VS2003 that we still precautionarily build with,
several more type-checks have to be #ifdeffed out because the
functions they check against just aren't there at all.
2017-04-11 17:56:55 +00:00
|
|
|
#define DECL_WINDOWS_FUNCTION(linkage, rettype, name, params) \
|
|
|
|
typedef rettype (WINAPI *t_##name) params; \
|
2009-11-08 18:47:41 +00:00
|
|
|
linkage t_##name p_##name
|
2020-02-02 10:00:43 +00:00
|
|
|
/* If you DECL_WINDOWS_FUNCTION as extern in a header file, use this to
|
|
|
|
* define the function pointer in a source file */
|
|
|
|
#define DEF_WINDOWS_FUNCTION(name) t_##name p_##name
|
Add automatic type-checking to GET_WINDOWS_FUNCTION.
This gives me an extra safety-check against having mistyped one of the
function prototypes that we load at run time from DLLs: we verify that
the typedef we defined based on the prototype in our source code
matches the type of the real function as declared in the Windows
headers.
This was an idea I had while adding a pile of further functions using
this mechanism. It didn't catch any errors (either in the new
functions or in the existing collection), but that's no reason not to
keep it anyway now that I've thought of it!
In VS2015, this automated type-check works for most functions, but a
couple manage to break it. SetCurrentProcessExplicitAppUserModelID in
winjump.c can't be type-checked, because including <shobjidl.h> where
that function is declared would also bring in a load of other stuff
that conflicts with the painful manual COM declarations in winjump.c.
(That stuff could probably be removed now we're on an up-to-date
Visual Studio, on the other hand, but that's a separate chore.) And
gai_strerror, used in winnet.c, does _have_ an implementation in a
DLL, but the header files like to provide an inline version with a
different calling convention, which defeats this error-checking trick.
And in the older VS2003 that we still precautionarily build with,
several more type-checks have to be #ifdeffed out because the
functions they check against just aren't there at all.
2017-04-11 17:56:55 +00:00
|
|
|
#define GET_WINDOWS_FUNCTION_PP(module, name) \
|
|
|
|
TYPECHECK((t_##name)NULL == name, \
|
|
|
|
(p_##name = module ? \
|
|
|
|
(t_##name) GetProcAddress(module, STR(name)) : NULL))
|
|
|
|
#define GET_WINDOWS_FUNCTION(module, name) \
|
|
|
|
TYPECHECK((t_##name)NULL == name, \
|
|
|
|
(p_##name = module ? \
|
|
|
|
(t_##name) GetProcAddress(module, #name) : NULL))
|
|
|
|
#define GET_WINDOWS_FUNCTION_NO_TYPECHECK(module, name) \
|
|
|
|
(p_##name = module ? \
|
|
|
|
(t_##name) GetProcAddress(module, #name) : NULL)
|
2009-11-08 18:47:41 +00:00
|
|
|
|
2002-10-07 16:45:23 +00:00
|
|
|
#define PUTTY_REG_POS "Software\\SimonTatham\\PuTTY"
|
|
|
|
#define PUTTY_REG_PARENT "Software\\SimonTatham"
|
|
|
|
#define PUTTY_REG_PARENT_CHILD "PuTTY"
|
|
|
|
#define PUTTY_REG_GPARENT "Software"
|
|
|
|
#define PUTTY_REG_GPARENT_CHILD "SimonTatham"
|
|
|
|
|
2010-12-23 17:32:28 +00:00
|
|
|
/* Result values for the jumplist registry functions. */
|
|
|
|
#define JUMPLISTREG_OK 0
|
|
|
|
#define JUMPLISTREG_ERROR_INVALID_PARAMETER 1
|
|
|
|
#define JUMPLISTREG_ERROR_KEYOPENCREATE_FAILURE 2
|
|
|
|
#define JUMPLISTREG_ERROR_VALUEREAD_FAILURE 3
|
|
|
|
#define JUMPLISTREG_ERROR_VALUEWRITE_FAILURE 4
|
|
|
|
#define JUMPLISTREG_ERROR_INVALID_VALUE 5
|
|
|
|
|
2006-12-17 11:16:07 +00:00
|
|
|
#define PUTTY_CHM_FILE "putty.chm"
|
2005-02-16 01:47:10 +00:00
|
|
|
|
2002-10-07 16:45:23 +00:00
|
|
|
#define GETTICKCOUNT GetTickCount
|
|
|
|
#define CURSORBLINK GetCaretBlinkTime()
|
2019-09-08 19:29:00 +00:00
|
|
|
#define TICKSPERSEC 1000 /* GetTickCount returns milliseconds */
|
2002-10-07 16:45:23 +00:00
|
|
|
|
|
|
|
#define DEFAULT_CODEPAGE CP_ACP
|
2012-04-22 14:22:10 +00:00
|
|
|
#define USES_VTLINE_HACK
|
2023-01-28 14:53:55 +00:00
|
|
|
#define CP_UTF8 65001
|
2023-03-04 12:57:03 +00:00
|
|
|
#define CP_437 437 /* used for test suites */
|
2023-03-04 17:47:01 +00:00
|
|
|
#define CP_ISO8859_1 0x10001 /* used for test suites */
|
2002-10-07 16:45:23 +00:00
|
|
|
|
2008-11-24 23:44:55 +00:00
|
|
|
#ifndef NO_GSSAPI
|
|
|
|
/*
|
|
|
|
* GSS-API stuff
|
|
|
|
*/
|
2010-05-19 18:22:17 +00:00
|
|
|
#define GSS_CC CALLBACK
|
|
|
|
/*
|
2008-11-24 23:44:55 +00:00
|
|
|
typedef struct Ssh_gss_buf {
|
2010-05-19 18:22:17 +00:00
|
|
|
size_t length;
|
2008-11-24 23:44:55 +00:00
|
|
|
char *value;
|
|
|
|
} Ssh_gss_buf;
|
|
|
|
|
|
|
|
#define SSH_GSS_EMPTY_BUF (Ssh_gss_buf) {0,NULL}
|
2008-12-01 21:18:29 +00:00
|
|
|
typedef void *Ssh_gss_name;
|
2010-05-19 18:22:17 +00:00
|
|
|
*/
|
2008-11-24 23:44:55 +00:00
|
|
|
#endif
|
|
|
|
|
2002-10-07 16:45:23 +00:00
|
|
|
/*
|
Remove remaining uses of the GLOBAL macro.
We now have no remaining things in header files that switch from being
a declaration to a definition depending on an awkward #define at the
point of including that header. There are still a few mutable
variables with external linkage, but at least now each one is defined
in a specific source file file appropriate to its purpose and context.
The remaining globals as of this commit were:
- 'logctx' and 'term', which never needed to be globals in the first
place, because they were never actually shared between source
files. Now 'term' is just a static in window.c, and 'logctx' is a
static in each of that and winplink.c.
- 'hinst', which still has external linkage, but is now defined
separately in each source file that sets it up (i.e. those with a
WinMain)
- osMajorVersion, osMinorVersion and osPlatformId, whose definitions
now live in winmisc.c alongside the code which sets them up.
(Actually they were defined there all along, it turns out, but
every toolchain I've built with has commoned them together with the
version defined by the GLOBAL in the header.)
- 'hwnd', which nothing was actually _using_ any more after previous
commits, so all this commit had to do was delete it.
2020-02-02 10:00:43 +00:00
|
|
|
* The all-important instance handle, saved from WinMain in every GUI
|
|
|
|
* program and exported for other GUI code to pass back to the Windows
|
|
|
|
* API.
|
2002-10-07 16:45:23 +00:00
|
|
|
*/
|
Remove remaining uses of the GLOBAL macro.
We now have no remaining things in header files that switch from being
a declaration to a definition depending on an awkward #define at the
point of including that header. There are still a few mutable
variables with external linkage, but at least now each one is defined
in a specific source file file appropriate to its purpose and context.
The remaining globals as of this commit were:
- 'logctx' and 'term', which never needed to be globals in the first
place, because they were never actually shared between source
files. Now 'term' is just a static in window.c, and 'logctx' is a
static in each of that and winplink.c.
- 'hinst', which still has external linkage, but is now defined
separately in each source file that sets it up (i.e. those with a
WinMain)
- osMajorVersion, osMinorVersion and osPlatformId, whose definitions
now live in winmisc.c alongside the code which sets them up.
(Actually they were defined there all along, it turns out, but
every toolchain I've built with has commoned them together with the
version defined by the GLOBAL in the header.)
- 'hwnd', which nothing was actually _using_ any more after previous
commits, so all this commit had to do was delete it.
2020-02-02 10:00:43 +00:00
|
|
|
extern HINSTANCE hinst;
|
2000-10-18 15:36:32 +00:00
|
|
|
|
2002-10-26 10:33:59 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* Help file stuff in help.c.
|
2002-10-26 10:33:59 +00:00
|
|
|
*/
|
2006-12-17 11:16:07 +00:00
|
|
|
void init_help(void);
|
|
|
|
void shutdown_help(void);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool has_help(void);
|
2006-12-17 11:16:07 +00:00
|
|
|
void launch_help(HWND hwnd, const char *topic);
|
|
|
|
void quit_help(HWND hwnd);
|
2019-01-26 20:26:09 +00:00
|
|
|
int has_embedded_chm(void); /* 1 = yes, 0 = no, -1 = N/A */
|
2002-10-26 10:33:59 +00:00
|
|
|
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* GUI seat methods in dialog.c, so that the vtable definition in
|
2018-11-03 10:06:33 +00:00
|
|
|
* window.c can refer to them.
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
*/
|
Richer data type for interactive prompt results.
All the seat functions that request an interactive prompt of some kind
to the user - both the main seat_get_userpass_input and the various
confirmation dialogs for things like host keys - were using a simple
int return value, with the general semantics of 0 = "fail", 1 =
"proceed" (and in the case of seat_get_userpass_input, answers to the
prompts were provided), and -1 = "request in progress, wait for a
callback".
In this commit I change all those functions' return types to a new
struct called SeatPromptResult, whose primary field is an enum
replacing those simple integer values.
The main purpose is that the enum has not three but _four_ values: the
"fail" result has been split into 'user abort' and 'software abort'.
The distinction is that a user abort occurs as a result of an
interactive UI action, such as the user clicking 'cancel' in a dialog
box or hitting ^D or ^C at a terminal password prompt - and therefore,
there's no need to display an error message telling the user that the
interactive operation has failed, because the user already knows,
because they _did_ it. 'Software abort' is from any other cause, where
PuTTY is the first to know there was a problem, and has to tell the
user.
We already had this 'user abort' vs 'software abort' distinction in
other parts of the code - the SSH backend has separate termination
functions which protocol layers can call. But we assumed that any
failure from an interactive prompt request fell into the 'user abort'
category, which is not true. A couple of examples: if you configure a
host key fingerprint in your saved session via the SSH > Host keys
pane, and the server presents a host key that doesn't match it, then
verify_ssh_host_key would report that the user had aborted the
connection, and feel no need to tell the user what had gone wrong!
Similarly, if a password provided on the command line was not
accepted, then (after I fixed the semantics of that in the previous
commit) the same wrong handling would occur.
So now, those Seat prompt functions too can communicate whether the
user or the software originated a connection abort. And in the latter
case, we also provide an error message to present to the user. Result:
in those two example cases (and others), error messages should no
longer go missing.
Implementation note: to avoid the hassle of having the error message
in a SeatPromptResult being a dynamically allocated string (and hence,
every recipient of one must always check whether it's non-NULL and
free it on every exit path, plus being careful about copying the
struct around), I've instead arranged that the structure contains a
function pointer and a couple of parameters, so that the string form
of the message can be constructed on demand. That way, the only users
who need to free it are the ones who actually _asked_ for it in the
first place, which is a much smaller set.
(This is one of the rare occasions that I regret not having C++'s
extra features available in this code base - a unique_ptr or
shared_ptr to a string would have been just the thing here, and the
compiler would have done all the hard work for me of remembering where
to insert the frees!)
2021-12-28 17:52:00 +00:00
|
|
|
SeatPromptResult win_seat_confirm_ssh_host_key(
|
2021-03-13 10:59:47 +00:00
|
|
|
Seat *seat, const char *host, int port, const char *keytype,
|
Centralise most details of host-key prompting.
The text of the host key warnings was replicated in three places: the
Windows rc file, the GTK dialog setup function, and the console.c
shared between both platforms' CLI tools. Now it lives in just one
place, namely ssh/common.c where the rest of the centralised host-key
checking is done, so it'll be easier to adjust the wording in future.
This comes with some extra automation. Paragraph wrapping is no longer
done by hand in any version of these prompts. (Previously we let GTK
do the wrapping on GTK, but on Windows the resource file contained a
bunch of pre-wrapped LTEXT lines, and console.c had pre-wrapped
terminal messages.) And the dialog heights in Windows are determined
automatically based on the amount of stuff in the window.
The main idea of all this is that it'll be easier to set up more
elaborate kinds of host key prompt that deal with certificates (if,
e.g., a server sends us a certified host key which we don't trust the
CA for). But there are side benefits of this refactoring too: each
tool now reliably inserts its own appname in the prompts, and also, on
Windows the entire prompt text is copy-pastable.
Details of implementation: there's a new type SeatDialogText which
holds a set of (type, string) pairs describing the contents of a
prompt. Type codes distinguish ordinary text paragraphs, paragraphs to
be displayed prominently (like key fingerprints), the extra-bold scary
title at the top of the 'host key changed' version of the dialog, and
the various information that lives in the subsidiary 'more info' box.
ssh/common.c constructs this, and passes it to the Seat to present the
actual prompt.
In order to deal with the different UI for answering the prompt, I've
added an extra Seat method 'prompt_descriptions' which returns some
snippets of text to interpolate into the messages. ssh/common.c calls
that while it's still constructing the text, and incorporates the
resulting snippets into the SeatDialogText.
For the moment, this refactoring only affects the host key prompts.
The warnings about outmoded crypto are still done the old-fashioned
way; they probably ought to be similarly refactored to use this new
SeatDialogText system, but it's not immediately critical for the
purpose I have right now.
2022-07-07 16:25:15 +00:00
|
|
|
char *keystr, SeatDialogText *text, HelpCtx helpctx,
|
Richer data type for interactive prompt results.
All the seat functions that request an interactive prompt of some kind
to the user - both the main seat_get_userpass_input and the various
confirmation dialogs for things like host keys - were using a simple
int return value, with the general semantics of 0 = "fail", 1 =
"proceed" (and in the case of seat_get_userpass_input, answers to the
prompts were provided), and -1 = "request in progress, wait for a
callback".
In this commit I change all those functions' return types to a new
struct called SeatPromptResult, whose primary field is an enum
replacing those simple integer values.
The main purpose is that the enum has not three but _four_ values: the
"fail" result has been split into 'user abort' and 'software abort'.
The distinction is that a user abort occurs as a result of an
interactive UI action, such as the user clicking 'cancel' in a dialog
box or hitting ^D or ^C at a terminal password prompt - and therefore,
there's no need to display an error message telling the user that the
interactive operation has failed, because the user already knows,
because they _did_ it. 'Software abort' is from any other cause, where
PuTTY is the first to know there was a problem, and has to tell the
user.
We already had this 'user abort' vs 'software abort' distinction in
other parts of the code - the SSH backend has separate termination
functions which protocol layers can call. But we assumed that any
failure from an interactive prompt request fell into the 'user abort'
category, which is not true. A couple of examples: if you configure a
host key fingerprint in your saved session via the SSH > Host keys
pane, and the server presents a host key that doesn't match it, then
verify_ssh_host_key would report that the user had aborted the
connection, and feel no need to tell the user what had gone wrong!
Similarly, if a password provided on the command line was not
accepted, then (after I fixed the semantics of that in the previous
commit) the same wrong handling would occur.
So now, those Seat prompt functions too can communicate whether the
user or the software originated a connection abort. And in the latter
case, we also provide an error message to present to the user. Result:
in those two example cases (and others), error messages should no
longer go missing.
Implementation note: to avoid the hassle of having the error message
in a SeatPromptResult being a dynamically allocated string (and hence,
every recipient of one must always check whether it's non-NULL and
free it on every exit path, plus being careful about copying the
struct around), I've instead arranged that the structure contains a
function pointer and a couple of parameters, so that the string form
of the message can be constructed on demand. That way, the only users
who need to free it are the ones who actually _asked_ for it in the
first place, which is a much smaller set.
(This is one of the rare occasions that I regret not having C++'s
extra features available in this code base - a unique_ptr or
shared_ptr to a string would have been just the thing here, and the
compiler would have done all the hard work for me of remembering where
to insert the frees!)
2021-12-28 17:52:00 +00:00
|
|
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
|
|
|
SeatPromptResult win_seat_confirm_weak_crypto_primitive(
|
2023-11-22 08:57:54 +00:00
|
|
|
Seat *seat, SeatDialogText *text,
|
Richer data type for interactive prompt results.
All the seat functions that request an interactive prompt of some kind
to the user - both the main seat_get_userpass_input and the various
confirmation dialogs for things like host keys - were using a simple
int return value, with the general semantics of 0 = "fail", 1 =
"proceed" (and in the case of seat_get_userpass_input, answers to the
prompts were provided), and -1 = "request in progress, wait for a
callback".
In this commit I change all those functions' return types to a new
struct called SeatPromptResult, whose primary field is an enum
replacing those simple integer values.
The main purpose is that the enum has not three but _four_ values: the
"fail" result has been split into 'user abort' and 'software abort'.
The distinction is that a user abort occurs as a result of an
interactive UI action, such as the user clicking 'cancel' in a dialog
box or hitting ^D or ^C at a terminal password prompt - and therefore,
there's no need to display an error message telling the user that the
interactive operation has failed, because the user already knows,
because they _did_ it. 'Software abort' is from any other cause, where
PuTTY is the first to know there was a problem, and has to tell the
user.
We already had this 'user abort' vs 'software abort' distinction in
other parts of the code - the SSH backend has separate termination
functions which protocol layers can call. But we assumed that any
failure from an interactive prompt request fell into the 'user abort'
category, which is not true. A couple of examples: if you configure a
host key fingerprint in your saved session via the SSH > Host keys
pane, and the server presents a host key that doesn't match it, then
verify_ssh_host_key would report that the user had aborted the
connection, and feel no need to tell the user what had gone wrong!
Similarly, if a password provided on the command line was not
accepted, then (after I fixed the semantics of that in the previous
commit) the same wrong handling would occur.
So now, those Seat prompt functions too can communicate whether the
user or the software originated a connection abort. And in the latter
case, we also provide an error message to present to the user. Result:
in those two example cases (and others), error messages should no
longer go missing.
Implementation note: to avoid the hassle of having the error message
in a SeatPromptResult being a dynamically allocated string (and hence,
every recipient of one must always check whether it's non-NULL and
free it on every exit path, plus being careful about copying the
struct around), I've instead arranged that the structure contains a
function pointer and a couple of parameters, so that the string form
of the message can be constructed on demand. That way, the only users
who need to free it are the ones who actually _asked_ for it in the
first place, which is a much smaller set.
(This is one of the rare occasions that I regret not having C++'s
extra features available in this code base - a unique_ptr or
shared_ptr to a string would have been just the thing here, and the
compiler would have done all the hard work for me of remembering where
to insert the frees!)
2021-12-28 17:52:00 +00:00
|
|
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
|
|
|
SeatPromptResult win_seat_confirm_weak_cached_hostkey(
|
2023-11-22 08:57:54 +00:00
|
|
|
Seat *seat, SeatDialogText *text,
|
Richer data type for interactive prompt results.
All the seat functions that request an interactive prompt of some kind
to the user - both the main seat_get_userpass_input and the various
confirmation dialogs for things like host keys - were using a simple
int return value, with the general semantics of 0 = "fail", 1 =
"proceed" (and in the case of seat_get_userpass_input, answers to the
prompts were provided), and -1 = "request in progress, wait for a
callback".
In this commit I change all those functions' return types to a new
struct called SeatPromptResult, whose primary field is an enum
replacing those simple integer values.
The main purpose is that the enum has not three but _four_ values: the
"fail" result has been split into 'user abort' and 'software abort'.
The distinction is that a user abort occurs as a result of an
interactive UI action, such as the user clicking 'cancel' in a dialog
box or hitting ^D or ^C at a terminal password prompt - and therefore,
there's no need to display an error message telling the user that the
interactive operation has failed, because the user already knows,
because they _did_ it. 'Software abort' is from any other cause, where
PuTTY is the first to know there was a problem, and has to tell the
user.
We already had this 'user abort' vs 'software abort' distinction in
other parts of the code - the SSH backend has separate termination
functions which protocol layers can call. But we assumed that any
failure from an interactive prompt request fell into the 'user abort'
category, which is not true. A couple of examples: if you configure a
host key fingerprint in your saved session via the SSH > Host keys
pane, and the server presents a host key that doesn't match it, then
verify_ssh_host_key would report that the user had aborted the
connection, and feel no need to tell the user what had gone wrong!
Similarly, if a password provided on the command line was not
accepted, then (after I fixed the semantics of that in the previous
commit) the same wrong handling would occur.
So now, those Seat prompt functions too can communicate whether the
user or the software originated a connection abort. And in the latter
case, we also provide an error message to present to the user. Result:
in those two example cases (and others), error messages should no
longer go missing.
Implementation note: to avoid the hassle of having the error message
in a SeatPromptResult being a dynamically allocated string (and hence,
every recipient of one must always check whether it's non-NULL and
free it on every exit path, plus being careful about copying the
struct around), I've instead arranged that the structure contains a
function pointer and a couple of parameters, so that the string form
of the message can be constructed on demand. That way, the only users
who need to free it are the ones who actually _asked_ for it in the
first place, which is a much smaller set.
(This is one of the rare occasions that I regret not having C++'s
extra features available in this code base - a unique_ptr or
shared_ptr to a string would have been just the thing here, and the
compiler would have done all the hard work for me of remembering where
to insert the frees!)
2021-12-28 17:52:00 +00:00
|
|
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
Centralise most details of host-key prompting.
The text of the host key warnings was replicated in three places: the
Windows rc file, the GTK dialog setup function, and the console.c
shared between both platforms' CLI tools. Now it lives in just one
place, namely ssh/common.c where the rest of the centralised host-key
checking is done, so it'll be easier to adjust the wording in future.
This comes with some extra automation. Paragraph wrapping is no longer
done by hand in any version of these prompts. (Previously we let GTK
do the wrapping on GTK, but on Windows the resource file contained a
bunch of pre-wrapped LTEXT lines, and console.c had pre-wrapped
terminal messages.) And the dialog heights in Windows are determined
automatically based on the amount of stuff in the window.
The main idea of all this is that it'll be easier to set up more
elaborate kinds of host key prompt that deal with certificates (if,
e.g., a server sends us a certified host key which we don't trust the
CA for). But there are side benefits of this refactoring too: each
tool now reliably inserts its own appname in the prompts, and also, on
Windows the entire prompt text is copy-pastable.
Details of implementation: there's a new type SeatDialogText which
holds a set of (type, string) pairs describing the contents of a
prompt. Type codes distinguish ordinary text paragraphs, paragraphs to
be displayed prominently (like key fingerprints), the extra-bold scary
title at the top of the 'host key changed' version of the dialog, and
the various information that lives in the subsidiary 'more info' box.
ssh/common.c constructs this, and passes it to the Seat to present the
actual prompt.
In order to deal with the different UI for answering the prompt, I've
added an extra Seat method 'prompt_descriptions' which returns some
snippets of text to interpolate into the messages. ssh/common.c calls
that while it's still constructing the text, and incorporates the
resulting snippets into the SeatDialogText.
For the moment, this refactoring only affects the host key prompts.
The warnings about outmoded crypto are still done the old-fashioned
way; they probably ought to be similarly refactored to use this new
SeatDialogText system, but it's not immediately critical for the
purpose I have right now.
2022-07-07 16:25:15 +00:00
|
|
|
const SeatDialogPromptDescriptions *win_seat_prompt_descriptions(Seat *seat);
|
2002-10-26 12:58:13 +00:00
|
|
|
|
2017-12-09 11:57:34 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* Windows-specific clipboard helper function shared with dialog.c,
|
2017-12-09 11:57:34 +00:00
|
|
|
* which takes the data string in the system code page instead of
|
|
|
|
* Unicode.
|
|
|
|
*/
|
2022-09-12 10:27:34 +00:00
|
|
|
void write_aclip(HWND hwnd, int clipboard, char *, int);
|
2017-12-09 11:57:34 +00:00
|
|
|
|
2005-08-10 18:31:24 +00:00
|
|
|
#define WM_NETEVENT (WM_APP + 5)
|
2002-10-07 16:45:23 +00:00
|
|
|
|
2002-10-13 11:24:25 +00:00
|
|
|
/*
|
|
|
|
* On Windows, we send MA_2CLK as the only event marking the second
|
2022-01-22 15:38:53 +00:00
|
|
|
* press of a mouse button. Compare unix/platform.h.
|
2002-10-13 11:24:25 +00:00
|
|
|
*/
|
|
|
|
#define MULTICLICK_ONLY_EVENT 1
|
|
|
|
|
|
|
|
/*
|
|
|
|
* On Windows, data written to the clipboard must be NUL-terminated.
|
|
|
|
*/
|
|
|
|
#define SELECTION_NUL_TERMINATED 1
|
|
|
|
|
2002-10-14 09:06:31 +00:00
|
|
|
/*
|
|
|
|
* On Windows, copying to the clipboard terminates lines with CRLF.
|
|
|
|
*/
|
|
|
|
#define SEL_NL { 13, 10 }
|
|
|
|
|
2003-01-11 09:31:54 +00:00
|
|
|
/*
|
|
|
|
* sk_getxdmdata() does not exist under Windows (not that I
|
|
|
|
* couldn't write it if I wanted to, but I haven't bothered), so
|
2005-01-28 11:39:45 +00:00
|
|
|
* it's a macro which always returns NULL. With any luck this will
|
2003-01-11 09:31:54 +00:00
|
|
|
* cause the compiler to notice it can optimise away the
|
2021-04-22 16:58:40 +00:00
|
|
|
* implementation of XDM-AUTHORIZATION-1 in ssh/x11fwd.c :-)
|
2003-01-11 09:31:54 +00:00
|
|
|
*/
|
2005-01-28 11:39:45 +00:00
|
|
|
#define sk_getxdmdata(socket, lenp) (NULL)
|
2003-01-11 09:31:54 +00:00
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
/*
|
|
|
|
* File-selector filter strings used in the config box. On Windows,
|
|
|
|
* these strings are of exactly the type needed to go in
|
|
|
|
* `lpstrFilter' in an OPENFILENAME structure.
|
|
|
|
*/
|
Some support for wide-character filenames in Windows.
The Windows version of the Filename structure now contains three
versions of the pathname, in UTF-16, UTF-8 and the system code page.
Callers can use whichever is most convenient.
All uses of filenames for actually opening files now use the UTF-16
version, which means they can tolerate 'exotic' filenames, by which I
mean those including Unicode characters outside the host system's
CP_ACP default code page.
Other uses of Filename structures inside the 'windows' subdirectory do
something appropriate, e.g. when printing a filename inside a message
box or a console message, we use the UTF-8 version of the filename
with the UTF-8 version of the appropriate API.
There are three remaining pieces to full Unicode filename support:
One is that the cross-platform code has many calls to
filename_to_str(), embodying the assumption that a file name can be
reliably converted into the unspecified current character set; those
will all need changing in some way.
Another is that write_setting_filename(), in windows/storage.c, still
saves filenames to the Registry as an ordinary REG_SZ in the system
code page. So even if an exotic filename were stored in a Conf, that
Conf couldn't round-trip via the Registry and back without corrupting
that filename by coercing it back to a string that fits in CP_ACP and
therefore doesn't represent the same file. This can't be fixed without
a compatibility break in the storage format, and I don't want to make
a minimal change in that area: if we're going to break compatibility,
then we should break it good and hard (the Nanny Ogg principle), and
devise a completely fresh storage representation that fixes as many
other legacy problems as possible at the same time. So that's my plan,
not yet started.
The final point, much more obviously, is that we're still short of
methods to _construct_ any Filename structures using a Unicode input
string! It should now work to enter one in the GUI configurer (either
by manual text input or via the file selector), but it won't
round-trip through a save and load (as discussed above), and there's
still no way to specify one on the command line (the groundwork is
laid by commit 10e1ac7752de928 but not yet linked up).
But this is a start.
2023-05-28 10:30:59 +00:00
|
|
|
typedef const wchar_t *FILESELECT_FILTER_TYPE;
|
|
|
|
#define FILTER_KEY_FILES (L"PuTTY Private Key Files (*.ppk)\0*.ppk\0" \
|
|
|
|
L"All Files (*.*)\0*\0\0\0")
|
|
|
|
#define FILTER_WAVE_FILES (L"Wave Files (*.wav)\0*.WAV\0" \
|
|
|
|
L"All Files (*.*)\0*\0\0\0")
|
|
|
|
#define FILTER_DYNLIB_FILES (L"Dynamic Library Files (*.dll)\0*.dll\0" \
|
|
|
|
L"All Files (*.*)\0*\0\0\0")
|
|
|
|
|
|
|
|
/* char-based versions of the above, for outlying uses of file selectors. */
|
|
|
|
#define FILTER_KEY_FILES_C ("PuTTY Private Key Files (*.ppk)\0*.ppk\0" \
|
|
|
|
"All Files (*.*)\0*\0\0\0")
|
|
|
|
#define FILTER_WAVE_FILES_C ("Wave Files (*.wav)\0*.WAV\0" \
|
|
|
|
"All Files (*.*)\0*\0\0\0")
|
|
|
|
#define FILTER_DYNLIB_FILES_C ("Dynamic Library Files (*.dll)\0*.dll\0" \
|
2019-09-08 19:29:00 +00:00
|
|
|
"All Files (*.*)\0*\0\0\0")
|
2003-03-05 22:07:40 +00:00
|
|
|
|
2013-08-17 16:06:35 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* Exports from network.c.
|
2013-08-17 16:06:35 +00:00
|
|
|
*/
|
2018-11-03 10:06:33 +00:00
|
|
|
/* Report an event notification from WSA*Select */
|
|
|
|
void select_result(WPARAM, LPARAM);
|
|
|
|
/* Enumerate all currently live OS-level SOCKETs */
|
|
|
|
SOCKET first_socket(int *);
|
|
|
|
SOCKET next_socket(int *);
|
2022-01-22 15:38:53 +00:00
|
|
|
/* Ask network.c whether we currently want to try to write to a SOCKET */
|
2018-11-03 10:06:33 +00:00
|
|
|
bool socket_writable(SOCKET skt);
|
|
|
|
/* Force a refresh of the SOCKET list by re-calling do_select for each one */
|
|
|
|
void socket_reselect_all(void);
|
|
|
|
/* Make a SockAddr which just holds a named pipe address. */
|
|
|
|
SockAddr *sk_namedpipe_addr(const char *pipename);
|
2020-01-01 11:10:22 +00:00
|
|
|
/* Turn a WinSock error code into a string. */
|
|
|
|
const char *winsock_error_string(int error);
|
2022-01-27 20:37:32 +00:00
|
|
|
Socket *sk_newlistener_unix(const char *socketpath, Plug *plug);
|
2013-08-17 16:06:35 +00:00
|
|
|
|
2003-10-12 13:46:12 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* network.c dynamically loads WinSock 2 or WinSock 1 depending on
|
2003-10-12 13:46:12 +00:00
|
|
|
* what it can get, which means any WinSock routines used outside
|
|
|
|
* that module must be exported from it as function pointers. So
|
|
|
|
* here they are.
|
|
|
|
*/
|
2020-02-02 10:00:43 +00:00
|
|
|
DECL_WINDOWS_FUNCTION(extern, int, WSAAsyncSelect,
|
2022-05-08 10:06:14 +00:00
|
|
|
(SOCKET, HWND, u_int, LONG));
|
2020-02-02 10:00:43 +00:00
|
|
|
DECL_WINDOWS_FUNCTION(extern, int, WSAEventSelect,
|
2022-05-08 10:06:14 +00:00
|
|
|
(SOCKET, WSAEVENT, LONG));
|
2020-02-02 10:00:43 +00:00
|
|
|
DECL_WINDOWS_FUNCTION(extern, int, WSAGetLastError, (void));
|
|
|
|
DECL_WINDOWS_FUNCTION(extern, int, WSAEnumNetworkEvents,
|
2019-09-08 19:29:00 +00:00
|
|
|
(SOCKET, WSAEVENT, LPWSANETWORKEVENTS));
|
2017-02-14 23:19:13 +00:00
|
|
|
#ifdef NEED_DECLARATION_OF_SELECT
|
|
|
|
/* This declaration is protected by an ifdef for the sake of building
|
|
|
|
* against winelib, in which you have to include winsock2.h before
|
|
|
|
* stdlib.h so that the right fd_set type gets defined. It would be a
|
|
|
|
* pain to do that throughout this codebase, so instead I arrange that
|
|
|
|
* only a modules actually needing to use (or define, or initialise)
|
|
|
|
* this function pointer will see its declaration, and _those_ modules
|
|
|
|
* - which will be Windows-specific anyway - can take more care. */
|
2020-02-02 10:00:43 +00:00
|
|
|
DECL_WINDOWS_FUNCTION(extern, int, select,
|
2019-09-08 19:29:00 +00:00
|
|
|
(int, fd_set FAR *, fd_set FAR *,
|
|
|
|
fd_set FAR *, const struct timeval FAR *));
|
2017-02-14 23:19:13 +00:00
|
|
|
#endif
|
2003-10-12 13:46:12 +00:00
|
|
|
|
2018-11-03 10:06:33 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* Implemented differently depending on the client of network.c, and
|
|
|
|
* called by network.c to turn on or off WSA*Select for a given socket.
|
2018-11-03 10:06:33 +00:00
|
|
|
*/
|
2020-01-01 15:46:59 +00:00
|
|
|
const char *do_select(SOCKET skt, bool enable);
|
2004-11-27 13:20:21 +00:00
|
|
|
|
2020-01-01 11:10:22 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* Exports from select-{gui,cli}.c, each of which provides an
|
2020-01-01 11:10:22 +00:00
|
|
|
* implementation of do_select.
|
|
|
|
*/
|
|
|
|
void winselgui_set_hwnd(HWND hwnd);
|
|
|
|
void winselgui_clear_hwnd(void);
|
2022-01-29 16:49:44 +00:00
|
|
|
void winselgui_response(WPARAM wParam, LPARAM lParam);
|
2020-01-01 11:10:22 +00:00
|
|
|
|
|
|
|
void winselcli_setup(void);
|
|
|
|
SOCKET winselcli_unique_socket(void);
|
|
|
|
extern HANDLE winselcli_event;
|
|
|
|
|
2018-11-03 10:06:33 +00:00
|
|
|
/*
|
|
|
|
* Network-subsystem-related functions provided in other Windows modules.
|
|
|
|
*/
|
|
|
|
Socket *make_handle_socket(HANDLE send_H, HANDLE recv_H, HANDLE stderr_H,
|
2021-09-13 13:34:46 +00:00
|
|
|
SockAddr *addr, int port, Plug *plug,
|
|
|
|
bool overlapped); /* winhsock */
|
Allow creating FdSocket/HandleSocket before the fds/handles.
Previously, a setup function returning one of these socket types (such
as platform_new_connection) had to do all its setup synchronously,
because if it was going to call make_fd_socket or make_handle_socket,
it had to have the actual fds or HANDLEs ready-made. If some kind of
asynchronous operation were needed before those fds become available,
there would be no way the function could achieve it, except by
becoming a whole extra permanent Socket wrapper layer.
Now there is, because you can make an FdSocket when you don't yet have
the fds, or a HandleSocket without the HANDLEs. Instead, you provide
an instance of the new trait 'DeferredSocketOpener', which is
responsible for setting in motion whatever asynchronous setup
procedure it needs, and when that finishes, calling back to
setup_fd_socket / setup_handle_socket to provide the missing pieces.
In the meantime, the FdSocket or HandleSocket will sit there inertly,
buffering any data the client might eagerly hand it via sk_write(),
and waiting for its setup to finish. When it does finish, buffered
data will be released.
In FdSocket, this is easy enough, because we were doing our own
buffering anyway - we called the uxsel system to find out when the fds
were readable/writable, and then wrote to them from our own bufchain.
So more or less all I had to do was make the try_send function do
nothing if the setup phase wasn't finished yet.
In HandleSocket, on the other hand, we're passing all our data to the
underlying handle-io.c system, and making _that_ deferrable in the
same way would be much more painful, because that's the place where
the scary threads live. So instead I've arranged it by replacing the
whole vtable, so that a deferred HandleSocket and a normal
HandleSocket are effectively separate trait implementations that can
share their state structure. And in fact that state struct itself now
contains a big anonymous union, containing one branch to go with each
vtable.
Nothing yet uses this system, but the next commit will do so.
2021-12-22 09:31:06 +00:00
|
|
|
Socket *make_deferred_handle_socket(DeferredSocketOpener *opener,
|
|
|
|
SockAddr *addr, int port, Plug *plug);
|
|
|
|
void setup_handle_socket(Socket *s, HANDLE send_H, HANDLE recv_H,
|
|
|
|
HANDLE stderr_H, bool overlapped);
|
2022-08-22 17:46:32 +00:00
|
|
|
void handle_socket_set_psb_prefix(Socket *s, const char *prefix);
|
2018-11-03 10:06:33 +00:00
|
|
|
Socket *new_named_pipe_client(const char *pipename, Plug *plug); /* winnpc */
|
|
|
|
Socket *new_named_pipe_listener(const char *pipename, Plug *plug); /* winnps */
|
2007-01-08 19:38:39 +00:00
|
|
|
|
2022-01-22 15:38:53 +00:00
|
|
|
/* A lower-level function in named-pipe-client.c, which does most of
|
|
|
|
* the work of new_named_pipe_client (including checking the ownership
|
|
|
|
* of what it's connected to), but returns a plain HANDLE instead of
|
|
|
|
* wrapping it into a Socket. */
|
2020-01-01 18:58:11 +00:00
|
|
|
HANDLE connect_to_named_pipe(const char *pipename, char **err);
|
|
|
|
|
2000-10-18 15:36:32 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* Exports from controls.c.
|
2000-10-18 15:36:32 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
struct ctlpos {
|
|
|
|
HWND hwnd;
|
|
|
|
WPARAM font;
|
|
|
|
int dlu4inpix;
|
|
|
|
int ypos, width;
|
|
|
|
int xoff;
|
2001-01-22 17:17:26 +00:00
|
|
|
int boxystart, boxid;
|
2022-07-30 13:12:32 +00:00
|
|
|
const char *boxtext;
|
2000-10-18 15:36:32 +00:00
|
|
|
};
|
2017-03-13 21:42:44 +00:00
|
|
|
void init_common_controls(void); /* also does some DLL-loading */
|
2000-10-18 15:36:32 +00:00
|
|
|
|
2002-08-04 21:18:56 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* Exports from utils.
|
2002-08-04 21:18:56 +00:00
|
|
|
*/
|
2005-02-28 02:40:43 +00:00
|
|
|
typedef struct filereq_tag filereq; /* cwd for file requester */
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool request_file(filereq *state, OPENFILENAME *of, bool preserve, bool save);
|
2023-05-29 14:30:57 +00:00
|
|
|
bool request_file_w(filereq *state, OPENFILENAMEW *of,
|
|
|
|
bool preserve, bool save);
|
2005-02-28 02:40:43 +00:00
|
|
|
filereq *filereq_new(void);
|
|
|
|
void filereq_free(filereq *state);
|
2020-02-02 10:00:42 +00:00
|
|
|
void pgp_fingerprints_msgbox(HWND owner);
|
2023-05-29 12:28:11 +00:00
|
|
|
int message_box(HWND owner, LPCTSTR text, LPCTSTR caption, DWORD style,
|
|
|
|
bool utf8, DWORD helpctxid);
|
2021-04-06 20:14:51 +00:00
|
|
|
void MakeDlgItemBorderless(HWND parent, int id);
|
2011-10-02 13:53:58 +00:00
|
|
|
char *GetDlgItemText_alloc(HWND hwnd, int id);
|
2023-05-29 12:31:14 +00:00
|
|
|
wchar_t *GetDlgItemTextW_alloc(HWND hwnd, int id);
|
2024-09-26 09:23:50 +00:00
|
|
|
/*
|
|
|
|
* The split_into_argv functions take a single string 'cmdline' (char
|
|
|
|
* or wide) to split up into arguments. They return an argc and argv
|
|
|
|
* pair, and also 'argstart', an array of pointers into the original
|
|
|
|
* command line, pointing at the place where each output argument
|
|
|
|
* begins. (Useful for retrieving the tail of the original command
|
|
|
|
* line corresponding to a certain argument onwards, or identifying a
|
|
|
|
* section of the original command line to blank out for privacy.)
|
|
|
|
*
|
|
|
|
* If the command line includes the program name (e.g. if it was
|
|
|
|
* returned from GetCommandLine()), set includes_program_name=true. If
|
|
|
|
* it doesn't (e.g. it was the arguments string received by WinMain),
|
|
|
|
* set that flag to false. This affects the rules for argument
|
|
|
|
* splitting, which is done differently in the program name
|
|
|
|
* (specifically, \ isn't special, and won't escape ").
|
|
|
|
*
|
|
|
|
* Mutability: the argv[] words are in fresh dynamically allocated
|
|
|
|
* memory, so you can write into them safely. The original cmdline is
|
|
|
|
* passed in as a const pointer, and not modified in this function.
|
|
|
|
* But the pointers into that string written into argstart have the
|
|
|
|
* type of a mutable char *. Similarly to strchr, this is due to the
|
|
|
|
* limitation of C that you can't specify argstart as having the same
|
|
|
|
* constness as cmdline: the idea is that you either pass a
|
|
|
|
* non-mutable cmdline and promise not to write through the argstart
|
|
|
|
* pointers, of you pass a mutable one and are free to write through
|
|
|
|
* it.
|
|
|
|
*
|
|
|
|
* Allocation: argv and argstart are dynamically allocated. There's
|
|
|
|
* also a dynamically allocated string behind the scenes storing the
|
|
|
|
* actual strings. argv[0] guarantees to point at the first character
|
|
|
|
* of that. So to free all the memory allocated by this function, you
|
|
|
|
* must free argv[0], then argv, and also argstart.
|
|
|
|
*/
|
|
|
|
void split_into_argv(const char *cmdline, bool includes_program_name,
|
|
|
|
int *argc, char ***argv, char ***argstart);
|
|
|
|
void split_into_argv_w(const wchar_t *cmdline, bool includes_program_name,
|
|
|
|
int *argc, wchar_t ***argv, wchar_t ***argstart);
|
2002-08-04 21:18:56 +00:00
|
|
|
|
2001-08-25 19:33:33 +00:00
|
|
|
/*
|
|
|
|
* Private structure for prefslist state. Only in the header file
|
|
|
|
* so that we can delegate allocation to callers.
|
|
|
|
*/
|
|
|
|
struct prefslist {
|
|
|
|
int listid, upbid, dnbid;
|
|
|
|
int srcitem;
|
|
|
|
int dummyitem;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool dragging;
|
2001-08-25 19:33:33 +00:00
|
|
|
};
|
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
/*
|
|
|
|
* This structure is passed to event handler functions as the `dlg'
|
|
|
|
* parameter, and hence is passed back to winctrls access functions.
|
|
|
|
*/
|
|
|
|
struct dlgparam {
|
2019-09-08 19:29:00 +00:00
|
|
|
HWND hwnd; /* the hwnd of the dialog box */
|
2003-03-05 22:07:40 +00:00
|
|
|
struct winctrls *controltrees[8]; /* can have several of these */
|
|
|
|
int nctrltrees;
|
2019-09-08 19:29:00 +00:00
|
|
|
char *wintitle; /* title of actual window */
|
|
|
|
char *errtitle; /* title of error sub-messageboxes */
|
|
|
|
void *data; /* data to pass in refresh events */
|
2022-05-01 08:48:38 +00:00
|
|
|
dlgcontrol *focused, *lastfocused; /* which ctrl has focus now/before */
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool shortcuts[128]; /* track which shortcuts in use */
|
|
|
|
bool coloursel_wanted; /* has an event handler asked for
|
2019-09-08 19:29:00 +00:00
|
|
|
* a colour selector? */
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
struct {
|
|
|
|
unsigned char r, g, b; /* 0-255 */
|
|
|
|
bool ok;
|
|
|
|
} coloursel_result;
|
2019-09-08 19:29:00 +00:00
|
|
|
tree234 *privdata; /* stores per-control private data */
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool ended; /* has the dialog been ended? */
|
|
|
|
int endresult; /* and if so, what was the result? */
|
|
|
|
bool fixed_pitch_fonts; /* are we constrained to fixed fonts? */
|
2003-03-05 22:07:40 +00:00
|
|
|
};
|
|
|
|
|
2002-10-07 16:45:23 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* Exports from controls.c.
|
2002-10-07 16:45:23 +00:00
|
|
|
*/
|
2000-10-18 15:36:32 +00:00
|
|
|
void ctlposinit(struct ctlpos *cp, HWND hwnd,
|
2019-09-08 19:29:00 +00:00
|
|
|
int leftborder, int rightborder, int topborder);
|
2022-07-30 13:12:32 +00:00
|
|
|
HWND doctl(struct ctlpos *cp, RECT r, const char *wclass, int wstyle,
|
|
|
|
int exstyle, const char *wtext, int wid);
|
|
|
|
void bartitle(struct ctlpos *cp, const char *name, int id);
|
|
|
|
void beginbox(struct ctlpos *cp, const char *name, int idbox);
|
2000-10-18 15:36:32 +00:00
|
|
|
void endbox(struct ctlpos *cp);
|
2022-07-30 13:12:32 +00:00
|
|
|
void editboxfw(struct ctlpos *cp, bool password, bool readonly,
|
|
|
|
const char *text, int staticid, int editid);
|
|
|
|
void radioline(struct ctlpos *cp, const char *text, int id, int nacross, ...);
|
2001-08-08 20:44:35 +00:00
|
|
|
void bareradioline(struct ctlpos *cp, int nacross, ...);
|
2022-07-30 13:12:32 +00:00
|
|
|
void radiobig(struct ctlpos *cp, const char *text, int id, ...);
|
|
|
|
void checkbox(struct ctlpos *cp, const char *text, int id);
|
2022-07-30 13:41:08 +00:00
|
|
|
void button(struct ctlpos *cp, const char *btext, int bid, bool defbtn);
|
2022-07-30 13:12:32 +00:00
|
|
|
void statictext(struct ctlpos *cp, const char *text, int lines, int id);
|
|
|
|
void staticbtn(struct ctlpos *cp, const char *stext, int sid,
|
|
|
|
const char *btext, int bid);
|
|
|
|
void static2btn(struct ctlpos *cp, const char *stext, int sid,
|
|
|
|
const char *btext1, int bid1, const char *btext2, int bid2);
|
|
|
|
void staticedit(struct ctlpos *cp, const char *stext,
|
2019-09-08 19:29:00 +00:00
|
|
|
int sid, int eid, int percentedit);
|
2022-07-30 13:12:32 +00:00
|
|
|
void staticddl(struct ctlpos *cp, const char *stext,
|
2019-09-08 19:29:00 +00:00
|
|
|
int sid, int lid, int percentlist);
|
2022-07-30 13:12:32 +00:00
|
|
|
void combobox(struct ctlpos *cp, const char *text, int staticid, int listid);
|
|
|
|
void staticpassedit(struct ctlpos *cp, const char *stext,
|
2019-09-08 19:29:00 +00:00
|
|
|
int sid, int eid, int percentedit);
|
2022-07-30 13:12:32 +00:00
|
|
|
void bigeditctrl(struct ctlpos *cp, const char *stext,
|
2019-09-08 19:29:00 +00:00
|
|
|
int sid, int eid, int lines);
|
2022-07-30 13:12:32 +00:00
|
|
|
void ersatztab(struct ctlpos *cp, const char *stext, int sid, int lid,
|
|
|
|
int s2id);
|
|
|
|
void editbutton(struct ctlpos *cp, const char *stext, int sid,
|
|
|
|
int eid, const char *btext, int bid);
|
|
|
|
void sesssaver(struct ctlpos *cp, const char *text,
|
2019-09-08 19:29:00 +00:00
|
|
|
int staticid, int editid, int listid, ...);
|
2022-07-30 13:12:32 +00:00
|
|
|
void envsetter(struct ctlpos *cp, const char *stext, int sid,
|
|
|
|
const char *e1stext, int e1sid, int e1id,
|
|
|
|
const char *e2stext, int e2sid, int e2id,
|
|
|
|
int listid, const char *b1text, int b1id,
|
|
|
|
const char *b2text, int b2id);
|
|
|
|
void charclass(struct ctlpos *cp, const char *stext, int sid, int listid,
|
|
|
|
const char *btext, int bid, int eid, const char *s2text,
|
|
|
|
int s2id);
|
|
|
|
void colouredit(struct ctlpos *cp, const char *stext, int sid, int listid,
|
|
|
|
const char *btext, int bid, ...);
|
2003-03-05 22:07:40 +00:00
|
|
|
void prefslist(struct prefslist *hdl, struct ctlpos *cp, int lines,
|
2022-07-30 13:12:32 +00:00
|
|
|
const char *stext, int sid, int listid, int upbid, int dnbid);
|
2001-08-25 19:33:33 +00:00
|
|
|
int handle_prefslist(struct prefslist *hdl,
|
2019-09-08 19:29:00 +00:00
|
|
|
int *array, int maxmemb,
|
|
|
|
bool is_dlmsg, HWND hwnd,
|
|
|
|
WPARAM wParam, LPARAM lParam);
|
2000-10-19 15:43:08 +00:00
|
|
|
void progressbar(struct ctlpos *cp, int id);
|
2022-07-30 13:12:32 +00:00
|
|
|
void fwdsetter(struct ctlpos *cp, int listid, const char *stext, int sid,
|
|
|
|
const char *e1stext, int e1sid, int e1id,
|
|
|
|
const char *e2stext, int e2sid, int e2id,
|
|
|
|
const char *btext, int bid,
|
|
|
|
const char *r1text, int r1id, const char *r2text, int r2id);
|
2002-10-07 16:45:23 +00:00
|
|
|
|
2018-09-13 11:58:44 +00:00
|
|
|
void dlg_auto_set_fixed_pitch_flag(dlgparam *dlg);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool dlg_get_fixed_pitch_flag(dlgparam *dlg);
|
|
|
|
void dlg_set_fixed_pitch_flag(dlgparam *dlg, bool flag);
|
2010-12-29 14:11:25 +00:00
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
#define MAX_SHORTCUTS_PER_CTRL 16
|
|
|
|
|
|
|
|
/*
|
2022-05-01 08:48:38 +00:00
|
|
|
* This structure is what's stored for each `dlgcontrol' in the
|
2003-03-05 22:07:40 +00:00
|
|
|
* portable-dialog interface.
|
|
|
|
*/
|
|
|
|
struct winctrl {
|
2022-05-01 08:48:38 +00:00
|
|
|
dlgcontrol *ctrl;
|
2003-03-05 22:07:40 +00:00
|
|
|
/*
|
|
|
|
* The control may have several components at the Windows
|
|
|
|
* level, with different dialog IDs. To avoid needing N
|
|
|
|
* separate platformsidectrl structures (which could be stored
|
|
|
|
* separately in a tree234 so that lookup by ID worked), we
|
|
|
|
* impose the constraint that those IDs must be in a contiguous
|
|
|
|
* block.
|
|
|
|
*/
|
|
|
|
int base_id;
|
|
|
|
int num_ids;
|
2021-04-03 16:45:31 +00:00
|
|
|
/*
|
|
|
|
* For vertical alignment, the id of a particular representative
|
|
|
|
* control that has the y-extent of the sensible part of the
|
|
|
|
* control.
|
|
|
|
*/
|
|
|
|
int align_id;
|
2003-03-05 22:07:40 +00:00
|
|
|
/*
|
|
|
|
* Remember what keyboard shortcuts were used by this control,
|
|
|
|
* so that when we remove it again we can take them out of the
|
|
|
|
* list in the dlgparam.
|
|
|
|
*/
|
|
|
|
char shortcuts[MAX_SHORTCUTS_PER_CTRL];
|
|
|
|
/*
|
|
|
|
* Some controls need a piece of allocated memory in which to
|
|
|
|
* store temporary data about the control.
|
|
|
|
*/
|
|
|
|
void *data;
|
|
|
|
};
|
|
|
|
/*
|
|
|
|
* And this structure holds a set of the above, in two separate
|
2022-05-01 08:48:38 +00:00
|
|
|
* tree234s so that it can find an item by `dlgcontrol' or by
|
2003-03-05 22:07:40 +00:00
|
|
|
* dialog ID.
|
|
|
|
*/
|
|
|
|
struct winctrls {
|
|
|
|
tree234 *byctrl, *byid;
|
|
|
|
};
|
2003-03-06 12:41:39 +00:00
|
|
|
struct controlset;
|
|
|
|
struct controlbox;
|
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
void winctrl_init(struct winctrls *);
|
|
|
|
void winctrl_cleanup(struct winctrls *);
|
|
|
|
void winctrl_add(struct winctrls *, struct winctrl *);
|
|
|
|
void winctrl_remove(struct winctrls *, struct winctrl *);
|
2022-05-01 08:48:38 +00:00
|
|
|
struct winctrl *winctrl_findbyctrl(struct winctrls *, dlgcontrol *);
|
2003-03-05 22:07:40 +00:00
|
|
|
struct winctrl *winctrl_findbyid(struct winctrls *, int);
|
|
|
|
struct winctrl *winctrl_findbyindex(struct winctrls *, int);
|
|
|
|
void winctrl_layout(struct dlgparam *dp, struct winctrls *wc,
|
2019-09-08 19:29:00 +00:00
|
|
|
struct ctlpos *cp, struct controlset *s, int *id);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool winctrl_handle_command(struct dlgparam *dp, UINT msg,
|
|
|
|
WPARAM wParam, LPARAM lParam);
|
2003-03-06 12:41:39 +00:00
|
|
|
void winctrl_rem_shortcuts(struct dlgparam *dp, struct winctrl *c);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool winctrl_context_help(struct dlgparam *dp, HWND hwnd, int id);
|
2003-03-06 12:41:39 +00:00
|
|
|
|
2003-03-08 11:46:42 +00:00
|
|
|
void dp_init(struct dlgparam *dp);
|
|
|
|
void dp_add_tree(struct dlgparam *dp, struct winctrls *tree);
|
|
|
|
void dp_cleanup(struct dlgparam *dp);
|
|
|
|
|
2003-03-06 12:41:39 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* Exports from config.c.
|
2003-03-06 12:41:39 +00:00
|
|
|
*/
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
void win_setup_config_box(struct controlbox *b, HWND *hwndp, bool has_help,
|
2019-09-08 19:29:00 +00:00
|
|
|
bool midsession, int protocol);
|
2003-03-05 22:07:40 +00:00
|
|
|
|
2002-10-07 16:45:23 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* Exports from dialog.c.
|
2002-10-07 16:45:23 +00:00
|
|
|
*/
|
|
|
|
void defuse_showwindow(void);
|
2020-02-02 10:00:42 +00:00
|
|
|
bool do_config(Conf *);
|
|
|
|
bool do_reconfig(HWND, Conf *, int);
|
2002-10-07 16:45:23 +00:00
|
|
|
void showeventlog(HWND);
|
|
|
|
void showabout(HWND);
|
|
|
|
void force_normal(HWND hwnd);
|
2003-03-06 12:41:39 +00:00
|
|
|
void modal_about_box(HWND hwnd);
|
|
|
|
void show_help(HWND hwnd);
|
2020-02-02 10:00:42 +00:00
|
|
|
HWND event_log_window(void);
|
2002-10-07 16:45:23 +00:00
|
|
|
|
2003-06-16 23:55:26 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* Exports from utils.
|
2003-06-16 23:55:26 +00:00
|
|
|
*/
|
Remove remaining uses of the GLOBAL macro.
We now have no remaining things in header files that switch from being
a declaration to a definition depending on an awkward #define at the
point of including that header. There are still a few mutable
variables with external linkage, but at least now each one is defined
in a specific source file file appropriate to its purpose and context.
The remaining globals as of this commit were:
- 'logctx' and 'term', which never needed to be globals in the first
place, because they were never actually shared between source
files. Now 'term' is just a static in window.c, and 'logctx' is a
static in each of that and winplink.c.
- 'hinst', which still has external linkage, but is now defined
separately in each source file that sets it up (i.e. those with a
WinMain)
- osMajorVersion, osMinorVersion and osPlatformId, whose definitions
now live in winmisc.c alongside the code which sets them up.
(Actually they were defined there all along, it turns out, but
every toolchain I've built with has commoned them together with the
version defined by the GLOBAL in the header.)
- 'hwnd', which nothing was actually _using_ any more after previous
commits, so all this commit had to do was delete it.
2020-02-02 10:00:43 +00:00
|
|
|
extern DWORD osMajorVersion, osMinorVersion, osPlatformId;
|
2018-06-03 14:05:44 +00:00
|
|
|
void init_winver(void);
|
2016-07-18 19:02:32 +00:00
|
|
|
void dll_hijacking_protection(void);
|
2021-04-24 16:15:47 +00:00
|
|
|
const char *get_system_dir(void);
|
2010-09-13 08:29:45 +00:00
|
|
|
HMODULE load_system32_dll(const char *libname);
|
2013-07-22 07:11:39 +00:00
|
|
|
const char *win_strerror(int error);
|
2022-03-12 15:02:12 +00:00
|
|
|
bool should_have_security(void);
|
2017-01-28 21:56:28 +00:00
|
|
|
void restrict_process_acl(void);
|
2020-02-02 10:00:42 +00:00
|
|
|
bool restricted_acl(void);
|
Rework mungestr() and unmungestr().
For a start, they now have different names on Windows and Unix,
reflecting their different roles: on Windows they apply escaping to
any string that's going to be used as a registry key (be it a session
name, or a host name for host key storage), whereas on Unix they're
for constructing saved-session file names in particular (and also
handle the special case of filling in "Default Settings" for NULL).
Also, they now produce output by writing to a strbuf, which simplifies
a lot of the call sites. In particular, the strbuf output idiom is
passed on to enum_settings_next, which is especially nice because its
only actual caller was doing an ad-hoc realloc loop that I can now get
rid of completely.
Thirdly, on Windows they're centralised into winmisc.c instead of
living in winstore.c, because that way Pageant can use the unescape
function too. (It was spotting the duplication there that made me
think of doing this in the first place, but once I'd started, I had to
keep unravelling the thread...)
2018-11-03 08:58:41 +00:00
|
|
|
void escape_registry_key(const char *in, strbuf *out);
|
|
|
|
void unescape_registry_key(const char *in, strbuf *out);
|
2003-08-21 19:48:45 +00:00
|
|
|
|
2019-02-20 06:54:51 +00:00
|
|
|
bool is_console_handle(HANDLE);
|
|
|
|
|
2017-04-03 19:30:18 +00:00
|
|
|
/* A few pieces of up-to-date Windows API definition needed for older
|
|
|
|
* compilers. */
|
|
|
|
#ifndef LOAD_LIBRARY_SEARCH_SYSTEM32
|
|
|
|
#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
|
|
|
|
#endif
|
|
|
|
#ifndef LOAD_LIBRARY_SEARCH_USER_DIRS
|
|
|
|
#define LOAD_LIBRARY_SEARCH_USER_DIRS 0x00000400
|
|
|
|
#endif
|
|
|
|
#ifndef LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
|
|
|
|
#define LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR 0x00000100
|
|
|
|
#endif
|
2017-05-24 19:34:38 +00:00
|
|
|
#ifndef DLL_DIRECTORY_COOKIE
|
2017-04-03 19:30:18 +00:00
|
|
|
typedef PVOID DLL_DIRECTORY_COOKIE;
|
2017-05-24 19:34:38 +00:00
|
|
|
DECLSPEC_IMPORT DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory (PCWSTR NewDirectory);
|
2017-04-03 19:30:18 +00:00
|
|
|
#endif
|
|
|
|
|
2002-10-07 16:45:23 +00:00
|
|
|
/*
|
|
|
|
* Exports from sizetip.c.
|
|
|
|
*/
|
|
|
|
void UpdateSizeTip(HWND src, int cx, int cy);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
void EnableSizeTip(bool bEnable);
|
2002-10-07 16:45:23 +00:00
|
|
|
|
2003-01-01 22:25:25 +00:00
|
|
|
/*
|
|
|
|
* Exports from unicode.c.
|
|
|
|
*/
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
void init_ucs(Conf *, struct unicode_data *);
|
2003-01-01 22:25:25 +00:00
|
|
|
|
2006-08-25 22:10:16 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* Exports from handle-io.c.
|
2006-08-25 22:10:16 +00:00
|
|
|
*/
|
2006-08-27 10:00:36 +00:00
|
|
|
#define HANDLE_FLAG_OVERLAPPED 1
|
|
|
|
#define HANDLE_FLAG_IGNOREEOF 2
|
2006-08-28 18:27:54 +00:00
|
|
|
#define HANDLE_FLAG_UNITBUFFER 4
|
2006-08-25 22:10:16 +00:00
|
|
|
struct handle;
|
2019-02-06 20:42:44 +00:00
|
|
|
typedef size_t (*handle_inputfn_t)(
|
|
|
|
struct handle *h, const void *data, size_t len, int err);
|
2019-02-06 20:36:11 +00:00
|
|
|
typedef void (*handle_outputfn_t)(
|
handle_write_eof: delegate CloseHandle back to the client.
When a writable HANDLE is managed by the handle-io.c system, you ask
to send EOF on the handle by calling handle_write_eof. That waits
until all buffered data has been written, and then sends an EOF event
by simply closing the handle.
That is, of course, the only way to send an EOF signal on a handle at
all. And yet, it's a bug, because the handle_output system does not
take ownership of the handle you give it: the client of handle_output
retains ownership, keeps its own copy of the handle, and will expect
to close it itself.
In most cases, the extra close will harmlessly fail, and return
ERROR_INVALID_HANDLE (which the caller didn't notice anyway). But if
you're unlucky, in conditions of frantic handle opening and closing
(e.g. with a lot of separate named-pipe-style agent forwarding
connections being constantly set up and torn down), the handle value
might have been reused between the two closes, so that the second
CloseHandle closes an unrelated handle belonging to some other part of
the program.
We can't fix this by giving handle_output permanent ownership of the
handle, because it really _is_ necessary for copies of it to survive
elsewhere: in particular, for a bidirectional file such as a serial
port or named pipe, the reading side also needs a copy of the same
handle! And yet, we can't replace the handle_write_eof call in the
client with a direct CloseHandle, because that won't wait until
buffered output has been drained.
The solution is that the client still calls handle_write_eof to
register that it _wants_ an EOF sent; the handle_output system will
wait until it's ready, but then, instead of calling CloseHandle, it
will ask its _client_ to close the handle, by calling the provided
'sentdata' callback with the new 'close' flag set to true. And then
the client can not only close the handle, but do whatever else it
needs to do to record that that has been done.
2021-09-30 18:16:20 +00:00
|
|
|
struct handle *h, size_t new_backlog, int err, bool close);
|
2006-08-26 07:41:15 +00:00
|
|
|
struct handle *handle_input_new(HANDLE handle, handle_inputfn_t gotdata,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *privdata, int flags);
|
2006-08-26 07:41:15 +00:00
|
|
|
struct handle *handle_output_new(HANDLE handle, handle_outputfn_t sentdata,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *privdata, int flags);
|
2019-02-06 20:42:44 +00:00
|
|
|
size_t handle_write(struct handle *h, const void *data, size_t len);
|
2011-09-13 11:44:03 +00:00
|
|
|
void handle_write_eof(struct handle *h);
|
2006-08-25 22:10:16 +00:00
|
|
|
void handle_free(struct handle *h);
|
2019-02-06 20:42:44 +00:00
|
|
|
void handle_unthrottle(struct handle *h, size_t backlog);
|
|
|
|
size_t handle_backlog(struct handle *h);
|
2006-08-26 07:41:15 +00:00
|
|
|
void *handle_get_privdata(struct handle *h);
|
2019-02-20 06:52:54 +00:00
|
|
|
/* Analogue of stdio_sink in marshal.h, for a Windows handle */
|
|
|
|
struct handle_sink {
|
|
|
|
struct handle *h;
|
|
|
|
BinarySink_IMPLEMENTATION;
|
|
|
|
};
|
|
|
|
void handle_sink_init(handle_sink *sink, struct handle *h);
|
2006-08-25 22:10:16 +00:00
|
|
|
|
Reorganise Windows HANDLE management.
Before commit 6e69223dc262755, Pageant would stop working after a
certain number of PuTTYs were active at the same time. (At most about
60, but maybe fewer - see below.)
This was because of two separate bugs. The easy one, fixed in
6e69223dc262755 itself, was that PuTTY left each named-pipe connection
to Pageant open for the rest of its lifetime. So the real problem was
that Pageant had too many active connections at once. (And since a
given PuTTY might make multiple connections during userauth - one to
list keys, and maybe another to actually make a signature - that was
why the number of _PuTTYs_ might vary.)
It was clearly a bug that PuTTY was leaving connections to Pageant
needlessly open. But it was _also_ a bug that Pageant couldn't handle
more than about 60 at once. In this commit, I fix that secondary bug.
The cause of the bug is that the WaitForMultipleObjects function
family in the Windows API have a limit on the number of HANDLE objects
they can select between. The limit is MAXIMUM_WAIT_OBJECTS, defined to
be 64. And handle-io.c was using a separate event object for each I/O
subthread to communicate back to the main thread, so as soon as all
those event objects (plus a handful of other HANDLEs) added up to more
than 64, we'd start passing an overlarge handle array to
WaitForMultipleObjects, and it would start not doing what we wanted.
To fix this, I've reorganised handle-io.c so that all its subthreads
share just _one_ event object to signal readiness back to the main
thread. There's now a linked list of 'struct handle' objects that are
ready to be processed, protected by a CRITICAL_SECTION. Each subthread
signals readiness by adding itself to the linked list, and setting the
event object to indicate that the list is now non-empty. When the main
thread receives the event, it iterates over the whole list processing
all the ready handles.
(Each 'struct handle' still has a separate event object for the main
thread to use to communicate _to_ the subthread. That's OK, because no
thread is ever waiting on all those events at once: each subthread
only waits on its own.)
The previous HT_FOREIGN system didn't really fit into this framework.
So I've moved it out into its own system. There's now a handle-wait.c
which deals with the relatively simple job of managing a list of
handles that need to be waited for, each with a callback function;
that's what communicates a list of HANDLEs to event loops, and
receives the notification when the event loop notices that one of them
has done something. And handle-io.c is now just one client of
handle-wait.c, providing a single HANDLE to the event loop, and
dealing internally with everything that needs to be done when that
handle fires.
The new top-level handle-wait.c system *still* can't deal with more
than MAXIMUM_WAIT_OBJECTS. At the moment, I'm reasonably convinced it
doesn't need to: the only kind of HANDLE that any of our tools could
previously have needed to wait on more than one of was the one in
handle-io.c that I've just removed. But I've left some assertions and
a TODO comment in there just in case we need to change that in future.
2021-05-24 12:06:10 +00:00
|
|
|
/*
|
|
|
|
* Exports from handle-wait.c.
|
|
|
|
*/
|
|
|
|
typedef struct HandleWait HandleWait;
|
|
|
|
typedef void (*handle_wait_callback_fn_t)(void *);
|
|
|
|
HandleWait *add_handle_wait(HANDLE h, handle_wait_callback_fn_t callback,
|
|
|
|
void *callback_ctx);
|
|
|
|
void delete_handle_wait(HandleWait *hw);
|
|
|
|
|
|
|
|
typedef struct HandleWaitList {
|
|
|
|
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
|
|
|
|
int nhandles;
|
|
|
|
} HandleWaitList;
|
|
|
|
HandleWaitList *get_handle_wait_list(void);
|
|
|
|
void handle_wait_activate(HandleWaitList *hwl, int index);
|
|
|
|
void handle_wait_list_free(HandleWaitList *hwl);
|
|
|
|
|
2020-01-01 15:55:06 +00:00
|
|
|
/*
|
Windows Pageant: make atomic client/server decision.
In the previous state of the code, we first tested agent_exists() to
decide whether to be the long-running Pageant server or a short-lived
client; then, during the command-line parsing loop, we prompted for
passphrases to add keys presented on the command line (to ourself or
the server, respectively); *then* we set up the named pipe and
WM_COPYDATA receiver window to actually start functioning as a server,
if we decided that was our role.
A consequence is that if a user started up two Pageants each with an
encrypted key on the command line, there would be a race condition:
each one would decide that it was _going_ to be the server, then
prompt for a passphrase, and then try to set itself up as the server
once the passphrase is entered. So whichever one's passphrase prompt
was answered second would add its key to its own internal data
structures, then fail to set up the server's named pipe, terminate
with an error, and end up not having added its key to the _surviving_
server.
This change reorders the setup steps so that the command-line parsing
loop does not add the keys immediately; instead it merely caches the
key filenames provided. Then we make the decision about whether we're
the server, and set up both the named pipe and WM_COPYDATA window if
we are; and finally, we go back to our list of key filenames and
actually add them, either to ourself (if we're the server) or to some
other Pageant (if we're a client).
Moreover, the decision about whether to be the server is now wrapped
in an interprocess mutex similar to the one used in connection
sharing, which means that even if two or more Pageants are started up
as close to simultaneously as possible, they should avoid a race
condition and successfully manage to agree on exactly one of
themselves to be the server. For example, a user reported that this
could occur if you put shortcuts to multiple private key files in your
Windows Startup folder, so that they were all launched simultaneously
at startup.
One slightly odd behaviour that remains: if the server Pageant has to
prompt for private key passphrases at startup, then it won't actually
start _servicing_ requests from other Pageants until it's finished
dealing with its own prompts. As a result, if you do start up two
Pageants at once each with an encrypted key file on its command line,
the second one won't even manage to present its passphrase prompt
until the first one's prompt is dismissed, because it will block
waiting for the initial check of the key list. But it will get there
in the end, so that's only a cosmetic oddity.
It would be nice to arrange that Pageant GUI operations don't block
unrelated agent requests (e.g. by having the GUI and the agent code
run in separate threads). But that's a bigger problem, not specific to
startup time - the same thing happens if you interactively load a key
via Pageant's file dialog. And it would require a major reorganisation
to fix that fully, because currently the GUI code depends on being
able to call _internal_ Pageant query functions like
pageant_count_ssh2_keys() that don't work by constructing an agent
request at all.
2022-01-03 12:17:15 +00:00
|
|
|
* Pageant-related pathnames.
|
2020-01-01 15:55:06 +00:00
|
|
|
*/
|
Windows Pageant: make atomic client/server decision.
In the previous state of the code, we first tested agent_exists() to
decide whether to be the long-running Pageant server or a short-lived
client; then, during the command-line parsing loop, we prompted for
passphrases to add keys presented on the command line (to ourself or
the server, respectively); *then* we set up the named pipe and
WM_COPYDATA receiver window to actually start functioning as a server,
if we decided that was our role.
A consequence is that if a user started up two Pageants each with an
encrypted key on the command line, there would be a race condition:
each one would decide that it was _going_ to be the server, then
prompt for a passphrase, and then try to set itself up as the server
once the passphrase is entered. So whichever one's passphrase prompt
was answered second would add its key to its own internal data
structures, then fail to set up the server's named pipe, terminate
with an error, and end up not having added its key to the _surviving_
server.
This change reorders the setup steps so that the command-line parsing
loop does not add the keys immediately; instead it merely caches the
key filenames provided. Then we make the decision about whether we're
the server, and set up both the named pipe and WM_COPYDATA window if
we are; and finally, we go back to our list of key filenames and
actually add them, either to ourself (if we're the server) or to some
other Pageant (if we're a client).
Moreover, the decision about whether to be the server is now wrapped
in an interprocess mutex similar to the one used in connection
sharing, which means that even if two or more Pageants are started up
as close to simultaneously as possible, they should avoid a race
condition and successfully manage to agree on exactly one of
themselves to be the server. For example, a user reported that this
could occur if you put shortcuts to multiple private key files in your
Windows Startup folder, so that they were all launched simultaneously
at startup.
One slightly odd behaviour that remains: if the server Pageant has to
prompt for private key passphrases at startup, then it won't actually
start _servicing_ requests from other Pageants until it's finished
dealing with its own prompts. As a result, if you do start up two
Pageants at once each with an encrypted key file on its command line,
the second one won't even manage to present its passphrase prompt
until the first one's prompt is dismissed, because it will block
waiting for the initial check of the key list. But it will get there
in the end, so that's only a cosmetic oddity.
It would be nice to arrange that Pageant GUI operations don't block
unrelated agent requests (e.g. by having the GUI and the agent code
run in separate threads). But that's a bigger problem, not specific to
startup time - the same thing happens if you interactively load a key
via Pageant's file dialog. And it would require a major reorganisation
to fix that fully, because currently the GUI code depends on being
able to call _internal_ Pageant query functions like
pageant_count_ssh2_keys() that don't work by constructing an agent
request at all.
2022-01-03 12:17:15 +00:00
|
|
|
char *agent_mutex_name(void);
|
2020-01-01 15:55:06 +00:00
|
|
|
char *agent_named_pipe_name(void);
|
|
|
|
|
2006-08-28 10:35:12 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* Exports from serial.c.
|
2006-08-28 10:35:12 +00:00
|
|
|
*/
|
2018-10-05 06:03:46 +00:00
|
|
|
extern const struct BackendVtable serial_backend;
|
2006-08-28 10:35:12 +00:00
|
|
|
|
2010-12-23 17:32:28 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* Exports from jump-list.c.
|
2010-12-23 17:32:28 +00:00
|
|
|
*/
|
|
|
|
#define JUMPLIST_SUPPORTED /* suppress #defines in putty.h */
|
|
|
|
void add_session_to_jumplist(const char * const sessionname);
|
|
|
|
void remove_session_from_jumplist(const char * const sessionname);
|
2010-12-26 20:00:45 +00:00
|
|
|
void clear_jumplist(void);
|
2018-11-03 08:28:35 +00:00
|
|
|
bool set_explicit_app_user_model_id(void);
|
2010-12-23 17:32:28 +00:00
|
|
|
|
2018-06-03 13:41:31 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* Exports from noise.c.
|
2018-06-03 13:41:31 +00:00
|
|
|
*/
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool win_read_random(void *buf, unsigned wanted); /* returns true on success */
|
2018-06-03 13:41:31 +00:00
|
|
|
|
2010-12-23 17:32:28 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* Extra functions in storage.c over and above the interface in
|
2010-12-23 17:32:28 +00:00
|
|
|
* storage.h.
|
|
|
|
*
|
|
|
|
* These functions manipulate the Registry section which mirrors the
|
|
|
|
* current Windows 7 jump list. (Because the real jump list storage is
|
|
|
|
* write-only, we need to keep another copy of whatever we put in it,
|
|
|
|
* so that we can put in a slightly modified version the next time.)
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Adds a saved session to the registry jump list mirror. 'item' is a
|
|
|
|
* string naming a saved session. */
|
|
|
|
int add_to_jumplist_registry(const char *item);
|
|
|
|
|
|
|
|
/* Removes an item from the registry jump list mirror. */
|
|
|
|
int remove_from_jumplist_registry(const char *item);
|
|
|
|
|
|
|
|
/* Returns the current jump list entries from the registry. Caller
|
|
|
|
* must free the returned pointer, which points to a contiguous
|
|
|
|
* sequence of NUL-terminated strings in memory, terminated with an
|
|
|
|
* empty one. */
|
|
|
|
char *get_jumplist_registry_entries(void);
|
|
|
|
|
2017-12-10 17:16:50 +00:00
|
|
|
/*
|
|
|
|
* Windows clipboard-UI wording.
|
|
|
|
*/
|
|
|
|
#define CLIPNAME_IMPLICIT "Last selected text"
|
|
|
|
#define CLIPNAME_EXPLICIT "System clipboard"
|
|
|
|
#define CLIPNAME_EXPLICIT_OBJECT "system clipboard"
|
|
|
|
/* These defaults are the ones PuTTY has historically had */
|
2018-10-29 19:50:29 +00:00
|
|
|
#define CLIPUI_DEFAULT_AUTOCOPY true
|
2017-12-10 17:16:50 +00:00
|
|
|
#define CLIPUI_DEFAULT_MOUSE CLIPUI_EXPLICIT
|
|
|
|
#define CLIPUI_DEFAULT_INS CLIPUI_EXPLICIT
|
|
|
|
|
2022-01-22 15:38:53 +00:00
|
|
|
/* In utils */
|
windows/utils/registry.c: allow opening reg keys RO.
These handy wrappers on the verbose underlying Win32 registry API have
to lose some expressiveness, and one thing they lost was the ability
to open a registry key without asking for both read and write access.
This meant they couldn't be used for accessing keys not owned by the
calling user.
So far, I've only used them for accessing PuTTY's own saved data,
which means that hasn't been a problem. But I want to use them
elsewhere in an upcoming commit, so I need to fix that.
The obvious thing would be to change the meaning of the existing
'create' boolean flag so that if it's false, we also don't request
write access. The rationale would be that you're either reading or
writing, and if you're writing you want both RW access and to create
keys that don't already exist. But in fact that's not true: you do
want to set create==false and have write access in the case where
you're _deleting_ things from the key (or the whole key). So we really
do need three ways to call the wrapper function.
Rather than add another boolean field to every call site or mess about
with an 'access type' enum, I've taken an in-between route: the
underlying open_regkey_fn *function* takes a 'create' and a 'write'
flag, but at call sites, it's wrapped with a macro anyway (to append
NULL to the variadic argument list), so I've just made three macros
whose names request different access. That makes call sites marginally
_less_ verbose, while still
2022-09-14 15:04:14 +00:00
|
|
|
HKEY open_regkey_fn(bool create, bool write, HKEY base, const char *path, ...);
|
|
|
|
#define open_regkey_ro(base, ...) \
|
|
|
|
open_regkey_fn(false, false, base, __VA_ARGS__, (const char *)NULL)
|
|
|
|
#define open_regkey_rw(base, ...) \
|
|
|
|
open_regkey_fn(false, true, base, __VA_ARGS__, (const char *)NULL)
|
|
|
|
#define create_regkey(base, ...) \
|
|
|
|
open_regkey_fn(true, true, base, __VA_ARGS__, (const char *)NULL)
|
2022-04-22 09:01:01 +00:00
|
|
|
void close_regkey(HKEY key);
|
|
|
|
void del_regkey(HKEY key, const char *name);
|
|
|
|
char *enum_regkey(HKEY key, int index);
|
|
|
|
bool get_reg_dword(HKEY key, const char *name, DWORD *out);
|
|
|
|
bool put_reg_dword(HKEY key, const char *name, DWORD value);
|
|
|
|
char *get_reg_sz(HKEY key, const char *name);
|
|
|
|
bool put_reg_sz(HKEY key, const char *name, const char *str);
|
|
|
|
strbuf *get_reg_multi_sz(HKEY key, const char *name);
|
|
|
|
bool put_reg_multi_sz(HKEY key, const char *name, strbuf *str);
|
|
|
|
|
|
|
|
char *get_reg_sz_simple(HKEY key, const char *name, const char *leaf);
|
2019-01-26 20:26:09 +00:00
|
|
|
|
2022-01-22 15:38:53 +00:00
|
|
|
/* In cliloop.c */
|
2020-02-07 19:15:13 +00:00
|
|
|
typedef bool (*cliloop_pre_t)(void *vctx, const HANDLE **extra_handles,
|
|
|
|
size_t *n_extra_handles);
|
|
|
|
typedef bool (*cliloop_post_t)(void *vctx, size_t extra_handle_index);
|
|
|
|
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);
|
|
|
|
|
New application: a Windows version of 'pterm'!
This fulfills our long-standing Mayhem-difficulty wishlist item
'win-command-prompt': this is a Windows pterm in the sense that when
you run it you get a local cmd.exe running inside a PuTTY-style window.
Advantages of this: you get the same free choice of fonts as PuTTY has
(no restriction to a strange subset of the system's available fonts);
you get the same copy-paste gestures as PuTTY (no mental gear-shifting
when you have command prompts and SSH sessions open on the same
desktop); you get scrollback with the PuTTY semantics (scrolling to
the bottom gets you to where the action is, as opposed to the way you
could accidentally find yourself 500 lines past the end of the action
in a real console).
'win-command-prompt' was at Mayhem difficulty ('Probably impossible')
basically on the grounds that with Windows's old APIs for accessing
the contents of consoles, there was no way I could find to get this to
work sensibly. What was needed to make it feasible was a major piece
of re-engineering work inside Windows itself.
But, of course, that's exactly what happened! In 2019, the new ConPTY
API arrived, which lets you create an object that behaves like a
Windows console at one end, and round the back, emits a stream of
VT-style escape sequences as the screen contents evolve, and accepts a
VT-style input stream in return which it will parse function and arrow
keys out of in the usual way.
So now it's actually _easy_ to get this to basically work. The new
backend, in conpty.c, has to do a handful of magic Windows API calls
to set up the pseudo-console and its feeder pipes and start a
subprocess running in it, a further magic call every time the PuTTY
window is resized, and detect the end of the session by watching for
the subprocess terminating. But apart from that, all it has to do is
pass data back and forth unmodified between those pipes and the
backend's associated Seat!
That said, this is new and experimental, and there will undoubtedly be
issues. One that I already know about is that you can't copy and paste
a word that has wrapped between lines without getting an annoying
newline in the middle of it. As far as I can see this is a fundamental
limitation: the ConPTY system sends the _same_ escape sequence stream
for a line that wrapped as it would send for a line that had a logical
\n at what would have been the wrap point. Probably the best we can do
to mitigate this is to adopt a different heuristic for newline elision
that's right more often than it's wrong.
For the moment, that experimental-ness is indicated by the fact that
Buildscr will build, sign and deliver a copy of pterm.exe for each
flavour of Windows, but won't include it in the .zip file or in the
installer. (In fact, that puts it in exactly the same ad-hoc category
as PuTTYtel, although for completely different reasons.)
2021-05-08 16:24:13 +00:00
|
|
|
extern const struct BackendVtable conpty_backend;
|
|
|
|
|
|
|
|
/* Functions that parametrise window.c between PuTTY and pterm */
|
2021-05-08 16:20:50 +00:00
|
|
|
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);
|
|
|
|
|
Convenience wrappers on plug_closing().
Having a single plug_closing() function covering various kinds of
closure is reasonably convenient from the point of view of Plug
implementations, but it's annoying for callers, who all have to fill
in pointless NULL and 0 parameters in the cases where they're not
used.
Added some inline helper functions in network.h alongside the main
plug_closing() dispatch wrappers, so that each kind of connection
closure can present a separate API for the Socket side of the
interface, without complicating the vtable for the Plug side.
Also, added OS-specific extra helpers in the Unix and Windows
directories, which centralise the job of taking an OS error code (of
whatever kind) and translating it into its error message.
In passing, this removes the horrible ad-hoc made-up error codes in
proxy.h, which is OK, because nothing checked for them anyway, and
also I'm about to do an API change to plug_closing proper that removes
the need for them.
2021-11-06 13:25:42 +00:00
|
|
|
/* network.c: network error reporting helpers taking OS error code */
|
|
|
|
void plug_closing_system_error(Plug *plug, DWORD error);
|
|
|
|
void plug_closing_winsock_error(Plug *plug, DWORD error);
|
|
|
|
|
Richer data type for interactive prompt results.
All the seat functions that request an interactive prompt of some kind
to the user - both the main seat_get_userpass_input and the various
confirmation dialogs for things like host keys - were using a simple
int return value, with the general semantics of 0 = "fail", 1 =
"proceed" (and in the case of seat_get_userpass_input, answers to the
prompts were provided), and -1 = "request in progress, wait for a
callback".
In this commit I change all those functions' return types to a new
struct called SeatPromptResult, whose primary field is an enum
replacing those simple integer values.
The main purpose is that the enum has not three but _four_ values: the
"fail" result has been split into 'user abort' and 'software abort'.
The distinction is that a user abort occurs as a result of an
interactive UI action, such as the user clicking 'cancel' in a dialog
box or hitting ^D or ^C at a terminal password prompt - and therefore,
there's no need to display an error message telling the user that the
interactive operation has failed, because the user already knows,
because they _did_ it. 'Software abort' is from any other cause, where
PuTTY is the first to know there was a problem, and has to tell the
user.
We already had this 'user abort' vs 'software abort' distinction in
other parts of the code - the SSH backend has separate termination
functions which protocol layers can call. But we assumed that any
failure from an interactive prompt request fell into the 'user abort'
category, which is not true. A couple of examples: if you configure a
host key fingerprint in your saved session via the SSH > Host keys
pane, and the server presents a host key that doesn't match it, then
verify_ssh_host_key would report that the user had aborted the
connection, and feel no need to tell the user what had gone wrong!
Similarly, if a password provided on the command line was not
accepted, then (after I fixed the semantics of that in the previous
commit) the same wrong handling would occur.
So now, those Seat prompt functions too can communicate whether the
user or the software originated a connection abort. And in the latter
case, we also provide an error message to present to the user. Result:
in those two example cases (and others), error messages should no
longer go missing.
Implementation note: to avoid the hassle of having the error message
in a SeatPromptResult being a dynamically allocated string (and hence,
every recipient of one must always check whether it's non-NULL and
free it on every exit path, plus being careful about copying the
struct around), I've instead arranged that the structure contains a
function pointer and a couple of parameters, so that the string form
of the message can be constructed on demand. That way, the only users
who need to free it are the ones who actually _asked_ for it in the
first place, which is a much smaller set.
(This is one of the rare occasions that I regret not having C++'s
extra features available in this code base - a unique_ptr or
shared_ptr to a string would have been just the thing here, and the
compiler would have done all the hard work for me of remembering where
to insert the frees!)
2021-12-28 17:52:00 +00:00
|
|
|
SeatPromptResult make_spr_sw_abort_winerror(const char *prefix, DWORD error);
|
|
|
|
|
2022-01-03 11:40:22 +00:00
|
|
|
HANDLE lock_interprocess_mutex(const char *mutexname, char **error);
|
|
|
|
void unlock_interprocess_mutex(HANDLE mutex);
|
|
|
|
|
2022-01-15 18:27:19 +00:00
|
|
|
typedef void (*aux_opt_error_fn_t)(const char *, ...);
|
|
|
|
typedef struct AuxMatchOpt {
|
New abstraction for command-line arguments.
This begins the process of enabling our Windows applications to handle
Unicode characters on their command lines which don't fit in the
system code page.
Instead of passing plain strings to cmdline_process_param, we now pass
a partially opaque and platform-specific thing called a CmdlineArg.
This has a method that extracts the argument word as a default-encoded
string, and another one that tries to extract it as UTF-8 (though it
may fail if the UTF-8 isn't available).
On Windows, the command line is now constructed by calling
split_into_argv_w on the Unicode command line returned by
GetCommandLineW(), and the UTF-8 method returns text converted
directly from that wide-character form, not going via the system code
page. So it _can_ include UTF-8 characters that wouldn't have
round-tripped via CP_ACP.
This commit introduces the abstraction and switches over the
cross-platform and Windows argv-handling code to use it, with minimal
functional change. Nothing yet tries to call cmdline_arg_get_utf8().
I say 'cross-platform and Windows' because on the Unix side there's
still a lot of use of plain old argv which I haven't converted. That
would be a much larger project, and isn't currently needed: the
_current_ aim of this abstraction is to get the right things to happen
relating to Unicode on Windows, so for code that doesn't run on
Windows anyway, it's not adding value. (Also there's a tension with
GTK, which wants to talk to standard argv and extract arguments _it_
knows about, so at the very least we'd have to let it munge argv
before importing it into this new system.)
2024-09-25 09:18:38 +00:00
|
|
|
CmdlineArgList *arglist;
|
|
|
|
size_t index;
|
2022-01-15 18:27:19 +00:00
|
|
|
bool doing_opts;
|
|
|
|
aux_opt_error_fn_t error;
|
|
|
|
} AuxMatchOpt;
|
New abstraction for command-line arguments.
This begins the process of enabling our Windows applications to handle
Unicode characters on their command lines which don't fit in the
system code page.
Instead of passing plain strings to cmdline_process_param, we now pass
a partially opaque and platform-specific thing called a CmdlineArg.
This has a method that extracts the argument word as a default-encoded
string, and another one that tries to extract it as UTF-8 (though it
may fail if the UTF-8 isn't available).
On Windows, the command line is now constructed by calling
split_into_argv_w on the Unicode command line returned by
GetCommandLineW(), and the UTF-8 method returns text converted
directly from that wide-character form, not going via the system code
page. So it _can_ include UTF-8 characters that wouldn't have
round-tripped via CP_ACP.
This commit introduces the abstraction and switches over the
cross-platform and Windows argv-handling code to use it, with minimal
functional change. Nothing yet tries to call cmdline_arg_get_utf8().
I say 'cross-platform and Windows' because on the Unix side there's
still a lot of use of plain old argv which I haven't converted. That
would be a much larger project, and isn't currently needed: the
_current_ aim of this abstraction is to get the right things to happen
relating to Unicode on Windows, so for code that doesn't run on
Windows anyway, it's not adding value. (Also there's a tension with
GTK, which wants to talk to standard argv and extract arguments _it_
knows about, so at the very least we'd have to let it munge argv
before importing it into this new system.)
2024-09-25 09:18:38 +00:00
|
|
|
AuxMatchOpt aux_match_opt_init(aux_opt_error_fn_t opt_error);
|
|
|
|
bool aux_match_arg(AuxMatchOpt *amo, CmdlineArg **val);
|
|
|
|
bool aux_match_opt(AuxMatchOpt *amo, CmdlineArg **val,
|
|
|
|
const char *optname, ...);
|
2022-01-15 18:27:19 +00:00
|
|
|
bool aux_match_done(AuxMatchOpt *amo);
|
|
|
|
|
2024-09-24 16:50:19 +00:00
|
|
|
char *save_screenshot(HWND hwnd, Filename *outfile);
|
2022-04-02 15:18:08 +00:00
|
|
|
void gui_terminal_ready(HWND hwnd, Seat *seat, Backend *backend);
|
|
|
|
|
2022-09-12 10:57:15 +00:00
|
|
|
void setup_gui_timing(void);
|
|
|
|
|
New abstraction for command-line arguments.
This begins the process of enabling our Windows applications to handle
Unicode characters on their command lines which don't fit in the
system code page.
Instead of passing plain strings to cmdline_process_param, we now pass
a partially opaque and platform-specific thing called a CmdlineArg.
This has a method that extracts the argument word as a default-encoded
string, and another one that tries to extract it as UTF-8 (though it
may fail if the UTF-8 isn't available).
On Windows, the command line is now constructed by calling
split_into_argv_w on the Unicode command line returned by
GetCommandLineW(), and the UTF-8 method returns text converted
directly from that wide-character form, not going via the system code
page. So it _can_ include UTF-8 characters that wouldn't have
round-tripped via CP_ACP.
This commit introduces the abstraction and switches over the
cross-platform and Windows argv-handling code to use it, with minimal
functional change. Nothing yet tries to call cmdline_arg_get_utf8().
I say 'cross-platform and Windows' because on the Unix side there's
still a lot of use of plain old argv which I haven't converted. That
would be a much larger project, and isn't currently needed: the
_current_ aim of this abstraction is to get the right things to happen
relating to Unicode on Windows, so for code that doesn't run on
Windows anyway, it's not adding value. (Also there's a tension with
GTK, which wants to talk to standard argv and extract arguments _it_
knows about, so at the very least we'd have to let it munge argv
before importing it into this new system.)
2024-09-25 09:18:38 +00:00
|
|
|
/* Windows-specific extra functions in cmdline_arg.c */
|
|
|
|
CmdlineArgList *cmdline_arg_list_from_GetCommandLineW(void);
|
|
|
|
const wchar_t *cmdline_arg_remainder_wide(CmdlineArg *);
|
|
|
|
char *cmdline_arg_remainder_acp(CmdlineArg *);
|
|
|
|
char *cmdline_arg_remainder_utf8(CmdlineArg *);
|
|
|
|
CmdlineArg *cmdline_arg_from_utf8(CmdlineArgList *list, const char *string);
|
|
|
|
|
2021-04-18 06:58:27 +00:00
|
|
|
#endif /* PUTTY_WINDOWS_PLATFORM_H */
|