mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-03-22 14:39:24 -05:00
Backport of the pre-0.77 demo features to 0.76.
This is a combined cherry-pick of three commits on the 0.77 branch: 896bcd506866d3f "Resurrect the test backends" 9294ee349617632 "Windows PuTTYgen: saw load_key_file in half" bc7e06c49411a89 "Windows tools: assorted '-demo' options" Of course, these commits aren't in 0.76 itself, and I don't see any reason to publish a binary build of 0.76 containing them. This is just a branch I can build from myself to get a version of PuTTY that will look exactly like the real 0.76 but permit automated generation of demo screenshots.
This commit is contained in:
parent
1fd7baa734
commit
11192e2e33
3
Recipe
3
Recipe
@ -330,7 +330,9 @@ KEYGEN = sshrsag sshdssg sshecdsag
|
|||||||
# X/GTK Unix app, [U] for command-line Unix app.
|
# X/GTK Unix app, [U] for command-line Unix app.
|
||||||
|
|
||||||
putty : [G] GUITERM NONSSH WINSSH W_BE_ALL WINMISC winx11 putty.res LIBS
|
putty : [G] GUITERM NONSSH WINSSH W_BE_ALL WINMISC winx11 putty.res LIBS
|
||||||
|
+ screenshot testback
|
||||||
puttytel : [G] GUITERM NONSSH W_BE_NOSSH WINMISC puttytel.res nogss LIBS
|
puttytel : [G] GUITERM NONSSH W_BE_NOSSH WINMISC puttytel.res nogss LIBS
|
||||||
|
+ screenshot testback
|
||||||
plink : [C] winplink wincons console NONSSH WINSSH W_BE_ALL logging WINMISC
|
plink : [C] winplink wincons console NONSSH WINSSH W_BE_ALL logging WINMISC
|
||||||
+ winx11 plink.res winnojmp sessprep noterm winnohlp winselcli
|
+ winx11 plink.res winnojmp sessprep noterm winnohlp winselcli
|
||||||
+ clicons wincliloop console LIBS
|
+ clicons wincliloop console LIBS
|
||||||
@ -353,6 +355,7 @@ puttygen : [G] winpgen KEYGEN SSHPRIME sshdes ARITH sshmd5 version
|
|||||||
+ sshpubk sshaes sshsh256 sshsh512 IMPORT winutils puttygen.res
|
+ sshpubk sshaes sshsh256 sshsh512 IMPORT winutils puttygen.res
|
||||||
+ tree234 notiming winhelp winnojmp CONF LIBS wintime sshecc sshprng
|
+ tree234 notiming winhelp winnojmp CONF LIBS wintime sshecc sshprng
|
||||||
+ sshauxcrypt sshhmac winsecur winmiscs sshsha3 sshblake2 sshargon2
|
+ sshauxcrypt sshhmac winsecur winmiscs sshsha3 sshblake2 sshargon2
|
||||||
|
+ screenshot
|
||||||
|
|
||||||
pterm : [X] GTKTERM uxmisc misc ldisc settings uxpty uxsel BE_NONE uxstore
|
pterm : [X] GTKTERM uxmisc misc ldisc settings uxpty uxsel BE_NONE uxstore
|
||||||
+ uxsignal CHARSET cmdline uxpterm version time xpmpterm xpmptcfg
|
+ uxsignal CHARSET cmdline uxpterm version time xpmpterm xpmptcfg
|
||||||
|
18
settings.c
18
settings.c
@ -1302,6 +1302,8 @@ static int sessioncmp(const void *av, const void *bv)
|
|||||||
return strcmp(a, b); /* otherwise, compare normally */
|
return strcmp(a, b); /* otherwise, compare normally */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sesslist_demo_mode = false;
|
||||||
|
|
||||||
void get_sesslist(struct sesslist *list, bool allocate)
|
void get_sesslist(struct sesslist *list, bool allocate)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -1311,12 +1313,18 @@ void get_sesslist(struct sesslist *list, bool allocate)
|
|||||||
if (allocate) {
|
if (allocate) {
|
||||||
strbuf *sb = strbuf_new();
|
strbuf *sb = strbuf_new();
|
||||||
|
|
||||||
if ((handle = enum_settings_start()) != NULL) {
|
if (sesslist_demo_mode) {
|
||||||
while (enum_settings_next(handle, sb))
|
put_asciz(sb, "demo-server");
|
||||||
put_byte(sb, '\0');
|
put_asciz(sb, "demo-server-2");
|
||||||
enum_settings_finish(handle);
|
} else {
|
||||||
|
if ((handle = enum_settings_start()) != NULL) {
|
||||||
|
while (enum_settings_next(handle, sb))
|
||||||
|
put_byte(sb, '\0');
|
||||||
|
enum_settings_finish(handle);
|
||||||
|
}
|
||||||
|
put_byte(sb, '\0');
|
||||||
}
|
}
|
||||||
put_byte(sb, '\0');
|
|
||||||
list->buffer = strbuf_to_str(sb);
|
list->buffer = strbuf_to_str(sb);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
27
testback.c
27
testback.c
@ -32,11 +32,8 @@
|
|||||||
|
|
||||||
#include "putty.h"
|
#include "putty.h"
|
||||||
|
|
||||||
static char *null_init(const BackendVtable *, Seat *, Backend **, LogContext *,
|
|
||||||
Conf *, const char *, int, char **, bool, bool);
|
|
||||||
static char *loop_init(const BackendVtable *, Seat *, Backend **, LogContext *,
|
static char *loop_init(const BackendVtable *, Seat *, Backend **, LogContext *,
|
||||||
Conf *, const char *, int, char **, bool, bool);
|
Conf *, const char *, int, char **, bool, bool);
|
||||||
static void null_free(Backend *);
|
|
||||||
static void loop_free(Backend *);
|
static void loop_free(Backend *);
|
||||||
static void null_reconfig(Backend *, Conf *);
|
static void null_reconfig(Backend *, Conf *);
|
||||||
static size_t null_send(Backend *, const char *, size_t);
|
static size_t null_send(Backend *, const char *, size_t);
|
||||||
@ -54,8 +51,8 @@ static void null_unthrottle(Backend *, size_t);
|
|||||||
static int null_cfg_info(Backend *);
|
static int null_cfg_info(Backend *);
|
||||||
|
|
||||||
const BackendVtable null_backend = {
|
const BackendVtable null_backend = {
|
||||||
.init = null_init,
|
.init = loop_init,
|
||||||
.free = null_free,
|
.free = loop_free,
|
||||||
.reconfig = null_reconfig,
|
.reconfig = null_reconfig,
|
||||||
.send = null_send,
|
.send = null_send,
|
||||||
.sendbuffer = null_sendbuffer,
|
.sendbuffer = null_sendbuffer,
|
||||||
@ -102,17 +99,6 @@ struct loop_state {
|
|||||||
Backend backend;
|
Backend backend;
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *null_init(const BackendVtable *vt, Seat *seat,
|
|
||||||
Backend **backend_handle, LogContext *logctx,
|
|
||||||
Conf *conf, const char *host, int port,
|
|
||||||
char **realhost, bool nodelay, bool keepalive) {
|
|
||||||
/* No local authentication phase in this protocol */
|
|
||||||
seat_set_trust_status(seat, false);
|
|
||||||
|
|
||||||
*backend_handle = NULL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *loop_init(const BackendVtable *vt, Seat *seat,
|
static char *loop_init(const BackendVtable *vt, Seat *seat,
|
||||||
Backend **backend_handle, LogContext *logctx,
|
Backend **backend_handle, LogContext *logctx,
|
||||||
Conf *conf, const char *host, int port,
|
Conf *conf, const char *host, int port,
|
||||||
@ -123,15 +109,14 @@ static char *loop_init(const BackendVtable *vt, Seat *seat,
|
|||||||
seat_set_trust_status(seat, false);
|
seat_set_trust_status(seat, false);
|
||||||
|
|
||||||
st->seat = seat;
|
st->seat = seat;
|
||||||
|
st->backend.vt = vt;
|
||||||
*backend_handle = &st->backend;
|
*backend_handle = &st->backend;
|
||||||
|
|
||||||
|
*realhost = dupstr(host);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void null_free(Backend *be)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void loop_free(Backend *be)
|
static void loop_free(Backend *be)
|
||||||
{
|
{
|
||||||
struct loop_state *st = container_of(be, struct loop_state, backend);
|
struct loop_state *st = container_of(be, struct loop_state, backend);
|
||||||
|
114
windows/screenshot.c
Normal file
114
windows/screenshot.c
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
#include "putty.h"
|
||||||
|
|
||||||
|
#include <dwmapi.h>
|
||||||
|
|
||||||
|
char *save_screenshot(HWND hwnd, const char *outfile)
|
||||||
|
{
|
||||||
|
HDC dcWindow = NULL, dcSave = NULL;
|
||||||
|
HBITMAP bmSave = NULL;
|
||||||
|
uint8_t *buffer = NULL;
|
||||||
|
char *err = NULL;
|
||||||
|
|
||||||
|
static HMODULE dwmapi_module;
|
||||||
|
DECL_WINDOWS_FUNCTION(static, HRESULT, DwmGetWindowAttribute,
|
||||||
|
(HWND, DWORD, PVOID, DWORD));
|
||||||
|
|
||||||
|
if (!dwmapi_module) {
|
||||||
|
dwmapi_module = load_system32_dll("dwmapi.dll");
|
||||||
|
GET_WINDOWS_FUNCTION(dwmapi_module, DwmGetWindowAttribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
dcWindow = GetDC(NULL);
|
||||||
|
if (!dcWindow) {
|
||||||
|
err = dupprintf("GetDC(window): %s", win_strerror(GetLastError()));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
int x, y, w, h;
|
||||||
|
RECT wr;
|
||||||
|
|
||||||
|
/* Use DwmGetWindowAttribute in place of GetWindowRect to exclude
|
||||||
|
* drop shadow, otherwise we get a load of unwanted desktop
|
||||||
|
* background under the shadow */
|
||||||
|
if (p_DwmGetWindowAttribute &&
|
||||||
|
0 <= p_DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS,
|
||||||
|
&wr, sizeof(wr))) {
|
||||||
|
x = wr.left;
|
||||||
|
y = wr.top;
|
||||||
|
w = wr.right - wr.left;
|
||||||
|
h = wr.bottom - wr.top;
|
||||||
|
} else {
|
||||||
|
BITMAP bmhdr;
|
||||||
|
memset(&bmhdr, 0, sizeof(bmhdr));
|
||||||
|
GetObject(GetCurrentObject(dcWindow, OBJ_BITMAP),
|
||||||
|
sizeof(bmhdr), &bmhdr);
|
||||||
|
x = y = 0;
|
||||||
|
w = bmhdr.bmWidth;
|
||||||
|
h = bmhdr.bmHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
dcSave = CreateCompatibleDC(dcWindow);
|
||||||
|
if (!dcSave) {
|
||||||
|
err = dupprintf("CreateCompatibleDC(desktop window dc): %s",
|
||||||
|
win_strerror(GetLastError()));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
bmSave = CreateCompatibleBitmap(dcWindow, w, h);
|
||||||
|
if (!bmSave) {
|
||||||
|
err = dupprintf("CreateCompatibleBitmap: %s",
|
||||||
|
win_strerror(GetLastError()));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SelectObject(dcSave, bmSave)) {
|
||||||
|
err = dupprintf("SelectObject: %s", win_strerror(GetLastError()));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!BitBlt(dcSave, 0, 0, w, h, dcWindow, x, y, SRCCOPY)) {
|
||||||
|
err = dupprintf("BitBlt: %s", win_strerror(GetLastError()));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
BITMAPINFO bmInfo;
|
||||||
|
memset(&bmInfo, 0, sizeof(bmInfo));
|
||||||
|
bmInfo.bmiHeader.biSize = sizeof(bmInfo.bmiHeader);
|
||||||
|
bmInfo.bmiHeader.biWidth = w;
|
||||||
|
bmInfo.bmiHeader.biHeight = h;
|
||||||
|
bmInfo.bmiHeader.biPlanes = 1;
|
||||||
|
bmInfo.bmiHeader.biBitCount = 32;
|
||||||
|
bmInfo.bmiHeader.biCompression = BI_RGB;
|
||||||
|
|
||||||
|
size_t bmPixels = (size_t)w*h, bmBytes = bmPixels * 4;
|
||||||
|
buffer = snewn(bmBytes, uint8_t);
|
||||||
|
|
||||||
|
if (!GetDIBits(dcWindow, bmSave, 0, h, buffer, &bmInfo, DIB_RGB_COLORS))
|
||||||
|
err = dupprintf("GetDIBits (get data): %s",
|
||||||
|
win_strerror(GetLastError()));
|
||||||
|
|
||||||
|
FILE *fp = fopen(outfile, "wb");
|
||||||
|
if (!fp) {
|
||||||
|
err = dupprintf("'%s': unable to open file", outfile);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
BITMAPFILEHEADER bmFileHdr;
|
||||||
|
bmFileHdr.bfType = 'B' | ('M' << 8);
|
||||||
|
bmFileHdr.bfSize = sizeof(bmFileHdr) + sizeof(bmInfo.bmiHeader) + bmBytes;
|
||||||
|
bmFileHdr.bfOffBits = sizeof(bmFileHdr) + sizeof(bmInfo.bmiHeader);
|
||||||
|
fwrite((void *)&bmFileHdr, 1, sizeof(bmFileHdr), fp);
|
||||||
|
fwrite((void *)&bmInfo.bmiHeader, 1, sizeof(bmInfo.bmiHeader), fp);
|
||||||
|
fwrite((void *)buffer, 1, bmBytes, fp);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (dcWindow)
|
||||||
|
ReleaseDC(NULL, dcWindow);
|
||||||
|
if (bmSave)
|
||||||
|
DeleteObject(bmSave);
|
||||||
|
if (dcSave)
|
||||||
|
DeleteObject(dcSave);
|
||||||
|
sfree(buffer);
|
||||||
|
return err;
|
||||||
|
}
|
@ -388,6 +388,8 @@ static void create_controls(HWND hwnd, char *path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *dialog_box_demo_screenshot_filename = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is the configuration box.
|
* This function is the configuration box.
|
||||||
* (Being a dialog procedure, in general it returns 0 if the default
|
* (Being a dialog procedure, in general it returns 0 if the default
|
||||||
@ -396,6 +398,7 @@ static void create_controls(HWND hwnd, char *path)
|
|||||||
static INT_PTR CALLBACK GenericMainDlgProc(HWND hwnd, UINT msg,
|
static INT_PTR CALLBACK GenericMainDlgProc(HWND hwnd, UINT msg,
|
||||||
WPARAM wParam, LPARAM lParam)
|
WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
|
const int DEMO_SCREENSHOT_TIMER_ID = 1230;
|
||||||
HWND hw, treeview;
|
HWND hw, treeview;
|
||||||
struct treeview_faff tvfaff;
|
struct treeview_faff tvfaff;
|
||||||
int ret;
|
int ret;
|
||||||
@ -565,6 +568,21 @@ static INT_PTR CALLBACK GenericMainDlgProc(HWND hwnd, UINT msg,
|
|||||||
* spurious firing during the above setup procedure.
|
* spurious firing during the above setup procedure.
|
||||||
*/
|
*/
|
||||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, 1);
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, 1);
|
||||||
|
|
||||||
|
if (dialog_box_demo_screenshot_filename)
|
||||||
|
SetTimer(hwnd, DEMO_SCREENSHOT_TIMER_ID, TICKSPERSEC, NULL);
|
||||||
|
return 0;
|
||||||
|
case WM_TIMER:
|
||||||
|
if (dialog_box_demo_screenshot_filename &&
|
||||||
|
(UINT_PTR)wParam == DEMO_SCREENSHOT_TIMER_ID) {
|
||||||
|
KillTimer(hwnd, DEMO_SCREENSHOT_TIMER_ID);
|
||||||
|
const char *err = save_screenshot(
|
||||||
|
hwnd, dialog_box_demo_screenshot_filename);
|
||||||
|
if (err)
|
||||||
|
MessageBox(hwnd, err, "Demo screenshot failure",
|
||||||
|
MB_OK | MB_ICONERROR);
|
||||||
|
SaneEndDialog(hwnd, 0);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
case WM_LBUTTONUP:
|
case WM_LBUTTONUP:
|
||||||
/*
|
/*
|
||||||
|
@ -231,6 +231,11 @@ static int compose_state = 0;
|
|||||||
|
|
||||||
static UINT wm_mousewheel = WM_MOUSEWHEEL;
|
static UINT wm_mousewheel = WM_MOUSEWHEEL;
|
||||||
|
|
||||||
|
extern bool sesslist_demo_mode;
|
||||||
|
extern const char *dialog_box_demo_screenshot_filename;
|
||||||
|
static strbuf *demo_terminal_data = NULL;
|
||||||
|
static const char *terminal_demo_screenshot_filename;
|
||||||
|
|
||||||
#define IS_HIGH_VARSEL(wch1, wch2) \
|
#define IS_HIGH_VARSEL(wch1, wch2) \
|
||||||
((wch1) == 0xDB40 && ((wch2) >= 0xDD00 && (wch2) <= 0xDDEF))
|
((wch1) == 0xDB40 && ((wch2) >= 0xDD00 && (wch2) <= 0xDDEF))
|
||||||
#define IS_LOW_VARSEL(wch) \
|
#define IS_LOW_VARSEL(wch) \
|
||||||
@ -369,7 +374,10 @@ static void start_backend(void)
|
|||||||
* Select protocol. This is farmed out into a table in a
|
* Select protocol. This is farmed out into a table in a
|
||||||
* separate file to enable an ssh-free variant.
|
* separate file to enable an ssh-free variant.
|
||||||
*/
|
*/
|
||||||
vt = backend_vt_from_proto(conf_get_int(conf, CONF_protocol));
|
if (demo_terminal_data)
|
||||||
|
vt = &null_backend;
|
||||||
|
else
|
||||||
|
vt = backend_vt_from_proto(conf_get_int(conf, CONF_protocol));
|
||||||
if (!vt) {
|
if (!vt) {
|
||||||
char *str = dupprintf("%s Internal Error", appname);
|
char *str = dupprintf("%s Internal Error", appname);
|
||||||
MessageBox(NULL, "Unsupported protocol number found",
|
MessageBox(NULL, "Unsupported protocol number found",
|
||||||
@ -520,6 +528,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
|||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
bool special_launchable_argument = false;
|
bool special_launchable_argument = false;
|
||||||
|
bool demo_config_box = false;
|
||||||
|
|
||||||
settings_set_default_protocol(be_default_protocol);
|
settings_set_default_protocol(be_default_protocol);
|
||||||
/* Find the appropriate default port. */
|
/* Find the appropriate default port. */
|
||||||
@ -646,6 +655,30 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
|||||||
} else if (!strcmp(p, "-pgpfp")) {
|
} else if (!strcmp(p, "-pgpfp")) {
|
||||||
pgp_fingerprints_msgbox(NULL);
|
pgp_fingerprints_msgbox(NULL);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
} else if (!strcmp(p, "-demo-config-box")) {
|
||||||
|
if (i+1 >= argc) {
|
||||||
|
cmdline_error("%s expects an output filename", p);
|
||||||
|
} else {
|
||||||
|
demo_config_box = true;
|
||||||
|
dialog_box_demo_screenshot_filename = argv[++i];
|
||||||
|
}
|
||||||
|
} else if (!strcmp(p, "-demo-terminal")) {
|
||||||
|
if (i+2 >= argc) {
|
||||||
|
cmdline_error("%s expects input and output filenames",
|
||||||
|
p);
|
||||||
|
} else {
|
||||||
|
const char *infile = argv[++i];
|
||||||
|
terminal_demo_screenshot_filename = argv[++i];
|
||||||
|
FILE *fp = fopen(infile, "rb");
|
||||||
|
if (!fp)
|
||||||
|
cmdline_error("can't open input file '%s'", argv);
|
||||||
|
demo_terminal_data = strbuf_new();
|
||||||
|
char buf[4096];
|
||||||
|
int retd;
|
||||||
|
while ((retd = fread(buf, 1, sizeof(buf), fp)) > 0)
|
||||||
|
put_data(demo_terminal_data, buf, retd);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
} else if (*p != '-') {
|
} else if (*p != '-') {
|
||||||
cmdline_error("unexpected argument \"%s\"", p);
|
cmdline_error("unexpected argument \"%s\"", p);
|
||||||
} else {
|
} else {
|
||||||
@ -656,13 +689,26 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
|||||||
|
|
||||||
cmdline_run_saved(conf);
|
cmdline_run_saved(conf);
|
||||||
|
|
||||||
/*
|
if (demo_config_box) {
|
||||||
* Bring up the config dialog if the command line hasn't
|
sesslist_demo_mode = true;
|
||||||
* (explicitly) specified a launchable configuration.
|
load_open_settings(NULL, conf);
|
||||||
*/
|
conf_set_str(conf, CONF_host, "demo-server.example.com");
|
||||||
if (!(special_launchable_argument || cmdline_host_ok(conf))) {
|
do_config(conf);
|
||||||
if (!do_config(conf))
|
cleanup_exit(0);
|
||||||
cleanup_exit(0);
|
} else if (demo_terminal_data) {
|
||||||
|
/* Ensure conf will cause an immediate session launch */
|
||||||
|
load_open_settings(NULL, conf);
|
||||||
|
conf_set_str(conf, CONF_host, "demo-server.example.com");
|
||||||
|
conf_set_int(conf, CONF_close_on_exit, FORCE_OFF);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Bring up the config dialog if the command line hasn't
|
||||||
|
* (explicitly) specified a launchable configuration.
|
||||||
|
*/
|
||||||
|
if (!(special_launchable_argument || cmdline_host_ok(conf))) {
|
||||||
|
if (!do_config(conf))
|
||||||
|
cleanup_exit(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare_session(conf);
|
prepare_session(conf);
|
||||||
@ -885,6 +931,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
|||||||
term_set_focus(term, GetForegroundWindow() == wgs.term_hwnd);
|
term_set_focus(term, GetForegroundWindow() == wgs.term_hwnd);
|
||||||
UpdateWindow(wgs.term_hwnd);
|
UpdateWindow(wgs.term_hwnd);
|
||||||
|
|
||||||
|
gui_terminal_ready(wgs.term_hwnd, &wgs.seat, backend);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
HANDLE *handles;
|
HANDLE *handles;
|
||||||
int nhandles, n;
|
int nhandles, n;
|
||||||
@ -5858,3 +5906,19 @@ static bool win_seat_get_window_pixel_size(Seat *seat, int *x, int *y)
|
|||||||
*y = r.bottom - r.top;
|
*y = r.bottom - r.top;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void demo_terminal_screenshot(void *ctx, unsigned long now)
|
||||||
|
{
|
||||||
|
HWND hwnd = (HWND)ctx;
|
||||||
|
save_screenshot(hwnd, terminal_demo_screenshot_filename);
|
||||||
|
cleanup_exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gui_terminal_ready(HWND hwnd, Seat *seat, Backend *backend)
|
||||||
|
{
|
||||||
|
if (demo_terminal_data) {
|
||||||
|
ptrlen data = ptrlen_from_strbuf(demo_terminal_data);
|
||||||
|
seat_stdout(seat, data.ptr, data.len);
|
||||||
|
schedule_timer(TICKSPERSEC, demo_terminal_screenshot, (void *)hwnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
#define DEFAULT_EDCURVE_INDEX 0
|
#define DEFAULT_EDCURVE_INDEX 0
|
||||||
|
|
||||||
static char *cmdline_keyfile = NULL;
|
static char *cmdline_keyfile = NULL;
|
||||||
|
static ptrlen cmdline_demo_keystr;
|
||||||
|
static const char *demo_screenshot_filename = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print a modal (Really Bad) message box and perform a fatal exit.
|
* Print a modal (Really Bad) message box and perform a fatal exit.
|
||||||
@ -966,6 +968,65 @@ void ui_set_fptype(HWND hwnd, struct MainDlgState *state, int option)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void update_ui_after_load(HWND hwnd, struct MainDlgState *state,
|
||||||
|
const char *passphrase, int type,
|
||||||
|
RSAKey *newkey1, ssh2_userkey *newkey2)
|
||||||
|
{
|
||||||
|
SetDlgItemText(hwnd, IDC_PASSPHRASE1EDIT, passphrase);
|
||||||
|
SetDlgItemText(hwnd, IDC_PASSPHRASE2EDIT, passphrase);
|
||||||
|
|
||||||
|
if (type == SSH_KEYTYPE_SSH1) {
|
||||||
|
char *fingerprint, *savecomment;
|
||||||
|
|
||||||
|
state->ssh2 = false;
|
||||||
|
state->commentptr = &state->key.comment;
|
||||||
|
state->key = *newkey1; /* structure copy */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the key fingerprint.
|
||||||
|
*/
|
||||||
|
savecomment = state->key.comment;
|
||||||
|
state->key.comment = NULL;
|
||||||
|
fingerprint = rsa_ssh1_fingerprint(&state->key);
|
||||||
|
state->key.comment = savecomment;
|
||||||
|
SetDlgItemText(hwnd, IDC_FINGERPRINT, fingerprint);
|
||||||
|
sfree(fingerprint);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Construct a decimal representation of the key, for pasting
|
||||||
|
* into .ssh/authorized_keys on a Unix box.
|
||||||
|
*/
|
||||||
|
setupbigedit1(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC, &state->key);
|
||||||
|
} else {
|
||||||
|
char *fp;
|
||||||
|
char *savecomment;
|
||||||
|
|
||||||
|
state->ssh2 = true;
|
||||||
|
state->commentptr = &state->ssh2key.comment;
|
||||||
|
state->ssh2key = *newkey2; /* structure copy */
|
||||||
|
sfree(newkey2);
|
||||||
|
|
||||||
|
savecomment = state->ssh2key.comment;
|
||||||
|
state->ssh2key.comment = NULL;
|
||||||
|
fp = ssh2_fingerprint(state->ssh2key.key, state->fptype);
|
||||||
|
state->ssh2key.comment = savecomment;
|
||||||
|
|
||||||
|
SetDlgItemText(hwnd, IDC_FINGERPRINT, fp);
|
||||||
|
sfree(fp);
|
||||||
|
|
||||||
|
setupbigedit2(hwnd, IDC_KEYDISPLAY,
|
||||||
|
IDC_PKSTATIC, &state->ssh2key);
|
||||||
|
}
|
||||||
|
SetDlgItemText(hwnd, IDC_COMMENTEDIT,
|
||||||
|
*state->commentptr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finally, hide the progress bar and show the key data.
|
||||||
|
*/
|
||||||
|
ui_set_state(hwnd, state, 2);
|
||||||
|
state->key_exists = true;
|
||||||
|
}
|
||||||
|
|
||||||
void load_key_file(HWND hwnd, struct MainDlgState *state,
|
void load_key_file(HWND hwnd, struct MainDlgState *state,
|
||||||
Filename *filename, bool was_import_cmd)
|
Filename *filename, bool was_import_cmd)
|
||||||
{
|
{
|
||||||
@ -1055,65 +1116,7 @@ void load_key_file(HWND hwnd, struct MainDlgState *state,
|
|||||||
* Now update the key controls with all the
|
* Now update the key controls with all the
|
||||||
* key data.
|
* key data.
|
||||||
*/
|
*/
|
||||||
{
|
update_ui_after_load(hwnd, state, passphrase, type, &newkey1, newkey2);
|
||||||
SetDlgItemText(hwnd, IDC_PASSPHRASE1EDIT,
|
|
||||||
passphrase);
|
|
||||||
SetDlgItemText(hwnd, IDC_PASSPHRASE2EDIT,
|
|
||||||
passphrase);
|
|
||||||
if (type == SSH_KEYTYPE_SSH1) {
|
|
||||||
char *fingerprint, *savecomment;
|
|
||||||
|
|
||||||
state->ssh2 = false;
|
|
||||||
state->commentptr = &state->key.comment;
|
|
||||||
state->key = newkey1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the key fingerprint.
|
|
||||||
*/
|
|
||||||
savecomment = state->key.comment;
|
|
||||||
state->key.comment = NULL;
|
|
||||||
fingerprint = rsa_ssh1_fingerprint(&state->key);
|
|
||||||
state->key.comment = savecomment;
|
|
||||||
SetDlgItemText(hwnd, IDC_FINGERPRINT, fingerprint);
|
|
||||||
sfree(fingerprint);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Construct a decimal representation
|
|
||||||
* of the key, for pasting into
|
|
||||||
* .ssh/authorized_keys on a Unix box.
|
|
||||||
*/
|
|
||||||
setupbigedit1(hwnd, IDC_KEYDISPLAY,
|
|
||||||
IDC_PKSTATIC, &state->key);
|
|
||||||
} else {
|
|
||||||
char *fp;
|
|
||||||
char *savecomment;
|
|
||||||
|
|
||||||
state->ssh2 = true;
|
|
||||||
state->commentptr =
|
|
||||||
&state->ssh2key.comment;
|
|
||||||
state->ssh2key = *newkey2; /* structure copy */
|
|
||||||
sfree(newkey2);
|
|
||||||
|
|
||||||
savecomment = state->ssh2key.comment;
|
|
||||||
state->ssh2key.comment = NULL;
|
|
||||||
fp = ssh2_fingerprint(state->ssh2key.key, state->fptype);
|
|
||||||
state->ssh2key.comment = savecomment;
|
|
||||||
|
|
||||||
SetDlgItemText(hwnd, IDC_FINGERPRINT, fp);
|
|
||||||
sfree(fp);
|
|
||||||
|
|
||||||
setupbigedit2(hwnd, IDC_KEYDISPLAY,
|
|
||||||
IDC_PKSTATIC, &state->ssh2key);
|
|
||||||
}
|
|
||||||
SetDlgItemText(hwnd, IDC_COMMENTEDIT,
|
|
||||||
*state->commentptr);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Finally, hide the progress bar and show
|
|
||||||
* the key data.
|
|
||||||
*/
|
|
||||||
ui_set_state(hwnd, state, 2);
|
|
||||||
state->key_exists = true;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the user has imported a foreign key
|
* If the user has imported a foreign key
|
||||||
@ -1179,6 +1182,7 @@ static void start_generating_key(HWND hwnd, struct MainDlgState *state)
|
|||||||
static INT_PTR CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
static INT_PTR CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||||
WPARAM wParam, LPARAM lParam)
|
WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
|
const int DEMO_SCREENSHOT_TIMER_ID = 1230;
|
||||||
static const char entropy_msg[] =
|
static const char entropy_msg[] =
|
||||||
"Please generate some randomness by moving the mouse over the blank area.";
|
"Please generate some randomness by moving the mouse over the blank area.";
|
||||||
struct MainDlgState *state;
|
struct MainDlgState *state;
|
||||||
@ -1402,9 +1406,33 @@ static INT_PTR CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
|||||||
Filename *fn = filename_from_str(cmdline_keyfile);
|
Filename *fn = filename_from_str(cmdline_keyfile);
|
||||||
load_key_file(hwnd, state, fn, false);
|
load_key_file(hwnd, state, fn, false);
|
||||||
filename_free(fn);
|
filename_free(fn);
|
||||||
|
} else if (cmdline_demo_keystr.ptr) {
|
||||||
|
BinarySource src[1];
|
||||||
|
BinarySource_BARE_INIT_PL(src, cmdline_demo_keystr);
|
||||||
|
const char *errmsg;
|
||||||
|
ssh2_userkey *k = ppk_load_s(src, NULL, &errmsg);
|
||||||
|
assert(!errmsg);
|
||||||
|
|
||||||
|
update_ui_after_load(hwnd, state, "demo passphrase",
|
||||||
|
SSH_KEYTYPE_SSH2, NULL, k);
|
||||||
|
/* BODGE for the 0.66 backport */
|
||||||
|
ui_set_key_type(hwnd, state, IDC_KEYSSH2EDDSA);
|
||||||
|
SetDlgItemInt(hwnd, IDC_BITS, 255, false);
|
||||||
|
|
||||||
|
SetTimer(hwnd, DEMO_SCREENSHOT_TIMER_ID, TICKSPERSEC, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
case WM_TIMER:
|
||||||
|
if ((UINT_PTR)wParam == DEMO_SCREENSHOT_TIMER_ID) {
|
||||||
|
KillTimer(hwnd, DEMO_SCREENSHOT_TIMER_ID);
|
||||||
|
const char *err = save_screenshot(hwnd, demo_screenshot_filename);
|
||||||
|
if (err)
|
||||||
|
MessageBox(hwnd, err, "Demo screenshot failure",
|
||||||
|
MB_OK | MB_ICONERROR);
|
||||||
|
EndDialog(hwnd, 0);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
case WM_MOUSEMOVE:
|
case WM_MOUSEMOVE:
|
||||||
state = (struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
state = (struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||||
if (state->collecting_entropy &&
|
if (state->collecting_entropy &&
|
||||||
@ -2006,6 +2034,21 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
|||||||
!strcmp(argv[i], "-restrict_acl") ||
|
!strcmp(argv[i], "-restrict_acl") ||
|
||||||
!strcmp(argv[i], "-restrictacl")) {
|
!strcmp(argv[i], "-restrictacl")) {
|
||||||
restrict_process_acl();
|
restrict_process_acl();
|
||||||
|
} else if (!strcmp(argv[i], "-demo-screenshot")) {
|
||||||
|
demo_screenshot_filename = (i+1 < argc ? argv[++i] :
|
||||||
|
"puttygen.bmp");
|
||||||
|
cmdline_demo_keystr = PTRLEN_LITERAL(
|
||||||
|
"PuTTY-User-Key-File-3: ssh-ed25519\n"
|
||||||
|
"Encryption: none\n"
|
||||||
|
"Comment: ed25519-key-20220402\n"
|
||||||
|
"Public-Lines: 2\n"
|
||||||
|
"AAAAC3NzaC1lZDI1NTE5AAAAILzuIFwZ"
|
||||||
|
"8ZhgOlilcSb+9zPuCf/DmKJiloVlmWGy\n"
|
||||||
|
"xa/F\n"
|
||||||
|
"Private-Lines: 1\n"
|
||||||
|
"AAAAIPca6vLwtB2NJhZUpABQISR0gcQH8jjQLta19VyzA3wc\n"
|
||||||
|
"Private-MAC: 1159e9628259b35933b397379bbe8a14"
|
||||||
|
"a1f1d97fe91e446e45a9581a3408b70e\n");
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Assume the first argument to be a private key file, and
|
* Assume the first argument to be a private key file, and
|
||||||
|
@ -701,4 +701,7 @@ void cli_main_loop(cliloop_pre_t pre, cliloop_post_t post, void *ctx);
|
|||||||
bool cliloop_null_pre(void *vctx, const HANDLE **, size_t *);
|
bool cliloop_null_pre(void *vctx, const HANDLE **, size_t *);
|
||||||
bool cliloop_null_post(void *vctx, size_t);
|
bool cliloop_null_post(void *vctx, size_t);
|
||||||
|
|
||||||
|
char *save_screenshot(HWND hwnd, const char *outfile);
|
||||||
|
void gui_terminal_ready(HWND hwnd, Seat *seat, Backend *backend);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user